Browse Source

新增添加商品实体类;

新增商家端滑动图片验证文件;
新增编辑规格明细页面,且数据交互已完成;
新增编辑规格明细实体类;
新增服务套餐功能本介绍;(ui设计为仅显示一张图片,接口未新增该字段;待开发,接入数据字段即可;)
新增服务套餐购买记录实体类;
新增服务套餐购买记录页面;(该页面已完成初步ui设计,接口数据已对接,服务内容暂未定义,暂时隐藏)
新增设置商品规格页面;(已完成数据的交互流程)
新增设置商品规格值页面;已完成数据的交互流程)
新增设置套餐选择页面;(已完成新增商品跳转,选择商品数据显示的交互流程)
新增设置规格列表实体类;
新增设置规格套餐列表实体类;
新增设置规格值列表实体类;
wr_2023_new_business
wurong 1 year ago
parent
commit
5b53c10436
  1. BIN
      assets/image/2x/register_account.webp
  2. BIN
      assets/image/2x/retrieve_password.webp
  3. BIN
      assets/image/3x/register_account.webp
  4. BIN
      assets/image/3x/retrieve_password.webp
  5. BIN
      assets/image/register_account.webp
  6. BIN
      assets/image/retrieve_password.webp
  7. 1211
      lib/business_system/goods/add_goods/add_goods_page.dart
  8. 440
      lib/business_system/goods/add_goods/edit_specs_detail.dart
  9. 444
      lib/business_system/goods/add_goods/set_goods_specs.dart
  10. 252
      lib/business_system/goods/add_goods/set_goods_specs_value.dart
  11. 491
      lib/business_system/goods/add_goods/set_meal.dart
  12. 551
      lib/business_system/login/captcha/bus_block_puzzle_captcha.dart
  13. 367
      lib/business_system/login/captcha/bus_click_word_captcha.dart
  14. 760
      lib/business_system/login/register_retrieve_password.dart
  15. 44
      lib/business_system/mine/service_subscription/function_version_detail.dart
  16. 459
      lib/business_system/mine/service_subscription/service_purchase_record.dart
  17. 12
      lib/main.dart
  18. 32
      lib/retrofit/data/edit_specs_detail_list.dart
  19. 313
      lib/retrofit/data/service_bug_list.dart
  20. 19
      lib/retrofit/data/set_specs_list.dart
  21. 34
      lib/retrofit/data/set_specs_meal_list.dart
  22. 10
      lib/retrofit/data/set_specs_value_list.dart

BIN
assets/image/2x/register_account.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/image/2x/retrieve_password.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/image/3x/register_account.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
assets/image/3x/retrieve_password.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
assets/image/register_account.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

BIN
assets/image/retrieve_password.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

1211
lib/business_system/goods/add_goods/add_goods_page.dart

File diff suppressed because it is too large Load Diff

440
lib/business_system/goods/add_goods/edit_specs_detail.dart

@ -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),
),
],
),
);
}
}

444
lib/business_system/goods/add_goods/set_goods_specs.dart

@ -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,
),
),
),
],
)),
)
],
),
);
}
}

252
lib/business_system/goods/add_goods/set_goods_specs_value.dart

@ -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),
),
],
),
);
}
}

491
lib/business_system/goods/add_goods/set_meal.dart

@ -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,
),
),
)
],
),
);
}
}

551
lib/business_system/login/captcha/bus_block_puzzle_captcha.dart

File diff suppressed because one or more lines are too long

367
lib/business_system/login/captcha/bus_click_word_captcha.dart

@ -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());
}
}

760
lib/business_system/login/register_retrieve_password.dart

@ -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");
},
);
},
);
}
}

44
lib/business_system/mine/service_subscription/function_version_detail.dart

@ -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,
),
),
);
}
}

459
lib/business_system/mine/service_subscription/service_purchase_record.dart

@ -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),
)),
)
],
),
);
}
}

12
lib/main.dart

@ -93,6 +93,7 @@ import 'business_system/date_select/week_report_page.dart';
import 'business_system/goods/add_goods/add_goods_page.dart'; import 'business_system/goods/add_goods/add_goods_page.dart';
import 'business_system/goods/add_goods/edit_specs_detail.dart'; import 'business_system/goods/add_goods/edit_specs_detail.dart';
import 'business_system/goods/add_goods/set_goods_specs.dart'; import 'business_system/goods/add_goods/set_goods_specs.dart';
import 'business_system/goods/add_goods/set_goods_specs_value.dart';
import 'business_system/goods/add_goods/set_meal.dart'; import 'business_system/goods/add_goods/set_meal.dart';
import 'business_system/goods/goods_search_page.dart'; import 'business_system/goods/goods_search_page.dart';
import 'business_system/goods/on_sale/add_assort.dart'; import 'business_system/goods/on_sale/add_assort.dart';
@ -113,11 +114,14 @@ import 'business_system/home/vip/member_details_page.dart';
import 'business_system/home/vip/pay_success_page.dart'; import 'business_system/home/vip/pay_success_page.dart';
import 'business_system/home/vip/vip_recharge_page.dart'; import 'business_system/home/vip/vip_recharge_page.dart';
import 'business_system/login/business_login_page.dart'; import 'business_system/login/business_login_page.dart';
import 'business_system/login/register_retrieve_password.dart';
import 'business_system/mine/account_information.dart'; import 'business_system/mine/account_information.dart';
import 'business_system/mine/clerk_manage/add_new_clerk_page.dart'; import 'business_system/mine/clerk_manage/add_new_clerk_page.dart';
import 'business_system/mine/clerk_manage/clerk_manage_page.dart'; import 'business_system/mine/clerk_manage/clerk_manage_page.dart';
import 'business_system/mine/merchant_info.dart'; import 'business_system/mine/merchant_info.dart';
import 'business_system/mine/security_setting.dart'; import 'business_system/mine/security_setting.dart';
import 'business_system/mine/service_subscription/function_version_detail.dart';
import 'business_system/mine/service_subscription/service_purchase_record.dart';
import 'business_system/mine/service_subscription/service_subscription_page.dart'; import 'business_system/mine/service_subscription/service_subscription_page.dart';
import 'business_system/mine/shop_image_info.dart'; import 'business_system/mine/shop_image_info.dart';
import 'business_system/mine/shop_reservation_code.dart'; import 'business_system/mine/shop_reservation_code.dart';
@ -566,4 +570,12 @@ Map<String, WidgetBuilder> routers = <String, WidgetBuilder>{
EditSpecsDetail(arguments:arguments), EditSpecsDetail(arguments:arguments),
'/router/set_meal': (context, {arguments}) => '/router/set_meal': (context, {arguments}) =>
SetMeal(arguments:arguments), SetMeal(arguments:arguments),
'/router/function_version_detail': (context, {arguments}) =>
FunctionVersionDetail(arguments:arguments),
'/router/register_retrieve_password': (context, {arguments}) =>
RegisterRetrievePassword(arguments:arguments),
'/router/service_purchase_record': (context, {arguments}) =>
ServicePurchaseRecord(arguments:arguments),
'/router/set_goods_specs_value': (context, {arguments}) =>
SetGoodsSpecsValue(arguments:arguments),
}; };

32
lib/retrofit/data/edit_specs_detail_list.dart

@ -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();
}
}

313
lib/retrofit/data/service_bug_list.dart

@ -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;
}
}

19
lib/retrofit/data/set_specs_list.dart

@ -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();
}
}

34
lib/retrofit/data/set_specs_meal_list.dart

@ -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;
}
}

10
lib/retrofit/data/set_specs_value_list.dart

@ -0,0 +1,10 @@
import 'package:flutter/cupertino.dart';
class SetSpecsValueList {
TextEditingController _specsValueNameController;
TextEditingController get specsValueNameController => _specsValueNameController;
SetSpecsValueList(){
_specsValueNameController = TextEditingController();
}
}
Loading…
Cancel
Save