|
|
@@ -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;
|