englishSpeaking.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // 练习方式
  2. export type PracticeMode = 'rounds' | 'time' | 'free'
  3. // 评分方式
  4. export type ScoreMode = 'numeric' | 'letter' | 'comment_only'
  5. // AI 角色
  6. export interface Role {
  7. id: string
  8. name: string
  9. avatar: string
  10. avatarUrl?: string
  11. identity: string
  12. personality: string
  13. difficulty: number
  14. isRecommended?: boolean
  15. }
  16. // 评估维度
  17. export interface EvalDimensions {
  18. accuracy: boolean
  19. fluency: boolean
  20. completeness: boolean
  21. rhythm: boolean
  22. }
  23. // 练习设置
  24. export interface PracticeSettings {
  25. mode: PracticeMode
  26. rounds: number
  27. duration: number // 时长(分钟)
  28. showEnglish: boolean
  29. taskHint: boolean
  30. stutterHint: boolean
  31. }
  32. // 评估设置
  33. export interface EvaluationSettings {
  34. showReport: boolean
  35. dimensions: EvalDimensions
  36. scoreMode: ScoreMode
  37. }
  38. // 学习目标
  39. export interface LearningGoals {
  40. vocabulary: string[]
  41. sentences: string[]
  42. }
  43. // 话题讨论配置
  44. export interface TopicDiscussionConfig {
  45. topic: string
  46. grade: string
  47. selectedRole: string
  48. learningGoals: LearningGoals
  49. practice: PracticeSettings
  50. evaluation: EvaluationSettings
  51. }
  52. // 推荐任务卡片
  53. export interface TopicDiscussionTask {
  54. id: string
  55. titleZh: string
  56. titleEn: string
  57. subtitle: string
  58. difficulty: 1 | 2 | 3
  59. rounds: number
  60. durationMinutes: number
  61. vocabulary: string[]
  62. sentences: string[]
  63. note: string
  64. }
  65. // 教材单元
  66. export interface CurriculumUnit {
  67. id: string
  68. number: string
  69. title: string
  70. description: string
  71. vocabulary: string[]
  72. sentences: string[]
  73. }
  74. // 教材年级
  75. export interface CurriculumGrade {
  76. id: string
  77. name: string
  78. semester: string
  79. units: CurriculumUnit[]
  80. }
  81. // 教材
  82. export interface CurriculumTextbook {
  83. id: string
  84. name: string
  85. grades: CurriculumGrade[]
  86. }
  87. // 教材数据根
  88. export interface CurriculumData {
  89. textbooks: CurriculumTextbook[]
  90. }
  91. // 创建方式
  92. export type CreationMode = 'smart' | 'ai' | 'manual'
  93. // 页面层级
  94. export type PageMode = 'layer1' | 'layer2' | 'config'
  95. // 练习类型
  96. export type ExerciseType = 'speaking' | 'listening' | 'reading' | 'writing'
  97. // ==================== 预览组件类型定义 ====================
  98. // 评分等级
  99. export type ScoreLevel = 'excellent' | 'good' | 'fair' | 'needsWork'
  100. // 评分展示方式(复用配置侧的 ScoreMode)
  101. export type ScoreDisplayMode = ScoreMode
  102. // 对话统计数据
  103. export interface DialogueStatistics {
  104. totalRounds: number
  105. averageScore: number
  106. highestScore: number
  107. highestRound: number
  108. grammarErrors: number
  109. excellentExpressions: number
  110. totalDuration: number // 秒
  111. }
  112. // 下次挑战推荐
  113. export interface NextChallenge {
  114. difficulty?: string
  115. unlockedTopic?: string
  116. suggestedMode?: string
  117. }
  118. // 单句评价
  119. export interface SentenceEvaluation {
  120. id: string
  121. round: number
  122. role: 'ai' | 'student'
  123. content: string
  124. contentZh?: string
  125. audioUrl?: string
  126. audioDuration?: number
  127. score?: number
  128. pronunciation?: {
  129. accuracy: number
  130. intonation: number
  131. stress: number
  132. fluency: number
  133. }
  134. feedback?: {
  135. comment: string
  136. betterExpression: string
  137. }
  138. }
  139. // 整体评价报告
  140. export interface OverallEvaluation {
  141. overallScore: number
  142. scoreLevel: ScoreLevel
  143. percentile: number
  144. dimensions: {
  145. fluency: number
  146. interaction: number
  147. vocabulary: number
  148. grammar: number
  149. }
  150. aiComment: string
  151. highlights: string[]
  152. improvements: string[]
  153. nextChallenge: NextChallenge
  154. statistics: DialogueStatistics
  155. sentenceEvaluations: SentenceEvaluation[]
  156. }
  157. // 预览用 AI 角色(扩展配置侧的 Role)
  158. export interface PreviewAIRole {
  159. id: string
  160. name: string
  161. avatar: string
  162. identity: string
  163. personality: string
  164. speakingStyle: 'formal' | 'casual' | 'playful'
  165. speed: 'slow' | 'normal' | 'fast'
  166. isCustom: boolean
  167. isRecommended?: boolean
  168. }
  169. // 消息状态
  170. export type MessageStatus = 'loading' | 'done' | 'error'
  171. // 对话消息
  172. export interface PreviewChatMessage {
  173. id: string
  174. role: 'ai' | 'student'
  175. content: string
  176. timestamp: Date
  177. status?: MessageStatus
  178. error?: string
  179. turnId?: string // set when message is created via begin/commit
  180. recovery?: 'retry' | 'rerecord' | 'restart' // set on error; drives the button matrix
  181. audioBlob?: Blob
  182. audioUrl?: string
  183. audioDuration?: number // NEW: 秒,由后端 transcript 事件 / sessions-latest 写入
  184. evaluation?: {
  185. dimensions: {
  186. accuracy: 'excellent' | 'good' | 'improve'
  187. fluency: 'excellent' | 'good' | 'improve'
  188. completeness: 'excellent' | 'good' | 'improve'
  189. rhythm: 'excellent' | 'good' | 'improve'
  190. }
  191. suggestion: string
  192. betterExpression?: string
  193. suggestedWords?: string[]
  194. wordAnalysis?: {
  195. word: string
  196. status: 'correct' | 'improvable'
  197. userPronunciation?: string
  198. standardPronunciation?: string
  199. tip?: string
  200. }[]
  201. }
  202. }
  203. // ==================== 对话引擎类型定义 ====================
  204. // SSE 事件类型
  205. export type SSEEvent =
  206. | { type: 'transcript'; text: string; audioDuration?: number | null }
  207. | { type: 'token'; text: string }
  208. | { type: 'done'; isComplete: boolean }
  209. | { type: 'error'; message: string }
  210. // 对话会话配置
  211. export interface SessionConfig {
  212. topic: string
  213. grade: string
  214. roleId: string
  215. totalRounds: number
  216. /** 时长(分钟)。与 totalRounds 是并存的两个结束条件,后端据此计算 expiresAt */
  217. durationMinutes: number
  218. vocabulary?: string[]
  219. sentences?: string[]
  220. configId?: string | null
  221. userId?: string | null
  222. }
  223. // 对话会话信息 (createSession 返回)
  224. export interface SessionInfo {
  225. sessionId: string
  226. totalRounds: number
  227. currentRound: number
  228. expiresAt: string | null
  229. }
  230. // 开场白生成结果 (generateGreeting 返回)
  231. export interface GreetingInfo {
  232. aiMessage: string
  233. }
  234. export interface HistoricalDialogueMessage {
  235. id: string
  236. round: number
  237. role: 'ai' | 'student'
  238. content: string
  239. audioUrl?: string | null
  240. audioDuration?: number | null // NEW: 秒,来自后端 sessions/latest
  241. clientTurnId?: string | null
  242. }
  243. // 用于启动 chat view 的最小 session 信息(父组件 createSession 后传给 DialogueChatView)
  244. // expiresAt 由后端基于 createSession 时传入的 durationMinutes 计算下发 —— 后端权威,
  245. // 关页面/刷新/换设备重进都接续同一个截止时刻,确保倒计时不会因任何原因暂停。
  246. export interface SessionStartInfo {
  247. sessionId: string
  248. expiresAt: string | null
  249. currentRound?: number
  250. messages?: HistoricalDialogueMessage[]
  251. }
  252. export interface LatestSessionInfo extends SessionStartInfo {
  253. status: 'active' | 'completed' | 'abandoned'
  254. totalRounds: number
  255. currentRound: number
  256. createdAt: string | null
  257. completedAt: string | null
  258. messages: HistoricalDialogueMessage[]
  259. }
  260. export interface LatestSessionResponse {
  261. session: LatestSessionInfo | null
  262. }
  263. // 对话报告
  264. export type DialogueReportStatus = 'evaluating' | 'ready' | 'failed' | 'incomplete'
  265. export interface DialogueReport {
  266. status: DialogueReportStatus
  267. evaluation: OverallEvaluation
  268. }
  269. export interface TaskHint {
  270. practice_level: string
  271. conversation_topic: string
  272. current_question: string
  273. example_sentences: {
  274. english: string
  275. chinese: string
  276. }[]
  277. key_vocabulary: {
  278. word: string
  279. meaning: string
  280. }[]
  281. }
  282. // 对话 API 接口
  283. export interface DialogueAPI {
  284. createSession(config: SessionConfig): Promise<SessionInfo>
  285. getLatestSession(configId: string, userId: string): Promise<LatestSessionResponse>
  286. completeSession(sessionId: string): Promise<void>
  287. /** Throws DOMException('AbortError') on signal abort; throws DialogueApiError on non-OK HTTP. */
  288. generateGreeting(sessionId: string, turnId: string, signal?: AbortSignal): Promise<GreetingInfo>
  289. generateTaskHint(sessionId: string): Promise<TaskHint>
  290. speak(sessionId: string, audioBlob: Blob, signal: AbortSignal, turnId: string): AsyncGenerator<SSEEvent>
  291. getReport(sessionId: string): Promise<DialogueReport>
  292. }
  293. // 徽章成就
  294. export interface BadgeAchievement {
  295. id: string
  296. name: string
  297. nameEn: string
  298. icon: string
  299. description: string
  300. }
  301. // 预览对话状态
  302. export type PreviewDialogueState = 'checking-history' | 'ready' | 'chatting' | 'completed'