DialogCard.vue 4.9 KB

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