Browse Source

智能出题接口调试

zhangjie 1 year ago
parent
commit
e1afcf6c07

+ 4 - 0
src/assets/styles/base.scss

@@ -373,6 +373,10 @@ body {
   display: inline-block;
   vertical-align: middle;
 }
+.inline-top {
+  display: inline-block;
+  vertical-align: top;
+}
 
 .color-primary {
   color: $--color-primary;

+ 19 - 17
src/modules/question/api.js

@@ -306,34 +306,36 @@ export function questionImportDownloadTemplate(datas) {
 
 // gpt-question
 export function buildGptQuestionApi(datas) {
-  // auditResult,auditRemark,questionIds
-  return $httpWithMsg.post(
-    `${QUESTION_API}/question/gpt/build`,
-    {},
-    {
-      params: datas,
-    }
-  );
+  return $httpWithMsg.post(`${QUESTION_API}/ai/question/build`, datas);
 }
 export function gptQuestionListApi(data = {}) {
   return $httpWithMsg.post(
-    `${QUESTION_API}/question/gpt/list`,
+    `${QUESTION_API}/ai/question/page`,
     {},
     { params: data }
   );
 }
-export function saveGptQuestionApi(datas) {
-  // auditResult,auditRemark,questionIds
-  return $httpWithMsg.post(`${QUESTION_API}/question/gpt/save`, datas);
+export function saveGptQuestionApi(idList) {
+  return $httpWithMsg.post(
+    `${QUESTION_API}/ai/question/join`,
+    {},
+    { params: { idList } }
+  );
 }
 export function updateGptQuestionApi(datas) {
-  // auditResult,auditRemark,questionIds
-  return $httpWithMsg.post(`${QUESTION_API}/question/gpt/update`, datas);
+  return $httpWithMsg.post(`${QUESTION_API}/ai/question/edit`, datas);
 }
-export function deleteGptQuestionApi(ids) {
+export function deleteGptQuestionApi(idList) {
   return $httpWithMsg.post(
-    `${QUESTION_API}/question/gpt/delete`,
+    `${QUESTION_API}/ai/question/delete`,
     {},
-    { params: { ids: ids.join() } }
+    { params: { idList } }
+  );
+}
+export function gptTaskDetailApi({ taskId, courseId }) {
+  return $httpWithMsg.post(
+    `${QUESTION_API}/ai/question/find_task`,
+    {},
+    { params: { taskId, courseId } }
   );
 }

+ 132 - 63
src/modules/question/components/GptQuestionDialog.vue

@@ -8,19 +8,20 @@
       append-to-body
       fullscreen
       @opened="dialogOpened"
+      @close="dialogClose"
     >
       <div slot="title">
-        <div>
-          <h2>智能出题</h2>
-          <span>课程代码:{{ formModel.courseCode }}</span>
-          <span>课程名称:{{ formModel.courseName }}</span>
-        </div>
+        <h2>
+          智能出题 --<span
+            >{{ formModel.courseName }}({{ formModel.courseCode }})</span
+          >
+        </h2>
       </div>
 
       <div class="part-box">
         <h2 class="part-box-title">生成试题</h2>
 
-        <el-form :model="formModel" label-width="100px">
+        <el-form class="margin-top-20" :model="formModel" label-width="100px">
           <el-form-item label="题型">
             <el-button
               v-for="item in BASE_QUESTION_TYPES"
@@ -33,7 +34,7 @@
               >{{ item.name }}</el-button
             >
           </el-form-item>
-          <el-form-item label="出题数量">
+          <el-form-item class="inline-top" label="出题数量">
             <el-input-number
               v-model="formModel.questionCount"
               placeholder="出题数量"
@@ -45,7 +46,11 @@
               :controls="false"
             ></el-input-number>
           </el-form-item>
-          <el-form-item v-if="IS_SELECTION_QUESTION" label="选项个数">
+          <el-form-item
+            v-if="IS_SELECTION_QUESTION"
+            class="inline-top"
+            label="选项个数"
+          >
             <el-input-number
               v-model="formModel.optionCount"
               placeholder="选项个数"
@@ -57,9 +62,13 @@
               :controls="false"
             ></el-input-number>
           </el-form-item>
-          <el-form-item v-if="IS_BOOLEAN_QUESTION" label="填空个数">
+          <el-form-item
+            v-if="IS_FILL_QUESTION"
+            class="inline-top"
+            label="填空个数"
+          >
             <el-input-number
-              v-model="formModel.fillCount"
+              v-model="formModel.blankCount"
               placeholder="填空个数"
               style="width: 150px"
               :min="1"
@@ -71,27 +80,33 @@
           </el-form-item>
           <el-form-item label="知识点">
             <property-tree-select
-              v-model="formModel.questionProperty"
+              ref="PropertyTreeSelect"
+              class="width-full"
+              v-model="formModel.propertyIdList"
               :course-id="formModel.courseId"
-              @change="propertyChange"
             ></property-tree-select>
             <br />
             <el-input
-              v-model="formModel.supplement"
+              class="padding-top-6"
+              v-model="formModel.knowledgeNotes"
               placeholder="请录入知识点补充说明"
               type="textarea"
               clearable
             ></el-input>
           </el-form-item>
-
-          <el-form-item>
-            <el-button type="danger" @click="toProduct">生成试题</el-button>
+          <el-form-item style="margin: 0">
+            <el-button
+              type="primary"
+              :loading="hasTaskRunning || loading"
+              @click="toProduct"
+              >生成试题</el-button
+            >
           </el-form-item>
         </el-form>
       </div>
 
       <div class="part-box">
-        <div class="box-justify">
+        <div class="part-box-header">
           <h2 class="part-box-title">检查试题</h2>
           <div>
             <el-button
@@ -129,12 +144,12 @@
               ></rich-text>
             </div>
           </el-table-column>
-          <el-table-column label="课程" width="120">
-            <template slot-scope="scope">
-              <span>{{ scope.row.course.name }}</span>
-            </template>
+          <el-table-column label="题型" prop="questionType" width="100">
+            <span slot-scope="scope">
+              {{ scope.row.questionType | questionTypeFilter }}
+            </span>
           </el-table-column>
-          <el-table-column label="题型" prop="sourceDetailName" width="100">
+          <el-table-column label="生成时间" prop="creationTime" width="170">
           </el-table-column>
           <el-table-column label="操作" width="180" fixed="right">
             <template slot-scope="scope">
@@ -175,7 +190,6 @@
     <!-- GptQuestionEditDialog -->
     <gpt-question-edit-dialog
       ref="GptQuestionEditDialog"
-      :option-info="{ ...searchFormModel, propertyInfos }"
       :question="curQuestion"
       @modified="getList"
     ></gpt-question-edit-dialog>
@@ -191,26 +205,38 @@ import {
   gptQuestionListApi,
   saveGptQuestionApi,
   deleteGptQuestionApi,
+  gptTaskDetailApi,
 } from "../api";
+import timeMixin from "@/mixins/timeMixin";
 
 const initFormModel = {
   courseId: null,
   courseCode: "",
   courseName: "",
   questionType: "SINGLE_ANSWER_QUESTION",
-  questionCount: null,
-  optionCount: null,
-  fillCount: null,
-  questionProperty: [],
-  supplement: "",
+  questionCount: 1,
+  optionCount: 4,
+  blankCount: 1,
+  propertyIdList: [],
+  knowledgeNotes: "",
 };
 
 export default {
   name: "GptQuestionDialog",
   components: { PropertyTreeSelect, GptQuestionEditDialog },
+  mixins: [timeMixin],
+  props: {
+    course: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
   data() {
     return {
-      taskId: null,
+      curTaskId: null,
+      hasTaskRunning: false,
       formModel: {
         ...initFormModel,
       },
@@ -233,15 +259,64 @@ export default {
         this.formModel.questionType
       );
     },
-    IS_BOOLEAN_QUESTION() {
-      return this.formModel.questionType === "BOOL_ANSWER_QUESTION";
-    },
     IS_FILL_QUESTION() {
       return this.formModel.questionType === "FILL_BLANK_QUESTION";
     },
   },
+  beforeDestroy() {
+    this.clearSetTs();
+  },
   methods: {
-    dialogOpened() {},
+    dialogOpened() {
+      this.formModel = this.$objAssign(initFormModel, this.course);
+      this.checkTaskStatus(true);
+    },
+    dialogClose() {
+      this.resetData();
+      this.clearSetTs();
+    },
+    resetData() {
+      this.questionList = [];
+      this.selectedQuestionIds = [];
+      this.propertyInfos = [];
+      this.curQuestion = {};
+      this.searchFormModel = {};
+      this.formModel = { ...initFormModel };
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async checkTaskStatus(isReview) {
+      this.clearSetTs();
+
+      const res = await gptTaskDetailApi({
+        courseId: this.course.courseId,
+        taskId: this.curTaskId,
+      }).catch(() => {});
+      if (!res || !res.data) return;
+
+      this.curTaskId = res.data.id;
+
+      if (res.data.status === "FAILED") {
+        this.hasTaskRunning = false;
+        if (!isReview) this.$message.error("出题失败,请重新尝试!");
+        this.toPage(1);
+        return;
+      }
+      if (res.data.status === "FINISH") {
+        this.hasTaskRunning = false;
+        if (!isReview) this.$message.success("出题成功!");
+        this.toPage(1);
+        return;
+      }
+      this.hasTaskRunning = res.data.status === "RUNNING";
+      this.addSetTime(() => {
+        this.checkTaskStatus();
+      }, 3 * 1000);
+    },
     async toProduct() {
       this.loading = true;
 
@@ -251,23 +326,23 @@ export default {
       this.loading = false;
       if (!res) return;
 
+      this.curTaskId = res.data;
       this.searchFormModel = { ...this.formModel };
-      this.taskId = res.data;
-      this.toPage(1);
+
+      this.hasTaskRunning = true;
+      this.addSetTime(() => {
+        this.checkTaskStatus();
+      }, 3 * 1000);
     },
     toPage(page) {
       this.currentPage = page;
       this.getList();
     },
     async getList() {
-      // this.selectedQuestionIds = [];
-      // this.questionList = this.questions.slice(
-      //   (this.currentPage - 1) * this.pageSize,
-      //   this.currentPage * this.pageSize
-      // );
+      this.selectedQuestionIds = [];
       let data = {
-        taskId: this.taskId,
-        pageNumber: this.currentPage,
+        courseId: this.course.courseId,
+        curPage: this.currentPage,
         pageSize: this.pageSize,
       };
       const res = await gptQuestionListApi(data).catch(() => {});
@@ -284,26 +359,25 @@ export default {
       this.selectedQuestionIds = selections.map((item) => item.id);
     },
     switchQuestionType(questionType) {
-      this.questionModel.questionType = questionType;
+      this.formModel.questionType = questionType;
       this.$nextTick(() => {
         this.questionTypeChange();
       });
     },
     questionTypeChange() {
       if (this.IS_FILL_QUESTION) {
-        this.questionModel.optionCount = null;
+        this.formModel.optionCount = null;
       } else if (this.IS_SELECTION_QUESTION) {
-        this.questionModel.fillCount = null;
+        this.formModel.blankCount = null;
       } else {
-        this.questionModel.optionCount = null;
-        this.questionModel.fillCount = null;
+        this.formModel.optionCount = null;
+        this.formModel.blankCount = null;
       }
     },
-    propertyChange(propertyInfos) {
-      this.propertyInfos = propertyInfos;
-    },
     toEditQuestion(row) {
-      this.curQuestion = row;
+      const propertyInfos =
+        this.$refs.PropertyTreeSelect.getCheckedPropertyInfos(row.propertyIds);
+      this.curQuestion = { ...row, ...this.course, propertyInfos };
       this.$refs.GptQuestionEditDialog.open();
     },
     async toDeleteQuestion(row) {
@@ -327,12 +401,6 @@ export default {
       this.deleteQuestion(this.selectedQuestionIds);
     },
     async deleteQuestion(ids) {
-      // this.questions = this.questions.filter((q) => !ids.includes(q.id));
-      // this.total = this.questions.length;
-      // const maxPage = Math.ceil(this.total / this.pageSize);
-      // this.currentPage = Math.min(maxPage, this.currentPage);
-      // this.toPage(this.currentPage);
-
       this.loading = true;
       const res = await deleteGptQuestionApi(ids.join()).catch(() => {});
       this.loading = false;
@@ -348,7 +416,7 @@ export default {
       if (this.loading) return;
 
       if (!this.selectedQuestionIds.length) {
-        this.$message.error("请选择需要删除的试题!");
+        this.$message.error("请选择需要保存的试题!");
         return;
       }
 
@@ -359,15 +427,16 @@ export default {
         return;
       }
 
+      if (this.loading) return;
       this.loading = true;
-      const datas = {
-        questions: this.selectedQuestionIds,
-      };
-      const res = await saveGptQuestionApi(datas).catch(() => {});
+      const res = await saveGptQuestionApi(
+        this.selectedQuestionIds.join()
+      ).catch(() => {});
       this.loading = false;
       if (!res) return;
       this.$message.success("保存成功!");
-      this.deleteQuestion(this.selectedQuestionIds);
+      this.getList();
+      this.$emit("modified");
     },
   },
 };

+ 158 - 65
src/modules/question/components/GptQuestionEditDialog.vue

@@ -6,32 +6,50 @@
     :close-on-press-escape="false"
     append-to-body
     fullscreen
-    :show-close="false"
     @open="visibleChange"
   >
-    <div slot="title">
-      <h2>{{ isEdit ? "编辑试题" : "创建试题" }}</h2>
-      <span>课程代码:{{ formModel.courseCode }}</span>
-      <span>课程名称:{{ formModel.courseName }}</span>
+    <div slot="title" class="box-justify">
+      <div>
+        <h2>编辑试题</h2>
+        <span
+          >课程:{{ formModel.courseName }}({{ formModel.courseCode }})</span
+        >
+      </div>
+      <div>
+        <el-button
+          size="small"
+          type="primary"
+          :disabled="hasTaskRunning || buildLoading"
+          :loading="confirmLoading"
+          @click="confirm"
+          >确定</el-button
+        >
+        <el-button size="small" @click="cancel">取消</el-button>
+      </div>
     </div>
-    <div class="part-box question-edit">
+    <div class="part-box">
       <el-form label-width="100px">
-        <el-form-item v-if="isEdit" label="题型">
-          <el-button type="primary" size="small">
-            {{ formModel.questionType | questionTypeFilter }}
-          </el-button>
+        <el-form-item class="inline-top" label="题型:">
+          {{ formModel.questionType | questionTypeFilter }}
         </el-form-item>
-        <el-form-item v-if="IS_SELECTION_QUESTION" label="选项个数">
+        <el-form-item
+          v-if="IS_SELECTION_QUESTION"
+          class="inline-top"
+          label="选项个数:"
+        >
           {{ formModel.optionCount }}
         </el-form-item>
-        <el-form-item v-if="IS_BOOLEAN_QUESTION" label="填空个数">
-          {{ formModel.fillCount }}
+        <el-form-item
+          v-if="IS_FILL_QUESTION"
+          class="inline-top"
+          label="填空个数:"
+        >
+          {{ formModel.blankCount }}
         </el-form-item>
-        <el-form-item label="知识点">
+        <el-form-item label="知识点">
           <el-tag
-            v-for="content in formModel.quesProperties"
+            v-for="content in quesProperties"
             :key="content.key"
-            closable
             effect="dark"
             type="primary"
             style="margin-right: 5px; margin-bottom: 5px"
@@ -48,20 +66,26 @@
           </el-tag>
           <br />
           <el-input
-            v-model="formModel.supplement"
+            v-model="formModel.knowledgeNotes"
             placeholder="请录入知识点补充说明"
             type="textarea"
             clearable
           ></el-input>
         </el-form-item>
 
-        <el-form-item>
-          <el-button type="danger" :disabled="loading" @click="toProduct"
+        <el-form-item style="margin: 0">
+          <el-button
+            type="danger"
+            :loading="hasTaskRunning || buildLoading"
+            :disabled="confirmLoading"
+            @click="toProduct"
             >生成试题</el-button
           >
         </el-form-item>
       </el-form>
-      <!-- question-body -->
+    </div>
+    <!-- question-body -->
+    <div class="part-box question-edit">
       <component
         :is="structTypeComp"
         :key="questionKey"
@@ -70,12 +94,6 @@
         :can-edit-question-info="false"
       ></component>
     </div>
-    <div slot="footer" class="text-center">
-      <el-button type="primary" :disabled="loading" @click="confirm"
-        >确定</el-button
-      >
-      <el-button @click="cancel"> 取消</el-button>
-    </div>
   </el-dialog>
 </template>
 
@@ -86,7 +104,13 @@ import FillBlankQuestion from "./edit/FillBlankQuestion.vue";
 import SelectQuestion from "./edit/SelectQuestion.vue";
 import TextAnswerQuestion from "./edit/TextAnswerQuestion.vue";
 import { randomCode } from "@/plugins/utils";
-import { buildGptQuestionApi, updateGptQuestionApi } from "../api";
+import {
+  buildGptQuestionApi,
+  gptQuestionListApi,
+  updateGptQuestionApi,
+  gptTaskDetailApi,
+} from "../api";
+import timeMixin from "@/mixins/timeMixin";
 
 export default {
   name: "GptQuestionEditDialog",
@@ -96,6 +120,7 @@ export default {
     TextAnswerQuestion,
     BooleanQuestion,
   },
+  mixins: [timeMixin],
   props: {
     question: {
       type: Object,
@@ -103,65 +128,76 @@ export default {
         return { id: "" };
       },
     },
-    optionInfo: {
-      type: Object,
-      default() {
-        return {};
-      },
-    },
   },
   data() {
     return {
       modalIsShow: false,
+      curTaskId: null,
+      hasTaskRunning: false,
       questionModel: {
         questionType: "SINGLE_ANSWER_QUESTION",
       },
       formModel: {},
-      seletedPropertyInfos: [],
+      quesProperties: [],
       questionKey: "",
       editMode: "question",
-      loading: false,
+      buildLoading: false,
+      confirmLoading: false,
     };
   },
   computed: {
-    isEdit() {
-      return !!this.question.id;
-    },
-    title() {
-      return this.isEdit ? "编辑试题" : "创建试题";
-    },
     structTypeComp() {
       return STRUCT_TYPE_COMP_DICT[this.questionModel.questionType];
     },
-    IS_BOOLEAN_QUESTION() {
-      return this.questionModel.questionType === "BOOL_ANSWER_QUESTION";
+    IS_SELECTION_QUESTION() {
+      return ["SINGLE_ANSWER_QUESTION", "MULTIPLE_ANSWER_QUESTION"].includes(
+        this.questionModel.questionType
+      );
     },
     IS_FILL_QUESTION() {
       return this.questionModel.questionType === "FILL_BLANK_QUESTION";
     },
   },
+  beforeDestroy() {
+    this.clearSetTs();
+  },
   methods: {
-    visibleChange() {
-      this.formModel = { ...this.optionInfo };
-      delete this.formModel.propertyInfos;
-      let seletedPropertyInfos = [];
-      this.optionInfo.propertyInfos.forEach((item) => {
+    async visibleChange() {
+      this.curTaskId = this.question.taskId;
+      const res = await gptTaskDetailApi(this.question.taskId).catch(() => {});
+      if (!res || !res.data) return;
+
+      const { prompt } = res.data;
+      this.formModel = {
+        courseId: this.question.courseId,
+        courseCode: this.question.courseCode,
+        courseName: this.question.courseName,
+        questionType: prompt.questionType,
+        questionCount: 1,
+        optionCount: prompt.optionCount,
+        blankCount: prompt.blankCount,
+        propertyIdList: this.question.propertyIds,
+        knowledgeNotes: prompt.knowledgeNotes,
+      };
+
+      let quesProperties = [];
+      this.question.propertyInfos.forEach((item) => {
         let nitem = {};
         nitem.key = item.map((elem) => elem.id).join("_");
         nitem.courseProperty = item[0];
         nitem.firstProperty = item[1];
         if (item[2]) nitem.secondProperty = item[2];
-        seletedPropertyInfos.push(nitem);
+        quesProperties.push(nitem);
       });
-      this.seletedPropertyInfos = seletedPropertyInfos;
+      this.quesProperties = quesProperties;
 
       this.initData(this.question);
     },
     initData(question) {
       const courseInfo = {
-        courseId: question.course.id,
-        courseCode: question.course.code,
-        courseName: question.course.name,
+        courseId: this.formModel.courseId,
+        courseCode: this.formModel.courseCode,
+        courseName: this.formModel.courseName,
       };
       let questionModel = {
         ...question,
@@ -179,21 +215,78 @@ export default {
 
       this.questionKey = randomCode();
     },
-    cancel() {
+    async cancel() {
+      if (this.hasTaskRunning) {
+        const confirm = await this.$confirm(
+          "当前正在生成试题,确定要退出吗?",
+          "提示",
+          {
+            type: "warning",
+          }
+        ).catch(() => {});
+        if (confirm !== "confirm") return;
+
+        this.clearSetTs();
+      }
       this.modalIsShow = false;
     },
     open() {
       this.modalIsShow = true;
     },
     async toProduct() {
-      this.loading = true;
+      this.buildLoading = true;
 
-      const res = await buildGptQuestionApi({ ...this.formModel }).catch(
-        () => {}
-      );
-      this.loading = false;
+      const res = await buildGptQuestionApi({
+        ...this.formModel,
+        sideQuestionId: this.questionModel.id,
+      }).catch(() => {});
+      this.buildLoading = false;
       if (!res) return;
-      this.initData(res.data);
+
+      this.curTaskId = res.data;
+      this.hasTaskRunning = true;
+      this.addSetTime(() => {
+        this.checkTaskStatus();
+      }, 3 * 1000);
+    },
+    async checkTaskStatus() {
+      this.clearSetTs();
+
+      if (!this.curTaskId) return;
+
+      const res = await gptTaskDetailApi({
+        courseId: this.formModel.courseId,
+        taskId: this.curTaskId,
+      }).catch(() => {});
+      if (!res || !res.data) return;
+
+      if (res.data.status === "FAILED") {
+        this.hasTaskRunning = false;
+        this.$message.error("重新生成试题失败,请重新尝试!");
+        this.getResult();
+        return;
+      }
+      if (res.data.status === "FINISH") {
+        this.hasTaskRunning = false;
+        this.$message.success("重新生成试题成功!");
+        this.getResult();
+        return;
+      }
+      this.hasTaskRunning = res.data.status === "RUNNING";
+      this.addSetTime(() => {
+        this.checkTaskStatus();
+      }, 3 * 1000);
+    },
+    async getResult() {
+      let data = {
+        courseId: this.formModel.courseId,
+        taskId: this.curTaskId,
+        curPage: 1,
+        pageSize: 1,
+      };
+      const res = await gptQuestionListApi(data).catch(() => {});
+      if (!res) return;
+      this.initData(res.data.content[0]);
     },
     async confirm() {
       const valid = await this.$refs.QuestionEditDetail.validate().catch(
@@ -201,17 +294,17 @@ export default {
       );
       if (!valid) return;
 
-      if (this.loading) return;
-      this.loading = true;
+      if (this.confirmLoading) return;
+      this.confirmLoading = true;
 
       let questionModel = this.$refs.QuestionEditDetail.getData();
       const res = await updateGptQuestionApi(questionModel).catch(() => {});
-      this.loading = false;
+      this.confirmLoading = false;
       if (!res) return;
 
-      this.$message.success(this.title + "成功");
+      this.$message.success("保存成功");
       this.$emit("modified");
-      this.cancel();
+      this.modalIsShow = false;
     },
   },
 };

+ 5 - 5
src/modules/question/components/PropertyTreeSelect.vue

@@ -43,7 +43,7 @@
     <el-popover
       v-model="visible"
       popper-class="property-popover"
-      placement="bottom"
+      placement="bottom-left"
       trigger="manual"
     >
       <div ref="popoverRef" slot="reference"></div>
@@ -129,7 +129,7 @@ export default {
       if (val !== oldval) this.initSelected(val);
     },
     courseId(val, oldval) {
-      console.log(val, oldval);
+      // console.log(val, oldval);
       if (val !== oldval) {
         this.resetData();
         this.emitChange();
@@ -198,13 +198,13 @@ export default {
       this.selectedPropName = nodes.map((item) => item.name).join(";");
       this.emitChange();
     },
-    getCheckedPropertyInfos() {
+    getCheckedPropertyInfos(selectedPropIds = []) {
       let propertyInfos = [];
       const getProperty = (propertyList, parents) => {
         propertyList.forEach((item) => {
           let nitem = Object.assign({}, item, { propertyList: null });
           let nparents = [...parents, nitem];
-          if (this.selectedPropIds.includes(item.id)) {
+          if (selectedPropIds.includes(item.id)) {
             propertyInfos.push(nparents);
           }
 
@@ -220,7 +220,7 @@ export default {
     },
     emitChange() {
       this.selectedPropIds = this.$refs.PropertyTree.getCheckedKeys();
-      const propertyInfos = this.getCheckedPropertyInfos();
+      const propertyInfos = this.getCheckedPropertyInfos(this.selectedPropIds);
       this.$emit("input", this.selectedPropIds);
       this.$emit("change", propertyInfos);
     },

+ 5 - 0
src/modules/question/components/edit/BankedClozeQuestion.vue

@@ -89,6 +89,7 @@
           ref="MatchQuestion"
           :question="subq"
           :parent-question="modalForm"
+          :can-edit-question-info="canEditQuestionInfo"
         ></match-question>
       </el-collapse-item>
     </el-collapse>
@@ -120,6 +121,10 @@ export default {
         return {};
       },
     },
+    canEditQuestionInfo: {
+      type: Boolean,
+      default: true,
+    },
   },
   data() {
     return {

+ 1 - 0
src/modules/question/components/edit/FillBlankQuestion.vue

@@ -40,6 +40,7 @@
       </el-form-item>
     </el-form>
     <question-info-edit
+      v-if="canEditQuestionInfo"
       ref="QuestionInfoEdit"
       :question="modalForm"
       @change="questionInfoChange"

+ 1 - 0
src/modules/question/components/edit/MatchQuestion.vue

@@ -31,6 +31,7 @@
       </el-form-item>
     </el-form>
     <question-info-edit
+      v-if="canEditQuestionInfo"
       ref="QuestionInfoEdit"
       :question="modalForm"
       @change="questionInfoChange"

+ 5 - 0
src/modules/question/components/edit/NestedQuestion.vue

@@ -48,6 +48,7 @@
           :question="subq"
           :show-ques-body="!IS_CLOZE"
           :ques-body-required="!IS_LISTENING_QUESTION"
+          :can-edit-question-info="canEditQuestionInfo"
         ></component>
       </el-collapse-item>
     </el-collapse>
@@ -113,6 +114,10 @@ export default {
         return {};
       },
     },
+    canEditQuestionInfo: {
+      type: Boolean,
+      default: true,
+    },
   },
   data() {
     return {

+ 1 - 0
src/modules/question/components/edit/SelectQuestion.vue

@@ -101,6 +101,7 @@
       </el-form-item>
     </el-form>
     <question-info-edit
+      v-if="canEditQuestionInfo"
       ref="QuestionInfoEdit"
       :question="modalForm"
       @change="questionInfoChange"

+ 1 - 0
src/modules/question/components/edit/TextAnswerQuestion.vue

@@ -27,6 +27,7 @@
       </el-form-item>
     </el-form>
     <question-info-edit
+      v-if="canEditQuestionInfo"
       ref="QuestionInfoEdit"
       :question="modalForm"
       @change="questionInfoChange"

+ 13 - 4
src/modules/question/views/QuestionManage.vue

@@ -240,6 +240,16 @@
       :data="questionImportData"
       @modified="toPage(1)"
     ></question-import-edit>
+    <!-- GptQuestionDialog -->
+    <gpt-question-dialog
+      ref="GptQuestionDialog"
+      :course="{
+        courseId: curCourse.id,
+        courseCode: curCourse.code,
+        courseName: curCourse.name,
+      }"
+      @modified="getList"
+    ></gpt-question-dialog>
   </div>
 </template>
 
@@ -259,6 +269,7 @@ import QuestionPreviewDialog from "../components/QuestionPreviewDialog.vue";
 import FolderQuestionManageDialog from "../components/FolderQuestionManageDialog.vue";
 import PropertyTreeSelect from "../components/PropertyTreeSelect.vue";
 import QuestionImportEdit from "../components/QuestionImportEdit.vue";
+import GptQuestionDialog from "../components/GptQuestionDialog.vue";
 
 export default {
   name: "QuestionMamage",
@@ -272,6 +283,7 @@ export default {
     FolderQuestionManageDialog,
     PropertyTreeSelect,
     QuestionImportEdit,
+    GptQuestionDialog,
   },
   data() {
     return {
@@ -463,10 +475,7 @@ export default {
         this.$message.error("请先选择课程!");
         return;
       }
-      window.sessionStorage.setItem(
-        "courseInfo",
-        JSON.stringify(this.curCourse)
-      );
+      this.$refs.GptQuestionDialog.open();
     },
   },
 };