Commit bc0550ae13b26fb1bc0dbacd80556b33112e53ce

Authored by Key
1 parent 68dd7ba8

fixed: avatar修改

lib/common/extension/exception_ext.dart
... ... @@ -4,6 +4,8 @@ extension ExceptionExtension on Exception {
4 4 String get getShowMessage {
5 5 if (this is ApiException) {
6 6 return (this as ApiException).message ?? '未知错误';
  7 + } else if (this is FormatException) {
  8 + return (this as FormatException).message;
7 9 } else {
8 10 return '未知错误';
9 11 }
... ...
lib/pages/user/bloc/user_bloc.dart
... ... @@ -35,32 +35,24 @@ class UserBloc extends Bloc<UserEvent, UserState> {
35 35 void _updateUser(UserUpdate event, Emitter<UserState> emitter) async {
36 36 Log.d('_updateUser, event: ${event.type}, emitter.isDone: ${emitter.isDone}, text=${event.content}');
37 37 UserEntity user = UserUtil.getUser()!;
38   - switch (event.type) {
39   - case ModifyUserInformationType.avatar:
40   - String avatarUrl = event.content;
41   - try {
  38 + try {
  39 + switch (event.type) {
  40 + case ModifyUserInformationType.avatar:
  41 + String avatarUrl = event.content;
42 42 await UserDao.updateUserInfoField(avatarUrl: avatarUrl);
43 43 // 修改成功,更新本地缓存及UI
44 44 user.avatarUrl = avatarUrl;
45 45 emitter(UserInfoUpdated());
46   - } catch (e) {
47   - Log.e('_updateUser avatarUrl, e: $e');
48   - }
49   - break;
50   - case ModifyUserInformationType.name:
51   - String name = event.content;
52   - try {
  46 + break;
  47 + case ModifyUserInformationType.name:
  48 + String name = event.content;
53 49 await UserDao.updateUserInfoField(name: name);
54 50 // 修改成功,更新本地缓存及UI
55 51 user.name = name;
56 52 emitter(UserInfoUpdated());
57   - } catch (e) {
58   - Log.e('_updateUser name, e: $e');
59   - }
60   - break;
61   - case ModifyUserInformationType.age:
62   - // todo 校验格式
63   - try {
  53 + break;
  54 + case ModifyUserInformationType.age:
  55 + // todo 校验格式
64 56 int age;
65 57 try {
66 58 age = int.parse(event.content);
... ... @@ -72,20 +64,18 @@ class UserBloc extends Bloc&lt;UserEvent, UserState&gt; {
72 64 // 修改成功,更新本地缓存及UI
73 65 user.age = age;
74 66 emitter(UserInfoUpdated());
75   - } catch (e) {
76   - Log.e('_updateUser age, e: $e');
77   - }
78   - break;
79   - case ModifyUserInformationType.gender:
80   - try {
  67 + break;
  68 + case ModifyUserInformationType.gender:
81 69 var gender = int.parse(event.content);
82 70 await UserDao.updateUserInfoField(gender: gender);
83 71 user.gender = gender;
84 72 emitter(UserInfoUpdated());
85   - } catch (e) {
86   - Log.e('_updateUser gender, e: $e');
87   - }
88   - break;
  73 + break;
  74 + }
  75 + // 服务器保存成功后本地再保存一下
  76 + UserUtil.saveUser(user);
  77 + } catch (e) {
  78 + Log.e('修改个人信息失败: $e');
89 79 }
90 80 }
91 81 }
... ...
lib/pages/user/modify/modify_user_avatar_page.dart
... ... @@ -30,39 +30,39 @@ class ModifyUserAvatarPage extends StatelessWidget {
30 30  
31 31 class _ModifyUserAvatarPage extends StatelessWidget {
32 32 const _ModifyUserAvatarPage({required this.pageType});
  33 +
33 34 final int pageType;
34 35  
35 36 @override
36 37 Widget build(BuildContext context) {
37 38 return MultiBlocListener(
38 39 listeners: [
39   - BlocListener<UserBloc,UserState>(
40   - listener: (context, state){
41   - if (state is UserInfoUpdated) {
42   - if (pageType == 1) {
43   - showToast('修改成功');
44   - popPage();
45   - } else {
46   - context.read<UserAvatarBloc>().add(ChangeUserEnterAppStateEvent());
47   - }
48   - }
49   - }),
50   - BlocListener<UserAvatarBloc,UserAvatarState>(
51   - listener: (context,state){
  40 + BlocListener<UserBloc, UserState>(listener: (context, state) {
  41 + if (state is UserInfoUpdated) {
  42 + if (pageType == 1) {
  43 + showToast('修改成功');
  44 + popPage();
  45 + } else {
  46 + context.read<UserAvatarBloc>().add(ChangeUserEnterAppStateEvent());
  47 + }
  48 + }
  49 + }),
  50 + BlocListener<UserAvatarBloc, UserAvatarState>(
  51 + listener: (context, state) {
52 52 if (state is ChangeImageState) {
53   - context.read<UserBloc>().add(UserUpdate(ModifyUserInformationType.avatar,state.imageUrl));
  53 + context.read<UserBloc>().add(UserUpdate(ModifyUserInformationType.avatar, state.imageUrl));
54 54 }
55   - },)
  55 + },
  56 + )
56 57 ],
57   - child: pageType == 0 ? _setUserAvatarView():_modifyUserAvatarPageView(),
  58 + child: pageType == 0 ? _setUserAvatarView() : _modifyUserAvatarPageView(),
58 59 );
59 60 }
60 61  
61 62 ///个人信息修改头像
62   - Widget _modifyUserAvatarPageView() => BlocBuilder<UserAvatarBloc,UserAvatarState>(
63   - builder: (context,state){
  63 + Widget _modifyUserAvatarPageView() => BlocBuilder<UserAvatarBloc, UserAvatarState>(builder: (context, state) {
64 64 return Scaffold(
65   - appBar:const WEAppBar(
  65 + appBar: const WEAppBar(
66 66 titleText: '头像修改',
67 67 ),
68 68 body: SafeArea(
... ... @@ -77,64 +77,53 @@ class _ModifyUserAvatarPage extends StatelessWidget {
77 77 });
78 78  
79 79 ///新用户设置头像
80   - Widget _setUserAvatarView() => BlocBuilder<UserAvatarBloc,UserAvatarState>(
81   - builder: (context, state) {
82   - final bloc = BlocProvider.of<UserAvatarBloc>(context);
83   - return Container(
84   - color: Colors.white,
85   - child: SafeArea(
86   - child: Column(
87   - children: [
88   - 20.verticalSpace,
89   - Row(
90   - children: [
91   - Image.asset(
92   - 'wow_logo'.assetPng,
93   - height: 49.h,
94   - width: 84.w,
95   - ),
96   - Text(
97   - '欢迎登录wow english\n接下来请填写一下您的个人信息吧',
98   - textAlign: TextAlign.left,
99   - style: TextStyle(
100   - fontSize: 17.sp,
101   - color: const Color(0xFF666666)
  80 + Widget _setUserAvatarView() => BlocBuilder<UserAvatarBloc, UserAvatarState>(builder: (context, state) {
  81 + final bloc = BlocProvider.of<UserAvatarBloc>(context);
  82 + return Container(
  83 + color: Colors.white,
  84 + child: SafeArea(
  85 + child: Column(
  86 + children: [
  87 + 20.verticalSpace,
  88 + Row(
  89 + children: [
  90 + Image.asset(
  91 + 'wow_logo'.assetPng,
  92 + height: 49.h,
  93 + width: 84.w,
102 94 ),
103   - )
104   - ],
105   - ),
106   - 15.verticalSpace,
107   - _avatarImageWidget(),
108   - 10.verticalSpace,
109   - Container(
110   - width: 176.w,
111   - height: 52.h,
112   - padding: const EdgeInsets.all(5),
113   - decoration: BoxDecoration(
114   - image: DecorationImage(
115   - image: AssetImage(bloc.canInsertApp?'oninto'.assetPng:'intowow'.assetPng),
116   - fit: BoxFit.fill
  95 + Text(
  96 + '欢迎登录wow english\n接下来请填写一下您的个人信息吧',
  97 + textAlign: TextAlign.left,
  98 + style: TextStyle(fontSize: 17.sp, color: const Color(0xFF666666)),
117 99 )
  100 + ],
118 101 ),
119   - alignment: Alignment.center,
120   - child: Text(
121   - '进入wow english',
122   - textAlign: TextAlign.center,
123   - style: TextStyle(
124   - fontSize: 12.sp,
125   - color: Colors.white
  102 + 15.verticalSpace,
  103 + _avatarImageWidget(),
  104 + 10.verticalSpace,
  105 + Container(
  106 + width: 176.w,
  107 + height: 52.h,
  108 + padding: const EdgeInsets.all(5),
  109 + decoration: BoxDecoration(
  110 + image: DecorationImage(
  111 + image: AssetImage(bloc.canInsertApp ? 'oninto'.assetPng : 'intowow'.assetPng),
  112 + fit: BoxFit.fill)),
  113 + alignment: Alignment.center,
  114 + child: Text(
  115 + '进入wow english',
  116 + textAlign: TextAlign.center,
  117 + style: TextStyle(fontSize: 12.sp, color: Colors.white),
126 118 ),
127   - ),
128   - )
129   - ],
  119 + )
  120 + ],
  121 + ),
130 122 ),
131   - ),
132   - );
133   - }
134   - );
  123 + );
  124 + });
135 125  
136   - Widget _avatarImageWidget() => BlocBuilder<UserAvatarBloc,UserAvatarState>(
137   - builder: (context, state){
  126 + Widget _avatarImageWidget() => BlocBuilder<UserAvatarBloc, UserAvatarState>(builder: (context, state) {
138 127 final bloc = BlocProvider.of<UserAvatarBloc>(context);
139 128 return Row(
140 129 mainAxisAlignment: MainAxisAlignment.center,
... ... @@ -144,17 +133,13 @@ class _ModifyUserAvatarPage extends StatelessWidget {
144 133 height: 197.h,
145 134 padding: const EdgeInsets.all(5),
146 135 decoration: BoxDecoration(
147   - image: DecorationImage(
148   - image: AssetImage('video_background'.assetPng),
149   - fit: BoxFit.fill
150   - )
151   - ),
152   - child: bloc.file == null ?
153   - OwImageWidget(name: bloc.imageUrl):
154   - Image.file(
155   - File(bloc.file!.path),
156   - fit: BoxFit.fill,
157   - ),
  136 + image: DecorationImage(image: AssetImage('video_background'.assetPng), fit: BoxFit.fill)),
  137 + child: bloc.file == null
  138 + ? OwImageWidget(name: bloc.imageUrl)
  139 + : Image.file(
  140 + File(bloc.file!.path),
  141 + fit: BoxFit.fill,
  142 + ),
158 143 ),
159 144 54.horizontalSpace,
160 145 Column(
... ... @@ -166,19 +151,12 @@ class _ModifyUserAvatarPage extends StatelessWidget {
166 151 width: 222.w,
167 152 height: 65.h,
168 153 alignment: Alignment.center,
169   - decoration: BoxDecoration(
170   - image: DecorationImage(
171   - image: AssetImage('alter'.assetPng),
172   - fit: BoxFit.fill
173   - )
174   - ),
  154 + decoration:
  155 + BoxDecoration(image: DecorationImage(image: AssetImage('alter'.assetPng), fit: BoxFit.fill)),
175 156 child: Text(
176 157 '拍照修改头像',
177 158 textAlign: TextAlign.center,
178   - style: TextStyle(
179   - color: Colors.white,
180   - fontSize: 20.sp
181   - ),
  159 + style: TextStyle(color: Colors.white, fontSize: 20.sp),
182 160 ),
183 161 ),
184 162 ),
... ... @@ -189,19 +167,12 @@ class _ModifyUserAvatarPage extends StatelessWidget {
189 167 width: 222.w,
190 168 height: 65.h,
191 169 alignment: Alignment.center,
192   - decoration: BoxDecoration(
193   - image: DecorationImage(
194   - image: AssetImage('alter'.assetPng),
195   - fit: BoxFit.fill
196   - )
197   - ),
  170 + decoration:
  171 + BoxDecoration(image: DecorationImage(image: AssetImage('alter'.assetPng), fit: BoxFit.fill)),
198 172 child: Text(
199 173 '从相册选择',
200 174 textAlign: TextAlign.center,
201   - style: TextStyle(
202   - color: Colors.white,
203   - fontSize: 20.sp
204   - ),
  175 + style: TextStyle(color: Colors.white, fontSize: 20.sp),
205 176 ),
206 177 ),
207 178 )
... ...
lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart
... ... @@ -12,6 +12,7 @@ import &#39;package:wow_english/common/dialogs/show_dialog.dart&#39;;
12 12 import 'package:wow_english/route/route.dart';
13 13 import 'package:wow_english/utils/aliyun_oss_util.dart';
14 14 import 'package:wow_english/utils/log_util.dart';
  15 +import 'package:wow_english/utils/toast_util.dart';
15 16  
16 17 part 'user_avatar_event.dart';
17 18 part 'user_avatar_state.dart';
... ... @@ -38,10 +39,8 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
38 39 }
39 40  
40 41 Future<String> _uploadAvatar(String imagePath) async {
41   - // todo 加个loading UI
42   - EasyLoading.showToast('');
43 42 String avatarUrl = await AliyunOssUtil.uploadFile(imagePath);
44   - EasyLoading.dismiss();
  43 + debugPrint('>>>>>>>>>>阿里云图片地址: $avatarUrl');
45 44 return avatarUrl;
46 45 }
47 46  
... ... @@ -51,7 +50,7 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
51 50 final androidInfo = await DeviceInfoPlugin().androidInfo;
52 51 if (androidInfo.version.sdkInt <= 32) {
53 52 permission = Permission.storage;
54   - } else {
  53 + } else {
55 54 permission = Permission.photos;
56 55 }
57 56 } else {
... ... @@ -63,12 +62,15 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
63 62 return;
64 63 }
65 64 _file = await picker.pickImage(source: ImageSource.gallery);
  65 + EasyLoading.show();
66 66 try {
67 67 final urlStr = await _uploadAvatar(_file!.path);
68 68 emitter(ChangeImageState(urlStr));
69 69 } catch (e) {
70 70 Log.e('上传头像失败:$e');
  71 + showToast('上传头像失败: $e');
71 72 }
  73 + EasyLoading.dismiss();
72 74 });
73 75 }
74 76  
... ... @@ -79,17 +81,19 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
79 81 return;
80 82 }
81 83 _file = await picker.pickImage(source: ImageSource.camera);
  84 + EasyLoading.show();
82 85 try {
83 86 final urlStr = await _uploadAvatar(_file!.path);
84 87 emitter(ChangeImageState(urlStr));
85 88 } catch (e) {
86 89 Log.e('上传头像失败:$e');
  90 + showToast('上传头像失败: $e');
87 91 }
88   - //emitter(ChangeImageState());
  92 + EasyLoading.dismiss();
89 93 });
90 94 }
91 95  
92   - void _changeUserEnterAppState(ChangeUserEnterAppStateEvent event,Emitter<UserAvatarState> emitter) async {
  96 + void _changeUserEnterAppState(ChangeUserEnterAppStateEvent event, Emitter<UserAvatarState> emitter) async {
93 97 _canInsertApp = true;
94 98 emitter(ChangeUserEnterAppState());
95 99 }
... ... @@ -104,9 +108,7 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
104 108 showDialog(permission);
105 109 } else if (status.isRestricted) {
106 110 _requestPermission(permission);
107   - } else {
108   -
109   - }
  111 + } else {}
110 112 return false;
111 113 }
112 114  
... ...
lib/utils/aliyun_oss_util.dart
1 1 import 'package:dio/dio.dart';
2   -import 'package:flutter/cupertino.dart';
3 2 import 'package:flutter_oss_aliyun/flutter_oss_aliyun.dart';
  3 +import 'package:wow_english/common/request/api_response/api_response_entity.dart';
4 4 import 'package:wow_english/common/request/request_client.dart';
5 5 import 'package:wow_english/models/aliyun_oss_upload_sts_entity.dart';
6 6 import 'package:wow_english/utils/log_util.dart';
... ... @@ -10,15 +10,16 @@ import &#39;package:wow_english/utils/log_util.dart&#39;;
10 10 class AliyunOssUtil {
11 11 static Future<String> uploadFile(String filePath) async {
12 12 // 取出文件名
13   - String fileName = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length);
14   - Log.d("待上传文件fileName: $fileName");
  13 + //String fileName = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length);
  14 + String fileName = filePath.split('/').last;
  15 + Log.d("待上传文件: [$filePath], 截取的fileName: [$fileName]");
15 16 // 获取鉴权信息
16 17 AliyunOssUploadStsEntity? stsEntity = await _getSts(fileName);
17   - if(stsEntity == null) {
18   - // todo 为空的情况抛出错误
19   - return '';
  18 + if (stsEntity == null) {
  19 + // 为空的情况抛出错误
  20 + throw 'STS为空';
20 21 }
21   - debugPrint('鉴权信息$stsEntity');
  22 + //Log.d('鉴权信息: $stsEntity');
22 23 // 鉴权
23 24 Client.init(
24 25 ossEndpoint: stsEntity.endpoint,
... ... @@ -27,17 +28,17 @@ class AliyunOssUtil {
27 28 );
28 29  
29 30 // 上传文件
30   - await Client().putObjectFile(
  31 + final Response<dynamic> resp = await Client().putObjectFile(
31 32 filePath,
32 33 fileKey: stsEntity.fileKey,
33 34 option: PutRequestOption(
34 35 onSendProgress: (count, total) {
35   - Log.d("send: count = $count, and total = $total");
  36 + Log.d("send: $count/$total");
36 37 },
37 38 onReceiveProgress: (count, total) {
38   - Log.d("receive: count = $count, and total = $total");
  39 + Log.d("receive: $count/$total");
39 40 },
40   - aclModel: AclMode.publicRead,
  41 + aclModel: AclMode.inherited,
41 42 callback: Callback(
42 43 callbackUrl: stsEntity.callbackParam.callbackUrl,
43 44 callbackBody: stsEntity.callbackParam.callbackBody,
... ... @@ -45,13 +46,21 @@ class AliyunOssUtil {
45 46 ),
46 47 ),
47 48 );
48   - return '${stsEntity.host}/${stsEntity.fileKey}';
  49 + var url = '${stsEntity.host}/${stsEntity.fileKey}';
  50 + // 正确返回时,是我们自己服务器的回调,所以使用我们的格式解析
  51 + var result = ApiResponse.fromJson(resp.data);
  52 + Log.d('上传结果: $result, url: $url');
  53 + if (result.code != 200) {
  54 + // 上传失败抛出错误
  55 + throw result.msg ?? '未知错误';
  56 + }
  57 + return url;
49 58 }
50 59  
51 60 /// 获取鉴权信息
52 61 static Future<AliyunOssUploadStsEntity?> _getSts(String fileName) async {
53   - var result = await requestClient.get<AliyunOssUploadStsEntity>(Apis.aliyunOssSts, queryParameters: {'fileName': fileName});
54   - debugPrint('鉴权结果$result');
  62 + var result =
  63 + await requestClient.get<AliyunOssUploadStsEntity>(Apis.aliyunOssSts, queryParameters: {'fileName': fileName});
55 64 return result;
56 65 }
57 66 }
... ...