feat:查询菜谱适配小键盘硬件

This commit is contained in:
dzc committed 2026-09-20 11:43:33 +08:00
1 parent a179729e79
commit 8e9bcba3c3
11 files changed
+861 -7

No files matched your search

@@ -77,6 +77,11 @@ abstract class AppSettingTool {
static const String _reservationQueryVerificationDateScopeKey =
"reservationQueryVerificationDateScope";
/// 查询菜单外接快捷小键盘动作绑定在现有 sysJson 中的稳定存储键;
/// 值为“动作编码 -> 按键绑定对象”,缺失或空对象表示全部未绑定。
static const String _menuQueryShortcutKeyBindingsKey =
"menuQueryShortcutKeyBindings";
/// 早餐、中餐和晚餐的本地时间范围;值使用现有 ProductHourType 后端编码。
static const String _productMealPeriodsKey = "productMealPeriods";
static const String _serialCardConfigKey = "serialCardConfig";
@@ -629,6 +634,9 @@ abstract class AppSettingTool {
)
.firstOrNull ??
ReservationMealSlot.morning;
final shortcutKeyBindings = _parseMenuQueryShortcutKeyBindings(
sysJson[_menuQueryShortcutKeyBindingsKey],
);
return ReservationQueryPagePreferences(
methodOrder: List.unmodifiable(restored),
defaultMethod: defaultMethod,
@@ -649,9 +657,42 @@ abstract class AppSettingTool {
sysJson[_reservationQueryAllowManualMealPeriodChangeKey] != false,
selectedMealSlot: selectedMealSlot,
verificationDateScope: verificationDateScope,
shortcutKeyBindings: shortcutKeyBindings,
);
}
/// 解析快捷小键盘绑定为强类型映射;损坏条目跳过,重复按键只保留首个动作。
///
/// sysJson 属于存储边界,可能被旧版本或人工编辑产生异常结构,
/// 单条解析失败不允许阻断其余查询菜单配置读取。
static Map<MenuQueryShortcutAction, MenuQueryShortcutKeyBinding>
_parseMenuQueryShortcutKeyBindings(Object? source) {
// 始终返回可变 Map:调用方可能直接写入,const 空 Map 会导致写入抛异常。
if (source is! Map) {
return <MenuQueryShortcutAction, MenuQueryShortcutKeyBinding>{};
}
final byCode = {
for (final action in MenuQueryShortcutAction.values) action.code: action,
};
final bindings = <MenuQueryShortcutAction, MenuQueryShortcutKeyBinding>{};
for (final entry in source.entries) {
final action = byCode[entry.key];
if (action == null || entry.value is! Map) continue;
try {
final binding = MenuQueryShortcutKeyBinding.fromJson(
Map<String, dynamic>.from(entry.value as Map),
);
// 空绑定没有运行期匹配价值;与已恢复动作冲突的按键保留先出现的动作。
if (binding.usbHidUsage == 0 && binding.logicalKeyId == 0) continue;
if (bindings.values.any(binding.conflictsWith)) continue;
bindings[action] = binding;
} on Object {
// 忽略无法解析的历史绑定,继续恢复其余动作。
}
}
return bindings;
}
/// 顺序与默认项一起保存,避免连续操作后出现“默认项不在当前列表中”的矛盾状态。
static Future<void> setReservationQueryPagePreferences({
required List<ReservationRecognitionMethod> order,
@@ -663,6 +704,8 @@ abstract class AppSettingTool {
required bool quickVerificationEnabled,
required bool allowManualMealPeriodChange,
required ReservationVerificationDateScope verificationDateScope,
required Map<MenuQueryShortcutAction, MenuQueryShortcutKeyBinding>
shortcutKeyBindings,
}) {
final normalized = <ReservationRecognitionMethod>[];
for (final method in order) {
@@ -689,6 +732,12 @@ abstract class AppSettingTool {
allowManualMealPeriodChange;
sysJson[_reservationQueryVerificationDateScopeKey] =
verificationDateScope.code;
// 持久化边界再次收敛空绑定,保证落盘结构与“未绑定即不写入”的读取约定一致。
sysJson[_menuQueryShortcutKeyBindingsKey] = {
for (final entry in shortcutKeyBindings.entries)
if (entry.value.usbHidUsage != 0 || entry.value.logicalKeyId != 0)
entry.key.code: entry.value.toJson(),
};
});
}