Переглянути джерело

试卷模板和安全接口调试

zhangjie 2 роки тому
батько
коміт
e6e5414a91

+ 64 - 2
src/App.vue

@@ -1,10 +1,40 @@
 <template>
-  <div id="app"><router-view /></div>
+  <div id="app">
+    <router-view />
+
+    <!-- check pwd -->
+    <el-dialog
+      :visible.sync="modalIsShow"
+      title="安全校验 "
+      width="500px"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      :show-close="false"
+      append-to-body
+    >
+      <el-form ref="modalFormComp" :model="modalForm" :rules="rules">
+        <el-form-item label="安全密码" prop="safePassword">
+          <el-input
+            v-model="modalForm.safePassword"
+            type="password"
+            class="dialog-input-width"
+            auto-complete="off"
+            placeholder="输入密码"
+          />
+        </el-form-item>
+      </el-form>
+
+      <div slot="footer">
+        <el-button type="primary" @click="confirm">确定</el-button>
+      </div>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
 import timeMixin from "./mixins/timeMixin";
 import { QUESTION_API } from "@/constants/constants";
+import { questionSecurityCheckApi } from "./modules/question/api";
 
 export default {
   name: "App",
@@ -12,8 +42,25 @@ export default {
   data() {
     return {
       signalWaiting: false,
+      // 安全校验
+      modalIsShow: false,
+      modalForm: { safePassword: "" },
+      rules: {
+        safePassword: [
+          {
+            required: true,
+            message: "请输入密码",
+            trigger: "change",
+          },
+        ],
+      },
     };
   },
+  computed: {
+    safeEnable() {
+      return this.$store.state.user.safeEnable;
+    },
+  },
   watch: {
     $route: {
       immediate: true,
@@ -31,10 +78,14 @@ export default {
           return;
         }
         this.onlineSignal();
+
+        const safeRoutes = ["QuestionManage"];
+        if (this.safeEnable && val.name && safeRoutes.includes(val.name)) {
+          this.modalIsShow = true;
+        }
       },
     },
   },
-
   beforeDestroy() {
     this.clearSetTs();
   },
@@ -62,6 +113,17 @@ export default {
         this.onlineSignal();
       }, 50 * 1000);
     },
+    async confirm() {
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
+      if (!valid) return;
+
+      const res = await questionSecurityCheckApi(
+        this.modalForm.safePassword
+      ).catch(() => {});
+      this.isSubmit = false;
+      if (!res) return;
+      this.modalIsShow = false;
+    },
   },
 };
 </script>

+ 5 - 0
src/constants/constants.js

@@ -167,3 +167,8 @@ export const DIFFICULTY_LIST = [
  * 空行用 {type: "text", value: "", param: null} 来表示
  */
 export const EMPTY_RICH_TEXT = { sections: [] };
+
+export const PAPER_TEMPLATE_TYPE = {
+  PAPER_EXPORT: "试卷导出模板",
+  SYNTHESIZE_PAPER_EXPORT: "综合卷导出模版",
+};

+ 4 - 0
src/filters/filters.js

@@ -4,6 +4,7 @@ import {
   LEVEL_TYPE_SELECT,
   AUDIT_AUTHORITY,
   PAPER_AUDIT_STATUS,
+  PAPER_TEMPLATE_TYPE,
 } from "@/constants/constants";
 
 // 课程层次过滤器
@@ -30,3 +31,6 @@ Vue.filter("paperAuditStatusFilter", function (val) {
     }
   }
 });
+Vue.filter("paperTempalteTypeFilter", function (val) {
+  return PAPER_TEMPLATE_TYPE[val] || "";
+});

+ 19 - 9
src/modules/paper-export/api.js

@@ -2,8 +2,21 @@ import { $httpWithMsg } from "../../plugins/axios";
 import { QUESTION_API } from "@/constants/constants.js";
 
 // paper-template-mamage
-export const paperTemplateListApi = (datas) => {
-  return $httpWithMsg.post(`${QUESTION_API}/paper/template/page`, datas);
+export const paperTemplatePageListApi = (datas) => {
+  return $httpWithMsg.post(
+    `${QUESTION_API}/paper_template/page`,
+    {},
+    { params: datas }
+  );
+};
+export const paperTemplateListApi = (type) => {
+  return $httpWithMsg.post(
+    `${QUESTION_API}/paper_template/list`,
+    {},
+    {
+      params: { type },
+    }
+  );
 };
 export const paperTemplateDetailApi = (tid) => {
   return $httpWithMsg.post(
@@ -16,14 +29,11 @@ export const paperTemplateDetailApi = (tid) => {
 };
 
 export const savePaperTemplateApi = (datas) => {
-  return $httpWithMsg.post(
-    QUESTION_API + "/paper/template/save/structure",
-    datas
-  );
+  return $httpWithMsg.post(QUESTION_API + "/paper_template/save", datas);
 };
 export const paperTemplateEnableApi = ({ id, enable }) => {
   return $httpWithMsg.post(
-    QUESTION_API + "/paper/template/toggle",
+    QUESTION_API + "/paper_template/enable",
     {},
     {
       params: { id, enable },
@@ -32,10 +42,10 @@ export const paperTemplateEnableApi = ({ id, enable }) => {
 };
 export const paperTemplateDeleteApi = (ids) => {
   return $httpWithMsg.post(
-    QUESTION_API + "/paper/template/delete",
+    QUESTION_API + "/paper_template/delete",
     {},
     {
-      params: { ids: ids.join() },
+      params: { idList: ids.join() },
     }
   );
 };

+ 128 - 0
src/modules/paper-export/components/ModifyPaperTemplateInfo.vue

@@ -0,0 +1,128 @@
+<template>
+  <el-dialog
+    class="modify-paper-template-info"
+    :visible.sync="modalIsShow"
+    :title="title"
+    width="600px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @open="visibleChange"
+  >
+    <el-form
+      ref="modalFormComp"
+      label-position="left"
+      :rules="rules"
+      :model="modalForm"
+      label-width="95px"
+    >
+      <el-form-item prop="name" label="模板名称:">
+        <el-input
+          v-model.trim="modalForm.name"
+          placeholder="建议不超过30个字"
+          clearable
+        ></el-input>
+      </el-form-item>
+      <el-form-item prop="type" label="模板类型:">
+        <el-radio-group v-model="modalForm.type" :disabled="isEdit">
+          <el-radio-button
+            v-for="(val, key) in PAPER_TEMPLATE_TYPE"
+            :key="key"
+            :label="key"
+            >{{ val }}</el-radio-button
+          >
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <div slot="footer">
+      <el-button type="primary" :disabled="isSubmit" @click="submit"
+        >确认</el-button
+      >
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { PAPER_TEMPLATE_TYPE } from "@/constants/constants";
+
+const initModalForm = {
+  id: null,
+  name: "",
+  type: "GENERIC",
+};
+
+export default {
+  name: "ModifyPaperTemplateInfo",
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      modalForm: {},
+      PAPER_TEMPLATE_TYPE,
+      rules: {
+        name: [
+          {
+            required: true,
+            message: "模板名称不能超过30个字",
+            max: 30,
+            trigger: "change",
+          },
+        ],
+        type: [
+          {
+            required: true,
+            message: "请选择模板类型",
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  computed: {
+    isEdit() {
+      return !!this.modalForm.id;
+    },
+    title() {
+      return (this.isEdit ? "编辑" : "新增") + "模板信息";
+    },
+  },
+  methods: {
+    initData(val) {
+      this.modalForm = this.$objAssign(initModalForm, val);
+    },
+    visibleChange() {
+      this.initData(this.instance);
+
+      this.$nextTick(() => {
+        this.$refs.modalFormComp.clearValidate();
+      });
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async submit() {
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
+      if (!valid) return;
+
+      if (!this.isEdit) {
+        this.$emit("new-temp", this.modalForm);
+        this.cancel();
+        return;
+      }
+    },
+  },
+};
+</script>

+ 1 - 1
src/modules/paper-export/router/index.js

@@ -11,7 +11,7 @@ export const menuRoutes = [
 
 export const otherRoutes = [
   {
-    path: "/paper-template/edit/:tid?",
+    path: "/paper-template/edit",
     name: "PaperTemplateEdit",
     component: () =>
       import(/* webpackChunkName: "card" */ "../views/PaperTemplateEdit.vue"),

+ 23 - 28
src/modules/paper-export/views/PaperTemplateEdit.vue

@@ -12,7 +12,7 @@
 </template>
 
 <script>
-import { paperTemplateDetailApi, savePaperTemplateApi } from "../api";
+import { savePaperTemplateApi } from "../api";
 import PaperTemplateDesign from "../components/PaperTemplateDesign.vue";
 export default {
   name: "PaperTemplateEdit",
@@ -21,44 +21,35 @@ export default {
   },
   data() {
     return {
-      tid: this.$route.params.tid,
       tempContent: {},
       dataReady: false,
+      paperTempInfo: {},
     };
   },
-  computed: {
-    isEdit() {
-      return !!this.tid;
-    },
-  },
   mounted() {
     this.initData();
   },
   methods: {
     async initData() {
+      let paperTempInfo = window.sessionStorage.getItem("paperTempInfo");
+      if (!paperTempInfo) {
+        this.$message.error("数据丢失,请退出编辑页面!");
+        return;
+      }
+      this.paperTempInfo = JSON.parse(paperTempInfo);
       this.dataReady = false;
-      if (this.isEdit) {
-        await this.getPaperTemplate();
+      if (this.paperTempInfo.id) {
+        const content = this.paperTempInfo.content
+          ? JSON.parse(this.paperTempInfo.content)
+          : { pages: [] };
+        this.tempContent = content;
       } else {
-        this.initTempContent();
+        this.tempContent = {
+          pages: [],
+        };
       }
       this.dataReady = true;
     },
-    async getPaperTemplate() {
-      const detDataRes = await paperTemplateDetailApi(this.tid);
-
-      if (!detDataRes.data || !detDataRes.data.content) {
-        this.$message.error("无模板内容");
-        return;
-      }
-
-      this.tempContent = JSON.parse(detDataRes.data.content);
-    },
-    initTempContent() {
-      this.tempContent = {
-        papes: [],
-      };
-    },
     // 操作
     async toPreview(paperTempData) {
       const result = await this.toSave(paperTempData).catch(() => {});
@@ -80,9 +71,11 @@ export default {
       this.$refs.PaperTemplateDesign.loading();
 
       let datas = {
-        id: this.tid,
+        id: this.paperTempInfo.id,
+        name: this.paperTempInfo.name,
+        type: this.paperTempInfo.type,
         content: JSON.stringify(paperTempData),
-        formal: true,
+        pageSize: paperTempData.pages[0].pageSize,
       };
       let result = await savePaperTemplateApi(datas).catch(() => {});
       this.$refs.PaperTemplateDesign.unloading();
@@ -91,7 +84,9 @@ export default {
       return Promise.resolve("保存成功!");
     },
     async toSubmit(paperTempData) {
-      const result = await this.toSave(paperTempData).catch(() => {});
+      const result = await this.toSave(paperTempData).catch((e) => {
+        console.dir(e);
+      });
       if (result) {
         this.$message.success("提交成功!");
         this.goback();

+ 32 - 17
src/modules/paper-export/views/PaperTemplateManage.vue

@@ -30,13 +30,13 @@
       <!-- 页面列表 -->
       <el-table ref="table" :data="tableData">
         <el-table-column prop="name" label="模版名称"> </el-table-column>
-        <el-table-column
-          prop="createTime"
-          label="创建时间"
-          width="170"
-        ></el-table-column>
-        <el-table-column prop="creator" label="创建人"></el-table-column>
-        <el-table-column width="50" label="状态">
+        <el-table-column prop="creatorName" label="创建人"></el-table-column>
+        <el-table-column prop="type" label="模板类型" width="120">
+          <span slot-scope="scope">{{
+            scope.row.type | paperTempalteTypeFilter
+          }}</span>
+        </el-table-column>
+        <el-table-column width="80" label="状态">
           <template slot-scope="scope">
             <span v-if="scope.row.enable">
               <el-tooltip
@@ -60,7 +60,12 @@
             </span>
           </template>
         </el-table-column>
-        <el-table-column width="170" label="操作">
+        <el-table-column
+          prop="creationTime"
+          label="创建时间"
+          width="170"
+        ></el-table-column>
+        <el-table-column width="220" label="操作">
           <template slot-scope="scope">
             <el-button
               size="mini"
@@ -70,7 +75,6 @@
               >编辑
             </el-button>
             <el-button
-              v-if="!onlyAssignTeacher"
               size="mini"
               :type="scope.row.enable ? 'danger' : 'primary'"
               plain
@@ -100,18 +104,27 @@
         />
       </div>
     </div>
+    <!-- ModifyPaperTemplateInfo -->
+    <modify-paper-template-info
+      ref="ModifyPaperTemplateInfo"
+      :instance="curRow"
+      @new-temp="toCreateTemp"
+    ></modify-paper-template-info>
   </div>
 </template>
 
 <script>
 import {
-  paperTemplateListApi,
+  paperTemplatePageListApi,
   paperTemplateEnableApi,
   paperTemplateDeleteApi,
 } from "../api";
 
+import ModifyPaperTemplateInfo from "../components/ModifyPaperTemplateInfo.vue";
+
 export default {
   name: "PaperTemplateManage",
+  components: { ModifyPaperTemplateInfo },
   data() {
     return {
       loading: false,
@@ -124,16 +137,16 @@ export default {
     };
   },
   mounted() {
-    // this.search();
+    this.search();
   },
   methods: {
     async search() {
       if (this.loading) return;
       this.loading = true;
 
-      const res = await paperTemplateListApi({
+      const res = await paperTemplatePageListApi({
         ...this.searchForm,
-        pageNumber: this.currentPage,
+        curPage: this.currentPage,
         pageSize: this.pageSize,
       }).catch(() => {});
 
@@ -153,6 +166,11 @@ export default {
       this.search();
     },
     toCreate() {
+      this.curRow = {};
+      this.$refs.ModifyPaperTemplateInfo.open();
+    },
+    toCreateTemp(tempInfo) {
+      window.sessionStorage.setItem("paperTempInfo", JSON.stringify(tempInfo));
       this.$router.push({
         name: "PaperTemplateEdit",
       });
@@ -177,12 +195,9 @@ export default {
       this.search();
     },
     toEdit(row) {
-      console.log(row);
+      window.sessionStorage.setItem("paperTempInfo", JSON.stringify(row));
       this.$router.push({
         name: "PaperTemplateEdit",
-        params: {
-          tid: row.id,
-        },
       });
     },
     async toDelete(row) {

+ 20 - 0
src/modules/question/api.js

@@ -196,3 +196,23 @@ export const auditQuestionApi = (datas) => {
     }
   );
 };
+
+// question/security_settings
+export const questionSecuritySettingsApi = (datas) => {
+  return $httpWithMsg.post(
+    `${QUESTION_API}/question/security_settings`,
+    {},
+    {
+      params: datas,
+    }
+  );
+};
+export const questionSecurityCheckApi = (safePassword) => {
+  return $httpWithMsg.post(
+    `${QUESTION_API}/question/check_password`,
+    {},
+    {
+      params: { safePassword },
+    }
+  );
+};

+ 107 - 12
src/modules/question/components/QuestionSafetySetDialog.vue

@@ -10,40 +10,116 @@
     append-to-body
     @open="visibleChange"
   >
-    <el-form>
+    <el-form ref="modalFormComp" :model="modalForm" :rules="rules">
       <el-form-item label="加密“题库”,“卷库”">
-        <el-switch v-model="modalForm.questionActionIsCrypto"></el-switch>
+        <el-switch v-model="modalForm.safeEnable"></el-switch>
         <p class="tips-info">开启后,进入题库、卷库模块,需要进行密码验证!</p>
       </el-form-item>
+      <el-form-item
+        v-if="modalForm.safeEnable"
+        label="设置密码"
+        prop="safePassword"
+      >
+        <el-input
+          v-model="modalForm.safePassword"
+          type="password"
+          class="dialog-input-width"
+          auto-complete="off"
+          placeholder="请输入6位以上数字和字母组合"
+        />
+      </el-form-item>
+      <el-form-item
+        v-if="modalForm.safeEnable"
+        label="确认密码"
+        prop="checkSafePassword"
+      >
+        <el-input
+          v-model="modalForm.checkSafePassword"
+          type="password"
+          class="dialog-input-width"
+          auto-complete="off"
+          placeholder="请输入6位以上数字和字母组合"
+        />
+      </el-form-item>
     </el-form>
 
     <div slot="footer">
-      <el-button type="primary" @click="confirm">确定</el-button>
+      <el-button type="primary" :loading="isSubmit" @click="confirm"
+        >确定</el-button
+      >
       <el-button @click="cancel">取消</el-button>
     </div>
   </el-dialog>
 </template>
 
 <script>
-import { mapState, mapMutations } from "vuex";
+import { questionSecuritySettingsApi } from "../api";
+import { mapActions } from "vuex";
+import { USER_SIGNIN } from "../../../modules/portal/store/user";
 
 export default {
   name: "QuestionSafetySetDialog",
   data() {
+    var validatePassWeakPass = (rule, value, callback) => {
+      if (this.modalForm.checkSafePassword !== "") {
+        this.$refs.modalFormComp.validateField("checkSafePassword");
+      }
+      callback();
+    };
+    var validatePassWeakPass2 = (rule, value, callback) => {
+      if (value !== this.modalForm.safePassword) {
+        callback(new Error("两次输入密码不一致!"));
+      } else {
+        callback();
+      }
+    };
+    const pwdRule = [
+      {
+        validator: (rule, value, callback) => {
+          if (value && value.match(/[0-9]+/) && value.match(/[a-zA-Z]+/)) {
+            callback();
+          } else {
+            callback(new Error("请输入数字和字母组合"));
+          }
+        },
+        trigger: "change",
+      },
+      {
+        required: true,
+        min: 6,
+        max: 16,
+        message: "密码只能6-16个字符",
+        trigger: "change",
+      },
+    ];
     return {
       modalIsShow: false,
+      isSubmit: false,
       modalForm: {
-        questionActionIsCrypto: false,
+        safeEnable: false,
+        safePassword: "",
+        checkSafePassword: "",
+      },
+      rules: {
+        safePassword: [
+          { validator: validatePassWeakPass, trigger: "blur" },
+          ...pwdRule,
+        ],
+        checkSafePassword: [
+          { validator: validatePassWeakPass2, trigger: "blur" },
+          ...pwdRule,
+        ],
       },
     };
   },
-  computed: {
-    ...mapState("question", ["questionActionIsCrypto"]),
-  },
   methods: {
-    ...mapMutations("question", ["setQuestionActionIsCrypto"]),
+    ...mapActions([USER_SIGNIN]),
     visibleChange() {
-      this.modalForm.questionActionIsCrypto = this.questionActionIsCrypto;
+      this.modalForm = {
+        safeEnable: this.$store.state.user.safeEnable,
+        safePassword: "",
+        checkSafePassword: "",
+      };
     },
     cancel() {
       this.modalIsShow = false;
@@ -51,8 +127,27 @@ export default {
     open() {
       this.modalIsShow = true;
     },
-    confirm() {
-      this.setQuestionActionIsCrypto(this.modalForm.questionActionIsCrypto);
+    async confirm() {
+      if (this.modalForm.safeEnable) {
+        const valid = await this.$refs.modalFormComp.validate().catch(() => {});
+        if (!valid) return;
+      }
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const data = await questionSecuritySettingsApi(this.modalForm).catch(
+        () => {}
+      );
+      this.isSubmit = false;
+
+      if (!data) return;
+
+      let user = this.$store.state.user;
+      user.safeEnable = this.modalForm.safeEnable;
+      this.USER_SIGNIN(user);
+
+      this.$message.success("设置成功!");
+      this.$emit("modified");
       this.cancel();
     },
   },

+ 0 - 14
src/modules/question/store.js

@@ -1,14 +0,0 @@
-const questionActionIsCrypto = sessionStorage.getItem("questionActionIsCrypto");
-
-export default {
-  namespaced: true,
-  state: {
-    questionActionIsCrypto: questionActionIsCrypto === "true",
-  },
-  mutations: {
-    setQuestionActionIsCrypto(state, questionActionIsCrypto) {
-      sessionStorage.setItem("questionActionIsCrypto", questionActionIsCrypto);
-      state.questionActionIsCrypto = questionActionIsCrypto;
-    },
-  },
-};

+ 1 - 0
src/modules/questions/routes/routes.js

@@ -108,6 +108,7 @@ export const menuRoutes = [
       },
       {
         path: "import_paper/:isClear", //题库试卷列表
+        name: "QuestionManage",
         component: ImportPaper,
       },
       {

+ 0 - 2
src/store/index.js

@@ -4,7 +4,6 @@ import user from "../modules/portal/store/user";
 import currentPaths from "../modules/portal/store/currentPaths";
 import menuList from "../modules/portal/store/menuList";
 import { card } from "../modules/card/store";
-import question from "../modules/question/store";
 import paperExport from "../modules/paper-export/store";
 
 Vue.use(Vuex);
@@ -18,7 +17,6 @@ export default new Vuex.Store({
     currentPaths,
     menuList,
     card,
-    question,
     "paper-export": paperExport,
   },
 });