225 lines
6.6 KiB
Dart
225 lines
6.6 KiB
Dart
|
|
/// Question type enum for text questions
|
|||
|
|
enum QuestionType {
|
|||
|
|
inspiration, // 启发类(包含"启发"关键词)
|
|||
|
|
suggestion, // 建议类(包含"建议"、"意见"关键词)
|
|||
|
|
overall, // 总体评价(zgpj)
|
|||
|
|
general, // 通用类型
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Metadata for questionnaire
|
|||
|
|
class QuestionnaireMetadata {
|
|||
|
|
final String title;
|
|||
|
|
final String evaluatedPerson;
|
|||
|
|
final String evaluationContent;
|
|||
|
|
final String tokenValue;
|
|||
|
|
final String questionnaireCode;
|
|||
|
|
final String evaluatedPeopleNumber;
|
|||
|
|
|
|||
|
|
QuestionnaireMetadata({
|
|||
|
|
required this.title,
|
|||
|
|
required this.evaluatedPerson,
|
|||
|
|
required this.evaluationContent,
|
|||
|
|
required this.tokenValue,
|
|||
|
|
required this.questionnaireCode,
|
|||
|
|
required this.evaluatedPeopleNumber,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
factory QuestionnaireMetadata.fromJson(Map<String, dynamic> json) {
|
|||
|
|
return QuestionnaireMetadata(
|
|||
|
|
title: json['title'] as String? ?? '',
|
|||
|
|
evaluatedPerson: json['evaluatedPerson'] as String? ?? '',
|
|||
|
|
evaluationContent: json['evaluationContent'] as String? ?? '',
|
|||
|
|
tokenValue: json['tokenValue'] as String? ?? '',
|
|||
|
|
questionnaireCode: json['questionnaireCode'] as String? ?? '',
|
|||
|
|
evaluatedPeopleNumber: json['evaluatedPeopleNumber'] as String? ?? '',
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Map<String, dynamic> toJson() {
|
|||
|
|
return {
|
|||
|
|
'title': title,
|
|||
|
|
'evaluatedPerson': evaluatedPerson,
|
|||
|
|
'evaluationContent': evaluationContent,
|
|||
|
|
'tokenValue': tokenValue,
|
|||
|
|
'questionnaireCode': questionnaireCode,
|
|||
|
|
'evaluatedPeopleNumber': evaluatedPeopleNumber,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Radio option for single-choice questions
|
|||
|
|
class RadioOption {
|
|||
|
|
final String label; // 如"(A) 非常满意"
|
|||
|
|
final String value; // 如"5_1"(5分×100%)
|
|||
|
|
final double score; // 解析后的分数
|
|||
|
|
final double weight; // 解析后的权重
|
|||
|
|
|
|||
|
|
RadioOption({
|
|||
|
|
required this.label,
|
|||
|
|
required this.value,
|
|||
|
|
required this.score,
|
|||
|
|
required this.weight,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
factory RadioOption.fromJson(Map<String, dynamic> json) {
|
|||
|
|
return RadioOption(
|
|||
|
|
label: json['label'] as String? ?? '',
|
|||
|
|
value: json['value'] as String? ?? '',
|
|||
|
|
score: (json['score'] as num?)?.toDouble() ?? 0.0,
|
|||
|
|
weight: (json['weight'] as num?)?.toDouble() ?? 0.0,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Map<String, dynamic> toJson() {
|
|||
|
|
return {'label': label, 'value': value, 'score': score, 'weight': weight};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
String toString() {
|
|||
|
|
return 'RadioOption(label: $label, value: $value, score: $score, weight: $weight)';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Radio question (single-choice question)
|
|||
|
|
class RadioQuestion {
|
|||
|
|
final String key; // 动态key,如"0000000401"
|
|||
|
|
final String questionText; // 题目文本
|
|||
|
|
final List<RadioOption> options;
|
|||
|
|
final String category; // 如"师德师风"、"教学内容"
|
|||
|
|
|
|||
|
|
RadioQuestion({
|
|||
|
|
required this.key,
|
|||
|
|
required this.questionText,
|
|||
|
|
required this.options,
|
|||
|
|
this.category = '',
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
factory RadioQuestion.fromJson(Map<String, dynamic> json) {
|
|||
|
|
return RadioQuestion(
|
|||
|
|
key: json['key'] as String? ?? '',
|
|||
|
|
questionText: json['questionText'] as String? ?? '',
|
|||
|
|
options:
|
|||
|
|
(json['options'] as List<dynamic>?)
|
|||
|
|
?.map((e) => RadioOption.fromJson(e as Map<String, dynamic>))
|
|||
|
|
.toList() ??
|
|||
|
|
[],
|
|||
|
|
category: json['category'] as String? ?? '',
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Map<String, dynamic> toJson() {
|
|||
|
|
return {
|
|||
|
|
'key': key,
|
|||
|
|
'questionText': questionText,
|
|||
|
|
'options': options.map((e) => e.toJson()).toList(),
|
|||
|
|
'category': category,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
String toString() {
|
|||
|
|
return 'RadioQuestion(key: $key, questionText: $questionText, category: $category, options: ${options.length})';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Text question (open-ended question)
|
|||
|
|
class TextQuestion {
|
|||
|
|
final String key; // 动态key或"zgpj"
|
|||
|
|
final String questionText; // 题目文本
|
|||
|
|
final QuestionType type; // 通过关键词识别的类型
|
|||
|
|
final bool isRequired; // 是否必填
|
|||
|
|
|
|||
|
|
TextQuestion({
|
|||
|
|
required this.key,
|
|||
|
|
required this.questionText,
|
|||
|
|
required this.type,
|
|||
|
|
this.isRequired = false,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
factory TextQuestion.fromJson(Map<String, dynamic> json) {
|
|||
|
|
return TextQuestion(
|
|||
|
|
key: json['key'] as String? ?? '',
|
|||
|
|
questionText: json['questionText'] as String? ?? '',
|
|||
|
|
type: QuestionType.values.firstWhere(
|
|||
|
|
(e) => e.toString() == 'QuestionType.${json['type']}',
|
|||
|
|
orElse: () => QuestionType.general,
|
|||
|
|
),
|
|||
|
|
isRequired: json['isRequired'] as bool? ?? false,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Map<String, dynamic> toJson() {
|
|||
|
|
return {
|
|||
|
|
'key': key,
|
|||
|
|
'questionText': questionText,
|
|||
|
|
'type': type.toString().split('.').last,
|
|||
|
|
'isRequired': isRequired,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
String toString() {
|
|||
|
|
return 'TextQuestion(key: $key, questionText: $questionText, type: $type, isRequired: $isRequired)';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Complete questionnaire structure
|
|||
|
|
class Questionnaire {
|
|||
|
|
final QuestionnaireMetadata metadata;
|
|||
|
|
final List<RadioQuestion> radioQuestions;
|
|||
|
|
final List<TextQuestion> textQuestions;
|
|||
|
|
final String tokenValue;
|
|||
|
|
final String questionnaireCode;
|
|||
|
|
final String evaluationContent;
|
|||
|
|
final String evaluatedPeopleNumber;
|
|||
|
|
|
|||
|
|
Questionnaire({
|
|||
|
|
required this.metadata,
|
|||
|
|
required this.radioQuestions,
|
|||
|
|
required this.textQuestions,
|
|||
|
|
required this.tokenValue,
|
|||
|
|
required this.questionnaireCode,
|
|||
|
|
required this.evaluationContent,
|
|||
|
|
required this.evaluatedPeopleNumber,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
factory Questionnaire.fromJson(Map<String, dynamic> json) {
|
|||
|
|
return Questionnaire(
|
|||
|
|
metadata: QuestionnaireMetadata.fromJson(
|
|||
|
|
json['metadata'] as Map<String, dynamic>? ?? {},
|
|||
|
|
),
|
|||
|
|
radioQuestions:
|
|||
|
|
(json['radioQuestions'] as List<dynamic>?)
|
|||
|
|
?.map((e) => RadioQuestion.fromJson(e as Map<String, dynamic>))
|
|||
|
|
.toList() ??
|
|||
|
|
[],
|
|||
|
|
textQuestions:
|
|||
|
|
(json['textQuestions'] as List<dynamic>?)
|
|||
|
|
?.map((e) => TextQuestion.fromJson(e as Map<String, dynamic>))
|
|||
|
|
.toList() ??
|
|||
|
|
[],
|
|||
|
|
tokenValue: json['tokenValue'] as String? ?? '',
|
|||
|
|
questionnaireCode: json['questionnaireCode'] as String? ?? '',
|
|||
|
|
evaluationContent: json['evaluationContent'] as String? ?? '',
|
|||
|
|
evaluatedPeopleNumber: json['evaluatedPeopleNumber'] as String? ?? '',
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Map<String, dynamic> toJson() {
|
|||
|
|
return {
|
|||
|
|
'metadata': metadata.toJson(),
|
|||
|
|
'radioQuestions': radioQuestions.map((e) => e.toJson()).toList(),
|
|||
|
|
'textQuestions': textQuestions.map((e) => e.toJson()).toList(),
|
|||
|
|
'tokenValue': tokenValue,
|
|||
|
|
'questionnaireCode': questionnaireCode,
|
|||
|
|
'evaluationContent': evaluationContent,
|
|||
|
|
'evaluatedPeopleNumber': evaluatedPeopleNumber,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
String toString() {
|
|||
|
|
return 'Questionnaire(radioQuestions: ${radioQuestions.length}, textQuestions: ${textQuestions.length})';
|
|||
|
|
}
|
|||
|
|
}
|