From 2eb67dd4fdb548124043dfb1c9d37a681b349ea4 Mon Sep 17 00:00:00 2001 From: lcy <2503978335@qq.com> Date: Wed, 28 Jun 2023 17:24:51 +0800 Subject: [PATCH] feat:调整代码 --- ios/Runner.xcodeproj/project.pbxproj | 4 ++++ ios/Runner/AppDelegate.swift | 16 +++++++++------- ios/Runner/Runner-Bridging-Header.h | 1 + ios/Runner/VoiceXSMessageChannel.swift | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/common/request/dao/listen_dao.dart | 7 +++++++ lib/generated/json/base/json_convert_content.dart | 31 ++++++++++++++++++++++++++----- lib/generated/json/course_process_entity.g.dart | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/generated/json/user_entity.g.dart | 2 +- lib/models/course_process_entity.dart | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/practice/bloc/topic_picture_bloc.dart | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/pages/practice/bloc/topic_picture_event.dart | 15 +++++++++++++++ lib/pages/practice/bloc/topic_picture_state.dart | 4 ++++ lib/pages/practice/topic_picture_page.dart | 499 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 13 files changed, 937 insertions(+), 258 deletions(-) create mode 100644 ios/Runner/VoiceXSMessageChannel.swift create mode 100644 lib/generated/json/course_process_entity.g.dart create mode 100644 lib/models/course_process_entity.dart diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 2b01cd7..8e8e64f 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 525E171A2A4BD03900104CDF /* VoiceXSMessageChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525E17192A4BD03900104CDF /* VoiceXSMessageChannel.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -51,6 +52,7 @@ 3563EC8D55A646823FD26A83 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 48BCA0827DCB98991774F5AC /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 525E17192A4BD03900104CDF /* VoiceXSMessageChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceXSMessageChannel.swift; sourceTree = ""; }; 6DEBBC1D861BE053F3ECE0B9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -150,6 +152,7 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 525E17192A4BD03900104CDF /* VoiceXSMessageChannel.swift */, 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; @@ -393,6 +396,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 525E171A2A4BD03900104CDF /* VoiceXSMessageChannel.swift in Sources */, 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 70693e4..41fde88 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -3,11 +3,13 @@ import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + let controller : FlutterViewController = window?.rootViewController as! FlutterViewController + _ = VoiceXSMessageChannel(messager: controller.binaryMessenger) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } } diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h index 308a2a5..6da1ed4 100644 --- a/ios/Runner/Runner-Bridging-Header.h +++ b/ios/Runner/Runner-Bridging-Header.h @@ -1 +1,2 @@ #import "GeneratedPluginRegistrant.h" +#import diff --git a/ios/Runner/VoiceXSMessageChannel.swift b/ios/Runner/VoiceXSMessageChannel.swift new file mode 100644 index 0000000..fc02604 --- /dev/null +++ b/ios/Runner/VoiceXSMessageChannel.swift @@ -0,0 +1,118 @@ +// +// VoiceXSMessageChannel.swift +// Runner +// +// Created by MacBook Pro on 2023/6/28. +// + +import UIKit + +class VoiceXSMessageChannel: NSObject,SSOralEvaluatingManagerDelegate { + var resultData:Dictionary? + var channel:FlutterBasicMessageChannel? + init(messager:FlutterBinaryMessenger) { + super.init() + resultData = Dictionary() + self.setEvaluateConfig() + channel = FlutterBasicMessageChannel(name: "com.owEnglish.voiceXs.BasicMessageChannel", binaryMessenger: messager) + channel!.setMessageHandler { message, reply in + if let dict = message as? Dictionary { + self.evaluateVioce(dict: dict); + } + } + } + + //配置评测信息 + func setEvaluateConfig() { + let config = SSOralEvaluatingManagerConfig.init() + config.appKey = "a418" + config.secretKey = "1a16f31f2611bf32fb7b3fc38f5b2c81" + config.vad = true + config.frontTime = 3 + config.backTime = 3 + config.isOutputLog = false + SSOralEvaluatingManager.register(config) + SSOralEvaluatingManager.share().register(.line, userId: "321") + SSOralEvaluatingManager.share().delegate = self + } + + //开始评测 + func evaluateVioce(dict:Dictionary) { + let text = dict["word"] as! String + let type = dict["type"] as! Int + let userId = dict["userId"] as! String + let config = SSOralEvaluatingConfig() + config.oralContent = text + if (type == 0) { + config.oralType = .word + } else { + config.oralType = .sentence + } + config.userId = userId + SSOralEvaluatingManager.share().startEvaluateOral(with: config) + } + + //评测结果回调 + func evaluateResult() { + channel!.sendMessage(resultData) {(reply) in + self.resultData?.removeAll() + } + } + + //SSOralEvaluatingManagerDelegate + /** + 评测开始 + */ + func oralEvaluatingDidStart() { + print("评测开始") + } + + /** + 评测停止 + */ + func oralEvaluatingDidStop() { + print("评测结束") + } + + /** + 评测完成后的结果 + */ + func oralEvaluatingDidEnd(withResult result: [AnyHashable : Any]?, requestId request_id: String?) { + print("评测完成结果") + let resultDict:Dictionary = result?["result"] as! Dictionary + resultData!["result"] = "1" + //分数 + resultData!["overall"] = resultDict["overall"] + self.evaluateResult() + } + + /** + 评测失败回调 + */ + func oralEvaluatingDidEndError(_ error: Error?, requestId request_id: String?) { + print("评测失败") + resultData!["result"] = "0" + self.evaluateResult() + } + + /** + VAD(前置时间)超时回调 + */ + func oralEvaluatingDidVADFrontTimeOut() { + print("前置超时--->取消") + SSOralEvaluatingManager.share().cancelEvaluate() + if(resultData?.keys.count == 0) { + resultData!["result"] = "0" + self.evaluateResult(); + } + } + + /** + VAD(后置时间)超时回调 + */ + func oralEvaluatingDidVADBackTimeOut() { + print("后置超时--->结束") + ///结束回调 + SSOralEvaluatingManager.share().stopEvaluate(); + } +} diff --git a/lib/common/request/dao/listen_dao.dart b/lib/common/request/dao/listen_dao.dart index 5d6e8dd..df3d510 100644 --- a/lib/common/request/dao/listen_dao.dart +++ b/lib/common/request/dao/listen_dao.dart @@ -1,4 +1,5 @@ import 'package:wow_english/common/request/request_client.dart'; +import 'package:wow_english/models/course_process_entity.dart'; import 'package:wow_english/models/follow_read_entity.dart'; import 'package:wow_english/models/listen_entity.dart'; @@ -14,4 +15,10 @@ class ListenDao { var data = await requestClient.get>(Apis.followRead); return data; } + + ///课程内容 + static Future process(courseLessonId) async { + var data = await requestClient.get(Apis.process,queryParameters: {'courseLessonId':courseLessonId}); + return data; + } } diff --git a/lib/generated/json/base/json_convert_content.dart b/lib/generated/json/base/json_convert_content.dart index 46247dc..6860aa9 100644 --- a/lib/generated/json/base/json_convert_content.dart +++ b/lib/generated/json/base/json_convert_content.dart @@ -4,9 +4,10 @@ // This file is automatically generated. DO NOT EDIT, all your changes would be lost. import 'package:flutter/material.dart' show debugPrint; -import 'package:wow_english/models/follow_read_entity.dart'; import 'package:wow_english/models/course_entity.dart'; import 'package:wow_english/models/course_module_entity.dart'; +import 'package:wow_english/models/course_process_entity.dart'; +import 'package:wow_english/models/follow_read_entity.dart'; import 'package:wow_english/models/listen_entity.dart'; import 'package:wow_english/models/user_entity.dart'; @@ -16,10 +17,15 @@ typedef EnumConvertFunction = T Function(String value); class JsonConvert { static final Map convertFuncMap = { - (FollowReadEntity).toString(): FollowReadEntity.fromJson, (CourseEntity).toString(): CourseEntity.fromJson, (CourseCourseLessons).toString(): CourseCourseLessons.fromJson, (CourseModuleEntity).toString(): CourseModuleEntity.fromJson, + (CourseProcessEntity).toString(): CourseProcessEntity.fromJson, + (CourseProcessReadings).toString(): CourseProcessReadings.fromJson, + (CourseProcessTopics).toString(): CourseProcessTopics.fromJson, + (CourseProcessTopicsTopicAnswerList).toString(): CourseProcessTopicsTopicAnswerList.fromJson, + (CourseProcessVideos).toString(): CourseProcessVideos.fromJson, + (FollowReadEntity).toString(): FollowReadEntity.fromJson, (ListenEntity).toString(): ListenEntity.fromJson, (UserEntity).toString(): UserEntity.fromJson, }; @@ -100,9 +106,6 @@ List? convertListNotNull(dynamic value, {EnumConvertFunction? enumConvert} //list is returned by type static M? _getListChildType(List> data) { - if([] is M){ - return data.map((Map e) => FollowReadEntity.fromJson(e)).toList() as M; - } if([] is M){ return data.map((Map e) => CourseEntity.fromJson(e)).toList() as M; } @@ -112,6 +115,24 @@ List? convertListNotNull(dynamic value, {EnumConvertFunction? enumConvert} if([] is M){ return data.map((Map e) => CourseModuleEntity.fromJson(e)).toList() as M; } + if([] is M){ + return data.map((Map e) => CourseProcessEntity.fromJson(e)).toList() as M; + } + if([] is M){ + return data.map((Map e) => CourseProcessReadings.fromJson(e)).toList() as M; + } + if([] is M){ + return data.map((Map e) => CourseProcessTopics.fromJson(e)).toList() as M; + } + if([] is M){ + return data.map((Map e) => CourseProcessTopicsTopicAnswerList.fromJson(e)).toList() as M; + } + if([] is M){ + return data.map((Map e) => CourseProcessVideos.fromJson(e)).toList() as M; + } + if([] is M){ + return data.map((Map e) => FollowReadEntity.fromJson(e)).toList() as M; + } if([] is M){ return data.map((Map e) => ListenEntity.fromJson(e)).toList() as M; } diff --git a/lib/generated/json/course_process_entity.g.dart b/lib/generated/json/course_process_entity.g.dart new file mode 100644 index 0000000..354a939 --- /dev/null +++ b/lib/generated/json/course_process_entity.g.dart @@ -0,0 +1,277 @@ +import 'package:wow_english/generated/json/base/json_convert_content.dart'; +import 'package:wow_english/models/course_process_entity.dart'; + +CourseProcessEntity $CourseProcessEntityFromJson(Map json) { + final CourseProcessEntity courseProcessEntity = CourseProcessEntity(); + final int? currentStep = jsonConvert.convert(json['currentStep']); + if (currentStep != null) { + courseProcessEntity.currentStep = currentStep; + } + final int? currentTime = jsonConvert.convert(json['currentTime']); + if (currentTime != null) { + courseProcessEntity.currentTime = currentTime; + } + final List? readings = jsonConvert.convertListNotNull(json['readings']); + if (readings != null) { + courseProcessEntity.readings = readings; + } + final List? topics = jsonConvert.convertListNotNull(json['topics']); + if (topics != null) { + courseProcessEntity.topics = topics; + } + final CourseProcessVideos? videos = jsonConvert.convert(json['videos']); + if (videos != null) { + courseProcessEntity.videos = videos; + } + return courseProcessEntity; +} + +Map $CourseProcessEntityToJson(CourseProcessEntity entity) { + final Map data = {}; + data['currentStep'] = entity.currentStep; + data['currentTime'] = entity.currentTime; + data['readings'] = entity.readings?.map((v) => v.toJson()).toList(); + data['topics'] = entity.topics?.map((v) => v.toJson()).toList(); + data['videos'] = entity.videos?.toJson(); + return data; +} + +CourseProcessReadings $CourseProcessReadingsFromJson(Map json) { + final CourseProcessReadings courseProcessReadings = CourseProcessReadings(); + final String? auditUrl = jsonConvert.convert(json['auditUrl']); + if (auditUrl != null) { + courseProcessReadings.auditUrl = auditUrl; + } + final int? courseLessonId = jsonConvert.convert(json['courseLessonId']); + if (courseLessonId != null) { + courseProcessReadings.courseLessonId = courseLessonId; + } + final String? createTime = jsonConvert.convert(json['createTime']); + if (createTime != null) { + courseProcessReadings.createTime = createTime; + } + final String? deleted = jsonConvert.convert(json['deleted']); + if (deleted != null) { + courseProcessReadings.deleted = deleted; + } + final String? id = jsonConvert.convert(json['id']); + if (id != null) { + courseProcessReadings.id = id; + } + final String? modifyTime = jsonConvert.convert(json['modifyTime']); + if (modifyTime != null) { + courseProcessReadings.modifyTime = modifyTime; + } + final String? padPicUrl = jsonConvert.convert(json['padPicUrl']); + if (padPicUrl != null) { + courseProcessReadings.padPicUrl = padPicUrl; + } + final String? picUrl = jsonConvert.convert(json['picUrl']); + if (picUrl != null) { + courseProcessReadings.picUrl = picUrl; + } + final int? sortOrder = jsonConvert.convert(json['sortOrder']); + if (sortOrder != null) { + courseProcessReadings.sortOrder = sortOrder; + } + final String? word = jsonConvert.convert(json['word']); + if (word != null) { + courseProcessReadings.word = word; + } + return courseProcessReadings; +} + +Map $CourseProcessReadingsToJson(CourseProcessReadings entity) { + final Map data = {}; + data['auditUrl'] = entity.auditUrl; + data['courseLessonId'] = entity.courseLessonId; + data['createTime'] = entity.createTime; + data['deleted'] = entity.deleted; + data['id'] = entity.id; + data['modifyTime'] = entity.modifyTime; + data['padPicUrl'] = entity.padPicUrl; + data['picUrl'] = entity.picUrl; + data['sortOrder'] = entity.sortOrder; + data['word'] = entity.word; + return data; +} + +CourseProcessTopics $CourseProcessTopicsFromJson(Map json) { + final CourseProcessTopics courseProcessTopics = CourseProcessTopics(); + final String? audioUrl = jsonConvert.convert(json['audioUrl']); + if (audioUrl != null) { + courseProcessTopics.audioUrl = audioUrl; + } + final int? courseLessonId = jsonConvert.convert(json['courseLessonId']); + if (courseLessonId != null) { + courseProcessTopics.courseLessonId = courseLessonId; + } + final String? createTime = jsonConvert.convert(json['createTime']); + if (createTime != null) { + courseProcessTopics.createTime = createTime; + } + final String? deleted = jsonConvert.convert(json['deleted']); + if (deleted != null) { + courseProcessTopics.deleted = deleted; + } + final String? id = jsonConvert.convert(json['id']); + if (id != null) { + courseProcessTopics.id = id; + } + final String? keyWord = jsonConvert.convert(json['keyWord']); + if (keyWord != null) { + courseProcessTopics.keyWord = keyWord; + } + final String? modifyTime = jsonConvert.convert(json['modifyTime']); + if (modifyTime != null) { + courseProcessTopics.modifyTime = modifyTime; + } + final String? picUrl = jsonConvert.convert(json['picUrl']); + if (picUrl != null) { + courseProcessTopics.picUrl = picUrl; + } + final int? sortOrder = jsonConvert.convert(json['sortOrder']); + if (sortOrder != null) { + courseProcessTopics.sortOrder = sortOrder; + } + final int? status = jsonConvert.convert(json['status']); + if (status != null) { + courseProcessTopics.status = status; + } + final List? topicAnswerList = jsonConvert.convertListNotNull(json['topicAnswerList']); + if (topicAnswerList != null) { + courseProcessTopics.topicAnswerList = topicAnswerList; + } + final int? type = jsonConvert.convert(json['type']); + if (type != null) { + courseProcessTopics.type = type; + } + final String? word = jsonConvert.convert(json['word']); + if (word != null) { + courseProcessTopics.word = word; + } + return courseProcessTopics; +} + +Map $CourseProcessTopicsToJson(CourseProcessTopics entity) { + final Map data = {}; + data['audioUrl'] = entity.audioUrl; + data['courseLessonId'] = entity.courseLessonId; + data['createTime'] = entity.createTime; + data['deleted'] = entity.deleted; + data['id'] = entity.id; + data['keyWord'] = entity.keyWord; + data['modifyTime'] = entity.modifyTime; + data['picUrl'] = entity.picUrl; + data['sortOrder'] = entity.sortOrder; + data['status'] = entity.status; + data['topicAnswerList'] = entity.topicAnswerList?.map((v) => v.toJson()).toList(); + data['type'] = entity.type; + data['word'] = entity.word; + return data; +} + +CourseProcessTopicsTopicAnswerList $CourseProcessTopicsTopicAnswerListFromJson(Map json) { + final CourseProcessTopicsTopicAnswerList courseProcessTopicsTopicAnswerList = CourseProcessTopicsTopicAnswerList(); + final int? correct = jsonConvert.convert(json['correct']); + if (correct != null) { + courseProcessTopicsTopicAnswerList.correct = correct; + } + final String? createTime = jsonConvert.convert(json['createTime']); + if (createTime != null) { + courseProcessTopicsTopicAnswerList.createTime = createTime; + } + final String? deleted = jsonConvert.convert(json['deleted']); + if (deleted != null) { + courseProcessTopicsTopicAnswerList.deleted = deleted; + } + final String? id = jsonConvert.convert(json['id']); + if (id != null) { + courseProcessTopicsTopicAnswerList.id = id; + } + final String? modifyTime = jsonConvert.convert(json['modifyTime']); + if (modifyTime != null) { + courseProcessTopicsTopicAnswerList.modifyTime = modifyTime; + } + final String? picUrl = jsonConvert.convert(json['picUrl']); + if (picUrl != null) { + courseProcessTopicsTopicAnswerList.picUrl = picUrl; + } + final int? sortOrder = jsonConvert.convert(json['sortOrder']); + if (sortOrder != null) { + courseProcessTopicsTopicAnswerList.sortOrder = sortOrder; + } + final int? topicId = jsonConvert.convert(json['topicId']); + if (topicId != null) { + courseProcessTopicsTopicAnswerList.topicId = topicId; + } + final String? word = jsonConvert.convert(json['word']); + if (word != null) { + courseProcessTopicsTopicAnswerList.word = word; + } + return courseProcessTopicsTopicAnswerList; +} + +Map $CourseProcessTopicsTopicAnswerListToJson(CourseProcessTopicsTopicAnswerList entity) { + final Map data = {}; + data['correct'] = entity.correct; + data['createTime'] = entity.createTime; + data['deleted'] = entity.deleted; + data['id'] = entity.id; + data['modifyTime'] = entity.modifyTime; + data['picUrl'] = entity.picUrl; + data['sortOrder'] = entity.sortOrder; + data['topicId'] = entity.topicId; + data['word'] = entity.word; + return data; +} + +CourseProcessVideos $CourseProcessVideosFromJson(Map json) { + final CourseProcessVideos courseProcessVideos = CourseProcessVideos(); + final int? courseLessonId = jsonConvert.convert(json['courseLessonId']); + if (courseLessonId != null) { + courseProcessVideos.courseLessonId = courseLessonId; + } + final String? createTime = jsonConvert.convert(json['createTime']); + if (createTime != null) { + courseProcessVideos.createTime = createTime; + } + final String? deleted = jsonConvert.convert(json['deleted']); + if (deleted != null) { + courseProcessVideos.deleted = deleted; + } + final String? id = jsonConvert.convert(json['id']); + if (id != null) { + courseProcessVideos.id = id; + } + final String? modifyTime = jsonConvert.convert(json['modifyTime']); + if (modifyTime != null) { + courseProcessVideos.modifyTime = modifyTime; + } + final int? sortOrder = jsonConvert.convert(json['sortOrder']); + if (sortOrder != null) { + courseProcessVideos.sortOrder = sortOrder; + } + final String? subtitleUrl = jsonConvert.convert(json['subtitleUrl']); + if (subtitleUrl != null) { + courseProcessVideos.subtitleUrl = subtitleUrl; + } + final String? videoUrl = jsonConvert.convert(json['videoUrl']); + if (videoUrl != null) { + courseProcessVideos.videoUrl = videoUrl; + } + return courseProcessVideos; +} + +Map $CourseProcessVideosToJson(CourseProcessVideos entity) { + final Map data = {}; + data['courseLessonId'] = entity.courseLessonId; + data['createTime'] = entity.createTime; + data['deleted'] = entity.deleted; + data['id'] = entity.id; + data['modifyTime'] = entity.modifyTime; + data['sortOrder'] = entity.sortOrder; + data['subtitleUrl'] = entity.subtitleUrl; + data['videoUrl'] = entity.videoUrl; + return data; +} \ No newline at end of file diff --git a/lib/generated/json/user_entity.g.dart b/lib/generated/json/user_entity.g.dart index 456b6d9..58db2a3 100644 --- a/lib/generated/json/user_entity.g.dart +++ b/lib/generated/json/user_entity.g.dart @@ -59,4 +59,4 @@ Map $UserEntityToJson(UserEntity entity) { data['nowCourseModuleId'] = entity.nowCourseModuleId; data['effectiveDate'] = entity.effectiveDate; return data; -} +} \ No newline at end of file diff --git a/lib/models/course_process_entity.dart b/lib/models/course_process_entity.dart new file mode 100644 index 0000000..d88e603 --- /dev/null +++ b/lib/models/course_process_entity.dart @@ -0,0 +1,123 @@ +import 'package:wow_english/generated/json/base/json_field.dart'; +import 'package:wow_english/generated/json/course_process_entity.g.dart'; +import 'dart:convert'; + +@JsonSerializable() +class CourseProcessEntity { + int? currentStep; + int? currentTime; + List? readings; + List? topics; + CourseProcessVideos? videos; + + CourseProcessEntity(); + + factory CourseProcessEntity.fromJson(Map json) => $CourseProcessEntityFromJson(json); + + Map toJson() => $CourseProcessEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} + +@JsonSerializable() +class CourseProcessReadings { + String? auditUrl; + int? courseLessonId; + String? createTime; + String? deleted; + String? id; + String? modifyTime; + String? padPicUrl; + String? picUrl; + int? sortOrder; + String? word; + + CourseProcessReadings(); + + factory CourseProcessReadings.fromJson(Map json) => $CourseProcessReadingsFromJson(json); + + Map toJson() => $CourseProcessReadingsToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} + +@JsonSerializable() +class CourseProcessTopics { + String? audioUrl; + int? courseLessonId; + String? createTime; + String? deleted; + String? id; + String? keyWord; + String? modifyTime; + String? picUrl; + int? sortOrder; + int? status; + List? topicAnswerList; + int? type; + String? word; + + CourseProcessTopics(); + + factory CourseProcessTopics.fromJson(Map json) => $CourseProcessTopicsFromJson(json); + + Map toJson() => $CourseProcessTopicsToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} + +@JsonSerializable() +class CourseProcessTopicsTopicAnswerList { + int? correct; + String? createTime; + String? deleted; + String? id; + String? modifyTime; + String? picUrl; + int? sortOrder; + int? topicId; + String? word; + + CourseProcessTopicsTopicAnswerList(); + + factory CourseProcessTopicsTopicAnswerList.fromJson(Map json) => $CourseProcessTopicsTopicAnswerListFromJson(json); + + Map toJson() => $CourseProcessTopicsTopicAnswerListToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} + +@JsonSerializable() +class CourseProcessVideos { + int? courseLessonId; + String? createTime; + String? deleted; + String? id; + String? modifyTime; + int? sortOrder; + String? subtitleUrl; + String? videoUrl; + + CourseProcessVideos(); + + factory CourseProcessVideos.fromJson(Map json) => $CourseProcessVideosFromJson(json); + + Map toJson() => $CourseProcessVideosToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} \ No newline at end of file diff --git a/lib/pages/practice/bloc/topic_picture_bloc.dart b/lib/pages/practice/bloc/topic_picture_bloc.dart index 1248801..913d03c 100644 --- a/lib/pages/practice/bloc/topic_picture_bloc.dart +++ b/lib/pages/practice/bloc/topic_picture_bloc.dart @@ -1,5 +1,13 @@ +import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:wow_english/common/request/dao/listen_dao.dart'; +import 'package:wow_english/common/request/exception.dart'; +import 'package:wow_english/models/course_process_entity.dart'; +import 'package:wow_english/utils/loading.dart'; part 'topic_picture_event.dart'; part 'topic_picture_state.dart'; @@ -12,25 +20,70 @@ class TopicPictureBloc extends Bloc { int _currentPage = 0; - int _selectItem = 0; + int _selectItem = -1; + + CourseProcessEntity? _entity; + + ///正在评测 + bool _isVoicing = false; + + CourseProcessEntity? get entity => _entity; int get currentPage => _currentPage + 1; int get selectItem => _selectItem; + bool get isVoicing => _isVoicing; + + var messageChannel = const BasicMessageChannel('com.owEnglish.voiceXs.BasicMessageChannel', StandardMessageCodec()); + + final audioPlayer = AudioPlayer(); + TopicPictureBloc(this.pageController, this.modelCount) : super(TopicPictureInitial()) { on(_pageControllerChange); + on(_initMessageChannelCall); + on(_requestData); on(_selectItemLoad); + on(_voiceXsTest); + on(_voiceResult); + on((event, emit) { + + }); } @override Future close() { pageController.dispose(); + audioPlayer.dispose(); return super.close(); } + void _requestData(RequestDataEvent event,Emitter emitter) async { + try { + await loading(() async { + _entity = await ListenDao.process('8'); + emitter(RequestDataState()); + }); + } catch (e) { + if (e is ApiException) { + EasyLoading.showToast(e.message??'请求失败,请检查网络连接'); + } + } + } + void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter emitter) async { _currentPage = event.pageIndex; + final topics = _entity?.topics?[_currentPage]; + if (topics?.type == 1 || topics?.type == 2) { + if (topics?.audioUrl != null) { + final urlStr = topics?.audioUrl??''; + if (urlStr.isNotEmpty) { + audioPlayer.play(UrlSource(urlStr)); + } + } + } else { + audioPlayer.stop(); + } emitter(CurrentPageIndexState()); } @@ -38,4 +91,47 @@ class TopicPictureBloc extends Bloc { _selectItem = event.selectIndex; emitter(SelectItemChangeState()); } + + ///messageChannel回调 + Future messageResultHandler(message,Emitter emitter) async { + EasyLoading.dismiss(); + final Map args = message as Map; + final result = args['result'] as String; + if (result == '1') { + final overall = args['overall'].toString(); + EasyLoading.showToast('测评成功,分数是$overall',duration: const Duration(seconds: 10)); + } else { + EasyLoading.showToast('测评失败',duration: const Duration(seconds: 10)); + } + if (kDebugMode) { + print('是否被移除>>>>>$emitter'); + } + _isVoicing = false; + } + + Future _initMessageChannelCall(InitMessageChannelEvent event,Emitter emitter) async { + messageChannel.setMessageHandler((message) => + messageResultHandler(message, emitter) + ); + + audioPlayer.onPlayerStateChanged.listen((event) { + if (event == PlayerState.stopped) { + if (kDebugMode) { + print('播放结束'); + } + } + }); + } + + void _voiceXsTest(VoiceXsTestEvent event,Emitter emitter) async { + EasyLoading.show(status: '录音中....'); + messageChannel.send({'word':event.testWord,'type':event.type,'userId':event.userId.toString()}); + _isVoicing = true; + emitter(VoiceXsTestState()); + } + + void _voiceResult(VoiceResultEvent event,Emitter emitter) async { + _isVoicing = false; + emitter(VoiceXsTestState()); + } } diff --git a/lib/pages/practice/bloc/topic_picture_event.dart b/lib/pages/practice/bloc/topic_picture_event.dart index 781f545..09cf5d7 100644 --- a/lib/pages/practice/bloc/topic_picture_event.dart +++ b/lib/pages/practice/bloc/topic_picture_event.dart @@ -3,6 +3,21 @@ part of 'topic_picture_bloc.dart'; @immutable abstract class TopicPictureEvent {} +class RequestDataEvent extends TopicPictureEvent {} + +///初始化消息回调 +class InitMessageChannelEvent extends TopicPictureEvent {} + +class VoiceResultEvent extends TopicPictureEvent {} + +///先声测试 +class VoiceXsTestEvent extends TopicPictureEvent { + final String testWord; + final int type; + final int userId; + VoiceXsTestEvent(this.testWord,this.type,this.userId); +} + class CurrentPageIndexChangeEvent extends TopicPictureEvent { final int pageIndex; CurrentPageIndexChangeEvent(this.pageIndex); diff --git a/lib/pages/practice/bloc/topic_picture_state.dart b/lib/pages/practice/bloc/topic_picture_state.dart index af0e103..876e24e 100644 --- a/lib/pages/practice/bloc/topic_picture_state.dart +++ b/lib/pages/practice/bloc/topic_picture_state.dart @@ -3,6 +3,10 @@ part of 'topic_picture_bloc.dart'; @immutable abstract class TopicPictureState {} +class RequestDataState extends TopicPictureState {} + +class VoiceXsTestState extends TopicPictureState {} + class TopicPictureInitial extends TopicPictureState {} class CurrentPageIndexState extends TopicPictureState {} diff --git a/lib/pages/practice/topic_picture_page.dart b/lib/pages/practice/topic_picture_page.dart index 690e593..28d6713 100644 --- a/lib/pages/practice/topic_picture_page.dart +++ b/lib/pages/practice/topic_picture_page.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/blocs/cachebloc/cache_bloc.dart'; import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/common/widgets/ow_image_widget.dart'; +import 'package:wow_english/models/course_process_entity.dart'; import 'bloc/topic_picture_bloc.dart'; import 'widgets/practice_header_widget.dart'; @@ -13,7 +15,12 @@ class TopicPicturePage extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => TopicPictureBloc(PageController(),3), + create: (context) => TopicPictureBloc( + PageController(), + 3 + ) + ..add(RequestDataEvent()) + ..add(InitMessageChannelEvent()), child: _TopicPicturePage(), ); } @@ -23,13 +30,16 @@ class _TopicPicturePage extends StatelessWidget { @override Widget build(BuildContext context) { return BlocListener( - listener: (context, state){}, + listener: (context, state){ + if (state is RequestDataState) { + context.read().add(CurrentPageIndexChangeEvent(0)); + } + }, child: _topicPictureView(), ); } Widget _topicPictureView() => BlocBuilder( - buildWhen: (_,s) => s is CurrentPageIndexState, builder: (context,state){ final bloc = BlocProvider.of(context); return Container( @@ -39,28 +49,29 @@ class _TopicPicturePage extends StatelessWidget { Column( children: [ PracticeHeaderWidget( - title: '${bloc.currentPage}/8', + title: '${bloc.currentPage}/${bloc.entity?.topics?.length}', onTap: (){Navigator.pop(context);}, ), Expanded( child: PageView.builder( - itemCount: 8, + itemCount: bloc.entity?.topics?.length, scrollDirection: Axis.horizontal, controller: bloc.pageController, onPageChanged: (int index) { bloc.add(CurrentPageIndexChangeEvent(index)); }, itemBuilder: (BuildContext context,int index){ - if (index % 5 == 0) { - return _pageViewWordItemWidget(); - } else if (index % 5 == 1) { - return _pageViewItemWidget(); - } else if (index % 5 == 2){ - return _pageViewVoicePictureItemWidget(); - } else if (index % 5 == 3){ - return _voiceAnswerItem(); - } else { - return _pageViewVoiceWordItemWidget(); + CourseProcessTopics? topics = bloc.entity?.topics![index]; + if (topics?.type == 1) {//听音选图 + return _pageViewVoicePictureItemWidget(topics); + } else if (topics?.type == 2) {//听音选字 + return _pageViewVoiceWordItemWidget(topics); + } else if (topics?.type == 3) {//看题选字 + return _pageViewWordItemWidget(topics); + } else if (topics?.type == 4) {//看题选图 + return _pageViewItemWidget(topics); + } else {//语音问答 + return _voiceAnswerItem(topics); } }), ) @@ -78,9 +89,8 @@ class _TopicPicturePage extends StatelessWidget { }); ///看题选图 - Widget _pageViewItemWidget() => BlocBuilder( + Widget _pageViewItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state){ - final bloc = BlocProvider.of(context); return SafeArea( child: Column( children: [ @@ -93,27 +103,16 @@ class _TopicPicturePage extends StatelessWidget { ) ), 26.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeImageWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeImageWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeImageWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeImageWidget(4), - ) - ], - ) + SizedBox( + height: 143.h, + width: 143.w * (topics?.topicAnswerList?.length??0), + child: ListView.builder( + itemCount: topics?.topicAnswerList?.length??0, + scrollDirection: Axis.horizontal, + itemBuilder: (context,index){ + return _decodeImageWidget(index); + }), + ), ], ), ); @@ -123,28 +122,31 @@ class _TopicPicturePage extends StatelessWidget { buildWhen: (_, s) => s is SelectItemChangeState, builder: (context,state){ final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () => bloc.add(SelectItemEvent(index)), - child: Container( - padding: const EdgeInsets.all(4.5), - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15), - ), - height: 143.h, - width: 143.w, + return Container( + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: GestureDetector( + onTap: () => bloc.add(SelectItemEvent(index)), child: Container( + padding: const EdgeInsets.all(4.5), decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) - ), - image: const DecorationImage( - fit: BoxFit.fitWidth, - image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') - ) + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15), + ), + height: 143.h, + width: 143.w, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), + image: const DecorationImage( + fit: BoxFit.fitWidth, + image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') + ) + ), ), ), ), @@ -152,7 +154,7 @@ class _TopicPicturePage extends StatelessWidget { }); ///看题选字 - Widget _pageViewWordItemWidget() => BlocBuilder( + Widget _pageViewWordItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state){ final bloc = BlocProvider.of(context); return SafeArea( @@ -167,27 +169,16 @@ class _TopicPicturePage extends StatelessWidget { ) ), 26.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeWordWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeWordWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeWordWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeWordWidget(4), - ) - ], - ) + SizedBox( + height: 143.h, + width: 143.w * (topics?.topicAnswerList?.length??0), + child: ListView.builder( + itemCount: topics?.topicAnswerList?.length??0, + scrollDirection: Axis.horizontal, + itemBuilder: (context,index){ + return _decodeWordWidget(index); + }), + ), ], ), ); @@ -197,57 +188,60 @@ class _TopicPicturePage extends StatelessWidget { buildWhen: (_, s) => s is SelectItemChangeState, builder: (context,state){ final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () => bloc.add(SelectItemEvent(index)), - child: Container( - width: 143.w, - height: 143.h, - padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) + return Container( + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: GestureDetector( + onTap: () => bloc.add(SelectItemEvent(index)), + child: Container( + width: 143.w, + height: 143.h, + padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Expanded( - child: Container( - alignment: Alignment.center, - child: Text( - 'yellow', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333) - ) + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: Container( + alignment: Alignment.center, + child: Text( + 'yellow', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333) + ) + ), ), ), - ), - Container( - height: 30.h, - width: double.infinity, - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15.r), - border: Border.all( - width: 1.5, - color: const Color(0xFF140C10) + Container( + height: 30.h, + width: double.infinity, + decoration: BoxDecoration( + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15.r), + border: Border.all( + width: 1.5, + color: const Color(0xFF140C10) + ), ), - ), - alignment: Alignment.center, - child: Image.asset('choose'.assetPng), - ) - ], + alignment: Alignment.center, + child: Image.asset('choose'.assetPng), + ) + ], + ), ), ), ); }); ///听音选图 - Widget _pageViewVoicePictureItemWidget() => BlocBuilder( + Widget _pageViewVoicePictureItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state){ final bloc = BlocProvider.of(context); return SafeArea( @@ -268,58 +262,51 @@ class _TopicPicturePage extends StatelessWidget { ], ), 26.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeVoiceImageWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeVoiceImageWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeVoiceImageWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeVoiceImageWidget(4), - ) - ], + SizedBox( + height: 143.h, + width: 163.w * (topics?.topicAnswerList?.length??0), + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: topics?.topicAnswerList?.length??0, + itemBuilder: (BuildContext context,int index){ + return _decodeVoiceImageWidget(1,topics?.topicAnswerList?[index]); + }) + , ) ], ), ); }); - Widget _decodeVoiceImageWidget(int index) => BlocBuilder( + Widget _decodeVoiceImageWidget(int index,CourseProcessTopicsTopicAnswerList? answerList) => BlocBuilder( buildWhen: (_, s) => s is SelectItemChangeState, builder: (context,state){ final bloc = BlocProvider.of(context); - return GestureDetector( - onTap: () => bloc.add(SelectItemEvent(index)), - child: Container( - padding: const EdgeInsets.all(4.5), - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15), - ), - height: 143.h, - width: 143.w, + return Container( + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: GestureDetector( + onTap: () => bloc.add(SelectItemEvent(index)), child: Container( + padding: const EdgeInsets.all(4.5), decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) - ), - image: const DecorationImage( - fit: BoxFit.fitWidth, - image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') - ) + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15), + ), + height: 143.h, + width: 143.w, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), + image: const DecorationImage( + fit: BoxFit.fitWidth, + image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714') + ) + ), ), ), ), @@ -327,7 +314,7 @@ class _TopicPicturePage extends StatelessWidget { }); ///听音选字 - Widget _pageViewVoiceWordItemWidget() => BlocBuilder( + Widget _pageViewVoiceWordItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state){ final bloc = BlocProvider.of(context); return SafeArea( @@ -335,114 +322,138 @@ class _TopicPicturePage extends StatelessWidget { children: [ Image.asset('voice'.assetPng,height: 33.h,width: 30.w,), 26.verticalSpace, - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Offstage( - offstage: (bloc.modelCount < 1), - child: _decodeVoiceWordImageWidget(1), - ), - Offstage( - offstage: (bloc.modelCount < 2), - child: _decodeVoiceWordImageWidget(2), - ), - Offstage( - offstage: (bloc.modelCount < 3), - child: _decodeVoiceWordImageWidget(3), - ), - Offstage( - offstage: (bloc.modelCount < 4), - child: _decodeVoiceWordImageWidget(4), - ) - ], - ) + SizedBox( + width: 163.w * (topics?.topicAnswerList?.length??0), + height: 143.h, + child: ListView.builder( + itemCount: topics?.topicAnswerList?.length, + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext context,int index){ + return _decodeVoiceWordImageWidget(index, topics!.topicAnswerList![index]); + }), + ), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Offstage( + // offstage: topics.topicAnswerList!.length <= 1, + // child: _decodeVoiceWordImageWidget(1,topics.topicAnswerList![0]), + // ), + // Offstage( + // offstage: topics.topicAnswerList!.length <= 2, + // child: _decodeVoiceWordImageWidget(2,topics.topicAnswerList![1]), + // ), + // // Offstage( + // // offstage: topics.topicAnswerList!.length <= 3, + // // child: _decodeVoiceWordImageWidget(3,topics.topicAnswerList![2]), + // // ), + // // Offstage( + // // offstage: topics.topicAnswerList!.length <= 4, + // // child: _decodeVoiceWordImageWidget(4,topics.topicAnswerList![3]), + // // ) + // ], + // ) ], ), ); }); - Widget _decodeVoiceWordImageWidget(int index) => BlocBuilder( + Widget _decodeVoiceWordImageWidget(int index,CourseProcessTopicsTopicAnswerList answerList) => BlocBuilder( buildWhen: (_, s) => s is SelectItemChangeState, builder: (context,state){ final bloc = BlocProvider.of(context); return GestureDetector( onTap: () => bloc.add(SelectItemEvent(index)), child: Container( - width: 143.w, + width: 163.w, height: 143.h, - padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - border: Border.all( - width: 1.0, - color: const Color(0xFF140C10) + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Container( + width: 143.w, + height: 143.h, + padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10) + ), ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Expanded( - child: Container( - alignment: Alignment.center, - child: Text( - 'yellow', - style: TextStyle( - fontSize: 20.sp, - color: const Color(0xFF333333) - ) + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: Container( + alignment: Alignment.center, + child: Text( + answerList.word??'', + style: TextStyle( + fontSize: 20.sp, + color: const Color(0xFF333333) + ) + ), ), ), - ), - Container( - height: 30.h, - width: double.infinity, - decoration: BoxDecoration( - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, - borderRadius: BorderRadius.circular(15.r), - border: Border.all( - width: 1.5, - color: const Color(0xFF140C10) + Container( + height: 30.h, + width: double.infinity, + decoration: BoxDecoration( + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white, + borderRadius: BorderRadius.circular(15.r), + border: Border.all( + width: 1.5, + color: const Color(0xFF140C10) + ), ), - ), - alignment: Alignment.center, - child: Image.asset('choose'.assetPng), - ) - ], + alignment: Alignment.center, + child: Image.asset('choose'.assetPng), + ) + ], + ), ), ), ); }); ///语音问答 - Widget _voiceAnswerItem() => BlocBuilder( + Widget _voiceAnswerItem(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state) { + final bloc = BlocProvider.of(context); return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - OwImageWidget( - name:'https://up.enterdesk.com/edpic_source/16/e7/0d/16e70d550daff77cbac31fae5e1651d4.jpg', - height: 186.h, - width: 186.w, - ), - 160.horizontalSpace, - Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset( - 'voice'.assetPng, - height: 52.h, - width: 46.w, + OwImageWidget( + name:'https://up.enterdesk.com/edpic_source/16/e7/0d/16e70d550daff77cbac31fae5e1651d4.jpg', + height: 186.h, + width: 186.w, ), - 70.verticalSpace, - Image.asset( - 'micro_phone'.assetPng, - height: 75.w, - width: 75.w, + 160.horizontalSpace, + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'voice'.assetPng, + height: 52.h, + width: 46.w, + ), + 70.verticalSpace, + GestureDetector( + onTap: () { + if (bloc.isVoicing) { + return; + } + bloc.add(VoiceXsTestEvent('Hello', 0,context.read().userEntity!.id)); + }, + child: Image.asset( + 'micro_phone'.assetPng, + height: 75.w, + width: 75.w, + ), + ) + ], ) ], - ) - ], - ); - }); + ); + }); } \ No newline at end of file -- libgit2 0.22.2