Prechádzať zdrojové kódy

AI古诗词新增提问对话类型为单选逻辑和样式

liyanbo 1 týždeň pred
rodič
commit
237d771418
1 zmenil súbory, kde vykonal 216 pridanie a 1 odobranie
  1. 216 1
      src/views/AIPage/aiGenerate/DialogContent.vue

+ 216 - 1
src/views/AIPage/aiGenerate/DialogContent.vue

@@ -88,7 +88,7 @@
 
       <!-- 用户输入卡片 -->
       <div
-        v-if="currentDialogue.type === 'user'"
+        v-if="currentDialogue.type === 'user' && !isUserSingleChoice"
         class="dialogue-card user-input-card"
       >
         <div class="dialogue-header">
@@ -109,6 +109,38 @@
         </div>
       </div>
 
+      <!-- 单选问题卡片(在user类型时显示) -->
+      <div
+        v-if="isUserSingleChoice"
+        class="dialogue-card single-choice-card"
+      >
+        <div class="dialogue-header">
+          <span class="role-name">我</span>
+        </div>
+        <div class="single-choice-content">
+          <!-- 问题描述 -->
+          <div class="question-text" v-html="parseMarkdown(previousQuestDialogue?.content || '')"></div>
+          <!-- 选项列表 -->
+          <div class="options-list">
+            <div
+              v-for="(option, index) in previousQuestDialogue?.options"
+              :key="index"
+              class="option-item"
+              :class="{ 'selected': selectedOption === optionLabels[index] }"
+              @click="selectOption(optionLabels[index])"
+            >
+              <span class="option-label">{{ optionLabels[index] }}</span>
+              <span class="option-content">{{ option.content }}</span>
+            </div>
+          </div>
+          <!-- 操作按钮 -->
+          <div class="input-actions">
+            <button class="cancel-btn" @click="cancelSingleChoice">清空选择</button>
+            <button class="submit-btn" :disabled="!selectedOption" @click="submitSingleChoice">提交答案</button>
+          </div>
+        </div>
+      </div>
+
       <!-- 输入按钮区域 -->
       <div class="input-buttons-container" >
         <!-- 上一个对话按钮 -->
@@ -211,6 +243,10 @@ const voiceRecognizedText = ref("")
 const showPoem = ref(false)
 // 当前诗词内容
 const currentPoemContent = ref('')
+// 单选问题选中答案
+const selectedOption = ref('')
+// 选项标签映射
+const optionLabels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
 
 // 音频对象
 // 背景音频
@@ -299,6 +335,32 @@ const handleRecordingStatusChanged = (isRecording) => {
   }
 }
 
+// 获取上一条quest对话
+const previousQuestDialogue = computed(() => {
+  const prevDialogue = getPreviousDialogue()
+  if (prevDialogue?.type === 'quest') {
+    return prevDialogue
+  }
+  return null
+})
+
+// 判断当前user对话是否应该显示单选框
+const isUserSingleChoice = computed(() => {
+  if (currentDialogue.value?.type !== 'user') return false
+  const prevDialogue = previousQuestDialogue.value
+  return prevDialogue?.questionType === 'singleChoice' && 
+         prevDialogue?.options && 
+         prevDialogue.options.length > 0
+})
+
+// 判断是否是单选问题(quest类型时)
+const isSingleChoiceQuestion = computed(() => {
+  return currentDialogue.value?.type === 'quest' && 
+         currentDialogue.value?.questionType === 'singleChoice' && 
+         currentDialogue.value?.options && 
+         currentDialogue.value.options.length > 0
+})
+
 // 提交用户输入
 const submitUserInput = async () => {
   if (userInput.value.trim()) {
@@ -314,6 +376,26 @@ const cancelUserInput = () => {
   userInput.value = ''
 }
 
+// 选择单选选项
+const selectOption = (label) => {
+  selectedOption.value = label
+}
+
+// 取消单选选择
+const cancelSingleChoice = () => {
+  selectedOption.value = ''
+}
+
+// 提交单选答案
+const submitSingleChoice = async () => {
+  if (!selectedOption.value) return
+  
+  console.log('用户选择:', selectedOption.value)
+  
+  await createAiChart();
+  await doSendSingleChoiceMessage();
+}
+
 // 解析 Markdown 内容
 const parseMarkdown = (content) => {
   if (!content) return ''
@@ -883,6 +965,51 @@ const doSendMessage = async () => {
   userInput.value = ''
 }
 
+/** 发送单选问题消息 */
+const doSendSingleChoiceMessage = async () => {
+  if (activeConversationId.value == null) {
+    console.error('还没创建对话,不能发送!')
+    return
+  }
+
+  // 使用上一条quest对话的数据
+  const dialogue = previousQuestDialogue.value
+  if (!dialogue) {
+    console.error('找不到上一条quest对话!')
+    return
+  }
+  
+  // 构建选项字符串
+  const optionsStr = dialogue.options.map((opt, idx) => `${optionLabels[idx]}. ${opt.content}`).join(';')
+  
+  // 构建发送内容:包含问题、选项、用户答案
+  const content = `问题:${dialogue.content}\n选项:${optionsStr}\n我的答案:${selectedOption.value}\n正确答案:${dialogue.answer}\n\n请判断我的答案是否正确,并给予鼓励或夸赞,回复请精简,控制在50字内。`
+  
+  console.log('发送单选问题:', content)
+  
+  // 执行发送
+  await doSendMessageStream({
+    conversationId: activeConversationId.value,
+    content: content,
+    contentAnswer: null,
+  })
+  
+  // 清空选择
+  selectedOption.value = ''
+}
+
+// 获取上一条对话
+const getPreviousDialogue = () => {
+  const section = props.scriptData.sections[currentSectionIndex.value]
+  if (!section) return null
+  if (currentDialogueIndex.value > 0) {
+    return section.dialogues[currentDialogueIndex.value - 1]
+  }
+  return null
+}
+
+
+
 /** 显示问题回答对话 */
 const showQuestAnswerDialogue = () => {
   // 缓存当前对话
@@ -1468,6 +1595,94 @@ onUnmounted(() => {
   display: none;
 }
 
+.single-choice-card {
+  max-width: 55%;
+  position: absolute;
+  left: 50%;
+  transform: translateX(-50%);
+  bottom: rpx(50);
+  right: auto;
+  animation: dialogueEnterCenter 0.6s ease forwards;
+  z-index: 10;
+}
+
+.single-choice-card::before {
+  display: none;
+}
+
+.single-choice-content {
+  font-size: rpx(12);
+  line-height: 1.4;
+  color: #333;
+  text-align: left;
+  width: 100%;
+}
+
+.question-text {
+  margin-bottom: rpx(10);
+  padding-bottom: rpx(8);
+  border-bottom: rpx(1) dashed #ddd;
+  font-weight: 500;
+}
+
+.options-list {
+  display: flex;
+  flex-direction: column;
+  gap: rpx(6);
+  margin-bottom: rpx(12);
+}
+
+.option-item {
+  display: flex;
+  align-items: center;
+  padding: rpx(8) rpx(12);
+  background: #f8f9fa;
+  border: rpx(1) solid #e9ecef;
+  border-radius: rpx(6);
+  cursor: pointer;
+  transition: all 0.3s ease;
+
+  &:hover {
+    background: #e8f4fd;
+    border-color: #409EFF;
+  }
+
+  &.selected {
+    background: #e8f4fd;
+    border-color: #409EFF;
+    box-shadow: 0 rpx(2) rpx(8) rgba(64, 158, 255, 0.2);
+  }
+}
+
+.option-label {
+  width: rpx(24);
+  height: rpx(24);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #fff;
+  border: rpx(1) solid #ddd;
+  border-radius: 50%;
+  font-size: rpx(10);
+  font-weight: 600;
+  color: #666;
+  margin-right: rpx(8);
+  flex-shrink: 0;
+  transition: all 0.3s ease;
+
+  .option-item.selected & {
+    background: #409EFF;
+    border-color: #409EFF;
+    color: #fff;
+  }
+}
+
+.option-content {
+  font-size: rpx(11);
+  color: #333;
+  flex: 1;
+}
+
 @keyframes dialogueEnterCenter {
   from {
     opacity: 0;