Commit 0bd6ea43a0094c85f9255ab96f9fdb7302a0db10

Authored by xiaoyu
2 parents 6b46f015 1748f1e6

Merge remote-tracking branch 'origin/feat-wqf-payment' into xiaoyu_cocossteve

android/app/build.gradle
... ... @@ -94,5 +94,5 @@ dependencies {
94 94 // kotlin扩展(可选)
95 95 implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.2'
96 96 // coco2d游戏
97   - implementation 'io.keyss.android.library:steve_game:1.0.0'
  97 + implementation 'io.keyss.android.library:steve_game:1.0.1'
98 98 }
... ...
android/build.gradle
1 1 buildscript {
2 2 ext.kotlin_version = '1.8.21'
3 3 repositories {
  4 + maven { url 'https://maven.aliyun.com/repository/google' }
  5 + maven { url "https://maven.aliyun.com/repository/public" }
  6 + maven { url 'https://jitpack.io' }
  7 +// maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
4 8 google()
5 9 mavenCentral()
6 10 }
... ... @@ -14,6 +18,10 @@ buildscript {
14 18  
15 19 allprojects {
16 20 repositories {
  21 + maven { url 'https://maven.aliyun.com/repository/google' }
  22 + maven { url "https://maven.aliyun.com/repository/public" }
  23 + maven { url 'https://jitpack.io' }
  24 +// maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
17 25 google()
18 26 mavenCentral()
19 27 maven { url 'https://repo.singsound.com/repository/singsound_ginger_android_sdk/' }
... ...
assets/sounds/correct_voice.mp3 0 → 100644
No preview for this file type
assets/sounds/incorrect_voice.mp3 0 → 100644
No preview for this file type
lib/common/core/app_config_helper.dart
... ... @@ -22,8 +22,8 @@ class AppConfigHelper {
22 22 static bool checkedUpdate = false;
23 23  
24 24 // 获取用户信息
25   - static Future<AppConfigEntity?> getAppConfig() async {
26   - if (configEntityEntity != null) {
  25 + static Future<AppConfigEntity?> getAppConfig({ bool forceSync = false }) async {
  26 + if (forceSync == false && configEntityEntity != null) {
27 27 return configEntityEntity;
28 28 }
29 29 configEntityEntity = await SystemDao.getAppConfig();
... ...
lib/common/core/user_util.dart
... ... @@ -63,8 +63,8 @@ class UserUtil {
63 63 pushNamedAndRemoveUntil(AppRouteName.login, (route) => false, arguments: {'showPasswordPage': showPasswordLoginPage});
64 64 }
65 65  
66   - // 是否有游戏权限
67   - static bool hasGamePermission() {
  66 + // 是否有权限
  67 + static bool hasPermission() {
68 68 return _userEntity?.valid ?? false;
69 69 }
70 70  
... ...
lib/common/extension/string_extension.dart
1 1 /// 资源类扩展方法
2 2 extension AssetExtension on String {
3 3 static const String _assetImagePrefix = "assets/images/";
  4 + static const String _assetSoundPrefix = 'sounds/';
4 5  
5 6 /// 图片url
6 7 String get assetImg => _assetImagePrefix + this;
... ... @@ -10,6 +11,10 @@ extension AssetExtension on String {
10 11 String get assetWebp => '$assetImg.webp';
11 12  
12 13 String get assetGif => '$assetImg.gif';
  14 +
  15 + String get assetSound => _assetSoundPrefix + this;
  16 +
  17 + String get assetMp3 => '$assetSound.mp3';
13 18 }
14 19  
15 20 extension StringExtension on String {
... ...
lib/common/request/dao/user_dao.dart
... ... @@ -2,6 +2,7 @@ import &#39;package:wow_english/common/core/user_util.dart&#39;;
2 2 import 'package:wow_english/models/user_entity.dart';
3 3 import 'package:wow_english/utils/log_util.dart';
4 4  
  5 +import '../../core/app_config_helper.dart';
5 6 import '../request_client.dart';
6 7  
7 8 enum SmsType { login, change_passWord, stdDestroy }
... ... @@ -18,6 +19,8 @@ class UserDao {
18 19 UserUtil.saveUser(data);
19 20 // 由于userInfo接口不会返回token,所以这里需要再次保存一下token
20 21 final token = data.token;
  22 + //登录成功后刷新下配置信息
  23 + AppConfigHelper.getAppConfig(forceSync: true);
21 24 //登录成功后zip一下getUserInfo,因为进入首页需要的信息在userinfo里,保证进入首页数据是最新的
22 25 data = await getUserInfo();
23 26 data?.token = token;
... ...
lib/pages/home/view.dart
1 1  
2   -import 'package:flutter/foundation.dart';
3 2 import 'package:flutter/material.dart';
4   -import 'package:flutter/services.dart';
5 3 import 'package:flutter_app_update/azhon_app_update.dart';
6 4 import 'package:flutter_app_update/update_model.dart';
7 5 import 'package:flutter_bloc/flutter_bloc.dart';
... ... @@ -69,11 +67,9 @@ class _HomePageView extends StatelessWidget {
69 67 Expanded(
70 68 child: GestureDetector(
71 69 onTap: () {
72   - if (UserUtil.isLogined()) {
  70 + _checkPermission(() {
73 71 pushNamed(AppRouteName.courseUnit);
74   - } else {
75   - pushNamed(AppRouteName.login);
76   - }
  72 + });
77 73 },
78 74 child: Column(
79 75 mainAxisAlignment: MainAxisAlignment.center,
... ... @@ -105,30 +101,9 @@ class _HomePageView extends StatelessWidget {
105 101 'WQF ModuleSelectPage BlocBuilder state: $userState');
106 102 return GestureDetector(
107 103 onTap: () {
108   - //如果没登录先登录
109   - if (UserUtil.isLogined()) {
110   - if (AppConfigHelper
111   - .shouldHidePay()) {
112   - pushNamed(AppRouteName.games);
113   - } else {
114   - if (UserUtil
115   - .hasGamePermission()) {
116   - pushNamed(AppRouteName.games);
117   - } else {
118   - showTwoActionDialog(
119   - '提示', '忽略', '去续费',
120   - '您的课程已到期,请快快续费继续学习吧!',
121   - leftTap: () {
122   - popPage();
123   - }, rightTap: () {
124   - popPage();
125   - pushNamed(AppRouteName.shop);
126   - });
127   - }
128   - }
129   - } else {
130   - pushNamed(AppRouteName.login);
131   - }
  104 + _checkPermission(() {
  105 + pushNamed(AppRouteName.games);
  106 + });
132 107 },
133 108 child: Column(
134 109 mainAxisAlignment: MainAxisAlignment
... ... @@ -168,6 +143,30 @@ class _HomePageView extends StatelessWidget {
168 143 });
169 144  
170 145  
  146 + _checkPermission(VoidCallback onAllowed) {
  147 + if (UserUtil.isLogined()) {
  148 + if (AppConfigHelper.shouldHidePay()) {
  149 + onAllowed();
  150 + } else {
  151 + if (UserUtil.hasPermission()) {
  152 + onAllowed();
  153 + } else {
  154 + showTwoActionDialog('提示', '忽略', '去续费',
  155 + '您的课程已到期,请快快续费继续学习吧!', leftTap: () {
  156 + popPage();
  157 + }, rightTap: () {
  158 + popPage();
  159 + pushNamed(AppRouteName.shop);
  160 + });
  161 + }
  162 + }
  163 + } else {
  164 + //如果没登录先登录
  165 + pushNamed(AppRouteName.login);
  166 + }
  167 + }
  168 +
  169 +
171 170 ///Flutter侧处理升级对话框
172 171 ///[forcedUpgrade] 是否强制升级
173 172 _showUpdateDialog(BuildContext context, bool forcedUpgrade,
... ...
lib/pages/home/widgets/BaseHomeHeaderWidget.dart
... ... @@ -79,18 +79,24 @@ class BaseHomeHeaderWidget extends StatelessWidget {
79 79 style: TextStyle(color: Colors.white, fontSize: 30.0),
80 80 )),
81 81 Offstage(
82   - offstage: AppConfigHelper.shouldHidePay() || !UserUtil.isLogined(),
83   - child: Row(children: <Widget>[
84   - Image(
85   - width: 20.0.w,
86   - height: 20.0.h,
87   - image: AssetImage('ic_countdown'.assetPng)),
88   - // 替换为你的图片资源路径
89   - const SizedBox(width: 10.0),
90   - // 图片和文本之间的间隔
91   - Text('还剩${UserUtil.getRemainingValidity()}天'),
92   - ]),
93   - ),
  82 + offstage: AppConfigHelper.shouldHidePay() ||
  83 + !UserUtil.isLogined(),
  84 + child: GestureDetector(
  85 + onTap: () => {
  86 + pushNamed(AppRouteName.shop),
  87 + },
  88 + child: Row(
  89 + children: <Widget>[
  90 + Image(
  91 + width: 20.0.w,
  92 + height: 20.0.h,
  93 + image: AssetImage('ic_countdown'.assetPng)),
  94 + // 替换为你的图片资源路径
  95 + const SizedBox(width: 6.0),
  96 + // 图片和文本之间的间隔
  97 + Text('还剩${UserUtil.getRemainingValidity()}天'),
  98 + ]),
  99 + )),
94 100 ScreenUtil().bottomBarHeight.horizontalSpace,
95 101 ],
96 102 ));
... ...
lib/pages/practice/bloc/topic_picture_bloc.dart
... ... @@ -5,6 +5,7 @@ import &#39;package:flutter/services.dart&#39;;
5 5 import 'package:flutter_bloc/flutter_bloc.dart';
6 6 import 'package:flutter_easyloading/flutter_easyloading.dart';
7 7 import 'package:permission_handler/permission_handler.dart';
  8 +import 'package:wow_english/common/extension/string_extension.dart';
8 9 import 'package:wow_english/common/request/dao/listen_dao.dart';
9 10 import 'package:wow_english/common/request/exception.dart';
10 11 import 'package:wow_english/models/course_process_entity.dart';
... ... @@ -45,6 +46,16 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
45 46 ///正在播放音频
46 47 VoicePlayState _voicePlayState = VoicePlayState.unKnow;
47 48  
  49 + // 是否是回答(选择)结果音效
  50 + bool _isResultSoundPlaying = false;
  51 +
  52 + bool get isResultSoundPlaying => _isResultSoundPlaying;
  53 +
  54 + // 答对播放音效时禁止任何点击(选择)操作
  55 + bool _forbiddenWhenCorrect = false;
  56 +
  57 + bool get forbiddenWhenCorrect => _forbiddenWhenCorrect;
  58 +
48 59 CourseProcessEntity? get entity => _entity;
49 60  
50 61 int get currentPage => _currentPage + 1;
... ... @@ -70,29 +81,43 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
70 81 on<RequestDataEvent>(_requestData);
71 82 on<XSVoiceTestEvent>(_voiceXsTest);
72 83 on<XSVoiceStopEvent>(_voiceXsStop);
73   - on<VoicePlayEvent>(_voicePlay);
  84 + on<VoicePlayEvent>(_questionVoicePlay);
74 85 on<InitBlocEvent>((event, emit) {
75 86 //音频播放器
76 87 audioPlayer = AudioPlayer();
77 88 audioPlayer.onPlayerStateChanged.listen((event) async {
78   - debugPrint('播放状态变化');
79   - if (event == PlayerState.completed) {
80   - debugPrint('播放完成');
81   - _voicePlayState = VoicePlayState.completed;
82   - }
83   - if (event == PlayerState.stopped) {
84   - debugPrint('播放结束');
85   - _voicePlayState = VoicePlayState.stop;
86   - }
  89 + debugPrint('播放状态变化 _voicePlayState=$_voicePlayState event=$event _isResultSoundPlaying=$_isResultSoundPlaying _forbiddenWhenCorrect=$_forbiddenWhenCorrect');
  90 + if (_isResultSoundPlaying) {
  91 + if (event != PlayerState.playing) {
  92 + _isResultSoundPlaying = false;
  93 + if (_forbiddenWhenCorrect) {
  94 + _forbiddenWhenCorrect = false;
  95 + // 答对后自动翻页
  96 + pageController.nextPage(
  97 + duration: const Duration(milliseconds: 500),
  98 + curve: Curves.ease,
  99 + );
  100 + }
  101 + }
  102 + } else {
  103 + if (event == PlayerState.completed) {
  104 + debugPrint('播放完成');
  105 + _voicePlayState = VoicePlayState.completed;
  106 + }
  107 + if (event == PlayerState.stopped) {
  108 + debugPrint('播放结束');
  109 + _voicePlayState = VoicePlayState.stop;
  110 + }
87 111  
88   - if (event == PlayerState.playing) {
89   - debugPrint('正在播放中');
90   - _voicePlayState = VoicePlayState.playing;
91   - }
92   - if(isClosed) {
93   - return;
  112 + if (event == PlayerState.playing) {
  113 + debugPrint('正在播放中');
  114 + _voicePlayState = VoicePlayState.playing;
  115 + }
  116 + if (isClosed) {
  117 + return;
  118 + }
  119 + add(VoicePlayStateChangeEvent());
94 120 }
95   - add(VoicePlayStateChangeEvent());
96 121 });
97 122  
98 123 methodChannel = const MethodChannel('wow_english/sing_sound_method_channel');
... ... @@ -129,6 +154,8 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
129 154 pageController.dispose();
130 155 audioPlayer.release();
131 156 audioPlayer.dispose();
  157 + _isResultSoundPlaying = false;
  158 + _forbiddenWhenCorrect = false;
132 159 _voiceXsCancel();
133 160 return super.close();
134 161 }
... ... @@ -149,10 +176,12 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
149 176  
150 177 ///页面切换
151 178 void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter<TopicPictureState> emitter) async {
152   - _currentPage = event.pageIndex;
153   - if (voicePlayState == VoicePlayState.playing) {
154   - await audioPlayer.stop();
  179 + await closePlayerResource();
  180 + debugPrint('翻页 $_currentPage->${event.pageIndex}');
  181 + if (_currentPage == _entity?.topics?.length) {
  182 + return;
155 183 }
  184 + _currentPage = event.pageIndex;
156 185 final topics = _entity?.topics?[_currentPage];
157 186 if (topics?.type != 3 && topics?.type != 4) {
158 187 if (topics?.audioUrl != null) {
... ... @@ -169,13 +198,18 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
169 198  
170 199 ///选择
171 200 void _selectItemLoad(SelectItemEvent event,Emitter<TopicPictureState> emitter) async {
  201 + if (_forbiddenWhenCorrect) {
  202 + return;
  203 + }
172 204 _selectItem = event.selectIndex;
173 205 CourseProcessTopics? topics = _entity?.topics?[_currentPage];
174 206 CourseProcessTopicsTopicAnswerList? answerList = topics?.topicAnswerList?[_selectItem];
175 207 if (answerList?.correct == 0) {
176   - showToast('继续加油哦',duration: const Duration(seconds: 2));
  208 + _playResultSound(false);
  209 + // showToast('继续加油哦',duration: const Duration(seconds: 2));
177 210 } else {
178   - showToast('恭喜你,答对啦!',duration: const Duration(seconds: 2));
  211 + _playResultSound(true);
  212 + // showToast('恭喜你,答对啦!',duration: const Duration(seconds: 2));
179 213 }
180 214 emitter(SelectItemChangeState());
181 215 }
... ... @@ -228,17 +262,37 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
228 262 emitter(XSVoiceTestState());
229 263 }
230 264  
  265 + // 暂时没用上
231 266 void _voicePlayStateChange(VoicePlayStateChangeEvent event,Emitter<TopicPictureState> emitter) async {
232 267 emitter(VoicePlayStateChange());
233 268 }
234 269  
235   - void _voicePlay(VoicePlayEvent event,Emitter<TopicPictureState> emitter) async {
236   - if (voicePlayState == VoicePlayState.playing) {
237   - await audioPlayer.stop();
  270 + // 题目音频播放
  271 + void _questionVoicePlay(VoicePlayEvent event,Emitter<TopicPictureState> emitter) async {
  272 + if (_forbiddenWhenCorrect) {
238 273 return;
239 274 }
  275 + _forbiddenWhenCorrect = false;
  276 + await closePlayerResource();
240 277 final topics = _entity?.topics?[_currentPage];
241 278 final urlStr = topics?.audioUrl??'';
242 279 await audioPlayer.play(UrlSource(urlStr));
243 280 }
  281 +
  282 + Future<void> closePlayerResource() async {
  283 + if (voicePlayState == VoicePlayState.playing || _isResultSoundPlaying) {
  284 + await audioPlayer.stop();
  285 + }
  286 + }
  287 +
  288 + void _playResultSound(bool isCorrect) async {
  289 + await audioPlayer.stop();
  290 + _isResultSoundPlaying = true;
  291 + _forbiddenWhenCorrect = isCorrect;
  292 + if (isCorrect) {
  293 + await audioPlayer.play(AssetSource('correct_voice'.assetMp3));
  294 + } else {
  295 + await audioPlayer.play(AssetSource('incorrect_voice'.assetMp3));
  296 + }
  297 + }
244 298 }
... ...
lib/pages/practice/bloc/topic_picture_event.dart
... ... @@ -48,5 +48,5 @@ class SelectItemEvent extends TopicPictureEvent {
48 48 ///音频播放事件
49 49 class VoicePlayChangeEvent extends TopicPictureEvent {}
50 50  
51   -///播放音乐
  51 +///播放(题目)音乐
52 52 class VoicePlayEvent extends TopicPictureEvent {}
53 53 \ No newline at end of file
... ...
lib/pages/practice/widgets/practice_header_widget.dart
... ... @@ -14,46 +14,42 @@ class PracticeHeaderWidget extends StatelessWidget {
14 14 return Container(
15 15 color: Colors.white,
16 16 height: 60.h,
17   - child: Row(
18   - mainAxisAlignment: MainAxisAlignment.spaceBetween,
19   - children: [
20   - Padding(
21   - padding: EdgeInsets.only(
22   - left: ScreenUtil().bottomBarHeight
23   - ),
24   - child: IconButton(
25   - onPressed: (){
26   - onTap();
27   - },
28   - icon: Image.asset(
29   - 'back_around'.assetPng,
30   - width: 40,
31   - height: 40,
32   - )),
  17 + child: AppBar(
  18 + leading: IconButton(
  19 + icon: Image.asset(
  20 + 'back_around'.assetPng,
  21 + width: 40,
  22 + height: 40,
33 23 ),
34   - Container(
35   - height: 40.h,
36   - padding: EdgeInsets.symmetric(horizontal: 27.w),
37   - decoration: BoxDecoration(
38   - color: const Color(0xFF00B6F1),
39   - borderRadius: BorderRadius.circular(20.r),
40   - border: Border.all(
41   - width: 1.0,
42   - color: const Color(0xFF333333),
43   - ),
44   - ),
45   - alignment: Alignment.center,
46   - child: Text(
47   - title,
48   - style: TextStyle(
49   - fontSize: 20.sp,
50   - color: Colors.white
  24 + onPressed: () {
  25 + onTap();
  26 + },
  27 + ),
  28 + centerTitle: true,
  29 + title: IntrinsicWidth(
  30 + child: Container(
  31 + height: 40.h,
  32 + padding: EdgeInsets.symmetric(horizontal: 27.w),
  33 + decoration: BoxDecoration(
  34 + color: const Color(0xFF00B6F1),
  35 + borderRadius: BorderRadius.circular(20.r),
  36 + border: Border.all(
  37 + width: 1.0,
  38 + color: const Color(0xFF333333),
  39 + ),
51 40 ),
52   - ),
  41 + child: Center(
  42 + child: Text(
  43 + title,
  44 + style: TextStyle(
  45 + fontSize: 15.sp,
  46 + color: Colors.white
  47 + ),
  48 + ),
  49 + )
53 50 ),
54   - ScreenUtil().bottomBarHeight.horizontalSpace,
55   - ],
56   - ),
  51 + )
  52 + )
57 53 );
58 54 }
59 55 }
60 56 \ No newline at end of file
... ...
lib/pages/reading/bloc/reading_bloc.dart
... ... @@ -309,12 +309,12 @@ class ReadingPageBloc extends Bloc&lt;ReadingPageEvent, ReadingPageState&gt; {
309 309 Log.d("_voiceXsResult result=$result");
310 310 final overall = result['overall'].toString();
311 311 EasyLoading.showToast('测评成功,分数是$overall',
312   - duration: const Duration(seconds: 10));
  312 + duration: const Duration(seconds: 2));
313 313 currentPageData()?.recordScore = overall;
314 314 currentPageData()?.recordUrl = args['audioUrl'] + '.mp3';
315 315 ///完成录音后紧接着播放录音
316 316 _playRecordAudioInner();
317   - emitter(FeedbackState());
  317 + // emitter(FeedbackState());
318 318 }
319 319  
320 320 ///终止评测
... ...
lib/pages/section/section_page.dart
... ... @@ -183,46 +183,46 @@ class _SectionPageView extends StatelessWidget {
183 183 );
184 184 }
185 185 })),
186   - SafeArea(
187   - child: Padding(
188   - padding: EdgeInsets.symmetric(horizontal: 13.w),
189   - child: Row(
190   - mainAxisAlignment: MainAxisAlignment.spaceBetween,
191   - children: [
192   - SizedBox(
193   - height: 47.h,
194   - width: 80.w,
195   - ),
196   - Container(
197   - decoration: BoxDecoration(
198   - color: CourseModuleModel(
199   - bloc.courseUnitEntity.courseModuleCode ??
200   - 'Phase-1')
201   - .color,
202   - borderRadius: BorderRadius.circular(14.5.r),
203   - ),
204   - padding: EdgeInsets.symmetric(
205   - vertical: 8.h, horizontal: 24.w),
206   - child: Text(
207   - '${(bloc.courseUnitEntity.nowStep ?? 0)}/${bloc.courseUnitEntity.total ?? 0}',
208   - style: TextStyle(
209   - color: Colors.white, fontSize: 12.sp),
210   - ),
211   - ),
212   - Image.asset(
213   - CourseModuleModel(
214   - bloc.courseUnitEntity.courseModuleCode ??
215   - 'Phase-1')
216   - .courseModuleLogo
217   - .assetPng,
218   - height: 47.h,
219   - width: 80.w,
220   - // color: Colors.red,
221   - ),
222   - ],
223   - ),
224   - ),
225   - )
  186 + // SafeArea(
  187 + // child: Padding(
  188 + // padding: EdgeInsets.symmetric(horizontal: 13.w),
  189 + // child: Row(
  190 + // mainAxisAlignment: MainAxisAlignment.spaceBetween,
  191 + // children: [
  192 + // SizedBox(
  193 + // height: 47.h,
  194 + // width: 80.w,
  195 + // ),
  196 + // Container(
  197 + // decoration: BoxDecoration(
  198 + // color: CourseModuleModel(
  199 + // bloc.courseUnitEntity.courseModuleCode ??
  200 + // 'Phase-1')
  201 + // .color,
  202 + // borderRadius: BorderRadius.circular(14.5.r),
  203 + // ),
  204 + // padding: EdgeInsets.symmetric(
  205 + // vertical: 8.h, horizontal: 24.w),
  206 + // child: Text(
  207 + // '${(bloc.courseUnitEntity.nowStep ?? 0)}/${bloc.courseUnitEntity.total ?? 0}',
  208 + // style: TextStyle(
  209 + // color: Colors.white, fontSize: 12.sp),
  210 + // ),
  211 + // ),
  212 + // Image.asset(
  213 + // CourseModuleModel(
  214 + // bloc.courseUnitEntity.courseModuleCode ??
  215 + // 'Phase-1')
  216 + // .courseModuleLogo
  217 + // .assetPng,
  218 + // height: 47.h,
  219 + // width: 80.w,
  220 + // // color: Colors.red,
  221 + // ),
  222 + // ],
  223 + // ),
  224 + // ),
  225 + // )
226 226 ],
227 227 ),
228 228 ),
... ...
lib/pages/shop/home/shop_home_page.dart
... ... @@ -62,14 +62,14 @@ class _ShopHomeView extends StatelessWidget {
62 62 ),
63 63 body: Center(
64 64 child: Padding(
65   - padding: EdgeInsets.symmetric(vertical: 25.h, horizontal: 25.w),
  65 + padding: EdgeInsets.symmetric(vertical: 24.h, horizontal: 24.w),
66 66 child: GridView.builder(
67 67 itemCount: bloc.productDatas.length,
68 68 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
69 69 crossAxisCount: 2,
70 70 childAspectRatio: 2,
71 71 mainAxisSpacing: 14.h,
72   - crossAxisSpacing: 4.5.w,
  72 + crossAxisSpacing: 6.w,
73 73 ),
74 74 itemBuilder: (BuildContext context, int index) {
75 75 final productEntity = bloc.productDatas[index];
... ...
pubspec.yaml
... ... @@ -98,11 +98,11 @@ dependencies:
98 98 # 语音录制 https://pub.dev/packages/flutter_sound
99 99 flutter_sound: ^9.2.13
100 100 # 音频播放 https://pub.dev/packages/audio_session
101   - audio_session: ^0.1.16
  101 + audio_session: ^0.1.19
102 102 # 文件管理 https://pub.dev/packages/path_provider
103 103 path_provider: ^2.0.15
104 104 # 阿里云oss https://pub.dev/packages/flutter_oss_aliyun
105   - flutter_oss_aliyun: ^6.2.7
  105 + flutter_oss_aliyun: ^6.4.2
106 106 # App信息 https://pub.dev/packages/package_info_plus
107 107 package_info_plus: ^4.2.0
108 108 # 应用内更新 https://pub-web.flutter-io.cn/packages/flutter_app_update
... ... @@ -135,6 +135,7 @@ flutter:
135 135 assets:
136 136 - assets/images/
137 137 - assets/fonts/
  138 + - assets/sounds/
138 139 fonts:
139 140 - family: HannotateSC
140 141 fonts:
... ...