feat:取餐、订餐、广播
This commit is contained in:
1 parent
d5bfd91bc1
commit
e5100b46b1
10 files changed
+313
-4
No files matched your search
@@ -130,4 +130,15 @@ abstract class HardApi {
|
||||
if (res.data == null) return null;
|
||||
return ServiceChartLatitude.fromJson(res.data);
|
||||
}
|
||||
|
||||
/// android查询今日的广播
|
||||
static Future<ServiceBroadcastTodayPage?> broadcastToday(
|
||||
dynamic formData,
|
||||
) async {
|
||||
final res = await HttpManage()
|
||||
.dio
|
||||
.get("/hard/hard-broadcast/ad/today", queryParameters: formData);
|
||||
if (res.data == null) return null;
|
||||
return ServiceBroadcastTodayPage.fromJson(res.data);
|
||||
}
|
||||
}
|
||||
@@ -378,3 +378,94 @@ class ServiceChartLatitudeItem {
|
||||
|
||||
Map<String, dynamic> toJson() => _$ServiceChartLatitudeItemToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ServiceBroadcastToday {
|
||||
/// 广播id
|
||||
final String id;
|
||||
|
||||
/// 预定用户
|
||||
final String userId;
|
||||
|
||||
/// 用户名
|
||||
final String username;
|
||||
|
||||
/// 用户手机号
|
||||
final String userMobile;
|
||||
|
||||
/// 硬件id
|
||||
final String hardId;
|
||||
|
||||
/// mq主题
|
||||
final String topic;
|
||||
|
||||
/// 业务类型
|
||||
final String? bizType;
|
||||
|
||||
/// 关联业务编号
|
||||
final String? bizId;
|
||||
|
||||
/// 预定标题
|
||||
final String title;
|
||||
|
||||
/// 预定内容
|
||||
final String content;
|
||||
|
||||
/// 当前广播次数
|
||||
final int? broadcastCount;
|
||||
|
||||
/// 最大广播次数
|
||||
final int? broadcastMaxCount;
|
||||
|
||||
/// 是否广播语音
|
||||
@JsonKey(fromJson: JsonTool.stringToBoolean, toJson: JsonTool.booleanToString)
|
||||
final bool isBroadcast;
|
||||
|
||||
/// 用餐时间段
|
||||
final String? hourType;
|
||||
|
||||
/// 商品介绍
|
||||
String productDesc;
|
||||
|
||||
/// 支付价格
|
||||
int payPrice;
|
||||
|
||||
ServiceBroadcastToday({
|
||||
required this.id,
|
||||
required this.userId,
|
||||
required this.username,
|
||||
required this.userMobile,
|
||||
required this.hardId,
|
||||
required this.topic,
|
||||
this.bizType,
|
||||
this.bizId,
|
||||
required this.title,
|
||||
required this.content,
|
||||
this.broadcastCount,
|
||||
this.broadcastMaxCount,
|
||||
required this.isBroadcast,
|
||||
this.hourType,
|
||||
required this.productDesc,
|
||||
required this.payPrice,
|
||||
});
|
||||
|
||||
factory ServiceBroadcastToday.fromJson(Map<String, dynamic> json) =>
|
||||
_$ServiceBroadcastTodayFromJson(
|
||||
json,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ServiceBroadcastTodayToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ServiceBroadcastTodayPage extends ServicePageBase {
|
||||
List<ServiceBroadcastToday>? records;
|
||||
ServiceBroadcastTodayPage({
|
||||
this.records,
|
||||
});
|
||||
factory ServiceBroadcastTodayPage.fromJson(Map<String, dynamic> json) =>
|
||||
_$ServiceBroadcastTodayPageFromJson(
|
||||
json,
|
||||
);
|
||||
Map<String, dynamic> toJson() => _$ServiceBroadcastTodayPageToJson(this);
|
||||
}
|
||||
@@ -243,3 +243,68 @@ Map<String, dynamic> _$ServiceChartLatitudeItemToJson(
|
||||
'sum': instance.sum,
|
||||
'count': instance.count,
|
||||
};
|
||||
|
||||
ServiceBroadcastToday _$ServiceBroadcastTodayFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
ServiceBroadcastToday(
|
||||
id: json['id'] as String,
|
||||
userId: json['userId'] as String,
|
||||
username: json['username'] as String,
|
||||
userMobile: json['userMobile'] as String,
|
||||
hardId: json['hardId'] as String,
|
||||
topic: json['topic'] as String,
|
||||
bizType: json['bizType'] as String?,
|
||||
bizId: json['bizId'] as String?,
|
||||
title: json['title'] as String,
|
||||
content: json['content'] as String,
|
||||
broadcastCount: (json['broadcastCount'] as num?)?.toInt(),
|
||||
broadcastMaxCount: (json['broadcastMaxCount'] as num?)?.toInt(),
|
||||
isBroadcast: JsonTool.stringToBoolean(json['isBroadcast'] as String),
|
||||
hourType: json['hourType'] as String?,
|
||||
productDesc: json['productDesc'] as String,
|
||||
payPrice: (json['payPrice'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ServiceBroadcastTodayToJson(
|
||||
ServiceBroadcastToday instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'userId': instance.userId,
|
||||
'username': instance.username,
|
||||
'userMobile': instance.userMobile,
|
||||
'hardId': instance.hardId,
|
||||
'topic': instance.topic,
|
||||
'bizType': instance.bizType,
|
||||
'bizId': instance.bizId,
|
||||
'title': instance.title,
|
||||
'content': instance.content,
|
||||
'broadcastCount': instance.broadcastCount,
|
||||
'broadcastMaxCount': instance.broadcastMaxCount,
|
||||
'isBroadcast': JsonTool.booleanToString(instance.isBroadcast),
|
||||
'hourType': instance.hourType,
|
||||
'productDesc': instance.productDesc,
|
||||
'payPrice': instance.payPrice,
|
||||
};
|
||||
|
||||
ServiceBroadcastTodayPage _$ServiceBroadcastTodayPageFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
ServiceBroadcastTodayPage(
|
||||
records: (json['records'] as List<dynamic>?)
|
||||
?.map(
|
||||
(e) => ServiceBroadcastToday.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
)
|
||||
..current = (json['current'] as num).toInt()
|
||||
..pages = (json['pages'] as num).toInt()
|
||||
..size = (json['size'] as num).toInt()
|
||||
..total = (json['total'] as num).toInt();
|
||||
|
||||
Map<String, dynamic> _$ServiceBroadcastTodayPageToJson(
|
||||
ServiceBroadcastTodayPage instance) =>
|
||||
<String, dynamic>{
|
||||
'current': instance.current,
|
||||
'pages': instance.pages,
|
||||
'size': instance.size,
|
||||
'total': instance.total,
|
||||
'records': instance.records,
|
||||
};
|
||||
@@ -97,6 +97,10 @@ class MqttTakeFoodBroadcastMsg {
|
||||
/// 时间段类型
|
||||
String hourType;
|
||||
|
||||
/// 是否完成订单
|
||||
@JsonKey(fromJson: JsonTool.stringToBoolean, toJson: JsonTool.booleanToString)
|
||||
bool isDone;
|
||||
|
||||
MqttTakeFoodBroadcastMsg({
|
||||
required this.topic,
|
||||
required this.userId,
|
||||
@@ -109,6 +113,7 @@ class MqttTakeFoodBroadcastMsg {
|
||||
required this.productDesc,
|
||||
required this.payPrice,
|
||||
required this.hourType,
|
||||
required this.isDone,
|
||||
});
|
||||
|
||||
factory MqttTakeFoodBroadcastMsg.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -61,6 +61,7 @@ MqttTakeFoodBroadcastMsg _$MqttTakeFoodBroadcastMsgFromJson(
|
||||
productDesc: json['productDesc'] as String,
|
||||
payPrice: (json['payPrice'] as num).toInt(),
|
||||
hourType: json['hourType'] as String,
|
||||
isDone: JsonTool.stringToBoolean(json['isDone'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$MqttTakeFoodBroadcastMsgToJson(
|
||||
@@ -77,4 +78,5 @@ Map<String, dynamic> _$MqttTakeFoodBroadcastMsgToJson(
|
||||
'productDesc': instance.productDesc,
|
||||
'payPrice': instance.payPrice,
|
||||
'hourType': instance.hourType,
|
||||
'isDone': JsonTool.booleanToString(instance.isDone),
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:common_utils/common_utils.dart';
|
||||
import 'package:floor/floor.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
@@ -18,12 +19,36 @@ abstract class BroadcastDao {
|
||||
return await database.rawUpdate(sql, []);
|
||||
}
|
||||
|
||||
Future<int> delByServiceCodes(
|
||||
List<String> codes,
|
||||
) async {
|
||||
if (ObjectUtil.isEmptyList(codes)) return 0;
|
||||
final appC = Get.find<AppControl>();
|
||||
final database = appC.dataBase.database;
|
||||
final placeholders = List.generate(codes.length, (index) => '?').join(', ');
|
||||
final sql = '''
|
||||
DELETE FROM broadcast
|
||||
WHERE
|
||||
serviceCode IN ($placeholders)
|
||||
AND strftime('%Y-%m-%d', saleDate) = strftime('%Y-%m-%d', 'now', 'localtime')
|
||||
''';
|
||||
return await database.rawDelete(sql, [...codes]);
|
||||
}
|
||||
|
||||
@insert
|
||||
Future<void> save(BroadcastEntity entity);
|
||||
|
||||
@insert
|
||||
Future<void> batchSave(List<BroadcastEntity> entitys);
|
||||
|
||||
@Query("""
|
||||
DELETE FROM broadcast
|
||||
WHERE
|
||||
isDone = 1
|
||||
AND (:serviceCode = '-1' OR serviceCode = :serviceCode)
|
||||
""")
|
||||
Future<void> del(String serviceCode);
|
||||
|
||||
@update
|
||||
Future<void> edit(BroadcastEntity entity);
|
||||
|
||||
|
||||
@@ -274,6 +274,13 @@ class _$BroadcastDao extends BroadcastDao {
|
||||
|
||||
final UpdateAdapter<BroadcastEntity> _broadcastEntityUpdateAdapter;
|
||||
|
||||
@override
|
||||
Future<void> del(String serviceCode) async {
|
||||
await _queryAdapter.queryNoReturn(
|
||||
'DELETE FROM broadcast WHERE isDone = 1 AND (?1 = \'-1\' OR serviceCode = ?1)',
|
||||
arguments: [serviceCode]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BroadcastEntity>> getAll() async {
|
||||
return _queryAdapter.queryList(
|
||||
|
||||
@@ -11,6 +11,11 @@ abstract class SyncTakeFoodBroadcastTool {
|
||||
static Future<void> addTask(MqttTakeFoodBroadcastMsg msg) async {
|
||||
final appC = Get.find<AppControl>();
|
||||
final broadcastDao = appC.dataBase.getBroadcastDao;
|
||||
// 完成就删除掉
|
||||
if (msg.isDone) {
|
||||
await broadcastDao.del(msg.id);
|
||||
return;
|
||||
}
|
||||
final saveObj = BroadcastEntity(
|
||||
content: msg.content,
|
||||
broadcastCount: 0,
|
||||
@@ -72,6 +77,12 @@ abstract class SyncTakeFoodBroadcastTool {
|
||||
if (i < totalGroups - 1) {
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
}
|
||||
// 更新广播次数
|
||||
for (final v in currentGroup) {
|
||||
v.broadcastCount++;
|
||||
await broadcastDao.edit(v);
|
||||
}
|
||||
// 发送mq消息
|
||||
}
|
||||
} catch (e, stack) {
|
||||
logger.e("|$_tag|检查广播,广播错误,error:|$e|stack:|$stack|");
|
||||
@@ -79,4 +90,62 @@ abstract class SyncTakeFoodBroadcastTool {
|
||||
_isBroadcast = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 手动查询今天所有的广播并且更新本地数据库
|
||||
static Future<void> queryTodayBroadcast() async {
|
||||
// 检查有没有网络
|
||||
if (!AppNetworkTool.isAutoNetwork()) return;
|
||||
int currentPage = 1;
|
||||
final pa = {"current": currentPage, "size": 100};
|
||||
while (true) {
|
||||
final isMore = await _queryTodayBroadcastGroup(pa);
|
||||
if (!isMore) break;
|
||||
currentPage++;
|
||||
}
|
||||
}
|
||||
|
||||
/// 手动查询今天所有的广播并且更新本地数据库
|
||||
static Future<bool> _queryTodayBroadcastGroup(dynamic pa) async {
|
||||
final serviceList = await HardApi.broadcastToday(pa);
|
||||
if (serviceList == null) return false;
|
||||
final result = serviceList.size == 100;
|
||||
if (ObjectUtil.isEmptyList(serviceList.records)) return false;
|
||||
final appC = Get.find<AppControl>();
|
||||
final broadcastDao = appC.dataBase.getBroadcastDao;
|
||||
final serviceCodes =
|
||||
serviceList.records?.map((e) => e.id.toString()).toList();
|
||||
if (ObjectUtil.isEmptyList(serviceCodes)) {
|
||||
return result;
|
||||
}
|
||||
// 根据服务码查询本地数据库
|
||||
await broadcastDao.delByServiceCodes(serviceCodes!);
|
||||
final saveList = serviceList.records!
|
||||
.map((e) => _convertServiceBroadcastTodayToBroadcastEntity(e))
|
||||
.toList();
|
||||
await broadcastDao.batchSave(saveList);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 把 ServiceBroadcastToday 转化为 BroadcastEntity
|
||||
static BroadcastEntity _convertServiceBroadcastTodayToBroadcastEntity(
|
||||
ServiceBroadcastToday obj,
|
||||
) {
|
||||
return BroadcastEntity(
|
||||
content: obj.content,
|
||||
broadcastCount: 0,
|
||||
broadcastMaxCount: obj.broadcastMaxCount ?? 20,
|
||||
isBroadcast: true,
|
||||
isDone: false,
|
||||
productDesc: obj.productDesc,
|
||||
serviceCode: obj.id,
|
||||
userId: obj.userId,
|
||||
username: obj.username,
|
||||
userMobile: obj.userMobile,
|
||||
payPrice: obj.payPrice,
|
||||
hourType:
|
||||
ProductHourType.values.fromCode(obj.hourType) ?? ProductHourType.NOON,
|
||||
enable: true,
|
||||
createTime: DateTime.now(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:forui/forui.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -122,7 +121,8 @@ class CanteenReserveController extends GetxController {
|
||||
status: '广播中...',
|
||||
maskType: EasyLoadingMaskType.black,
|
||||
);
|
||||
await _getReservePage();
|
||||
// 立即执行一次广播
|
||||
SyncTakeFoodBroadcastTool.doCheckBroadcast();
|
||||
EasyLoading.dismiss();
|
||||
}
|
||||
|
||||
@@ -149,4 +149,24 @@ class CanteenReserveController extends GetxController {
|
||||
await _getReservePage();
|
||||
EasyLoading.dismiss();
|
||||
}
|
||||
|
||||
/// 同步所有广播
|
||||
Future<void> syncAllBroadcast() async {
|
||||
// 是否同步所有广播
|
||||
final isSure = await appMessageDialog(Get.context!, "是否同步所有广播");
|
||||
if (!isSure) return;
|
||||
EasyLoading.show(
|
||||
status: '同步中...',
|
||||
maskType: EasyLoadingMaskType.black,
|
||||
);
|
||||
try {
|
||||
await SyncTakeFoodBroadcastTool.queryTodayBroadcast();
|
||||
await _getReservePage();
|
||||
EasyLoading.dismiss();
|
||||
} catch (e, stack) {
|
||||
logger.e("同步广播失败error:|$e|stack:|$stack|");
|
||||
Toast.error(msg: "同步失败");
|
||||
EasyLoading.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,22 @@ class CanteenReservePage extends GetView<CanteenReserveController> {
|
||||
Widget _buildCondition(BuildContext context, double headerHeight) {
|
||||
final theme = FTheme.of(context);
|
||||
return <Widget>[
|
||||
const Spacer(),
|
||||
appRadioHourTypeDialog(context, controller.hourTypeC).width(300.w),
|
||||
const Spacer(),
|
||||
FButton(
|
||||
style: FButtonStyle.outline,
|
||||
prefix: FIcon(
|
||||
FAssets.icons.rotateCcw,
|
||||
size: theme.typography.base.fontSize,
|
||||
),
|
||||
label: Text(
|
||||
'同步所有广播',
|
||||
style: theme.typography.base.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
onPress: () => controller.syncAllBroadcast(),
|
||||
),
|
||||
FButton(
|
||||
prefix: FIcon(
|
||||
FAssets.icons.rocket,
|
||||
@@ -53,7 +67,7 @@ class CanteenReservePage extends GetView<CanteenReserveController> {
|
||||
),
|
||||
FButton(
|
||||
prefix: FIcon(
|
||||
FAssets.icons.rocket,
|
||||
FAssets.icons.laptopMinimalCheck,
|
||||
size: theme.typography.base.fontSize,
|
||||
),
|
||||
label: Text(
|
||||
|
||||
Reference in new issue
Block a user