DialogCard.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <div class="dialog-card-container">
  3. <!-- 普通对话类型 -->
  4. <DigitalDialogue
  5. v-if="dialogue?.type === 'digital'"
  6. :role-name="dialogue?.roleName"
  7. :content="dialogue?.content"
  8. :script-roles="scriptRoles"
  9. :index="index"
  10. />
  11. <!-- 提问类型(只显示提问内容,不显示用户输入) -->
  12. <QuestDialogue
  13. v-else-if="dialogue?.type === 'quest'"
  14. :role-name="dialogue?.roleName"
  15. :content="dialogue?.content"
  16. :script-roles="scriptRoles"
  17. :index="index"
  18. />
  19. <!-- 用户输入类型(根据上一条问题类型显示不同输入方式) -->
  20. <UserDialogue
  21. v-else-if="dialogue?.type === 'user'"
  22. :question="previousQuest?.content"
  23. :question-type="getQuestionType(previousQuest)"
  24. :options="previousQuest?.options"
  25. @user-input-submit="$emit('user-input-submit', $event)"
  26. @single-choice-submit="$emit('single-choice-submit', $event)"
  27. />
  28. <!-- 视频显示 -->
  29. <VideoDisplay
  30. v-else-if="dialogue?.type === 'video'"
  31. :video-url="dialogue?.videoUrl"
  32. @ended="$emit('video-ended', $event)"
  33. />
  34. <!-- 诗词朗读评价 -->
  35. <PoemReadingDialogue
  36. v-if="dialogue?.type === 'poem_reading'"
  37. :content="dialogue?.content"
  38. :role-id="getRoleIdByRoleName(dialogue?.roleName, scriptRoles)"
  39. @evaluation-complete="$emit('poem-reading-complete', $event)"
  40. />
  41. <!-- 写诗评价 -->
  42. <WriteReadingDialogue
  43. v-if="dialogue?.type === 'write_reading'"
  44. :content="dialogue?.content"
  45. @submit="$emit('write-reading-submit', $event)"
  46. />
  47. <!-- 背诵诗词评价 -->
  48. <ReciteReadingDialogue
  49. v-if="dialogue?.type === 'recite_reading'"
  50. :content="dialogue?.content"
  51. :role-id="getRoleIdByRoleName(dialogue?.roleName, scriptRoles)"
  52. @evaluation-complete="$emit('poem-reading-complete', $event)"
  53. />
  54. <!-- 诗词显示 -->
  55. <PoemDisplay
  56. v-if="poemShow"
  57. :content="poemContent"
  58. />
  59. </div>
  60. </template>
  61. <script setup>
  62. import DigitalDialogue from './dialogType/DigitalDialogue.vue';
  63. import QuestDialogue from './dialogType/QuestDialogue.vue';
  64. import UserDialogue from './dialogType/UserDialogue.vue';
  65. import PoemDisplay from './dialogType/PoemDisplay.vue';
  66. import VideoDisplay from './dialogType/VideoDisplay.vue';
  67. import PoemReadingDialogue from './dialogType/PoemReadingDialogue.vue';
  68. import WriteReadingDialogue from './dialogType/WriteReadingDialogue.vue';
  69. import ReciteReadingDialogue from './dialogType/ReciteReadingDialogue.vue';
  70. /**
  71. * DialogCard - 统一对话卡片容器
  72. * 根据对话类型渲染不同的子组件
  73. */
  74. /**
  75. * Props 定义
  76. * @prop {Object} dialogue - 当前对话数据
  77. * @prop {Array} scriptRoles - 角色列表
  78. * @prop {Number} index - 对话索引
  79. * @prop {Object} previousQuest - 上一条提问对话
  80. * @prop {Boolean} poemShow - 是否显示诗词
  81. * @prop {String} poemContent - 诗词内容
  82. */
  83. defineProps({
  84. dialogue: {
  85. type: Object,
  86. default: null
  87. },
  88. scriptRoles: {
  89. type: Array,
  90. default: () => []
  91. },
  92. index: {
  93. type: Number,
  94. default: 0
  95. },
  96. previousQuest: {
  97. type: Object,
  98. default: null
  99. },
  100. poemShow: {
  101. type: Boolean,
  102. default: false
  103. },
  104. poemContent: {
  105. type: String,
  106. default: ''
  107. }
  108. });
  109. /**
  110. * Emits 定义
  111. * @event user-input-submit - 用户文本输入提交
  112. * @event single-choice-submit - 单选问题提交
  113. * @event video-ended - 视频播放结束
  114. * @event poem-reading-complete - 诗词朗读评价完成
  115. */
  116. defineEmits([
  117. 'user-input-submit',
  118. 'single-choice-submit',
  119. 'write-reading-submit',
  120. 'video-ended',
  121. 'poem-reading-complete'
  122. ]);
  123. /**
  124. * 获取问题类型
  125. * @param {Object} questDialogue - 提问对话数据
  126. * @returns {String} 问题类型:'singleChoice' | 'AI Q&A'
  127. */
  128. const getQuestionType = (questDialogue) => {
  129. if (!questDialogue) return 'AI Q&A';
  130. if (questDialogue.questionType === 'singleChoice' && questDialogue.options?.length > 0) {
  131. return 'singleChoice';
  132. }
  133. return 'AI Q&A';
  134. };
  135. /**
  136. * 根据角色名称获取角色ID
  137. * @param {String} roleName - 角色名称
  138. * @param {Array} roles - 角色列表
  139. * @returns {String|Number} 角色ID,如果找不到则返回原值
  140. */
  141. const getRoleIdByRoleName = (roleName, roles) => {
  142. if (!roleName || !roles) return roleName;
  143. const role = roles.find(r => r.name === roleName);
  144. return role ? role.id : roleName;
  145. };
  146. </script>
  147. <style scoped lang="scss">
  148. .dialog-card-container {
  149. display: flex;
  150. flex-direction: column;
  151. align-items: center;
  152. }
  153. </style>