/// 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 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 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 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 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 options; final String category; // 如"师德师风"、"教学内容" RadioQuestion({ required this.key, required this.questionText, required this.options, this.category = '', }); factory RadioQuestion.fromJson(Map json) { return RadioQuestion( key: json['key'] as String? ?? '', questionText: json['questionText'] as String? ?? '', options: (json['options'] as List?) ?.map((e) => RadioOption.fromJson(e as Map)) .toList() ?? [], category: json['category'] as String? ?? '', ); } Map 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 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 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 radioQuestions; final List 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 json) { return Questionnaire( metadata: QuestionnaireMetadata.fromJson( json['metadata'] as Map? ?? {}, ), radioQuestions: (json['radioQuestions'] as List?) ?.map((e) => RadioQuestion.fromJson(e as Map)) .toList() ?? [], textQuestions: (json['textQuestions'] as List?) ?.map((e) => TextQuestion.fromJson(e as Map)) .toList() ?? [], tokenValue: json['tokenValue'] as String? ?? '', questionnaireCode: json['questionnaireCode'] as String? ?? '', evaluationContent: json['evaluationContent'] as String? ?? '', evaluatedPeopleNumber: json['evaluatedPeopleNumber'] as String? ?? '', ); } Map 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})'; } }