Showing
4 changed files
with
104 additions
and
7 deletions
... | @@ -114,6 +114,36 @@ class DioUtils { | ... | @@ -114,6 +114,36 @@ class DioUtils { |
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
117 | + // 数据返回格式统一,统一处理异常 | ||
118 | + Future<BaseEntity<T>> _upload<T>( | ||
119 | + String method, | ||
120 | + String url, { | ||
121 | + Object? data, | ||
122 | + Map<String, dynamic>? queryParameters, | ||
123 | + CancelToken? cancelToken, | ||
124 | + ProgressCallback? progressCallback, | ||
125 | + Options? options, | ||
126 | + }) async { | ||
127 | + final Response<String> response = await _dio.post<String>( | ||
128 | + url, | ||
129 | + data: data, | ||
130 | + queryParameters: queryParameters, | ||
131 | + options: _checkOptions(method, options), | ||
132 | + cancelToken: cancelToken, | ||
133 | + onSendProgress: progressCallback, | ||
134 | + ); | ||
135 | + try { | ||
136 | + final String data = response.data.toString(); | ||
137 | + final bool isCompute = !Constant.isDriverTest && data.length > 10 * 1024; | ||
138 | + final Map<String, dynamic> map = | ||
139 | + isCompute ? await compute(parseData, data) : parseData(data); | ||
140 | + return BaseEntity<T>.fromJson(map); | ||
141 | + } catch (e) { | ||
142 | + debugPrint(e.toString()); | ||
143 | + return BaseEntity<T>(ExceptionHandle.parse_error, '数据解析错误!', null); | ||
144 | + } | ||
145 | + } | ||
146 | + | ||
117 | Options _checkOptions(String method, Options? options) { | 147 | Options _checkOptions(String method, Options? options) { |
118 | options ??= Options(); | 148 | options ??= Options(); |
119 | options.method = method; | 149 | options.method = method; |
... | @@ -178,6 +208,41 @@ class DioUtils { | ... | @@ -178,6 +208,41 @@ class DioUtils { |
178 | } | 208 | } |
179 | 209 | ||
180 | /// 统一处理(onSuccess返回T对象,onSuccessList返回 List<T>) | 210 | /// 统一处理(onSuccess返回T对象,onSuccessList返回 List<T>) |
211 | + void asyncUploadFile<T>( | ||
212 | + Method method, | ||
213 | + String url, { | ||
214 | + NetSuccessCallback<T?>? onSuccess, | ||
215 | + NetErrorCallback? onError, | ||
216 | + Object? params, | ||
217 | + Map<String, dynamic>? queryParameters, | ||
218 | + CancelToken? cancelToken, | ||
219 | + ProgressCallback? progressCallback, | ||
220 | + Options? options, | ||
221 | + }) { | ||
222 | + Stream.fromFuture(_upload<T>( | ||
223 | + method.value, | ||
224 | + url, | ||
225 | + data: params, | ||
226 | + queryParameters: queryParameters, | ||
227 | + options: options, | ||
228 | + cancelToken: cancelToken, | ||
229 | + progressCallback: progressCallback, | ||
230 | + )).asBroadcastStream().listen((result) { | ||
231 | + if (result.code == 0) { | ||
232 | + if (onSuccess != null) { | ||
233 | + onSuccess(result.data); | ||
234 | + } | ||
235 | + } else { | ||
236 | + _onError(result.code, result.message, onError); | ||
237 | + } | ||
238 | + }, onError: (dynamic e) { | ||
239 | + _cancelLogPrint(e, url); | ||
240 | + final NetError error = ExceptionHandle.handleException(e); | ||
241 | + _onError(error.code, error.msg, onError); | ||
242 | + }); | ||
243 | + } | ||
244 | + | ||
245 | + /// 统一处理(onSuccess返回T对象,onSuccessList返回 List<T>) | ||
181 | void asyncRequestNetwork<T>( | 246 | void asyncRequestNetwork<T>( |
182 | Method method, | 247 | Method method, |
183 | String url, { | 248 | String url, { | ... | ... |
... | @@ -14,6 +14,7 @@ import 'package:Parlando/routers/routers.dart'; | ... | @@ -14,6 +14,7 @@ import 'package:Parlando/routers/routers.dart'; |
14 | import 'package:Parlando/widgets/my_app_bar.dart'; | 14 | import 'package:Parlando/widgets/my_app_bar.dart'; |
15 | 15 | ||
16 | import 'package:Parlando/extension/int_extension.dart'; | 16 | import 'package:Parlando/extension/int_extension.dart'; |
17 | +import 'package:getwidget/getwidget.dart'; | ||
17 | import 'package:path_provider/path_provider.dart'; | 18 | import 'package:path_provider/path_provider.dart'; |
18 | 19 | ||
19 | import '../poem_router.dart'; | 20 | import '../poem_router.dart'; |
... | @@ -36,13 +37,14 @@ class PoemPublish extends StatefulWidget { | ... | @@ -36,13 +37,14 @@ class PoemPublish extends StatefulWidget { |
36 | 37 | ||
37 | class PoemPublishState extends State<PoemPublish> { | 38 | class PoemPublishState extends State<PoemPublish> { |
38 | bool isPublishing = false; | 39 | bool isPublishing = false; |
40 | + bool isUploading = false; | ||
39 | String _langSortName = "普通话"; | 41 | String _langSortName = "普通话"; |
40 | int _langSortId = 1; //TODO 传入服务器的口音ID | 42 | int _langSortId = 1; //TODO 传入服务器的口音ID |
41 | String _address = '我在此地'; | 43 | String _address = '我在此地'; |
42 | String _longitude = ""; | 44 | String _longitude = ""; |
43 | String _latitude = ""; | 45 | String _latitude = ""; |
44 | final LangSortProvider _provider = LangSortProvider(); | 46 | final LangSortProvider _provider = LangSortProvider(); |
45 | - | 47 | + final ValueNotifier<double> _counter = ValueNotifier<double>(0.0); |
46 | final TextEditingController _msgController = TextEditingController(); | 48 | final TextEditingController _msgController = TextEditingController(); |
47 | 49 | ||
48 | @override | 50 | @override |
... | @@ -52,8 +54,9 @@ class PoemPublishState extends State<PoemPublish> { | ... | @@ -52,8 +54,9 @@ class PoemPublishState extends State<PoemPublish> { |
52 | 54 | ||
53 | @override | 55 | @override |
54 | void dispose() { | 56 | void dispose() { |
55 | - super.dispose(); | 57 | + _counter.dispose(); |
56 | _provider.dispose(); | 58 | _provider.dispose(); |
59 | + super.dispose(); | ||
57 | } | 60 | } |
58 | 61 | ||
59 | @override | 62 | @override |
... | @@ -203,6 +206,16 @@ class PoemPublishState extends State<PoemPublish> { | ... | @@ -203,6 +206,16 @@ class PoemPublishState extends State<PoemPublish> { |
203 | color: Colors.black54, fontSize: 15.px), | 206 | color: Colors.black54, fontSize: 15.px), |
204 | ), | 207 | ), |
205 | ), | 208 | ), |
209 | + Gaps.vGap10, | ||
210 | + isUploading | ||
211 | + ? Padding( | ||
212 | + padding: const EdgeInsets.all(20), | ||
213 | + child: ValueListenableBuilder<double>( | ||
214 | + builder: _buildWithValue, | ||
215 | + valueListenable: _counter, | ||
216 | + ), | ||
217 | + ) | ||
218 | + : Container(), | ||
206 | ], | 219 | ], |
207 | ), | 220 | ), |
208 | ), | 221 | ), |
... | @@ -222,6 +235,21 @@ class PoemPublishState extends State<PoemPublish> { | ... | @@ -222,6 +235,21 @@ class PoemPublishState extends State<PoemPublish> { |
222 | ); | 235 | ); |
223 | } | 236 | } |
224 | 237 | ||
238 | + Widget _buildWithValue(BuildContext context, double value, Widget? child) { | ||
239 | + return GFProgressBar( | ||
240 | + percentage: value, | ||
241 | + lineHeight: 10, | ||
242 | + alignment: MainAxisAlignment.spaceBetween, | ||
243 | + backgroundColor: Colors.black26, | ||
244 | + progressBarColor: GFColors.INFO, | ||
245 | + child: Text( | ||
246 | + "${(value * 100).toStringAsFixed(1)}%", | ||
247 | + textAlign: TextAlign.end, | ||
248 | + style: const TextStyle(fontSize: 8, color: Colors.white), | ||
249 | + ), | ||
250 | + ); | ||
251 | + } | ||
252 | + | ||
225 | Future<dynamic> _getUploadVideo() async { | 253 | Future<dynamic> _getUploadVideo() async { |
226 | final directory = await getApplicationDocumentsDirectory(); | 254 | final directory = await getApplicationDocumentsDirectory(); |
227 | dynamic video = await MultipartFile.fromFile( | 255 | dynamic video = await MultipartFile.fromFile( |
... | @@ -237,6 +265,7 @@ class PoemPublishState extends State<PoemPublish> { | ... | @@ -237,6 +265,7 @@ class PoemPublishState extends State<PoemPublish> { |
237 | } | 265 | } |
238 | 266 | ||
239 | isPublishing = true; | 267 | isPublishing = true; |
268 | + isUploading = true; | ||
240 | setState(() {}); | 269 | setState(() {}); |
241 | 270 | ||
242 | _getUploadVideo().then((value) { | 271 | _getUploadVideo().then((value) { |
... | @@ -244,14 +273,17 @@ class PoemPublishState extends State<PoemPublish> { | ... | @@ -244,14 +273,17 @@ class PoemPublishState extends State<PoemPublish> { |
244 | "video": value, | 273 | "video": value, |
245 | }; | 274 | }; |
246 | FormData formData = FormData.fromMap(map); | 275 | FormData formData = FormData.fromMap(map); |
247 | - DioUtils.instance.asyncRequestNetwork<UploadEntity>( | 276 | + DioUtils.instance.asyncUploadFile<UploadEntity>( |
248 | Method.post, | 277 | Method.post, |
249 | HttpApi.uploadVideo, | 278 | HttpApi.uploadVideo, |
250 | params: formData, | 279 | params: formData, |
280 | + progressCallback: (int count, int data) { | ||
281 | + _counter.value = count / data; | ||
282 | + }, | ||
251 | onSuccess: (data) { | 283 | onSuccess: (data) { |
252 | String path = data!.data!.relativePath!; | 284 | String path = data!.data!.relativePath!; |
253 | String videoId = '${widget.id}'; | 285 | String videoId = '${widget.id}'; |
254 | - | 286 | + isUploading = false; |
255 | Map<String, String> params = <String, String>{ | 287 | Map<String, String> params = <String, String>{ |
256 | "item_id": videoId, | 288 | "item_id": videoId, |
257 | "item_url": path, | 289 | "item_url": path, | ... | ... |
... | @@ -9,10 +9,10 @@ class AddressSelectPage extends StatefulWidget { | ... | @@ -9,10 +9,10 @@ class AddressSelectPage extends StatefulWidget { |
9 | const AddressSelectPage({Key? key}) : super(key: key); | 9 | const AddressSelectPage({Key? key}) : super(key: key); |
10 | 10 | ||
11 | @override | 11 | @override |
12 | - _AddressSelectPageState createState() => _AddressSelectPageState(); | 12 | + AddressSelectPageState createState() => AddressSelectPageState(); |
13 | } | 13 | } |
14 | 14 | ||
15 | -class _AddressSelectPageState extends State<AddressSelectPage> { | 15 | +class AddressSelectPageState extends State<AddressSelectPage> { |
16 | List<PoiSearch> _list = []; | 16 | List<PoiSearch> _list = []; |
17 | int _index = 0; | 17 | int _index = 0; |
18 | final ScrollController _controller = ScrollController(); | 18 | final ScrollController _controller = ScrollController(); | ... | ... |
... | @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev | ... | @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev |
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. | 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. |
16 | # Read more about iOS versioning at | 16 | # Read more about iOS versioning at |
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html |
18 | -version: 1.0.0+5 | 18 | +version: 1.0.0+6 |
19 | 19 | ||
20 | environment: | 20 | environment: |
21 | sdk: ">=2.16.2 <3.0.0" | 21 | sdk: ">=2.16.2 <3.0.0" | ... | ... |
-
Please register or login to post a comment