# Conflicts: # ios/Podfile.lock # ios/Runner.xcodeproj/project.pbxproj # lib/home/home_page.dart # lib/main.dart # pubspec.lockwr_2023_business
After Width: | Height: | Size: 812 B |
After Width: | Height: | Size: 736 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 840 B |
After Width: | Height: | Size: 824 B |
After Width: | Height: | Size: 596 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1016 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 666 B |
After Width: | Height: | Size: 672 B |
After Width: | Height: | Size: 622 B |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 724 B |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 666 B |
After Width: | Height: | Size: 574 B |
After Width: | Height: | Size: 980 B |
After Width: | Height: | Size: 888 B |
@ -0,0 +1,14 @@
|
||||
{ |
||||
"热门城市": [ |
||||
{"area": "武汉"}, |
||||
{"area": "北京"}, |
||||
{ "area": "郑州" } |
||||
], |
||||
"B": [ |
||||
{ "area": "北京" } |
||||
], |
||||
"W": [{ "area": "武汉" }], |
||||
"Z": [ |
||||
{ "area": "郑州" } |
||||
] |
||||
} |
@ -0,0 +1,367 @@
|
||||
import 'dart:convert'; |
||||
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
||||
import '../../retrofit/retrofit_api.dart'; |
||||
import '../../utils/captcha_util.dart'; |
||||
import '../../utils/widget_util.dart'; |
||||
|
||||
typedef VoidSuccessCallback = dynamic Function(String v); |
||||
|
||||
class ClickWordCaptcha extends StatefulWidget { |
||||
final VoidSuccessCallback onSuccess; //文字点击后验证成功回调 |
||||
final VoidCallback onFail; //文字点击完成后验证失败回调 |
||||
|
||||
const ClickWordCaptcha({Key key, this.onSuccess, this.onFail}) |
||||
: super(key: key); |
||||
|
||||
@override |
||||
_ClickWordCaptchaState createState() => _ClickWordCaptchaState(); |
||||
} |
||||
|
||||
class _ClickWordCaptchaState extends State<ClickWordCaptcha> { |
||||
ClickWordCaptchaState _clickWordCaptchaState = ClickWordCaptchaState.none; |
||||
List<Offset> _tapOffsetList = []; |
||||
ClickWordCaptchaModel _clickWordCaptchaModel = ClickWordCaptchaModel(); |
||||
|
||||
Color titleColor = Colors.black; |
||||
Color borderColor = Color(0xffdddddd); |
||||
String bottomTitle = ""; |
||||
Size baseSize = Size(310.0, 155.0); |
||||
|
||||
//改变底部样式及字段 |
||||
_changeResultState() { |
||||
switch (_clickWordCaptchaState) { |
||||
case ClickWordCaptchaState.normal: |
||||
titleColor = Colors.black; |
||||
borderColor = Color(0xffdddddd); |
||||
break; |
||||
case ClickWordCaptchaState.success: |
||||
_tapOffsetList = []; |
||||
titleColor = Colors.green; |
||||
borderColor = Colors.green; |
||||
bottomTitle = "验证成功"; |
||||
break; |
||||
case ClickWordCaptchaState.fail: |
||||
_tapOffsetList = []; |
||||
titleColor = Colors.red; |
||||
borderColor = Colors.red; |
||||
bottomTitle = "验证失败"; |
||||
break; |
||||
default: |
||||
titleColor = Colors.black; |
||||
borderColor = Color(0xffdddddd); |
||||
bottomTitle = "数据加载中……"; |
||||
break; |
||||
} |
||||
setState(() {}); |
||||
} |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_loadCaptcha(); |
||||
} |
||||
|
||||
//加载验证码 |
||||
_loadCaptcha() async { |
||||
_tapOffsetList = []; |
||||
_clickWordCaptchaState = ClickWordCaptchaState.none; |
||||
_changeResultState(); |
||||
ApiService apiIpService = ApiService(Dio(), context: context); |
||||
ClickWordCaptchaModel baseData = await apiIpService.captchaGet({"captchaType": "clickWord"}).catchError((onError) {}); |
||||
if (baseData == null) { |
||||
_clickWordCaptchaModel.secretKey = ""; |
||||
bottomTitle = "加载失败,请刷新"; |
||||
_clickWordCaptchaState = ClickWordCaptchaState.normal; |
||||
_changeResultState(); |
||||
return; |
||||
} |
||||
else { |
||||
_clickWordCaptchaModel = baseData; |
||||
var baseR = await WidgetUtil.getImageWH( |
||||
image: Image.memory( |
||||
Base64Decoder().convert(_clickWordCaptchaModel.imgStr))); |
||||
baseSize = baseR.size; |
||||
|
||||
bottomTitle = "请依次点击【${_clickWordCaptchaModel.wordStr}】"; |
||||
} |
||||
|
||||
_clickWordCaptchaState = ClickWordCaptchaState.normal; |
||||
_changeResultState(); |
||||
} |
||||
|
||||
//校验验证码 |
||||
_checkCaptcha() async { |
||||
List<Map<String, dynamic>> mousePos = []; |
||||
_tapOffsetList.map((size) { |
||||
mousePos |
||||
.add({"x": size.dx.roundToDouble(), "y": size.dy.roundToDouble()}); |
||||
}).toList(); |
||||
var pointStr = json.encode(mousePos); |
||||
|
||||
var cryptedStr = pointStr; |
||||
|
||||
// secretKey 不为空 进行as加密 |
||||
if (!CaptchaUtil.isEmpty(_clickWordCaptchaModel.secretKey)) { |
||||
cryptedStr = CaptchaUtil.aesEncode( |
||||
key: _clickWordCaptchaModel.secretKey, content: pointStr); |
||||
// var dcrypt = CaptchaUtil.aesDecode( |
||||
// key: _clickWordCaptchaModel.secretKey, content: cryptedStr); |
||||
} |
||||
|
||||
// Map _map = json.decode(dcrypt); |
||||
ApiService apiIpService = ApiService(Dio(), context: context); |
||||
bool baseData = await apiIpService.captchaCheck({ |
||||
"pointJson": cryptedStr, |
||||
"captchaType": "clickWord", |
||||
"token": _clickWordCaptchaModel.token |
||||
}).catchError((onError) {}); |
||||
if (baseData) { |
||||
_checkFail(); |
||||
return; |
||||
} |
||||
//如果不加密 将 token 和 坐标序列化 通过 --- 链接成字符串 |
||||
var captchaVerification = "${_clickWordCaptchaModel.token}---$pointStr"; |
||||
if (!CaptchaUtil.isEmpty(_clickWordCaptchaModel.secretKey)) { |
||||
//如果加密 将 token 和 坐标序列化 通过 --- 链接成字符串 进行加密 加密密钥为 _clickWordCaptchaModel.secretKey |
||||
captchaVerification = CaptchaUtil.aesEncode( |
||||
key: _clickWordCaptchaModel.secretKey, |
||||
content: captchaVerification); |
||||
} |
||||
_checkSuccess(captchaVerification); |
||||
} |
||||
|
||||
//校验失败 |
||||
_checkFail() async { |
||||
_clickWordCaptchaState = ClickWordCaptchaState.fail; |
||||
_changeResultState(); |
||||
|
||||
await Future.delayed(Duration(milliseconds: 1000)); |
||||
_loadCaptcha(); |
||||
//回调 |
||||
if (widget.onFail != null) { |
||||
widget.onFail(); |
||||
} |
||||
} |
||||
|
||||
//校验成功 |
||||
_checkSuccess(String pointJson) async { |
||||
_clickWordCaptchaState = ClickWordCaptchaState.success; |
||||
_changeResultState(); |
||||
|
||||
await Future.delayed(Duration(milliseconds: 1000)); |
||||
|
||||
var cryptedStr = CaptchaUtil.aesEncode(key: 'BGxdEUOZkXka4HSj', content: pointJson); |
||||
|
||||
print(cryptedStr); |
||||
//回调 pointJson 是经过es加密之后的信息 |
||||
if (widget.onSuccess != null) { |
||||
widget.onSuccess(cryptedStr); |
||||
} |
||||
//关闭 |
||||
Navigator.pop(context); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
var data = MediaQuery.of(context); |
||||
var dialogWidth = 0.9 * data.size.width; |
||||
var isRatioCross = false; |
||||
if (dialogWidth < 320.0) { |
||||
dialogWidth = data.size.width; |
||||
isRatioCross = true; |
||||
} |
||||
return Scaffold( |
||||
backgroundColor: Colors.transparent, |
||||
body: Center( |
||||
child: Container( |
||||
width: dialogWidth, |
||||
height: 320.h, |
||||
color: Colors.white, |
||||
child: Column( |
||||
children: <Widget>[ |
||||
_topConttainer(), |
||||
_captchaContainer(), |
||||
_bottomContainer() |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
//图片验证码 |
||||
_captchaContainer() { |
||||
List<Widget> _widgetList = []; |
||||
if (!CaptchaUtil.isEmpty(_clickWordCaptchaModel.imgStr)) { |
||||
_widgetList.add(Image( |
||||
width: baseSize.width, |
||||
height: baseSize.height, |
||||
gaplessPlayback: true, |
||||
image: MemoryImage( |
||||
Base64Decoder().convert(_clickWordCaptchaModel.imgStr)))); |
||||
} |
||||
|
||||
double _widgetW = 20; |
||||
for (int i = 0; i < _tapOffsetList.length; i++) { |
||||
Offset offset = _tapOffsetList[i]; |
||||
_widgetList.add(Positioned( |
||||
left: offset.dx - _widgetW * 0.5, |
||||
top: offset.dy - _widgetW * 0.5, |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
width: _widgetW, |
||||
height: _widgetW, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xCC43A047), |
||||
borderRadius: BorderRadius.all(Radius.circular(_widgetW))), |
||||
child: Text( |
||||
"${i + 1}", |
||||
style: TextStyle(color: Colors.white, fontSize: 15), |
||||
), |
||||
))); |
||||
} |
||||
_widgetList.add(//刷新按钮 |
||||
Positioned( |
||||
top: 0, |
||||
right: 0, |
||||
child: IconButton( |
||||
icon: Icon(Icons.refresh), |
||||
iconSize: 30, |
||||
color: Colors.deepOrangeAccent, |
||||
onPressed: () { |
||||
//刷新 |
||||
_loadCaptcha(); |
||||
}), |
||||
)); |
||||
|
||||
return GestureDetector( |
||||
onTapDown: (TapDownDetails details) { |
||||
debugPrint( |
||||
"onTapDown globalPosition全局坐标系位置: ${details.globalPosition} localPosition组件坐标系位置: ${details.localPosition} "); |
||||
if (!CaptchaUtil.isListEmpty(_clickWordCaptchaModel.wordList) && |
||||
_tapOffsetList.length < _clickWordCaptchaModel.wordList.length) { |
||||
_tapOffsetList.add( |
||||
Offset(details.localPosition.dx, details.localPosition.dy)); |
||||
} |
||||
setState(() {}); |
||||
if (!CaptchaUtil.isListEmpty(_clickWordCaptchaModel.wordList) && |
||||
_tapOffsetList.length == _clickWordCaptchaModel.wordList.length) { |
||||
_checkCaptcha(); |
||||
} |
||||
}, |
||||
child: Container( |
||||
width: baseSize.width, |
||||
height: baseSize.height, |
||||
child: Stack( |
||||
children: _widgetList, |
||||
), |
||||
)); |
||||
} |
||||
|
||||
//底部提示部件 |
||||
_bottomContainer() { |
||||
return Container( |
||||
height: 50.h, |
||||
margin: EdgeInsets.only(top: 10), |
||||
alignment: Alignment.center, |
||||
width: baseSize.width, |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.all(Radius.circular(4)), |
||||
border: Border.all(color: borderColor)), |
||||
child: |
||||
Text(bottomTitle, style: TextStyle(fontSize: 18, color: titleColor)), |
||||
); |
||||
} |
||||
|
||||
//顶部,提示+关闭 |
||||
_topConttainer() { |
||||
return Container( |
||||
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), |
||||
margin: EdgeInsets.only(bottom: 20, top: 5), |
||||
decoration: BoxDecoration( |
||||
border: Border(bottom: BorderSide(width: 1, color: Color(0xffe5e5e5))), |
||||
), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
children: <Widget>[ |
||||
Text( |
||||
'请完成安全验证', |
||||
style: TextStyle(fontSize: 18), |
||||
), |
||||
IconButton( |
||||
icon: Icon(Icons.highlight_off), |
||||
iconSize: 35, |
||||
color: Colors.black54, |
||||
onPressed: () { |
||||
//退出 |
||||
Navigator.pop(context); |
||||
}), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
//校验状态 |
||||
enum ClickWordCaptchaState { |
||||
normal, //默认 可自定义描述 |
||||
success, //成功 |
||||
fail, //失败 |
||||
none, //无状态 用于加载使用 |
||||
} |
||||
|
||||
//请求数据模型 |
||||
class ClickWordCaptchaModel { |
||||
String imgStr; //图表url 目前用base64 data |
||||
String jigsawImageBase64; //图表url 目前用base64 data |
||||
String token; // 获取的token 用于校验 |
||||
List wordList; //显示需要点选的字 |
||||
String wordStr; //显示需要点选的字转换为字符串 |
||||
String secretKey; //加密key |
||||
|
||||
ClickWordCaptchaModel( |
||||
{this.imgStr = "", |
||||
this.jigsawImageBase64 = "", |
||||
this.token = "", |
||||
this.secretKey = "", |
||||
this.wordList = const [], |
||||
this.wordStr = ""}); |
||||
|
||||
//解析数据转换模型 |
||||
static ClickWordCaptchaModel fromMap(Map<String, dynamic> map) { |
||||
ClickWordCaptchaModel captchaModel = ClickWordCaptchaModel(); |
||||
captchaModel.imgStr = map["originalImageBase64"] ?? ""; |
||||
captchaModel.jigsawImageBase64 = map["jigsawImageBase64"] ?? ""; |
||||
captchaModel.token = map["token"] ?? ""; |
||||
captchaModel.secretKey = map["secretKey"] ?? ""; |
||||
captchaModel.wordList = map["wordList"] ?? []; |
||||
|
||||
if (!CaptchaUtil.isListEmpty(captchaModel.wordList)) { |
||||
captchaModel.wordStr = captchaModel.wordList.join(","); |
||||
} |
||||
|
||||
return captchaModel; |
||||
} |
||||
|
||||
//将模型转换 |
||||
Map<String, dynamic> toJson() { |
||||
var map = new Map<String, dynamic>(); |
||||
map['imgStr'] = imgStr; |
||||
map['jigsawImageBase64'] = jigsawImageBase64; |
||||
map['token'] = token; |
||||
map['secretKey'] = token; |
||||
map['wordList'] = wordList; |
||||
map['wordStr'] = wordStr; |
||||
return map; |
||||
} |
||||
|
||||
@override |
||||
String toString() { |
||||
// TODO: implement toString |
||||
return JsonEncoder.withIndent(' ').convert(toJson()); |
||||
} |
||||
} |
@ -0,0 +1,908 @@
|
||||
import 'dart:io'; |
||||
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_html/flutter_html.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:fluwx/fluwx.dart'; |
||||
import 'package:huixiang/generated/l10n.dart'; |
||||
import 'package:huixiang/retrofit/data/base_data.dart'; |
||||
import 'package:huixiang/retrofit/data/vip_card.dart'; |
||||
import 'package:huixiang/retrofit/retrofit_api.dart'; |
||||
import 'package:huixiang/store/scan.dart'; |
||||
import 'package:huixiang/utils/font_weight.dart'; |
||||
import 'package:huixiang/view_widget/custom_image.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
|
||||
import '../retrofit/data/member_recharge_list.dart'; |
||||
import '../retrofit/data/rechargeActLists.dart'; |
||||
import '../retrofit/data/wx_pay.dart'; |
||||
import '../retrofit/min_api.dart'; |
||||
import '../utils/flutter_utils.dart'; |
||||
import '../utils/min.dart'; |
||||
import '../view_widget/classic_header.dart'; |
||||
import '../view_widget/my_footer.dart'; |
||||
import '../view_widget/no_data_view.dart'; |
||||
import '../view_widget/recharge_details_dialog.dart'; |
||||
import 'package:tobias/tobias.dart' as tobias; |
||||
|
||||
class MineShopRecharge extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
MineShopRecharge({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _MineShopRecharge(); |
||||
} |
||||
} |
||||
|
||||
class _MineShopRecharge extends State<MineShopRecharge> { |
||||
ApiService apiService; |
||||
MinApiService minService; |
||||
VipCard vipCard; |
||||
List<MemberRechargeList> memberRechargeList = []; |
||||
int selectIndex = 0; |
||||
double discount = 100; |
||||
var checkIndex = 2; |
||||
dynamic payListen; |
||||
int _loadCount = 0; |
||||
String tenant; |
||||
String storeId; |
||||
String minToken; |
||||
final RefreshController refreshController = RefreshController(); |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
refreshController.dispose(); |
||||
if (payListen != null) payListen.cancel(); |
||||
} |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
storeId = widget.arguments["storeId"]; |
||||
tenant = widget.arguments["tenantCode"]; |
||||
_onRefresh(); |
||||
payListen = weChatResponseEventHandler.listen((event) async { |
||||
print("payCallback: ${event.errCode}"); |
||||
if (event.errCode == 0) { |
||||
SmartDialog.showToast("充值成功", alignment: Alignment.center); |
||||
} else { |
||||
SmartDialog.showToast("充值失败", alignment: Alignment.center); |
||||
} |
||||
vipDetail(); |
||||
}); |
||||
} |
||||
|
||||
///会员卡详情 |
||||
vipDetail({bool isSingle = true}) async { |
||||
try { |
||||
BaseData<VipCard> baseData = await apiService.vipDetail({ |
||||
"id": widget.arguments["id"], |
||||
"latitude": "", |
||||
"longitude": "", |
||||
}).catchError((onError) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
vipCard = baseData.data; |
||||
} |
||||
} finally { |
||||
if (isSingle) |
||||
setState(() {}); |
||||
else |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
|
||||
///小程序登录 |
||||
minLogin() async { |
||||
try { |
||||
var baseData = await apiService.minLogin(storeId).catchError((onError) { |
||||
debugPrint(onError.toString()); |
||||
}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
minToken = baseData.data["token"]; |
||||
SharedPreferences.getInstance().then( |
||||
(value) => { |
||||
value.setString('minToken', minToken), |
||||
value.setString('tenant', tenant), |
||||
value.setString('storeId', storeId), |
||||
}, |
||||
); |
||||
minService = MinApiService( |
||||
Dio(), |
||||
context: context, |
||||
token: minToken, |
||||
tenant: tenant, |
||||
storeId: storeId, |
||||
); |
||||
} |
||||
} finally {} |
||||
} |
||||
|
||||
///充值列表 |
||||
queryRechargeActList() async { |
||||
try { |
||||
BaseData<List<MemberRechargeList>> baseData = |
||||
await minService.memberRechargeList().catchError((onError) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
memberRechargeList = baseData.data; |
||||
} |
||||
} finally { |
||||
addLoadCount(); |
||||
} |
||||
} |
||||
|
||||
///门店充值 |
||||
shopRecharge() async { |
||||
if (minService == null) await minLogin(); |
||||
BaseData<dynamic> baseData = await minService.memberRecharge({ |
||||
"money": 0, |
||||
"rechargeId": memberRechargeList[selectIndex].id, |
||||
"type": checkIndex == 2 ? "wechat" : "alipay", |
||||
}).catchError((error) {}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
if (checkIndex == 2) { |
||||
if (Platform.isAndroid) { |
||||
if (!(await Min.isInitialize())) { |
||||
// 小程序的微信支付和app的充值支付使用同一个WXPayEntryActivity回调, |
||||
// 然而充值时小程序未初始化会导致回调内部代码调用getPackage空指针, |
||||
// 故而在此初始化一下 |
||||
await Min.initialize(); |
||||
} |
||||
} |
||||
WxPay wxPay = WxPay.fromJson(baseData.data); |
||||
await registerWxApi( |
||||
appId: wxPay.appId, |
||||
doOnAndroid: true, |
||||
universalLink: "https://hx.lotus-wallet.com/app/", |
||||
); |
||||
payWithWeChat( |
||||
appId: wxPay.appId, |
||||
partnerId: wxPay.partnerId, |
||||
prepayId: wxPay.prepayId, |
||||
packageValue: wxPay.packageValue, |
||||
nonceStr: wxPay.nonceStr, |
||||
timeStamp: int.tryParse(wxPay.timeStamp), |
||||
sign: wxPay.sign, |
||||
); |
||||
} else { |
||||
tobias.isAliPayInstalled().then((value) => { |
||||
// 判断是否安装了支付宝 |
||||
if (!value) |
||||
{SmartDialog.showToast("请安装支付宝", alignment: Alignment.center)} |
||||
else |
||||
{ |
||||
tobias.aliPay(baseData.data["body"]).then((payRes) { |
||||
if (payRes['resultStatus'] == 9000 || |
||||
payRes['resultStatus'] == '9000') { |
||||
SmartDialog.showToast("充值成功", |
||||
alignment: Alignment.center); |
||||
} else { |
||||
SmartDialog.showToast(payRes['memo'], |
||||
alignment: Alignment.center); |
||||
} |
||||
vipDetail(); |
||||
}) |
||||
} |
||||
}); |
||||
} |
||||
} else { |
||||
SmartDialog.showToast(baseData.msg, alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
_onRefresh() async { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black); |
||||
if (apiService == null) { |
||||
SharedPreferences value = await SharedPreferences.getInstance(); |
||||
apiService = |
||||
ApiService(Dio(), context: context, token: value.getString("token")); |
||||
} |
||||
if (minService == null) await minLogin(); |
||||
vipDetail(isSingle: false); |
||||
queryRechargeActList(); |
||||
} |
||||
|
||||
addLoadCount() { |
||||
_loadCount += 1; |
||||
if (_loadCount == 2) { |
||||
_loadCount = 0; |
||||
EasyLoading.dismiss(); |
||||
if (refreshController.isRefresh) refreshController.refreshCompleted(); |
||||
if (mounted) setState(() {}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "店铺充值", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
brightness: Brightness.dark, |
||||
leadingColor: Colors.black, |
||||
), |
||||
body: SmartRefresher( |
||||
enablePullDown: true, |
||||
enablePullUp: false, |
||||
header: MyHeader(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
controller: refreshController, |
||||
onRefresh: _onRefresh, |
||||
physics: BouncingScrollPhysics(), |
||||
child: Column( |
||||
children: [ |
||||
shopRechargeCard(), |
||||
(memberRechargeList != null && |
||||
(memberRechargeList?.length ?? 0) > 0) |
||||
? Expanded( |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: (memberRechargeList != null && |
||||
(memberRechargeList?.length ?? 0) > 0) |
||||
? memberRechargeList.length |
||||
: 0, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
selectIndex = position; |
||||
}); |
||||
}, |
||||
child: rechargeItem( |
||||
memberRechargeList[position], position)); |
||||
}, |
||||
)) |
||||
: NoDataView( |
||||
src: "assets/image/xiao_fei.webp", |
||||
isShowBtn: false, |
||||
text: "当前店铺暂无充值套餐~", |
||||
fontSize: 16.sp, |
||||
margin: |
||||
EdgeInsets.only(top: 90.h, left: 60.w, right: 60.w), |
||||
), |
||||
if (memberRechargeList != null && |
||||
(memberRechargeList?.length ?? 0) > 0) |
||||
Container( |
||||
width: double.infinity, |
||||
margin: EdgeInsets.only(left: 16, right: 16), |
||||
padding: EdgeInsets.only( |
||||
top: 20.h, |
||||
bottom: 24.h, |
||||
), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 16.h), |
||||
child: Text( |
||||
S.of(context).zhifufangshi, |
||||
style: TextStyle( |
||||
fontSize: 16.sp, |
||||
color: Colors.black, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
checkIndex = 2; |
||||
}); |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Image.asset("assets/image/icon_we_chat.webp"), |
||||
Expanded( |
||||
flex: 1, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(left: 8.w), |
||||
child: Text( |
||||
S.of(context).weixinzhifu, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xff353535), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
checkView(2), |
||||
], |
||||
), |
||||
), |
||||
SizedBox(height: 10.h), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
checkIndex = 3; |
||||
}); |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Image.asset("assets/image/icon_alipay.webp"), |
||||
Expanded( |
||||
flex: 1, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(left: 8.w), |
||||
child: Text( |
||||
S.of(context).zhifubao, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xff353535), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
checkView(3), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
if (memberRechargeList != null && |
||||
(memberRechargeList?.length ?? 0) > 0) |
||||
Align( |
||||
alignment: Alignment.bottomCenter, |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
shopRecharge(); |
||||
}, |
||||
child: Container( |
||||
height: 56.h, |
||||
width: double.infinity, |
||||
alignment: Alignment.center, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF32A060), |
||||
borderRadius: BorderRadius.circular(27), |
||||
), |
||||
margin: EdgeInsets.only( |
||||
top: 12.h, left: 16.w, right: 16.w, bottom: 21.h), |
||||
child: Text( |
||||
S.of(context).querenchongzhi, |
||||
style: TextStyle( |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Colors.white, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///卡片背景底色 |
||||
int colorByName(String storeName) { |
||||
if (storeName == null) return 0xFF32A060; |
||||
if (storeName.contains("百年川椒") || storeName.contains("百年川椒")) { |
||||
return 0xFFC30D23; |
||||
} else if (storeName.contains("海峡姐妹") || storeName.contains("海峽姐妹")) { |
||||
return 0xFFE4C796; |
||||
} else if (storeName.contains("前进麦味") || storeName.contains("前進麥味")) { |
||||
return 0xFF265782; |
||||
} |
||||
return 0xFF32A060; |
||||
} |
||||
|
||||
///卡片详情 |
||||
Widget shopRechargeCard() { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed('/router/mine_shop_details', |
||||
arguments: {"id": widget.arguments["id"]}); |
||||
}, |
||||
child: Container( |
||||
width: double.infinity, |
||||
// height:140.h, |
||||
margin: |
||||
EdgeInsets.only(bottom: 24.h, top: 14.h, left: 14.w, right: 14.w), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: new BorderRadius.only( |
||||
topLeft: Radius.circular(6), |
||||
topRight: Radius.circular(6), |
||||
), |
||||
color: Color(colorByName(vipCard?.tenantName ?? "")), |
||||
), |
||||
padding: EdgeInsets.only(left: 12.w), |
||||
height: 62.h, |
||||
child: Row( |
||||
children: [ |
||||
MImage( |
||||
(vipCard?.storeList?.length ?? 0) > 0 |
||||
? vipCard.storeList[0].logo |
||||
: "", |
||||
width: 38, |
||||
height: 38, |
||||
radius: BorderRadius.circular(100), |
||||
fit: BoxFit.cover, |
||||
errorSrc: "assets/image/default_1.webp", |
||||
fadeSrc: "assets/image/default_1.webp", |
||||
), |
||||
SizedBox( |
||||
width: 6, |
||||
), |
||||
Text( |
||||
vipCard != null ? vipCard.tenantName : "", |
||||
style: TextStyle( |
||||
color: Color(0xFFFFFFFF), |
||||
fontSize: 15.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: new BorderRadius.only( |
||||
bottomRight: Radius.circular(6), |
||||
topRight: Radius.circular(6), |
||||
), |
||||
color: Colors.white, |
||||
), |
||||
padding: EdgeInsets.all(12.h), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
"店铺余额(元)", |
||||
style: TextStyle( |
||||
color: Color(0xFF262626), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
Text( |
||||
"No.${vipCard?.id ?? ""}", |
||||
style: TextStyle( |
||||
color: Color(0xFF262626), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 4.h, |
||||
), |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"¥ ${vipCard != null ? vipCard.balance : ""}", |
||||
style: TextStyle( |
||||
color: Color(0xFF262626), |
||||
fontSize: 24.sp, |
||||
fontFamily: 'JDZhengHT', |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
), |
||||
Text( |
||||
"适用门店", |
||||
style: TextStyle( |
||||
color: Color(0xFF262626), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 2, |
||||
), |
||||
Image.asset( |
||||
"assets/image/icon_right_z.webp", |
||||
width: 16, |
||||
height: 16, |
||||
color: Color(0xFF262626), |
||||
) |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
///充值item |
||||
Widget rechargeItem(MemberRechargeList memberRechargeList, index) { |
||||
return Container( |
||||
width: double.infinity, |
||||
height: 69.h, |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.circular(4), |
||||
border: Border.all( |
||||
color: |
||||
selectIndex == index ? Color(0xFF32A060) : Color(0xFFFAFAFA), |
||||
width: selectIndex == index ? 1 : 0, |
||||
), |
||||
color: selectIndex == index ? Color(0XFFF0FAF4) : Colors.white), |
||||
margin: EdgeInsets.only(bottom: 14.h, left: 14.w, right: 14.w), |
||||
padding: EdgeInsets.only(left: 16), |
||||
child: Flex( |
||||
direction: Axis.horizontal, |
||||
children: [ |
||||
Expanded( |
||||
flex: 1, |
||||
child: Container( |
||||
child: Text.rich( |
||||
TextSpan(children: [ |
||||
TextSpan( |
||||
text: "储值 ", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: selectIndex == index |
||||
? Color(0xFF4D4D4D) |
||||
: Color(0xFF868686), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
TextSpan( |
||||
text: |
||||
"${AppUtils.calculateDouble(double.tryParse(memberRechargeList.rechargeMoney) ?? 0)}元", |
||||
style: TextStyle( |
||||
fontSize: 18.sp, |
||||
fontFamily: 'JDZhengHT', |
||||
color: selectIndex == index |
||||
? Color(0xFF353535) |
||||
: Color(0xFF868686), |
||||
fontWeight: MyFontWeight.semi_bold), |
||||
), |
||||
]), |
||||
), |
||||
)), |
||||
Container( |
||||
width: 1.w, |
||||
height: 37.h, |
||||
color: |
||||
selectIndex == index ? Color(0xFF32A060) : Color(0xFF979797), |
||||
margin: EdgeInsets.only(right: 16.w, left: 12), |
||||
), |
||||
Expanded( |
||||
flex: 2, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text.rich( |
||||
TextSpan(children: [ |
||||
TextSpan( |
||||
text: "实际到账 ", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: selectIndex == index |
||||
? Color(0xFF353535) |
||||
: Color(0xFF868686), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
TextSpan( |
||||
text: |
||||
"${((memberRechargeList?.limitNum ?? 0) != 0 && ((memberRechargeList?.limitNum ?? 0) - (memberRechargeList?.useNum ?? 0) <= 0)) ? |
||||
(AppUtils.calculateDouble(double.tryParse(memberRechargeList.rechargeMoney) ?? 0)) : |
||||
(AppUtils.calculateDouble((double.tryParse(memberRechargeList.rechargeMoney) ?? 0) + (double.tryParse(memberRechargeList.giftdMoney) ?? 0) + ((double.tryParse(memberRechargeList.rechargeMoney) ?? 0) - ((double.tryParse(memberRechargeList.rechargeMoney) ?? 0) * (discount / 100)))))}元", |
||||
style: TextStyle( |
||||
fontSize: 18.sp, |
||||
fontFamily: 'JDZhengHT', |
||||
color: selectIndex == index |
||||
? Color(0xFF353535) |
||||
: Color(0xFF868686), |
||||
fontWeight: MyFontWeight.semi_bold), |
||||
), |
||||
]), |
||||
), |
||||
SizedBox( |
||||
height: 4.h, |
||||
), |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
if (selectIndex == index) |
||||
showRecharge(memberRechargeList, index); |
||||
}); |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"充值说明", |
||||
style: TextStyle( |
||||
color: selectIndex == index |
||||
? Color(0xFF4D4D4D) |
||||
: Color(0xFF868686), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
Icon( |
||||
Icons.chevron_right, |
||||
size: 20, |
||||
color: selectIndex == index |
||||
? Color(0xFF353535) |
||||
: Color(0xFF868686), |
||||
), |
||||
], |
||||
)), |
||||
], |
||||
)) |
||||
], |
||||
)); |
||||
} |
||||
|
||||
Widget checkView(var index) { |
||||
return Container( |
||||
padding: EdgeInsets.only(right: 16.w, left: 46.w), |
||||
alignment: Alignment.center, |
||||
child: Image.asset( |
||||
checkIndex != index |
||||
? "assets/image/icon_radio_unselected.webp" |
||||
: "assets/image/icon_radio_selected.webp", |
||||
width: 15.w, |
||||
height: 15.h, |
||||
), |
||||
); |
||||
} |
||||
|
||||
///充值说明底部弹窗 |
||||
showRecharge(MemberRechargeList memberRechargeList, index) { |
||||
showModalBottomSheet( |
||||
context: context, |
||||
backgroundColor: Colors.transparent, |
||||
builder: (context) { |
||||
return Container( |
||||
padding: EdgeInsets.only(top: 12), |
||||
decoration: new BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: new BorderRadius.only( |
||||
topLeft: const Radius.circular(25.0), |
||||
topRight: const Radius.circular(25.0))), |
||||
child: Container( |
||||
height: 355, |
||||
child: SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Container( |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
alignment: Alignment.center, |
||||
child: Text( |
||||
"充值说明", |
||||
style: TextStyle( |
||||
fontWeight: MyFontWeight.bold, |
||||
fontSize: 15.sp, |
||||
color: Color(0xFF353535), |
||||
), |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
Navigator.of(context).pop(); |
||||
}); |
||||
}, |
||||
child: Icon( |
||||
Icons.clear, |
||||
color: Colors.black, |
||||
size: 18, |
||||
), |
||||
), |
||||
SizedBox(width: 14), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 12.h, |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0xFFF2F2F2), |
||||
margin: EdgeInsets.only(bottom: 13.h), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 14), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||
children: [ |
||||
Expanded( |
||||
child: Container( |
||||
color: Colors.white, |
||||
child: Html( |
||||
data: memberRechargeList?.remark ?? "", |
||||
customImageRenders: { |
||||
networkSourceMatcher(): |
||||
networkImageRender( |
||||
loadingWidget: () { |
||||
return Container(); |
||||
}, |
||||
), |
||||
}, |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
) |
||||
], |
||||
), |
||||
))); |
||||
}); |
||||
} |
||||
|
||||
Widget shopItem(StoreListBean store) { |
||||
return Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: new BorderRadius.circular(6), |
||||
color: Colors.white, |
||||
), |
||||
padding: EdgeInsets.all(12), |
||||
margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.spaceAround, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
children: [ |
||||
Expanded( |
||||
flex: 1, |
||||
child: Text( |
||||
(store != null) ? store.storeName : "", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.semi_bold, |
||||
color: Colors.black, |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
onTap: () { |
||||
// Navigator.of(context).pushNamed('/router/union_detail_page', |
||||
// arguments: {"id": store.id}); |
||||
if (store.posType.code == "NORMALSTORE") { |
||||
Scan.toScan( |
||||
context, |
||||
store.id, |
||||
store.tenantCode, |
||||
store.storeName, |
||||
); |
||||
} else { |
||||
Navigator.of(context).pushNamed( |
||||
'/router/store_order', |
||||
arguments: { |
||||
"id": store.id, |
||||
"tenant": store.tenantCode, |
||||
"storeName": store.storeName |
||||
}, |
||||
); |
||||
} |
||||
}, |
||||
child: Text( |
||||
S.of(context).chakan, |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xff32A060), |
||||
), |
||||
), |
||||
), |
||||
Icon( |
||||
Icons.chevron_right, |
||||
color: Color(0xff32A060), |
||||
size: 16, |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 8.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"${S.of(context).dizhi}: ", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xff353535), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Text( |
||||
store.address, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xff353535), |
||||
), |
||||
), |
||||
flex: 1, |
||||
) |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 4.h, |
||||
), |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
flex: 1, |
||||
child: Text( |
||||
S.of(context).yingyeshijian((store.openStartTime == null && |
||||
store.openEndTime == null) |
||||
? S.of(context).quantian |
||||
: "${store.openStartTime.substring(0, store.openStartTime.lastIndexOf(":"))} - ${store.openEndTime.substring(0, store.openEndTime.lastIndexOf(":"))}"), |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xff353535), |
||||
), |
||||
), |
||||
), |
||||
Text( |
||||
(store.distance ?? 0) > 1000 |
||||
? S.of(context).gongli( |
||||
((store.distance ?? 0) / 1000 * 100).toInt() / 100.0) |
||||
: S |
||||
.of(context) |
||||
.mi(((store.distance ?? 0) * 100).toInt() / 100.0), |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xff868686), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,105 @@
|
||||
/// ip : "27.18.151.119" |
||||
/// pro : "湖北省" |
||||
/// proCode : "420000" |
||||
/// city : "武汉市" |
||||
/// cityCode : "420100" |
||||
/// region : "" |
||||
/// regionCode : "0" |
||||
/// addr : "湖北省武汉市 电信" |
||||
/// regionNames : "" |
||||
/// err : "" |
||||
|
||||
class IpData { |
||||
IpData({ |
||||
String ip, |
||||
String pro, |
||||
String proCode, |
||||
String city, |
||||
String cityCode, |
||||
String region, |
||||
String regionCode, |
||||
String addr, |
||||
String regionNames, |
||||
String err,}){ |
||||
_ip = ip; |
||||
_pro = pro; |
||||
_proCode = proCode; |
||||
_city = city; |
||||
_cityCode = cityCode; |
||||
_region = region; |
||||
_regionCode = regionCode; |
||||
_addr = addr; |
||||
_regionNames = regionNames; |
||||
_err = err; |
||||
} |
||||
|
||||
IpData.fromJson(dynamic json) { |
||||
_ip = json['ip']; |
||||
_pro = json['pro']; |
||||
_proCode = json['proCode']; |
||||
_city = json['city']; |
||||
_cityCode = json['cityCode']; |
||||
_region = json['region']; |
||||
_regionCode = json['regionCode']; |
||||
_addr = json['addr']; |
||||
_regionNames = json['regionNames']; |
||||
_err = json['err']; |
||||
} |
||||
String _ip; |
||||
String _pro; |
||||
String _proCode; |
||||
String _city; |
||||
String _cityCode; |
||||
String _region; |
||||
String _regionCode; |
||||
String _addr; |
||||
String _regionNames; |
||||
String _err; |
||||
IpData copyWith({ String ip, |
||||
String pro, |
||||
String proCode, |
||||
String city, |
||||
String cityCode, |
||||
String region, |
||||
String regionCode, |
||||
String addr, |
||||
String regionNames, |
||||
String err, |
||||
}) => IpData( ip: ip ?? _ip, |
||||
pro: pro ?? _pro, |
||||
proCode: proCode ?? _proCode, |
||||
city: city ?? _city, |
||||
cityCode: cityCode ?? _cityCode, |
||||
region: region ?? _region, |
||||
regionCode: regionCode ?? _regionCode, |
||||
addr: addr ?? _addr, |
||||
regionNames: regionNames ?? _regionNames, |
||||
err: err ?? _err, |
||||
); |
||||
String get ip => _ip; |
||||
String get pro => _pro; |
||||
String get proCode => _proCode; |
||||
String get city => _city; |
||||
String get cityCode => _cityCode; |
||||
String get region => _region; |
||||
String get regionCode => _regionCode; |
||||
String get addr => _addr; |
||||
String get regionNames => _regionNames; |
||||
String get err => _err; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['ip'] = _ip; |
||||
map['pro'] = _pro; |
||||
map['proCode'] = _proCode; |
||||
map['city'] = _city; |
||||
map['cityCode'] = _cityCode; |
||||
map['region'] = _region; |
||||
map['regionCode'] = _regionCode; |
||||
map['addr'] = _addr; |
||||
map['regionNames'] = _regionNames; |
||||
map['err'] = _err; |
||||
return map; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,159 @@
|
||||
/// id : "1681490552371019776" |
||||
/// rechargeMoney : "100.00" |
||||
/// giftdMoney : "10.00" |
||||
/// limitNum : 0 |
||||
/// gitfdCouponId : null |
||||
/// startDate : null |
||||
/// endDate : null |
||||
/// startTime : null |
||||
/// endTime : null |
||||
/// tenantCode : "1175" |
||||
/// createTime : "2023-07-21 09:22:53" |
||||
/// isDeleted : 0 |
||||
/// rechargeType : 0 |
||||
/// remark : "充值100.00 赠送10.00" |
||||
/// sortValue : 0 |
||||
/// useNum : 0 |
||||
|
||||
class MemberRechargeList { |
||||
MemberRechargeList({ |
||||
String id, |
||||
String rechargeMoney, |
||||
String giftdMoney, |
||||
dynamic limitNum, |
||||
dynamic gitfdCouponId, |
||||
dynamic startDate, |
||||
dynamic endDate, |
||||
dynamic startTime, |
||||
dynamic endTime, |
||||
String tenantCode, |
||||
String createTime, |
||||
num isDeleted, |
||||
num rechargeType, |
||||
String remark, |
||||
num sortValue, |
||||
dynamic useNum,}){ |
||||
_id = id; |
||||
_rechargeMoney = rechargeMoney; |
||||
_giftdMoney = giftdMoney; |
||||
_limitNum = limitNum; |
||||
_gitfdCouponId = gitfdCouponId; |
||||
_startDate = startDate; |
||||
_endDate = endDate; |
||||
_startTime = startTime; |
||||
_endTime = endTime; |
||||
_tenantCode = tenantCode; |
||||
_createTime = createTime; |
||||
_isDeleted = isDeleted; |
||||
_rechargeType = rechargeType; |
||||
_remark = remark; |
||||
_sortValue = sortValue; |
||||
_useNum = useNum; |
||||
} |
||||
|
||||
MemberRechargeList.fromJson(dynamic json) { |
||||
_id = json['id']; |
||||
_rechargeMoney = json['rechargeMoney']; |
||||
_giftdMoney = json['giftdMoney']; |
||||
_limitNum = json['limitNum']; |
||||
_gitfdCouponId = json['gitfdCouponId']; |
||||
_startDate = json['startDate']; |
||||
_endDate = json['endDate']; |
||||
_startTime = json['startTime']; |
||||
_endTime = json['endTime']; |
||||
_tenantCode = json['tenantCode']; |
||||
_createTime = json['createTime']; |
||||
_isDeleted = json['isDeleted']; |
||||
_rechargeType = json['rechargeType']; |
||||
_remark = json['remark']; |
||||
_sortValue = json['sortValue']; |
||||
_useNum = json['useNum']; |
||||
} |
||||
String _id; |
||||
String _rechargeMoney; |
||||
String _giftdMoney; |
||||
dynamic _limitNum; |
||||
dynamic _gitfdCouponId; |
||||
dynamic _startDate; |
||||
dynamic _endDate; |
||||
dynamic _startTime; |
||||
dynamic _endTime; |
||||
String _tenantCode; |
||||
String _createTime; |
||||
num _isDeleted; |
||||
num _rechargeType; |
||||
String _remark; |
||||
num _sortValue; |
||||
dynamic _useNum; |
||||
MemberRechargeList copyWith({ String id, |
||||
String rechargeMoney, |
||||
String giftdMoney, |
||||
dynamic limitNum, |
||||
dynamic gitfdCouponId, |
||||
dynamic startDate, |
||||
dynamic endDate, |
||||
dynamic startTime, |
||||
dynamic endTime, |
||||
String tenantCode, |
||||
String createTime, |
||||
num isDeleted, |
||||
num rechargeType, |
||||
String remark, |
||||
num sortValue, |
||||
dynamic useNum, |
||||
}) => MemberRechargeList( id: id ?? _id, |
||||
rechargeMoney: rechargeMoney ?? _rechargeMoney, |
||||
giftdMoney: giftdMoney ?? _giftdMoney, |
||||
limitNum: limitNum ?? _limitNum, |
||||
gitfdCouponId: gitfdCouponId ?? _gitfdCouponId, |
||||
startDate: startDate ?? _startDate, |
||||
endDate: endDate ?? _endDate, |
||||
startTime: startTime ?? _startTime, |
||||
endTime: endTime ?? _endTime, |
||||
tenantCode: tenantCode ?? _tenantCode, |
||||
createTime: createTime ?? _createTime, |
||||
isDeleted: isDeleted ?? _isDeleted, |
||||
rechargeType: rechargeType ?? _rechargeType, |
||||
remark: remark ?? _remark, |
||||
sortValue: sortValue ?? _sortValue, |
||||
useNum: useNum ?? _useNum, |
||||
); |
||||
String get id => _id; |
||||
String get rechargeMoney => _rechargeMoney; |
||||
String get giftdMoney => _giftdMoney; |
||||
dynamic get limitNum => _limitNum; |
||||
dynamic get gitfdCouponId => _gitfdCouponId; |
||||
dynamic get startDate => _startDate; |
||||
dynamic get endDate => _endDate; |
||||
dynamic get startTime => _startTime; |
||||
dynamic get endTime => _endTime; |
||||
String get tenantCode => _tenantCode; |
||||
String get createTime => _createTime; |
||||
num get isDeleted => _isDeleted; |
||||
num get rechargeType => _rechargeType; |
||||
String get remark => _remark; |
||||
num get sortValue => _sortValue; |
||||
dynamic get useNum => _useNum; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['id'] = _id; |
||||
map['rechargeMoney'] = _rechargeMoney; |
||||
map['giftdMoney'] = _giftdMoney; |
||||
map['limitNum'] = _limitNum; |
||||
map['gitfdCouponId'] = _gitfdCouponId; |
||||
map['startDate'] = _startDate; |
||||
map['endDate'] = _endDate; |
||||
map['startTime'] = _startTime; |
||||
map['endTime'] = _endTime; |
||||
map['tenantCode'] = _tenantCode; |
||||
map['createTime'] = _createTime; |
||||
map['isDeleted'] = _isDeleted; |
||||
map['rechargeType'] = _rechargeType; |
||||
map['remark'] = _remark; |
||||
map['sortValue'] = _sortValue; |
||||
map['useNum'] = _useNum; |
||||
return map; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,749 @@
|
||||
/// id : "1484156758195699712" |
||||
/// createTime : "2022-01-20 21:32:00" |
||||
/// createUser : "1364043181062094848" |
||||
/// updateTime : "2022-01-21 18:27:02" |
||||
/// updateUser : "1364043181062094848" |
||||
/// supplierName : "一心回乡生态农场" |
||||
/// storeId : "1460885296764682240" |
||||
/// categoryId : "1460889654206136320" |
||||
/// groupId : "1484146679266410496" |
||||
/// shortName : "【一心回乡】三益米 筋道绵润、鲜稻尝鲜;自留种老品种,非转基因种子" |
||||
/// productName : "三益米1kg" |
||||
/// sellDesc : "" |
||||
/// productCode : "PRO202201202132000000000000001" |
||||
/// weight : "0" |
||||
/// applyPrice : "39.00" |
||||
/// price : "24.00" |
||||
/// vipPrice : null |
||||
/// stock : -13 |
||||
/// sellCount : 19 |
||||
/// needLogistics : 1 |
||||
/// oversold : 1 |
||||
/// organic : 0 |
||||
/// status : 1 |
||||
/// posShow : true |
||||
/// subscribeParam : null |
||||
/// isRaise : false |
||||
/// productType : 0 |
||||
/// productNumber : 1 |
||||
/// setMeal : 1 |
||||
/// attrStyle : 0 |
||||
/// detail : "" |
||||
/// isDelete : 0 |
||||
/// printerFlag : "DEFAULT" |
||||
/// materials : null |
||||
/// materialId : null |
||||
/// details : "" |
||||
/// thumbnailImg : "" |
||||
/// info : "" |
||||
/// buyCount : 12 |
||||
/// sellCountLimit : 0 |
||||
/// stockRecoveryTime : null |
||||
/// isAddPurchase : null |
||||
/// limitNum : 0 |
||||
/// rankId : "0" |
||||
/// happyBean : 0 |
||||
/// imgs : ["https://pos.upload.lotus-wallet.com/1179/2022/01/243f54db-2dc8-4a9b-9ccc-09fc7a4e2a2e.jpg"] |
||||
/// productSkuList : [{"id":"1484156758229254144","createTime":"2022-01-20 21:32:00","createUser":"1364043181062094848","updateTime":"2022-01-20 21:32:00","updateUser":"1364043181062094848","storeId":"1460885296764682240","skuCode":"P202201202132002","skuNameStr":"","productId":"1484156758195699712","skuPrice":"24.00","applyPrice":"39.00","vipPrice":"24.00","packagingFee":"0.00","skuImg":null,"skuStock":-13,"autoRenewSkuStock":0,"deliveries":0,"ticketType":"","ticketWipedTimeTemplateId":null,"takeType":null,"ticketDays":"0","ticketExpireTime":"23:59:59","sort":50,"setMeal":"","productSetMeals":null,"weight":0.0,"volume":0.0,"isDelete":0,"material":null,"version":0,"skuTickets":null,"ticketStyle":""}] |
||||
|
||||
class ProductShow { |
||||
ProductShow({ |
||||
String id, |
||||
String createTime, |
||||
String createUser, |
||||
String updateTime, |
||||
String updateUser, |
||||
String supplierName, |
||||
String storeId, |
||||
String categoryId, |
||||
String groupId, |
||||
String shortName, |
||||
String productName, |
||||
String sellDesc, |
||||
String productCode, |
||||
String weight, |
||||
String applyPrice, |
||||
String price, |
||||
dynamic vipPrice, |
||||
num stock, |
||||
num sellCount, |
||||
num needLogistics, |
||||
num oversold, |
||||
num organic, |
||||
num status, |
||||
bool posShow, |
||||
dynamic subscribeParam, |
||||
bool isRaise, |
||||
num productType, |
||||
num productNumber, |
||||
num setMeal, |
||||
num attrStyle, |
||||
String detail, |
||||
num isDelete, |
||||
String printerFlag, |
||||
dynamic materials, |
||||
dynamic materialId, |
||||
String details, |
||||
String thumbnailImg, |
||||
String info, |
||||
num buyCount, |
||||
num sellCountLimit, |
||||
dynamic stockRecoveryTime, |
||||
dynamic isAddPurchase, |
||||
num limitNum, |
||||
String rankId, |
||||
num happyBean, |
||||
List<String> imgs, |
||||
List<ProductSkuList> productSkuList,}){ |
||||
_id = id; |
||||
_createTime = createTime; |
||||
_createUser = createUser; |
||||
_updateTime = updateTime; |
||||
_updateUser = updateUser; |
||||
_supplierName = supplierName; |
||||
_storeId = storeId; |
||||
_categoryId = categoryId; |
||||
_groupId = groupId; |
||||
_shortName = shortName; |
||||
_productName = productName; |
||||
_sellDesc = sellDesc; |
||||
_productCode = productCode; |
||||
_weight = weight; |
||||
_applyPrice = applyPrice; |
||||
_price = price; |
||||
_vipPrice = vipPrice; |
||||
_stock = stock; |
||||
_sellCount = sellCount; |
||||
_needLogistics = needLogistics; |
||||
_oversold = oversold; |
||||
_organic = organic; |
||||
_status = status; |
||||
_posShow = posShow; |
||||
_subscribeParam = subscribeParam; |
||||
_isRaise = isRaise; |
||||
_productType = productType; |
||||
_productNumber = productNumber; |
||||
_setMeal = setMeal; |
||||
_attrStyle = attrStyle; |
||||
_detail = detail; |
||||
_isDelete = isDelete; |
||||
_printerFlag = printerFlag; |
||||
_materials = materials; |
||||
_materialId = materialId; |
||||
_details = details; |
||||
_thumbnailImg = thumbnailImg; |
||||
_info = info; |
||||
_buyCount = buyCount; |
||||
_sellCountLimit = sellCountLimit; |
||||
_stockRecoveryTime = stockRecoveryTime; |
||||
_isAddPurchase = isAddPurchase; |
||||
_limitNum = limitNum; |
||||
_rankId = rankId; |
||||
_happyBean = happyBean; |
||||
_imgs = imgs; |
||||
_productSkuList = productSkuList; |
||||
} |
||||
|
||||
ProductShow.fromJson(dynamic json) { |
||||
_id = json['id']; |
||||
_createTime = json['createTime']; |
||||
_createUser = json['createUser']; |
||||
_updateTime = json['updateTime']; |
||||
_updateUser = json['updateUser']; |
||||
_supplierName = json['supplierName']; |
||||
_storeId = json['storeId']; |
||||
_categoryId = json['categoryId']; |
||||
_groupId = json['groupId']; |
||||
_shortName = json['shortName']; |
||||
_productName = json['productName']; |
||||
_sellDesc = json['sellDesc']; |
||||
_productCode = json['productCode']; |
||||
_weight = json['weight']; |
||||
_applyPrice = json['applyPrice']; |
||||
_price = json['price']; |
||||
_vipPrice = json['vipPrice']; |
||||
_stock = json['stock']; |
||||
_sellCount = json['sellCount']; |
||||
_needLogistics = json['needLogistics']; |
||||
_oversold = json['oversold']; |
||||
_organic = json['organic']; |
||||
_status = json['status']; |
||||
_posShow = json['posShow']; |
||||
_subscribeParam = json['subscribeParam']; |
||||
_isRaise = json['isRaise']; |
||||
_productType = json['productType']; |
||||
_productNumber = json['productNumber']; |
||||
_setMeal = json['setMeal']; |
||||
_attrStyle = json['attrStyle']; |
||||
_detail = json['detail']; |
||||
_isDelete = json['isDelete']; |
||||
_printerFlag = json['printerFlag']; |
||||
_materials = json['materials']; |
||||
_materialId = json['materialId']; |
||||
_details = json['details']; |
||||
_thumbnailImg = json['thumbnailImg']; |
||||
_info = json['info']; |
||||
_buyCount = json['buyCount']; |
||||
_sellCountLimit = json['sellCountLimit']; |
||||
_stockRecoveryTime = json['stockRecoveryTime']; |
||||
_isAddPurchase = json['isAddPurchase']; |
||||
_limitNum = json['limitNum']; |
||||
_rankId = json['rankId']; |
||||
_happyBean = json['happyBean']; |
||||
_imgs = json['imgs'] != null ? json['imgs'].cast<String>() : []; |
||||
if (json['productSkuList'] != null) { |
||||
_productSkuList = []; |
||||
json['productSkuList'].forEach((v) { |
||||
_productSkuList.add(ProductSkuList.fromJson(v)); |
||||
}); |
||||
} |
||||
} |
||||
String _id; |
||||
String _createTime; |
||||
String _createUser; |
||||
String _updateTime; |
||||
String _updateUser; |
||||
String _supplierName; |
||||
String _storeId; |
||||
String _categoryId; |
||||
String _groupId; |
||||
String _shortName; |
||||
String _productName; |
||||
String _sellDesc; |
||||
String _productCode; |
||||
String _weight; |
||||
String _applyPrice; |
||||
String _price; |
||||
dynamic _vipPrice; |
||||
num _stock; |
||||
num _sellCount; |
||||
num _needLogistics; |
||||
num _oversold; |
||||
num _organic; |
||||
num _status; |
||||
bool _posShow; |
||||
dynamic _subscribeParam; |
||||
bool _isRaise; |
||||
num _productType; |
||||
num _productNumber; |
||||
num _setMeal; |
||||
num _attrStyle; |
||||
String _detail; |
||||
num _isDelete; |
||||
String _printerFlag; |
||||
dynamic _materials; |
||||
dynamic _materialId; |
||||
String _details; |
||||
String _thumbnailImg; |
||||
String _info; |
||||
num _buyCount; |
||||
num _sellCountLimit; |
||||
dynamic _stockRecoveryTime; |
||||
dynamic _isAddPurchase; |
||||
num _limitNum; |
||||
String _rankId; |
||||
num _happyBean; |
||||
List<String> _imgs; |
||||
List<ProductSkuList> _productSkuList; |
||||
ProductShow copyWith({ String id, |
||||
String createTime, |
||||
String createUser, |
||||
String updateTime, |
||||
String updateUser, |
||||
String supplierName, |
||||
String storeId, |
||||
String categoryId, |
||||
String groupId, |
||||
String shortName, |
||||
String productName, |
||||
String sellDesc, |
||||
String productCode, |
||||
String weight, |
||||
String applyPrice, |
||||
String price, |
||||
dynamic vipPrice, |
||||
num stock, |
||||
num sellCount, |
||||
num needLogistics, |
||||
num oversold, |
||||
num organic, |
||||
num status, |
||||
bool posShow, |
||||
dynamic subscribeParam, |
||||
bool isRaise, |
||||
num productType, |
||||
num productNumber, |
||||
num setMeal, |
||||
num attrStyle, |
||||
String detail, |
||||
num isDelete, |
||||
String printerFlag, |
||||
dynamic materials, |
||||
dynamic materialId, |
||||
String details, |
||||
String thumbnailImg, |
||||
String info, |
||||
num buyCount, |
||||
num sellCountLimit, |
||||
dynamic stockRecoveryTime, |
||||
dynamic isAddPurchase, |
||||
num limitNum, |
||||
String rankId, |
||||
num happyBean, |
||||
List<String> imgs, |
||||
List<ProductSkuList> productSkuList, |
||||
}) => ProductShow( id: id ?? _id, |
||||
createTime: createTime ?? _createTime, |
||||
createUser: createUser ?? _createUser, |
||||
updateTime: updateTime ?? _updateTime, |
||||
updateUser: updateUser ?? _updateUser, |
||||
supplierName: supplierName ?? _supplierName, |
||||
storeId: storeId ?? _storeId, |
||||
categoryId: categoryId ?? _categoryId, |
||||
groupId: groupId ?? _groupId, |
||||
shortName: shortName ?? _shortName, |
||||
productName: productName ?? _productName, |
||||
sellDesc: sellDesc ?? _sellDesc, |
||||
productCode: productCode ?? _productCode, |
||||
weight: weight ?? _weight, |
||||
applyPrice: applyPrice ?? _applyPrice, |
||||
price: price ?? _price, |
||||
vipPrice: vipPrice ?? _vipPrice, |
||||
stock: stock ?? _stock, |
||||
sellCount: sellCount ?? _sellCount, |
||||
needLogistics: needLogistics ?? _needLogistics, |
||||
oversold: oversold ?? _oversold, |
||||
organic: organic ?? _organic, |
||||
status: status ?? _status, |
||||
posShow: posShow ?? _posShow, |
||||
subscribeParam: subscribeParam ?? _subscribeParam, |
||||
isRaise: isRaise ?? _isRaise, |
||||
productType: productType ?? _productType, |
||||
productNumber: productNumber ?? _productNumber, |
||||
setMeal: setMeal ?? _setMeal, |
||||
attrStyle: attrStyle ?? _attrStyle, |
||||
detail: detail ?? _detail, |
||||
isDelete: isDelete ?? _isDelete, |
||||
printerFlag: printerFlag ?? _printerFlag, |
||||
materials: materials ?? _materials, |
||||
materialId: materialId ?? _materialId, |
||||
details: details ?? _details, |
||||
thumbnailImg: thumbnailImg ?? _thumbnailImg, |
||||
info: info ?? _info, |
||||
buyCount: buyCount ?? _buyCount, |
||||
sellCountLimit: sellCountLimit ?? _sellCountLimit, |
||||
stockRecoveryTime: stockRecoveryTime ?? _stockRecoveryTime, |
||||
isAddPurchase: isAddPurchase ?? _isAddPurchase, |
||||
limitNum: limitNum ?? _limitNum, |
||||
rankId: rankId ?? _rankId, |
||||
happyBean: happyBean ?? _happyBean, |
||||
imgs: imgs ?? _imgs, |
||||
productSkuList: productSkuList ?? _productSkuList, |
||||
); |
||||
String get id => _id; |
||||
String get createTime => _createTime; |
||||
String get createUser => _createUser; |
||||
String get updateTime => _updateTime; |
||||
String get updateUser => _updateUser; |
||||
String get supplierName => _supplierName; |
||||
String get storeId => _storeId; |
||||
String get categoryId => _categoryId; |
||||
String get groupId => _groupId; |
||||
String get shortName => _shortName; |
||||
String get productName => _productName; |
||||
String get sellDesc => _sellDesc; |
||||
String get productCode => _productCode; |
||||
String get weight => _weight; |
||||
String get applyPrice => _applyPrice; |
||||
String get price => _price; |
||||
dynamic get vipPrice => _vipPrice; |
||||
num get stock => _stock; |
||||
num get sellCount => _sellCount; |
||||
num get needLogistics => _needLogistics; |
||||
num get oversold => _oversold; |
||||
num get organic => _organic; |
||||
num get status => _status; |
||||
bool get posShow => _posShow; |
||||
dynamic get subscribeParam => _subscribeParam; |
||||
bool get isRaise => _isRaise; |
||||
num get productType => _productType; |
||||
num get productNumber => _productNumber; |
||||
num get setMeal => _setMeal; |
||||
num get attrStyle => _attrStyle; |
||||
String get detail => _detail; |
||||
num get isDelete => _isDelete; |
||||
String get printerFlag => _printerFlag; |
||||
dynamic get materials => _materials; |
||||
dynamic get materialId => _materialId; |
||||
String get details => _details; |
||||
String get thumbnailImg => _thumbnailImg; |
||||
String get info => _info; |
||||
num get buyCount => _buyCount; |
||||
num get sellCountLimit => _sellCountLimit; |
||||
dynamic get stockRecoveryTime => _stockRecoveryTime; |
||||
dynamic get isAddPurchase => _isAddPurchase; |
||||
num get limitNum => _limitNum; |
||||
String get rankId => _rankId; |
||||
num get happyBean => _happyBean; |
||||
List<String> get imgs => _imgs; |
||||
List<ProductSkuList> get productSkuList => _productSkuList; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['id'] = _id; |
||||
map['createTime'] = _createTime; |
||||
map['createUser'] = _createUser; |
||||
map['updateTime'] = _updateTime; |
||||
map['updateUser'] = _updateUser; |
||||
map['supplierName'] = _supplierName; |
||||
map['storeId'] = _storeId; |
||||
map['categoryId'] = _categoryId; |
||||
map['groupId'] = _groupId; |
||||
map['shortName'] = _shortName; |
||||
map['productName'] = _productName; |
||||
map['sellDesc'] = _sellDesc; |
||||
map['productCode'] = _productCode; |
||||
map['weight'] = _weight; |
||||
map['applyPrice'] = _applyPrice; |
||||
map['price'] = _price; |
||||
map['vipPrice'] = _vipPrice; |
||||
map['stock'] = _stock; |
||||
map['sellCount'] = _sellCount; |
||||
map['needLogistics'] = _needLogistics; |
||||
map['oversold'] = _oversold; |
||||
map['organic'] = _organic; |
||||
map['status'] = _status; |
||||
map['posShow'] = _posShow; |
||||
map['subscribeParam'] = _subscribeParam; |
||||
map['isRaise'] = _isRaise; |
||||
map['productType'] = _productType; |
||||
map['productNumber'] = _productNumber; |
||||
map['setMeal'] = _setMeal; |
||||
map['attrStyle'] = _attrStyle; |
||||
map['detail'] = _detail; |
||||
map['isDelete'] = _isDelete; |
||||
map['printerFlag'] = _printerFlag; |
||||
map['materials'] = _materials; |
||||
map['materialId'] = _materialId; |
||||
map['details'] = _details; |
||||
map['thumbnailImg'] = _thumbnailImg; |
||||
map['info'] = _info; |
||||
map['buyCount'] = _buyCount; |
||||
map['sellCountLimit'] = _sellCountLimit; |
||||
map['stockRecoveryTime'] = _stockRecoveryTime; |
||||
map['isAddPurchase'] = _isAddPurchase; |
||||
map['limitNum'] = _limitNum; |
||||
map['rankId'] = _rankId; |
||||
map['happyBean'] = _happyBean; |
||||
map['imgs'] = _imgs; |
||||
if (_productSkuList != null) { |
||||
map['productSkuList'] = _productSkuList.map((v) => v.toJson()).toList(); |
||||
} |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// id : "1484156758229254144" |
||||
/// createTime : "2022-01-20 21:32:00" |
||||
/// createUser : "1364043181062094848" |
||||
/// updateTime : "2022-01-20 21:32:00" |
||||
/// updateUser : "1364043181062094848" |
||||
/// storeId : "1460885296764682240" |
||||
/// skuCode : "P202201202132002" |
||||
/// skuNameStr : "" |
||||
/// productId : "1484156758195699712" |
||||
/// skuPrice : "24.00" |
||||
/// applyPrice : "39.00" |
||||
/// vipPrice : "24.00" |
||||
/// packagingFee : "0.00" |
||||
/// skuImg : null |
||||
/// skuStock : -13 |
||||
/// autoRenewSkuStock : 0 |
||||
/// deliveries : 0 |
||||
/// ticketType : "" |
||||
/// ticketWipedTimeTemplateId : null |
||||
/// takeType : null |
||||
/// ticketDays : "0" |
||||
/// ticketExpireTime : "23:59:59" |
||||
/// sort : 50 |
||||
/// setMeal : "" |
||||
/// productSetMeals : null |
||||
/// weight : 0.0 |
||||
/// volume : 0.0 |
||||
/// isDelete : 0 |
||||
/// material : null |
||||
/// version : 0 |
||||
/// skuTickets : null |
||||
/// ticketStyle : "" |
||||
|
||||
class ProductSkuList { |
||||
ProductSkuList({ |
||||
String id, |
||||
String createTime, |
||||
String createUser, |
||||
String updateTime, |
||||
String updateUser, |
||||
String storeId, |
||||
String skuCode, |
||||
String skuNameStr, |
||||
String productId, |
||||
String skuPrice, |
||||
String applyPrice, |
||||
String vipPrice, |
||||
String packagingFee, |
||||
dynamic skuImg, |
||||
num skuStock, |
||||
num autoRenewSkuStock, |
||||
num deliveries, |
||||
String ticketType, |
||||
dynamic ticketWipedTimeTemplateId, |
||||
dynamic takeType, |
||||
String ticketDays, |
||||
String ticketExpireTime, |
||||
num sort, |
||||
String setMeal, |
||||
dynamic productSetMeals, |
||||
num weight, |
||||
num volume, |
||||
num isDelete, |
||||
dynamic material, |
||||
num version, |
||||
dynamic skuTickets, |
||||
String ticketStyle,}){ |
||||
_id = id; |
||||
_createTime = createTime; |
||||
_createUser = createUser; |
||||
_updateTime = updateTime; |
||||
_updateUser = updateUser; |
||||
_storeId = storeId; |
||||
_skuCode = skuCode; |
||||
_skuNameStr = skuNameStr; |
||||
_productId = productId; |
||||
_skuPrice = skuPrice; |
||||
_applyPrice = applyPrice; |
||||
_vipPrice = vipPrice; |
||||
_packagingFee = packagingFee; |
||||
_skuImg = skuImg; |
||||
_skuStock = skuStock; |
||||
_autoRenewSkuStock = autoRenewSkuStock; |
||||
_deliveries = deliveries; |
||||
_ticketType = ticketType; |
||||
_ticketWipedTimeTemplateId = ticketWipedTimeTemplateId; |
||||
_takeType = takeType; |
||||
_ticketDays = ticketDays; |
||||
_ticketExpireTime = ticketExpireTime; |
||||
_sort = sort; |
||||
_setMeal = setMeal; |
||||
_productSetMeals = productSetMeals; |
||||
_weight = weight; |
||||
_volume = volume; |
||||
_isDelete = isDelete; |
||||
_material = material; |
||||
_version = version; |
||||
_skuTickets = skuTickets; |
||||
_ticketStyle = ticketStyle; |
||||
} |
||||
|
||||
ProductSkuList.fromJson(dynamic json) { |
||||
_id = json['id']; |
||||
_createTime = json['createTime']; |
||||
_createUser = json['createUser']; |
||||
_updateTime = json['updateTime']; |
||||
_updateUser = json['updateUser']; |
||||
_storeId = json['storeId']; |
||||
_skuCode = json['skuCode']; |
||||
_skuNameStr = json['skuNameStr']; |
||||
_productId = json['productId']; |
||||
_skuPrice = json['skuPrice']; |
||||
_applyPrice = json['applyPrice']; |
||||
_vipPrice = json['vipPrice']; |
||||
_packagingFee = json['packagingFee']; |
||||
_skuImg = json['skuImg']; |
||||
_skuStock = json['skuStock']; |
||||
_autoRenewSkuStock = json['autoRenewSkuStock']; |
||||
_deliveries = json['deliveries']; |
||||
_ticketType = json['ticketType']; |
||||
_ticketWipedTimeTemplateId = json['ticketWipedTimeTemplateId']; |
||||
_takeType = json['takeType']; |
||||
_ticketDays = json['ticketDays']; |
||||
_ticketExpireTime = json['ticketExpireTime']; |
||||
_sort = json['sort']; |
||||
_setMeal = json['setMeal']; |
||||
_productSetMeals = json['productSetMeals']; |
||||
_weight = json['weight']; |
||||
_volume = json['volume']; |
||||
_isDelete = json['isDelete']; |
||||
_material = json['material']; |
||||
_version = json['version']; |
||||
_skuTickets = json['skuTickets']; |
||||
_ticketStyle = json['ticketStyle']; |
||||
} |
||||
String _id; |
||||
String _createTime; |
||||
String _createUser; |
||||
String _updateTime; |
||||
String _updateUser; |
||||
String _storeId; |
||||
String _skuCode; |
||||
String _skuNameStr; |
||||
String _productId; |
||||
String _skuPrice; |
||||
String _applyPrice; |
||||
String _vipPrice; |
||||
String _packagingFee; |
||||
dynamic _skuImg; |
||||
num _skuStock; |
||||
num _autoRenewSkuStock; |
||||
num _deliveries; |
||||
String _ticketType; |
||||
dynamic _ticketWipedTimeTemplateId; |
||||
dynamic _takeType; |
||||
String _ticketDays; |
||||
String _ticketExpireTime; |
||||
num _sort; |
||||
String _setMeal; |
||||
dynamic _productSetMeals; |
||||
num _weight; |
||||
num _volume; |
||||
num _isDelete; |
||||
dynamic _material; |
||||
num _version; |
||||
dynamic _skuTickets; |
||||
String _ticketStyle; |
||||
ProductSkuList copyWith({ String id, |
||||
String createTime, |
||||
String createUser, |
||||
String updateTime, |
||||
String updateUser, |
||||
String storeId, |
||||
String skuCode, |
||||
String skuNameStr, |
||||
String productId, |
||||
String skuPrice, |
||||
String applyPrice, |
||||
String vipPrice, |
||||
String packagingFee, |
||||
dynamic skuImg, |
||||
num skuStock, |
||||
num autoRenewSkuStock, |
||||
num deliveries, |
||||
String ticketType, |
||||
dynamic ticketWipedTimeTemplateId, |
||||
dynamic takeType, |
||||
String ticketDays, |
||||
String ticketExpireTime, |
||||
num sort, |
||||
String setMeal, |
||||
dynamic productSetMeals, |
||||
num weight, |
||||
num volume, |
||||
num isDelete, |
||||
dynamic material, |
||||
num version, |
||||
dynamic skuTickets, |
||||
String ticketStyle, |
||||
}) => ProductSkuList( id: id ?? _id, |
||||
createTime: createTime ?? _createTime, |
||||
createUser: createUser ?? _createUser, |
||||
updateTime: updateTime ?? _updateTime, |
||||
updateUser: updateUser ?? _updateUser, |
||||
storeId: storeId ?? _storeId, |
||||
skuCode: skuCode ?? _skuCode, |
||||
skuNameStr: skuNameStr ?? _skuNameStr, |
||||
productId: productId ?? _productId, |
||||
skuPrice: skuPrice ?? _skuPrice, |
||||
applyPrice: applyPrice ?? _applyPrice, |
||||
vipPrice: vipPrice ?? _vipPrice, |
||||
packagingFee: packagingFee ?? _packagingFee, |
||||
skuImg: skuImg ?? _skuImg, |
||||
skuStock: skuStock ?? _skuStock, |
||||
autoRenewSkuStock: autoRenewSkuStock ?? _autoRenewSkuStock, |
||||
deliveries: deliveries ?? _deliveries, |
||||
ticketType: ticketType ?? _ticketType, |
||||
ticketWipedTimeTemplateId: ticketWipedTimeTemplateId ?? _ticketWipedTimeTemplateId, |
||||
takeType: takeType ?? _takeType, |
||||
ticketDays: ticketDays ?? _ticketDays, |
||||
ticketExpireTime: ticketExpireTime ?? _ticketExpireTime, |
||||
sort: sort ?? _sort, |
||||
setMeal: setMeal ?? _setMeal, |
||||
productSetMeals: productSetMeals ?? _productSetMeals, |
||||
weight: weight ?? _weight, |
||||
volume: volume ?? _volume, |
||||
isDelete: isDelete ?? _isDelete, |
||||
material: material ?? _material, |
||||
version: version ?? _version, |
||||
skuTickets: skuTickets ?? _skuTickets, |
||||
ticketStyle: ticketStyle ?? _ticketStyle, |
||||
); |
||||
String get id => _id; |
||||
String get createTime => _createTime; |
||||
String get createUser => _createUser; |
||||
String get updateTime => _updateTime; |
||||
String get updateUser => _updateUser; |
||||
String get storeId => _storeId; |
||||
String get skuCode => _skuCode; |
||||
String get skuNameStr => _skuNameStr; |
||||
String get productId => _productId; |
||||
String get skuPrice => _skuPrice; |
||||
String get applyPrice => _applyPrice; |
||||
String get vipPrice => _vipPrice; |
||||
String get packagingFee => _packagingFee; |
||||
dynamic get skuImg => _skuImg; |
||||
num get skuStock => _skuStock; |
||||
num get autoRenewSkuStock => _autoRenewSkuStock; |
||||
num get deliveries => _deliveries; |
||||
String get ticketType => _ticketType; |
||||
dynamic get ticketWipedTimeTemplateId => _ticketWipedTimeTemplateId; |
||||
dynamic get takeType => _takeType; |
||||
String get ticketDays => _ticketDays; |
||||
String get ticketExpireTime => _ticketExpireTime; |
||||
num get sort => _sort; |
||||
String get setMeal => _setMeal; |
||||
dynamic get productSetMeals => _productSetMeals; |
||||
num get weight => _weight; |
||||
num get volume => _volume; |
||||
num get isDelete => _isDelete; |
||||
dynamic get material => _material; |
||||
num get version => _version; |
||||
dynamic get skuTickets => _skuTickets; |
||||
String get ticketStyle => _ticketStyle; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['id'] = _id; |
||||
map['createTime'] = _createTime; |
||||
map['createUser'] = _createUser; |
||||
map['updateTime'] = _updateTime; |
||||
map['updateUser'] = _updateUser; |
||||
map['storeId'] = _storeId; |
||||
map['skuCode'] = _skuCode; |
||||
map['skuNameStr'] = _skuNameStr; |
||||
map['productId'] = _productId; |
||||
map['skuPrice'] = _skuPrice; |
||||
map['applyPrice'] = _applyPrice; |
||||
map['vipPrice'] = _vipPrice; |
||||
map['packagingFee'] = _packagingFee; |
||||
map['skuImg'] = _skuImg; |
||||
map['skuStock'] = _skuStock; |
||||
map['autoRenewSkuStock'] = _autoRenewSkuStock; |
||||
map['deliveries'] = _deliveries; |
||||
map['ticketType'] = _ticketType; |
||||
map['ticketWipedTimeTemplateId'] = _ticketWipedTimeTemplateId; |
||||
map['takeType'] = _takeType; |
||||
map['ticketDays'] = _ticketDays; |
||||
map['ticketExpireTime'] = _ticketExpireTime; |
||||
map['sort'] = _sort; |
||||
map['setMeal'] = _setMeal; |
||||
map['productSetMeals'] = _productSetMeals; |
||||
map['weight'] = _weight; |
||||
map['volume'] = _volume; |
||||
map['isDelete'] = _isDelete; |
||||
map['material'] = _material; |
||||
map['version'] = _version; |
||||
map['skuTickets'] = _skuTickets; |
||||
map['ticketStyle'] = _ticketStyle; |
||||
return map; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,372 @@
|
||||
import 'dart:convert'; |
||||
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:huixiang/utils/font_weight.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
|
||||
import '../retrofit/data/ip_data.dart'; |
||||
import '../retrofit/retrofit_api.dart'; |
||||
|
||||
class UnionSelectCity extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
UnionSelectCity({this.arguments}); |
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _UnionSelectCity(); |
||||
} |
||||
} |
||||
|
||||
class _UnionSelectCity extends State<UnionSelectCity> { |
||||
RefreshController refreshController = RefreshController(); |
||||
Map<String, dynamic> areaMap; |
||||
ApiService apiIpService; |
||||
String ipName; |
||||
int ipState = 0; |
||||
List<String> hotCity = []; |
||||
List<String> areaList = []; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
areaCode(); |
||||
queryIpInfo(); |
||||
} |
||||
|
||||
void areaCode({String searchTxt}) async { |
||||
var value = |
||||
await rootBundle.loadString('assets/map_style/chinese_cities.json'); |
||||
areaList.clear(); |
||||
areaMap = jsonDecode(value); |
||||
hotCity = (areaMap["热门城市"] as List).map((e) { |
||||
return e["area"].toString(); |
||||
}).toList(); |
||||
areaMap.remove("热门城市"); |
||||
Map<String, dynamic> tempAreaMap = jsonDecode(value); |
||||
areaMap.forEach((key, value) { |
||||
if (searchTxt != null && searchTxt.trim() != "") |
||||
value.forEach((element) { |
||||
if (!element["area"].contains(searchTxt)) |
||||
(tempAreaMap[key] as List) |
||||
.removeWhere((el) => el["area"] == element["area"]); |
||||
}); |
||||
if (tempAreaMap[key].isNotEmpty) areaList.add(key); |
||||
}); |
||||
areaMap = tempAreaMap; |
||||
setState(() {}); |
||||
} |
||||
|
||||
queryIpInfo() async { |
||||
apiIpService = ApiService( |
||||
Dio(), |
||||
context: context, |
||||
isIp: true |
||||
); |
||||
IpData baseData = await apiIpService.getIpInfo().catchError((onError) {}); |
||||
if (baseData?.city != null) { |
||||
ipName = baseData.city.replaceAll("市", ""); |
||||
if(ipName != widget.arguments["cityName"] ){ |
||||
ipState=2; |
||||
setState((){}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
backgroundColor: Color(0xFFF0F0F0), |
||||
body: Container( |
||||
color: Color(0xFFF0F0F0), |
||||
child: Column( |
||||
children: [ |
||||
Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.only(left: 14.w, top: 44.h, bottom: 24.h), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
children: [ |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(right: 21.w), |
||||
child: Icon( |
||||
Icons.arrow_back_ios, |
||||
color: Colors.black, |
||||
), |
||||
)), |
||||
Expanded(child: searchCityItem()) |
||||
], |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 16.h, bottom: 24.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 10.w), |
||||
child: Text( |
||||
(ipState == 0||ipState == 1) ? "当前位置" : "已选:", |
||||
style: TextStyle( |
||||
color: Color(0xFFA29E9E), |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 16.sp, |
||||
), |
||||
), |
||||
), |
||||
Image.asset( |
||||
"assets/image/icon_union_location.webp", |
||||
width: 20, |
||||
height: 20, |
||||
), |
||||
Expanded( |
||||
// padding: EdgeInsets.only( |
||||
// left: 8.w, |
||||
// ), |
||||
child: Text( |
||||
(ipState== 1) ? (ipName??""):widget.arguments["cityName"] ?? "", |
||||
style: TextStyle( |
||||
color: Color(0xFF4D4D4D), |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 16.sp, |
||||
), |
||||
), |
||||
), |
||||
if(ipState == 2) |
||||
Icon( |
||||
Icons.gps_fixed, |
||||
color: Colors.grey, |
||||
size: 18, |
||||
), |
||||
if(ipState == 2) |
||||
Padding(padding:EdgeInsets.only(left:5.w,right: 12.w), |
||||
child:GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: (){ |
||||
setState((){ |
||||
ipState = 1; |
||||
Navigator.of(context).pop(ipName); |
||||
}); |
||||
}, |
||||
child: Text( |
||||
"重新定位", |
||||
style: TextStyle( |
||||
color: Color(0xFF4D4D4D), |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 16.sp, |
||||
), |
||||
), |
||||
),) |
||||
], |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 16.h), |
||||
child: Text( |
||||
"热门城市", |
||||
style: TextStyle( |
||||
color: Color(0xFFA29E9E), |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 16.sp, |
||||
), |
||||
), |
||||
), |
||||
GridView.builder( |
||||
itemCount: hotCity.length, |
||||
padding: EdgeInsets.only(right: 14.h, bottom: 14.h), |
||||
shrinkWrap: true, |
||||
physics: NeverScrollableScrollPhysics(), |
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |
||||
crossAxisCount: 4, |
||||
crossAxisSpacing: 12.w, |
||||
mainAxisSpacing: 12.w, |
||||
childAspectRatio: 2.5, |
||||
), |
||||
itemBuilder: (context, index) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pop(hotCity[index]); |
||||
setState((){}); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFFF7F7F7), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
alignment: Alignment.center, |
||||
child: Text( |
||||
hotCity[index], |
||||
style: TextStyle( |
||||
color: Color(0xFF4D4D4D), |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 16.sp, |
||||
), |
||||
))); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Expanded(child: sortList()) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget searchCityItem() { |
||||
return Container( |
||||
margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0), |
||||
padding: EdgeInsets.symmetric(vertical: 6.h), |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFFF1F1F1), |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Colors.black.withAlpha(12), |
||||
offset: Offset(0, 3), |
||||
blurRadius: 14, |
||||
spreadRadius: 0, |
||||
), |
||||
], |
||||
), |
||||
child: TextField( |
||||
textInputAction: TextInputAction.search, |
||||
onEditingComplete: () { |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
}, |
||||
onChanged: (txt) { |
||||
areaCode(searchTxt: txt); |
||||
}, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
), |
||||
decoration: InputDecoration( |
||||
hintText: "搜索联盟会员店", |
||||
hintStyle: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFFB3B3B3), |
||||
), |
||||
isCollapsed: true, |
||||
prefixIcon:Padding(padding: EdgeInsets.only(left: 5.w,right: 5.w),child: Image.asset( |
||||
"assets/image/icon_search.webp", |
||||
width: 16.h, |
||||
height: 16.h, |
||||
),), |
||||
prefixIconConstraints: BoxConstraints(), |
||||
border: InputBorder.none, |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget sortList() { |
||||
return areaList.length != 0 ?ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: areaList.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
onTap: () {}, |
||||
child: sortItem(position), |
||||
); |
||||
}, |
||||
):Padding(padding:EdgeInsets.only(top:12.h), |
||||
child: Text( |
||||
"抱歉,未找到相关位置,可尝试修改后重试", |
||||
style: TextStyle( |
||||
color: Color(0xFF4D4D4D), |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 14.sp, |
||||
), |
||||
)); |
||||
} |
||||
|
||||
Widget sortItem(int position) { |
||||
return Column( |
||||
children: [ |
||||
Container( |
||||
width: double.infinity, |
||||
// color: Colors.white, |
||||
padding: EdgeInsets.only(top: 14.h, bottom: 4.h, left: 16.w), |
||||
margin: EdgeInsets.only(bottom: 12.h), |
||||
child: Text( |
||||
areaList[position], |
||||
style: TextStyle( |
||||
color: Color(0xFF4D4D4D), |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 16.sp, |
||||
), |
||||
), |
||||
), |
||||
Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.circular(6.w), |
||||
color: Colors.white, |
||||
), |
||||
margin: EdgeInsets.symmetric(horizontal: 14.w), |
||||
padding: EdgeInsets.only( |
||||
top: 8.h, |
||||
), |
||||
child: mapWidget(position), |
||||
) |
||||
], |
||||
); |
||||
} |
||||
|
||||
Widget mapWidget(position) { |
||||
int mapIndex = 0; |
||||
return Column( |
||||
children: (areaMap[areaList[position]] as List).map((e) { |
||||
mapIndex += 1; |
||||
return globalRoamingItem( |
||||
e, mapIndex == areaMap[areaList[position]].length); |
||||
}).toList(), |
||||
); |
||||
} |
||||
|
||||
Widget globalRoamingItem(data, isLast) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pop(data["area"]); |
||||
}, |
||||
child: Container( |
||||
width: double.infinity, |
||||
child: Text( |
||||
data["area"], |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontWeight: MyFontWeight.regular, |
||||
fontSize: 14.sp, |
||||
), |
||||
), |
||||
decoration: BoxDecoration( |
||||
border: isLast |
||||
? null |
||||
: Border( |
||||
bottom: BorderSide( |
||||
width: 1.w, |
||||
color: Color(0xFFDCDCDC), |
||||
style: BorderStyle.solid, |
||||
), |
||||
), |
||||
), |
||||
padding: EdgeInsets.only(top: 16.h, bottom: 16.h, left: 16.w), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,86 @@
|
||||
import 'dart:convert'; |
||||
import 'package:steel_crypt/steel_crypt.dart'; |
||||
import 'package:convert/convert.dart'; |
||||
import 'package:crypto/crypto.dart'; |
||||
|
||||
class CaptchaUtil{ |
||||
///aes加密 |
||||
/// [key]AesCrypt加密key |
||||
/// [content] 需要加密的内容字符串 |
||||
static String aesEncode({String key, String content}) { |
||||
var aesCrypt = AesCrypt( |
||||
key: base64UrlEncode(key.codeUnits), padding: PaddingAES.pkcs7); |
||||
return aesCrypt.ecb.encrypt(inp: content); |
||||
} |
||||
|
||||
///aes解密 |
||||
/// [key]aes解密key |
||||
/// [content] 需要加密的内容字符串 |
||||
static String aesDecode({String key, String content}) { |
||||
var aesCrypt = AesCrypt( |
||||
key: base64UrlEncode(key.codeUnits), padding: PaddingAES.pkcs7); |
||||
return aesCrypt.ecb.decrypt(enc: content); |
||||
} |
||||
/// isEmpty. |
||||
static bool isEmpty(Object value) { |
||||
if (value == null) return true; |
||||
if (value is String && value.isEmpty) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
//list length == 0 || list == null |
||||
static bool isListEmpty(Object value) { |
||||
if (value == null) return true; |
||||
if (value is List && value.length == 0) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
static String jsonFormat(Map<dynamic, dynamic> map) { |
||||
Map _map = Map<String, Object>.from(map); |
||||
JsonEncoder encoder = JsonEncoder.withIndent(' '); |
||||
return encoder.convert(_map); |
||||
} |
||||
|
||||
|
||||
static String generateMd5(String data){ |
||||
var content = new Utf8Encoder().convert(data); |
||||
var digest = md5.convert(content); |
||||
return hex.encode(digest.bytes); |
||||
} |
||||
|
||||
static signData(Object params, tokenStr) async { |
||||
var time = new DateTime.now().millisecondsSinceEpoch; |
||||
String token = tokenStr; |
||||
Map<String, dynamic> reqData = new Map(); |
||||
Map<String, dynamic> paramsObj = new Map(); |
||||
paramsObj = params as Map<String, dynamic>; |
||||
var arr = []; |
||||
//将字典转成数组 |
||||
paramsObj?.forEach((key, value) => arr.add(key)); |
||||
//进行签名校验 |
||||
Map cr = new Map(); |
||||
cr['token'] = token; |
||||
cr['time'] = time.toString(); |
||||
cr['reqData'] = json.encode(paramsObj); |
||||
var array = []; |
||||
cr.forEach((key, value) => array.add(key)); |
||||
array.sort(); |
||||
var str = ''; |
||||
for (var i = 0; i < array.length; i++) { |
||||
var key = array[i]; |
||||
var value = cr[key]; |
||||
str += key + value; |
||||
} |
||||
|
||||
reqData["time"] = time; |
||||
reqData["token"] = token; |
||||
reqData['reqData'] = params; |
||||
reqData['sign'] = generateMd5(str); |
||||
|
||||
return reqData; |
||||
} |
||||
} |
@ -0,0 +1,133 @@
|
||||
import 'dart:async'; |
||||
|
||||
import 'package:flutter/widgets.dart'; |
||||
|
||||
import 'captcha_util.dart'; |
||||
/** |
||||
* @Author: thl |
||||
* @GitHub: https://github.com/Sky24n |
||||
* @Email: 863764940@qq.com |
||||
* @Email: sky24no@gmail.com |
||||
* @Description: Widget Util. |
||||
* @Date: 2018/9/10 |
||||
*/ |
||||
|
||||
/// Widget Util. |
||||
class WidgetUtil { |
||||
bool _hasMeasured = false; |
||||
double _width; |
||||
double _height; |
||||
|
||||
/// Widget rendering listener. |
||||
/// Widget渲染监听. |
||||
/// context: Widget context. |
||||
/// isOnce: true,Continuous monitoring false,Listen only once. |
||||
/// onCallBack: Widget Rect CallBack. |
||||
void asyncPrepare( |
||||
BuildContext context, bool isOnce, ValueChanged<Rect> onCallBack) { |
||||
if (_hasMeasured) return; |
||||
WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { |
||||
RenderObject box = context.findRenderObject(); |
||||
if (box != null) { |
||||
if (isOnce) _hasMeasured = true; |
||||
double width = box.semanticBounds.width; |
||||
double height = box.semanticBounds.height; |
||||
if (_width != width || _height != height) { |
||||
_width = width; |
||||
_height = height; |
||||
if (onCallBack != null) onCallBack(box.semanticBounds); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/// Widget渲染监听. |
||||
void asyncPrepares(bool isOnce, ValueChanged<Rect> onCallBack) { |
||||
if (_hasMeasured) return; |
||||
WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { |
||||
if (isOnce) _hasMeasured = true; |
||||
if (onCallBack != null) onCallBack(null); |
||||
}); |
||||
} |
||||
|
||||
///get Widget Bounds (width, height, left, top, right, bottom and so on).Widgets must be rendered completely. |
||||
///获取widget Rect |
||||
static Rect getWidgetBounds(BuildContext context) { |
||||
RenderObject box = context.findRenderObject(); |
||||
return (box != null) ? box.semanticBounds : Rect.zero; |
||||
} |
||||
|
||||
///Get the coordinates of the widget on the screen.Widgets must be rendered completely. |
||||
///获取widget在屏幕上的坐标,widget必须渲染完成 |
||||
static Offset getWidgetLocalToGlobal(BuildContext context) { |
||||
RenderBox box = context.findRenderObject() as RenderBox; |
||||
return box == null ? Offset.zero : box.localToGlobal(Offset.zero); |
||||
} |
||||
|
||||
/// get image width height,load error return Rect.zero.(unit px) |
||||
/// 获取图片宽高,加载错误情况返回 Rect.zero.(单位 px) |
||||
/// image |
||||
/// url network |
||||
/// local url , package |
||||
static Future<Rect> getImageWH( |
||||
{Image image, String url, String localUrl, String package}) { |
||||
if (CaptchaUtil.isEmpty(image) && |
||||
CaptchaUtil.isEmpty(url) && |
||||
CaptchaUtil.isEmpty(localUrl)) { |
||||
return Future.value(Rect.zero); |
||||
} |
||||
Completer<Rect> completer = Completer<Rect>(); |
||||
Image img = image ?? ((url != null && url.isNotEmpty) |
||||
? Image.network(url) |
||||
: Image.asset(localUrl, package: package)); |
||||
img.image |
||||
.resolve(const ImageConfiguration()) |
||||
.addListener(ImageStreamListener( |
||||
(ImageInfo info, bool _) { |
||||
completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(), |
||||
info.image.height.toDouble())); |
||||
}, |
||||
onError: (Object exception, StackTrace stackTrace) { |
||||
completer.completeError(exception, stackTrace); |
||||
}, |
||||
)); |
||||
return completer.future; |
||||
} |
||||
|
||||
/// get image width height, load error throw exception.(unit px) |
||||
/// 获取图片宽高,加载错误会抛出异常.(单位 px) |
||||
/// image |
||||
/// url network |
||||
/// local url (full path/全路径,example:"assets/images/ali_connors.png",""assets/images/3.0x/ali_connors.png"" ); |
||||
/// package |
||||
static Future<Rect> getImageWHE( |
||||
{Image image, |
||||
String url, |
||||
String localUrl, |
||||
String package}) { |
||||
if (CaptchaUtil.isEmpty(image) && |
||||
CaptchaUtil.isEmpty(url) && |
||||
CaptchaUtil.isEmpty(localUrl)) { |
||||
return Future.error("image is null."); |
||||
} |
||||
Completer<Rect> completer = Completer<Rect>(); |
||||
Image img = image != null |
||||
? image |
||||
: ((url != null && url.isNotEmpty) |
||||
? Image.network(url) |
||||
: Image.asset(localUrl, package: package)); |
||||
img.image |
||||
.resolve(const ImageConfiguration()) |
||||
.addListener(ImageStreamListener( |
||||
(ImageInfo info, bool _) { |
||||
completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(), |
||||
info.image.height.toDouble())); |
||||
}, |
||||
onError: (Object exception, StackTrace stackTrace) { |
||||
completer.completeError(exception, stackTrace); |
||||
}, |
||||
)); |
||||
|
||||
return completer.future; |
||||
} |
||||
} |