zhangjie 2 сар өмнө
parent
commit
7bd2fd5230

+ 38 - 0
src/modules/mark/components/ModifyMarkSetting.vue

@@ -94,6 +94,21 @@
             >填空题作为一个整体设置评卷员及评卷方式</el-checkbox
           >
         </el-form-item>
+        <el-form-item prop="aiMarkType" class="form-item-info">
+          <el-checkbox
+            v-model="modalForm.enableAIMark"
+            @change="enableAIMarkChange"
+            >启用AI智能评卷</el-checkbox
+          >
+          <el-radio-group
+            v-if="modalForm.enableAIMark"
+            v-model="modalForm.aiMarkType"
+            class="ml-2"
+          >
+            <el-radio label="AI_ONLY">仅AI评卷</el-radio>
+            <el-radio label="AI_HUMAN">人机双评</el-radio>
+          </el-radio-group>
+        </el-form-item>
         <!-- <el-form-item class="form-item-info">
           <el-checkbox v-model="modalForm.allowCloseBeforeFinish"
             >允许不评卷结束评卷</el-checkbox
@@ -140,6 +155,8 @@ const initModalForm = {
   doubleMark: false,
   autoScroll: false,
   mergeMarker: true,
+  enableAIMark: false,
+  aiMarkType: "",
   // allowCloseBeforeFinish: false,
   passScore: 60,
   excellentScore: 80,
@@ -199,6 +216,20 @@ export default {
             trigger: "change",
           },
         ],
+        aiMarkType: [
+          {
+            required: true,
+            message: "请选择AI评卷方式",
+            trigger: "change",
+            validator: (rule, value, callback) => {
+              if (this.modalForm.enableAIMark && !value) {
+                callback(new Error("请选择AI评卷方式"));
+              } else {
+                callback();
+              }
+            },
+          },
+        ],
       },
       // date-picker
       markTime: [],
@@ -295,6 +326,13 @@ export default {
         this.modalForm.markEndTime = "";
       }
     },
+    enableAIMarkChange() {
+      if (this.modalForm.enableAIMark) {
+        this.modalForm.aiMarkType = "AI_HUMAN";
+      } else {
+        this.modalForm.aiMarkType = "";
+      }
+    },
     areaModified(areas) {
       this.modalForm.sheetConfig = areas;
     },

+ 35 - 1
src/modules/mark/components/markParam/MarkParamGroup.vue

@@ -68,6 +68,14 @@
             {{ scope.row.doubleRate }}%
           </template>
         </el-table-column>
+        <el-table-column label="AI评卷" width="80" align="center">
+          <template slot-scope="scope">
+            <i
+              v-if="scope.row.aiMarkSet"
+              class="el-icon-success color-success"
+            ></i>
+          </template>
+        </el-table-column>
         <el-table-column label="评卷区" width="80" align="center">
           <template slot-scope="scope">
             <i
@@ -76,7 +84,7 @@
             ></i>
           </template>
         </el-table-column>
-        <el-table-column class-name="action-column" label="操作" width="160px">
+        <el-table-column class-name="action-column" label="操作" width="275px">
           <template slot-scope="scope">
             <el-button
               class="btn-primary"
@@ -91,6 +99,13 @@
               @click="toSetArea(scope.row)"
               >评卷区</el-button
             >
+            <el-button
+              :disabled="!checkAiMarkEnabled(scope.row)"
+              class="btn-primary"
+              type="text"
+              @click="toAiMarkSet(scope.row)"
+              >AI智能评卷设置</el-button
+            >
           </template>
         </el-table-column>
       </el-table>
@@ -131,6 +146,12 @@
       :paper-list="paperList"
       @modified="areaModified"
     ></modify-mark-area>
+    <!-- ModifyMarkAiSet -->
+    <modify-mark-ai-set
+      ref="ModifyMarkAiSet"
+      :group="curRow"
+      @modified="aiSetModified"
+    ></modify-mark-ai-set>
   </div>
 </template>
 
@@ -139,6 +160,7 @@ import { mapState, mapMutations } from "vuex";
 import ModifyMarkType from "./ModifyMarkType.vue";
 import ModifyMarkArea from "./ModifyMarkArea.vue";
 import ModifyMarkMarker from "./ModifyMarkMarker.vue";
+import ModifyMarkAiSet from "./ModifyMarkAiSet.vue";
 import MarkParamSubjectiveAnswer from "./MarkParamSubjectiveAnswer.vue";
 import {
   examStructureFindJpg,
@@ -158,6 +180,7 @@ export default {
     ModifyMarkArea,
     ModifyMarkMarker,
     MarkParamSubjectiveAnswer,
+    ModifyMarkAiSet,
   },
   data() {
     return {
@@ -181,6 +204,7 @@ export default {
       "paperStructureInfo",
       "openMergeMarker",
       "subjectiveTaskList",
+      "enableAIMark",
     ]),
     unsetQuestionNos() {
       return this.subjectiveTaskList
@@ -221,6 +245,9 @@ export default {
         };
       });
     },
+    checkAiMarkEnabled(item) {
+      return this.enableAIMark && item.questionType !== 4;
+    },
     async getCardPages() {
       const detData = await cardDetail(this.basicInfo.cardId);
       const cardContent = detData?.content
@@ -454,6 +481,13 @@ export default {
       // console.log(combinePictureConfigList);
       return combinePictureConfigList;
     },
+    toAiMarkSet(row) {
+      this.curRow = row;
+      this.$refs.ModifyMarkAiSet.open();
+    },
+    aiSetModified(data) {
+      this.$set(this.curRow, "aiMarkSet", data);
+    },
     checkData() {
       const errorList = [];
       this.subjectiveTaskList.forEach((item) => {

+ 112 - 0
src/modules/mark/components/markParam/ModifyMarkAiLevelAnswer.vue

@@ -0,0 +1,112 @@
+<template>
+  <el-dialog
+    title="档次标答编辑"
+    :visible.sync="visible"
+    width="600px"
+    append-to-body
+    top="10vh"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    @close="handleClose"
+  >
+    <div class="modify-mark-ai-level-answer">
+      <el-form ref="FormRef" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="分值:" prop="minScore">
+          <el-input-number
+            v-model="form.minScore"
+            :min="0"
+            :max="100"
+            :precision="1"
+            :step="0.1"
+            :controls="false"
+          ></el-input-number>
+          <el-input-number
+            v-model="form.maxScore"
+            :min="0"
+            :max="100"
+            :precision="1"
+            :step="0.1"
+            :controls="false"
+          ></el-input-number>
+        </el-form-item>
+        <el-form-item label="标答内容:" prop="content">
+          <el-input
+            v-model="form.content"
+            type="textarea"
+            :rows="4"
+            placeholder="请输入标答内容"
+            maxlength="999"
+            show-word-limit
+          ></el-input>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div slot="footer">
+      <el-button @click="handleClose">取 消</el-button>
+      <el-button type="primary" @click="handleSubmit">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: "modify-mark-ai-level-answer",
+  data() {
+    return {
+      visible: false,
+      form: {
+        minScore: 0,
+        maxScore: 0,
+        content: "",
+      },
+      rules: {
+        minScore: [
+          { required: true, message: "请输入最小分", trigger: "change" },
+          {
+            validator: (rule, value, callback) => {
+              if (value < 0 || value > 100) {
+                callback(new Error("最小分必须在0-100之间"));
+              } else if (
+                value &&
+                this.form.maxScore &&
+                value >= this.form.maxScore
+              ) {
+                callback(new Error("最小分必须小于最大分"));
+              } else {
+                callback();
+              }
+            },
+          },
+        ],
+        content: [
+          { required: true, message: "请输入标答内容", trigger: "change" },
+        ],
+      },
+    };
+  },
+  methods: {
+    open(data) {
+      this.visible = true;
+      if (data) {
+        this.form = { ...data };
+      } else {
+        this.form = {
+          minScore: 0,
+          maxScore: 0,
+          content: "",
+        };
+      }
+    },
+    handleClose() {
+      this.visible = false;
+      this.$refs.FormRef.resetFields();
+    },
+    async handleSubmit() {
+      const valid = await this.$refs.FormRef.validate().catch(() => {});
+      if (!valid) return;
+      this.$emit("modified", { ...this.form });
+      this.handleClose();
+    },
+  },
+};
+</script>

+ 85 - 0
src/modules/mark/components/markParam/ModifyMarkAiPointAnswer.vue

@@ -0,0 +1,85 @@
+<template>
+  <el-dialog
+    title="得分点标答编辑"
+    :visible.sync="visible"
+    width="600px"
+    append-to-body
+    top="10vh"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    @close="handleClose"
+  >
+    <div class="modify-mark-ai-score-answer">
+      <el-form ref="FormRef" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="分值:" prop="score">
+          <el-input-number
+            v-model="form.score"
+            :min="0"
+            :max="100"
+            :precision="1"
+            :step="0.1"
+            :controls="false"
+          ></el-input-number>
+        </el-form-item>
+        <el-form-item label="标答内容:" prop="content">
+          <el-input
+            v-model="form.content"
+            type="textarea"
+            :rows="4"
+            :maxlength="999"
+            show-word-limit
+            placeholder="请输入标答内容"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div slot="footer">
+      <el-button @click="handleClose">取 消</el-button>
+      <el-button type="primary" @click="handleSubmit">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: "modify-mark-ai-score-answer",
+  data() {
+    return {
+      visible: false,
+      form: {
+        score: 0,
+        content: "",
+      },
+      rules: {
+        score: [{ required: true, message: "请输入分值", trigger: "blur" }],
+        content: [
+          { required: true, message: "请输入标答内容", trigger: "blur" },
+        ],
+      },
+    };
+  },
+  methods: {
+    open(data) {
+      this.visible = true;
+      if (data) {
+        this.form = { ...data };
+      } else {
+        this.form = {
+          score: 0,
+          content: "",
+        };
+      }
+    },
+    handleClose() {
+      this.visible = false;
+      this.$refs.FormRef.resetFields();
+    },
+    async handleSubmit() {
+      const valid = await this.$refs.FormRef.validate().catch(() => {});
+      if (!valid) return;
+      this.$emit("modified", { ...this.form });
+      this.handleClose();
+    },
+  },
+};
+</script>

+ 226 - 0
src/modules/mark/components/markParam/ModifyMarkAiSet.vue

@@ -0,0 +1,226 @@
+<template>
+  <div>
+    <el-dialog
+      title="AI智能评卷设置"
+      :visible.sync="modalIsShow"
+      width="800px"
+      append-to-body
+      top="10vh"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      @open="visibleChange"
+    >
+      <div class="modify-mark-ai-set">
+        <el-form ref="FormRef" :model="form" :rules="rules" label-width="90px">
+          <el-form-item label="试卷题干:" prop="questionStem">
+            <el-input
+              v-model="form.questionStem"
+              type="textarea"
+              :maxlength="999"
+              show-word-limit
+              :rows="4"
+              placeholder="请输入试卷题干"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="评分模式:" prop="scoreMode">
+            <el-radio-group
+              v-model="form.scoreMode"
+              @change="handleScoreModeChange"
+            >
+              <el-radio label="POINT">按得分点评分</el-radio>
+              <el-radio label="LEVEL">按档次评分</el-radio>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="最小分:" prop="minScore">
+            <el-input-number
+              v-model="form.minScore"
+              :min="0"
+              :max="100"
+              :precision="1"
+              :step="0.5"
+              :controls="false"
+            ></el-input-number>
+          </el-form-item>
+        </el-form>
+
+        <!-- 标答列表 -->
+        <div class="answer-list">
+          <div class="box-justify mb-2">
+            <h3 class="no-margin">标答列表</h3>
+            <el-button type="primary" size="small" @click="toAddAnswer"
+              >新增</el-button
+            >
+          </div>
+          <el-table :data="form.answers" border>
+            <el-table-column
+              type="index"
+              label="序号"
+              width="60"
+              align="center"
+            ></el-table-column>
+            <template v-if="form.scoreMode === 'POINT'">
+              <el-table-column prop="score" label="分值" width="100">
+                <template slot-scope="scope">
+                  {{ scope.row.score }}
+                </template>
+              </el-table-column>
+            </template>
+            <template v-else>
+              <el-table-column label="分值区间" width="160">
+                <template slot-scope="scope">
+                  {{ scope.row.minScore }} - {{ scope.row.maxScore }}
+                </template>
+              </el-table-column>
+            </template>
+            <el-table-column
+              prop="content"
+              label="标答内容"
+              show-overflow-tooltip
+            ></el-table-column>
+            <el-table-column label="操作" width="100" align="center">
+              <template slot-scope="scope">
+                <el-button
+                  type="text"
+                  class="btn-primary"
+                  @click="toEditAnswer(scope.row)"
+                  >编辑</el-button
+                >
+                <el-button
+                  type="text"
+                  class="btn-danger"
+                  @click="toDeleteAnswer(scope.$index)"
+                  >删除</el-button
+                >
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+      <div slot="footer">
+        <el-button @click="close">取 消</el-button>
+        <el-button type="primary" @click="handleSubmit">确 定</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 得分点标答编辑弹窗 -->
+    <modify-mark-ai-point-answer
+      ref="ModifyMarkAiPointAnswer"
+      @modified="answerModified"
+    ></modify-mark-ai-point-answer>
+    <!-- 档次标答编辑弹窗 -->
+    <modify-mark-ai-level-answer
+      ref="ModifyMarkAiLevelAnswer"
+      @modified="answerModified"
+    ></modify-mark-ai-level-answer>
+  </div>
+</template>
+
+<script>
+import ModifyMarkAiPointAnswer from "./ModifyMarkAiPointAnswer.vue";
+import ModifyMarkAiLevelAnswer from "./ModifyMarkAiLevelAnswer.vue";
+
+const getInitForm = () => {
+  return {
+    questionStem: "",
+    scoreMode: "POINT",
+    minScore: undefined,
+    answers: [],
+  };
+};
+
+export default {
+  name: "modify-mark-ai-set",
+  components: {
+    ModifyMarkAiPointAnswer,
+    ModifyMarkAiLevelAnswer,
+  },
+  props: {
+    group: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      form: getInitForm(),
+      rules: {
+        questionStem: [
+          { required: true, message: "请输入试卷题干", trigger: "blur" },
+        ],
+        scoreMode: [
+          { required: true, message: "请选择评分模式", trigger: "change" },
+        ],
+        minScore: [
+          { required: true, message: "请输入最小分", trigger: "blur" },
+        ],
+      },
+      curAnswer: null,
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.form = this.group.aiMarkSet || getInitForm();
+      this.$nextTick(() => {
+        this.$refs.FormRef.clearValidate();
+      });
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    close() {
+      this.modalIsShow = false;
+      this.$refs.FormRef.resetFields();
+    },
+    handleScoreModeChange() {
+      this.form.answers = [];
+    },
+    toAddAnswer() {
+      if (this.form.scoreMode === "POINT") {
+        this.$refs.ModifyMarkAiPointAnswer.open();
+      } else {
+        this.$refs.ModifyMarkAiLevelAnswer.open();
+      }
+    },
+    toEditAnswer(row) {
+      this.curAnswer = row;
+      if (this.form.scoreMode === "POINT") {
+        this.$refs.ModifyMarkAiPointAnswer.open(row);
+      } else {
+        this.$refs.ModifyMarkAiLevelAnswer.open(row);
+      }
+    },
+    toDeleteAnswer(index) {
+      this.form.answers.splice(index, 1);
+    },
+    answerModified(answer) {
+      if (this.curAnswer) {
+        Object.assign(this.curAnswer, answer);
+      } else {
+        this.form.answers.push(answer);
+      }
+      this.curAnswer = null;
+    },
+    async handleSubmit() {
+      const valid = await this.$refs.FormRef.validate().catch(() => {});
+      if (!valid) return;
+      if (!this.form.answers.length) {
+        this.$message.error("请添加标答");
+        return;
+      }
+      this.$emit("modified", { ...this.form });
+      this.close();
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.modify-mark-ai-set {
+  .answer-list {
+    margin-top: 20px;
+  }
+}
+</style>

+ 6 - 0
src/modules/mark/components/markParam/ModifyMarkParams.vue

@@ -148,6 +148,7 @@ export default {
       "setOpenMergeMarker",
       "setOpenDoubleMark",
       "setOpenClassMark",
+      "setAiMark",
       "initStore",
     ]),
     async initData() {
@@ -183,6 +184,11 @@ export default {
       this.setOpenMergeMarker(!!subjectRes.mergeMarker);
       this.setOpenDoubleMark(!!subjectRes.doubleMark);
       this.setOpenClassMark(!!subjectRes.classMark);
+      this.setAiMark({
+        enableAIMark: true,
+        // enableAIMark: !!subjectRes.enableAIMark,
+        aiMarkType: subjectRes.aiMarkType,
+      });
 
       this.dataReady = true;
     },

+ 8 - 0
src/modules/mark/components/markParam/store.js

@@ -19,6 +19,10 @@ const state = {
   openMergeMarker: false,
   // 是否开启双评
   openDoubleMark: false,
+  // 是否开启AI评卷
+  enableAIMark: false,
+  // AI评卷类型
+  aiMarkType: "",
   // 分班评卷班级信息
   classInfo: [],
   // 客观题结构
@@ -58,6 +62,10 @@ const mutations = {
   setOpenDoubleMark(state, openDoubleMark) {
     state.openDoubleMark = openDoubleMark;
   },
+  setAiMark(state, { aiMarkType, enableAIMark }) {
+    state.enableAIMark = enableAIMark;
+    state.aiMarkType = aiMarkType;
+  },
   setClassInfo(state, classInfo) {
     state.classInfo = classInfo;
   },