reason

修改用户信息页面

1 +import 'dart:convert';
2 +import 'package:Parlando/generated/json/base/json_field.dart';
3 +import 'package:Parlando/generated/json/upload_avatar_entity.g.dart';
4 +
5 +@JsonSerializable()
6 +class UploadAvatarEntity {
7 + String? status;
8 + int? code;
9 + String? message;
10 + UploadAvatarData? data;
11 + UploadAvatarError? error;
12 +
13 + UploadAvatarEntity();
14 +
15 + factory UploadAvatarEntity.fromJson(Map<String, dynamic> json) =>
16 + $UploadAvatarEntityFromJson(json);
17 +
18 + Map<String, dynamic> toJson() => $UploadAvatarEntityToJson(this);
19 +
20 + @override
21 + String toString() {
22 + return jsonEncode(this);
23 + }
24 +}
25 +
26 +@JsonSerializable()
27 +class UploadAvatarData {
28 + String? avatar;
29 +
30 + UploadAvatarData();
31 +
32 + factory UploadAvatarData.fromJson(Map<String, dynamic> json) =>
33 + $UploadAvatarDataFromJson(json);
34 +
35 + Map<String, dynamic> toJson() => $UploadAvatarDataToJson(this);
36 +
37 + @override
38 + String toString() {
39 + return jsonEncode(this);
40 + }
41 +}
42 +
43 +@JsonSerializable()
44 +class UploadAvatarError {
45 + UploadAvatarError();
46 +
47 + factory UploadAvatarError.fromJson(Map<String, dynamic> json) =>
48 + $UploadAvatarErrorFromJson(json);
49 +
50 + Map<String, dynamic> toJson() => $UploadAvatarErrorToJson(this);
51 +
52 + @override
53 + String toString() {
54 + return jsonEncode(this);
55 + }
56 +}
1 +import 'package:Parlando/account/models/upload_avatar_entity.dart';
2 +import 'package:Parlando/models/upload_entity.dart';
3 +import 'package:Parlando/net/dio_utils.dart';
4 +import 'package:Parlando/net/http_api.dart';
5 +import 'package:Parlando/util/toast_utils.dart';
6 +import 'package:cached_network_image/cached_network_image.dart';
7 +import 'package:dio/dio.dart';
8 +import 'package:flutter/cupertino.dart';
1 import 'package:flutter/material.dart'; 9 import 'package:flutter/material.dart';
2 import 'package:Parlando/extension/int_extension.dart'; 10 import 'package:Parlando/extension/int_extension.dart';
3 import 'package:Parlando/widgets/my_app_bar.dart'; 11 import 'package:Parlando/widgets/my_app_bar.dart';
...@@ -15,7 +23,10 @@ class AccountEditPage extends StatefulWidget { ...@@ -15,7 +23,10 @@ class AccountEditPage extends StatefulWidget {
15 class MapScreenState extends State<AccountEditPage> 23 class MapScreenState extends State<AccountEditPage>
16 with SingleTickerProviderStateMixin { 24 with SingleTickerProviderStateMixin {
17 bool _status = true; 25 bool _status = true;
26 + bool isUpdateAvatar = false;
18 final FocusNode myFocusNode = FocusNode(); 27 final FocusNode myFocusNode = FocusNode();
28 + String _imageFile =
29 + 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif';
19 30
20 @override 31 @override
21 void initState() { 32 void initState() {
...@@ -25,379 +36,385 @@ class MapScreenState extends State<AccountEditPage> ...@@ -25,379 +36,385 @@ class MapScreenState extends State<AccountEditPage>
25 @override 36 @override
26 Widget build(BuildContext context) { 37 Widget build(BuildContext context) {
27 return Scaffold( 38 return Scaffold(
28 - appBar: const MyAppBar( 39 + appBar: const MyAppBar(
29 - isBack: true, 40 + isBack: true,
30 - isTransparent: true, 41 + isTransparent: true,
31 - ), 42 + ),
32 - body: Container( 43 + body: Container(
33 - color: Colors.white, 44 + color: Colors.white,
34 - child: ListView( 45 + child: ListView(
35 - children: <Widget>[ 46 + children: <Widget>[
36 - Column( 47 + Column(
37 - children: <Widget>[ 48 + children: <Widget>[
38 - Container( 49 + Container(
39 - height: 220.px, 50 + height: 220.px,
40 - color: Colors.white, 51 + color: Colors.white,
41 - child: Column( 52 + child: Column(
42 - children: <Widget>[ 53 + children: <Widget>[
43 - Padding( 54 + Padding(
44 - padding: const EdgeInsets.only(top: 20.0), 55 + padding: const EdgeInsets.only(top: 20.0),
45 - child: Stack(fit: StackFit.loose, children: <Widget>[ 56 + child: Stack(fit: StackFit.loose, children: <Widget>[
46 - Row( 57 + Row(
47 - crossAxisAlignment: CrossAxisAlignment.center, 58 + crossAxisAlignment: CrossAxisAlignment.center,
48 - mainAxisAlignment: MainAxisAlignment.center, 59 + mainAxisAlignment: MainAxisAlignment.center,
49 - children: <Widget>[ 60 + children: <Widget>[
50 - Container( 61 + Container(
51 - height: 140.px, 62 + height: 140.px,
52 - width: 140.px, 63 + width: 140.px,
53 - margin: EdgeInsets.only(bottom: 12.px), 64 + margin: EdgeInsets.only(bottom: 12.px),
54 - child: ClipOval( 65 + child: ClipOval(
55 - child: Image.network( 66 + child: CachedNetworkImage(
56 - "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif", 67 + fit: BoxFit.cover,
57 - fit: BoxFit.cover, 68 + placeholder: (context, url) =>
58 - ), 69 + const CircularProgressIndicator(),
70 + errorWidget: (context, url, error) =>
71 + const Icon(Icons.error),
72 + imageUrl: _imageFile,
59 ), 73 ),
60 ), 74 ),
61 - ], 75 + ),
62 - ), 76 + ],
63 - Padding( 77 + ),
64 - padding: EdgeInsets.only( 78 + Padding(
65 - top: 90.px, 79 + padding: EdgeInsets.only(
66 - right: 100.px, 80 + top: 90.px,
67 - ), 81 + right: 100.px,
68 - child: Row( 82 + ),
69 - mainAxisAlignment: MainAxisAlignment.center, 83 + child: Row(
70 - children: <Widget>[ 84 + mainAxisAlignment: MainAxisAlignment.center,
71 - InkWell( 85 + children: <Widget>[
72 - child: CircleAvatar( 86 + InkWell(
73 - backgroundColor: Colors.red, 87 + child: CircleAvatar(
74 - radius: 25.px, 88 + backgroundColor: Colors.red,
75 - child: const Icon( 89 + radius: 25.px,
76 - Icons.camera_alt, 90 + child: const Icon(
77 - color: Colors.white, 91 + Icons.camera_alt,
78 - ), 92 + color: Colors.white,
79 ), 93 ),
80 - onTap: () { 94 + ),
81 - showModalBottomSheet( 95 + onTap: () {
82 - context: context, 96 + showModalBottomSheet(
83 - builder: (context) { 97 + context: context,
84 - return Column( 98 + builder: (context) {
85 - mainAxisSize: MainAxisSize.min, 99 + return Column(
86 - children: <Widget>[ 100 + mainAxisSize: MainAxisSize.min,
87 - ListTile( 101 + children: <Widget>[
88 - title: const Center( 102 + ListTile(
89 - child: Text( 103 + title: const Center(
90 - '拍照', 104 + child: Text(
91 - style: TextStyle( 105 + '拍照',
92 - fontSize: 18, 106 + style: TextStyle(
93 - ), 107 + fontSize: 18,
94 ), 108 ),
95 ), 109 ),
96 - onTap: () {
97 - Navigator.pop(context);
98 - onImageButtonPressed(
99 - ImageSource.camera,
100 - context: context,
101 - capturedImageFile: (s) {
102 - setState(() {
103 - print(s);
104 - // _imageFile = s;
105 - });
106 - },
107 - );
108 - },
109 ), 110 ),
110 - ListTile( 111 + onTap: () {
111 - title: const Center( 112 + Navigator.pop(context);
112 - child: Text( 113 + onImageButtonPressed(
113 - '相册', 114 + ImageSource.camera,
114 - style: TextStyle( 115 + context: context,
115 - fontSize: 18, 116 + capturedImageFile: (s) {
116 - ), 117 + _imageFile = s;
118 + updateAvatar(s);
119 + },
120 + );
121 + },
122 + ),
123 + ListTile(
124 + title: const Center(
125 + child: Text(
126 + '相册',
127 + style: TextStyle(
128 + fontSize: 18,
117 ), 129 ),
118 ), 130 ),
119 - onTap: () {
120 - Navigator.pop(context);
121 - onImageButtonPressed(
122 - ImageSource.gallery,
123 - context: context,
124 - capturedImageFile: (s) {
125 - print(
126 - "file path ${s}");
127 - setState(() {
128 - // _imageFile = s;
129 - });
130 - },
131 - );
132 - },
133 ), 131 ),
134 - ], 132 + onTap: () {
135 - ); 133 + Navigator.pop(context);
136 - }); 134 + onImageButtonPressed(
137 - }, 135 + ImageSource.gallery,
138 - ) 136 + context: context,
139 - ], 137 + capturedImageFile: (s) {
140 - )), 138 + _imageFile = s;
141 - ]), 139 + updateAvatar(s);
142 - ) 140 + },
143 - ], 141 + );
144 - ), 142 + },
145 - ), 143 + ),
146 - Container( 144 + ],
147 - color: const Color(0xffFFFFFF), 145 + );
148 - child: Padding( 146 + });
149 - padding: EdgeInsets.only(bottom: 5.px), 147 + },
150 - child: Column(
151 - crossAxisAlignment: CrossAxisAlignment.start,
152 - mainAxisAlignment: MainAxisAlignment.start,
153 - children: <Widget>[
154 - Padding(
155 - padding: EdgeInsets.only(
156 - left: 25.px,
157 - right: 25.px,
158 - top: 5.px,
159 - ),
160 - child: Row(
161 - mainAxisAlignment:
162 - MainAxisAlignment.spaceBetween,
163 - mainAxisSize: MainAxisSize.max,
164 - children: <Widget>[
165 - Column(
166 - mainAxisAlignment: MainAxisAlignment.start,
167 - mainAxisSize: MainAxisSize.min,
168 - children: <Widget>[
169 - Text(
170 - ParlandoLocalizations.of(context)
171 - .accountEditPageUserInfo,
172 - style: TextStyle(
173 - fontSize: 18.px,
174 - fontWeight: FontWeight.bold),
175 - ),
176 - ],
177 - ),
178 - Column(
179 - mainAxisAlignment: MainAxisAlignment.end,
180 - mainAxisSize: MainAxisSize.min,
181 - children: <Widget>[
182 - _status ? _getEditIcon() : Container(),
183 - ],
184 ) 148 )
185 ], 149 ],
186 )), 150 )),
187 - Padding( 151 + isUpdateAvatar
188 - padding: EdgeInsets.only( 152 + ? const Center(
189 - left: 25.px, right: 25.px, top: 25.px), 153 + child: CupertinoActivityIndicator(
190 - child: Row( 154 + radius: 16.0,
191 - mainAxisSize: MainAxisSize.max,
192 - children: <Widget>[
193 - Column(
194 - mainAxisAlignment: MainAxisAlignment.start,
195 - mainAxisSize: MainAxisSize.min,
196 - children: <Widget>[
197 - Text(
198 - ParlandoLocalizations.of(context)
199 - .accountEditPageUserName,
200 - style: TextStyle(
201 - fontSize: 16.px,
202 - fontWeight: FontWeight.bold),
203 - ),
204 - ],
205 ), 155 ),
206 - ], 156 + )
207 - )), 157 + : Container(),
208 - Padding( 158 + ]),
209 - padding: EdgeInsets.only( 159 + )
210 - left: 25.px, 160 + ],
211 - right: 25.px, 161 + ),
212 - top: 2.px, 162 + ),
213 - ), 163 + Container(
214 - child: Row( 164 + color: const Color(0xffFFFFFF),
215 - mainAxisSize: MainAxisSize.max, 165 + child: Padding(
216 - children: <Widget>[ 166 + padding: EdgeInsets.only(bottom: 5.px),
217 - Flexible( 167 + child: Column(
218 - child: TextField( 168 + crossAxisAlignment: CrossAxisAlignment.start,
219 - decoration: InputDecoration( 169 + mainAxisAlignment: MainAxisAlignment.start,
220 - hintText: ParlandoLocalizations.of( 170 + children: <Widget>[
221 - context) 171 + Padding(
222 - .accountEditPageUserNamePlaceholder, 172 + padding: EdgeInsets.only(
223 - ), 173 + left: 25.px,
224 - enabled: !_status, 174 + right: 25.px,
225 - autofocus: !_status, 175 + top: 5.px,
176 + ),
177 + child: Row(
178 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
179 + mainAxisSize: MainAxisSize.max,
180 + children: <Widget>[
181 + Column(
182 + mainAxisAlignment: MainAxisAlignment.start,
183 + mainAxisSize: MainAxisSize.min,
184 + children: <Widget>[
185 + Text(
186 + ParlandoLocalizations.of(context)
187 + .accountEditPageUserInfo,
188 + style: TextStyle(
189 + fontSize: 18.px,
190 + fontWeight: FontWeight.bold),
226 ), 191 ),
227 - ), 192 + ],
228 - ], 193 + ),
229 - )), 194 + Column(
230 - Padding( 195 + mainAxisAlignment: MainAxisAlignment.end,
231 - padding: EdgeInsets.only( 196 + mainAxisSize: MainAxisSize.min,
232 - left: 25.px, 197 + children: <Widget>[
233 - right: 25.px, 198 + _status ? _getEditIcon() : Container(),
234 - top: 25.px, 199 + ],
235 - ), 200 + )
236 - child: Row( 201 + ],
237 - mainAxisSize: MainAxisSize.max, 202 + )),
238 - children: <Widget>[ 203 + Padding(
239 - Column( 204 + padding: EdgeInsets.only(
240 - mainAxisAlignment: MainAxisAlignment.start, 205 + left: 25.px, right: 25.px, top: 25.px),
241 - mainAxisSize: MainAxisSize.min, 206 + child: Row(
242 - children: <Widget>[ 207 + mainAxisSize: MainAxisSize.max,
243 - Text( 208 + children: <Widget>[
244 - ParlandoLocalizations.of(context) 209 + Column(
245 - .accountEditPageUserEmail, 210 + mainAxisAlignment: MainAxisAlignment.start,
246 - style: TextStyle( 211 + mainAxisSize: MainAxisSize.min,
247 - fontSize: 16.px, 212 + children: <Widget>[
248 - fontWeight: FontWeight.bold), 213 + Text(
249 - ), 214 + ParlandoLocalizations.of(context)
250 - ], 215 + .accountEditPageUserName,
251 - ), 216 + style: TextStyle(
252 - ], 217 + fontSize: 16.px,
253 - )), 218 + fontWeight: FontWeight.bold),
254 - Padding(
255 - padding: EdgeInsets.only(
256 - left: 25.px,
257 - right: 25.px,
258 - top: 2.px,
259 - ),
260 - child: Row(
261 - mainAxisSize: MainAxisSize.max,
262 - children: <Widget>[
263 - Flexible(
264 - child: TextField(
265 - decoration: InputDecoration(
266 - hintText: ParlandoLocalizations.of(
267 - context)
268 - .accountEditPageUserEmailPlaceholder,
269 - ),
270 - enabled: !_status,
271 ), 219 ),
272 - ), 220 + ],
273 - ], 221 + ),
274 - )), 222 + ],
275 - Padding( 223 + )),
276 - padding: EdgeInsets.only( 224 + Padding(
277 - left: 25.px, 225 + padding: EdgeInsets.only(
278 - right: 25.px, 226 + left: 25.px,
279 - top: 25.px, 227 + right: 25.px,
280 - ), 228 + top: 2.px,
281 - child: Row( 229 + ),
282 - mainAxisSize: MainAxisSize.max, 230 + child: Row(
283 - children: <Widget>[ 231 + mainAxisSize: MainAxisSize.max,
284 - Column( 232 + children: <Widget>[
285 - mainAxisAlignment: MainAxisAlignment.start, 233 + Flexible(
286 - mainAxisSize: MainAxisSize.min, 234 + child: TextField(
287 - children: <Widget>[ 235 + decoration: InputDecoration(
288 - Text( 236 + hintText: ParlandoLocalizations.of(
289 - ParlandoLocalizations.of(context) 237 + context)
290 - .accountEditPageUserPhone, 238 + .accountEditPageUserNamePlaceholder,
291 - style: TextStyle(
292 - fontSize: 16.px,
293 - fontWeight: FontWeight.bold),
294 - ),
295 - ],
296 - ),
297 - ],
298 - )),
299 - Padding(
300 - padding: EdgeInsets.only(
301 - left: 25.px,
302 - right: 25.px,
303 - top: 2.px,
304 - ),
305 - child: Row(
306 - mainAxisSize: MainAxisSize.max,
307 - children: <Widget>[
308 - Flexible(
309 - child: TextField(
310 - decoration: InputDecoration(
311 - hintText: ParlandoLocalizations.of(
312 - context)
313 - .accountEditPageUserPhonePlaceholder,
314 - ),
315 - enabled: !_status,
316 ), 239 ),
240 + enabled: !_status,
241 + autofocus: !_status,
317 ), 242 ),
318 - ], 243 + ),
319 - )), 244 + ],
320 - Padding( 245 + )),
321 - padding: EdgeInsets.only( 246 + Padding(
322 - left: 25.px, 247 + padding: EdgeInsets.only(
323 - right: 25.px, 248 + left: 25.px,
324 - top: 25.px, 249 + right: 25.px,
325 - ), 250 + top: 25.px,
326 - child: Row( 251 + ),
327 - mainAxisSize: MainAxisSize.max, 252 + child: Row(
328 - mainAxisAlignment: MainAxisAlignment.start, 253 + mainAxisSize: MainAxisSize.max,
329 - children: <Widget>[ 254 + children: <Widget>[
330 - Expanded( 255 + Column(
331 - child: Text( 256 + mainAxisAlignment: MainAxisAlignment.start,
257 + mainAxisSize: MainAxisSize.min,
258 + children: <Widget>[
259 + Text(
332 ParlandoLocalizations.of(context) 260 ParlandoLocalizations.of(context)
333 - .accountEditPageUserGender, 261 + .accountEditPageUserEmail,
334 style: TextStyle( 262 style: TextStyle(
335 - fontSize: 16.px, 263 + fontSize: 16.px,
336 - fontWeight: FontWeight.bold, 264 + fontWeight: FontWeight.bold),
337 - ), 265 + ),
266 + ],
267 + ),
268 + ],
269 + )),
270 + Padding(
271 + padding: EdgeInsets.only(
272 + left: 25.px,
273 + right: 25.px,
274 + top: 2.px,
275 + ),
276 + child: Row(
277 + mainAxisSize: MainAxisSize.max,
278 + children: <Widget>[
279 + Flexible(
280 + child: TextField(
281 + decoration: InputDecoration(
282 + hintText: ParlandoLocalizations.of(
283 + context)
284 + .accountEditPageUserEmailPlaceholder,
338 ), 285 ),
339 - flex: 2, 286 + enabled: !_status,
340 ), 287 ),
341 - Expanded( 288 + ),
342 - child: Text( 289 + ],
290 + )),
291 + Padding(
292 + padding: EdgeInsets.only(
293 + left: 25.px,
294 + right: 25.px,
295 + top: 25.px,
296 + ),
297 + child: Row(
298 + mainAxisSize: MainAxisSize.max,
299 + children: <Widget>[
300 + Column(
301 + mainAxisAlignment: MainAxisAlignment.start,
302 + mainAxisSize: MainAxisSize.min,
303 + children: <Widget>[
304 + Text(
343 ParlandoLocalizations.of(context) 305 ParlandoLocalizations.of(context)
344 - .accountEditPageUserBirthday, 306 + .accountEditPageUserPhone,
345 style: TextStyle( 307 style: TextStyle(
346 - fontSize: 16.px, 308 + fontSize: 16.px,
347 - fontWeight: FontWeight.bold, 309 + fontWeight: FontWeight.bold),
348 - ),
349 ), 310 ),
350 - flex: 2, 311 + ],
312 + ),
313 + ],
314 + )),
315 + Padding(
316 + padding: EdgeInsets.only(
317 + left: 25.px,
318 + right: 25.px,
319 + top: 2.px,
320 + ),
321 + child: Row(
322 + mainAxisSize: MainAxisSize.max,
323 + children: <Widget>[
324 + Flexible(
325 + child: TextField(
326 + decoration: InputDecoration(
327 + hintText: ParlandoLocalizations.of(
328 + context)
329 + .accountEditPageUserPhonePlaceholder,
330 + ),
331 + enabled: !_status,
351 ), 332 ),
352 - ], 333 + ),
353 - )), 334 + ],
354 - Padding( 335 + )),
355 - padding: EdgeInsets.only( 336 + Padding(
356 - left: 25.px, 337 + padding: EdgeInsets.only(
357 - right: 25.px, 338 + left: 25.px,
358 - top: 2.px, 339 + right: 25.px,
359 - ), 340 + top: 25.px,
360 - child: Row( 341 + ),
361 - mainAxisSize: MainAxisSize.max, 342 + child: Row(
362 - mainAxisAlignment: MainAxisAlignment.start, 343 + mainAxisSize: MainAxisSize.max,
363 - children: <Widget>[ 344 + mainAxisAlignment: MainAxisAlignment.start,
364 - Flexible( 345 + children: <Widget>[
365 - child: Padding( 346 + Expanded(
366 - padding: EdgeInsets.only(right: 10.px), 347 + child: Text(
367 - child: TextField( 348 + ParlandoLocalizations.of(context)
368 - decoration: InputDecoration( 349 + .accountEditPageUserGender,
369 - hintText: ParlandoLocalizations.of( 350 + style: TextStyle(
370 - context) 351 + fontSize: 16.px,
371 - .accountEditPageUserGenderPlaceholder, 352 + fontWeight: FontWeight.bold,
372 - ), 353 + ),
373 - enabled: !_status, 354 + ),
374 - ), 355 + flex: 2,
356 + ),
357 + Expanded(
358 + child: Text(
359 + ParlandoLocalizations.of(context)
360 + .accountEditPageUserBirthday,
361 + style: TextStyle(
362 + fontSize: 16.px,
363 + fontWeight: FontWeight.bold,
375 ), 364 ),
376 - flex: 2,
377 ), 365 ),
378 - Flexible( 366 + flex: 2,
367 + ),
368 + ],
369 + )),
370 + Padding(
371 + padding: EdgeInsets.only(
372 + left: 25.px,
373 + right: 25.px,
374 + top: 2.px,
375 + ),
376 + child: Row(
377 + mainAxisSize: MainAxisSize.max,
378 + mainAxisAlignment: MainAxisAlignment.start,
379 + children: <Widget>[
380 + Flexible(
381 + child: Padding(
382 + padding: EdgeInsets.only(right: 10.px),
379 child: TextField( 383 child: TextField(
380 decoration: InputDecoration( 384 decoration: InputDecoration(
381 hintText: ParlandoLocalizations.of( 385 hintText: ParlandoLocalizations.of(
382 context) 386 context)
383 - .accountEditPageUserBirthdayPlaceholder, 387 + .accountEditPageUserGenderPlaceholder,
384 ), 388 ),
385 enabled: !_status, 389 enabled: !_status,
386 ), 390 ),
387 - flex: 2,
388 ), 391 ),
389 - ], 392 + flex: 2,
390 - )), 393 + ),
391 - !_status ? _getActionButtons() : Container(), 394 + Flexible(
392 - ], 395 + child: TextField(
393 - ), 396 + decoration: InputDecoration(
397 + hintText: ParlandoLocalizations.of(
398 + context)
399 + .accountEditPageUserBirthdayPlaceholder,
400 + ),
401 + enabled: !_status,
402 + ),
403 + flex: 2,
404 + ),
405 + ],
406 + )),
407 + !_status ? _getActionButtons() : Container(),
408 + ],
394 ), 409 ),
395 - ) 410 + ),
396 - ], 411 + )
397 - ), 412 + ],
398 - ], 413 + ),
399 - ), 414 + ],
400 - )); 415 + ),
416 + ),
417 + );
401 } 418 }
402 419
403 @override 420 @override
...@@ -473,6 +490,48 @@ class MapScreenState extends State<AccountEditPage> ...@@ -473,6 +490,48 @@ class MapScreenState extends State<AccountEditPage>
473 }, 490 },
474 ); 491 );
475 } 492 }
493 +
494 + Future<void> updateAvatar(String path) async {
495 + isUpdateAvatar = true;
496 + dynamic avatar = await MultipartFile.fromFile(path, filename: "avatar.png");
497 + Map<String, dynamic> map = <String, dynamic>{
498 + "image": avatar,
499 + };
500 + FormData formData = FormData.fromMap(map);
501 + DioUtils.instance.asyncRequestNetwork<UploadEntity>(
502 + Method.post,
503 + HttpApi.uploadImage,
504 + params: formData,
505 + onSuccess: (data) {
506 + String path = data!.data!.relativePath!;
507 +
508 + Map<String, String> params = <String, String>{
509 + "avatar": path,
510 + };
511 + DioUtils.instance.asyncRequestNetwork<UploadAvatarEntity>(
512 + Method.post,
513 + HttpApi.avatar,
514 + params: params,
515 + onSuccess: (data) {
516 + isUpdateAvatar = false;
517 + setState(() {
518 + _imageFile = data!.data!.avatar!;
519 + });
520 + Toast.show("头像更新成功");
521 + },
522 + onError: (code, msg) {
523 + Toast.show(msg.toString());
524 + isUpdateAvatar = false;
525 + setState(() {});
526 + },
527 + );
528 + },
529 + onError: (code, msg) {
530 + isUpdateAvatar = false;
531 + setState(() {});
532 + },
533 + );
534 + }
476 } 535 }
477 536
478 typedef CapturedImageFile = String Function(String); 537 typedef CapturedImageFile = String Function(String);
......
...@@ -3,6 +3,7 @@ import 'package:Parlando/account/view_models/account_view_model.dart'; ...@@ -3,6 +3,7 @@ import 'package:Parlando/account/view_models/account_view_model.dart';
3 import 'package:Parlando/apis/api_response.dart'; 3 import 'package:Parlando/apis/api_response.dart';
4 import 'package:Parlando/login/login_router.dart'; 4 import 'package:Parlando/login/login_router.dart';
5 import 'package:Parlando/res/constant.dart'; 5 import 'package:Parlando/res/constant.dart';
6 +import 'package:cached_network_image/cached_network_image.dart';
6 import 'package:flustars/flustars.dart'; 7 import 'package:flustars/flustars.dart';
7 import 'package:flutter/material.dart'; 8 import 'package:flutter/material.dart';
8 import 'package:Parlando/membership/membership_router.dart'; 9 import 'package:Parlando/membership/membership_router.dart';
...@@ -98,9 +99,12 @@ class _AccountPageState extends State<AccountPage> { ...@@ -98,9 +99,12 @@ class _AccountPageState extends State<AccountPage> {
98 ), 99 ),
99 ), 100 ),
100 child: ClipOval( 101 child: ClipOval(
101 - child: Image.network( 102 + child: CachedNetworkImage(
102 - "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
103 fit: BoxFit.cover, 103 fit: BoxFit.cover,
104 + placeholder: (context, url) =>
105 + const CircularProgressIndicator(),
106 + errorWidget: (context, url, error) => const Icon(Icons.error),
107 + imageUrl: _user.avatar!,
104 ), 108 ),
105 ), 109 ),
106 ), 110 ),
......
...@@ -17,7 +17,7 @@ class AccountViewProvider with ChangeNotifier { ...@@ -17,7 +17,7 @@ class AccountViewProvider with ChangeNotifier {
17 } 17 }
18 18
19 Future<void> fetchAccountData(String value) async { 19 Future<void> fetchAccountData(String value) async {
20 - _apiResponse = ApiResponse.loading('Fetching artist data'); 20 + _apiResponse = ApiResponse.loading('请求数据中...');
21 DioUtils.instance.asyncRequestNetwork<UserEntity>( 21 DioUtils.instance.asyncRequestNetwork<UserEntity>(
22 Method.get, 22 Method.get,
23 HttpApi.user, 23 HttpApi.user,
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
4 4
5 // This file is automatically generated. DO NOT EDIT, all your changes would be lost. 5 // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
6 import 'package:flutter/material.dart'; 6 import 'package:flutter/material.dart';
7 +import 'package:Parlando/account/models/upload_avatar_entity.dart';
7 import 'package:Parlando/account/models/user_entity.dart'; 8 import 'package:Parlando/account/models/user_entity.dart';
8 import 'package:Parlando/category/models/category_item_entity.dart'; 9 import 'package:Parlando/category/models/category_item_entity.dart';
9 import 'package:Parlando/home/models/setting_entity.dart'; 10 import 'package:Parlando/home/models/setting_entity.dart';
...@@ -18,17 +19,20 @@ typedef JsonConvertFunction<T> = T Function(Map<String, dynamic> json); ...@@ -18,17 +19,20 @@ typedef JsonConvertFunction<T> = T Function(Map<String, dynamic> json);
18 19
19 class JsonConvert { 20 class JsonConvert {
20 static final Map<String, JsonConvertFunction> _convertFuncMap = { 21 static final Map<String, JsonConvertFunction> _convertFuncMap = {
21 - (UserEntity).toString(): UserEntity.fromJson, 22 + (UploadAvatarEntity).toString(): UploadAvatarEntity.fromJson,
22 - (UserData).toString(): UserData.fromJson, 23 + (UploadAvatarData).toString(): UploadAvatarData.fromJson,
23 - (UserError).toString(): UserError.fromJson, 24 + (UploadAvatarError).toString(): UploadAvatarError.fromJson,
24 - (CategoryItemEntity).toString(): CategoryItemEntity.fromJson, 25 + (UserEntity).toString(): UserEntity.fromJson,
25 - (SettingEntity).toString(): SettingEntity.fromJson, 26 + (UserData).toString(): UserData.fromJson,
26 - (SettingData).toString(): SettingData.fromJson, 27 + (UserError).toString(): UserError.fromJson,
27 - (SettingDataLoginSetting).toString(): SettingDataLoginSetting.fromJson, 28 + (CategoryItemEntity).toString(): CategoryItemEntity.fromJson,
28 - (SettingError).toString(): SettingError.fromJson, 29 + (SettingEntity).toString(): SettingEntity.fromJson,
29 - (AuthEntity).toString(): AuthEntity.fromJson, 30 + (SettingData).toString(): SettingData.fromJson,
30 - (AuthData).toString(): AuthData.fromJson, 31 + (SettingDataLoginSetting).toString(): SettingDataLoginSetting.fromJson,
31 - (AuthError).toString(): AuthError.fromJson, 32 + (SettingError).toString(): SettingError.fromJson,
33 + (AuthEntity).toString(): AuthEntity.fromJson,
34 + (AuthData).toString(): AuthData.fromJson,
35 + (AuthError).toString(): AuthError.fromJson,
32 (UploadEntity).toString(): UploadEntity.fromJson, 36 (UploadEntity).toString(): UploadEntity.fromJson,
33 (UploadData).toString(): UploadData.fromJson, 37 (UploadData).toString(): UploadData.fromJson,
34 (UploadError).toString(): UploadError.fromJson, 38 (UploadError).toString(): UploadError.fromJson,
...@@ -114,73 +118,97 @@ class JsonConvert { ...@@ -114,73 +118,97 @@ class JsonConvert {
114 118
115 //list is returned by type 119 //list is returned by type
116 static M? _getListChildType<M>(List<Map<String, dynamic>> data) { 120 static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
117 - if(<UserEntity>[] is M){ 121 + if (<UploadAvatarEntity>[] is M) {
118 - return data.map<UserEntity>((Map<String, dynamic> e) => UserEntity.fromJson(e)).toList() as M; 122 + return data
119 - } 123 + .map<UploadAvatarEntity>(
120 - if(<UserData>[] is M){ 124 + (Map<String, dynamic> e) => UploadAvatarEntity.fromJson(e))
121 - return data.map<UserData>((Map<String, dynamic> e) => UserData.fromJson(e)).toList() as M; 125 + .toList() as M;
122 - } 126 + }
123 - if(<UserError>[] is M){ 127 + if (<UploadAvatarData>[] is M) {
124 - return data.map<UserError>((Map<String, dynamic> e) => UserError.fromJson(e)).toList() as M; 128 + return data
125 - } 129 + .map<UploadAvatarData>(
126 - if(<CategoryItemEntity>[] is M){ 130 + (Map<String, dynamic> e) => UploadAvatarData.fromJson(e))
127 - return data.map<CategoryItemEntity>((Map<String, dynamic> e) => CategoryItemEntity.fromJson(e)).toList() as M; 131 + .toList() as M;
128 - } 132 + }
129 - if(<SettingEntity>[] is M){ 133 + if (<UploadAvatarError>[] is M) {
130 - return data.map<SettingEntity>((Map<String, dynamic> e) => SettingEntity.fromJson(e)).toList() as M; 134 + return data
131 - } 135 + .map<UploadAvatarError>(
132 - if(<SettingData>[] is M){ 136 + (Map<String, dynamic> e) => UploadAvatarError.fromJson(e))
133 - return data.map<SettingData>((Map<String, dynamic> e) => SettingData.fromJson(e)).toList() as M; 137 + .toList() as M;
134 - } 138 + }
135 - if(<SettingDataLoginSetting>[] is M){ 139 + if (<UserEntity>[] is M) {
136 - return data.map<SettingDataLoginSetting>((Map<String, dynamic> e) => SettingDataLoginSetting.fromJson(e)).toList() as M; 140 + return data
137 - } 141 + .map<UserEntity>((Map<String, dynamic> e) => UserEntity.fromJson(e))
138 - if(<SettingError>[] is M){ 142 + .toList() as M;
139 - return data.map<SettingError>((Map<String, dynamic> e) => SettingError.fromJson(e)).toList() as M; 143 + }
140 - } 144 + if (<UserData>[] is M) {
141 - if(<AuthEntity>[] is M){ 145 + return data
142 - return data.map<AuthEntity>((Map<String, dynamic> e) => AuthEntity.fromJson(e)).toList() as M; 146 + .map<UserData>((Map<String, dynamic> e) => UserData.fromJson(e))
143 - } 147 + .toList() as M;
144 - if(<AuthData>[] is M){ 148 + }
145 - return data.map<AuthData>((Map<String, dynamic> e) => AuthData.fromJson(e)).toList() as M; 149 + if (<UserError>[] is M) {
146 - } 150 + return data
147 - if(<AuthError>[] is M){ 151 + .map<UserError>((Map<String, dynamic> e) => UserError.fromJson(e))
148 - return data.map<AuthError>((Map<String, dynamic> e) => AuthError.fromJson(e)).toList() as M; 152 + .toList() as M;
149 - } 153 + }
150 - if(<UploadEntity>[] is M){ 154 + if (<CategoryItemEntity>[] is M) {
151 - return data.map<UploadEntity>((Map<String, dynamic> e) => UploadEntity.fromJson(e)).toList() as M; 155 + return data.map<CategoryItemEntity>((Map<String, dynamic> e) => CategoryItemEntity.fromJson(e)).toList() as M;
152 - } 156 + }
153 - if(<UploadData>[] is M){ 157 + if(<SettingEntity>[] is M){
154 - return data.map<UploadData>((Map<String, dynamic> e) => UploadData.fromJson(e)).toList() as M; 158 + return data.map<SettingEntity>((Map<String, dynamic> e) => SettingEntity.fromJson(e)).toList() as M;
155 - } 159 + }
156 - if(<UploadError>[] is M){ 160 + if(<SettingData>[] is M){
157 - return data.map<UploadError>((Map<String, dynamic> e) => UploadError.fromJson(e)).toList() as M; 161 + return data.map<SettingData>((Map<String, dynamic> e) => SettingData.fromJson(e)).toList() as M;
158 - } 162 + }
159 - if(<LangSortEntity>[] is M){ 163 + if(<SettingDataLoginSetting>[] is M){
160 - return data.map<LangSortEntity>((Map<String, dynamic> e) => LangSortEntity.fromJson(e)).toList() as M; 164 + return data.map<SettingDataLoginSetting>((Map<String, dynamic> e) => SettingDataLoginSetting.fromJson(e)).toList() as M;
161 - } 165 + }
162 - if(<SearchEntity>[] is M){ 166 + if(<SettingError>[] is M){
163 - return data.map<SearchEntity>((Map<String, dynamic> e) => SearchEntity.fromJson(e)).toList() as M; 167 + return data.map<SettingError>((Map<String, dynamic> e) => SettingError.fromJson(e)).toList() as M;
164 - } 168 + }
165 - if(<SearchItems>[] is M){ 169 + if(<AuthEntity>[] is M){
166 - return data.map<SearchItems>((Map<String, dynamic> e) => SearchItems.fromJson(e)).toList() as M; 170 + return data.map<AuthEntity>((Map<String, dynamic> e) => AuthEntity.fromJson(e)).toList() as M;
167 - } 171 + }
168 - if(<SearchItemsOwner>[] is M){ 172 + if(<AuthData>[] is M){
169 - return data.map<SearchItemsOwner>((Map<String, dynamic> e) => SearchItemsOwner.fromJson(e)).toList() as M; 173 + return data.map<AuthData>((Map<String, dynamic> e) => AuthData.fromJson(e)).toList() as M;
170 - } 174 + }
171 - if(<SearchItemsLicense>[] is M){ 175 + if(<AuthError>[] is M){
172 - return data.map<SearchItemsLicense>((Map<String, dynamic> e) => SearchItemsLicense.fromJson(e)).toList() as M; 176 + return data.map<AuthError>((Map<String, dynamic> e) => AuthError.fromJson(e)).toList() as M;
173 - } 177 + }
174 - if(<FriendEntity>[] is M){ 178 + if(<UploadEntity>[] is M){
175 - return data.map<FriendEntity>((Map<String, dynamic> e) => FriendEntity.fromJson(e)).toList() as M; 179 + return data.map<UploadEntity>((Map<String, dynamic> e) => UploadEntity.fromJson(e)).toList() as M;
176 - } 180 + }
177 - if(<FriendData>[] is M){ 181 + if(<UploadData>[] is M){
178 - return data.map<FriendData>((Map<String, dynamic> e) => FriendData.fromJson(e)).toList() as M; 182 + return data.map<UploadData>((Map<String, dynamic> e) => UploadData.fromJson(e)).toList() as M;
179 - } 183 + }
184 + if(<UploadError>[] is M){
185 + return data.map<UploadError>((Map<String, dynamic> e) => UploadError.fromJson(e)).toList() as M;
186 + }
187 + if(<LangSortEntity>[] is M){
188 + return data.map<LangSortEntity>((Map<String, dynamic> e) => LangSortEntity.fromJson(e)).toList() as M;
189 + }
190 + if(<SearchEntity>[] is M){
191 + return data.map<SearchEntity>((Map<String, dynamic> e) => SearchEntity.fromJson(e)).toList() as M;
192 + }
193 + if(<SearchItems>[] is M){
194 + return data.map<SearchItems>((Map<String, dynamic> e) => SearchItems.fromJson(e)).toList() as M;
195 + }
196 + if(<SearchItemsOwner>[] is M){
197 + return data.map<SearchItemsOwner>((Map<String, dynamic> e) => SearchItemsOwner.fromJson(e)).toList() as M;
198 + }
199 + if(<SearchItemsLicense>[] is M){
200 + return data.map<SearchItemsLicense>((Map<String, dynamic> e) => SearchItemsLicense.fromJson(e)).toList() as M;
201 + }
202 + if(<FriendEntity>[] is M){
203 + return data.map<FriendEntity>((Map<String, dynamic> e) => FriendEntity.fromJson(e)).toList() as M;
204 + }
205 + if(<FriendData>[] is M){
206 + return data.map<FriendData>((Map<String, dynamic> e) => FriendData.fromJson(e)).toList() as M;
207 + }
208 +
209 + debugPrint("${M.toString()} not found");
180 210
181 - debugPrint("${M.toString()} not found"); 211 + return null;
182 -
183 - return null;
184 } 212 }
185 213
186 static M? fromJsonAsT<M>(dynamic json) { 214 static M? fromJsonAsT<M>(dynamic json) {
......
1 +import 'package:Parlando/generated/json/base/json_convert_content.dart';
2 +import 'package:Parlando/account/models/upload_avatar_entity.dart';
3 +
4 +UploadAvatarEntity $UploadAvatarEntityFromJson(Map<String, dynamic> json) {
5 + final UploadAvatarEntity uploadAvatarEntity = UploadAvatarEntity();
6 + final String? status = jsonConvert.convert<String>(json['status']);
7 + if (status != null) {
8 + uploadAvatarEntity.status = status;
9 + }
10 + final int? code = jsonConvert.convert<int>(json['code']);
11 + if (code != null) {
12 + uploadAvatarEntity.code = code;
13 + }
14 + final String? message = jsonConvert.convert<String>(json['message']);
15 + if (message != null) {
16 + uploadAvatarEntity.message = message;
17 + }
18 + final UploadAvatarData? data =
19 + jsonConvert.convert<UploadAvatarData>(json['data']);
20 + if (data != null) {
21 + uploadAvatarEntity.data = data;
22 + }
23 + final UploadAvatarError? error =
24 + jsonConvert.convert<UploadAvatarError>(json['error']);
25 + if (error != null) {
26 + uploadAvatarEntity.error = error;
27 + }
28 + return uploadAvatarEntity;
29 +}
30 +
31 +Map<String, dynamic> $UploadAvatarEntityToJson(UploadAvatarEntity entity) {
32 + final Map<String, dynamic> data = <String, dynamic>{};
33 + data['status'] = entity.status;
34 + data['code'] = entity.code;
35 + data['message'] = entity.message;
36 + data['data'] = entity.data?.toJson();
37 + data['error'] = entity.error?.toJson();
38 + return data;
39 +}
40 +
41 +UploadAvatarData $UploadAvatarDataFromJson(Map<String, dynamic> json) {
42 + final UploadAvatarData uploadAvatarData = UploadAvatarData();
43 + final String? avatar = jsonConvert.convert<String>(json['avatar']);
44 + if (avatar != null) {
45 + uploadAvatarData.avatar = avatar;
46 + }
47 + return uploadAvatarData;
48 +}
49 +
50 +Map<String, dynamic> $UploadAvatarDataToJson(UploadAvatarData entity) {
51 + final Map<String, dynamic> data = <String, dynamic>{};
52 + data['avatar'] = entity.avatar;
53 + return data;
54 +}
55 +
56 +UploadAvatarError $UploadAvatarErrorFromJson(Map<String, dynamic> json) {
57 + final UploadAvatarError uploadAvatarError = UploadAvatarError();
58 + return uploadAvatarError;
59 +}
60 +
61 +Map<String, dynamic> $UploadAvatarErrorToJson(UploadAvatarError entity) {
62 + final Map<String, dynamic> data = <String, dynamic>{};
63 + return data;
64 +}
...@@ -4,7 +4,9 @@ class HttpApi { ...@@ -4,7 +4,9 @@ class HttpApi {
4 static const String verify = 'verify'; 4 static const String verify = 'verify';
5 static const String login = 'login'; 5 static const String login = 'login';
6 static const String uploadVideo = 'upload/video'; 6 static const String uploadVideo = 'upload/video';
7 + static const String uploadImage = 'upload/image';
7 static const String immersive = 'immersive'; 8 static const String immersive = 'immersive';
9 + static const String avatar = 'avatar';
8 static const String user = 'user'; 10 static const String user = 'user';
9 static const String search = 'search/repositories'; 11 static const String search = 'search/repositories';
10 static const String subscriptions = 'users/simplezhli/subscriptions'; 12 static const String subscriptions = 'users/simplezhli/subscriptions';
......
...@@ -215,7 +215,7 @@ class _PoemPublishState extends State<PoemPublish> { ...@@ -215,7 +215,7 @@ class _PoemPublishState extends State<PoemPublish> {
215 final directory = await getApplicationDocumentsDirectory(); 215 final directory = await getApplicationDocumentsDirectory();
216 dynamic video = await MultipartFile.fromFile( 216 dynamic video = await MultipartFile.fromFile(
217 directory.path + "/" + widget.data, 217 directory.path + "/" + widget.data,
218 - filename: "xxx23.png"); 218 + filename: "video.mp4");
219 return video; 219 return video;
220 } 220 }
221 221
......