Browse Source

AI古诗词:
1、新加入提问类型,加入单选类型数据配置

liyanbo 1 week ago
parent
commit
d4d5997798
2 changed files with 284 additions and 20 deletions
  1. 0 17
      src/types/auto-components.d.ts
  2. 284 3
      src/views/bjdx/course/aiGenerate/aiGengrate.vue

+ 0 - 17
src/types/auto-components.d.ts

@@ -45,18 +45,13 @@ declare module 'vue' {
     Draggable: typeof import('./../components/Draggable/index.vue')['default']
     Echart: typeof import('./../components/Echart/src/Echart.vue')['default']
     Editor: typeof import('./../components/Editor/src/Editor.vue')['default']
-    ElAside: typeof import('element-plus/es')['ElAside']
-    ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer']
     ElAvatar: typeof import('element-plus/es')['ElAvatar']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
-    ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
     ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
-    ElCollapseTransition: typeof import('element-plus/es')['ElCollapseTransition']
-    ElContainer: typeof import('element-plus/es')['ElContainer']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
     ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
@@ -74,18 +69,13 @@ declare module 'vue' {
     ElementOtherConfig: typeof import('./../components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue')['default']
     ElementProperties: typeof import('./../components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue')['default']
     ElementTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/ElementTask.vue')['default']
-    ElEmpty: typeof import('element-plus/es')['ElEmpty']
-    ElFooter: typeof import('element-plus/es')['ElFooter']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
-    ElHeader: typeof import('element-plus/es')['ElHeader']
     ElIcon: typeof import('element-plus/es')['ElIcon']
-    ElImage: typeof import('element-plus/es')['ElImage']
     ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElLink: typeof import('element-plus/es')['ElLink']
-    ElMain: typeof import('element-plus/es')['ElMain']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
@@ -95,21 +85,14 @@ declare module 'vue' {
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
-    ElSegmented: typeof import('element-plus/es')['ElSegmented']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
-    ElSlider: typeof import('element-plus/es')['ElSlider']
-    ElSpace: typeof import('element-plus/es')['ElSpace']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
-    ElTableV2: typeof import('element-plus/es')['ElTableV2']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
-    ElText: typeof import('element-plus/es')['ElText']
-    ElTimeline: typeof import('element-plus/es')['ElTimeline']
-    ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
     ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']

+ 284 - 3
src/views/bjdx/course/aiGenerate/aiGengrate.vue

@@ -449,6 +449,17 @@
                           </el-select>
                         </div>
                         <div class="dialogue-content-container">
+                          <div class="question-type-select">
+                            <span class="question-type-label">提问类型:</span>
+                            <el-select
+                              v-model="dialogue.questionType"
+                              placeholder="请选择提问类型"
+                              style="width: 140px"
+                            >
+                              <el-option label="AI问答" value="AI Q&A" />
+                              <el-option label="单选题" value="singleChoice" />
+                            </el-select>
+                          </div>
                           <el-input
                             v-model="dialogue.content"
                             type="textarea"
@@ -456,6 +467,37 @@
                             placeholder="提问内容..."
                             :autosize="{ minRows: 2, maxRows: 4 }"
                           />
+                          <!-- 单选题选项 -->
+                          <div v-if="dialogue.questionType === 'singleChoice'" class="single-choice-options">
+                            <div class="options-header">
+                              <span class="options-label">选项列表:</span>
+                              <button class="add-option-btn" @click="addOption(sectionIndex, dialogueIndex)">+ 添加选项</button>
+                            </div>
+                            <div
+                              v-for="(option, optionIndex) in (dialogue.options || [])"
+                              :key="optionIndex"
+                              class="option-item"
+                            >
+                              <span class="option-label">{{ String.fromCharCode(65 + optionIndex) }}.</span>
+                              <el-input
+                                v-model="option.content"
+                                placeholder="选项内容"
+                                style="flex: 1; margin-right: 10px;"
+                              />
+                              <div class="answer-radio-wrapper">
+                                <el-radio
+                                  v-model="dialogue.answer"
+                                  :label="String.fromCharCode(65 + optionIndex)"
+                                />
+                                <span v-if="dialogue.answer === String.fromCharCode(65 + optionIndex)" class="correct-mark">✓</span>
+                              </div>
+                              <button
+                                v-if="(dialogue.options || []).length > 2"
+                                class="remove-option-btn"
+                                @click="removeOption(sectionIndex, dialogueIndex, optionIndex)"
+                              >×</button>
+                            </div>
+                          </div>
                         </div>
                         <div class="action-buttons">
                           <div class="action-buttons-row">
@@ -970,7 +1012,7 @@ const scriptData = reactive(
   }
 )
 
-// 兼容旧数据,为旧数据添加背景类型字段
+// 兼容旧数据,为旧数据添加背景类型字段和提问类型字段
 if (scriptData.sections) {
   scriptData.sections.forEach(section => {
     if (!section.backgroundType) {
@@ -983,6 +1025,16 @@ if (scriptData.sections) {
         generating: false
       };
     }
+    // 为旧数据的提问类型对话添加默认的questionType
+    if (section.dialogues) {
+      section.dialogues.forEach(dialogue => {
+        if (dialogue.type === 'quest' && !dialogue.questionType) {
+          dialogue.questionType = 'AI Q&A';
+          dialogue.options = [{ content: '' }, { content: '' }];
+          dialogue.answer = '';
+        }
+      });
+    }
   });
 }
 
@@ -1024,6 +1076,16 @@ const loadDraftAndGotoStep2 = () => {
             generating: false
           };
         }
+        // 为旧数据的提问类型对话添加默认的questionType
+        if (section.dialogues) {
+          section.dialogues.forEach(dialogue => {
+            if (dialogue.type === 'quest' && !dialogue.questionType) {
+              dialogue.questionType = 'AI Q&A';
+              dialogue.options = [{ content: '' }, { content: '' }];
+              dialogue.answer = '';
+            }
+          });
+        }
       });
     }
     currentStep.value = 2
@@ -1068,6 +1130,16 @@ watch(
                   generating: false
                 };
               }
+              // 为旧数据的提问类型对话添加默认的questionType
+              if (section.dialogues) {
+                section.dialogues.forEach(dialogue => {
+                  if (dialogue.type === 'quest' && !dialogue.questionType) {
+                    dialogue.questionType = 'AI Q&A';
+                    dialogue.options = [{ content: '' }, { content: '' }];
+                    dialogue.answer = '';
+                  }
+                });
+              }
             });
           }
         } catch (error) {
@@ -1089,6 +1161,16 @@ watch(
                     generating: false
                   };
                 }
+                // 为旧数据的提问类型对话添加默认的questionType
+                if (section.dialogues) {
+                  section.dialogues.forEach(dialogue => {
+                    if (dialogue.type === 'quest' && !dialogue.questionType) {
+                      dialogue.questionType = 'AI Q&A';
+                      dialogue.options = [{ content: '' }, { content: '' }];
+                      dialogue.answer = '';
+                    }
+                  });
+                }
               });
             }
           }
@@ -1113,6 +1195,16 @@ watch(
                   generating: false
                 };
               }
+              // 为旧数据的提问类型对话添加默认的questionType
+              if (section.dialogues) {
+                section.dialogues.forEach(dialogue => {
+                  if (dialogue.type === 'quest' && !dialogue.questionType) {
+                    dialogue.questionType = 'AI Q&A';
+                    dialogue.options = [{ content: '' }, { content: '' }];
+                    dialogue.answer = '';
+                  }
+                });
+              }
             });
           }
         }
@@ -1305,6 +1397,16 @@ const doSendMessageStream = async (conversationId, content) => {
                     generating: false
                   };
                 }
+                // 为新生成的提问类型对话添加默认的questionType
+                if (section.dialogues) {
+                  section.dialogues.forEach(dialogue => {
+                    if (dialogue.type === 'quest' && !dialogue.questionType) {
+                      dialogue.questionType = 'AI Q&A';
+                      dialogue.options = [{ content: '' }, { content: '' }];
+                      dialogue.answer = '';
+                    }
+                  });
+                }
               });
             }
           } catch (e) {
@@ -1338,6 +1440,16 @@ const doSendMessageStream = async (conversationId, content) => {
                     generating: false
                   };
                 }
+                // 为新生成的提问类型对话添加默认的questionType
+                if (section.dialogues) {
+                  section.dialogues.forEach(dialogue => {
+                    if (dialogue.type === 'quest' && !dialogue.questionType) {
+                      dialogue.questionType = 'AI Q&A';
+                      dialogue.options = [{ content: '' }, { content: '' }];
+                      dialogue.answer = '';
+                    }
+                  });
+                }
               });
             }
           }
@@ -1370,6 +1482,16 @@ const doSendMessageStream = async (conversationId, content) => {
                     generating: false
                   };
                 }
+                // 为新生成的提问类型对话添加默认的questionType
+                if (section.dialogues) {
+                  section.dialogues.forEach(dialogue => {
+                    if (dialogue.type === 'quest' && !dialogue.questionType) {
+                      dialogue.questionType = 'AI Q&A';
+                      dialogue.options = [{ content: '' }, { content: '' }];
+                      dialogue.answer = '';
+                    }
+                  });
+                }
               });
             }
           } catch (cleanError) {
@@ -1436,7 +1558,10 @@ const addQuestDialogue = (sectionIndex) => {
     content: '',
     roleName: '',
     voiceoverUrl: '',
-    generatingVoiceover: false
+    generatingVoiceover: false,
+    questionType: 'AI Q&A',
+    options: [{ content: '' }, { content: '' }],
+    answer: ''
   })
 }
 
@@ -1459,7 +1584,10 @@ const addQuestWithUserReply = (sectionIndex) => {
     content: '',
     roleName: '',
     voiceoverUrl: '',
-    generatingVoiceover: false
+    generatingVoiceover: false,
+    questionType: 'AI Q&A',
+    options: [{ content: '' }, { content: '' }],
+    answer: ''
   })
   // 添加用户回复类型对话
   scriptData.sections[sectionIndex].dialogues.push({
@@ -1471,6 +1599,29 @@ const addQuestWithUserReply = (sectionIndex) => {
   })
 }
 
+// 步骤2:添加单选题选项
+const addOption = (sectionIndex, dialogueIndex) => {
+  const dialogue = scriptData.sections[sectionIndex].dialogues[dialogueIndex]
+  if (!dialogue.options) {
+    dialogue.options = []
+  }
+  if (dialogue.options.length < 6) {
+    dialogue.options.push({ content: '' })
+  }
+}
+
+// 步骤2:删除单选题选项
+const removeOption = (sectionIndex, dialogueIndex, optionIndex) => {
+  const dialogue = scriptData.sections[sectionIndex].dialogues[dialogueIndex]
+  if (dialogue.options && dialogue.options.length > 2) {
+    dialogue.options.splice(optionIndex, 1)
+    // 如果删除的是当前选中的答案,需要重新设置答案
+    if (dialogue.answer && dialogue.answer.charCodeAt(0) - 65 >= dialogue.options.length) {
+      dialogue.answer = ''
+    }
+  }
+}
+
 // 步骤2:删除对话
 const removeDialogue = (sectionIndex, dialogueIndex) => {
   const dialogues = scriptData.sections[sectionIndex].dialogues
@@ -3257,6 +3408,136 @@ onUnmounted(() => {
   box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.1);
 }
 
+/* 提问类型选择 */
+.question-type-select {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  margin-bottom: 12px;
+}
+
+.question-type-label {
+  font-size: 14px;
+  font-weight: 600;
+  color: #666;
+}
+
+/* 单选题选项 */
+.single-choice-options {
+  margin-top: 16px;
+  padding: 16px;
+  background: #f8f9fa;
+  border-radius: 8px;
+  border: 1px solid #e8e8e8;
+}
+
+.options-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 12px;
+}
+
+.options-label {
+  font-size: 14px;
+  font-weight: 600;
+  color: #666;
+}
+
+.add-option-btn {
+  padding: 6px 12px;
+  background: #409eff;
+  color: white;
+  border: none;
+  border-radius: 4px;
+  font-size: 12px;
+  cursor: pointer;
+  transition: all 0.2s ease;
+}
+
+.add-option-btn:hover {
+  background: #66b1ff;
+}
+
+.option-item {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  margin-bottom: 10px;
+}
+
+.option-item:last-child {
+  margin-bottom: 0;
+}
+
+.option-label {
+  font-weight: 600;
+  color: #409eff;
+  width: 20px;
+  text-align: center;
+  flex-shrink: 0;
+}
+
+.answer-radio-wrapper {
+  width: 60px;
+  flex-shrink: 0;
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.remove-option-btn {
+  flex-shrink: 0;
+  background: #ff4d4f;
+  border: none;
+  color: white;
+  font-size: 14px;
+  cursor: pointer;
+  padding: 0;
+  width: 24px;
+  height: 24px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 4px;
+  transition: all 0.2s ease;
+}
+
+.remove-option-btn:hover {
+  background: #ff7875;
+}
+
+/* 答案单选框包装器 */
+.answer-radio-wrapper {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+/* 正确答案标记 */
+.correct-mark {
+  color: #52c41a;
+  font-size: 18px;
+  font-weight: bold;
+  animation: fadeIn 0.2s ease;
+}
+
+/* 调整单选框右外边距 */
+:deep(.el-radio) {
+  margin-right: 10;
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+    transform: scale(0.5);
+  }
+  to {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+
 .remove-btn {
   background: #ff4d4f;
   border: none;