Browse Source
新增商家端滑动图片验证文件; 新增编辑规格明细页面,且数据交互已完成; 新增编辑规格明细实体类; 新增服务套餐功能本介绍;(ui设计为仅显示一张图片,接口未新增该字段;待开发,接入数据字段即可;) 新增服务套餐购买记录实体类; 新增服务套餐购买记录页面;(该页面已完成初步ui设计,接口数据已对接,服务内容暂未定义,暂时隐藏) 新增设置商品规格页面;(已完成数据的交互流程) 新增设置商品规格值页面;已完成数据的交互流程) 新增设置套餐选择页面;(已完成新增商品跳转,选择商品数据显示的交互流程) 新增设置规格列表实体类; 新增设置规格套餐列表实体类; 新增设置规格值列表实体类;wr_2023_new_business
wurong
1 year ago
22 changed files with 5439 additions and 0 deletions
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 968 B |
After Width: | Height: | Size: 888 B |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,440 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/edit_specs_detail_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
class EditSpecsDetail extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
EditSpecsDetail({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _EditSpecsDetail(); |
||||
} |
||||
} |
||||
|
||||
class _EditSpecsDetail extends State<EditSpecsDetail> { |
||||
List<EditSpecsDetailList> editSpecsDetailList = []; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
List<String> skus = widget?.arguments["skus"] ?? []; |
||||
List<Map<String, String>> specsDetails = |
||||
widget.arguments["specsDetails"] ?? []; |
||||
skus.forEach((element) { |
||||
var edit = EditSpecsDetailList(element); |
||||
for(var e1 in specsDetails){ |
||||
if(e1["skuName"] == element){ |
||||
edit.goodPriceController.text = e1["goodPrice"]; |
||||
edit.originalPriceController.text = e1["originalPrice"]; |
||||
edit.packagingFeeController.text = e1["packagingFee"]; |
||||
edit.specsWeightController.text = e1["specsWeight"]; |
||||
edit.skuStockController.text = e1["skuStock"]; |
||||
break; |
||||
} |
||||
} |
||||
editSpecsDetailList.add(edit); |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "编辑规格明细", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
Container( |
||||
margin: EdgeInsets.only(bottom: 120.h), |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: editSpecsDetailList.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
FocusScope.of(context).unfocus(); |
||||
}); |
||||
}, |
||||
child: editSpecsItem(position)); |
||||
}, |
||||
), |
||||
), |
||||
|
||||
///确认 |
||||
Align( |
||||
alignment: Alignment.bottomCenter, |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
bool flag = false; |
||||
String editType = ""; |
||||
List<Map<String, String>> specsDetail = []; |
||||
editSpecsDetailList.forEach((element) { |
||||
if (element.goodPriceController.text.trim() == "") { |
||||
flag = true; |
||||
editType = "请输入商品售价"; |
||||
return; |
||||
} else if (element.originalPriceController.text.trim() == |
||||
"") { |
||||
flag = true; |
||||
editType = "请输入商品原价"; |
||||
return; |
||||
} |
||||
specsDetail.add({ |
||||
"skuName": element.specsDetailName, |
||||
"goodPrice": element.goodPriceController.text, |
||||
"originalPrice": element.originalPriceController.text, |
||||
"packagingFee": element.packagingFeeController.text, |
||||
"specsWeight": element.specsWeightController.text, |
||||
"skuStock": element.skuStockController.text |
||||
}); |
||||
}); |
||||
if (flag) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: editType, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
Navigator.of(context).pop(specsDetail); |
||||
} |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, left: 16.w, right: 16.w, bottom: 34.h), |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
height: 54.h, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(27), |
||||
), |
||||
child: Text( |
||||
S.of(context).baocun, |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///编辑规格list |
||||
Widget editSpecsItem(index) { |
||||
return Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
editSpecsDetailList[index].specsDetailName ?? "", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
margin: EdgeInsets.only(top: 20.h), |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "*", |
||||
style: TextStyle( |
||||
color: Color(0xFFE02020), |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "商品售价", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].goodPriceController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品售卖价格", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: "*", |
||||
style: TextStyle( |
||||
color: Color(0xFFE02020), |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "商品原价", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: |
||||
editSpecsDetailList[index].originalPriceController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品划线价格", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"商品打包费", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].packagingFeeController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品打包费", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"商品重量", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].specsWeightController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品重量(单位kg)", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"商品库存", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editSpecsDetailList[index].skuStockController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商品库存", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,444 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/edit_specs_detail_list.dart'; |
||||
import '../../../retrofit/data/set_specs_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
class SetGoodsSpecs extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
SetGoodsSpecs({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _SetGoodsSpecs(); |
||||
} |
||||
} |
||||
|
||||
class _SetGoodsSpecs extends State<SetGoodsSpecs> { |
||||
List<SetSpecsList> specs = []; |
||||
List<Map<String, String>> specsDetails = []; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
///sku计算 |
||||
List<String> mergeArr(List<List<String>> arr) { |
||||
var result = arr.removeAt(0); |
||||
while (arr.isNotEmpty) { |
||||
var curArr = arr.removeAt(0); |
||||
var lastArr = result; |
||||
result = []; |
||||
for (var lastVal in lastArr) { |
||||
for (var curVal in curArr) { |
||||
result.add("$lastVal $curVal"); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "设置商品规格", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 150.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: specs.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: specsText(position)); |
||||
}, |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specs.add(SetSpecsList()); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.symmetric(vertical: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 20, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"添加规格", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
if (specs.length > 0) |
||||
Padding( |
||||
padding: EdgeInsets.all(16), |
||||
child: Text( |
||||
"设置库存/价格等规格明细", |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), |
||||
if (specs.length > 0) |
||||
Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.only( |
||||
top: 20.h, |
||||
bottom: 20.h, |
||||
left: 16.w, |
||||
right: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"规格明细", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
bool flag = false; |
||||
String tipText = ""; |
||||
specs.forEach((element) { |
||||
if (element.specsNameController.text |
||||
.trim() == |
||||
"") { |
||||
flag = true; |
||||
tipText = "规格名称未输入,请先输入规格名称"; |
||||
return; |
||||
} else if (element |
||||
.specsValues.length == |
||||
0) { |
||||
flag = true; |
||||
tipText = "未添加规格值,请先添加规格值"; |
||||
return; |
||||
} |
||||
}); |
||||
if (flag) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: tipText, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
List<String> skus = mergeArr(specs |
||||
.map((e) => e.specsValues) |
||||
.toList()); |
||||
Navigator.of(context).pushNamed( |
||||
'/router/edit_specs_detail', |
||||
arguments: { |
||||
"skus": skus, |
||||
"specsDetails": specsDetails |
||||
}).then((value) { |
||||
if (value != null){ |
||||
specsDetails.clear(); |
||||
specsDetails.addAll(value); |
||||
setState((){}); |
||||
} |
||||
}); |
||||
} |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: |
||||
MainAxisAlignment.end, |
||||
children: [ |
||||
Padding( |
||||
padding: |
||||
EdgeInsets.only(right: 5.w), |
||||
child: Text( |
||||
"去设置", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Image.asset( |
||||
"assets/image/bs_right.webp", |
||||
width: 16.h, |
||||
height: 16.h, |
||||
), |
||||
], |
||||
))) |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
|
||||
///确认 |
||||
Align( |
||||
alignment: Alignment.bottomCenter, |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, left: 16.w, right: 16.w, bottom: 34.h), |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
height: 54.h, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(27), |
||||
), |
||||
child: Text( |
||||
"确认", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///添加规格样式 |
||||
Widget specsText(index) { |
||||
return Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w), |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"添加规格", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: specs[index].specsNameController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入规格名称", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF0D0D0D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
flex: 1, |
||||
child: Text( |
||||
"规格植", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed( |
||||
'/router/set_goods_specs_value', |
||||
arguments: { |
||||
"storeId": "", |
||||
"specsValues": specs[index].specsValues |
||||
}).then((value) { |
||||
if (value != null) |
||||
setState(() { |
||||
specs[index].specsValues = value; |
||||
}); |
||||
}); |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
specs[index].specsValues.length != 0 |
||||
? specs[index] |
||||
.specsValues |
||||
.map((e) => e) |
||||
.toString() |
||||
.replaceAll("(", "") |
||||
.replaceAll(")", "") |
||||
: "请添加规格值", |
||||
overflow: TextOverflow.ellipsis, |
||||
maxLines: 1, |
||||
textAlign: TextAlign.end, |
||||
style: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), |
||||
Image.asset( |
||||
"assets/image/bs_right.webp", |
||||
width: 16.h, |
||||
height: 16.h, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
)), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
margin: EdgeInsets.only(bottom: 18.h), |
||||
), |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
specs.removeAt(index); |
||||
}); |
||||
}, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(bottom: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
children: [ |
||||
Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 24, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"删除", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,252 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/set_specs_list.dart'; |
||||
import '../../../retrofit/data/set_specs_value_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
class SetGoodsSpecsValue extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
SetGoodsSpecsValue({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _SetGoodsSpecsValue(); |
||||
} |
||||
} |
||||
|
||||
class _SetGoodsSpecsValue extends State<SetGoodsSpecsValue> { |
||||
List<SetSpecsValueList> specsValue = []; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
List<String> specsValues = widget.arguments["specsValues"] ?? []; |
||||
specsValues.forEach((element) { |
||||
var temp = SetSpecsValueList(); |
||||
temp.specsValueNameController.text = element; |
||||
specsValue.add(temp); |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "设置商品规格值", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 150.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
color: Colors.white, |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: specsValue.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() {}); |
||||
}, |
||||
child: specsValueText(position)); |
||||
}, |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsValue.add(SetSpecsValueList()); |
||||
FocusScope.of(context).unfocus(); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.symmetric(vertical: 20.h), |
||||
margin: EdgeInsets.only(top: 12.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 20, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"添加规格值", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
|
||||
///确认 |
||||
Align( |
||||
alignment: Alignment.bottomCenter, |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
bool flag = false; |
||||
List<String> values = []; |
||||
specsValue.forEach((element) { |
||||
if (element.specsValueNameController.text == "") { |
||||
flag = true; |
||||
return; |
||||
} |
||||
values.add(element.specsValueNameController.text); |
||||
}); |
||||
if (flag) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: "还有规格未输入值,请输入完整", |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} else { |
||||
Navigator.of(context).pop(values); |
||||
} |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, left: 16.w, right: 16.w, bottom: 34.h), |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
height: 54.h, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(27), |
||||
), |
||||
child: Text( |
||||
"确认", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
)) |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///添加规格样式 |
||||
Widget specsValueText(index) { |
||||
return Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w), |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
specsValue.removeAt(index); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(right: 12.w), |
||||
child: Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 24, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: specsValue[index].specsValueNameController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入规格值名称", |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
style: TextStyle( |
||||
color: Color(0xFF0D0D0D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
if (specsValue.length - 1 > index) |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,491 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/set_specs_meal_list.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
|
||||
class SetMeal extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
SetMeal({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _SetMeal(); |
||||
} |
||||
} |
||||
|
||||
class _SetMeal extends State<SetMeal> { |
||||
List<SetSpecsMealList> specsMeal = []; |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
BusinessApiService businessService; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
_focusNode.unfocus(); |
||||
super.dispose(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "套餐选择", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
action: GestureDetector( |
||||
onTap: () { |
||||
}, |
||||
child: Text( |
||||
"确定", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
body: Stack( |
||||
children: [ |
||||
SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 150.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: specsMeal.length, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() {}); |
||||
}, |
||||
child: specsValueText(position)); |
||||
}, |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal.add(SetSpecsMealList()); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.symmetric(vertical: 20.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 20, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"添加分组", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
)); |
||||
} |
||||
|
||||
///添加规格样式 |
||||
Widget specsValueText(index) { |
||||
return Column( |
||||
children: [ |
||||
Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
padding: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 12.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"分组1", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: specsMeal[index].groupsNameController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入分组名称", |
||||
hintTextDirection: TextDirection.rtl, |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF7A797F), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
border: InputBorder.none, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Color(0xFF0D0D0D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
flex: 2, |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 14.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"分组总数", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
if (specsMeal[index].groupsTotal <= 1) return; |
||||
specsMeal[index].groupsTotal = |
||||
specsMeal[index].groupsTotal - 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 20.w), |
||||
child: Icon( |
||||
Icons.remove_circle_outline, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
))), |
||||
Text( |
||||
specsMeal[index].groupsTotal.toString(), |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 20.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal[index].groupsTotal = |
||||
specsMeal[index].groupsTotal + 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(left: 20.w), |
||||
child: Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
)), |
||||
), |
||||
], |
||||
)), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
margin: EdgeInsets.only(bottom: 18.h), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 14.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"可选数量", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
if (specsMeal[index].optionalNum <= 1) return; |
||||
specsMeal[index].optionalNum = |
||||
specsMeal[index].optionalNum - 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 20.w), |
||||
child: Icon( |
||||
Icons.remove_circle_outline, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
))), |
||||
Text( |
||||
specsMeal[index].optionalNum.toString(), |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 20.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal[index].optionalNum = |
||||
specsMeal[index].optionalNum + 1; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(left: 20.w), |
||||
child: Icon( |
||||
Icons.add_circle, |
||||
color: Color(0xFF30415B), |
||||
size: 24, |
||||
)), |
||||
), |
||||
], |
||||
)), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0x14000000), |
||||
margin: EdgeInsets.only(bottom: 18.h), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed('/router/batch_shelf', |
||||
arguments: { |
||||
"storeId": widget.arguments["storeId"], |
||||
"titleName": "选择商品" |
||||
}).then((value) { |
||||
specsMeal[index].goodsMeal.clear(); |
||||
specsMeal[index].goodsMeal.addAll(value); |
||||
setState(() {}); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.only( |
||||
left: 8.w, right: 8.w, bottom: 3.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
border: Border.all( |
||||
color: Color(0xFF2E3552), |
||||
width: 1, |
||||
), |
||||
borderRadius: BorderRadius.circular(100), |
||||
), |
||||
child: Text( |
||||
"+增加商品", |
||||
style: TextStyle( |
||||
color: Color(0xFF30415B), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
)), |
||||
Spacer(), |
||||
GestureDetector( |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal.removeAt(index); |
||||
}); |
||||
}, |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
children: [ |
||||
Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 24, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 7.w), |
||||
child: Text( |
||||
"删除分组", |
||||
style: TextStyle( |
||||
color: Color(0xD9000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
) |
||||
], |
||||
), |
||||
), |
||||
Text( |
||||
"*请添加或减少商品,直到达到分组总数", |
||||
style: TextStyle( |
||||
color: Color(0xFFFA5151), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
ListView.builder( |
||||
itemCount: specsMeal[index]?.goodsMeal?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: specsInfoItem(index, position), |
||||
); |
||||
}, |
||||
) |
||||
], |
||||
); |
||||
} |
||||
|
||||
///规格信息样式 |
||||
Widget specsInfoItem(specsIndex, index) { |
||||
return Container( |
||||
color: Colors.white, |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
padding: EdgeInsets.only( |
||||
left: 16.w, |
||||
top: 20.h, |
||||
bottom: 20.h, |
||||
), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
specsMeal[specsIndex]?.goodsMeal[index]["goodsName"] ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
flex: 2, |
||||
), |
||||
Expanded( |
||||
child: Text( |
||||
"所有规格", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Text( |
||||
specsMeal[specsIndex]?.goodsMeal[index]["goodsNum"] ?? "", |
||||
textAlign: TextAlign.center, |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
specsMeal[specsIndex].goodsMeal.removeAt(index); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(right: 31.h), |
||||
child: Icon( |
||||
Icons.remove_circle, |
||||
color: Color(0xFFFA5151), |
||||
size: 20, |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,367 @@
|
||||
import 'dart:convert'; |
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../utils/captcha_util.dart'; |
||||
import '../../../utils/widget_util.dart'; |
||||
|
||||
typedef VoidSuccessCallback = dynamic Function(String v); |
||||
|
||||
class BusClickWordCaptcha extends StatefulWidget { |
||||
final VoidSuccessCallback onSuccess; //文字点击后验证成功回调 |
||||
final VoidCallback onFail; //文字点击完成后验证失败回调 |
||||
|
||||
const BusClickWordCaptcha({Key key, this.onSuccess, this.onFail}) |
||||
: super(key: key); |
||||
|
||||
@override |
||||
_BusClickWordCaptchaState createState() => _BusClickWordCaptchaState(); |
||||
} |
||||
|
||||
class _BusClickWordCaptchaState extends State<BusClickWordCaptcha> { |
||||
BusClickWordCaptchaState _busClickWordCaptchaState = BusClickWordCaptchaState.none; |
||||
List<Offset> _tapOffsetList = []; |
||||
BusClickWordCaptchaModel _busClickWordCaptchaModel = BusClickWordCaptchaModel(); |
||||
|
||||
Color titleColor = Colors.black; |
||||
Color borderColor = Color(0xffdddddd); |
||||
String bottomTitle = ""; |
||||
Size baseSize = Size(310.0, 155.0); |
||||
|
||||
//改变底部样式及字段 |
||||
_changeResultState() { |
||||
switch (_busClickWordCaptchaState) { |
||||
case BusClickWordCaptchaState.normal: |
||||
titleColor = Colors.black; |
||||
borderColor = Color(0xffdddddd); |
||||
break; |
||||
case BusClickWordCaptchaState.success: |
||||
_tapOffsetList = []; |
||||
titleColor = Colors.green; |
||||
borderColor = Colors.green; |
||||
bottomTitle = "验证成功"; |
||||
break; |
||||
case BusClickWordCaptchaState.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 = []; |
||||
_busClickWordCaptchaState = BusClickWordCaptchaState.none; |
||||
_changeResultState(); |
||||
BusinessApiService businessService = BusinessApiService(Dio(), context: context); |
||||
BusClickWordCaptchaModel baseData = (await businessService.captchaGet({"captchaType": "clickWord"}).catchError((onError) {})) as BusClickWordCaptchaModel; |
||||
if (baseData == null) { |
||||
_busClickWordCaptchaModel.secretKey = ""; |
||||
bottomTitle = "加载失败,请刷新"; |
||||
_busClickWordCaptchaState = BusClickWordCaptchaState.normal; |
||||
_changeResultState(); |
||||
return; |
||||
} |
||||
else { |
||||
_busClickWordCaptchaModel = baseData; |
||||
var baseR = await WidgetUtil.getImageWH( |
||||
image: Image.memory( |
||||
Base64Decoder().convert(_busClickWordCaptchaModel.imgStr))); |
||||
baseSize = baseR.size; |
||||
|
||||
bottomTitle = "请依次点击【${_busClickWordCaptchaModel.wordStr}】"; |
||||
} |
||||
|
||||
_busClickWordCaptchaState = BusClickWordCaptchaState.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(_busClickWordCaptchaModel.secretKey)) { |
||||
cryptedStr = CaptchaUtil.aesEncode( |
||||
key: _busClickWordCaptchaModel.secretKey, content: pointStr); |
||||
// var dcrypt = CaptchaUtil.aesDecode( |
||||
// key: _busClickWordCaptchaModel.secretKey, content: cryptedStr); |
||||
} |
||||
|
||||
// Map _map = json.decode(dcrypt); |
||||
BusinessApiService businessService = BusinessApiService(Dio(), context: context); |
||||
bool baseData = await businessService.captchaCheck({ |
||||
"pointJson": cryptedStr, |
||||
"captchaType": "clickWord", |
||||
"token": _busClickWordCaptchaModel.token |
||||
}).catchError((onError) {}); |
||||
if (baseData) { |
||||
_checkFail(); |
||||
return; |
||||
} |
||||
//如果不加密 将 token 和 坐标序列化 通过 --- 链接成字符串 |
||||
var captchaVerification = "${_busClickWordCaptchaModel.token}---$pointStr"; |
||||
if (!CaptchaUtil.isEmpty(_busClickWordCaptchaModel.secretKey)) { |
||||
//如果加密 将 token 和 坐标序列化 通过 --- 链接成字符串 进行加密 加密密钥为 _busClickWordCaptchaModel.secretKey |
||||
captchaVerification = CaptchaUtil.aesEncode( |
||||
key: _busClickWordCaptchaModel.secretKey, |
||||
content: captchaVerification); |
||||
} |
||||
_checkSuccess(captchaVerification); |
||||
} |
||||
|
||||
//校验失败 |
||||
_checkFail() async { |
||||
_busClickWordCaptchaState = BusClickWordCaptchaState.fail; |
||||
_changeResultState(); |
||||
|
||||
await Future.delayed(Duration(milliseconds: 1000)); |
||||
_loadCaptcha(); |
||||
//回调 |
||||
if (widget.onFail != null) { |
||||
widget.onFail(); |
||||
} |
||||
} |
||||
|
||||
//校验成功 |
||||
_checkSuccess(String pointJson) async { |
||||
_busClickWordCaptchaState = BusClickWordCaptchaState.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(_busClickWordCaptchaModel.imgStr)) { |
||||
_widgetList.add(Image( |
||||
width: baseSize.width, |
||||
height: baseSize.height, |
||||
gaplessPlayback: true, |
||||
image: MemoryImage( |
||||
Base64Decoder().convert(_busClickWordCaptchaModel.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(_busClickWordCaptchaModel.wordList) && |
||||
_tapOffsetList.length < _busClickWordCaptchaModel.wordList.length) { |
||||
_tapOffsetList.add( |
||||
Offset(details.localPosition.dx, details.localPosition.dy)); |
||||
} |
||||
setState(() {}); |
||||
if (!CaptchaUtil.isListEmpty(_busClickWordCaptchaModel.wordList) && |
||||
_tapOffsetList.length == _busClickWordCaptchaModel.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 BusClickWordCaptchaState { |
||||
normal, //默认 可自定义描述 |
||||
success, //成功 |
||||
fail, //失败 |
||||
none, //无状态 用于加载使用 |
||||
} |
||||
|
||||
//请求数据模型 |
||||
class BusClickWordCaptchaModel { |
||||
String imgStr; //图表url 目前用base64 data |
||||
String jigsawImageBase64; //图表url 目前用base64 data |
||||
String token; // 获取的token 用于校验 |
||||
List wordList; //显示需要点选的字 |
||||
String wordStr; //显示需要点选的字转换为字符串 |
||||
String secretKey; //加密key |
||||
|
||||
BusClickWordCaptchaModel( |
||||
{this.imgStr = "", |
||||
this.jigsawImageBase64 = "", |
||||
this.token = "", |
||||
this.secretKey = "", |
||||
this.wordList = const [], |
||||
this.wordStr = ""}); |
||||
|
||||
//解析数据转换模型 |
||||
static BusClickWordCaptchaModel fromMap(Map<String, dynamic> map) { |
||||
BusClickWordCaptchaModel captchaModel = BusClickWordCaptchaModel(); |
||||
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,760 @@
|
||||
import 'dart:async'; |
||||
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/gestures.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:sharesdk_plugin/sharesdk_interface.dart'; |
||||
|
||||
import '../../generated/l10n.dart'; |
||||
import '../../retrofit/business_api.dart'; |
||||
import '../../retrofit/data/base_data.dart'; |
||||
import '../../utils/flutter_utils.dart'; |
||||
import '../../utils/font_weight.dart'; |
||||
import '../../view_widget/border_text.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
import '../../view_widget/round_button.dart'; |
||||
import '../../view_widget/settlement_tips_dialog.dart'; |
||||
import 'captcha/bus_block_puzzle_captcha.dart'; |
||||
|
||||
class RegisterRetrievePassword extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
RegisterRetrievePassword({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _RegisterRetrievePassword(); |
||||
} |
||||
} |
||||
|
||||
class _RegisterRetrievePassword extends State<RegisterRetrievePassword> { |
||||
TextEditingController phoneController = TextEditingController(); |
||||
TextEditingController codeController = TextEditingController(); |
||||
TextEditingController passwordController = TextEditingController(); |
||||
TextEditingController changePasswordController = TextEditingController(); |
||||
TextEditingController businessNameController = TextEditingController(); |
||||
final TapGestureRecognizer tapGestureRecognizer = TapGestureRecognizer(); |
||||
var checkStatus = false; |
||||
String titleName; |
||||
BusinessApiService businessService; |
||||
Color statusCodeTextColor = Color(0xFF353535); |
||||
var verifyStatus = 0; |
||||
var mobileStatus = 0; |
||||
var btnText = "获取验证码"; |
||||
var sendCodeStatus = 0; |
||||
Timer _timer; |
||||
int phoneState = 1; |
||||
String mobile; |
||||
String newMobile; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
titleName = widget?.arguments["titleName"] ?? ""; |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
if (_timer != null && _timer.isActive) _timer.cancel(); |
||||
} |
||||
|
||||
///发送验证码 |
||||
sendVerifyCode(v) async { |
||||
BusinessApiService businessService = |
||||
BusinessApiService(Dio(), context: context); |
||||
BaseData baseData = await businessService.busSendVerify({ |
||||
"areaCode": "+86", |
||||
"mobile": phoneController.text, |
||||
"verification": v |
||||
}).catchError((onError) { |
||||
SmartDialog.showToast(AppUtils.dioErrorTypeToString(onError.type), |
||||
alignment: Alignment.center); |
||||
}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
sendCodeStatus = 1; |
||||
countdown(); |
||||
SmartDialog.showToast(baseData.data, alignment: Alignment.center); |
||||
} else { |
||||
btnText = S.of(context).send_code; |
||||
sendCodeStatus = 0; |
||||
SmartDialog.showToast("${baseData.msg}", alignment: Alignment.center); |
||||
refresh(); |
||||
} |
||||
} |
||||
|
||||
///刷新页面 |
||||
void refresh() { |
||||
if (!mounted) return; |
||||
setState(() {}); |
||||
} |
||||
|
||||
///发送验证码成功倒计时 |
||||
countdown() { |
||||
if (_timer != null && _timer.isActive) return; |
||||
int countdown = 60; |
||||
_timer = Timer.periodic(Duration(seconds: 1), (timer) { |
||||
countdown--; |
||||
if (countdown == 0) { |
||||
btnText = "重新发送"; |
||||
sendCodeStatus = 0; |
||||
_timer.cancel(); |
||||
} else { |
||||
btnText = "${countdown}s"; |
||||
} |
||||
if (!mounted) return; |
||||
setState(() {}); |
||||
}); |
||||
} |
||||
|
||||
///注册接口 |
||||
register() async { |
||||
try { |
||||
if (codeController.text == "") { |
||||
SmartDialog.showToast("请输入验证码", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (phoneController.text == "") { |
||||
SmartDialog.showToast(S.of(context).qingshurushoujihao, |
||||
alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (passwordController.text == "") { |
||||
SmartDialog.showToast("请输入密码", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (businessNameController.text == "") { |
||||
SmartDialog.showToast("请输入商户名称", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (!checkStatus) { |
||||
SmartDialog.showToast(S.of(context).gouxuanxieyi, |
||||
alignment: Alignment.center); |
||||
return; |
||||
} |
||||
|
||||
var param = { |
||||
"areaCode": "+86", |
||||
"mobile": phoneController.text, |
||||
"capcha": codeController.text, |
||||
"tenantName": businessNameController.text, |
||||
"password": passwordController.text, |
||||
}; |
||||
EasyLoading.show( |
||||
status: S.of(context).zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
businessService = BusinessApiService(Dio(), context: context); |
||||
BaseData baseData = |
||||
await businessService.tenantAppLogin(param).catchError((error) { |
||||
print(error.message); |
||||
}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: baseData.data, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
Navigator.of(context).pop(); |
||||
} else { |
||||
if (baseData.msg != null) |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: baseData.msg, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} |
||||
} finally { |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
///找回密码 |
||||
userChangePsd() async { |
||||
try { |
||||
if (phoneController.text == "") { |
||||
SmartDialog.showToast(S.of(context).qingshurushoujihao, |
||||
alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (codeController.text == "") { |
||||
SmartDialog.showToast("请输入验证码", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (passwordController.text == "") { |
||||
SmartDialog.showToast("请输入密码", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (changePasswordController.text == "") { |
||||
SmartDialog.showToast("请输入确认密码", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
if (passwordController.text != changePasswordController.text) { |
||||
SmartDialog.showToast("两次密码不一致,请重新输入", alignment: Alignment.center); |
||||
return; |
||||
} |
||||
|
||||
var param = { |
||||
"areaCode": "+86", |
||||
"mobile": phoneController.text, |
||||
"capcha": codeController.text, |
||||
"newPassword": changePasswordController.text, |
||||
}; |
||||
EasyLoading.show( |
||||
status: S.of(context).zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
businessService = BusinessApiService(Dio(), context: context); |
||||
BaseData baseData = |
||||
await businessService.tenantUserChangePsd(param).catchError((error) { |
||||
print(error.message); |
||||
}); |
||||
if (baseData != null && baseData.isSuccess) { |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: baseData.data, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
Navigator.of(context).pop(); |
||||
} else { |
||||
if (baseData.msg != null) |
||||
SmartDialog.show( |
||||
clickBgDismissTemp: false, |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: baseData.msg, |
||||
color: Color(0xFF30415B), |
||||
)); |
||||
} |
||||
} finally { |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
backgroundColor: Colors.white, |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: titleName, |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
}, |
||||
child: Column( |
||||
children: [ |
||||
registerAccount(), |
||||
GestureDetector( |
||||
onTap: () { |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
if (titleName == "注册账号") { |
||||
register(); |
||||
} else { |
||||
userChangePsd(); |
||||
} |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(vertical: 15.h), |
||||
margin: |
||||
EdgeInsets.symmetric(horizontal: 16.w, vertical: 30.h), |
||||
alignment: Alignment.center, |
||||
width: double.infinity, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
child: Text( |
||||
titleName == "注册账号" ? "注册" : "确定", |
||||
style: TextStyle( |
||||
fontSize: 16.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
), |
||||
), |
||||
if (titleName == "注册账号") |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Checkbox( |
||||
value: checkStatus, |
||||
onChanged: (a) { |
||||
setState(() { |
||||
checkStatus = !checkStatus; |
||||
}); |
||||
}, |
||||
checkColor: Color(0xFFFFFFFF), |
||||
fillColor: MaterialStateProperty.all(Color(0xFF30415B)), |
||||
), |
||||
Expanded( |
||||
child: Text.rich( |
||||
TextSpan(children: [ |
||||
TextSpan( |
||||
text: S.of(context).privacy_policy1, |
||||
style: TextStyle( |
||||
fontSize: 11.sp, |
||||
color: Color(0xFF010101), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "《一心回乡用户协议》", |
||||
recognizer: TapGestureRecognizer() |
||||
..onTap = () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/user_service_page'); |
||||
}, |
||||
style: TextStyle( |
||||
fontSize: 11.sp, |
||||
color: Color(0xFF010101), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "、", |
||||
style: TextStyle( |
||||
fontSize: 11.sp, |
||||
color: Colors.black, |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: S.of(context).privacy_policy3, |
||||
recognizer: tapGestureRecognizer, |
||||
style: TextStyle( |
||||
fontSize: 11.sp, |
||||
color: Color(0xFF010101), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: S.of(context).privacy_policy4, |
||||
style: TextStyle( |
||||
fontSize: 11.sp, |
||||
height: 1.2, |
||||
color: Color(0xFF010101), |
||||
), |
||||
), |
||||
]), |
||||
)), |
||||
SizedBox( |
||||
width: 30, |
||||
) |
||||
], |
||||
), |
||||
], |
||||
)), |
||||
); |
||||
} |
||||
|
||||
Widget registerAccount() { |
||||
return Container( |
||||
padding: |
||||
EdgeInsets.only(top: 21.h, bottom: 16.h, left: 15.w, right: 18.w), |
||||
margin: EdgeInsets.only(left: 16.w, right: 16.w, top: 16.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Colors.black.withAlpha(12), |
||||
offset: Offset(0, 3), |
||||
blurRadius: 14, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Column( |
||||
children: [ |
||||
///手机号 |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"手机号码", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: phoneController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入手机号码", |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
border: InputBorder.none, |
||||
contentPadding: EdgeInsets.only(left: 23.w), |
||||
), |
||||
inputFormatters: [LengthLimitingTextInputFormatter(11)], |
||||
keyboardType: TextInputType.phone, |
||||
style: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
color: Color(0xFFEBECEF), |
||||
margin: EdgeInsets.only(bottom: 16.h), |
||||
), |
||||
|
||||
///验证码 |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"验证码", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
Expanded( |
||||
flex: 2, |
||||
child: TextField( |
||||
controller: codeController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入验证码", |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
border: InputBorder.none, |
||||
contentPadding: EdgeInsets.only(left: 23.w), |
||||
), |
||||
keyboardType: TextInputType.phone, |
||||
style: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
mobile = phoneController.text; |
||||
if (mobile == "") { |
||||
SmartDialog.showToast(S.of(context).qingshurushoujihao, |
||||
alignment: Alignment.center); |
||||
return; |
||||
} |
||||
loadingBlockPuzzle(context); |
||||
}, |
||||
child: Text( |
||||
btnText, |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF30415B), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
Container( |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
color: Color(0xFFEBECEF), |
||||
margin: EdgeInsets.only(bottom: 16.h), |
||||
), |
||||
|
||||
///密码 |
||||
Row( |
||||
children: [ |
||||
Text( |
||||
"密码", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: passwordController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入密码", |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
border: InputBorder.none, |
||||
contentPadding: EdgeInsets.only(left: 23.w), |
||||
), |
||||
keyboardType: TextInputType.phone, |
||||
style: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
Container( |
||||
height: 1.h, |
||||
width: double.infinity, |
||||
color: Color(0xFFEBECEF), |
||||
margin: EdgeInsets.only(bottom: 16.h), |
||||
), |
||||
|
||||
///商户名称/确认密码 |
||||
titleName == "注册账号" |
||||
? Row( |
||||
children: [ |
||||
Text( |
||||
"商户名称", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: businessNameController, |
||||
decoration: InputDecoration( |
||||
hintText: "请输入商户名称", |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
border: InputBorder.none, |
||||
contentPadding: EdgeInsets.only(left: 23.w), |
||||
), |
||||
keyboardType: TextInputType.phone, |
||||
style: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
], |
||||
) |
||||
: Row( |
||||
children: [ |
||||
Text( |
||||
"确认密码", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: changePasswordController, |
||||
decoration: InputDecoration( |
||||
hintText: "请再次输入密码", |
||||
hintStyle: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
border: InputBorder.none, |
||||
contentPadding: EdgeInsets.only(left: 23.w), |
||||
), |
||||
keyboardType: TextInputType.phone, |
||||
style: TextStyle( |
||||
color: Color(0xFF808080), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
], |
||||
) |
||||
], |
||||
)); |
||||
} |
||||
|
||||
showAlertDialog() { |
||||
//显示对话框 |
||||
showDialog( |
||||
context: context, |
||||
builder: (BuildContext context) { |
||||
return WillPopScope( |
||||
onWillPop: () async => false, |
||||
child: SimpleDialog( |
||||
titlePadding: EdgeInsets.all(10), |
||||
backgroundColor: Colors.transparent, |
||||
elevation: 0, |
||||
shape: RoundedRectangleBorder( |
||||
borderRadius: BorderRadius.circular(6), |
||||
), |
||||
children: <Widget>[ |
||||
Stack( |
||||
alignment: Alignment.bottomCenter, |
||||
children: [ |
||||
Container( |
||||
alignment: Alignment.center, |
||||
width: double.infinity, |
||||
height: 325.h, |
||||
padding: EdgeInsets.only(left: 16.w, right: 16.w), |
||||
decoration: new BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Column( |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 24.h, bottom: 10.h), |
||||
child: Text( |
||||
S.of(context).xieyitanchuang, |
||||
style: TextStyle( |
||||
color: Color(0xff4D4D4D), |
||||
fontSize: 18.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
Text.rich( |
||||
TextSpan(children: [ |
||||
TextSpan( |
||||
text: S.of(context).yinsizhengce1, |
||||
style: TextStyle( |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 14.sp, |
||||
height: 1.3.h, |
||||
color: Color(0xff727272), |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: S.of(context).yinsixieyi, |
||||
style: TextStyle( |
||||
fontWeight: MyFontWeight.medium, |
||||
fontSize: 14.sp, |
||||
color: Color(0xff32A060)), |
||||
recognizer: TapGestureRecognizer() |
||||
..onTap = () { |
||||
Navigator.of(context) |
||||
.popAndPushNamed('/router/treaty_page'); |
||||
}, |
||||
), |
||||
]), |
||||
), |
||||
SizedBox( |
||||
height: 10.h, |
||||
), |
||||
Text( |
||||
S.of(context).yinsizhengce2, |
||||
style: TextStyle( |
||||
color: Color(0xff727272), |
||||
fontSize: 14.sp, |
||||
height: 1.3.h, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 16.h, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
GestureDetector( |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
// exit(0); |
||||
}, |
||||
child: Container( |
||||
height: 40.h, |
||||
alignment: Alignment.bottomCenter, |
||||
margin: EdgeInsets.only(bottom: 20.h), |
||||
child: BorderText( |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, |
||||
bottom: 10.h, |
||||
left: 36.w, |
||||
right: 36.w, |
||||
), |
||||
text: S.of(context).jujue, |
||||
fontSize: 12.sp, |
||||
textColor: Color(0xFF32A060), |
||||
borderColor: Color(0xFF32A060), |
||||
borderWidth: 1.w, |
||||
radius: 23, |
||||
), |
||||
), |
||||
), |
||||
SizedBox( |
||||
width: 21.w, |
||||
), |
||||
Container( |
||||
height: 40.h, |
||||
margin: EdgeInsets.only(bottom: 20.h), |
||||
alignment: Alignment.bottomCenter, |
||||
child: RoundButton( |
||||
text: S.of(context).tongyibingjixu, |
||||
textColor: Colors.white, |
||||
fontSize: 12.sp, |
||||
callback: () { |
||||
SharedPreferences.getInstance().then((value) { |
||||
value.setBool("isShowPrivacyPolicy", true); |
||||
}); |
||||
SharesdkPlugin.uploadPrivacyPermissionStatus( |
||||
1, |
||||
(success) => { |
||||
Navigator.of(context).pop(), |
||||
}, |
||||
); |
||||
}, |
||||
padding: EdgeInsets.only( |
||||
top: 10.h, |
||||
bottom: 10.h, |
||||
left: 21.5.w, |
||||
right: 21.5.w, |
||||
), |
||||
backgroup: Color(0xff32A060), |
||||
radius: 23, |
||||
), |
||||
), |
||||
SizedBox( |
||||
height: 20.h, |
||||
), |
||||
], |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
//滑动拼图 |
||||
loadingBlockPuzzle(BuildContext context, {barrierDismissible = true}) { |
||||
showDialog<Null>( |
||||
context: context, |
||||
barrierDismissible: barrierDismissible, |
||||
builder: (BuildContext context) { |
||||
return BusBlockPuzzleCaptchaPage( |
||||
onSuccess: (v) { |
||||
sendVerifyCode(v); |
||||
}, |
||||
onFail: () { |
||||
print("onFail"); |
||||
}, |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,44 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:huixiang/view_widget/my_appbar.dart'; |
||||
|
||||
class FunctionVersionDetail extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
FunctionVersionDetail({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _FunctionVersionDetail(); |
||||
} |
||||
} |
||||
|
||||
class _FunctionVersionDetail extends State<FunctionVersionDetail> { |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "功能版本介绍", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
brightness: Brightness.dark, |
||||
), |
||||
body:Container( |
||||
width: double.infinity, |
||||
height: double.infinity, |
||||
child:Image.asset( |
||||
"assets/image/activity_q.webp", |
||||
width: double.infinity, |
||||
height: double.infinity, |
||||
fit: BoxFit.fill, |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,459 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:huixiang/view_widget/classic_header.dart'; |
||||
import 'package:huixiang/view_widget/my_footer.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../../generated/l10n.dart'; |
||||
import '../../../retrofit/business_api.dart'; |
||||
import '../../../retrofit/data/base_data.dart'; |
||||
import '../../../retrofit/data/service_bug_list.dart'; |
||||
import '../../../utils/business_instance.dart'; |
||||
import '../../../utils/flutter_utils.dart'; |
||||
import '../../../utils/font_weight.dart'; |
||||
import '../../../view_widget/my_appbar.dart'; |
||||
import '../../../view_widget/no_data_view.dart'; |
||||
|
||||
class ServicePurchaseRecord extends StatefulWidget { |
||||
final Map<String, dynamic> arguments; |
||||
|
||||
ServicePurchaseRecord({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _ServicePurchaseRecord(); |
||||
} |
||||
} |
||||
|
||||
class _ServicePurchaseRecord extends State<ServicePurchaseRecord> { |
||||
final RefreshController refreshController = RefreshController(); |
||||
BusinessApiService businessService; |
||||
int _current = 1; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
List<Records> records = []; |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
refreshController.dispose(); |
||||
} |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
_onRefresh({bool isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
await queryPackageBuyList(); |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (refreshController.isRefresh) refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
|
||||
///服务购买记录 |
||||
queryPackageBuyList() async { |
||||
try { |
||||
if (businessService == null) { |
||||
businessService = BusinessApiService(Dio(), |
||||
context: context, |
||||
token: BusinessInstance.instance.businessToken, |
||||
tenant: BusinessInstance.instance.businessTenant, |
||||
storeId: widget.arguments["storeId"]); |
||||
} |
||||
BaseData<ServiceBugList> baseData = await businessService.packageBuyList({ |
||||
"current": _current, |
||||
"map": {}, |
||||
"model": {"tenantCode": BusinessInstance.instance.businessTenant}, |
||||
"order": "descending", |
||||
"size": 10, |
||||
"sort": "createTime" |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData != null && baseData.isSuccess) { |
||||
records.addAll(baseData?.data?.records ?? []); |
||||
if ((baseData?.data?.records ?? []).isEmpty || |
||||
records.length.toString() == baseData.data.total) |
||||
refreshController.loadNoData(); |
||||
else |
||||
refreshController.loadComplete(); |
||||
networkStatus = 1; |
||||
} |
||||
} finally { |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: MyAppBar( |
||||
title: "购买记录", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
), |
||||
body: SmartRefresher( |
||||
controller: refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: records.length == 0 ? false : true, |
||||
header: MyHeader(color: Color(0xFF30415B)), |
||||
physics: BouncingScrollPhysics(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
_current = 1; |
||||
records.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
onLoading: () { |
||||
_current++; |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
child: networkStatus == -1 |
||||
? noNetwork() |
||||
: ((networkStatus == 0) |
||||
? Container( |
||||
margin: EdgeInsets.only(top: 12.h), |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
itemCount: 10, |
||||
scrollDirection: Axis.vertical, |
||||
shrinkWrap: true, |
||||
physics: BouncingScrollPhysics(), |
||||
itemBuilder: (context, position) { |
||||
return purchaseRecordItemSm(); |
||||
}, |
||||
)) |
||||
: ((records == null || records.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/bs_no data_logo.webp", |
||||
isShowBtn: false, |
||||
text: "暂无购买记录", |
||||
fontSize: 16.sp, |
||||
iconHeight: 120.h, |
||||
margin: EdgeInsets.all(50.h), |
||||
) |
||||
: Container( |
||||
margin: EdgeInsets.only(top: 12.h), |
||||
child: ListView.builder( |
||||
itemCount: records?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: purchaseRecordItem(records[position]), |
||||
); |
||||
}, |
||||
), |
||||
)))), |
||||
); |
||||
} |
||||
|
||||
Widget purchaseRecordItem(Records records) { |
||||
return Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
margin: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 12.h), |
||||
padding: EdgeInsets.only( |
||||
left: 12.h, |
||||
top: 12.h, |
||||
bottom: 12.h, |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
records?.packageName ?? "", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0xFFF4F6F7), |
||||
margin: EdgeInsets.symmetric(vertical: 13.h), |
||||
), |
||||
|
||||
///服务内容暂未定义,暂时隐藏 |
||||
// Padding( |
||||
// padding: EdgeInsets.only(bottom: 12.h), |
||||
// child: Text( |
||||
// "套餐内容: 会员管理", |
||||
// style: TextStyle( |
||||
// fontSize: 12.sp, |
||||
// color: Color(0xFF1A1A1A), |
||||
// fontWeight: MyFontWeight.regular), |
||||
// ), |
||||
// ), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Text( |
||||
"套餐年限: ${records?.packageNum ?? "0"}年", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Text( |
||||
"套餐金额: ${records?.packagePrice ?? "0"}元", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Text( |
||||
"购买时间: ${records?.createTime ?? ""}", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
Text( |
||||
"支付方式: ${records?.payChannel == 1 ? "微信支付" :"支付宝支付"}", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF1A1A1A), |
||||
fontWeight: MyFontWeight.regular), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget purchaseRecordItemSm() { |
||||
return Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
margin: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 12.h), |
||||
padding: EdgeInsets.only( |
||||
left: 12.h, |
||||
top: 16.h, |
||||
bottom: 16.h, |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 70.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Container( |
||||
width: double.infinity, |
||||
height: 1.h, |
||||
color: Color(0xFFF4F6F7), |
||||
margin: EdgeInsets.symmetric(vertical: 13.h), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 52.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(left: 15.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 48.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 52.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(left: 15.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 30.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 12.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 52.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(left: 15.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 123.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 52.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(left: 15.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 48.w, |
||||
height: 18.h, |
||||
), |
||||
), |
||||
], |
||||
) |
||||
], |
||||
)); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
margin: EdgeInsets.only(top: 120.h), |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
// "无法连接到网络", |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFF30415B), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
|
||||
class EditSpecsDetailList { |
||||
String _specsDetailName; |
||||
TextEditingController _goodPriceController; |
||||
TextEditingController _originalPriceController; |
||||
TextEditingController _packagingFeeController; |
||||
TextEditingController _specsWeightController; |
||||
TextEditingController _skuStockController; |
||||
|
||||
TextEditingController get goodPriceController => _goodPriceController; |
||||
TextEditingController get originalPriceController => _originalPriceController; |
||||
TextEditingController get packagingFeeController => _packagingFeeController; |
||||
TextEditingController get specsWeightController => _specsWeightController; |
||||
TextEditingController get skuStockController => _skuStockController; |
||||
|
||||
|
||||
String get specsDetailName => _specsDetailName; |
||||
|
||||
set specsDetailName(String value) { |
||||
_specsDetailName = value; |
||||
} |
||||
|
||||
EditSpecsDetailList(String specsDetailName){ |
||||
_specsDetailName = specsDetailName; |
||||
_goodPriceController = TextEditingController(); |
||||
_originalPriceController = TextEditingController(); |
||||
_packagingFeeController = TextEditingController(); |
||||
_specsWeightController = TextEditingController(); |
||||
_skuStockController = TextEditingController(); |
||||
} |
||||
} |
@ -0,0 +1,313 @@
|
||||
/// records : [{"id":"1745006589485514752","createTime":"2024-01-10 16:56:06","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:48","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1743090505270427648","oldPackageId":"1742842291845857280","packagePrice":"0.01","packageNum":1,"packageDiscount":100,"expirationTime":"2025-01-10 16:56:06","upgradeTime":null,"status":0,"payChannel":1,"isDelete":0,"packageName":"品牌商户"},{"id":"1745002175626477568","createTime":"2024-01-10 16:38:34","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:47","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1742842291845857280","oldPackageId":null,"packagePrice":"200.00","packageNum":10,"packageDiscount":100,"expirationTime":"2049-09-11 15:39:12","upgradeTime":null,"status":0,"payChannel":1,"isDelete":0,"packageName":"普通商户"},{"id":"1744984806560628736","createTime":"2024-01-10 15:29:33","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:46","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1743090505270427648","oldPackageId":null,"packagePrice":"0.01","packageNum":2,"packageDiscount":100,"expirationTime":"2030-01-10 14:23:37","upgradeTime":null,"status":1,"payChannel":1,"isDelete":0,"packageName":"品牌商户"},{"id":"1744983525037178880","createTime":"2024-01-10 15:24:27","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:46","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1743090505270427648","oldPackageId":null,"packagePrice":"0.01","packageNum":3,"packageDiscount":100,"expirationTime":"2028-01-10 14:23:37","upgradeTime":null,"status":1,"payChannel":1,"isDelete":0,"packageName":"品牌商户"},{"id":"1744968216842600448","createTime":"2024-01-10 14:23:37","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:45","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1743090505270427648","oldPackageId":"1742842291845857280","packagePrice":"0.01","packageNum":1,"packageDiscount":100,"expirationTime":"2025-01-10 14:23:37","upgradeTime":null,"status":1,"payChannel":1,"isDelete":0,"packageName":"品牌商户"},{"id":"1744965441966571520","createTime":"2024-01-10 14:12:36","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:44","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1742842291845857280","oldPackageId":null,"packagePrice":"0.01","packageNum":10,"packageDiscount":100,"expirationTime":"2030-01-10 18:00:00","upgradeTime":"2024-01-10 16:56:05","status":3,"payChannel":1,"isDelete":0,"packageName":"普通商户"},{"id":"1744965184633438208","createTime":"2024-01-10 14:11:35","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:44","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1742842291845857280","oldPackageId":null,"packagePrice":"0.01","packageNum":5,"packageDiscount":100,"expirationTime":"2027-01-10 18:00:00","upgradeTime":"2024-01-10 16:38:57","status":3,"payChannel":1,"isDelete":0,"packageName":"普通商户"},{"id":"1744965083273887744","createTime":"2024-01-10 14:11:10","createUser":"1739884285034233856","updateTime":"2024-01-11 07:51:43","updateUser":"1739884285034233856","tenantId":"1739884282001752064","tenantCode":"1197","packageId":"1742842291845857280","oldPackageId":null,"packagePrice":"0.01","packageNum":1,"packageDiscount":100,"expirationTime":"2025-01-10 18:00:00","upgradeTime":"2024-05-10 18:00:00","status":3,"payChannel":1,"isDelete":0,"packageName":"普通商户"}] |
||||
/// total : "8" |
||||
/// size : "10" |
||||
/// current : "1" |
||||
/// orders : [{"column":"create_time","asc":false}] |
||||
/// hitCount : false |
||||
/// searchCount : true |
||||
/// pages : "1" |
||||
|
||||
class ServiceBugList { |
||||
ServiceBugList({ |
||||
List<Records> records, |
||||
String total, |
||||
String size, |
||||
String current, |
||||
List<Orders> orders, |
||||
bool hitCount, |
||||
bool searchCount, |
||||
String pages,}){ |
||||
_records = records; |
||||
_total = total; |
||||
_size = size; |
||||
_current = current; |
||||
_orders = orders; |
||||
_hitCount = hitCount; |
||||
_searchCount = searchCount; |
||||
_pages = pages; |
||||
} |
||||
|
||||
ServiceBugList.fromJson(dynamic json) { |
||||
if (json['records'] != null) { |
||||
_records = []; |
||||
json['records'].forEach((v) { |
||||
_records.add(Records.fromJson(v)); |
||||
}); |
||||
} |
||||
_total = json['total']; |
||||
_size = json['size']; |
||||
_current = json['current']; |
||||
if (json['orders'] != null) { |
||||
_orders = []; |
||||
json['orders'].forEach((v) { |
||||
_orders.add(Orders.fromJson(v)); |
||||
}); |
||||
} |
||||
_hitCount = json['hitCount']; |
||||
_searchCount = json['searchCount']; |
||||
_pages = json['pages']; |
||||
} |
||||
List<Records> _records; |
||||
String _total; |
||||
String _size; |
||||
String _current; |
||||
List<Orders> _orders; |
||||
bool _hitCount; |
||||
bool _searchCount; |
||||
String _pages; |
||||
ServiceBugList copyWith({ List<Records> records, |
||||
String total, |
||||
String size, |
||||
String current, |
||||
List<Orders> orders, |
||||
bool hitCount, |
||||
bool searchCount, |
||||
String pages, |
||||
}) => ServiceBugList( records: records ?? _records, |
||||
total: total ?? _total, |
||||
size: size ?? _size, |
||||
current: current ?? _current, |
||||
orders: orders ?? _orders, |
||||
hitCount: hitCount ?? _hitCount, |
||||
searchCount: searchCount ?? _searchCount, |
||||
pages: pages ?? _pages, |
||||
); |
||||
List<Records> get records => _records; |
||||
String get total => _total; |
||||
String get size => _size; |
||||
String get current => _current; |
||||
List<Orders> get orders => _orders; |
||||
bool get hitCount => _hitCount; |
||||
bool get searchCount => _searchCount; |
||||
String get pages => _pages; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
if (_records != null) { |
||||
map['records'] = _records.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['total'] = _total; |
||||
map['size'] = _size; |
||||
map['current'] = _current; |
||||
if (_orders != null) { |
||||
map['orders'] = _orders.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['hitCount'] = _hitCount; |
||||
map['searchCount'] = _searchCount; |
||||
map['pages'] = _pages; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// column : "create_time" |
||||
/// asc : false |
||||
|
||||
class Orders { |
||||
Orders({ |
||||
String column, |
||||
bool asc,}){ |
||||
_column = column; |
||||
_asc = asc; |
||||
} |
||||
|
||||
Orders.fromJson(dynamic json) { |
||||
_column = json['column']; |
||||
_asc = json['asc']; |
||||
} |
||||
String _column; |
||||
bool _asc; |
||||
Orders copyWith({ String column, |
||||
bool asc, |
||||
}) => Orders( column: column ?? _column, |
||||
asc: asc ?? _asc, |
||||
); |
||||
String get column => _column; |
||||
bool get asc => _asc; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['column'] = _column; |
||||
map['asc'] = _asc; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// id : "1745006589485514752" |
||||
/// createTime : "2024-01-10 16:56:06" |
||||
/// createUser : "1739884285034233856" |
||||
/// updateTime : "2024-01-11 07:51:48" |
||||
/// updateUser : "1739884285034233856" |
||||
/// tenantId : "1739884282001752064" |
||||
/// tenantCode : "1197" |
||||
/// packageId : "1743090505270427648" |
||||
/// oldPackageId : "1742842291845857280" |
||||
/// packagePrice : "0.01" |
||||
/// packageNum : 1 |
||||
/// packageDiscount : 100 |
||||
/// expirationTime : "2025-01-10 16:56:06" |
||||
/// upgradeTime : null |
||||
/// status : 0 |
||||
/// payChannel : 1 |
||||
/// isDelete : 0 |
||||
/// packageName : "品牌商户" |
||||
|
||||
class Records { |
||||
Records({ |
||||
String id, |
||||
String createTime, |
||||
String createUser, |
||||
String updateTime, |
||||
String updateUser, |
||||
String tenantId, |
||||
String tenantCode, |
||||
String packageId, |
||||
String oldPackageId, |
||||
String packagePrice, |
||||
num packageNum, |
||||
num packageDiscount, |
||||
String expirationTime, |
||||
dynamic upgradeTime, |
||||
num status, |
||||
num payChannel, |
||||
num isDelete, |
||||
String packageName,}){ |
||||
_id = id; |
||||
_createTime = createTime; |
||||
_createUser = createUser; |
||||
_updateTime = updateTime; |
||||
_updateUser = updateUser; |
||||
_tenantId = tenantId; |
||||
_tenantCode = tenantCode; |
||||
_packageId = packageId; |
||||
_oldPackageId = oldPackageId; |
||||
_packagePrice = packagePrice; |
||||
_packageNum = packageNum; |
||||
_packageDiscount = packageDiscount; |
||||
_expirationTime = expirationTime; |
||||
_upgradeTime = upgradeTime; |
||||
_status = status; |
||||
_payChannel = payChannel; |
||||
_isDelete = isDelete; |
||||
_packageName = packageName; |
||||
} |
||||
|
||||
Records.fromJson(dynamic json) { |
||||
_id = json['id']; |
||||
_createTime = json['createTime']; |
||||
_createUser = json['createUser']; |
||||
_updateTime = json['updateTime']; |
||||
_updateUser = json['updateUser']; |
||||
_tenantId = json['tenantId']; |
||||
_tenantCode = json['tenantCode']; |
||||
_packageId = json['packageId']; |
||||
_oldPackageId = json['oldPackageId']; |
||||
_packagePrice = json['packagePrice']; |
||||
_packageNum = json['packageNum']; |
||||
_packageDiscount = json['packageDiscount']; |
||||
_expirationTime = json['expirationTime']; |
||||
_upgradeTime = json['upgradeTime']; |
||||
_status = json['status']; |
||||
_payChannel = json['payChannel']; |
||||
_isDelete = json['isDelete']; |
||||
_packageName = json['packageName']; |
||||
} |
||||
String _id; |
||||
String _createTime; |
||||
String _createUser; |
||||
String _updateTime; |
||||
String _updateUser; |
||||
String _tenantId; |
||||
String _tenantCode; |
||||
String _packageId; |
||||
String _oldPackageId; |
||||
String _packagePrice; |
||||
num _packageNum; |
||||
num _packageDiscount; |
||||
String _expirationTime; |
||||
dynamic _upgradeTime; |
||||
num _status; |
||||
num _payChannel; |
||||
num _isDelete; |
||||
String _packageName; |
||||
Records copyWith({ String id, |
||||
String createTime, |
||||
String createUser, |
||||
String updateTime, |
||||
String updateUser, |
||||
String tenantId, |
||||
String tenantCode, |
||||
String packageId, |
||||
String oldPackageId, |
||||
String packagePrice, |
||||
num packageNum, |
||||
num packageDiscount, |
||||
String expirationTime, |
||||
dynamic upgradeTime, |
||||
num status, |
||||
num payChannel, |
||||
num isDelete, |
||||
String packageName, |
||||
}) => Records( id: id ?? _id, |
||||
createTime: createTime ?? _createTime, |
||||
createUser: createUser ?? _createUser, |
||||
updateTime: updateTime ?? _updateTime, |
||||
updateUser: updateUser ?? _updateUser, |
||||
tenantId: tenantId ?? _tenantId, |
||||
tenantCode: tenantCode ?? _tenantCode, |
||||
packageId: packageId ?? _packageId, |
||||
oldPackageId: oldPackageId ?? _oldPackageId, |
||||
packagePrice: packagePrice ?? _packagePrice, |
||||
packageNum: packageNum ?? _packageNum, |
||||
packageDiscount: packageDiscount ?? _packageDiscount, |
||||
expirationTime: expirationTime ?? _expirationTime, |
||||
upgradeTime: upgradeTime ?? _upgradeTime, |
||||
status: status ?? _status, |
||||
payChannel: payChannel ?? _payChannel, |
||||
isDelete: isDelete ?? _isDelete, |
||||
packageName: packageName ?? _packageName, |
||||
); |
||||
String get id => _id; |
||||
String get createTime => _createTime; |
||||
String get createUser => _createUser; |
||||
String get updateTime => _updateTime; |
||||
String get updateUser => _updateUser; |
||||
String get tenantId => _tenantId; |
||||
String get tenantCode => _tenantCode; |
||||
String get packageId => _packageId; |
||||
String get oldPackageId => _oldPackageId; |
||||
String get packagePrice => _packagePrice; |
||||
num get packageNum => _packageNum; |
||||
num get packageDiscount => _packageDiscount; |
||||
String get expirationTime => _expirationTime; |
||||
dynamic get upgradeTime => _upgradeTime; |
||||
num get status => _status; |
||||
num get payChannel => _payChannel; |
||||
num get isDelete => _isDelete; |
||||
String get packageName => _packageName; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['id'] = _id; |
||||
map['createTime'] = _createTime; |
||||
map['createUser'] = _createUser; |
||||
map['updateTime'] = _updateTime; |
||||
map['updateUser'] = _updateUser; |
||||
map['tenantId'] = _tenantId; |
||||
map['tenantCode'] = _tenantCode; |
||||
map['packageId'] = _packageId; |
||||
map['oldPackageId'] = _oldPackageId; |
||||
map['packagePrice'] = _packagePrice; |
||||
map['packageNum'] = _packageNum; |
||||
map['packageDiscount'] = _packageDiscount; |
||||
map['expirationTime'] = _expirationTime; |
||||
map['upgradeTime'] = _upgradeTime; |
||||
map['status'] = _status; |
||||
map['payChannel'] = _payChannel; |
||||
map['isDelete'] = _isDelete; |
||||
map['packageName'] = _packageName; |
||||
return map; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,19 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
|
||||
class SetSpecsList { |
||||
TextEditingController _specsNameController; |
||||
List<String> _specsValues = []; |
||||
|
||||
TextEditingController get specsNameController => _specsNameController; |
||||
|
||||
|
||||
List<String> get specsValues => _specsValues; |
||||
|
||||
set specsValues(List<String> value) { |
||||
_specsValues = value; |
||||
} |
||||
|
||||
SetSpecsList(){ |
||||
_specsNameController = TextEditingController(); |
||||
} |
||||
} |
@ -0,0 +1,34 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
|
||||
class SetSpecsMealList { |
||||
TextEditingController _groupsNameController; |
||||
List<Map<String, String>> _goodsMeal = []; |
||||
num _groupsTotal = 1; |
||||
num _optionalNum = 1; |
||||
|
||||
TextEditingController get groupsNameController => _groupsNameController; |
||||
|
||||
|
||||
List<Map<String, String>> get goodsMeal => _goodsMeal; |
||||
|
||||
set goodsMeal(List<Map<String, String>> value) { |
||||
_goodsMeal = value; |
||||
} |
||||
|
||||
|
||||
num get groupsTotal => _groupsTotal; |
||||
|
||||
set groupsTotal(num value) { |
||||
_groupsTotal = value; |
||||
} |
||||
|
||||
SetSpecsMealList(){ |
||||
_groupsNameController = TextEditingController(); |
||||
} |
||||
|
||||
num get optionalNum => _optionalNum; |
||||
|
||||
set optionalNum(num value) { |
||||
_optionalNum = value; |
||||
} |
||||
} |
@ -0,0 +1,10 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
|
||||
class SetSpecsValueList { |
||||
TextEditingController _specsValueNameController; |
||||
|
||||
TextEditingController get specsValueNameController => _specsValueNameController; |
||||
SetSpecsValueList(){ |
||||
_specsValueNameController = TextEditingController(); |
||||
} |
||||
} |
Loading…
Reference in new issue