feat:副屏页面

This commit is contained in:
dzc committed 2025-03-18 15:32:30 +08:00
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',
};
+2 -2
View File
@@ -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(),
);
}
+2 -1
View File
@@ -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();
}
+3
View File
@@ -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
+4 -13
View File
@@ -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;
+22 -11
View File
@@ -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('欢迎使用'),
),
);
}
}
+159 -6
View File
@@ -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),
);
}
}