| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- // 练习方式
- export type PracticeMode = 'rounds' | 'time' | 'free'
- // 评分方式
- export type ScoreMode = 'numeric' | 'letter' | 'comment_only'
- // AI 角色
- export interface Role {
- id: string
- name: string
- avatar: string
- avatarUrl?: string
- identity: string
- personality: string
- difficulty: number
- isRecommended?: boolean
- }
- // 评估维度
- export interface EvalDimensions {
- accuracy: boolean
- fluency: boolean
- completeness: boolean
- rhythm: boolean
- }
- // 练习设置
- export interface PracticeSettings {
- mode: PracticeMode
- rounds: number
- duration: number // 时长(分钟)
- showEnglish: boolean
- taskHint: boolean
- stutterHint: boolean
- }
- // 评估设置
- export interface EvaluationSettings {
- showReport: boolean
- dimensions: EvalDimensions
- scoreMode: ScoreMode
- }
- // 学习目标
- export interface LearningGoals {
- vocabulary: string[]
- sentences: string[]
- }
- // 话题讨论配置
- export interface TopicDiscussionConfig {
- topic: string
- grade: string
- selectedRole: string
- learningGoals: LearningGoals
- practice: PracticeSettings
- evaluation: EvaluationSettings
- }
- // 推荐任务卡片
- export interface TopicDiscussionTask {
- id: string
- titleZh: string
- titleEn: string
- subtitle: string
- difficulty: 1 | 2 | 3
- rounds: number
- durationMinutes: number
- vocabulary: string[]
- sentences: string[]
- note: string
- }
- // 教材单元
- export interface CurriculumUnit {
- id: string
- number: string
- title: string
- description: string
- vocabulary: string[]
- sentences: string[]
- }
- // 教材年级
- export interface CurriculumGrade {
- id: string
- name: string
- semester: string
- units: CurriculumUnit[]
- }
- // 教材
- export interface CurriculumTextbook {
- id: string
- name: string
- grades: CurriculumGrade[]
- }
- // 教材数据根
- export interface CurriculumData {
- textbooks: CurriculumTextbook[]
- }
- // 创建方式
- export type CreationMode = 'smart' | 'ai' | 'manual'
- // 页面层级
- export type PageMode = 'layer1' | 'layer2' | 'config'
- // 练习类型
- export type ExerciseType = 'speaking' | 'listening' | 'reading' | 'writing'
- // ==================== 预览组件类型定义 ====================
- // 评分等级
- export type ScoreLevel = 'excellent' | 'good' | 'fair' | 'needsWork'
- // 评分展示方式(复用配置侧的 ScoreMode)
- export type ScoreDisplayMode = ScoreMode
- // 对话统计数据
- export interface DialogueStatistics {
- totalRounds: number
- averageScore: number
- highestScore: number
- highestRound: number
- grammarErrors: number
- excellentExpressions: number
- totalDuration: number // 秒
- }
- // 下次挑战推荐
- export interface NextChallenge {
- difficulty?: string
- unlockedTopic?: string
- suggestedMode?: string
- }
- // 单句评价
- export interface SentenceEvaluation {
- id: string
- round: number
- role: 'ai' | 'student'
- content: string
- contentZh?: string
- audioUrl?: string
- audioDuration?: number
- score?: number
- pronunciation?: {
- accuracy: number
- intonation: number
- stress: number
- fluency: number
- }
- feedback?: {
- comment: string
- betterExpression: string
- }
- }
- // 整体评价报告
- export interface OverallEvaluation {
- overallScore: number
- scoreLevel: ScoreLevel
- percentile: number
- dimensions: {
- fluency: number
- interaction: number
- vocabulary: number
- grammar: number
- }
- aiComment: string
- highlights: string[]
- improvements: string[]
- nextChallenge: NextChallenge
- statistics: DialogueStatistics
- sentenceEvaluations: SentenceEvaluation[]
- }
- // 预览用 AI 角色(扩展配置侧的 Role)
- export interface PreviewAIRole {
- id: string
- name: string
- avatar: string
- identity: string
- personality: string
- speakingStyle: 'formal' | 'casual' | 'playful'
- speed: 'slow' | 'normal' | 'fast'
- isCustom: boolean
- isRecommended?: boolean
- }
- // 消息状态
- export type MessageStatus = 'loading' | 'done' | 'error'
- // 对话消息
- export interface PreviewChatMessage {
- id: string
- role: 'ai' | 'student'
- content: string
- timestamp: Date
- status?: MessageStatus
- error?: string
- turnId?: string // set when message is created via begin/commit
- recovery?: 'retry' | 'rerecord' | 'restart' // set on error; drives the button matrix
- audioBlob?: Blob
- audioUrl?: string
- audioDuration?: number // NEW: 秒,由后端 transcript 事件 / sessions-latest 写入
- evaluation?: {
- dimensions: {
- accuracy: 'excellent' | 'good' | 'improve'
- fluency: 'excellent' | 'good' | 'improve'
- completeness: 'excellent' | 'good' | 'improve'
- rhythm: 'excellent' | 'good' | 'improve'
- }
- suggestion: string
- betterExpression?: string
- suggestedWords?: string[]
- wordAnalysis?: {
- word: string
- status: 'correct' | 'improvable'
- userPronunciation?: string
- standardPronunciation?: string
- tip?: string
- }[]
- }
- }
- // ==================== 对话引擎类型定义 ====================
- // SSE 事件类型
- export type SSEEvent =
- | { type: 'transcript'; text: string; audioDuration?: number | null }
- | { type: 'token'; text: string }
- | { type: 'done'; isComplete: boolean }
- | { type: 'error'; message: string }
- // 对话会话配置
- export interface SessionConfig {
- topic: string
- grade: string
- roleId: string
- totalRounds: number
- /** 时长(分钟)。与 totalRounds 是并存的两个结束条件,后端据此计算 expiresAt */
- durationMinutes: number
- vocabulary?: string[]
- sentences?: string[]
- configId?: string | null
- userId?: string | null
- }
- // 对话会话信息 (createSession 返回)
- export interface SessionInfo {
- sessionId: string
- totalRounds: number
- currentRound: number
- expiresAt: string | null
- }
- // 开场白生成结果 (generateGreeting 返回)
- export interface GreetingInfo {
- aiMessage: string
- }
- export interface HistoricalDialogueMessage {
- id: string
- round: number
- role: 'ai' | 'student'
- content: string
- audioUrl?: string | null
- audioDuration?: number | null // NEW: 秒,来自后端 sessions/latest
- clientTurnId?: string | null
- }
- // 用于启动 chat view 的最小 session 信息(父组件 createSession 后传给 DialogueChatView)
- // expiresAt 由后端基于 createSession 时传入的 durationMinutes 计算下发 —— 后端权威,
- // 关页面/刷新/换设备重进都接续同一个截止时刻,确保倒计时不会因任何原因暂停。
- export interface SessionStartInfo {
- sessionId: string
- expiresAt: string | null
- currentRound?: number
- messages?: HistoricalDialogueMessage[]
- }
- export interface LatestSessionInfo extends SessionStartInfo {
- status: 'active' | 'completed' | 'abandoned'
- totalRounds: number
- currentRound: number
- createdAt: string | null
- completedAt: string | null
- messages: HistoricalDialogueMessage[]
- }
- export interface LatestSessionResponse {
- session: LatestSessionInfo | null
- }
- // 对话报告
- export type DialogueReportStatus = 'evaluating' | 'ready' | 'failed' | 'incomplete'
- export interface DialogueReport {
- status: DialogueReportStatus
- evaluation: OverallEvaluation
- }
- export interface TaskHint {
- practice_level: string
- conversation_topic: string
- current_question: string
- example_sentences: {
- english: string
- chinese: string
- }[]
- key_vocabulary: {
- word: string
- meaning: string
- }[]
- }
- // 对话 API 接口
- export interface DialogueAPI {
- createSession(config: SessionConfig): Promise<SessionInfo>
- getLatestSession(configId: string, userId: string): Promise<LatestSessionResponse>
- completeSession(sessionId: string): Promise<void>
- /** Throws DOMException('AbortError') on signal abort; throws DialogueApiError on non-OK HTTP. */
- generateGreeting(sessionId: string, turnId: string, signal?: AbortSignal): Promise<GreetingInfo>
- generateTaskHint(sessionId: string): Promise<TaskHint>
- speak(sessionId: string, audioBlob: Blob, signal: AbortSignal, turnId: string): AsyncGenerator<SSEEvent>
- getReport(sessionId: string): Promise<DialogueReport>
- }
- // 徽章成就
- export interface BadgeAchievement {
- id: string
- name: string
- nameEn: string
- icon: string
- description: string
- }
- // 预览对话状态
- export type PreviewDialogueState = 'checking-history' | 'ready' | 'chatting' | 'completed'
|