feat:本地商品bug
This commit is contained in:
1 parent
32341ef253
commit
1f50f737b1
11 files changed
+152
-92
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:floor/floor.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:pj_supermarket_cloud/common/index.dart';
|
||||
@@ -6,7 +7,7 @@ part 'supermarket_spu_entity.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
@Entity(tableName: "supermarket_spu")
|
||||
class SupermarketSpuEntity {
|
||||
class SupermarketSpuEntity extends Equatable {
|
||||
/// 自增ID
|
||||
@PrimaryKey(autoGenerate: true)
|
||||
int? id;
|
||||
@@ -95,4 +96,22 @@ class SupermarketSpuEntity {
|
||||
_$SupermarketSpuEntityFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$SupermarketSpuEntityToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
serviceUniqueCode,
|
||||
classifyServiceUniqueCode,
|
||||
productCode,
|
||||
productName,
|
||||
productNature,
|
||||
barCode,
|
||||
packageNum,
|
||||
unit,
|
||||
spec,
|
||||
picUrl,
|
||||
stock,
|
||||
purchasePrice,
|
||||
retailPrice,
|
||||
promotionPrice,
|
||||
];
|
||||
}
|
||||
@@ -17,12 +17,16 @@ class BarcodeScanManage {
|
||||
static BarcodeScanManage get instance => _instance;
|
||||
|
||||
bool _isListening = false;
|
||||
String _buffer = '';
|
||||
StringBuffer _buffer = StringBuffer();
|
||||
Timer? _timer;
|
||||
final StreamController<String> _scanController =
|
||||
StreamController<String>.broadcast();
|
||||
|
||||
Stream<String> get scanStream => _scanController.stream;
|
||||
// 二维码扫码结果
|
||||
final _qrcodeScanController = StreamController<String>.broadcast();
|
||||
Stream<String> get qrcodeScanStream => _qrcodeScanController.stream;
|
||||
|
||||
// 扫码枪扫码结果
|
||||
final _gunScanController = StreamController<String>.broadcast();
|
||||
Stream<String> get gunScanStream => _gunScanController.stream;
|
||||
|
||||
// 开始监听USB读头输入
|
||||
void startListening() {
|
||||
@@ -30,44 +34,56 @@ class BarcodeScanManage {
|
||||
_isListening = true;
|
||||
// 确保没有焦点的控件
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
RawKeyboard.instance.addListener(_handleKeyEvent);
|
||||
HardwareKeyboard.instance.addHandler(_handleKeyEvent);
|
||||
logger.i("|$_tag|开始监听USB读头输入");
|
||||
}
|
||||
|
||||
// 停止监听
|
||||
void stopListening() {
|
||||
if (!_isListening) return;
|
||||
RawKeyboard.instance.removeListener(_handleKeyEvent);
|
||||
HardwareKeyboard.instance.removeHandler(_handleKeyEvent);
|
||||
_timer?.cancel();
|
||||
_isListening = false;
|
||||
logger.i("|$_tag|停止监听USB读头输入");
|
||||
}
|
||||
|
||||
// 处理键盘事件
|
||||
void _handleKeyEvent(RawKeyEvent event) {
|
||||
if (event is! RawKeyDownEvent) return;
|
||||
// 阻止键盘弹出
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
// 重置定时器
|
||||
_timer?.cancel();
|
||||
// 处理回车键,表示扫码结束
|
||||
if (event.logicalKey.keyId == 0x10000000d) {
|
||||
if (_buffer.isNotEmpty) {
|
||||
logger.i("|$_tag|扫码结果: $_buffer");
|
||||
_scanController.add(_buffer);
|
||||
_buffer = '';
|
||||
bool _handleKeyEvent(KeyEvent event) {
|
||||
if (event is! KeyDownEvent) return false;
|
||||
try {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
_timer?.cancel();
|
||||
// 处理回车键,表示扫码结束
|
||||
if (event.logicalKey.keyId == 0x10000000d) {
|
||||
if (_buffer.isNotEmpty) {
|
||||
final result = _buffer.toString();
|
||||
logger.i("|$_tag|扫码结果: $result");
|
||||
if (result.length >= 100) {
|
||||
_qrcodeScanController.add(result);
|
||||
} else {
|
||||
_gunScanController.add(result);
|
||||
}
|
||||
_buffer.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取字符
|
||||
final character = _getCharacter(event);
|
||||
if (character != null) {
|
||||
_buffer += character;
|
||||
// 设置超时定时器,如果超过一定时间没有新输入,则清空缓冲区
|
||||
_timer = Timer(Duration(milliseconds: 100), () {
|
||||
_buffer = '';
|
||||
});
|
||||
final character = _getCharacter(event);
|
||||
if (character != null) {
|
||||
_buffer.write(character);
|
||||
// 设置超时定时器,如果超过一定时间没有新输入,则清空缓冲区
|
||||
_timer = Timer(Duration(milliseconds: 100), () {
|
||||
if (_buffer.isNotEmpty) {
|
||||
logger.d("|$_tag|扫码超时,清空缓冲区");
|
||||
_buffer.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
} catch (e, stack) {
|
||||
logger.e("|$_tag|处理键盘事件错误error|$e|stack|$stack|");
|
||||
_buffer.clear();
|
||||
_timer?.cancel();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,31 +98,28 @@ class BarcodeScanManage {
|
||||
}
|
||||
|
||||
// 从键盘事件中获取字符
|
||||
String? _getCharacter(RawKeyEvent event) {
|
||||
String? _getCharacter(KeyEvent event) {
|
||||
// 处理数字键
|
||||
if (event.logicalKey.keyId >= LogicalKeyboardKey.digit0.keyId &&
|
||||
event.logicalKey.keyId <= LogicalKeyboardKey.digit9.keyId) {
|
||||
return String.fromCharCode(
|
||||
event.logicalKey.keyId - LogicalKeyboardKey.digit0.keyId + 48);
|
||||
}
|
||||
|
||||
// 处理小写字母键
|
||||
// 处理小写字母键
|
||||
if (event.logicalKey.keyId >= LogicalKeyboardKey.keyA.keyId &&
|
||||
event.logicalKey.keyId <= LogicalKeyboardKey.keyZ.keyId) {
|
||||
// 检查是否按下了Shift键,决定返回大写还是小写字母
|
||||
final isShiftPressed = event.isShiftPressed;
|
||||
final isShiftPressed = HardwareKeyboard.instance.isShiftPressed;
|
||||
final charCode = event.logicalKey.keyId -
|
||||
LogicalKeyboardKey.keyA.keyId +
|
||||
(isShiftPressed ? 65 : 97);
|
||||
return String.fromCharCode(charCode);
|
||||
}
|
||||
|
||||
// 处理其他常见字符
|
||||
switch (event.logicalKey) {
|
||||
case LogicalKeyboardKey.minus:
|
||||
return event.isShiftPressed ? '_' : '-';
|
||||
return HardwareKeyboard.instance.isShiftPressed ? '_' : '-';
|
||||
case LogicalKeyboardKey.equal:
|
||||
return event.isShiftPressed ? '+' : '=';
|
||||
return HardwareKeyboard.instance.isShiftPressed ? '+' : '=';
|
||||
case LogicalKeyboardKey.bracketLeft:
|
||||
return '[';
|
||||
case LogicalKeyboardKey.bracketRight:
|
||||
@@ -122,7 +135,7 @@ class BarcodeScanManage {
|
||||
case LogicalKeyboardKey.period:
|
||||
return '.';
|
||||
case LogicalKeyboardKey.slash:
|
||||
return event.isShiftPressed ? '?' : '/';
|
||||
return HardwareKeyboard.instance.isShiftPressed ? '?' : '/';
|
||||
case LogicalKeyboardKey.add:
|
||||
return '+';
|
||||
case LogicalKeyboardKey.underscore:
|
||||
@@ -177,6 +190,15 @@ class BarcodeScanManage {
|
||||
// 释放资源
|
||||
void dispose() {
|
||||
stopListening();
|
||||
_scanController.close();
|
||||
_qrcodeScanController.close();
|
||||
_gunScanController.close();
|
||||
}
|
||||
|
||||
void disposeQrCodeScan() {
|
||||
_qrcodeScanController.close();
|
||||
}
|
||||
|
||||
void disposeGunScan() {
|
||||
_gunScanController.close();
|
||||
}
|
||||
}
|
||||
@@ -163,21 +163,34 @@ abstract class SyncProductTool {
|
||||
await _batchUpdateCaneenProduct(list: canteenList);
|
||||
} else if (sysType == SysType.SUPERMARKET) {
|
||||
// 超市
|
||||
final app = Get.find<AppControl>();
|
||||
final dataBase = app.dataBase;
|
||||
final supermarketSpuDao = dataBase.getSupermarketSpuDao;
|
||||
final supermarketSkuDao = dataBase.getSupermarketSkuDao;
|
||||
final supermarketCodeDao = dataBase.getSupermarketCodeDao;
|
||||
int currentPage = 1;
|
||||
Set<String> serviceCodes = {};
|
||||
while (true) {
|
||||
final pa = {
|
||||
"current": currentPage,
|
||||
"size": 50,
|
||||
};
|
||||
final supermarket = await ProductApi.supermarketSpu(
|
||||
pa,
|
||||
final pa = {"current": currentPage, "size": 50};
|
||||
final supermarket = await ProductApi.supermarketSpu(pa);
|
||||
if (supermarket == null) break;
|
||||
if (ObjectUtil.isEmptyList(supermarket.records)) break;
|
||||
final ids = await _batchUpdateSupermarketProduct(
|
||||
list: supermarket.records!,
|
||||
);
|
||||
if (supermarket == null ||
|
||||
ObjectUtil.isEmptyList(supermarket.records)) {
|
||||
break;
|
||||
}
|
||||
currentPage += 1;
|
||||
await _batchUpdateSupermarketProduct(list: supermarket.records!);
|
||||
serviceCodes.addAll(ids);
|
||||
}
|
||||
// 处理删除
|
||||
final productList = await supermarketSpuDao.getAll(
|
||||
"-1",
|
||||
);
|
||||
final dbCodes = productList.map((e) => e.serviceUniqueCode).toSet();
|
||||
final deleteCodes = dbCodes.difference(serviceCodes).toList();
|
||||
if (ObjectUtil.isNotEmpty(deleteCodes)) {
|
||||
await supermarketSpuDao.delByIds(deleteCodes);
|
||||
await supermarketSkuDao.delBySpuIds(deleteCodes);
|
||||
await supermarketCodeDao.delBySpuIds(deleteCodes);
|
||||
}
|
||||
}
|
||||
// 更新同步时间
|
||||
@@ -299,7 +312,7 @@ abstract class SyncProductTool {
|
||||
// 同步食堂商品 spu start
|
||||
// **************************************************************************
|
||||
|
||||
static Future<void> _batchUpdateSupermarketProduct({
|
||||
static Future<List<String>> _batchUpdateSupermarketProduct({
|
||||
required List<ServiceSupermarketSpu> list,
|
||||
}) async {
|
||||
final app = Get.find<AppControl>();
|
||||
@@ -314,13 +327,12 @@ abstract class SyncProductTool {
|
||||
isUpdate: false,
|
||||
);
|
||||
await _batchAddOrUpdateSupermarketSpuAndCode(list);
|
||||
return;
|
||||
return list.map((e) => e.id.toString()).toSet().toList();
|
||||
}
|
||||
final apiServiceCodes = list.map((e) => e.id.toString()).toSet();
|
||||
final dbServiceCodes = productList.map((e) => e.serviceUniqueCode).toSet();
|
||||
|
||||
final addCodes = apiServiceCodes.difference(dbServiceCodes).toList();
|
||||
final deleteCodes = dbServiceCodes.difference(apiServiceCodes).toList();
|
||||
final updateCodes = apiServiceCodes.intersection(dbServiceCodes).toList();
|
||||
if (ObjectUtil.isNotEmpty(addCodes)) {
|
||||
await _batchAddOrUpdateSupermarketProduct(
|
||||
@@ -328,9 +340,6 @@ abstract class SyncProductTool {
|
||||
isUpdate: false,
|
||||
);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(deleteCodes)) {
|
||||
await supermarketSpuDao.delByIds(deleteCodes);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(updateCodes)) {
|
||||
await _batchAddOrUpdateSupermarketProduct(
|
||||
list: _filterCaneenSupermarketByCodes(list, updateCodes),
|
||||
@@ -338,6 +347,7 @@ abstract class SyncProductTool {
|
||||
);
|
||||
}
|
||||
await _batchAddOrUpdateSupermarketSpuAndCode(list);
|
||||
return apiServiceCodes.toList();
|
||||
}
|
||||
|
||||
static Future<void> _batchAddOrUpdateSupermarketProduct({
|
||||
@@ -354,13 +364,13 @@ abstract class SyncProductTool {
|
||||
serviceUniqueCode: v.id ?? "-1",
|
||||
classifyServiceUniqueCode: v.categoryId ?? "-1",
|
||||
productCode: v.productCode ?? "-1",
|
||||
productName: v.productCode ?? "",
|
||||
productName: v.productName ?? "",
|
||||
productNature: ProductNature.values.fromCode(v.productNature) ??
|
||||
ProductNature.DEFAULT,
|
||||
barCode: "",
|
||||
packageNum: 0,
|
||||
unit: v.productCode ?? "",
|
||||
spec: v.productCode ?? "",
|
||||
unit: v.unit ?? "",
|
||||
spec: v.spec ?? "",
|
||||
picUrl: v.picUrl ?? "",
|
||||
stock: v.stock ?? 0,
|
||||
salesCount:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -7,9 +7,10 @@ import 'package:pj_supermarket_cloud/common/index.dart';
|
||||
Widget orderSupermarketSpuCard(
|
||||
BuildContext context, {
|
||||
required SupermarketSpuEntity supermarketSpu,
|
||||
bool visibleProductImg = false,
|
||||
}) {
|
||||
final theme = FTheme.of(context);
|
||||
final textStyle = theme.typography.sm.copyWith(
|
||||
final textStyle = theme.typography.xs.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
);
|
||||
return FCard(
|
||||
@@ -19,17 +20,21 @@ Widget orderSupermarketSpuCard(
|
||||
),
|
||||
),
|
||||
image: appImg(supermarketSpu.picUrl, width: double.infinity, height: 100.h)
|
||||
.center(),
|
||||
.center()
|
||||
.offstage(offstage: !visibleProductImg),
|
||||
subtitle: <Widget>[
|
||||
Text(supermarketSpu.productName, style: theme.typography.xl),
|
||||
Text(
|
||||
supermarketSpu.productName,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.typography.base,
|
||||
),
|
||||
SizedBox(height: 5.h),
|
||||
FBadge(
|
||||
style: FBadgeStyle.secondary,
|
||||
label: Text(
|
||||
supermarketSpu.productNature.title,
|
||||
style: textStyle,
|
||||
),
|
||||
label: Text(supermarketSpu.productNature.title, style: textStyle),
|
||||
),
|
||||
SizedBox(height: 5.h),
|
||||
<Widget>[
|
||||
Text("零售价:", style: textStyle),
|
||||
appPrice(context, supermarketSpu.retailPrice),
|
||||
@@ -42,16 +47,19 @@ Widget orderSupermarketSpuCard(
|
||||
Text("货号:", style: textStyle),
|
||||
Text(supermarketSpu.productCode, style: textStyle),
|
||||
].toRow(mainAxisAlignment: MainAxisAlignment.center),
|
||||
<Widget>[
|
||||
Text("辅助条码:", style: textStyle),
|
||||
Text(supermarketSpu.barCode ?? "", style: textStyle),
|
||||
].toRow(mainAxisAlignment: MainAxisAlignment.center),
|
||||
<Widget>[
|
||||
Text("包装单位:", style: textStyle),
|
||||
Text("${supermarketSpu.packageNum}", style: textStyle),
|
||||
Text("/"),
|
||||
Text(supermarketSpu.unit, style: textStyle),
|
||||
].toRow(mainAxisAlignment: MainAxisAlignment.center),
|
||||
<Widget>[
|
||||
Text("条码:", style: textStyle),
|
||||
Text(
|
||||
supermarketSpu.barCode ?? "",
|
||||
style: textStyle,
|
||||
),
|
||||
].toRow(mainAxisAlignment: MainAxisAlignment.center),
|
||||
]
|
||||
.toColumn(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
|
||||
@@ -105,7 +105,9 @@ class SelectPayTypeDialogController extends GetxController {
|
||||
globalQrCode = null;
|
||||
_faceCallbackLock = false;
|
||||
// 设备
|
||||
BarcodeScanManage.instance.dispose();
|
||||
if (appSetting.sysType == SysType.CANTEEN) {
|
||||
BarcodeScanManage.instance.dispose();
|
||||
}
|
||||
app.serialCardManage.close();
|
||||
|
||||
// 取消人脸监听
|
||||
@@ -171,8 +173,11 @@ class SelectPayTypeDialogController extends GetxController {
|
||||
return;
|
||||
}
|
||||
TtsManage.speak("请出示二维码");
|
||||
isRecognition.value = true;
|
||||
onDiscernUser?.call(payUser.value);
|
||||
// 先关闭,超市有扫码枪
|
||||
BarcodeScanManage.instance.startListening();
|
||||
BarcodeScanManage.instance.scanStream.listen((event) async {
|
||||
BarcodeScanManage.instance.qrcodeScanStream.listen((event) async {
|
||||
final serviceCode = await BarcodeScanManage.instance.getCodeInfo(event);
|
||||
if (serviceCode == null) return;
|
||||
if (serviceCode.exceedTime != -1) {
|
||||
@@ -181,26 +186,26 @@ class SelectPayTypeDialogController extends GetxController {
|
||||
).millisecondsSinceEpoch;
|
||||
int nowTime = DateTime.now().millisecondsSinceEpoch;
|
||||
if (exceedTime <= nowTime) {
|
||||
Toast.error(msg: "识别错误,二维码已过期");
|
||||
TtsManage.speak("二维码已过期");
|
||||
return;
|
||||
}
|
||||
}
|
||||
globalQrCode = serviceCode;
|
||||
if (!_validateQrCodeType(orderPayType.value!)) {
|
||||
if (!_validateQrCodeType(serviceCode.payType!)) {
|
||||
logger.e("|$_tag|二维码识别,无效的二维码json:|${jsonEncode(serviceCode)}|");
|
||||
Toast.error(msg: "识别错误,无效的二维码");
|
||||
TtsManage.speak("无效的二维码");
|
||||
return;
|
||||
}
|
||||
globalQrCode = serviceCode;
|
||||
orderPayType.value = serviceCode.payType;
|
||||
logger.i("|$_tag|二维码识别,识别到的二维码json:|${jsonEncode(serviceCode)}|");
|
||||
final isNetwork = AppNetworkTool.isAutoNetwork();
|
||||
final appSetting = await AppSettingTool.getSysSetting();
|
||||
if (isNetwork) {
|
||||
final pa = {
|
||||
"id": serviceCode.userId,
|
||||
"type": appSetting.sysType.name,
|
||||
};
|
||||
final data = await HardApi.getUserInfoById(pa);
|
||||
if (data != null) throw Error();
|
||||
if (data == null) throw Exception("用户不存在");
|
||||
payUser.value = data;
|
||||
if (payUser.value != null) {
|
||||
await SyncUserTool.storageUser(user: payUser.value!);
|
||||
@@ -215,13 +220,9 @@ class SelectPayTypeDialogController extends GetxController {
|
||||
}
|
||||
}
|
||||
isRecognition.value = false;
|
||||
BarcodeScanManage.instance.dispose();
|
||||
Toast.success(msg: "识别二维码成功");
|
||||
TtsManage.speak("识别二维码成功");
|
||||
});
|
||||
isRecognition.value = true;
|
||||
onDiscernUser?.call(payUser.value);
|
||||
} catch (e) {
|
||||
TtsManage.speak("识别二维码错误");
|
||||
logger.e("|$_tag|二维码识别,失败error:|$e|");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ Future<void> _bindServiceDialog(BuildContext context, SysSetting sys) async {
|
||||
}
|
||||
if (AppSysTool.isDev()) {
|
||||
// 正式环境-超市
|
||||
uniqueCodeC.text = "1894303392833716226";
|
||||
// uniqueCodeC.text = "1894303392833716226";
|
||||
// 正式环境-测试
|
||||
// uniqueCodeC.text = "1896157295523049473";
|
||||
// 测试环境-测试设备
|
||||
// uniqueCodeC.text = "1877592554489143298";
|
||||
uniqueCodeC.text = "1877592554489143298";
|
||||
}
|
||||
await showAdaptiveDialog(
|
||||
context: context,
|
||||
|
||||
@@ -274,7 +274,7 @@ Widget _buildSupermarketList(BuildContext context) {
|
||||
crossAxisCount: 6,
|
||||
mainAxisSpacing: 10.w,
|
||||
crossAxisSpacing: 10.w,
|
||||
childAspectRatio: 0.7,
|
||||
childAspectRatio: 0.9,
|
||||
),
|
||||
itemCount: productC.supermarketSpuList.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
|
||||
@@ -297,7 +297,7 @@ class SupermarketOrderController extends GetxController with OrderMixin {
|
||||
|
||||
Future<void> _listenBarCodeCallback() async {
|
||||
BarcodeScanManage.instance.startListening();
|
||||
BarcodeScanManage.instance.scanStream.listen((event) async {
|
||||
BarcodeScanManage.instance.gunScanStream.listen((event) async {
|
||||
if (ObjectUtil.isEmpty(event)) return;
|
||||
if (event.length >= 30) return;
|
||||
// 根据条码查询商品
|
||||
|
||||
@@ -141,7 +141,7 @@ class SupermarketOrderPage extends GetView<SupermarketOrderController> {
|
||||
double maxHeight = constraints.maxHeight;
|
||||
double maxWidth = constraints.maxWidth;
|
||||
double itemWidth = (maxWidth - spacing * 4) / 5;
|
||||
double itemHeight = (maxHeight - (runSpacing + 30) * 2) / 2;
|
||||
double itemHeight = (maxHeight - (runSpacing + 130) * 2) / 2;
|
||||
return Obx(
|
||||
() => ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
|
||||
@@ -96,7 +96,7 @@ class TakeFoodController extends GetxController {
|
||||
try {
|
||||
// 监听二维码测试
|
||||
BarcodeScanManage.instance.startListening();
|
||||
BarcodeScanManage.instance.scanStream.listen((event) async {
|
||||
BarcodeScanManage.instance.qrcodeScanStream.listen((event) async {
|
||||
final serviceCode = await BarcodeScanManage.instance.getCodeInfo(event);
|
||||
if (serviceCode == null) return;
|
||||
if (serviceCode.payType != OrderPayType.RESERVE_QR_CODE) {
|
||||
|
||||
Reference in new issue
Block a user