PPT 编辑器采用三栏布局:左侧 CollapsibleToolbar(配置面板)、中间 Canvas(画布)、右侧 Toolbar(目前隐藏)。english-speaking 功能已完成教师配置流程(Layer 1-3),教师点击"应用配置"后触发 parentWindow.addTool(77) 向画布添加一个 PPTFrameElement。
画布中的 BaseFrameElement.vue 负责渲染 PPTFrameElement,按 toolType 分支:
<video> 标签<iframe> (bilibili)<iframe :src="url"> 或 <iframe :srcdoc="url">当前 toolType 77 走的是通用 iframe 分支。现在要改为直接渲染 Vue 组件,不再使用 iframe。
enspeak demo 项目中的 TopicDiscussionPreview 组件提供了完整的学生视角预览,包含三个阶段:准备页(Ready)→ 对话过程(Chatting)→ 完成报告(Completed),需要迁移到 PPT 项目中。
demo 组件依赖树:
TopicDiscussionPreview.tsx
├── StudentPreview.tsx — 16:9 PPT 页面容器
├── DialogueChatView.tsx — 对话交互(语音条、即时反馈、提示、徽章)
├── OverallReport.tsx — 整体报告(评分、四维能力、AI 点评、统计)
└── DetailedReport.tsx — 详细报告(按轮次分组、单句评价卡片)
Goals:
src/views/Editor/EnglishSpeaking/preview/ 目录下BaseFrameElement.vue 中 toolType 77 时直接渲染 Vue 组件(替代 iframe)src/types/englishSpeaking.ts 中追加预览相关类型Non-Goals:
选择: 在 BaseFrameElement.vue 的 v-if/v-else-if 链中新增 toolType 77 分支,直接渲染 <TopicDiscussionPreview> Vue 组件。
理由: 与 iframe 方式相比,Vue 组件可以直接访问 Pinia store 和父组件状态,便于后续配置联动;同时避免了 iframe 通信的复杂性。类似 toolType 74 渲染 <video> 的模式。
实现:
<!-- BaseFrameElement.vue 第 26 行后插入 -->
<TopicDiscussionPreview
v-else-if="elementInfo.toolType === 77 && !isThumbnail && isVisible"
:style="{ width: width + 'px', height: height + 'px' }"
/>
选择: 平铺式组件(每个子组件独立文件),保持与 demo 一致的层级结构。 理由: 每个组件职责明确、代码量大(DialogueChatView 700+ 行),拆分有利于维护。
选择: 组件内 ref 管理预览状态(dialogueState、messages 等)。 理由: 预览状态是纯 UI 状态,不需要跨组件共享或持久化,使用 store 过度设计。
选择: 手动转换为 scoped SCSS,与 PPT 项目其他组件保持一致。 理由: PPT 项目不使用 Tailwind,保持技术栈统一。
选择: 所有图标(MicIcon、VolumeIcon、LightbulbIcon、RefreshIcon、XIcon、ChevronDownIcon、PlayIcon、CheckIcon)使用 SVG 内联方式直接写在模板中。
理由: PPT 项目没有统一的图标组件库,内联 SVG 最简单直接,不引入额外依赖。从 enspeak demo 的 @/components/icons 中提取 SVG 路径数据。
选择: 在现有 src/types/englishSpeaking.ts 中追加预览相关类型(OverallEvaluation、SentenceEvaluation、AIRole 等)。
理由: 该文件已存在且包含配置侧类型(TopicDiscussionConfig、Role 等),预览类型与其紧密关联,保持集中管理。