Showing
16 changed files
with
864 additions
and
331 deletions
| @@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
| 7 | additional functionality it is fine to subclass or reimplement | 7 | additional functionality it is fine to subclass or reimplement |
| 8 | FlutterApplication and put your custom class here. --> | 8 | FlutterApplication and put your custom class here. --> |
| 9 | 9 | ||
| 10 | + | ||
| 10 | <uses-permission android:name="android.permission.READ_CONTACTS" /> | 11 | <uses-permission android:name="android.permission.READ_CONTACTS" /> |
| 11 | <uses-permission android:name="android.permission.WRITE_CONTACTS" /> | 12 | <uses-permission android:name="android.permission.WRITE_CONTACTS" /> |
| 12 | <uses-permission android:name="android.permission.READ_CONTACTS"/> | 13 | <uses-permission android:name="android.permission.READ_CONTACTS"/> |
assets/delete.png
0 → 100644
752 Bytes
| @@ -50,6 +50,8 @@ | @@ -50,6 +50,8 @@ | ||
| 50 | <key>NSAllowsArbitraryLoads</key> | 50 | <key>NSAllowsArbitraryLoads</key> |
| 51 | <true/> | 51 | <true/> |
| 52 | </dict> | 52 | </dict> |
| 53 | + <key>NSPhotoLibraryUsageDescription</key> | ||
| 54 | + <string>需要您的同意,APP才能访问您的相册来上传图片</string> | ||
| 53 | <key>NSAppleMusicUsageDescription</key> | 55 | <key>NSAppleMusicUsageDescription</key> |
| 54 | <string>需要您的同意,APP才能访问媒体资料库</string> | 56 | <string>需要您的同意,APP才能访问媒体资料库</string> |
| 55 | <key>NSCalendarsUsageDescription</key> | 57 | <key>NSCalendarsUsageDescription</key> |
lib/models/qiniu_info_model.dart
0 → 100644
| 1 | +import 'package:json_annotation/json_annotation.dart'; | ||
| 2 | + | ||
| 3 | +part 'qiniu_info_model.g.dart'; | ||
| 4 | + | ||
| 5 | +@JsonSerializable() | ||
| 6 | +class QiniuInfoModel extends Object { | ||
| 7 | + @JsonKey(name: 'ret') | ||
| 8 | + int ret; | ||
| 9 | + | ||
| 10 | + @JsonKey(name: 'data') | ||
| 11 | + QiniuInfoSunModel data; | ||
| 12 | + | ||
| 13 | + @JsonKey(name: 'msg') | ||
| 14 | + String msg; | ||
| 15 | + | ||
| 16 | + QiniuInfoModel( | ||
| 17 | + this.ret, | ||
| 18 | + this.data, | ||
| 19 | + this.msg, | ||
| 20 | + ); | ||
| 21 | + | ||
| 22 | + factory QiniuInfoModel.fromJson(Map<String, dynamic> srcJson) => | ||
| 23 | + _$QiniuInfoModelFromJson(srcJson); | ||
| 24 | + | ||
| 25 | + Map<String, dynamic> toJson() => _$QiniuInfoModelToJson(this); | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +@JsonSerializable() | ||
| 29 | +class QiniuInfoSunModel extends Object { | ||
| 30 | + @JsonKey(name: 'token') | ||
| 31 | + String token; | ||
| 32 | + | ||
| 33 | + @JsonKey(name: 'domain') | ||
| 34 | + String domain; | ||
| 35 | + | ||
| 36 | + QiniuInfoSunModel( | ||
| 37 | + this.token, | ||
| 38 | + this.domain, | ||
| 39 | + ); | ||
| 40 | + | ||
| 41 | + factory QiniuInfoSunModel.fromJson(Map<String, dynamic> srcJson) => | ||
| 42 | + _$QiniuInfoSunModelFromJson(srcJson); | ||
| 43 | + | ||
| 44 | + Map<String, dynamic> toJson() => _$QiniuInfoSunModelToJson(this); | ||
| 45 | +} |
lib/models/qiniu_info_model.g.dart
0 → 100644
| 1 | +// GENERATED CODE - DO NOT MODIFY BY HAND | ||
| 2 | + | ||
| 3 | +part of 'qiniu_info_model.dart'; | ||
| 4 | + | ||
| 5 | +// ************************************************************************** | ||
| 6 | +// JsonSerializableGenerator | ||
| 7 | +// ************************************************************************** | ||
| 8 | + | ||
| 9 | +QiniuInfoModel _$QiniuInfoModelFromJson(Map<String, dynamic> json) { | ||
| 10 | + return QiniuInfoModel( | ||
| 11 | + json['ret'] as int, | ||
| 12 | + json['data'] == null | ||
| 13 | + ? null | ||
| 14 | + : QiniuInfoSunModel.fromJson(json['data'] as Map<String, dynamic>), | ||
| 15 | + json['msg'] as String); | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +Map<String, dynamic> _$QiniuInfoModelToJson(QiniuInfoModel instance) => | ||
| 19 | + <String, dynamic>{ | ||
| 20 | + 'ret': instance.ret, | ||
| 21 | + 'data': instance.data, | ||
| 22 | + 'msg': instance.msg | ||
| 23 | + }; | ||
| 24 | + | ||
| 25 | +QiniuInfoSunModel _$QiniuInfoSunModelFromJson(Map<String, dynamic> json) { | ||
| 26 | + return QiniuInfoSunModel(json['token'] as String, json['domain'] as String); | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +Map<String, dynamic> _$QiniuInfoSunModelToJson(QiniuInfoSunModel instance) => | ||
| 30 | + <String, dynamic>{'token': instance.token, 'domain': instance.domain}; |
| @@ -63,4 +63,7 @@ class HttpUrl { | @@ -63,4 +63,7 @@ class HttpUrl { | ||
| 63 | "?service=App.Advance.CreateOrder"; //顾客扫桌码点餐-扫码创建订单 | 63 | "?service=App.Advance.CreateOrder"; //顾客扫桌码点餐-扫码创建订单 |
| 64 | static const String get_reserve_detail = | 64 | static const String get_reserve_detail = |
| 65 | "?service=App.Reserve.Detail"; //订座详情页面 | 65 | "?service=App.Reserve.Detail"; //订座详情页面 |
| 66 | + static const String get_qiniu_info = | ||
| 67 | + "?service=App.Qiniu.GetUploadToken"; //获取七牛上传token信息 | ||
| 68 | + | ||
| 66 | } | 69 | } |
| @@ -126,6 +126,11 @@ class HomePageState extends State<HomePage> with WidgetsBindingObserver { | @@ -126,6 +126,11 @@ class HomePageState extends State<HomePage> with WidgetsBindingObserver { | ||
| 126 | NavigatorUtil.goNotebookDetailPage(context, notifyParam['rid'], | 126 | NavigatorUtil.goNotebookDetailPage(context, notifyParam['rid'], |
| 127 | mid: notifyParam['mid'], fromNotify: true); | 127 | mid: notifyParam['mid'], fromNotify: true); |
| 128 | break; | 128 | break; |
| 129 | + case "12": | ||
| 130 | + //在线买单消息 去处理 跳转在线买单处理页面 | ||
| 131 | + NavigatorUtil.goOnlineCheckEditPage(context, | ||
| 132 | + rid: notifyParam["rid"], fromNotify: true); | ||
| 133 | + break; | ||
| 129 | case "1": | 134 | case "1": |
| 130 | NavigatorUtil.goHasOrderFoodPage(context, | 135 | NavigatorUtil.goHasOrderFoodPage(context, |
| 131 | rid: notifyParam["rid"], fromNotify: true); | 136 | rid: notifyParam["rid"], fromNotify: true); |
| 1 | -import 'dart:io'; | ||
| 2 | - | ||
| 3 | -import 'package:flutter/material.dart'; | ||
| 4 | -import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
| 5 | -import 'package:one_key/pages/online_check/photo_view_wiget.dart'; | ||
| 6 | - | ||
| 7 | -import 'package:one_key/provider/online_check_edit_provider.dart'; | ||
| 8 | -import 'package:one_key/res/colors.dart'; | ||
| 9 | -import 'package:one_key/utils/utils.dart'; | ||
| 10 | -import 'package:one_key/widgets/MyDivider.dart'; | ||
| 11 | -import 'package:one_key/widgets/v_empty_view.dart'; | ||
| 12 | -import 'package:provider/provider.dart'; | ||
| 13 | - | ||
| 14 | -import 'package:image_picker/image_picker.dart'; | ||
| 15 | -import 'package:video_player/video_player.dart'; | ||
| 16 | -import 'package:qiniu_flutter_sdk/qiniu_flutter_sdk.dart'; | ||
| 17 | - | ||
| 18 | -final int MAX_IMAGE_NUMBER = 9; | ||
| 19 | -typedef void OnPickImageCallback( | ||
| 20 | - double maxWidth, double maxHeight, int quality); | ||
| 21 | - | ||
| 22 | -class ImgPickerWidget extends StatefulWidget { | ||
| 23 | - final ScrollController scrollController; | ||
| 24 | - final Color borderColor; | ||
| 25 | - final ValueChanged onChange; | ||
| 26 | - ImgPickerWidget( | ||
| 27 | - {Key key, | ||
| 28 | - this.scrollController, | ||
| 29 | - this.borderColor = Colors.blue, | ||
| 30 | - this.onChange}) | ||
| 31 | - : super(key: key); | ||
| 32 | - | ||
| 33 | - @override | ||
| 34 | - _ImgPickerWidgetState createState() => _ImgPickerWidgetState(); | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | -class _ImgPickerWidgetState extends State<ImgPickerWidget> { | ||
| 38 | - File _image; | ||
| 39 | - final picker = ImagePicker(); | ||
| 40 | - OnlineCheckEditProvider _onlineCheckEditProvider; | ||
| 41 | - | ||
| 42 | - //相册 相机 | ||
| 43 | - // Future _getFromPictureOrCamera(context, imageSource) async { | ||
| 44 | - // File image = await picker.getImage( | ||
| 45 | - // source: imageSource, | ||
| 46 | - // ); | ||
| 47 | - // if (image != null) { | ||
| 48 | - // _provider.imageList.add(image); | ||
| 49 | - // _provider.notifyListeners(); | ||
| 50 | - // } | ||
| 51 | - // // _provider.uploadTravelReleaseImg(image); | ||
| 52 | - // } | ||
| 53 | - | ||
| 54 | - Future _getFromPictureOrCamera(imageSource) async { | ||
| 55 | - final pickedFile = await picker.getImage(source: imageSource); | ||
| 56 | - | ||
| 57 | - setState(() { | ||
| 58 | - if (pickedFile != null) { | ||
| 59 | - _image = File(pickedFile.path); | ||
| 60 | - _onlineCheckEditProvider.imageList.add(_image); | ||
| 61 | - _onlineCheckEditProvider.notifyListeners(); | ||
| 62 | - } else { | ||
| 63 | - print('No image selected.'); | ||
| 64 | - } | ||
| 65 | - }); | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - @override | ||
| 69 | - void dispose() { | ||
| 70 | - super.dispose(); | ||
| 71 | - } | ||
| 72 | - | ||
| 73 | - Future _openModalBottomSheet(context) async { | ||
| 74 | - final option = await showModalBottomSheet( | ||
| 75 | - context: context, | ||
| 76 | - backgroundColor: Colors.transparent, | ||
| 77 | - builder: (BuildContext context) { | ||
| 78 | - return Container( | ||
| 79 | - // height: ScreenUtil().setWidth(180 * 2), | ||
| 80 | - decoration: BoxDecoration( | ||
| 81 | - color: MyColours.color_ffffff, | ||
| 82 | - borderRadius: BorderRadius.only( | ||
| 83 | - topLeft: Radius.circular(ScreenUtil().setWidth(24)), | ||
| 84 | - topRight: Radius.circular(ScreenUtil().setWidth(24)))), | ||
| 85 | - child: Column( | ||
| 86 | - mainAxisSize: MainAxisSize.min, | ||
| 87 | - children: <Widget>[ | ||
| 88 | - InkWell( | ||
| 89 | - onTap: () { | ||
| 90 | - _getFromPictureOrCamera(ImageSource.camera); | ||
| 91 | - Navigator.pop(context); | ||
| 92 | - }, | ||
| 93 | - child: Padding( | ||
| 94 | - padding: EdgeInsets.symmetric( | ||
| 95 | - vertical: ScreenUtil().setWidth(18 * 2)), | ||
| 96 | - child: Text( | ||
| 97 | - '拍摄', | ||
| 98 | - style: TextStyle( | ||
| 99 | - fontSize: ScreenUtil().setSp(32), | ||
| 100 | - color: MyColours.color_353535, | ||
| 101 | - fontWeight: FontWeight.bold), | ||
| 102 | - ), | ||
| 103 | - ), | ||
| 104 | - ), | ||
| 105 | - MyDivider( | ||
| 106 | - double.infinity, | ||
| 107 | - ScreenUtil().setWidth(2), | ||
| 108 | - color: MyColours.color_EEEEEE, | ||
| 109 | - ), | ||
| 110 | - InkWell( | ||
| 111 | - onTap: () { | ||
| 112 | - _getFromPictureOrCamera(ImageSource.gallery); | ||
| 113 | - Navigator.pop(context); | ||
| 114 | - }, | ||
| 115 | - child: Padding( | ||
| 116 | - padding: EdgeInsets.symmetric( | ||
| 117 | - vertical: ScreenUtil().setWidth(18 * 2)), | ||
| 118 | - child: Text( | ||
| 119 | - '从相册选择', | ||
| 120 | - style: TextStyle( | ||
| 121 | - fontSize: ScreenUtil().setSp(32), | ||
| 122 | - color: MyColours.color_353535, | ||
| 123 | - fontWeight: FontWeight.bold), | ||
| 124 | - ), | ||
| 125 | - ), | ||
| 126 | - ), | ||
| 127 | - MyDivider( | ||
| 128 | - double.infinity, | ||
| 129 | - ScreenUtil().setWidth(10), | ||
| 130 | - color: MyColours.color_EEEEEE, | ||
| 131 | - ), | ||
| 132 | - InkWell( | ||
| 133 | - onTap: () { | ||
| 134 | - Navigator.pop(context, '取消'); | ||
| 135 | - }, | ||
| 136 | - child: Padding( | ||
| 137 | - padding: EdgeInsets.symmetric( | ||
| 138 | - vertical: ScreenUtil().setWidth(18 * 2)), | ||
| 139 | - child: Text( | ||
| 140 | - '取消', | ||
| 141 | - style: TextStyle( | ||
| 142 | - fontSize: ScreenUtil().setSp(32), | ||
| 143 | - color: MyColours.color_353535, | ||
| 144 | - fontWeight: FontWeight.bold), | ||
| 145 | - ), | ||
| 146 | - ), | ||
| 147 | - ) | ||
| 148 | - ], | ||
| 149 | - ), | ||
| 150 | - ); | ||
| 151 | - }); | ||
| 152 | - } | ||
| 153 | - | ||
| 154 | - _getGridImg(count, context, isLinjie) { | ||
| 155 | - OnlineCheckEditProvider _provider = | ||
| 156 | - Provider.of<OnlineCheckEditProvider>(context, listen: false); | ||
| 157 | - return GridView.builder( | ||
| 158 | - controller: widget.scrollController, | ||
| 159 | - // padding: EdgeInsets.only(top: ScreenUtil().getAdapterSize(10)), | ||
| 160 | - shrinkWrap: true, | ||
| 161 | - itemCount: count, | ||
| 162 | - //SliverGridDelegateWithFixedCrossAxisCount 构建一个横轴固定数量Widget | ||
| 163 | - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | ||
| 164 | - //横轴元素个数 | ||
| 165 | - crossAxisCount: 3, | ||
| 166 | - //纵轴间距 | ||
| 167 | - mainAxisSpacing: 20.0, | ||
| 168 | - //横轴间距 | ||
| 169 | - crossAxisSpacing: 10.0, | ||
| 170 | - //子组件宽高长度比例 | ||
| 171 | - childAspectRatio: 1.0), | ||
| 172 | - itemBuilder: (BuildContext context, int index) { | ||
| 173 | - //Widget Function(BuildContext context, int index) | ||
| 174 | - var linjie = MAX_IMAGE_NUMBER; | ||
| 175 | - if (isLinjie) { | ||
| 176 | - linjie = MAX_IMAGE_NUMBER - 1; | ||
| 177 | - } | ||
| 178 | - if (index == count - 1 && index < linjie) { | ||
| 179 | - return InkWell( | ||
| 180 | - onTap: () { | ||
| 181 | - _openModalBottomSheet(context); | ||
| 182 | - }, | ||
| 183 | - child: Container( | ||
| 184 | - width: ScreenUtil().setWidth(90 * 2), | ||
| 185 | - height: ScreenUtil().setWidth(90 * 2), | ||
| 186 | - decoration: BoxDecoration( | ||
| 187 | - border: Border.all( | ||
| 188 | - color: MyColours.color_E0E0E0, | ||
| 189 | - width: ScreenUtil().setWidth(2)), | ||
| 190 | - ), | ||
| 191 | - child: Column( | ||
| 192 | - children: [ | ||
| 193 | - VEmptyView(74), | ||
| 194 | - Image.asset( | ||
| 195 | - Utils.getImgPath('add_image'), | ||
| 196 | - width: ScreenUtil().setWidth(32), | ||
| 197 | - height: ScreenUtil().setWidth(32), | ||
| 198 | - ), | ||
| 199 | - VEmptyView(10), | ||
| 200 | - Text( | ||
| 201 | - '添加照片', | ||
| 202 | - style: TextStyle( | ||
| 203 | - fontSize: ScreenUtil().setSp(24), | ||
| 204 | - color: MyColours.color_999999), | ||
| 205 | - ) | ||
| 206 | - ], | ||
| 207 | - )), | ||
| 208 | - ); | ||
| 209 | - } | ||
| 210 | - return _provider.imageList.length < 1 | ||
| 211 | - ? Text('') | ||
| 212 | - : InkWell( | ||
| 213 | - onTap: () { | ||
| 214 | - _showPhotoView(context, index, _provider.imageList[index]); | ||
| 215 | - }, | ||
| 216 | - child: | ||
| 217 | - Image.file(_provider.imageList[index], fit: BoxFit.cover), | ||
| 218 | - ); | ||
| 219 | - }); | ||
| 220 | - } | ||
| 221 | - | ||
| 222 | - //查看大图 | ||
| 223 | - _showPhotoView(BuildContext context, int index, List imgs, | ||
| 224 | - {isShow = false, List dashName}) async { | ||
| 225 | - // if (imgs.length == 1 && | ||
| 226 | - // imgs[0] == | ||
| 227 | - // 'http://nosqn.colorcun.com/custom/lite-online/image/def-banner.png') { | ||
| 228 | - // imgs[0] = 'http://nosqn.colorcun.com/app/seller-hj-empty.png'; | ||
| 229 | - // } | ||
| 230 | - Utils.setBarStatus(false, color: Colors.black); | ||
| 231 | - dynamic result = await showGeneralDialog( | ||
| 232 | - context: context, | ||
| 233 | - barrierDismissible: false, | ||
| 234 | - // barrierColor: Colors.red, | ||
| 235 | - barrierLabel: | ||
| 236 | - MaterialLocalizations.of(context).modalBarrierDismissLabel, | ||
| 237 | - transitionDuration: const Duration(milliseconds: 150), | ||
| 238 | - pageBuilder: (BuildContext context, Animation animation, | ||
| 239 | - Animation secondaryAnimation) { | ||
| 240 | - Widget child = Stack( | ||
| 241 | - children: <Widget>[ | ||
| 242 | - PhotoPreview( | ||
| 243 | - initialIndex: index, | ||
| 244 | - photoList: imgs, | ||
| 245 | - isShow: isShow, | ||
| 246 | - dashName: dashName) | ||
| 247 | - ], | ||
| 248 | - ); | ||
| 249 | - return child; | ||
| 250 | - }); | ||
| 251 | - Utils.setBarStatus(true, color: Colors.white); | ||
| 252 | - } | ||
| 253 | - | ||
| 254 | - @override | ||
| 255 | - Widget build(BuildContext context) { | ||
| 256 | - _onlineCheckEditProvider = | ||
| 257 | - Provider.of<OnlineCheckEditProvider>(context, listen: true); | ||
| 258 | - return Container( | ||
| 259 | - width: double.infinity, | ||
| 260 | - decoration: BoxDecoration( | ||
| 261 | - color: Colors.white, borderRadius: BorderRadius.circular(10)), | ||
| 262 | - child: Column( | ||
| 263 | - crossAxisAlignment: CrossAxisAlignment.start, | ||
| 264 | - children: <Widget>[ | ||
| 265 | - Container( | ||
| 266 | - height: ScreenUtil().setWidth(53 * 2), | ||
| 267 | - width: double.infinity, | ||
| 268 | - decoration: BoxDecoration( | ||
| 269 | - color: MyColours.color_FAFAFA, | ||
| 270 | - borderRadius: BorderRadius.only( | ||
| 271 | - topLeft: Radius.circular(10), | ||
| 272 | - topRight: Radius.circular(10)), | ||
| 273 | - ), | ||
| 274 | - child: Padding( | ||
| 275 | - padding: EdgeInsets.fromLTRB( | ||
| 276 | - ScreenUtil().setWidth(20), | ||
| 277 | - ScreenUtil().setWidth(36), | ||
| 278 | - ScreenUtil().setWidth(20), | ||
| 279 | - ScreenUtil().setWidth(26)), | ||
| 280 | - child: Text( | ||
| 281 | - '消费清单(选填)', | ||
| 282 | - style: TextStyle( | ||
| 283 | - fontSize: ScreenUtil().setSp(32), | ||
| 284 | - color: MyColours.color_353535, | ||
| 285 | - fontWeight: FontWeight.bold), | ||
| 286 | - ), | ||
| 287 | - )), | ||
| 288 | - Padding( | ||
| 289 | - padding: EdgeInsets.all(ScreenUtil().setWidth(40)), | ||
| 290 | - child: _getGridImg( | ||
| 291 | - _onlineCheckEditProvider.imageList.length < MAX_IMAGE_NUMBER | ||
| 292 | - ? _onlineCheckEditProvider.imageList.length + 1 | ||
| 293 | - : _onlineCheckEditProvider.imageList.length, | ||
| 294 | - context, | ||
| 295 | - _onlineCheckEditProvider.imageList.length == MAX_IMAGE_NUMBER | ||
| 296 | - ? true | ||
| 297 | - : false), | ||
| 298 | - ) | ||
| 299 | - // _getGridImg(1, context) | ||
| 300 | - ], | ||
| 301 | - ), | ||
| 302 | - ); | ||
| 303 | - } | ||
| 304 | -} |
lib/pages/online_check/dispose.dart
0 → 100644
| 1 | +import 'package:flutter/widgets.dart'; | ||
| 2 | + | ||
| 3 | +abstract class DisposableState<T extends StatefulWidget> extends State<T> { | ||
| 4 | + List<Function> disposerList = []; | ||
| 5 | + | ||
| 6 | + void addDisposer(Function disposer) { | ||
| 7 | + disposerList.add(disposer); | ||
| 8 | + } | ||
| 9 | + | ||
| 10 | + @override | ||
| 11 | + @mustCallSuper | ||
| 12 | + void dispose() { | ||
| 13 | + for (var disposer in disposerList) { | ||
| 14 | + try { | ||
| 15 | + disposer?.call(); | ||
| 16 | + } catch (error) { | ||
| 17 | + rethrow; | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + super.dispose(); | ||
| 21 | + } | ||
| 22 | +} |
| 1 | +import 'dart:convert'; | ||
| 2 | +import 'dart:io'; | ||
| 3 | +import 'dart:async'; | ||
| 4 | + | ||
| 5 | +import 'package:cached_network_image/cached_network_image.dart'; | ||
| 6 | +import 'package:flutter/material.dart'; | ||
| 7 | +import 'package:flutter/services.dart'; | ||
| 8 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
| 9 | +import 'package:one_key/pages/online_check/photo_view_wiget.dart'; | ||
| 10 | +import 'package:one_key/pages/online_check/progress.dart'; | ||
| 11 | + | ||
| 12 | +import 'package:one_key/provider/online_check_edit_provider.dart'; | ||
| 13 | +import 'package:one_key/res/colors.dart'; | ||
| 14 | +import 'package:one_key/utils/utils.dart'; | ||
| 15 | +import 'package:one_key/widgets/MyDivider.dart'; | ||
| 16 | +import 'package:one_key/widgets/v_empty_view.dart'; | ||
| 17 | +import 'package:path_provider/path_provider.dart'; | ||
| 18 | +import 'package:photo/photo.dart'; | ||
| 19 | +import 'package:provider/provider.dart'; | ||
| 20 | + | ||
| 21 | +import 'package:image_picker/image_picker.dart'; | ||
| 22 | +import 'package:qiniu_flutter_sdk/qiniu_flutter_sdk.dart'; | ||
| 23 | +import './dispose.dart'; | ||
| 24 | +import 'package:photo_manager/photo_manager.dart'; | ||
| 25 | + | ||
| 26 | +final int MAX_IMAGE_NUMBER = 5; | ||
| 27 | +typedef void OnPickImageCallback( | ||
| 28 | + double maxWidth, double maxHeight, int quality); | ||
| 29 | + | ||
| 30 | +class ImgPickerWidget extends StatefulWidget { | ||
| 31 | + final ScrollController scrollController; | ||
| 32 | + final Color borderColor; | ||
| 33 | + final ValueChanged onChange; | ||
| 34 | + ImgPickerWidget( | ||
| 35 | + {Key key, | ||
| 36 | + this.scrollController, | ||
| 37 | + this.borderColor = Colors.blue, | ||
| 38 | + this.onChange}) | ||
| 39 | + : super(key: key); | ||
| 40 | + | ||
| 41 | + @override | ||
| 42 | + _ImgPickerWidgetState createState() => _ImgPickerWidgetState(); | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +class _ImgPickerWidgetState extends DisposableState<ImgPickerWidget> { | ||
| 46 | + final picker = ImagePicker(); | ||
| 47 | + OnlineCheckEditProvider _onlineCheckEditProvider; | ||
| 48 | + // 控制器,可以用于取消任务、获取上述的状态,进度等信息 | ||
| 49 | + PutController putController; | ||
| 50 | + // 用户输入的文件名 | ||
| 51 | + String key; | ||
| 52 | + // 用户输入的 partSize | ||
| 53 | + int partSize = 4; | ||
| 54 | + // 用户输入的 token | ||
| 55 | + String token; | ||
| 56 | + | ||
| 57 | + /// storage 实例 | ||
| 58 | + Storage storage; | ||
| 59 | + // 当前的进度 | ||
| 60 | + double progressValue = 0.01; | ||
| 61 | + // 当前的任务状态 | ||
| 62 | + StorageStatus statusValue; | ||
| 63 | + | ||
| 64 | + @override | ||
| 65 | + void initState() { | ||
| 66 | + storage = Storage(); | ||
| 67 | + super.initState(); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + @override | ||
| 71 | + void dispose() { | ||
| 72 | + super.dispose(); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + ///#相机拍照,单图选择 | ||
| 76 | + Future _getFromPictureOrCamera(imageSource) async { | ||
| 77 | + final pickedFile = await picker.getImage(source: imageSource); | ||
| 78 | + | ||
| 79 | + setState(() { | ||
| 80 | + if (pickedFile != null) { | ||
| 81 | + _onlineCheckEditProvider.imageListFile.add(File(pickedFile.path)); | ||
| 82 | + _onlineCheckEditProvider.statusMap[pickedFile.path] = false; | ||
| 83 | + } else { | ||
| 84 | + print('No image selected.'); | ||
| 85 | + } | ||
| 86 | + }); | ||
| 87 | + if (pickedFile != null) { | ||
| 88 | + startUpload(File(pickedFile.path)); | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + ///多图片选择 | ||
| 93 | + void pickAsset(PickType type, {List<AssetPathEntity> pathList}) async { | ||
| 94 | + /// context is required, other params is optional. | ||
| 95 | + List<AssetEntity> imgList = await PhotoPicker.pickAsset( | ||
| 96 | + // BuildContext required | ||
| 97 | + context: context, | ||
| 98 | + | ||
| 99 | + /// The following are optional parameters. | ||
| 100 | + themeColor: MyColours.color_199095, | ||
| 101 | + // the title color and bottom color | ||
| 102 | + textColor: Colors.white, | ||
| 103 | + // text color | ||
| 104 | + padding: 1.0, | ||
| 105 | + // item padding | ||
| 106 | + dividerColor: Colors.grey, | ||
| 107 | + // divider color | ||
| 108 | + disableColor: Colors.grey.shade300, | ||
| 109 | + // the check box disable color | ||
| 110 | + itemRadio: 0.88, | ||
| 111 | + // the content item radio | ||
| 112 | + maxSelected: | ||
| 113 | + MAX_IMAGE_NUMBER - _onlineCheckEditProvider.imageListFile.length, | ||
| 114 | + // max picker image count | ||
| 115 | + // provider: I18nProvider.english, | ||
| 116 | + provider: I18nProvider.chinese, | ||
| 117 | + // i18n provider ,default is chinese. , you can custom I18nProvider or use ENProvider() | ||
| 118 | + rowCount: 3, | ||
| 119 | + // item row count | ||
| 120 | + thumbSize: 150, | ||
| 121 | + // preview thumb size , default is 64 | ||
| 122 | + sortDelegate: SortDelegate.common, | ||
| 123 | + // default is common ,or you make custom delegate to sort your gallery | ||
| 124 | + checkBoxBuilderDelegate: DefaultCheckBoxBuilderDelegate( | ||
| 125 | + activeColor: MyColours.color_353535, | ||
| 126 | + unselectedColor: Colors.white, | ||
| 127 | + checkColor: MyColours.color_199095, | ||
| 128 | + ), | ||
| 129 | + // default is DefaultCheckBoxBuilderDelegate ,or you make custom delegate to create checkbox | ||
| 130 | + // loadingDelegate: this, | ||
| 131 | + // if you want to build custom loading widget,extends LoadingDelegate, [see example/lib/main.dart] | ||
| 132 | + badgeDelegate: const DurationBadgeDelegate(), | ||
| 133 | + // badgeDelegate to show badge widget | ||
| 134 | + pickType: type, | ||
| 135 | + photoPathList: pathList, | ||
| 136 | + ); | ||
| 137 | + if (imgList == null || imgList.isEmpty) { | ||
| 138 | + print("No pick item."); | ||
| 139 | + return; | ||
| 140 | + } else { | ||
| 141 | + List<String> r = []; | ||
| 142 | + for (var e in imgList) { | ||
| 143 | + var file = await e.file; | ||
| 144 | + r.add(file.absolute.path); | ||
| 145 | + setState(() { | ||
| 146 | + _onlineCheckEditProvider.imageListFile.add(File(file.absolute.path)); | ||
| 147 | + _onlineCheckEditProvider.statusMap[file.absolute.path] = false; | ||
| 148 | + }); | ||
| 149 | + startUpload(File(file.absolute.path)); | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + ///七牛云sdk | ||
| 155 | + | ||
| 156 | + void onStatus(StorageStatus status) { | ||
| 157 | + print('状态变化: 当前任务状态:${status.toString()}'); | ||
| 158 | + setState(() => statusValue = status); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + ///任务进度变化:进度 | ||
| 162 | + void onProgress(double percent) { | ||
| 163 | + setState(() => progressValue = percent); | ||
| 164 | + print('任务进度变化:进度:${percent.toStringAsFixed(4)}'); | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + ///实际发送变化:进度 | ||
| 168 | + void onSendProgress(double percent) { | ||
| 169 | + setState(() => progressValue = percent); | ||
| 170 | + print('实际发送变化:进度:${percent.toStringAsFixed(4)}'); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + ///上传到七牛云 | ||
| 174 | + void startUpload(File selectedFile) async { | ||
| 175 | + print('创建 PutController'); | ||
| 176 | + putController = PutController(); | ||
| 177 | + // _onlineCheckEditProvider.statusMapProgress[selectedFile.path] = | ||
| 178 | + // putController; | ||
| 179 | + print('添加实际发送进度订阅'); | ||
| 180 | + addDisposer(putController.addSendProgressListener(onSendProgress)); | ||
| 181 | + | ||
| 182 | + print('添加任务进度订阅'); | ||
| 183 | + addDisposer(putController.addProgressListener(onProgress)); | ||
| 184 | + | ||
| 185 | + print('添加状态订阅'); | ||
| 186 | + addDisposer(putController.addStatusListener(onStatus)); | ||
| 187 | + if (token == null || token == '') { | ||
| 188 | + await _onlineCheckEditProvider.getQiniuInfo(context, {}); | ||
| 189 | + } | ||
| 190 | + var usedToken = _onlineCheckEditProvider.qiniuInfoSunModel.token; | ||
| 191 | + | ||
| 192 | + if (usedToken == null || usedToken == '') { | ||
| 193 | + print('token 不能为空'); | ||
| 194 | + return; | ||
| 195 | + } | ||
| 196 | + print('开始上传文件'); | ||
| 197 | + storage.putFile( | ||
| 198 | + selectedFile, | ||
| 199 | + usedToken, | ||
| 200 | + options: PutOptions( | ||
| 201 | + key: key, | ||
| 202 | + partSize: partSize, | ||
| 203 | + controller: putController, | ||
| 204 | + ), | ||
| 205 | + ) | ||
| 206 | + ..then((PutResponse response) { | ||
| 207 | + print('上传已完成: 原始响应数据: ${jsonEncode(response.rawData)}'); | ||
| 208 | + print('------------------------'); | ||
| 209 | + String imgUrl = _onlineCheckEditProvider.qiniuInfoSunModel.domain + | ||
| 210 | + '/' + | ||
| 211 | + response.rawData['key']; | ||
| 212 | + _onlineCheckEditProvider.imageListUrl.add(imgUrl); | ||
| 213 | + // _image | ||
| 214 | + _onlineCheckEditProvider.statusMap[selectedFile.path] = true; | ||
| 215 | + _onlineCheckEditProvider.notifyListeners(); | ||
| 216 | + }) | ||
| 217 | + ..catchError((dynamic error) { | ||
| 218 | + if (error is StorageError) { | ||
| 219 | + switch (error.type) { | ||
| 220 | + case StorageErrorType.CONNECT_TIMEOUT: | ||
| 221 | + print('发生错误: 连接超时'); | ||
| 222 | + break; | ||
| 223 | + case StorageErrorType.SEND_TIMEOUT: | ||
| 224 | + print('发生错误: 发送数据超时'); | ||
| 225 | + break; | ||
| 226 | + case StorageErrorType.RECEIVE_TIMEOUT: | ||
| 227 | + print('发生错误: 响应数据超时'); | ||
| 228 | + break; | ||
| 229 | + case StorageErrorType.RESPONSE: | ||
| 230 | + print('发生错误: ${error.message}'); | ||
| 231 | + break; | ||
| 232 | + case StorageErrorType.CANCEL: | ||
| 233 | + print('发生错误: 请求取消'); | ||
| 234 | + break; | ||
| 235 | + case StorageErrorType.UNKNOWN: | ||
| 236 | + print('发生错误: 未知错误'); | ||
| 237 | + break; | ||
| 238 | + case StorageErrorType.NO_AVAILABLE_HOST: | ||
| 239 | + print('发生错误: 无可用 Host'); | ||
| 240 | + break; | ||
| 241 | + case StorageErrorType.IN_PROGRESS: | ||
| 242 | + print('发生错误: 已在队列中'); | ||
| 243 | + break; | ||
| 244 | + } | ||
| 245 | + } else { | ||
| 246 | + print('发生错误: ${error.toString()}'); | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + print('------------------------'); | ||
| 250 | + }); | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + ///添加图片UI弹出 | ||
| 254 | + Future _openModalBottomSheet(context) async { | ||
| 255 | + final option = await showModalBottomSheet( | ||
| 256 | + context: context, | ||
| 257 | + backgroundColor: Colors.transparent, | ||
| 258 | + isDismissible: false, | ||
| 259 | + builder: (BuildContext context) { | ||
| 260 | + return Container( | ||
| 261 | + // height: ScreenUtil().setWidth(180 * 2), | ||
| 262 | + decoration: BoxDecoration( | ||
| 263 | + color: MyColours.color_ffffff, | ||
| 264 | + borderRadius: BorderRadius.only( | ||
| 265 | + topLeft: Radius.circular(ScreenUtil().setWidth(24)), | ||
| 266 | + topRight: Radius.circular(ScreenUtil().setWidth(24)))), | ||
| 267 | + child: Column( | ||
| 268 | + mainAxisSize: MainAxisSize.min, | ||
| 269 | + children: <Widget>[ | ||
| 270 | + InkWell( | ||
| 271 | + onTap: () { | ||
| 272 | + _getFromPictureOrCamera(ImageSource.camera); | ||
| 273 | + Navigator.pop(context); | ||
| 274 | + }, | ||
| 275 | + child: Container( | ||
| 276 | + width: double.infinity, | ||
| 277 | + height: ScreenUtil().setWidth(58 * 2), | ||
| 278 | + child: Center( | ||
| 279 | + child: Text( | ||
| 280 | + '拍摄', | ||
| 281 | + style: TextStyle( | ||
| 282 | + fontSize: ScreenUtil().setSp(32), | ||
| 283 | + color: MyColours.color_353535, | ||
| 284 | + fontWeight: FontWeight.bold), | ||
| 285 | + ), | ||
| 286 | + )), | ||
| 287 | + ), | ||
| 288 | + MyDivider( | ||
| 289 | + double.infinity, | ||
| 290 | + ScreenUtil().setWidth(2), | ||
| 291 | + color: MyColours.color_EEEEEE, | ||
| 292 | + ), | ||
| 293 | + InkWell( | ||
| 294 | + onTap: () { | ||
| 295 | + // pickAsset(PickType.onlyImage); | ||
| 296 | + _getFromPictureOrCamera(ImageSource.gallery); | ||
| 297 | + Navigator.pop(context); | ||
| 298 | + }, | ||
| 299 | + child: Container( | ||
| 300 | + width: double.infinity, | ||
| 301 | + height: ScreenUtil().setWidth(58 * 2), | ||
| 302 | + child: Center( | ||
| 303 | + child: Text( | ||
| 304 | + '从相册选择', | ||
| 305 | + style: TextStyle( | ||
| 306 | + fontSize: ScreenUtil().setSp(32), | ||
| 307 | + color: MyColours.color_353535, | ||
| 308 | + fontWeight: FontWeight.bold), | ||
| 309 | + ), | ||
| 310 | + )), | ||
| 311 | + ), | ||
| 312 | + MyDivider( | ||
| 313 | + double.infinity, | ||
| 314 | + ScreenUtil().setWidth(10), | ||
| 315 | + color: MyColours.color_EEEEEE, | ||
| 316 | + ), | ||
| 317 | + InkWell( | ||
| 318 | + onTap: () { | ||
| 319 | + Navigator.pop(context, '取消'); | ||
| 320 | + }, | ||
| 321 | + child: Container( | ||
| 322 | + width: double.infinity, | ||
| 323 | + height: ScreenUtil().setWidth(58 * 2), | ||
| 324 | + child: Center( | ||
| 325 | + child: Text( | ||
| 326 | + '取消', | ||
| 327 | + style: TextStyle( | ||
| 328 | + fontSize: ScreenUtil().setSp(32), | ||
| 329 | + color: MyColours.color_353535, | ||
| 330 | + fontWeight: FontWeight.bold), | ||
| 331 | + ), | ||
| 332 | + ))) | ||
| 333 | + ], | ||
| 334 | + ), | ||
| 335 | + ); | ||
| 336 | + }); | ||
| 337 | + } | ||
| 338 | + | ||
| 339 | + //查看大图 | ||
| 340 | + _showPhotoView(BuildContext context, int index, List imgs, | ||
| 341 | + {isShow = false, List dashName}) async { | ||
| 342 | + // if (imgs.length == 1 && | ||
| 343 | + // imgs[0] == | ||
| 344 | + // 'http://nosqn.colorcun.com/custom/lite-online/image/def-banner.png') { | ||
| 345 | + // imgs[0] = 'http://nosqn.colorcun.com/app/seller-hj-empty.png'; | ||
| 346 | + // } | ||
| 347 | + Utils.setBarStatus(false, color: Colors.black); | ||
| 348 | + dynamic result = await showGeneralDialog( | ||
| 349 | + context: context, | ||
| 350 | + barrierDismissible: false, | ||
| 351 | + // barrierColor: Colors.red, | ||
| 352 | + barrierLabel: | ||
| 353 | + MaterialLocalizations.of(context).modalBarrierDismissLabel, | ||
| 354 | + transitionDuration: const Duration(milliseconds: 150), | ||
| 355 | + pageBuilder: (BuildContext context, Animation animation, | ||
| 356 | + Animation secondaryAnimation) { | ||
| 357 | + Widget child = Stack( | ||
| 358 | + children: <Widget>[ | ||
| 359 | + PhotoPreview( | ||
| 360 | + initialIndex: index, | ||
| 361 | + photoList: imgs, | ||
| 362 | + isShow: isShow, | ||
| 363 | + dashName: dashName) | ||
| 364 | + ], | ||
| 365 | + ); | ||
| 366 | + return child; | ||
| 367 | + }); | ||
| 368 | + Utils.setBarStatus(true, color: Colors.white); | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + @override | ||
| 372 | + Widget build(BuildContext context) { | ||
| 373 | + _onlineCheckEditProvider = | ||
| 374 | + Provider.of<OnlineCheckEditProvider>(context, listen: true); | ||
| 375 | + return Container( | ||
| 376 | + width: double.infinity, | ||
| 377 | + decoration: BoxDecoration( | ||
| 378 | + color: Colors.white, borderRadius: BorderRadius.circular(10)), | ||
| 379 | + child: Column( | ||
| 380 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 381 | + children: <Widget>[ | ||
| 382 | + Container( | ||
| 383 | + height: ScreenUtil().setWidth(53 * 2), | ||
| 384 | + width: double.infinity, | ||
| 385 | + decoration: BoxDecoration( | ||
| 386 | + color: MyColours.color_FAFAFA, | ||
| 387 | + borderRadius: BorderRadius.only( | ||
| 388 | + topLeft: Radius.circular(10), | ||
| 389 | + topRight: Radius.circular(10)), | ||
| 390 | + ), | ||
| 391 | + child: Padding( | ||
| 392 | + padding: EdgeInsets.fromLTRB( | ||
| 393 | + ScreenUtil().setWidth(20), | ||
| 394 | + ScreenUtil().setWidth(36), | ||
| 395 | + ScreenUtil().setWidth(20), | ||
| 396 | + ScreenUtil().setWidth(26)), | ||
| 397 | + child: Text( | ||
| 398 | + '消费清单(选填)', | ||
| 399 | + style: TextStyle( | ||
| 400 | + fontSize: ScreenUtil().setSp(32), | ||
| 401 | + color: MyColours.color_353535, | ||
| 402 | + fontWeight: FontWeight.bold), | ||
| 403 | + ), | ||
| 404 | + )), | ||
| 405 | + Padding( | ||
| 406 | + padding: EdgeInsets.all(ScreenUtil().setWidth(40)), | ||
| 407 | + child: _getGridImg( | ||
| 408 | + _onlineCheckEditProvider.imageListFile.length < MAX_IMAGE_NUMBER | ||
| 409 | + ? _onlineCheckEditProvider.imageListFile.length + 1 | ||
| 410 | + : _onlineCheckEditProvider.imageListFile.length, | ||
| 411 | + context, | ||
| 412 | + _onlineCheckEditProvider.imageListFile.length == | ||
| 413 | + MAX_IMAGE_NUMBER | ||
| 414 | + ? true | ||
| 415 | + : false), | ||
| 416 | + ) | ||
| 417 | + // _getGridImg(1, context) | ||
| 418 | + ], | ||
| 419 | + ), | ||
| 420 | + ); | ||
| 421 | + } | ||
| 422 | + | ||
| 423 | + /// 九宫格 | ||
| 424 | + Widget _getGridImg(count, context, isLinjie) { | ||
| 425 | + OnlineCheckEditProvider _provider = | ||
| 426 | + Provider.of<OnlineCheckEditProvider>(context, listen: false); | ||
| 427 | + return GridView.builder( | ||
| 428 | + controller: widget.scrollController, | ||
| 429 | + // padding: EdgeInsets.only(top: ScreenUtil().getAdapterSize(10)), | ||
| 430 | + shrinkWrap: true, | ||
| 431 | + itemCount: count, | ||
| 432 | + //SliverGridDelegateWithFixedCrossAxisCount 构建一个横轴固定数量Widget | ||
| 433 | + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | ||
| 434 | + //横轴元素个数 | ||
| 435 | + crossAxisCount: 3, | ||
| 436 | + //纵轴间距 | ||
| 437 | + mainAxisSpacing: ScreenUtil().setWidth(30), | ||
| 438 | + //横轴间距 | ||
| 439 | + crossAxisSpacing: ScreenUtil().setWidth(30), | ||
| 440 | + //子组件宽高长度比例 | ||
| 441 | + childAspectRatio: 1.0), | ||
| 442 | + itemBuilder: (BuildContext context, int index) { | ||
| 443 | + //Widget Function(BuildContext context, int index) | ||
| 444 | + var linjie = MAX_IMAGE_NUMBER; | ||
| 445 | + if (isLinjie) { | ||
| 446 | + linjie = MAX_IMAGE_NUMBER - 1; | ||
| 447 | + } | ||
| 448 | + if (index == count - 1 && index < linjie) { | ||
| 449 | + return InkWell( | ||
| 450 | + onTap: () { | ||
| 451 | + _openModalBottomSheet(context); | ||
| 452 | + }, | ||
| 453 | + child: Container( | ||
| 454 | + width: ScreenUtil().setWidth(90 * 2), | ||
| 455 | + height: ScreenUtil().setWidth(90 * 2), | ||
| 456 | + decoration: BoxDecoration( | ||
| 457 | + border: Border.all( | ||
| 458 | + color: MyColours.color_E0E0E0, | ||
| 459 | + width: ScreenUtil().setWidth(2)), | ||
| 460 | + ), | ||
| 461 | + child: Column( | ||
| 462 | + children: [ | ||
| 463 | + VEmptyView(74), | ||
| 464 | + Image.asset( | ||
| 465 | + Utils.getImgPath('add_image'), | ||
| 466 | + width: ScreenUtil().setWidth(32), | ||
| 467 | + height: ScreenUtil().setWidth(32), | ||
| 468 | + ), | ||
| 469 | + VEmptyView(10), | ||
| 470 | + Text( | ||
| 471 | + '添加照片', | ||
| 472 | + style: TextStyle( | ||
| 473 | + fontSize: ScreenUtil().setSp(24), | ||
| 474 | + color: MyColours.color_999999), | ||
| 475 | + ) | ||
| 476 | + ], | ||
| 477 | + )), | ||
| 478 | + ); | ||
| 479 | + } | ||
| 480 | + return _provider.imageListFile.length < 1 | ||
| 481 | + ? Text('') | ||
| 482 | + : InkWell( | ||
| 483 | + onTap: () { | ||
| 484 | + ///没有上传完成的不可以点击 | ||
| 485 | + _showPhotoView( | ||
| 486 | + context, index, _provider.imageListUrl[index]); | ||
| 487 | + }, | ||
| 488 | + child: Stack( | ||
| 489 | + children: [ | ||
| 490 | + Stack( | ||
| 491 | + alignment: Alignment.topRight, | ||
| 492 | + children: [ | ||
| 493 | + Image.file( | ||
| 494 | + _provider.imageListFile[index], | ||
| 495 | + fit: BoxFit.cover, | ||
| 496 | + width: ScreenUtil().setWidth(100 * 2), | ||
| 497 | + height: ScreenUtil().setWidth(100 * 2), | ||
| 498 | + ), | ||
| 499 | + Offstage( | ||
| 500 | + offstage: !_provider | ||
| 501 | + .statusMap[_provider.imageListFile[index].path], | ||
| 502 | + child: GestureDetector( | ||
| 503 | + child: Image.asset( | ||
| 504 | + Utils.getImgPath("delete"), | ||
| 505 | + width: ScreenUtil().setWidth(40), | ||
| 506 | + height: ScreenUtil().setWidth(40), | ||
| 507 | + ), | ||
| 508 | + onTap: () { | ||
| 509 | + //点击删除按钮 | ||
| 510 | + setState(() { | ||
| 511 | + _provider.imageListFile.removeWhere( | ||
| 512 | + (element) => | ||
| 513 | + element == | ||
| 514 | + _provider.imageListFile[index]); | ||
| 515 | + }); | ||
| 516 | + }, | ||
| 517 | + ), | ||
| 518 | + ), | ||
| 519 | + ], | ||
| 520 | + ), | ||
| 521 | + Offstage( | ||
| 522 | + offstage: _provider | ||
| 523 | + .statusMap[_provider.imageListFile[index].path], | ||
| 524 | + child: Progress(progressValue), | ||
| 525 | + ) | ||
| 526 | + ], | ||
| 527 | + )); | ||
| 528 | + }); | ||
| 529 | + } | ||
| 530 | +} |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:flutter_screenutil/screenutil.dart'; | 2 | import 'package:flutter_screenutil/screenutil.dart'; |
| 3 | -import 'package:one_key/pages/online_check/ImgPickerWidget.dart'; | 3 | +import 'package:one_key/pages/online_check/img_picker_widget.dart'; |
| 4 | +import 'package:one_key/provider/online_check_edit_provider.dart'; | ||
| 4 | import 'package:one_key/res/colors.dart'; | 5 | import 'package:one_key/res/colors.dart'; |
| 5 | import 'package:one_key/utils/navigator_util.dart'; | 6 | import 'package:one_key/utils/navigator_util.dart'; |
| 6 | import 'package:one_key/utils/utils.dart'; | 7 | import 'package:one_key/utils/utils.dart'; |
| 7 | import 'package:one_key/widgets/MyDivider.dart'; | 8 | import 'package:one_key/widgets/MyDivider.dart'; |
| 8 | import 'package:one_key/widgets/h_empty_view.dart'; | 9 | import 'package:one_key/widgets/h_empty_view.dart'; |
| 10 | +import 'package:one_key/widgets/my_item.dart'; | ||
| 9 | import 'package:one_key/widgets/system_app_bar.dart'; | 11 | import 'package:one_key/widgets/system_app_bar.dart'; |
| 10 | import 'package:one_key/widgets/v_empty_view.dart'; | 12 | import 'package:one_key/widgets/v_empty_view.dart'; |
| 13 | +import 'package:provider/provider.dart'; | ||
| 11 | 14 | ||
| 12 | class OnlineCheckEditPage extends StatefulWidget { | 15 | class OnlineCheckEditPage extends StatefulWidget { |
| 13 | final bool fromNotify; | 16 | final bool fromNotify; |
| @@ -21,10 +24,14 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | @@ -21,10 +24,14 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | ||
| 21 | ScrollController _scrollController = ScrollController(); | 24 | ScrollController _scrollController = ScrollController(); |
| 22 | TextEditingController _editingController = TextEditingController(); | 25 | TextEditingController _editingController = TextEditingController(); |
| 23 | FocusNode _focusNode = FocusNode(); | 26 | FocusNode _focusNode = FocusNode(); |
| 27 | + OnlineCheckEditProvider _onlineCheckEditProvider; | ||
| 24 | 28 | ||
| 25 | @override | 29 | @override |
| 26 | void initState() { | 30 | void initState() { |
| 27 | super.initState(); | 31 | super.initState(); |
| 32 | + WidgetsBinding.instance.addPostFrameCallback((_) { | ||
| 33 | + _getQiniuInfo(); | ||
| 34 | + }); | ||
| 28 | _focusNode.addListener(() { | 35 | _focusNode.addListener(() { |
| 29 | if (_focusNode.hasFocus) { | 36 | if (_focusNode.hasFocus) { |
| 30 | //有焦点 | 37 | //有焦点 |
| @@ -36,6 +43,18 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | @@ -36,6 +43,18 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | ||
| 36 | }); | 43 | }); |
| 37 | } | 44 | } |
| 38 | 45 | ||
| 46 | + @override | ||
| 47 | + void dispose() { | ||
| 48 | + super.dispose(); | ||
| 49 | + // _onlineCheckEditProvider | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + ///获取七牛云token | ||
| 53 | + /// | ||
| 54 | + _getQiniuInfo() async { | ||
| 55 | + await _onlineCheckEditProvider.getQiniuInfo(context, {}); | ||
| 56 | + } | ||
| 57 | + | ||
| 39 | ///顶部logo | 58 | ///顶部logo |
| 40 | Widget _getLogoWidget() { | 59 | Widget _getLogoWidget() { |
| 41 | return Column( | 60 | return Column( |
| @@ -156,9 +175,87 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | @@ -156,9 +175,87 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | ||
| 156 | ); | 175 | ); |
| 157 | } | 176 | } |
| 158 | 177 | ||
| 159 | - ///消费清单 | 178 | + ///顾客信息 |
| 179 | + Widget _customInfoItemWidget(String title, String subTitle) { | ||
| 180 | + return Row( | ||
| 181 | + mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
| 182 | + children: [ | ||
| 183 | + Text( | ||
| 184 | + title, | ||
| 185 | + style: TextStyle( | ||
| 186 | + fontSize: ScreenUtil().setSp(28), color: MyColours.color_707070), | ||
| 187 | + ), | ||
| 188 | + Text( | ||
| 189 | + subTitle, | ||
| 190 | + style: TextStyle( | ||
| 191 | + fontSize: ScreenUtil().setSp(28), | ||
| 192 | + color: MyColours.color_707070, | ||
| 193 | + fontWeight: FontWeight.bold), | ||
| 194 | + ) | ||
| 195 | + ], | ||
| 196 | + ); | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + Widget _customInfoWidget() { | ||
| 200 | + return Container( | ||
| 201 | + width: double.infinity, | ||
| 202 | + decoration: BoxDecoration( | ||
| 203 | + color: Colors.white, borderRadius: BorderRadius.circular(10)), | ||
| 204 | + child: Column( | ||
| 205 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 206 | + children: <Widget>[ | ||
| 207 | + Container( | ||
| 208 | + height: ScreenUtil().setWidth(53 * 2), | ||
| 209 | + width: double.infinity, | ||
| 210 | + decoration: BoxDecoration( | ||
| 211 | + color: MyColours.color_FAFAFA, | ||
| 212 | + borderRadius: BorderRadius.only( | ||
| 213 | + topLeft: Radius.circular(10), | ||
| 214 | + topRight: Radius.circular(10)), | ||
| 215 | + ), | ||
| 216 | + child: Padding( | ||
| 217 | + padding: EdgeInsets.fromLTRB( | ||
| 218 | + ScreenUtil().setWidth(20), | ||
| 219 | + ScreenUtil().setWidth(36), | ||
| 220 | + ScreenUtil().setWidth(20), | ||
| 221 | + ScreenUtil().setWidth(26)), | ||
| 222 | + child: Text( | ||
| 223 | + '顾客信息', | ||
| 224 | + style: TextStyle( | ||
| 225 | + fontSize: ScreenUtil().setSp(32), | ||
| 226 | + color: MyColours.color_353535, | ||
| 227 | + fontWeight: FontWeight.bold), | ||
| 228 | + ), | ||
| 229 | + )), | ||
| 230 | + Container( | ||
| 231 | + color: Colors.white, | ||
| 232 | + padding: EdgeInsets.fromLTRB( | ||
| 233 | + ScreenUtil().setWidth(40), | ||
| 234 | + ScreenUtil().setWidth(24), | ||
| 235 | + ScreenUtil().setWidth(40), | ||
| 236 | + ScreenUtil().setWidth(36)), | ||
| 237 | + child: Column( | ||
| 238 | + children: [ | ||
| 239 | + _customInfoItemWidget('买单顾客', 'ffff'), | ||
| 240 | + VEmptyView(24), | ||
| 241 | + _customInfoItemWidget('顾客电话', 'ffff'), | ||
| 242 | + VEmptyView(24), | ||
| 243 | + _customInfoItemWidget('到店时间', 'ffff'), | ||
| 244 | + VEmptyView(24), | ||
| 245 | + _customInfoItemWidget('申请时间', 'ffff') | ||
| 246 | + ], | ||
| 247 | + ), | ||
| 248 | + ) | ||
| 249 | + // _getGridImg(1, context) | ||
| 250 | + ], | ||
| 251 | + ), | ||
| 252 | + ); | ||
| 253 | + } | ||
| 254 | + | ||
| 160 | @override | 255 | @override |
| 161 | Widget build(BuildContext context) { | 256 | Widget build(BuildContext context) { |
| 257 | + _onlineCheckEditProvider = | ||
| 258 | + Provider.of<OnlineCheckEditProvider>(context, listen: true); | ||
| 162 | return Scaffold( | 259 | return Scaffold( |
| 163 | backgroundColor: MyColours.color_f5f5f5, | 260 | backgroundColor: MyColours.color_f5f5f5, |
| 164 | appBar: SystemAppBar( | 261 | appBar: SystemAppBar( |
| @@ -197,7 +294,9 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | @@ -197,7 +294,9 @@ class _OnlineCheckEditPageState extends State<OnlineCheckEditPage> { | ||
| 197 | ), | 294 | ), |
| 198 | ), | 295 | ), |
| 199 | VEmptyView(20), | 296 | VEmptyView(20), |
| 200 | - ImgPickerWidget() | 297 | + ImgPickerWidget(scrollController: _scrollController), |
| 298 | + VEmptyView(20), | ||
| 299 | + _customInfoWidget() | ||
| 201 | ], | 300 | ], |
| 202 | )), | 301 | )), |
| 203 | ), | 302 | ), |
lib/pages/online_check/progress.dart
0 → 100644
| 1 | +import 'package:flutter/material.dart'; | ||
| 2 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
| 3 | +import 'package:one_key/res/colors.dart'; | ||
| 4 | + | ||
| 5 | +class Progress extends StatelessWidget { | ||
| 6 | + final double value; | ||
| 7 | + Progress(this.value); | ||
| 8 | + | ||
| 9 | + Widget get progress { | ||
| 10 | + return Container( | ||
| 11 | + width: ScreenUtil().setWidth(30), | ||
| 12 | + height: ScreenUtil().setWidth(30), | ||
| 13 | + padding: EdgeInsets.all(10), | ||
| 14 | + color: Colors.red, | ||
| 15 | + child: CircularProgressIndicator( | ||
| 16 | + value: value, | ||
| 17 | + // strokeWidth: 14, | ||
| 18 | + backgroundColor: Colors.grey[200], | ||
| 19 | + ), | ||
| 20 | + ); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + Widget get progressText { | ||
| 24 | + final integer = (value * 100).toInt(); //当前上传进度 | ||
| 25 | + final decimal = (((value * 100) - integer) * 100).toInt(); //剩余进度 | ||
| 26 | + final unit = '%'; | ||
| 27 | + | ||
| 28 | + return DefaultTextStyle( | ||
| 29 | + style: TextStyle( | ||
| 30 | + color: Colors.black87, | ||
| 31 | + // fontWeight: FontWeight.bold, | ||
| 32 | + ), | ||
| 33 | + child: | ||
| 34 | + // Row( | ||
| 35 | + // mainAxisSize: MainAxisSize.min, | ||
| 36 | + // children: [ | ||
| 37 | + // Text( | ||
| 38 | + // integer.toString(), | ||
| 39 | + // style: TextStyle(fontSize: ScreenUtil().setSp(13)), | ||
| 40 | + // ), | ||
| 41 | + // Column( | ||
| 42 | + // children: [ | ||
| 43 | + Container( | ||
| 44 | + width: ScreenUtil().setWidth(100 * 2), | ||
| 45 | + height: ScreenUtil().setWidth(100 * 2), | ||
| 46 | + color: Color.fromRGBO(0, 0, 0, 0.5), | ||
| 47 | + child: Center( | ||
| 48 | + child: Text('${integer}${unit}', | ||
| 49 | + style: TextStyle( | ||
| 50 | + fontSize: ScreenUtil().setSp(24), | ||
| 51 | + color: MyColours.color_fefefe)), | ||
| 52 | + )) | ||
| 53 | + | ||
| 54 | + // Text('.$decimal', | ||
| 55 | + // style: TextStyle(fontSize: ScreenUtil().setSp(13))), | ||
| 56 | + // ], | ||
| 57 | + // ) | ||
| 58 | + // ], | ||
| 59 | + ); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @override | ||
| 63 | + Widget build(BuildContext context) { | ||
| 64 | + // return Stack( | ||
| 65 | + // alignment: AlignmentDirectional.center, | ||
| 66 | + // children: [progress, progressText], | ||
| 67 | + // ); | ||
| 68 | + return progressText; | ||
| 69 | + } | ||
| 70 | +} |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | +import 'package:one_key/constant/constant.dart'; | ||
| 3 | +import 'package:one_key/models/qiniu_info_model.dart'; | ||
| 4 | +import 'package:one_key/net/base_resp.dart'; | ||
| 5 | +import 'package:one_key/net/dio_util.dart'; | ||
| 6 | +import 'package:one_key/net/http_url.dart'; | ||
| 7 | +import 'package:one_key/utils/utils.dart'; | ||
| 2 | 8 | ||
| 3 | class OnlineCheckEditProvider extends ChangeNotifier { | 9 | class OnlineCheckEditProvider extends ChangeNotifier { |
| 4 | - List imageList = []; //图片数组 | 10 | + List imageListFile = []; //本地图片显示 |
| 11 | + List imageListUrl = []; //七牛云地址 | ||
| 12 | + Map statusMap = {}; //图片上传状态 <bool> true显示图片 ******* false显示进度 | ||
| 13 | + QiniuInfoSunModel qiniuInfoSunModel; | ||
| 14 | + // Map statusMapProgress = {}; //图片上传状态 <bool> true显示图片 ******* false显示进度 | ||
| 15 | + | ||
| 16 | + /// 获取七牛上传token信息 | ||
| 17 | + Future<QiniuInfoSunModel> getQiniuInfo( | ||
| 18 | + BuildContext context, Map<String, String> params, | ||
| 19 | + {isShowLoading = true}) async { | ||
| 20 | + BaseResp<Map<String, dynamic>> baseResp = await DioUtil() | ||
| 21 | + .request<Map<String, dynamic>>( | ||
| 22 | + context, Method.get, HttpUrl.get_qiniu_info, | ||
| 23 | + data: params, showLoading: false) | ||
| 24 | + .catchError((error) {}); | ||
| 25 | + if (baseResp.code == Constant.status_success) { | ||
| 26 | + if (baseResp.data.isEmpty) { | ||
| 27 | + } else { | ||
| 28 | + //解析解析 | ||
| 29 | + qiniuInfoSunModel = QiniuInfoModel.fromJson(baseResp.responseData).data; | ||
| 30 | + return qiniuInfoSunModel; | ||
| 31 | + } | ||
| 32 | + } else { | ||
| 33 | + if (baseResp != null) { | ||
| 34 | + Utils.showToast(baseResp.msg ?? ""); | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + } | ||
| 5 | } | 38 | } |
| @@ -57,4 +57,5 @@ class MyColours { | @@ -57,4 +57,5 @@ class MyColours { | ||
| 57 | static const Color color_9C9C9C = Color(0xff9C9C9C); | 57 | static const Color color_9C9C9C = Color(0xff9C9C9C); |
| 58 | static const Color color_FD5656 = Color(0xffFD5656); | 58 | static const Color color_FD5656 = Color(0xffFD5656); |
| 59 | static const Color color_FAFAFA = Color(0xffFAFAFA); | 59 | static const Color color_FAFAFA = Color(0xffFAFAFA); |
| 60 | + static const Color color_0D0D0D = Color(0xff0D0D0D); | ||
| 60 | } | 61 | } |
| @@ -667,6 +667,20 @@ packages: | @@ -667,6 +667,20 @@ packages: | ||
| 667 | url: "https://pub.flutter-io.cn" | 667 | url: "https://pub.flutter-io.cn" |
| 668 | source: hosted | 668 | source: hosted |
| 669 | version: "3.1.0" | 669 | version: "3.1.0" |
| 670 | + photo: | ||
| 671 | + dependency: "direct main" | ||
| 672 | + description: | ||
| 673 | + name: photo | ||
| 674 | + url: "https://pub.flutter-io.cn" | ||
| 675 | + source: hosted | ||
| 676 | + version: "0.4.8" | ||
| 677 | + photo_manager: | ||
| 678 | + dependency: transitive | ||
| 679 | + description: | ||
| 680 | + name: photo_manager | ||
| 681 | + url: "https://pub.flutter-io.cn" | ||
| 682 | + source: hosted | ||
| 683 | + version: "0.4.8" | ||
| 670 | photo_view: | 684 | photo_view: |
| 671 | dependency: "direct main" | 685 | dependency: "direct main" |
| 672 | description: | 686 | description: |
| @@ -996,27 +1010,6 @@ packages: | @@ -996,27 +1010,6 @@ packages: | ||
| 996 | url: "https://pub.flutter-io.cn" | 1010 | url: "https://pub.flutter-io.cn" |
| 997 | source: hosted | 1011 | source: hosted |
| 998 | version: "2.1.0-nullsafety.3" | 1012 | version: "2.1.0-nullsafety.3" |
| 999 | - video_player: | ||
| 1000 | - dependency: "direct main" | ||
| 1001 | - description: | ||
| 1002 | - name: video_player | ||
| 1003 | - url: "https://pub.flutter-io.cn" | ||
| 1004 | - source: hosted | ||
| 1005 | - version: "0.10.12+5" | ||
| 1006 | - video_player_platform_interface: | ||
| 1007 | - dependency: transitive | ||
| 1008 | - description: | ||
| 1009 | - name: video_player_platform_interface | ||
| 1010 | - url: "https://pub.flutter-io.cn" | ||
| 1011 | - source: hosted | ||
| 1012 | - version: "2.2.0" | ||
| 1013 | - video_player_web: | ||
| 1014 | - dependency: transitive | ||
| 1015 | - description: | ||
| 1016 | - name: video_player_web | ||
| 1017 | - url: "https://pub.flutter-io.cn" | ||
| 1018 | - source: hosted | ||
| 1019 | - version: "0.1.4+1" | ||
| 1020 | watcher: | 1013 | watcher: |
| 1021 | dependency: transitive | 1014 | dependency: transitive |
| 1022 | description: | 1015 | description: |
| @@ -90,11 +90,14 @@ dependencies: | @@ -90,11 +90,14 @@ dependencies: | ||
| 90 | easy_contact_picker: ^0.0.2 | 90 | easy_contact_picker: ^0.0.2 |
| 91 | flutter_app_badger: ^1.1.2 | 91 | flutter_app_badger: ^1.1.2 |
| 92 | scrollable_positioned_list: ^0.1.8 | 92 | scrollable_positioned_list: ^0.1.8 |
| 93 | - image_picker: ^0.6.7+21 | ||
| 94 | - video_player: ^0.10.3 | 93 | +#查看大图 |
| 95 | photo_view: ^0.9.2 | 94 | photo_view: ^0.9.2 |
| 96 | #七牛云sdk | 95 | #七牛云sdk |
| 97 | qiniu_flutter_sdk: ^0.2.0 | 96 | qiniu_flutter_sdk: ^0.2.0 |
| 97 | + #相机拍照,单图选择 | ||
| 98 | + image_picker: ^0.6.7+21 | ||
| 99 | + #多图选择 | ||
| 100 | + photo: ^0.4.8 | ||
| 98 | 101 | ||
| 99 | 102 | ||
| 100 | 103 |
-
Please register or login to post a comment