feat:副屏页面
This commit is contained in:
1 parent
29db4faa73
commit
6dc478077a
11 files changed
+275
-40
No files matched your search
@@ -1 +1,36 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
import 'package:pj_supermarket_cloud/common/index.dart';
|
||||
|
||||
part 'sub_screen_models.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class SubScreenProductEvent {
|
||||
// 购物车列表
|
||||
List<ShopCardEntity> shopList;
|
||||
|
||||
// 系统类型
|
||||
SysType sysType;
|
||||
|
||||
// 支付用户
|
||||
ServiceUser? payUser;
|
||||
|
||||
// 购物车总价
|
||||
int totalPrice;
|
||||
|
||||
// 额外支付
|
||||
int amountMealPrice;
|
||||
|
||||
SubScreenProductEvent({
|
||||
required this.shopList,
|
||||
required this.sysType,
|
||||
required this.payUser,
|
||||
required this.totalPrice,
|
||||
required this.amountMealPrice,
|
||||
});
|
||||
|
||||
factory SubScreenProductEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$SubScreenProductEventFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$SubScreenProductEventToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'sub_screen_models.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
SubScreenProductEvent _$SubScreenProductEventFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
SubScreenProductEvent(
|
||||
shopList: (json['shopList'] as List<dynamic>)
|
||||
.map((e) => ShopCardEntity.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
sysType: $enumDecode(_$SysTypeEnumMap, json['sysType']),
|
||||
payUser: json['payUser'] == null
|
||||
? null
|
||||
: ServiceUser.fromJson(json['payUser'] as Map<String, dynamic>),
|
||||
totalPrice: (json['totalPrice'] as num).toInt(),
|
||||
amountMealPrice: (json['amountMealPrice'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SubScreenProductEventToJson(
|
||||
SubScreenProductEvent instance) =>
|
||||
<String, dynamic>{
|
||||
'shopList': instance.shopList,
|
||||
'sysType': _$SysTypeEnumMap[instance.sysType]!,
|
||||
'payUser': instance.payUser,
|
||||
'totalPrice': instance.totalPrice,
|
||||
'amountMealPrice': instance.amountMealPrice,
|
||||
};
|
||||
|
||||
const _$SysTypeEnumMap = {
|
||||
SysType.SUPERMARKET: 'SUPERMARKET',
|
||||
SysType.CANTEEN: 'CANTEEN',
|
||||
};
|
||||
@@ -10,9 +10,9 @@ class Constants {
|
||||
static const pwdEncKey = 'pigxpigxpigxpigx';
|
||||
|
||||
/// 服务 url
|
||||
/// static const apiUrl = 'https://stgl.pj.gov.cn/api';
|
||||
static const apiUrl = 'https://stgl.pj.gov.cn/api';
|
||||
|
||||
static const apiUrl = 'http://192.168.101.64:9999';
|
||||
// static const apiUrl = 'http://192.168.101.64:9999';
|
||||
|
||||
/// 静态资源 url
|
||||
static const ossUrl = apiUrl;
|
||||
|
||||
@@ -430,10 +430,15 @@ mixin OrderMixin {
|
||||
}
|
||||
|
||||
void sendSubScreen() {
|
||||
final List<ShopCardEntity> list = shopCardList;
|
||||
SubScreenPlugin.sendMsgToViceScreen(
|
||||
SubScreenAction.updateCard.name,
|
||||
params: {},
|
||||
params: SubScreenProductEvent(
|
||||
shopList: shopCardList,
|
||||
sysType: _sysType,
|
||||
payUser: payUser.value,
|
||||
totalPrice: totalPrice.value,
|
||||
amountMealPrice: amountMealPrice.value,
|
||||
).toJson(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ Widget orderAllPrice(
|
||||
String productPrice = "菜品总价",
|
||||
bool visibleProductPrice = true,
|
||||
bool visibleAmountMealPrice = true,
|
||||
bool visibleDivider = true,
|
||||
}) {
|
||||
final theme = FTheme.of(context);
|
||||
return <Widget>[
|
||||
@@ -52,7 +53,7 @@ Widget orderAllPrice(
|
||||
color: theme.colorScheme.primary,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
).offstage(offstage: !visibleDivider),
|
||||
].toColumn();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ class OrderHistoryController extends GetxController {
|
||||
|
||||
late SysSetting appSetting;
|
||||
|
||||
final sysType = SysType.CANTEEN.obs;
|
||||
|
||||
PrintManage get printManage => appC.printManage;
|
||||
|
||||
Rx<ProductHourType> hourType = Rx(ProductHourType.MORNING);
|
||||
@@ -45,6 +47,7 @@ class OrderHistoryController extends GetxController {
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
appSetting = await AppSettingTool.getSysSetting();
|
||||
sysType.value = appSetting.sysType;
|
||||
hourType.value = appSetting.hourType ?? ProductHourType.MORNING;
|
||||
hourTypeC.value = {hourType.value.code};
|
||||
// tabs
|
||||
|
||||
@@ -64,7 +64,9 @@ class OrderHistoryPage extends GetView<OrderHistoryController> {
|
||||
.toRowSpace(space: 20.w),
|
||||
).scrollable(scrollDirection: Axis.horizontal).expanded(),
|
||||
// 用餐时间段
|
||||
appRadioHourTypeDialog(context, controller.hourTypeC).width(300.w),
|
||||
appRadioHourTypeDialog(context, controller.hourTypeC)
|
||||
.width(300.w)
|
||||
.offstage(offstage: controller.sysType.value != SysType.CANTEEN),
|
||||
SizedBox(width: 30.w),
|
||||
// 用餐时间
|
||||
Obx(() => appDatePicker(
|
||||
@@ -117,12 +119,7 @@ class OrderHistoryPage extends GetView<OrderHistoryController> {
|
||||
fixedWidth: 220.w,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('数量'),
|
||||
headingRowAlignment: MainAxisAlignment.center,
|
||||
fixedWidth: 150.w,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('菜品总价'),
|
||||
label: Text('总价'),
|
||||
headingRowAlignment: MainAxisAlignment.center,
|
||||
fixedWidth: 150.w,
|
||||
),
|
||||
@@ -175,12 +172,6 @@ class OrderHistoryPage extends GetView<OrderHistoryController> {
|
||||
textAlign: TextAlign.center,
|
||||
).center(),
|
||||
),
|
||||
DataCell(
|
||||
Text(
|
||||
"${v.count}",
|
||||
textAlign: TextAlign.center,
|
||||
).center(),
|
||||
),
|
||||
DataCell(
|
||||
appPrice(context, v.price).center(),
|
||||
),
|
||||
|
||||
@@ -15,11 +15,12 @@ Future<void> _bindServiceDialog(BuildContext context, SysSetting sys) async {
|
||||
if (ObjectUtil.isNotEmpty(sys.serviceId)) {
|
||||
uniqueCodeC.text = sys.serviceId ?? "";
|
||||
} else if (AppSysTool.isDev()) {
|
||||
// 超市
|
||||
// uniqueCodeC.text = "1894303392833716226";
|
||||
// 测试
|
||||
// 正式环境-超市
|
||||
uniqueCodeC.text = "1894303392833716226";
|
||||
// 正式环境-测试
|
||||
// uniqueCodeC.text = "1896157295523049473";
|
||||
uniqueCodeC.text = "1877592554489143298";
|
||||
// 测试环境-测试设备
|
||||
// uniqueCodeC.text = "1877592554489143298";
|
||||
}
|
||||
await showAdaptiveDialog(
|
||||
context: context,
|
||||
|
||||
@@ -305,7 +305,6 @@ class SupermarketOrderController extends GetxController with OrderMixin {
|
||||
BarcodeScanManage.instance.startListening();
|
||||
BarcodeScanManage.instance.scanStream.listen((event) async {
|
||||
if (ObjectUtil.isEmpty(event)) return;
|
||||
logger.d("|$_tag|条形码|$event|");
|
||||
if (event.length >= 30) return;
|
||||
// 根据条码查询商品
|
||||
final skuDao = appC.dataBase.getSupermarketSkuDao;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'dart:async';
|
||||
|
||||
// import 'package:ducafe_ui_core/ducafe_ui_core.dart';
|
||||
import 'package:ducafe_ui_core/ducafe_ui_core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_subscreen_plugin/flutter_subscreen_plugin.dart';
|
||||
// import 'package:forui/forui.dart';
|
||||
import 'package:forui/forui.dart';
|
||||
import 'package:pj_supermarket_cloud/common/index.dart';
|
||||
|
||||
import 'package:pj_supermarket_cloud/sub_screen/page/index.dart';
|
||||
@@ -37,16 +37,27 @@ class _SubAppPageState extends State<SubAppPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
navigatorKey: SubNavigatorKey.navigatorKey,
|
||||
debugShowCheckedModeBanner: false,
|
||||
routes: {
|
||||
SubRouteNames.subProduct: (context) => const SubProductPage(),
|
||||
final theme = FTheme.of(context);
|
||||
return ScreenUtilInit(
|
||||
designSize: const Size(1920, 1080),
|
||||
minTextAdapt: true,
|
||||
splitScreenMode: true,
|
||||
builder: (_, child) {
|
||||
return MaterialApp(
|
||||
navigatorKey: SubNavigatorKey.navigatorKey,
|
||||
debugShowCheckedModeBanner: false,
|
||||
routes: {
|
||||
SubRouteNames.subProduct: (context) => const SubProductPage(),
|
||||
},
|
||||
home: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Text(
|
||||
'欢迎使用',
|
||||
style: theme.typography.xl6,
|
||||
).center(),
|
||||
),
|
||||
);
|
||||
},
|
||||
home: Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: Text('欢迎使用'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,12 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:ducafe_ui_core/ducafe_ui_core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_subscreen_plugin/flutter_subscreen_plugin.dart';
|
||||
import 'package:forui/forui.dart';
|
||||
import 'package:data_table_2/data_table_2.dart';
|
||||
|
||||
import 'package:pj_supermarket_cloud/common/index.dart';
|
||||
|
||||
class SubProductPage extends StatefulWidget {
|
||||
const SubProductPage({super.key});
|
||||
@@ -13,14 +18,38 @@ class SubProductPage extends StatefulWidget {
|
||||
class _SubProductPageState extends State<SubProductPage> {
|
||||
late StreamSubscription _streamSubscription;
|
||||
|
||||
// 购物车商品列表
|
||||
List<ShopCardEntity> _shopList = [];
|
||||
|
||||
// 系统类型
|
||||
SysType _sysType = SysType.CANTEEN;
|
||||
|
||||
// 支付用户
|
||||
ServiceUser? _payUser;
|
||||
|
||||
// 购物车总价
|
||||
int _totalPrice = 0;
|
||||
|
||||
// 额外支付
|
||||
int _amountMealPrice = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_streamSubscription = SubScreenPlugin.viceStream.listen((event) {
|
||||
// dynamic params = event.arguments;
|
||||
// final action = SubScreenAction.values.fromCode(event.method);
|
||||
// if (action == null) return;
|
||||
// if (action == SubScreenAction.updateCard) {}
|
||||
dynamic params = event.arguments;
|
||||
final action = SubScreenAction.values.fromCode(event.method);
|
||||
if (action == null) return;
|
||||
if (action == SubScreenAction.updateCard) {
|
||||
final subScreenEvent = SubScreenProductEvent.fromJson(params);
|
||||
setState(() {
|
||||
_shopList = subScreenEvent.shopList;
|
||||
_sysType = subScreenEvent.sysType;
|
||||
_payUser = subScreenEvent.payUser;
|
||||
_totalPrice = subScreenEvent.totalPrice;
|
||||
_amountMealPrice = subScreenEvent.amountMealPrice;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,10 +59,134 @@ class _SubProductPageState extends State<SubProductPage> {
|
||||
_streamSubscription.cancel();
|
||||
}
|
||||
|
||||
// 商品区域
|
||||
Widget _buildProductArea(BuildContext context) {
|
||||
final theme = FTheme.of(context);
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
final width = constraints.maxWidth;
|
||||
final height = constraints.maxHeight;
|
||||
final hdHeight = height / 11;
|
||||
final hdWidth = width / 4.1;
|
||||
return DataTable2(
|
||||
columnSpacing: 12.w,
|
||||
horizontalMargin: 12.w,
|
||||
minWidth: hdWidth,
|
||||
showBottomBorder: true,
|
||||
headingTextStyle: theme.typography.lg,
|
||||
dataTextStyle: theme.typography.base,
|
||||
dataRowHeight: hdHeight,
|
||||
columns: [
|
||||
DataColumn2(
|
||||
label: Text("名称", textAlign: TextAlign.center),
|
||||
headingRowAlignment: MainAxisAlignment.center,
|
||||
fixedWidth: hdWidth,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text("数量", textAlign: TextAlign.center),
|
||||
headingRowAlignment: MainAxisAlignment.center,
|
||||
fixedWidth: hdWidth,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text("单价", textAlign: TextAlign.center),
|
||||
headingRowAlignment: MainAxisAlignment.center,
|
||||
fixedWidth: hdWidth,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text("总价", textAlign: TextAlign.center),
|
||||
headingRowAlignment: MainAxisAlignment.center,
|
||||
fixedWidth: hdWidth,
|
||||
),
|
||||
],
|
||||
rows: _shopList.map((v) {
|
||||
return DataRow(
|
||||
cells: [
|
||||
DataCell(
|
||||
Text(
|
||||
v.productName,
|
||||
textAlign: TextAlign.center,
|
||||
).center(),
|
||||
),
|
||||
DataCell(
|
||||
Text(
|
||||
v.nature == ProductNature.DEFAULT
|
||||
? v.productNumber.toString()
|
||||
: v.productWidget.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
).center(),
|
||||
),
|
||||
DataCell(
|
||||
appPrice(context, v.productPrice).center(),
|
||||
),
|
||||
DataCell(
|
||||
appPrice(context, v.totalPrice).center(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// 用户区域
|
||||
Widget _buildUserArea(BuildContext context) {
|
||||
final theme = FTheme.of(context);
|
||||
return <Widget>[
|
||||
appUserInfo(
|
||||
context,
|
||||
username: _payUser?.username,
|
||||
balance: _payUser?.walletBalance,
|
||||
avatar: _payUser?.userAvatar,
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
FDivider(
|
||||
style: theme.dividerStyles.verticalStyle.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
<Widget>[
|
||||
orderAllPrice(
|
||||
context,
|
||||
totalPrice: _totalPrice,
|
||||
amountMealPrice: _amountMealPrice,
|
||||
productPrice: "商品总价",
|
||||
visibleDivider: false,
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
].toColumn(mainAxisAlignment: MainAxisAlignment.end).expanded(),
|
||||
].toColumn().padding(vertical: 10.h, horizontal: 10.w);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
final width = MediaQuery.of(context).size.width;
|
||||
final theme = FTheme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
_sysType.cnStr,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.typography.lg.copyWith(
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
).center().width(double.infinity).padding(vertical: 1).decorated(
|
||||
color: theme.colorScheme.mutedForeground,
|
||||
borderRadius: theme.style.borderRadius / 2,
|
||||
),
|
||||
),
|
||||
body: <Widget>[
|
||||
_buildProductArea(context).expanded(),
|
||||
SizedBox(width: 20.w),
|
||||
_buildUserArea(context).width(width * 0.25).decorated(
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.primary,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: theme.style.borderRadius,
|
||||
),
|
||||
].toRow().padding(vertical: 20.h, horizontal: 30.w),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user