feat:副屏

This commit is contained in:
dzc committed 2025-03-12 19:39:18 +08:00
1 parent c02c01b442
commit e19463ede5
51 files changed
+450 -291

No files matched your search

+3
View File
@@ -7,6 +7,9 @@
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
analyzer:
errors:
constant_identifier_names: ignore
include: package:flutter_lints/flutter.yaml
linter:
+6 -7
View File
@@ -8,6 +8,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
@@ -20,17 +21,15 @@
<application
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:label="pj_supermarket_cloud"
android:label="智慧食堂"
android:requestLegacyExternalStorage="true"
android:requestRawExternalStorageAccess="true">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
android:theme="@style/LaunchTheme">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
@@ -45,7 +44,7 @@
android:exported="false"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme" />
android:theme="@style/Theme.AppCompat.NoActionBar" />
<meta-data
android:name="flutterEmbedding"
@@ -1,18 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<style name="LaunchTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<style name="NormalTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
+15 -9
View File
@@ -1,18 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>
<color name="face_lib_main_color">#0B4D46</color>
<color name="white">#FFFFFFFF</color>
<color name="yellow">#C2995C</color>
<color name="red">#E91E63</color>
<color name="green">#58E35E</color>
<color name="green2">#37B13C</color>
<color name="blue">#334141</color>
<color name="blue_sky">#AA0B4D46</color>
<color name="helloColor">#6817023D</color>
</resources>
+11 -10
View File
@@ -36,6 +36,11 @@ class MainApp extends StatelessWidget {
);
return GetMaterialApp(
title: '收银机',
theme: ThemeData(
bottomSheetTheme: const BottomSheetThemeData(
backgroundColor: Colors.transparent,
),
),
defaultTransition: Transition.noTransition,
initialRoute: RouteNames.load,
getPages: RoutePages.list,
@@ -47,7 +52,12 @@ class MainApp extends StatelessWidget {
builder: EasyLoading.init(
builder: (context, child) => FTheme(
data: themeData,
child: child!,
child: MediaQuery(
data: MediaQuery.of(context).copyWith(
viewInsets: MediaQuery.of(context).viewInsets,
),
child: child!,
),
),
),
);
@@ -56,12 +66,3 @@ class MainApp extends StatelessWidget {
);
}
}
class SubApp extends StatelessWidget {
const SubApp({super.key});
@override
Widget build(BuildContext context) {
return const SizedBox.shrink();
}
}
+1 -1
View File
@@ -46,7 +46,7 @@ abstract class HardApi {
}
/// 创建硬件订单
static Future<int?> createHardwareOrder(dynamic formData) async {
static Future<String?> createHardwareOrder(dynamic formData) async {
final res = await HttpManage().dio.post(
"/hard/hard-api/ad/create-order",
data: formData,
@@ -2,8 +2,8 @@ import 'package:pj_supermarket_cloud/common/index.dart';
/// 设备类型
enum SysType implements BaseEnum {
supermarket("1", "超市", "智慧超市", "supermarket"),
canteen("2", "食堂", "智慧食堂", "canteen"),
SUPERMARKET("1", "超市", "智慧超市", "supermarket"),
CANTEEN("2", "食堂", "智慧食堂", "canteen"),
;
@override
@@ -18,10 +18,11 @@ enum SysType implements BaseEnum {
/// 订单类型
enum OrderType implements BaseEnum {
below("1", "线下购买"),
reserve("2", "线上订餐"),
foreignTicket("3", "外来人员"),
strideDept("4", "跨单位"),
BELOW("1", "线下购买"),
RESERVE("2", "线上订餐"),
FOREIGN_TICKET("3", "外来人员"),
STRIDE_DEPT("4", "跨单位"),
ZY("5", "正元公务餐"),
;
@override
@@ -34,13 +35,14 @@ enum OrderType implements BaseEnum {
/// 付款方式
enum OrderPayType implements BaseEnum {
walletDefault("1", "普通钱包支付"),
walletQrCode("2", "钱包二维码支付"),
walletCard("3", "钱包饭卡支付"),
face("4", "人脸识别支付"),
strideDeptQrCode("5", "跨单位二维码支付"),
foreignTicketQrCode("6", "外来人员二维码支付"),
reserveQrCode("7", "线上订餐二维码支付"),
WALLET_DEFAULT("1", "普通钱包支付"),
WALLET_QR_CODE("2", "钱包二维码支付"),
WALLET_CARD("3", "钱包饭卡支付"),
FACE("4", "人脸识别支付"),
STRIDE_DEPT_QR_CODE("5", "跨单位二维码支付"),
FOREIGN_TICKET_QR_CODE("6", "外来人员二维码支付"),
RESERVE_QR_CODE("7", "线上订餐二维码支付"),
CASH("8", "现金支付"),
;
@override
@@ -54,12 +56,14 @@ enum OrderPayType implements BaseEnum {
/// 订单状态
enum OrderStatus implements BaseEnum {
// 查询使用
total("-1", "全部"),
TOTAL("-1", "全部"),
nonePay("1", "未付款"),
pay("5", "已付款"),
offlinePay("6", "本地支付"),
refund("10", "已退订"),
CREATE("1", "未付款"),
OFFLINE_CREATE("2", "离线创建订单(未支付)"),
PAY("5", "已付款"),
OFFLINE_PAY("6", "本地支付"),
REFUND("10", "退款"),
CANCEL("20", "已核销"),
;
@override
@@ -72,10 +76,10 @@ enum OrderStatus implements BaseEnum {
// 打印状态
enum PrintStatus implements BaseEnum {
none("10", "未打印"),
success("20", "打印成功"),
sync("30", "同步成功"),
error("40", "打印失败"),
NONE("10", "未打印"),
SUCCESS("20", "打印成功"),
SYNC("30", "同步成功"),
ERROR("40", "打印失败"),
;
@override
@@ -87,10 +91,11 @@ enum PrintStatus implements BaseEnum {
}
enum ProductHourType implements BaseEnum {
all("-1", "查询全部"),
morning("1", "早餐"),
noon("2", "中餐"),
night("3", "晚餐"),
TOTAL("-1", "查询全部"),
MORNING("1", "早餐"),
NOON("2", "中餐"),
NIGHT("3", "晚餐"),
;
@override
@@ -102,8 +107,8 @@ enum ProductHourType implements BaseEnum {
}
enum WalletType implements BaseEnum {
eat("1", "饭卡钱包"),
pay("2", "虚拟钱包"),
EAT("1", "饭卡钱包"),
PAY("2", "虚拟钱包"),
;
@override
@@ -103,15 +103,15 @@ Map<String, dynamic> _$SysSettingToJson(SysSetting instance) =>
};
const _$SysTypeEnumMap = {
SysType.supermarket: 'supermarket',
SysType.canteen: 'canteen',
SysType.SUPERMARKET: 'SUPERMARKET',
SysType.CANTEEN: 'CANTEEN',
};
const _$ProductHourTypeEnumMap = {
ProductHourType.all: 'all',
ProductHourType.morning: 'morning',
ProductHourType.noon: 'noon',
ProductHourType.night: 'night',
ProductHourType.TOTAL: 'TOTAL',
ProductHourType.MORNING: 'MORNING',
ProductHourType.NOON: 'NOON',
ProductHourType.NIGHT: 'NIGHT',
};
const _$SettingGlobalFontSizeEnumMap = {
+7 -7
View File
@@ -1,13 +1,13 @@
import 'package:pj_supermarket_cloud/common/index.dart';
enum MqtActionEnum implements BaseEnum {
config("10", "设置变化"),
canteenProduct("20", "食堂商品变化"),
canteenClassify("30", "食堂分类变化"),
supermarketProduct("40", "超市商品变化"),
supermarketClassify("50", "超市分类变化"),
print("60", "打印变化"),
face("70", "人脸变化"),
CONFIG("10", "设置变化"),
CANTEEN_PRODUCT("20", "食堂商品变化"),
CANTEEN_CLASSIFY("30", "食堂分类变化"),
SUPERMARKET_PRODUCT("40", "超市商品变化"),
SUPERMARKET_CLASSIFY("50", "超市分类变化"),
PRINT("60", "打印变化"),
FACE("70", "人脸变化"),
;
@override
+7 -7
View File
@@ -15,13 +15,13 @@ Map<String, dynamic> _$MqBaseMsgToJson(MqBaseMsg instance) => <String, dynamic>{
};
const _$MqtActionEnumEnumMap = {
MqtActionEnum.config: 'config',
MqtActionEnum.canteenProduct: 'canteenProduct',
MqtActionEnum.canteenClassify: 'canteenClassify',
MqtActionEnum.supermarketProduct: 'supermarketProduct',
MqtActionEnum.supermarketClassify: 'supermarketClassify',
MqtActionEnum.print: 'print',
MqtActionEnum.face: 'face',
MqtActionEnum.CONFIG: 'CONFIG',
MqtActionEnum.CANTEEN_PRODUCT: 'CANTEEN_PRODUCT',
MqtActionEnum.CANTEEN_CLASSIFY: 'CANTEEN_CLASSIFY',
MqtActionEnum.SUPERMARKET_PRODUCT: 'SUPERMARKET_PRODUCT',
MqtActionEnum.SUPERMARKET_CLASSIFY: 'SUPERMARKET_CLASSIFY',
MqtActionEnum.PRINT: 'PRINT',
MqtActionEnum.FACE: 'FACE',
};
MqttInvoiceMsg _$MqttInvoiceMsgFromJson(Map<String, dynamic> json) =>
@@ -2,10 +2,10 @@
import 'package:pj_supermarket_cloud/common/index.dart';
enum SubScreenAction implements BaseEnum {
updateCard("", "订单更新"),
jumpSubPage("", "跳转到订单选择页面"),
jumpSubBack("", "跳转到上一个页面"),
videoImg("", "视频图片"),
updateCard("updateCard", "订单更新"),
jumpSubPage("jumpSubPage", "跳转到订单选择页面"),
jumpSubBack("jumpSubBack", "跳转到上一个页面"),
videoImg("videoImg", "视频图片"),
;
@override
@@ -19,7 +19,7 @@ abstract class ProductDao {
final placeholders = List.generate(codes.length, (index) => '?').join(', ');
final sql = '''
UPDATE product SET delFlag = 1 WHERE serviceUniqueCode IN ($placeholders)
AND (sysType = 'canteen' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
AND (sysType = 'CANTEEN' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
''';
return await database.rawUpdate(sql, [...codes]);
}
@@ -41,7 +41,7 @@ abstract class ProductDao {
WHERE
delFlag = 0
AND serviceUniqueCode = :uniqueCode AND hourType = :hourType
AND (sysType = 'canteen' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
AND (sysType = 'CANTEEN' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
""")
Future<void> edit(bool isDefault, String uniqueCode, String hourType);
@@ -54,7 +54,7 @@ abstract class ProductDao {
delFlag = 0
AND (:sysType = '-1' OR sysType = :sysType)
AND (:hourType = '-1' OR INSTR(',' || hourType || ',', ',' || :hourType || ',') > 0)
AND (:sysType = 'canteen' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
AND (:sysType = 'CANTEEN' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
""")
Future<int?> getCount(
String sysType,
@@ -93,7 +93,7 @@ abstract class ProductDao {
(:classifyServiceUniqueCode = '-1' OR product.classifyServiceUniqueCode = :classifyServiceUniqueCode) AND
(:hourType = '-1' OR INSTR(',' || product.hourType || ',', ',' || :hourType || ',') > 0) AND
(:sysType = '-1' OR product.sysType = :sysType) AND
(:sysType = 'canteen' OR strftime('%Y-%m-%d', product.saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
(:sysType = 'CANTEEN' OR strftime('%Y-%m-%d', product.saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
ORDER BY classify.sort, classify.id, product.price
LIMIT :pageSize OFFSET :offset
''')
@@ -112,7 +112,7 @@ abstract class ProductDao {
AND isDefault = 1
AND (:sysType = '-1' OR sysType = :sysType)
AND (:hourType = '-1' OR hourType = :hourType)
AND (:sysType = 'canteen' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
AND (:sysType = 'CANTEEN' OR strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime'))
''')
Future<List<ProductEntity>> getDefault(String sysType, String hourType);
}
+4 -4
View File
@@ -532,7 +532,7 @@ class _$ProductDao extends ProductDao {
String hourType,
) async {
await _queryAdapter.queryNoReturn(
'UPDATE product SET isDefault = ?1 WHERE delFlag = 0 AND serviceUniqueCode = ?2 AND hourType = ?3 AND (sysType = \'canteen\' OR strftime(\'%Y-%m-%d\', saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\'))',
'UPDATE product SET isDefault = ?1 WHERE delFlag = 0 AND serviceUniqueCode = ?2 AND hourType = ?3 AND (sysType = \'CANTEEN\' OR strftime(\'%Y-%m-%d\', saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\'))',
arguments: [_boolConverter.encode(isDefault), uniqueCode, hourType]);
}
@@ -542,7 +542,7 @@ class _$ProductDao extends ProductDao {
String hourType,
) async {
return _queryAdapter.query(
'SELECT DISTINCT COUNT(0) FROM product WHERE delFlag = 0 AND (?1 = \'-1\' OR sysType = ?1) AND (?2 = \'-1\' OR INSTR(\',\' || hourType || \',\', \',\' || ?2 || \',\') > 0) AND (?1 = \'canteen\' OR strftime(\'%Y-%m-%d\', saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\'))',
'SELECT DISTINCT COUNT(0) FROM product WHERE delFlag = 0 AND (?1 = \'-1\' OR sysType = ?1) AND (?2 = \'-1\' OR INSTR(\',\' || hourType || \',\', \',\' || ?2 || \',\') > 0) AND (?1 = \'CANTEEN\' OR strftime(\'%Y-%m-%d\', saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\'))',
mapper: (Map<String, Object?> row) => row.values.first as int,
arguments: [sysType, hourType]);
}
@@ -594,7 +594,7 @@ class _$ProductDao extends ProductDao {
int offset,
) async {
return _queryAdapter.queryList(
'SELECT product.* FROM product LEFT JOIN classify ON product.classifyServiceUniqueCode = classify.serviceUniqueCode WHERE product.delFlag = 0 AND (?1 = \'-1\' OR product.classifyServiceUniqueCode = ?1) AND (?2 = \'-1\' OR INSTR(\',\' || product.hourType || \',\', \',\' || ?2 || \',\') > 0) AND (?3 = \'-1\' OR product.sysType = ?3) AND (?3 = \'canteen\' OR strftime(\'%Y-%m-%d\', product.saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\')) ORDER BY classify.sort, classify.id, product.price LIMIT ?4 OFFSET ?5',
'SELECT product.* FROM product LEFT JOIN classify ON product.classifyServiceUniqueCode = classify.serviceUniqueCode WHERE product.delFlag = 0 AND (?1 = \'-1\' OR product.classifyServiceUniqueCode = ?1) AND (?2 = \'-1\' OR INSTR(\',\' || product.hourType || \',\', \',\' || ?2 || \',\') > 0) AND (?3 = \'-1\' OR product.sysType = ?3) AND (?3 = \'CANTEEN\' OR strftime(\'%Y-%m-%d\', product.saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\')) ORDER BY classify.sort, classify.id, product.price LIMIT ?4 OFFSET ?5',
mapper: (Map<String, Object?> row) => ProductEntity(id: row['id'] as int?, serviceUniqueCode: row['serviceUniqueCode'] as String, sysType: _sysTypeConverter.decode(row['sysType'] as String), classifyServiceUniqueCode: row['classifyServiceUniqueCode'] as String, hourType: row['hourType'] == null ? null : ProductHourType.values[row['hourType'] as int], saleDate: _dateTimeEmptyConverter.decode(row['saleDate'] as String), name: row['name'] as String, price: row['price'] as int, image: row['image'] as String?, isDefault: _boolConverter.decode(row['isDefault'] as int), status: row['status'] as int, sort: row['sort'] as int, createTime: _dateTimeConverter.decode(row['createTime'] as String), updateTime: _dateTimeConverter.decode(row['updateTime'] as String), delFlag: _boolConverter.decode(row['delFlag'] as int)),
arguments: [
classifyServiceUniqueCode,
@@ -611,7 +611,7 @@ class _$ProductDao extends ProductDao {
String hourType,
) async {
return _queryAdapter.queryList(
'SELECT * FROM product WHERE delFlag = 0 AND isDefault = 1 AND (?1 = \'-1\' OR sysType = ?1) AND (?2 = \'-1\' OR hourType = ?2) AND (?1 = \'canteen\' OR strftime(\'%Y-%m-%d\', saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\'))',
'SELECT * FROM product WHERE delFlag = 0 AND isDefault = 1 AND (?1 = \'-1\' OR sysType = ?1) AND (?2 = \'-1\' OR hourType = ?2) AND (?1 = \'CANTEEN\' OR strftime(\'%Y-%m-%d\', saleDate) = strftime(\'%Y-%m-%d\', \'now\', \'localtime\'))',
mapper: (Map<String, Object?> row) => ProductEntity(id: row['id'] as int?, serviceUniqueCode: row['serviceUniqueCode'] as String, sysType: _sysTypeConverter.decode(row['sysType'] as String), classifyServiceUniqueCode: row['classifyServiceUniqueCode'] as String, hourType: row['hourType'] == null ? null : ProductHourType.values[row['hourType'] as int], saleDate: _dateTimeEmptyConverter.decode(row['saleDate'] as String), name: row['name'] as String, price: row['price'] as int, image: row['image'] as String?, isDefault: _boolConverter.decode(row['isDefault'] as int), status: row['status'] as int, sort: row['sort'] as int, createTime: _dateTimeConverter.decode(row['createTime'] as String), updateTime: _dateTimeConverter.decode(row['updateTime'] as String), delFlag: _boolConverter.decode(row['delFlag'] as int)),
arguments: [sysType, hourType]);
}
@@ -33,6 +33,6 @@ Map<String, dynamic> _$ClassifyEntityToJson(ClassifyEntity instance) =>
};
const _$SysTypeEnumMap = {
SysType.supermarket: 'supermarket',
SysType.canteen: 'canteen',
SysType.SUPERMARKET: 'SUPERMARKET',
SysType.CANTEEN: 'CANTEEN',
};
@@ -56,31 +56,35 @@ Map<String, dynamic> _$OrderEntityToJson(OrderEntity instance) =>
};
const _$SysTypeEnumMap = {
SysType.supermarket: 'supermarket',
SysType.canteen: 'canteen',
SysType.SUPERMARKET: 'SUPERMARKET',
SysType.CANTEEN: 'CANTEEN',
};
const _$OrderTypeEnumMap = {
OrderType.below: 'below',
OrderType.reserve: 'reserve',
OrderType.foreignTicket: 'foreignTicket',
OrderType.strideDept: 'strideDept',
OrderType.BELOW: 'BELOW',
OrderType.RESERVE: 'RESERVE',
OrderType.FOREIGN_TICKET: 'FOREIGN_TICKET',
OrderType.STRIDE_DEPT: 'STRIDE_DEPT',
OrderType.ZY: 'ZY',
};
const _$OrderStatusEnumMap = {
OrderStatus.total: 'total',
OrderStatus.nonePay: 'nonePay',
OrderStatus.pay: 'pay',
OrderStatus.offlinePay: 'offlinePay',
OrderStatus.refund: 'refund',
OrderStatus.TOTAL: 'TOTAL',
OrderStatus.CREATE: 'CREATE',
OrderStatus.OFFLINE_CREATE: 'OFFLINE_CREATE',
OrderStatus.PAY: 'PAY',
OrderStatus.OFFLINE_PAY: 'OFFLINE_PAY',
OrderStatus.REFUND: 'REFUND',
OrderStatus.CANCEL: 'CANCEL',
};
const _$OrderPayTypeEnumMap = {
OrderPayType.walletDefault: 'walletDefault',
OrderPayType.walletQrCode: 'walletQrCode',
OrderPayType.walletCard: 'walletCard',
OrderPayType.face: 'face',
OrderPayType.strideDeptQrCode: 'strideDeptQrCode',
OrderPayType.foreignTicketQrCode: 'foreignTicketQrCode',
OrderPayType.reserveQrCode: 'reserveQrCode',
OrderPayType.WALLET_DEFAULT: 'WALLET_DEFAULT',
OrderPayType.WALLET_QR_CODE: 'WALLET_QR_CODE',
OrderPayType.WALLET_CARD: 'WALLET_CARD',
OrderPayType.FACE: 'FACE',
OrderPayType.STRIDE_DEPT_QR_CODE: 'STRIDE_DEPT_QR_CODE',
OrderPayType.FOREIGN_TICKET_QR_CODE: 'FOREIGN_TICKET_QR_CODE',
OrderPayType.RESERVE_QR_CODE: 'RESERVE_QR_CODE',
OrderPayType.CASH: 'CASH',
};
@@ -35,8 +35,8 @@ Map<String, dynamic> _$PrintHistoryEntityToJson(PrintHistoryEntity instance) =>
};
const _$PrintStatusEnumMap = {
PrintStatus.none: 'none',
PrintStatus.success: 'success',
PrintStatus.sync: 'sync',
PrintStatus.error: 'error',
PrintStatus.NONE: 'NONE',
PrintStatus.SUCCESS: 'SUCCESS',
PrintStatus.SYNC: 'SYNC',
PrintStatus.ERROR: 'ERROR',
};
@@ -47,13 +47,13 @@ Map<String, dynamic> _$ProductEntityToJson(ProductEntity instance) =>
};
const _$SysTypeEnumMap = {
SysType.supermarket: 'supermarket',
SysType.canteen: 'canteen',
SysType.SUPERMARKET: 'SUPERMARKET',
SysType.CANTEEN: 'CANTEEN',
};
const _$ProductHourTypeEnumMap = {
ProductHourType.all: 'all',
ProductHourType.morning: 'morning',
ProductHourType.noon: 'noon',
ProductHourType.night: 'night',
ProductHourType.TOTAL: 'TOTAL',
ProductHourType.MORNING: 'MORNING',
ProductHourType.NOON: 'NOON',
ProductHourType.NIGHT: 'NIGHT',
};
@@ -1,3 +1,4 @@
import 'package:equatable/equatable.dart';
import 'package:floor/floor.dart';
import 'package:json_annotation/json_annotation.dart';
@@ -5,7 +6,7 @@ part 'user_entity.g.dart';
@JsonSerializable()
@Entity(tableName: "user_record")
class UserEntity {
class UserEntity extends Equatable {
/// 自增ID
@PrimaryKey(autoGenerate: true)
int? id;
@@ -58,4 +59,15 @@ class UserEntity {
_$UserEntityFromJson(json);
Map<String, dynamic> toJson() => _$UserEntityToJson(this);
@override
List<Object?> get props => [
userId,
nickname,
mobile,
walletCardNumber,
walletId,
walletTypeId,
walletBalance,
];
}
+2 -2
View File
@@ -105,7 +105,7 @@ abstract class AppFileTool {
logger.e("|$_tag|备份sql文件失败,无效的sourcePath路径path:|$sourcePath|");
return false;
}
final databaseFilePath = "$sourcePath${Constants.databaseName}";
final databaseFilePath = "$sourcePath/${Constants.databaseName}";
if (await File(databaseFilePath).exists()) {
logger.w("|$_tag|备份sql文件失败,无效的sourcePath路径path|$databaseFilePath|");
return false;
@@ -127,7 +127,7 @@ abstract class AppFileTool {
// 如果没有数据库将最新的数据库移动为使用的数据库
static Future<void> useLastBackDatabase() async {
final databasePath = getDatabasesPath();
final databaseFilePath = "$databasePath${Constants.databaseName}";
final databaseFilePath = "$databasePath/${Constants.databaseName}";
if (await File(databaseFilePath).exists()) {
logger.w("|$_tag|替换数据库错误,数据库文件已存在path|$databaseFilePath|");
return;
+13 -13
View File
@@ -77,27 +77,27 @@ class AppMqTool {
final app = Get.find<AppControl>();
final mqUpdateEventBus = app.mqUpdateEventBus;
switch (msg.action!) {
case MqtActionEnum.config:
case MqtActionEnum.CONFIG:
await SyncConfigTool.autoSyncSysInfo();
break;
case MqtActionEnum.canteenProduct:
case MqtActionEnum.CANTEEN_PRODUCT:
await SyncProductTool.syncProduct();
mqUpdateEventBus.fire(MqtActionEnum.canteenProduct);
mqUpdateEventBus.fire(MqtActionEnum.CANTEEN_PRODUCT);
break;
case MqtActionEnum.supermarketProduct:
case MqtActionEnum.SUPERMARKET_PRODUCT:
await SyncProductTool.syncProduct();
mqUpdateEventBus.fire(MqtActionEnum.supermarketProduct);
mqUpdateEventBus.fire(MqtActionEnum.SUPERMARKET_PRODUCT);
break;
case MqtActionEnum.canteenClassify:
case MqtActionEnum.CANTEEN_CLASSIFY:
await SyncProductTool.syncClassify();
mqUpdateEventBus.fire(MqtActionEnum.canteenClassify);
mqUpdateEventBus.fire(MqtActionEnum.CANTEEN_CLASSIFY);
break;
case MqtActionEnum.supermarketClassify:
case MqtActionEnum.SUPERMARKET_CLASSIFY:
await SyncProductTool.syncClassify();
mqUpdateEventBus.fire(MqtActionEnum.supermarketClassify);
mqUpdateEventBus.fire(MqtActionEnum.SUPERMARKET_CLASSIFY);
break;
case MqtActionEnum.print:
mqUpdateEventBus.fire(MqtActionEnum.print);
case MqtActionEnum.PRINT:
mqUpdateEventBus.fire(MqtActionEnum.PRINT);
final msg = MqttInvoiceMsg.fromJson(json.decode(orgStr));
if (ObjectUtil.isNotEmpty(msg.historyId) &&
ObjectUtil.isNotEmpty(msg.orderId) &&
@@ -111,7 +111,7 @@ class AppMqTool {
);
}
break;
case MqtActionEnum.face:
case MqtActionEnum.FACE:
final msg = MqttInvoiceMsg.fromJson(json.decode(orgStr));
final storagePath = await AppFileTool.getFacePath();
if (ObjectUtil.isEmpty(storagePath)) {
@@ -131,7 +131,7 @@ class AppMqTool {
storagePath: storagePath!,
isGlobalFace: msg.isGlobalFace,
);
mqUpdateEventBus.fire(MqtActionEnum.face);
mqUpdateEventBus.fire(MqtActionEnum.FACE);
break;
default:
break;
+2 -2
View File
@@ -14,7 +14,7 @@ abstract class AppSettingTool {
final setting = await settingDao.get();
if (setting == null) {
final initSysInfo = SysSetting(
sysType: SysType.canteen,
sysType: SysType.CANTEEN,
androidId: await AppSysTool.getAndroidId(),
sqlAddress: "",
);
@@ -114,7 +114,7 @@ abstract class AppSettingTool {
static Future<void> updateSysInfoByService(ServiceHardware data) async {
if (ObjectUtil.isEmpty(data)) {
final setting = SysSetting(
sysType: SysType.canteen,
sysType: SysType.CANTEEN,
androidId: await AppSysTool.getAndroidId(),
sqlAddress: await AppFileTool.getDatabaseBackupPath(),
);
+1
View File
@@ -7,6 +7,7 @@ export './app/app_face_tool.dart';
export './app/app_file_tool.dart';
export './app/app_mq_tool.dart';
export './app/app_network_tool.dart';
export './app/app_price_tool.dart';
export './app/app_setting_tool.dart';
export './app/app_sys_tool.dart';
export './app/app_user_tool.dart';
+1 -1
View File
@@ -20,7 +20,7 @@ class PrintManage extends BaseFacilityManage {
final usbPrinter = await USBPrinterManager.discover();
final sysSetting = await AppSettingTool.getSysSetting();
final sysType = sysSetting.sysType;
final vendorId = sysType == SysType.canteen ? 19267 : 4070;
final vendorId = sysType == SysType.CANTEEN ? 19267 : 4070;
final target = usbPrinter.firstWhereOrNull((v) => v.vendorId == vendorId);
if (ObjectUtil.isEmpty(target)) return false;
profile = await CapabilityProfile.load();
+1 -1
View File
@@ -78,7 +78,7 @@ abstract class SyncOrderTool {
UPDATE order_record SET status = ? WHERE uniqueCode IN ($placeholders)
''';
final database = app.dataBase.database;
return await database.rawUpdate(sql, [OrderStatus.pay.name, ...codes]);
return await database.rawUpdate(sql, [OrderStatus.PAY.name, ...codes]);
}
// 切割数组
+5 -5
View File
@@ -21,7 +21,7 @@ abstract class SyncPrintTool {
serviceOrderId: orderId,
servicePrintId: historyId,
invoiceUrl: pic,
status: PrintStatus.none,
status: PrintStatus.NONE,
createTime: DateTime.now(),
);
await printHistoryDao.save(saveObj);
@@ -40,7 +40,7 @@ abstract class SyncPrintTool {
final printFacility = app.printManage;
try {
// 检查有没有需要打印的
final list = await printHistoryDao.getAll(PrintStatus.none.name);
final list = await printHistoryDao.getAll(PrintStatus.NONE.name);
if (ObjectUtil.isEmptyList(list)) {
_isPrint = false;
logger.i("|$_tag|检查打印,没有需要打印的发票");
@@ -70,12 +70,12 @@ abstract class SyncPrintTool {
try {
final isPrint = await printFacility.printImg(v.invoiceUrl);
if (!isPrint) {
v.status = PrintStatus.error;
v.status = PrintStatus.ERROR;
await printHistoryDao.edit(v);
throw Error();
}
// 更新本地数据库
v.status = PrintStatus.success;
v.status = PrintStatus.SUCCESS;
v.printTime = DateUtil.formatDate(DateTime.now());
await printHistoryDao.edit(v);
// 同步到服务端
@@ -84,7 +84,7 @@ abstract class SyncPrintTool {
"historyId": v.servicePrintId,
};
await HardApi.printInvoice(printPa);
v.status = PrintStatus.sync;
v.status = PrintStatus.SYNC;
v.syncTime = DateTime.now();
await printHistoryDao.edit(v);
} catch (e) {
+9 -9
View File
@@ -25,9 +25,9 @@ abstract class SyncProductTool {
final sysType = sysSetting.sysType;
try {
List<ServiceClassify>? apiList;
if (sysType == SysType.canteen) {
if (sysType == SysType.CANTEEN) {
apiList = await ProductApi.cookbookClassify(null);
} else if (sysType == SysType.supermarket) {
} else if (sysType == SysType.SUPERMARKET) {
apiList = await ProductApi.supermarketClassify(null);
}
if (apiList == null) return;
@@ -36,10 +36,10 @@ abstract class SyncProductTool {
}
await _batchUpdateClassify(list: apiList, sysType: sysSetting.sysType);
// 更新同步时间
if (sysType == SysType.canteen) {
if (sysType == SysType.CANTEEN) {
sysSetting.canteenClassifySyncTime = DateTime.now();
}
if (sysType == SysType.supermarket) {
if (sysType == SysType.SUPERMARKET) {
sysSetting.supermarketClassifySyncTime = DateTime.now();
}
await AppSettingTool.setSysSetting(sysSetting);
@@ -141,7 +141,7 @@ abstract class SyncProductTool {
final sysType = sysSetting.sysType;
try {
List<ServiceProduct>? apiList;
if (sysType == SysType.canteen) {
if (sysType == SysType.CANTEEN) {
final day = DateUtil.formatDate(
DateTime.now(),
format: DateFormats.y_mo_d,
@@ -157,7 +157,7 @@ abstract class SyncProductTool {
if (!ObjectUtil.isEmptyList(apiList)) {
apiList?.forEach((v) => v.saleDate = dayStr);
}
} else if (sysType == SysType.supermarket) {
} else if (sysType == SysType.SUPERMARKET) {
apiList = await ProductApi.supermarketProduct(null);
}
if (apiList == null) return;
@@ -167,10 +167,10 @@ abstract class SyncProductTool {
// 更新数据
await _batchUpdateProduct(list: apiList, sysType: sysSetting.sysType);
// 更新同步时间
if (sysType == SysType.canteen) {
if (sysType == SysType.CANTEEN) {
sysSetting.canteenProductSyncTime = DateTime.now();
}
if (sysType == SysType.supermarket) {
if (sysType == SysType.SUPERMARKET) {
sysSetting.supermarketProductSyncTime = DateTime.now();
}
await AppSettingTool.setSysSetting(sysSetting);
@@ -236,7 +236,7 @@ abstract class SyncProductTool {
List<ProductEntity> changeList = [];
for (final v in list) {
ProductEntity item = ProductEntity(
serviceUniqueCode: sysType == SysType.canteen
serviceUniqueCode: sysType == SysType.CANTEEN
? v.spuId.toString()
: v.spuId.toString(),
sysType: sysType,
@@ -31,6 +31,7 @@ abstract class SyncUserTool {
} else {
final obj = _parseStorageUser(user: user, updateDate: true);
obj.id = detail.id;
if (obj == detail) return;
await userDao.edit(obj);
logger.i("|$_tag|,存储用户,修改成功|${obj.toJson()}|");
}
+21 -17
View File
@@ -20,10 +20,10 @@ mixin OrderMixin {
/// **************** start 需要重制 start ****************
// 时间类型
Rx<ProductHourType> hourType = Rx(ProductHourType.morning);
Rx<ProductHourType> hourType = Rx(ProductHourType.MORNING);
// 设备类型
SysType _sysType = SysType.canteen;
SysType _sysType = SysType.CANTEEN;
/// **************** end 需要重制 end ****************
@@ -46,10 +46,10 @@ mixin OrderMixin {
RxList<ShopCardEntity> shopCardList = RxList([]);
// 订单类型
OrderType orderType = OrderType.below;
OrderType orderType = OrderType.BELOW;
// 订单支付类型
Rxn<OrderPayType> orderPayType = Rxn(OrderPayType.face);
Rxn<OrderPayType> orderPayType = Rxn(OrderPayType.FACE);
// 显示的支付类型
Rxn<OrderPayDisplayType> orderPayDisplayType = Rxn(
@@ -144,7 +144,7 @@ mixin OrderMixin {
walletId: payUser.value?.walletId,
orderSourceTypeId: orderSourceTypeId,
type: orderType,
status: OrderStatus.nonePay,
status: OrderStatus.OFFLINE_CREATE,
price: getTotalPrice(),
extraPrice: amountMealPrice.value,
payPrice: getTotalPrice() + amountMealPrice.value,
@@ -254,7 +254,7 @@ mixin OrderMixin {
}
// 获取下单商品
List<Map<String, dynamic>> shopList = [];
if (_sysType == SysType.canteen) {
if (_sysType == SysType.CANTEEN) {
shopList = shopCardList.where((v) => v.productNumber > 0).map((v) {
return {
"productId": v.productServiceUniqueCode,
@@ -262,7 +262,7 @@ mixin OrderMixin {
"productWeight": 0,
};
}).toList();
} else if (_sysType == SysType.supermarket) {
} else if (_sysType == SysType.SUPERMARKET) {
shopList = shopCardList.where((v) => v.productWidget > 0).map((v) {
return {
"productId": v.productServiceUniqueCode,
@@ -286,7 +286,7 @@ mixin OrderMixin {
"list": shopList,
};
if (orderPayType.value != null &&
orderPayType.value == OrderPayType.walletQrCode) {
orderPayType.value == OrderPayType.WALLET_QR_CODE) {
pa["walletId"] = globalQrCode?.id;
}
logger.i("|$_tag|创建api订单,下单参数:|${json.encode(pa)}|");
@@ -296,14 +296,18 @@ mixin OrderMixin {
if (data == null) throw Error();
if (ObjectUtil.isEmpty(data)) throw Error();
logger.i("|$_tag||有网络|创建api订单,下单成功res:|$data|");
sqlOrderDetail.status = OrderStatus.pay;
sqlOrderDetail.serviceUniqueCode = data.toString();
sqlOrderDetail.status = OrderStatus.PAY;
sqlOrderDetail.serviceUniqueCode = data;
} else {
sqlOrderDetail.status = OrderStatus.offlinePay;
sqlOrderDetail.status = OrderStatus.OFFLINE_CREATE;
}
// 更新本地订单
sqlOrderDetail.payTime = DateTime.now();
await orderDao.edit(sqlOrderDetail);
if (sqlOrderDetail.payPrice != 0) {
final price = AppriceTool.fenToYuan(sqlOrderDetail.payPrice);
await TtsManage.speak("购买成功,总金额$price元");
}
EasyLoading.dismiss();
Toast.success(msg: "购买成功");
} catch (e, stack) {
@@ -318,23 +322,23 @@ mixin OrderMixin {
String orderSourceTypeId = "";
if (globalQrCode == null) return "";
switch (orderType) {
case OrderType.below:
case OrderType.BELOW:
break;
case OrderType.reserve:
case OrderType.RESERVE:
if (ObjectUtil.isEmpty(globalQrCode!.id)) {
Toast.error(msg: "二维码错误");
return "";
}
orderSourceTypeId = globalQrCode!.id.toString();
break;
case OrderType.foreignTicket:
case OrderType.FOREIGN_TICKET:
if (ObjectUtil.isEmpty(globalQrCode!.itemId)) {
Toast.error(msg: "二维码错误");
return "";
}
orderSourceTypeId = globalQrCode!.itemId.toString();
break;
case OrderType.strideDept:
case OrderType.STRIDE_DEPT:
if (ObjectUtil.isEmpty(globalQrCode!.itemId)) {
Toast.error(msg: "二维码错误");
return "";
@@ -359,7 +363,7 @@ mixin OrderMixin {
// 获取商品的总数
int getProductCount() {
int total = 0;
if (_sysType == SysType.supermarket) return shopCardList.length;
if (_sysType == SysType.SUPERMARKET) return shopCardList.length;
for (var e in shopCardList) {
total += e.productNumber;
}
@@ -369,7 +373,7 @@ mixin OrderMixin {
// 获取商品的总重量
double getProductWeight() {
double total = 0;
if (_sysType == SysType.canteen) return total;
if (_sysType == SysType.CANTEEN) return total;
for (var e in shopCardList) {
total += e.productWidget;
}
@@ -42,14 +42,14 @@ class SelectPayTypeDialogController extends GetxController {
Rxn<ServiceUser?> payUser = Rxn(null);
Rxn<OrderPayType> orderPayType = Rxn(OrderPayType.face);
Rxn<OrderPayType> orderPayType = Rxn(OrderPayType.FACE);
Rxn<OrderPayDisplayType> orderPayDisplayType = Rxn(OrderPayDisplayType.face);
RxList<OrderPayDisplayType> usePayDisplayTypeList =
<OrderPayDisplayType>[].obs;
Rxn<OrderType> orderType = Rxn(OrderType.below);
OrderType orderType = OrderType.BELOW;
RxBool isRecognition = RxBool(false);
@@ -64,13 +64,6 @@ class SelectPayTypeDialogController extends GetxController {
@override
void onInit() async {
super.onInit();
final appSetting = await AppSettingTool.getSysSetting();
if (appSetting.defaultPayDisplayType != null) {
payTypeRadioC.value = {appSetting.defaultPayDisplayType!};
}
if (!ObjectUtil.isEmptyList(appSetting.usePayDisplayType)) {
usePayDisplayTypeList.value = appSetting.usePayDisplayType!;
}
// 监听支付方式变化
payTypeRadioC.addValueListener((v) {
final payType = OrderPayDisplayType.values.fromCode(
@@ -80,6 +73,7 @@ class SelectPayTypeDialogController extends GetxController {
return;
}
orderPayDisplayType.value = payType;
orderPayDisplayType.refresh();
});
}
@@ -96,6 +90,16 @@ class SelectPayTypeDialogController extends GetxController {
_faceCallbackLock = false;
}
Future<void> initPayType() async {
final appSetting = await AppSettingTool.getSysSetting();
if (appSetting.defaultPayDisplayType != null) {
payTypeRadioC.value = {appSetting.defaultPayDisplayType!};
}
if (!ObjectUtil.isEmptyList(appSetting.usePayDisplayType)) {
usePayDisplayTypeList.value = appSetting.usePayDisplayType!;
}
}
_closeFacility() {
BarcodeScanManage.instance.dispose();
app.serialCardManage.close();
@@ -129,7 +133,7 @@ class SelectPayTypeDialogController extends GetxController {
}
onSubmit?.call(
payUser.value!,
orderType.value!,
orderType,
orderPayType.value!,
orderPayDisplayType.value!,
globalQrCode,
@@ -158,7 +162,9 @@ class SelectPayTypeDialogController extends GetxController {
Navigator.of(Get.context!).pop();
}
// 二维码识别
// **************************************************************************
// 二维码识别 start
// **************************************************************************
void _dispatchQrCode() async {
try {
if (isRecognition.value) {
@@ -219,8 +225,13 @@ class SelectPayTypeDialogController extends GetxController {
logger.e("|$_tag|二维码识别,失败error:|$e|");
}
}
// **************************************************************************
// 二维码识别 end
// **************************************************************************
// 饭卡识别
// **************************************************************************
// 饭卡识别 start
// **************************************************************************
void _dispatchWalletCard() async {
if (isRecognition.value) {
Toast.error(msg: "正在识别中,请勿重复点击");
@@ -266,8 +277,7 @@ class SelectPayTypeDialogController extends GetxController {
}
app.serialCardManage.close();
isRecognition.value = false;
orderPayType.value = OrderPayType.walletCard;
orderType.value = OrderType.below;
orderPayType.value = OrderPayType.WALLET_CARD;
break;
case SerialCardResStatus.warning:
break;
@@ -288,8 +298,13 @@ class SelectPayTypeDialogController extends GetxController {
logger.e("|$_tag|饭卡识别,失败error:|$e|");
}
}
// **************************************************************************
// 饭卡识别 end
// **************************************************************************
// 人脸支付
// **************************************************************************
// 人脸支付 start
// **************************************************************************
void _dispatchFace() async {
try {
EasyLoading.dismiss();
@@ -327,7 +342,7 @@ class SelectPayTypeDialogController extends GetxController {
Toast.error(msg: "人脸识别失败,请重试");
return;
}
faceDiscernAfter(event);
_faceDiscernAfter(event);
SubScreenPlugin.doubleScreenShow();
});
} catch (e) {
@@ -335,9 +350,10 @@ class SelectPayTypeDialogController extends GetxController {
}
}
/// android人脸识别成功回调
Future<void> faceDiscernAfter(FaceStream event) async {
// android人脸识别成功回调
Future<void> _faceDiscernAfter(FaceStream event) async {
try {
EasyLoading.dismiss();
EasyLoading.show(
status: '获取用户信息中...',
maskType: EasyLoadingMaskType.black,
@@ -353,9 +369,7 @@ class SelectPayTypeDialogController extends GetxController {
if (data == null) throw Error();
payUser.value = data;
logger.i("|_tag|人脸识别|有网络|,用户信息:|${payUser.toJson()}|");
if (payUser.value != null) {
await SyncUserTool.storageUser(user: payUser.value!);
}
await SyncUserTool.storageUser(user: payUser.value!);
} else {
// 没有网络去本地数据库查询
final user = await SyncUserTool.storageUserByUserId(event.userId!);
@@ -368,11 +382,10 @@ class SelectPayTypeDialogController extends GetxController {
payUser.refresh();
logger.i("|_tag|人脸识别|无网络|,用户信息:|${payUser.toJson()}|");
}
orderPayType.value = OrderPayType.face;
orderType.value = OrderType.below;
orderPayType.value = OrderPayType.FACE;
onDiscernUser?.call(payUser.value);
} catch (e, task) {
logger.e("|_tag|人脸识别,意外的错误error:|$e|task:|$task |");
logger.e("|$_tag|人脸识别,意外的错误error:|$e|task:|$task|");
Toast.error(msg: "识别人脸错误,请重试");
} finally {
_faceCallbackLock = false;
@@ -380,7 +393,7 @@ class SelectPayTypeDialogController extends GetxController {
}
}
/// android 点击返回回调
// android 点击返回回调
_listenAndroidFaceBack() {
final getChannel = FaceDiscernPlugs.getChannel;
getChannel.setMethodCallHandler((call) async {
@@ -394,12 +407,16 @@ class SelectPayTypeDialogController extends GetxController {
});
}
// **************************************************************************
// 人脸支付 end
// **************************************************************************
/// 校验二维码类型是否符合
_validateQrCodeType(OrderPayType type) {
const success = [
OrderPayType.walletQrCode,
OrderPayType.strideDeptQrCode,
OrderPayType.foreignTicketQrCode,
OrderPayType.WALLET_QR_CODE,
OrderPayType.STRIDE_DEPT_QR_CODE,
OrderPayType.FOREIGN_TICKET_QR_CODE,
];
return success.contains(type);
}
@@ -407,10 +424,10 @@ class SelectPayTypeDialogController extends GetxController {
Future<void> selectPayTypeDialog(BuildContext context) async {
final payTypeC = Get.find<SelectPayTypeDialogController>();
final payUser = payTypeC.payUser.value;
await payTypeC.initPayType();
final theme = FTheme.of(context);
final screenWidth = context.screenWidth;
final width = context.width;
final height = context.height;
showDialog(
context: context,
barrierDismissible: false,
@@ -420,6 +437,7 @@ Future<void> selectPayTypeDialog(BuildContext context) async {
body: <Widget>[
Obx(
() => FSelectGroup(
enabled: payTypeC.payUser.value == null,
controller: payTypeC.payTypeRadioC,
style: theme.selectGroupStyle.copyWith(
labelLayoutStyle:
@@ -448,59 +466,38 @@ Future<void> selectPayTypeDialog(BuildContext context) async {
),
),
SizedBox(height: 20.h),
Obx(() {
final payType = payTypeC.orderPayDisplayType.value;
if (payType == null) return const SizedBox.shrink();
const baseMsg = "请点击开始识别按钮";
String msg = "";
SvgAsset icon = FAssets.icons.bird;
switch (payType) {
case OrderPayDisplayType.qrCode:
msg = "$baseMsg,并让用户扫描二维码";
icon = FAssets.icons.qrCode;
break;
case OrderPayDisplayType.walletCard:
msg = "$baseMsg,并让用户刷饭卡";
icon = FAssets.icons.idCard;
break;
case OrderPayDisplayType.face:
msg = "$baseMsg,并让用户进行刷脸";
icon = FAssets.icons.scanFace;
break;
case OrderPayDisplayType.cash:
msg = "请打开钱箱,放入现金";
icon = FAssets.icons.circleDollarSign;
break;
}
return <Widget>[
FIcon(
icon,
size: theme.typography.xl4.fontSize,
Obx(
() => Visibility(
visible: payTypeC.payUser.value == null,
replacement: selectPayTypeUser(
context,
payTypeC.payUser.value,
),
SizedBox(height: 10.h),
Text(
msg,
style: theme.typography.lg,
child: selectPayTypeHint(
context,
payTypeC.orderPayDisplayType.value,
),
].toColumn().padding(vertical: 120.h);
}),
].toColumn().width(screenWidth),
),
).center().expanded(),
].toColumn().width(width * 0.5).height(height * 0.6),
actions: [
<Widget>[
FButton(
label: Text(
payUser == null ? "开始识别" : "确定支付",
style: theme.typography.xl.copyWith(
color: theme.colorScheme.secondary,
Obx(
() => FButton(
label: Text(
payTypeC.payUser.value == null ? "开始识别" : "确定支付",
style: theme.typography.xl.copyWith(
color: theme.colorScheme.secondary,
),
),
onPress: () {
if (payTypeC.payUser.value == null) {
payTypeC.doRecognition();
} else {
payTypeC.doSubmit();
}
},
),
onPress: () {
if (payUser == null) {
payTypeC.doRecognition();
} else {
payTypeC.doSubmit();
}
},
).flexible(flex: 1),
SizedBox(width: 20.w),
FButton(
@@ -520,3 +517,88 @@ Future<void> selectPayTypeDialog(BuildContext context) async {
),
);
}
Widget selectPayTypeUser(BuildContext context, ServiceUser? user) {
final theme = FTheme.of(context);
if (user == null) return const SizedBox.shrink();
final isFree = user.walletIsFreeze ?? true;
final textStyle = theme.typography.xl;
final titleTheme = theme.tileGroupStyle.tileStyle.copyWith(
border: Border.all(
color: Colors.transparent,
),
);
return <Widget>[
FTile(
style: titleTheme,
prefixIcon: FIcon(FAssets.icons.user),
title: Text('姓名', style: textStyle),
details: Text("${user.username}", style: textStyle),
),
FTile(
style: titleTheme,
prefixIcon: FIcon(FAssets.icons.smartphone),
title: Text('手机号', style: textStyle),
details: Text("${user.userMobile}", style: textStyle),
),
FTile(
style: titleTheme,
prefixIcon: FIcon(FAssets.icons.badgeDollarSign),
title: Text('余额', style: textStyle),
details: appPrice(context, user.walletBalance),
),
FTile(
style: titleTheme,
prefixIcon: FIcon(FAssets.icons.idCard),
title: Text('卡号', style: textStyle),
details: Text("${user.walletCardNumber}", style: textStyle),
).offstage(offstage: ObjectUtil.isEmpty(user.walletCardNumber)),
FTile(
style: titleTheme,
prefixIcon: FIcon(FAssets.icons.ban),
title: Text('是否冻结', style: textStyle),
details: Text(isFree ? "是" : "否", style: textStyle),
).offstage(offstage: user.walletCardNumber == null),
]
.toColumn(mainAxisAlignment: MainAxisAlignment.center)
.height(double.infinity);
}
Widget selectPayTypeHint(BuildContext context, OrderPayDisplayType? type) {
final theme = FTheme.of(context);
if (type == null) return const SizedBox.shrink();
const baseMsg = "请点击开始识别按钮";
String msg = "";
SvgAsset icon = FAssets.icons.bird;
switch (type) {
case OrderPayDisplayType.qrCode:
msg = "$baseMsg,并让用户扫描二维码";
icon = FAssets.icons.qrCode;
break;
case OrderPayDisplayType.walletCard:
msg = "$baseMsg,并让用户刷饭卡";
icon = FAssets.icons.idCard;
break;
case OrderPayDisplayType.face:
msg = "$baseMsg,并让用户进行刷脸";
icon = FAssets.icons.scanFace;
break;
case OrderPayDisplayType.cash:
msg = "请打开钱箱,放入现金";
icon = FAssets.icons.circleDollarSign;
break;
}
return <Widget>[
FIcon(
icon,
size: theme.typography.xl4.fontSize,
),
SizedBox(height: 10.h),
Text(
msg,
style: theme.typography.lg,
),
]
.toColumn(mainAxisAlignment: MainAxisAlignment.center)
.height(double.infinity);
}
+2 -1
View File
@@ -6,6 +6,7 @@ import 'package:get/get.dart';
import 'package:pj_supermarket_cloud/app.dart';
import 'package:pj_supermarket_cloud/common/index.dart';
import 'package:pj_supermarket_cloud/sub_screen/page/index.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -29,7 +30,7 @@ Future<void> checkSubScreen() async {
if (isMultipleScreen && isOverlay) {
SubScreenPlugin.doubleScreenShow();
}
// runApp(SubApp());
runApp(SubAppPage());
});
break;
}
+3 -3
View File
@@ -18,7 +18,7 @@ class CanteenProductController extends GetxController with OrderMixin {
StreamSubscription? mqUpdateListen;
final hourTypeC = FRadioSelectGroupController<String>(
value: ProductHourType.morning.code,
value: ProductHourType.MORNING.code,
);
late SysSetting appSetting;
@@ -45,9 +45,9 @@ class CanteenProductController extends GetxController with OrderMixin {
SubScreenPlugin.sendMsgToViceScreen(SubScreenAction.jumpSubPage.name);
/// **************** start 组件初始化 start ****************
hourType.value = appSetting.hourType ?? ProductHourType.morning;
hourType.value = appSetting.hourType ?? ProductHourType.MORNING;
hourTypeC.value = {hourType.value.code};
sysType = SysType.canteen;
sysType = SysType.CANTEEN;
_listenPayTypeSelectCallback();
/// **************** end 组件初始化 end ****************
+1
View File
@@ -270,6 +270,7 @@ class CanteenProductPage extends GetView<CanteenProductController> {
.padding(vertical: 30.h, horizontal: 10.w)
.decorated(),
content: _buildView(context),
resizeToAvoidBottomInset: false,
);
},
);
+1
View File
@@ -171,6 +171,7 @@ class CardActivePage extends GetView<CardActiveController> {
),
).height(height * 0.1),
content: _buildView(context),
resizeToAvoidBottomInset: false,
);
},
);
+1 -1
View File
@@ -24,7 +24,7 @@ class LoadPage extends GetView<LoadController> {
header: FHeader(title: SizedBox.shrink()),
content: _buildView(),
contentPad: true,
resizeToAvoidBottomInset: true,
resizeToAvoidBottomInset: false,
);
},
);
+1 -1
View File
@@ -65,7 +65,7 @@ class LoginPage extends GetView<LoginController> {
header: FHeader(title: SizedBox.shrink()),
content: _buildView(),
contentPad: true,
resizeToAvoidBottomInset: true,
resizeToAvoidBottomInset: false,
);
},
);
+5 -5
View File
@@ -12,9 +12,9 @@ class OrderHistoryController extends GetxController {
PrintManage get printManage => appC.printManage;
Rx<ProductHourType> hourType = Rx(ProductHourType.morning);
Rx<ProductHourType> hourType = Rx(ProductHourType.MORNING);
Rx<OrderStatus> currentStatus = OrderStatus.total.obs;
Rx<OrderStatus> currentStatus = OrderStatus.TOTAL.obs;
RxList<OrderHistoryTableItem> tabList = <OrderHistoryTableItem>[].obs;
@@ -34,7 +34,7 @@ class OrderHistoryController extends GetxController {
RxList<OrderEntity> orderList = RxList([]);
var hourTypeC = FRadioSelectGroupController(
value: ProductHourType.morning.code,
value: ProductHourType.MORNING.code,
);
_initData() {
@@ -45,7 +45,7 @@ class OrderHistoryController extends GetxController {
void onInit() async {
super.onInit();
appSetting = await AppSettingTool.getSysSetting();
hourType.value = appSetting.hourType ?? ProductHourType.morning;
hourType.value = appSetting.hourType ?? ProductHourType.MORNING;
hourTypeC.value = {hourType.value.code};
// tabs
await getTotalList();
@@ -94,7 +94,7 @@ class OrderHistoryController extends GetxController {
final orderDao = appC.dataBase.getOrderDao;
String orderStatus = currentStatus.value.name;
if (currentStatus.value == OrderStatus.total) {
if (currentStatus.value == OrderStatus.TOTAL) {
orderStatus = "-1";
}
+1 -1
View File
@@ -236,7 +236,7 @@ class OrderHistoryPage extends GetView<OrderHistoryController> {
header: FHeader(title: SizedBox.shrink()),
content: _buildView(context),
contentPad: true,
resizeToAvoidBottomInset: true,
resizeToAvoidBottomInset: false,
);
},
);
+1
View File
@@ -152,6 +152,7 @@ class OrderHistoryDetailPage extends GetView<OrderHistoryDetailController> {
),
).height(height * 0.1),
content: _buildView(context),
resizeToAvoidBottomInset: false,
);
},
);
+2 -7
View File
@@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:common_utils/common_utils.dart';
import 'package:get/get.dart';
@@ -77,9 +75,6 @@ class PanelController extends GetxController {
Get.offAndToNamed(RouteNames.login);
break;
case PanelType.test:
// tts测试 成功
// await TtsManage.initialize();
// await TtsManage.speak("购买成功1");
break;
default:
break;
@@ -100,11 +95,11 @@ class PanelController extends GetxController {
final sysSetting = await AppSettingTool.getSysSetting();
final sysType = sysSetting.sysType;
for (final v in panelBtnList) {
if (sysType == SysType.canteen) {
if (sysType == SysType.CANTEEN) {
if (canteenMenus.contains(v.type)) {
v.visible = true;
}
} else if (sysType == SysType.supermarket) {
} else if (sysType == SysType.SUPERMARKET) {
if (supermarketMenus.contains(v.type)) {
v.visible = true;
}
+1 -1
View File
@@ -57,7 +57,7 @@ class PanelPage extends GetView<PanelController> {
header: FHeader(title: SizedBox.shrink()),
content: _buildView(),
contentPad: true,
resizeToAvoidBottomInset: true,
resizeToAvoidBottomInset: false,
);
},
);
+1 -1
View File
@@ -148,7 +148,7 @@ class SettingPage extends GetView<SettingController> {
).height(height * 0.1),
content: _buildView(),
contentPad: true,
resizeToAvoidBottomInset: true,
resizeToAvoidBottomInset: false,
);
},
);
@@ -15,7 +15,10 @@ 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 = "1896157295523049473";
}
await showAdaptiveDialog(
context: context,
+1 -1
View File
@@ -135,7 +135,7 @@ class FaceManageController extends GetxController {
mqUpdateListen =
appC.mqUpdateEventBus.on<MqtActionEnum>().listen((event) async {
switch (event) {
case MqtActionEnum.face:
case MqtActionEnum.FACE:
getFaceList(isLoading: true);
break;
default:
@@ -12,7 +12,7 @@ class ProductManageController extends GetxController {
RxList<ProductEntity> productList = <ProductEntity>[].obs;
ProductHourType hourType = ProductHourType.morning;
ProductHourType hourType = ProductHourType.MORNING;
RxInt currentPage = RxInt(1);
@@ -21,7 +21,7 @@ class ProductManageController extends GetxController {
RxInt pageSize = RxInt(24);
final hourTypeC = FRadioSelectGroupController<String>(
value: ProductHourType.morning.code,
value: ProductHourType.MORNING.code,
);
@override
+4 -4
View File
@@ -20,9 +20,9 @@ Widget settingSync(BuildContext context) {
if (sys == null) return const SizedBox.shrink();
String getSyncClassifyTime() {
if (sys.sysType == SysType.canteen) {
if (sys.sysType == SysType.CANTEEN) {
return dateFormat(sys.canteenClassifySyncTime);
} else if (sys.sysType == SysType.supermarket) {
} else if (sys.sysType == SysType.SUPERMARKET) {
return dateFormat(sys.supermarketClassifySyncTime);
} else {
return "未同步";
@@ -30,9 +30,9 @@ Widget settingSync(BuildContext context) {
}
String getSyncProductTime() {
if (sys.sysType == SysType.canteen) {
if (sys.sysType == SysType.CANTEEN) {
return dateFormat(sys.canteenProductSyncTime);
} else if (sys.sysType == SysType.supermarket) {
} else if (sys.sysType == SysType.SUPERMARKET) {
return dateFormat(sys.supermarketProductSyncTime);
} else {
return "未同步";
+1
View File
@@ -37,6 +37,7 @@ class SupermarketOrderPage extends GetView<SupermarketOrderController> {
),
).height(height * 0.1),
content: _buildView(context),
resizeToAvoidBottomInset: false,
);
},
);
+3 -3
View File
@@ -11,9 +11,9 @@ class TakeFoodController extends GetxController {
RxList<ServiceCar> carList = <ServiceCar>[].obs;
OrderPayType orderPayType = OrderPayType.reserveQrCode;
OrderPayType orderPayType = OrderPayType.RESERVE_QR_CODE;
OrderType orderType = OrderType.reserve;
OrderType orderType = OrderType.RESERVE;
int totalPrice = 0;
@@ -99,7 +99,7 @@ class TakeFoodController extends GetxController {
BarcodeScanManage.instance.scanStream.listen((event) async {
final serviceCode = await BarcodeScanManage.instance.getCodeInfo(event);
if (serviceCode == null) return;
if (serviceCode.payType != OrderPayType.reserveQrCode) {
if (serviceCode.payType != OrderPayType.RESERVE_QR_CODE) {
await TtsManage.speak("请出示线上订餐二维码");
return;
}
+1
View File
@@ -159,6 +159,7 @@ class TakeFoodPage extends GetView<TakeFoodController> {
),
).height(height * 0.1),
content: _buildView(context),
resizeToAvoidBottomInset: false,
);
},
);
@@ -4,7 +4,7 @@ import 'package:pj_supermarket_cloud/common/index.dart';
import 'package:pj_supermarket_cloud/sub_screen/common/index.dart';
class SubPageToool {
void switchJump(SubScreenAction type) {
static void switchJump(SubScreenAction type) {
switch (type) {
case SubScreenAction.jumpSubPage:
SubNavigatorKey.navigatorKey.currentState?.pushNamedAndRemoveUntil(
+23 -1
View File
@@ -1,6 +1,10 @@
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:pj_supermarket_cloud/common/index.dart';
import 'package:pj_supermarket_cloud/sub_screen/page/index.dart';
import 'package:pj_supermarket_cloud/sub_screen/common/index.dart';
@@ -13,6 +17,24 @@ class SubAppPage extends StatefulWidget {
}
class _SubAppPageState extends State<SubAppPage> {
late StreamSubscription _streamSubscription;
@override
void initState() {
super.initState();
_streamSubscription = SubScreenPlugin.viceStream.listen((event) {
final action = SubScreenAction.values.fromCode(event.method);
if (action == null) return;
SubPageToool.switchJump(action);
});
}
@override
void dispose() {
super.dispose();
_streamSubscription.cancel();
}
@override
Widget build(BuildContext context) {
final theme = FTheme.of(context);
@@ -25,7 +47,7 @@ class _SubAppPageState extends State<SubAppPage> {
home: Scaffold(
backgroundColor: theme.colorScheme.background,
body: Text(
'SubApp',
'欢迎使用',
style: theme.typography.xl4,
).center(),
),
+24
View File
@@ -1,4 +1,9 @@
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:flutter_subscreen_plugin/flutter_subscreen_plugin.dart';
import 'package:pj_supermarket_cloud/common/index.dart';
class SubProductPage extends StatefulWidget {
const SubProductPage({super.key});
@@ -8,6 +13,25 @@ class SubProductPage extends StatefulWidget {
}
class _SubProductPageState extends State<SubProductPage> {
late StreamSubscription _streamSubscription;
@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) {}
});
}
@override
void dispose() {
super.dispose();
_streamSubscription.cancel();
}
@override
Widget build(BuildContext context) {
return Container();