init
This commit is contained in:
201
client/lib/features/speaking/models/pronunciation_item.dart
Normal file
201
client/lib/features/speaking/models/pronunciation_item.dart
Normal file
@@ -0,0 +1,201 @@
|
||||
/// 发音练习项目数据模型
|
||||
class PronunciationItem {
|
||||
final String id;
|
||||
final String text;
|
||||
final String phonetic;
|
||||
final String audioUrl;
|
||||
final PronunciationType type;
|
||||
final DifficultyLevel difficulty;
|
||||
final String category;
|
||||
final List<String> tips;
|
||||
final DateTime createdAt;
|
||||
|
||||
PronunciationItem({
|
||||
required this.id,
|
||||
required this.text,
|
||||
required this.phonetic,
|
||||
required this.audioUrl,
|
||||
required this.type,
|
||||
required this.difficulty,
|
||||
required this.category,
|
||||
required this.tips,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory PronunciationItem.fromJson(Map<String, dynamic> json) {
|
||||
return PronunciationItem(
|
||||
id: json['id'],
|
||||
text: json['text'],
|
||||
phonetic: json['phonetic'],
|
||||
audioUrl: json['audioUrl'],
|
||||
type: PronunciationType.values.firstWhere(
|
||||
(e) => e.toString().split('.').last == json['type'],
|
||||
),
|
||||
difficulty: DifficultyLevel.values.firstWhere(
|
||||
(e) => e.toString().split('.').last == json['difficulty'],
|
||||
),
|
||||
category: json['category'],
|
||||
tips: List<String>.from(json['tips']),
|
||||
createdAt: DateTime.parse(json['createdAt']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'text': text,
|
||||
'phonetic': phonetic,
|
||||
'audioUrl': audioUrl,
|
||||
'type': type.toString().split('.').last,
|
||||
'difficulty': difficulty.toString().split('.').last,
|
||||
'category': category,
|
||||
'tips': tips,
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
PronunciationItem copyWith({
|
||||
String? id,
|
||||
String? text,
|
||||
String? phonetic,
|
||||
String? audioUrl,
|
||||
PronunciationType? type,
|
||||
DifficultyLevel? difficulty,
|
||||
String? category,
|
||||
List<String>? tips,
|
||||
DateTime? createdAt,
|
||||
}) {
|
||||
return PronunciationItem(
|
||||
id: id ?? this.id,
|
||||
text: text ?? this.text,
|
||||
phonetic: phonetic ?? this.phonetic,
|
||||
audioUrl: audioUrl ?? this.audioUrl,
|
||||
type: type ?? this.type,
|
||||
difficulty: difficulty ?? this.difficulty,
|
||||
category: category ?? this.category,
|
||||
tips: tips ?? this.tips,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 发音练习类型
|
||||
enum PronunciationType {
|
||||
word,
|
||||
sentence,
|
||||
phrase,
|
||||
phoneme,
|
||||
}
|
||||
|
||||
extension PronunciationTypeExtension on PronunciationType {
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case PronunciationType.word:
|
||||
return '单词发音';
|
||||
case PronunciationType.sentence:
|
||||
return '句子朗读';
|
||||
case PronunciationType.phrase:
|
||||
return '短语练习';
|
||||
case PronunciationType.phoneme:
|
||||
return '音素练习';
|
||||
}
|
||||
}
|
||||
|
||||
String get description {
|
||||
switch (this) {
|
||||
case PronunciationType.word:
|
||||
return '练习单个单词的准确发音';
|
||||
case PronunciationType.sentence:
|
||||
return '练习完整句子的语调和节奏';
|
||||
case PronunciationType.phrase:
|
||||
return '练习常用短语的连读';
|
||||
case PronunciationType.phoneme:
|
||||
return '练习基础音素的发音';
|
||||
}
|
||||
}
|
||||
|
||||
String get icon {
|
||||
switch (this) {
|
||||
case PronunciationType.word:
|
||||
return '🔤';
|
||||
case PronunciationType.sentence:
|
||||
return '📝';
|
||||
case PronunciationType.phrase:
|
||||
return '💬';
|
||||
case PronunciationType.phoneme:
|
||||
return '🔊';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 难度级别
|
||||
enum DifficultyLevel {
|
||||
beginner,
|
||||
intermediate,
|
||||
advanced,
|
||||
}
|
||||
|
||||
extension DifficultyLevelExtension on DifficultyLevel {
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case DifficultyLevel.beginner:
|
||||
return '初级';
|
||||
case DifficultyLevel.intermediate:
|
||||
return '中级';
|
||||
case DifficultyLevel.advanced:
|
||||
return '高级';
|
||||
}
|
||||
}
|
||||
|
||||
String get code {
|
||||
switch (this) {
|
||||
case DifficultyLevel.beginner:
|
||||
return 'A1-A2';
|
||||
case DifficultyLevel.intermediate:
|
||||
return 'B1-B2';
|
||||
case DifficultyLevel.advanced:
|
||||
return 'C1-C2';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 发音练习记录
|
||||
class PronunciationRecord {
|
||||
final String id;
|
||||
final String itemId;
|
||||
final double score;
|
||||
final String feedback;
|
||||
final DateTime practiceDate;
|
||||
final int attempts;
|
||||
|
||||
PronunciationRecord({
|
||||
required this.id,
|
||||
required this.itemId,
|
||||
required this.score,
|
||||
required this.feedback,
|
||||
required this.practiceDate,
|
||||
required this.attempts,
|
||||
});
|
||||
|
||||
factory PronunciationRecord.fromJson(Map<String, dynamic> json) {
|
||||
return PronunciationRecord(
|
||||
id: json['id'],
|
||||
itemId: json['itemId'],
|
||||
score: json['score'].toDouble(),
|
||||
feedback: json['feedback'],
|
||||
practiceDate: DateTime.parse(json['practiceDate']),
|
||||
attempts: json['attempts'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'itemId': itemId,
|
||||
'score': score,
|
||||
'feedback': feedback,
|
||||
'practiceDate': practiceDate.toIso8601String(),
|
||||
'attempts': attempts,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user