关联文档:
需求说明书.html(需求基线 v1.0,2026-07-26,状态:需求确认中)|酒店模块需求缺口清单.md(需求对照 + P0/P1 缺口台账 + 补齐排期) 本文档职责:代码地图与实现进度,回答「代码里有什么」。需求视角的缺口、验收对照与排期不在本文档维护,避免双份状态互相失真。
forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/
├── controller/
│ ├── HotelQrCodeController.java ✅ 二维码管理 + 在住会话操作(入住/退房/打扫/维护/入住记录)
│ ├── HotelBusinessHoursController.java ✅ 营业时段管理(含 check-current 当前营业状态)
│ ├── HotelDishController.java ✅ 菜品管理(分页/详情/增删改/上下架/售罄/恢复/批量/销量排行)
│ ├── HotelDishCategoryController.java ✅ 菜品分类管理(分页/详情/增删改/启禁用)
│ ├── HotelDishSpecController.java ✅ 菜品规格管理(规格组 + 选项)
│ └── open/ ✅ 免登录开放接口(SaTokenConfig 已排除 /hotel/open/** 的登录与 API 权限校验)
│ ├── HotelOpenController.java ✅ 扫码查询 GET /hotel/open/scan
│ ├── HotelCustomerController.java ✅ 顾客端 9 接口(categoryEnabled/dishPage/dishDetail/orderCreate/orderDetail/orderPage/customerRefund/abandonOrder/businessHours)
│ ├── HotelPayController.java ✅ 支付 5 接口(create/notify/status/alipayQuery/mockSuccess)
│ └── AlipayAuthController.java ✅ 支付宝小程序用户授权 getUserInfo(姓名 + 手机号)
├── domain/
│ ├── HotelQrCode.java ✅ 二维码实体
│ ├── HotelQrBindLog.java ✅ 绑定日志实体
│ ├── HotelRoom.java ✅ 房间实体(⚠️ 无「启停点餐」字段)
│ ├── HotelRoomType.java ✅ 房型实体
│ ├── HotelRoomStay.java ✅ 在住会话实体(@TableLogic(value="0", delval="id"))
│ ├── HotelBusinessHours.java ✅ 营业时段实体
│ ├── HotelDish.java ✅ 菜品实体(image 主图 + images 附加图)
│ ├── HotelDishCategory.java ✅ 菜品分类实体
│ ├── HotelDishSpecGroup.java ✅ 规格组实体(挂 dishId)
│ ├── HotelDishSpecOption.java ✅ 规格选项实体(priceExtra 加价)
│ ├── HotelDishAddition.java ✅ 加料实体(extraPrice 加价)
│ └── HotelDishLog.java ⚠️ 菜品操作日志实体(表已建,**零业务代码**:无写入、无查询)
├── dto/
│ ├── QrCodeBatchGenerateDTO.java ✅
│ ├── QrCodeBindDTO.java ✅
│ ├── QrCodeQueryDTO.java ✅
│ ├── HotelRoomDTO.java ✅
│ ├── HotelRoomTypeDTO.java ✅
│ ├── HotelDishDTO.java ✅ 含 specGroups + additions 嵌套
│ ├── HotelDishCategoryDTO.java ✅
│ └── DishBatchOperationDTO.java ✅ 批量上下架/售罄
├── vo/
│ ├── HotelQrCodeVO.java ✅
│ ├── HotelQrBindLogVO.java ✅
│ ├── QrCodeScanVO.java ✅ RoomInfo 含 roomStatus/stayId/guestName/guestPhone
│ ├── HotelRoomVO.java ✅ 含 stayId/guestName/guestPhone/checkInTime
│ ├── HotelRoomTypeVO.java ✅
│ ├── HotelRoomStayVO.java ✅
│ ├── RoomCheckOutVO.java ✅ needConfirm/message/activeOrders/checkedOut
│ ├── HotelDishVO.java ✅ 含 specGroups + additions
│ ├── HotelDishCategoryVO.java ✅
│ └── BusinessHoursStatusVO.java ✅ 营业状态推导(configured/open/todayPeriods/nextText 等)
├── mapper/
│ ├── HotelQrCodeMapper.java ✅
│ ├── HotelQrBindLogMapper.java ✅
│ ├── HotelRoomMapper.java ✅ XML 含 JoinActiveStay
│ ├── HotelRoomTypeMapper.java ✅
│ ├── HotelRoomStayMapper.java ✅ XML 显式 AND del_flag = 0
│ ├── HotelBusinessHoursMapper.java ✅
│ ├── HotelDishMapper.java ✅ XML 含 selectSalesRanking 销量排行
│ ├── HotelDishCategoryMapper.java ✅
│ ├── HotelDishSpecGroupMapper.java ✅
│ ├── HotelDishSpecOptionMapper.java ✅
│ ├── HotelDishAdditionMapper.java ✅
│ └── HotelDishLogMapper.java ⚠️ 仅接口,无调用方
├── service/
│ ├── HotelQrCodeService.java ✅
│ ├── HotelBusinessHoursService.java ✅ 含 checkCurrentBusinessHours() + currentStatus()
│ ├── HotelRoomStayService.java ✅ 入住/退房/打扫/维护/入住记录/联系人回写
│ ├── HotelDishService.java ✅ 含 dishSalesRanking(limit)
│ ├── HotelDishCategoryService.java ✅
│ ├── HotelDishSpecGroupService.java ✅
│ ├── HotelDishSpecOptionService.java ✅
│ └── impl/ ✅ 7 个实现类与接口一一对应
├── constant/
│ └── HotelQrConstants.java ✅ 含 STAY_ACTIVE / STAY_CHECKED_OUT
├── utils/
│ └── QrCodeUtils.java ✅
└── notification/ ✅ 实时通知子包
├── controller/
│ └── NotificationController.java ✅ SSE 端点(subscribe/unsubscribe/connections/remote/notifyNewOrder)
└── manager/
└── SseEmitterManager.java ✅ 长连接管理 + 广播(仅 NEW_ORDER / REFUND_REQUEST 两类事件)
> ⚠️ 文档修正:原记录的 `OrderNotificationService.java` **不存在**,通知广播能力由 `SseEmitterManager` 直接承担。
order/ ✅ 订单管理子包(独立于已有代码)
├── constant/
│ └── HotelOrderConstants.java ✅ 订单状态常量 0~11 + 支付状态 0~3 + paySource + PAY_TIMEOUT_MINUTES=15 + 退单发起方 + refund_status 0~2
├── domain/
│ ├── HotelOrder.java ✅ 订单实体(含 payStatus/payExpireTime/paySource)
│ └── HotelOrderItem.java ✅ 订单明细实体
├── dto/
│ └── OrderCreateDTO.java ✅ 创建订单请求(roomNo/roomId/contactName/contactPhone/deliveryFee/deliveryTimeType/customDeliveryTime/note/items;已移除 payMethod,**无 paySource 字段**,paySource 在创建支付时传参)
├── vo/
│ ├── HotelOrderVO.java ✅ 订单视图(含内部类 OrderItemVO)
│ └── OrderDashboardVO.java ✅ 看板统计视图
├── mapper/
│ ├── HotelOrderMapper.java ✅
│ └── HotelOrderItemMapper.java ✅
├── service/
│ ├── HotelOrderService.java ✅ 15 个方法接口(查询/看板/创建/5 步流转/拒单/3 类退单/审核/放弃);支付与超时取消在 pay 子包的 `HotelPayService`
│ └── impl/
│ └── HotelOrderServiceImpl.java ✅ 完整状态机 + 退单流程 + 支付超时处理
├── controller/
│ └── HotelOrderController.java ✅ 基路径 `/hotel/order`,15 个 REST 接口(`/page` `/detail` `/dashboard` `POST /` `/accept` `/reject` `/prepare` `/ready` `/deliver` `/complete` `/customerRefund` `/hotelRefund` `/refundApprove` `/refundReject` `/refund`)
pay/ ✅ 支付系统子包(支付宝沙箱 H5 WAP Pay + 安全加固 + 超时取消 + 退款)
├── config/
│ └── AlipayConfig.java ✅ 支付宝配置(appId/密钥/网关/回调地址,@ConfigurationProperties)
├── domain/
│ └── HotelPayLog.java ✅ 支付流水实体(outTradeNo/tradeNo/payAmount/payStatus/payChannel/paySource)
├── dto/
│ └── AlipayAuthDTO.java ✅ 支付宝授权请求(authCode + phoneResponse)
├── vo/
│ ├── PayResultVO.java ✅ 支付结果视图(payStatus/payForm/tradeNo)
│ └── AlipayAuthVO.java ✅ 授权结果(userId/userName/phone)
├── mapper/
│ └── HotelPayLogMapper.java ✅ @InterceptorIgnore + 幂等更新 + 按 orderId 查最新流水
│ (XML:resources/mapper/business/hotel/pay/HotelPayLogMapper.xml,幂等 UPDATE WHERE pay_status != 1)
├── service/
│ ├── HotelPayService.java ✅ createPay/handlePayCallback/queryAlipayTradeStatus/refundOrder/cancelTimeoutOrder
│ ├── AlipayAuthService.java ✅ 支付宝用户信息 + 手机号解密
│ └── impl/
│ ├── HotelPayServiceImpl.java ✅ WAP Pay + 回调 + 退款 + 5 层安全加固
│ └── AlipayAuthServiceImpl.java ✅
└── task/
└── PayTimeoutTask.java ✅ @Scheduled(fixedDelay=120000) 每 2 分钟跨租户扫描超时未支付订单并取消(状态 10)
⚠️ 文档修正(3 处):
- 原记录的
pay/constant/HotelPayConstants.java不存在,payStatus / paySource 常量统一放在order/constant/HotelOrderConstants.java。- 原记录的
pay/dto/PayCreateDTO.java不存在,创建支付为createPay(Long orderId, String paySource)直接传参。HotelPayController与AlipayAuthController实际位于controller/open/包下,非pay/controller/open/。
forge-admin-ui/src/views/hotel/
├── board.vue ✅ 房态看板(房间卡片网格 + 状态 Tab + 入住/退房/打扫/维护/入住记录,V1.0.107 建菜单)
├── qrcode.vue ✅ 二维码管理(AiCrudPage + 批量生成/绑定/解绑/批量下载 ZIP)
├── room.vue ✅ 房间管理(AiCrudPage 纯 CRUD;⚠️ 在住业务操作已拆到 board.vue,编辑表单不含状态字段)
├── roomType.vue ✅ 房型管理(AiCrudPage)
├── dish.vue ✅ 菜品管理(AiCrudPage,图片预览/上下架/售罄;⚠️ 无加料与规格绑定编辑入口)
├── dishCategory.vue ✅ 菜品分类管理(AiCrudPage,含启禁用)
├── dishSpec.vue ✅ 菜品规格管理(AiCrudPage + 选项管理弹窗,规格组按 dishId 挂载)
├── businessHours.vue ✅ 营业时段管理(AiCrudPage,时间段下拉选择)
└── order.vue ✅ 订单管理(AiCrudPage + 看板统计 + 流程操作 + 详情弹窗 + 退单审核 + 退款状态列 + 手动退款 + SSE 通知)
forge-admin-ui/src/api/
└── hotel.js ✅ 酒店模块 API(房间/房型/二维码/菜品/分类/规格/营业时段/订单/退款/在住会话/销量排行)
forge-admin-ui/src/composables/
└── useOrderNotification.js ✅ SSE 订阅 + MP3 提示音 + 桌面通知 + 防抖合并 + 首次交互补播
forge-h5-ui/src/pages/hotel/
├── scan-bind.vue ✅ 扫码绑定页面(管理侧)
├── qr-scanner.vue ✅ 扫码页(html5-qrcode)
└── customer/
├── room-confirm.vue ✅ 房号确认入口页(扫码验证/房间卡片/开始点餐 + 🕐 非营业时段整页拦截)
├── menu.vue ✅ 点餐菜单页 Tab1(配送信息栏/Banner/搜索/分类/菜品列表/购物车浮层 + 🕐 非营业菜品区拦截)
├── dish-detail.vue ✅ 菜品详情页(大图/规格选择/加料/备注/数量/加入购物车)
├── cart.vue ✅ 购物车页 Tab3(商品列表/数量控制/备注/费用汇总/结算)
├── order-confirm.vue ✅ 确认下单页(配送信息/送达时间/明细/提交 + 🕐 提交前营业状态刷新阻断,已移除硬编码支付方式)
├── pay.vue ✅ 支付确认页(支付宝 H5 WAP Pay + 轮询 + 主动查询兜底 + 倒计时)
├── order-status.vue ✅ 订单状态页 Tab2(进度条/状态卡片/10秒轮询/自定义退单弹窗)
└── orders.vue ✅ 订单列表页 Tab2(订单卡片列表/分页加载/状态标签/待支付去支付按钮)
forge-h5-ui/src/components/hotel/
└── HotelTabBar.vue ✅ 酒店顾客端 3-tab TabBar(点餐/订单/购物车)
forge-h5-ui/src/styles/
└── hotel-theme.css ✅ 亚朵深墨绿主题 CSS 变量(--h-pri/--h-bg/--h-txt 等)
forge-h5-ui/src/store/modules/
└── hotel-order.js ✅ Pinia 购物车 Store(roomInfo/cartItems/orderNote/businessHours,持久化不含营业状态)
forge-h5-ui/src/api/
└── index.js ✅ 顾客端 API(扫码/分类/菜品/订单 CRUD/退单/放弃订单/支付/支付宝查询/支付宝授权/营业状态 businessHours)
| # | 模块 | 后端 | 数据库 | 前端 PC | 前端 H5 | 状态 |
|---|---|---|---|---|---|---|
| 1 | room(房间/房型管理) | ✅ | ✅ | ✅ | ✅ | 已完成 |
| 2 | qrcode(二维码管理) | ✅ | ✅ | ✅ | ✅ | 已完成 |
| 3 | open(开放扫码接口) | ✅ | — | — | ✅ | 已完成 |
| 4 | dish-spec(菜品规格管理) | ✅ | ✅ | ✅ | — | 已完成 |
| 5 | business-hours(营业时段) | ✅ | ✅ | ✅ | ✅ | 已完成(后端 currentStatus 推导 + 开放接口 + H5 三页接入 + 下单校验) |
| 6 | hotelconfig(酒店基础配置) | ❌ | ❌ | ❌ | — | 暂缓(暂不需要,配送费 + 预计配送时长待讨论) |
| 7 | dish(菜品管理) | ✅ | ✅ | ⚠️ | — | 核心已完成(加料后端已通但 PC 无编辑入口;操作日志 仅实体+Mapper,零业务代码) |
| 8 | order(订单管理) | ⚠️ | ✅ | ✅ | ✅ | 主链路完成(后端+PC管理端+H5顾客端+支付系统);🔴 金额重算未计入规格/加料加价,见 3.3 注意事项 |
| 8.1 | pay(支付系统) | ⚠️ | ✅ | — | ✅ | 支付宝完成(沙箱 H5 WAP Pay + 5 层安全加固 + 轮询兜底 + 退款 + 超时取消);🔴 微信支付未实现,WECHAT 落到 Mock 分支 |
| 8.2 | customer-open(顾客端开放接口) | ✅ | — | — | ✅ | 已完成(8 个免登录接口);🔴 tenantId 由前端传参、订单不校验会话归属,见缺口清单 3.2 |
| 8.3 | alipay-auth(支付宝授权) | ✅ | — | — | ✅ | 已完成(getUserInfo:姓名 + 手机号,为小程序化预留) |
| 9 | notification(实时通知) | ⚠️ | — | ✅ | — | 已完成(SSE + MP3 声音 + 桌面通知 + 防抖合并 + 跨服务转发);仅 NEW_ORDER / REFUND_REQUEST 两类事件,无接单/出餐通知 |
| 9.1 | stay(在住会话 + 订单退款) | ✅ | ✅ | ✅ | ✅ | 全部完成(入住/退房/打扫/维护 + 退房联动取消 + 自动/手动退款,见 3.10) |
| 9.2 | board(房态看板) | ✅ | ✅ | ✅ | — | 已完成(独立页面承接入住/退房/打扫/维护操作,V1.0.107 建菜单) |
| 10 | kitchen(厨房端) | ❌ | — | ❌ | ❌ | 未开发(无待备餐列表/无小票打印/无菜品语音播报) |
🔴 标记项与全部未完成项的需求依据、证据链、修复方向与补齐排期统一记在
酒店模块需求缺口清单.md,本表只保留实现状态。
状态: 暂缓开发。暂时用不到,其中配送费和预计配送时长功能待后续讨论后再实现。
HotelConfig.java — 酒店基础配置(名称/主题/配送费/预计配送时长)HotelConfigMapper.java + XMLHotelConfigService.java — 获取/保存配置HotelConfigController.java — 配置接口hotel_config(IF NOT EXISTS)forge-admin-ui/src/views/hotel/config.vue — 酒店基础配置表单| 文件 | 说明 |
|---|---|
hotelconfig/domain/HotelConfig.java |
配置实体 |
hotelconfig/domain/HotelBusinessHours.java |
营业时段实体 |
hotelconfig/controller/HotelConfigController.java |
全部接口 |
hotelconfig/service/HotelConfigService.java |
全部业务逻辑 |
hotelconfig/mapper/xml/HotelConfigMapper.xml |
配置查询 SQL |
前端:views/hotel/admin/HotelConfigManagement.vue |
配置管理页面 |
前端:views/hotel/admin/BusinessHoursManagement.vue |
营业时段页面 |
前端:views/hotel/admin/BusinessHoursForm.vue |
营业时段表单 |
前端:api/hotel/HotelConfigService.js |
配置 API |
前端:api/hotel/HotelBusinessHoursService.js |
营业时段 API |
HotelDish.java — 菜品主表HotelDishCategory.java — 菜品分类HotelDishSpecGroup.java — 规格组(源框架同时存在 spec 和 spec_group,Forge 统一用 spec_group)HotelDishSpecOption.java — 规格选项HotelDishAddition.java — 加料HotelDishLog.java — 操作日志HotelDishDTO.java — 菜品传输对象HotelDishCategoryDTO.java — 分类传输对象DishBatchOperationDTO.java — 批量操作传输对象HotelDishVO.java / HotelDishCategoryVO.java — 视图对象HotelDishMapper.java + XML(含管理后台分页查询)HotelDishCategoryMapper.java + XML(含分页查询)HotelDishSpecGroupMapper.javaHotelDishSpecOptionMapper.javaHotelDishAdditionMapper.java + XMLHotelDishLogMapper.javaHotelDishService.java — 菜品 CRUD + 上下架 + 售罄/恢复 + 删除HotelDishCategoryService.java — 分类 CRUD + 启用/禁用HotelDishSpecGroupService.java — 规格组 CRUD + 级联删除选项HotelDishSpecOptionService.java — 规格选项 CRUDHotelDishController.java — 菜品接口(分页/详情/新增/修改/删除/上下架/售罄/恢复)HotelDishCategoryController.java — 分类接口(分页/新增/修改/删除/启禁用)HotelDishSpecController.java — 规格组 + 规格选项统一接口HotelDishDTO.additions → saveAdditions()),菜品详情回传 additions,H5 详情页可选加料并计算加价dish.vue 表单不含加料与规格绑定项,等于加料数据无维护入口hotel_dish_log 表 + HotelDishLog 实体 + HotelDishLogMapper 已备,但无任何写入与查询代码(无需独立 Controller,应在 HotelDishServiceImpl 各操作埋点)hotel_dish(IF NOT EXISTS)— 含 image(主图)+ images(附加图片)字段hotel_dish_category(IF NOT EXISTS)hotel_dish_spec_group(IF NOT EXISTS)hotel_dish_spec_option(IF NOT EXISTS)hotel_dish_addition(IF NOT EXISTS)hotel_dish_log(IF NOT EXISTS)hotel_dish_status(ON_SALE/OFF_SHELF)hotel_dish_sold_out(0=正常/1=售罄)V1.0.101__add_hotel_dish_module_tables.sqlforge-admin-ui/src/views/hotel/dish.vue — 菜品管理(AiCrudPage)
forge-admin-ui/src/views/hotel/dishCategory.vue — 菜品分类管理(AiCrudPage)
forge-admin-ui/src/api/hotel.js 中追加菜品/分类相关接口| 文件 | 说明 |
|---|---|
dish/domain/HotelDish.java |
菜品实体 |
dish/domain/HotelDishCategory.java |
分类实体 |
dish/domain/HotelDishSpecGroup.java |
规格组实体 |
dish/domain/HotelDishSpecOption.java |
规格选项实体 |
dish/domain/HotelDishAddition.java |
加料实体 |
dish/domain/HotelDishLog.java |
日志实体 |
dish/controller/HotelDishController.java |
菜品全部接口 |
dish/controller/HotelDishCategoryController.java |
分类接口 |
dish/controller/HotelDishSpecGroupController.java |
规格组接口 |
dish/controller/HotelDishSpecOptionController.java |
规格选项接口 |
dish/service/HotelDishService.java |
菜品业务逻辑(417 行) |
dish/service/HotelDishCategoryService.java |
分类业务逻辑 |
dish/mapper/xml/HotelDishMapper.xml |
菜品 SQL |
dto/DishBatchOperationDTO.java |
批量操作 DTO |
前端:views/hotel/dish/DishManagement.vue |
菜品管理页面 |
前端:views/hotel/dish/DishForm.vue |
菜品表单 |
前端:views/hotel/dish/CategoryManagement.vue |
分类管理 |
前端:views/hotel/dish/CategoryForm.vue |
分类表单 |
前端:api/hotel/HotelDishService.js |
菜品 API |
前端:api/hotel/HotelDishSpecService.js |
规格 API |
hotel_dish_spec 和 hotel_dish_spec_group 两张表,Forge 统一使用 hotel_dish_spec_groupBigDecimal,金额单位与源框架保持一致(元)状态: 全部完成。后端 + 前端 PC 管理端 + H5 顾客点餐端 + 支付系统均已完成。
HotelOrder.java — 订单主表(Integer status,0~10 数字状态,含 payStatus/payExpireTime/paySource)HotelOrderItem.java — 订单明细(冗余 dishName/specDesc/additionsDesc)OrderCreateDTO.java — 创建订单请求(已移除 payMethod,改用 paySource)HotelOrderVO.java — 订单视图对象(含内部类 OrderItemVO + itemCount)OrderDashboardVO.java — 看板统计响应HotelOrderMapper.java + XML(含看板统计/今日营收/订单号生成,6 个自定义 SQL)HotelOrderItemMapper.java + XML(按订单ID查询 + 批量插入)HotelOrderService.java — 14+ 个方法接口(含完整 Javadoc + 支付/超时取消)HotelOrderServiceImpl.java — 完整状态机 + 退单流程 + 菜品销量累加 + 支付超时处理HotelOrderController.java — 15+ 个 REST 接口(查询3 + 操作6 + 退单4 + 创建1 + 看板1 + 支付相关)HotelOrderConstants.java — 状态 0~10 + 退单发起方hotel_order(IF NOT EXISTS)— 23+ 个字段 + 4 个索引(V1.0.104 建表 + V1.0.105 支付字段扩展)hotel_order_item(IF NOT EXISTS)— 13 个字段 + 1 个索引hotel_order_status(0~10 数字状态,对应中文标签 + list_class 颜色,V1.0.104 + V1.0.105 补充 0/10)hotel_pay_method(MOCK/CASH/ONLINE/CREDIT)hotel_delivery_time_type(ASAP/CUSTOM)V1.0.104__add_hotel_order_module.sql(建表 + 字典 + 菜单)V1.0.105__add_hotel_order_payment_fields.sql(支付字段 + 状态 0/10 + MySQL 8 兼容)forge-admin-ui/src/views/hotel/order.vue — 订单管理(AiCrudPage + 看板统计 + 流程操作 + 详情弹窗)
forge-admin-ui/src/api/hotel.js 中追加 14 个订单接口函数状态: 全部完成。支付宝沙箱 H5 WAP Pay 全链路集成 + 5 层安全加固 + 前端轮询兜底。
AlipayConfig.java — 支付宝配置(appId/privateKey/alipayPublicKey/gatewayUrl/notifyUrl/returnUrl,@ConfigurationProperties 注入)HotelPayConstants.java — 支付状态常量(0=待支付/1=成功/3=超时)+ 支付渠道(MOCK/WECHAT/ALIPAY)HotelPayLog.java — 支付流水(outTradeNo/tradeNo/payAmount/payStatus/payTime/notifyContent)PayCreateDTO.java — 创建支付请求(orderId + paySource)PayResultVO.java — 支付结果(payStatus/payForm/tradeNo)HotelPayLogMapper.java + XML
@InterceptorIgnore(tenantLine = "true") 绕过租户拦截(回调无登录态)updatePayStatusSuccessByIdempotent — 数据库级幂等更新(UPDATE WHERE pay_status != 1)selectLatestByOrderId — 按订单 ID 查最新支付流水(主动查询兜底用)HotelPayService.java — 支付接口(createPay/handlePayCallback/queryAlipayTradeStatus/queryPayStatus)HotelPayServiceImpl.java — 完整支付实现
createPay() — 根据 paySource 创建支付(ALIPAY → AlipayTradeWapPayRequest → 返回 payForm HTML)handlePayCallback() — 支付宝异步回调处理(拆分两步:查 payLog 获取 tenantId → TenantContextHolder.executeWithTenant 包裹业务处理)queryAlipayTradeStatus() — 主动查询支付宝侧订单状态(回调丢失时的兜底机制)controller/open/HotelPayController.java — 5 个接口(❗ 位于 controller/open/,非 pay/controller/)
POST /hotel/open/pay/create — 创建支付(返回 payForm/tradeNo)POST /hotel/open/pay/notify — 支付宝异步回调(签名验证 + 金额校验 + app_id 校验 + 幂等更新 + 异常返回 fail 触发重试)GET /hotel/open/pay/status — 查询支付状态(前端轮询用)GET /hotel/open/pay/alipayQuery — 主动查询支付宝侧订单状态(兜底机制)POST /hotel/open/pay/mockSuccess — Mock 支付(开发调试用)payNotify 实为 notify;returnUrl 接口不存在(AlipayConfig.returnUrl 仅作为支付宝同步跳转地址配置,回到 H5 后由前端轮询检测状态)controller/open/AlipayAuthController.java — POST /hotel/open/alipay-auth/getUserInfo(authCode → 姓名,加密响应 → 手机号)pay/task/PayTimeoutTask.java — 每 2 分钟跨租户扫描超时未支付订单(selectExpiredUnpaidOrderIds → cancelTimeoutOrder,状态 10)HotelPayService.refundOrder() — 支付宝 AlipayTradeRefundRequest 全额退款,失败标记 refund_status=2 可重试;MOCK 渠道直接标记成功hotel_pay_log(IF NOT EXISTS)— 支付流水表(outTradeNo/tradeNo/payAmount/payStatus/payTime/notifyTime/notifyContent)V1.0.106__add_hotel_pay_log_table.sql| # | 保障层 | 说明 |
|---|---|---|
| 1 | RSA2 签名验证 | AlipaySignature.rsaCheckV1 验证回调签名,防伪造 |
| 2 | app_id 校验 | 验证回调中的 app_id 与配置一致,防跨应用攻击 |
| 3 | 金额校验 | 回调金额与订单金额比对,不一致则拒绝 |
| 4 | 数据库级幂等 | UPDATE WHERE pay_status != 1 利用行锁保证原子性,防并发重复处理 |
| 5 | 主动查询兜底 | 前端轮询超时后调用 /alipayQuery 主动查支付宝侧状态,补偿丢失的回调 |
| 场景 | 防护措施 |
|---|---|
| 事务处理中断电 | @Transactional 保证原子性,全部回滚 |
| 回调时网络中断 | 返回 "fail",支付宝 24h 内自动重试(约 8 次) |
| 并发重复回调 | 数据库 UPDATE WHERE pay_status != 1 行锁幂等 |
| 回调全部丢失 | 前端 /alipayQuery 主动查支付宝侧订单状态 |
| 服务器长时间宕机 | 支付宝重试 + 恢复后自动处理 |
/alipayQuery 主动查询支付宝侧订单状态api/index.js — 新增 12+ 个顾客端 API 函数(含支付/支付宝查询)store/modules/hotel-order.js — Pinia 购物车 Store(roomInfo/cartItems/orderNote,persist 持久化)styles/hotel-theme.css — 亚朵深墨绿主题 CSS 变量(--h-pri: #2D5016 等)components/hotel/HotelTabBar.vue — 3-tab 自定义 TabBar(点餐/订单/购物车),使用 uni.reLaunch 导航(已移除"我的"tab,避免与系统 tabBar 冲突)pages.json — 注册 8 个顾客端页面路由forge-h5-ui/src/pages/hotel/customer/room-confirm.vue — 房号确认入口页
/hotel/open/scan 免登录接口)forge-h5-ui/src/pages/hotel/customer/menu.vue — 点餐菜单页(Tab1)
forge-h5-ui/src/pages/hotel/customer/dish-detail.vue — 菜品详情页
forge-h5-ui/src/pages/hotel/customer/cart.vue — 购物车页(Tab3)
box-sizing: border-box 防止越界forge-h5-ui/src/pages/hotel/customer/order-confirm.vue — 确认下单页
/hotel/order 创建)unitPrice 字段从 item.price(基础价)改为 item.unitPrice(含规格/加料加价)box-sizing: border-box 防止越界forge-h5-ui/src/pages/hotel/customer/pay.vue — 支付确认页
box-sizing: border-box 防止越界forge-h5-ui/src/pages/hotel/customer/order-status.vue — 订单状态页(Tab2)
forge-h5-ui/src/pages/hotel/customer/orders.vue — 订单列表页(Tab2)
pageNum + pageSize)、退单原因显示| 文件 | 说明 |
|---|---|
order/domain/HotelOrder.java |
订单实体 |
order/domain/HotelOrderItem.java |
订单明细实体 |
order/controller/HotelOrderController.java |
全部接口(430 行) |
order/service/HotelOrderService.java |
订单业务逻辑(749 行) |
order/mapper/xml/HotelOrderMapper.xml |
订单 SQL |
order/mapper/xml/HotelOrderItemMapper.xml |
明细 SQL |
dto/OrderCreateDTO.java |
创建订单 DTO |
dto/OrderDashboardDTO.java |
看板 DTO |
前端:views/hotel/hotelfront/HotelFrontOrders.vue |
前台订单页面 |
前端:views/hotel/kitchen/KitchenOrders.vue |
厨房订单页面 |
前端:views/hotel/restaurant/RestaurantOrders.vue |
餐厅订单页面 |
前端:views/hotel/customer/CustomerMenu.vue |
顾客点餐页面 |
前端:api/hotel/HotelOrderService.js |
订单 API |
0-PENDING_PAY(待支付)
└── → 超时自动取消 → 10-TIMEOUT_CANCELLED(超时取消)
└── → 支付成功 → 1-PLACED(待接单)
1-PLACED(待接单)
├── → 2-ACCEPTED(已接单)→ 3-PREPARING(备餐中)→ 4-READY(已出餐)→ 5-DELIVERING(配送中)→ 6-COMPLETED(已完成)
├── → 7-REJECTED(已拒单)
└── → 9-REFUNDED(已退单,未接单时直接退)
2-ACCEPTED(已接单)
└── → 8-REFUND_REQUESTED(退单待审核)
├── → 9-REFUNDED(审核通过)
── → 2-ACCEPTED(审核驳回,恢复)
synchronized 防止并发接单orderCreate() 虽然不信任前端价格,但只取 dish.getPrice() 基础价重算,未计入规格选项 priceExtra 与加料 extraPrice;同时 hotel_order_item 只存 specDesc/additionsDesc 文本,无规格选项 ID / 加料 ID,后端无法重算。后果:选加价规格/加料时少收款,且 pay.vue 金额取自后端 → 支付页金额 < 下单页金额OrderCreateDTO.deliveryFee → orderCreate() 直接落库并计入总额,而该接口免登录;当前 H5 hotelConfig.deliveryFee 无数据来源恒为 0,暂无实际损失,但接口层可构造任意值(含负数)incrementDishSales);销量排行接口 GET /hotel/dish/ranking 与前端 getDishSalesRanking() 已就绪,但无页面调用BigDecimal + 元(与 dish 模块一致),编码规范要求 bigint + 分但为模块一致性保持 DECIMAL状态: 已完成。后端 SSE 通知 + 前端声音提醒 + 桌面通知 + 防抖合并。
SseEmitterManager.java — SSE 长连接管理 + 广播(ConcurrentHashMap + AtomicInteger)+ 远程接收(receiveNewOrderFromRemote),直接承担通知广播职责NotificationController.java — SSE 端点(subscribe/unsubscribe/connections/remote/notifyNewOrder)OrderNotificationService.java(notifyNewOrder + notifyRefundRequest)不存在,该能力已内聚到 SseEmitterManagerNEW_ORDER、REFUND_REQUEST 两类;无接单/出餐通知事件(需求 4.2「出餐通知接收」未满足)HotelPayServiceImpl.java — 支付成功后发布 NEW_ORDER 通知(支持跨服务 HTTP 调用)HotelOrderServiceImpl.java — 客户申请退单时发布 REFUND_REQUEST 通知/hotel/notification/remote/notifyNewOrder 接口,解决双服务 SSE 内存不共享问题/hotel/notification/remote/** 到免登录路径(服务间调用无登录态)useOrderNotification.js — SSE 订阅 + MP3 声音 + 桌面通知 + 防抖合并 + Chrome 自动播放策略绕过order.vue — 接入 SSE 通知(声音提醒 + Naive UI 通知 + 看板/列表自动刷新 + 连接状态指示器 + 页面刷新自动检测待接单订单)forge-admin-ui/public/女生-订单提醒.mp3 — MP3 语音提醒文件@SaIgnore 跳过登录校验(EventSource 无法携带 Authorization Header)/女生-订单提醒.mp3),通过 Audio 对象播放/hotel/notification/remote/notifyNewOrder 接口,由 8580 推送 SSE 事件给 PC 端@Value("${server.type:admin}") 注入自定义配置属性判断当前服务类型(admin 或 app),在两个服务的 application.yml 中分别配置 server.type: admin/appaudio.play() 会被阻止。通过监听首次 click/keydown 事件,将播放失败的声音加入待播放队列,用户首次交互后自动补播watch(connected, ...) 监听 SSE 连接状态,连接成功后自动查询待接单订单(status=1)并触发语音提醒。重置按钮不触发背景:系统与亚朵PMS不互通,房间入住/退房由前台在本系统手动操作。核心诉求:入住到退房期间房间客人不变;移动端订单/购物车与当前住客绑定;退房后新客人扫码进来订单和购物车必须是全新的。 方案:引入“在住会话(hotel_room_stay)”——入住=开新会话,退房=关闭会话;订单挂载到会话(stay_id);H5 按会话隔离订单可见性与购物车。
HotelRoomStay.java(roomId/guestName/guestPhone/checkInTime/checkOutTime/status/remark,@TableLogic(value="0", delval="id"))HotelRoomStayMapper.java + XML(selectActiveByRoomId/selectStayPage/selectAllActive,均显式 AND del_flag = 0)HotelRoomStayVO.java、RoomCheckOutVO.java(needConfirm/message/activeOrders/checkedOut)HotelRoomStayService(Impl).java — roomCheckIn/roomCheckOut(两步交互)/roomCleaningDone/roomMaintenanceToggle/stayPage/backfillGuestHotelQrCodeController 新增 5 接口(/room/checkIn、/room/checkOut?force、/room/cleaningDone、/room/maintenanceToggle、/room/stayPage)HotelRoomMapper.xml JoinActiveStay + HotelRoomVO 增 stayId/guestName/guestPhone/checkInTimeQrCodeScanVO.RoomInfo 增 roomStatus/stayId(H5 拦截与隔离依据)roomUpdate 禁止直接改状态(状态仅通过操作流转)orderCreate 写 stay_id + 未入住拦截 + 首单联系人仅空字段回写会话 + 房号以数据库为准;分页支持 stayId 过滤cancelPendingByStayId 批量取消待支付订单(状态 11),进行中订单需二次确认(force)HotelPayService.refundOrder(全额退款,AlipayTradeRefundRequest,失败标记可重试);4 个自动触发点(拒单/顾客退单/前台退单/审核通过);手动退款接口 POST /hotel/order/refundHotelOrderConstants 新增 11=退房联动已取消 + 退款状态 0/1/2;HotelQrConstants 新增 STAY_ACTIVE/STAY_CHECKED_OUTboard.vue(房态看板):房间卡片网格 + 状态 Tab + 房间号/房型/楼层筛选 + 入住登记弹窗(住客姓名/电话/备注)+ 退房二次确认弹窗(进行中订单清单)+ 历史入住记录弹窗;菜单由 V1.0.107 写入room.vue:回归为 AiCrudPage 纯 CRUD(房间号/房型/楼层/状态列/排序/备注);在住业务操作已拆到看板页,编辑表单不含状态字段order.vue:退款状态列(DictTag hotel_refund_status)+ 手动退款按钮(已支付未退款且已取消/退款失败场景)api/hotel.js:新增 6 个接口(roomCheckIn/roomCheckOut/roomCleaningDone/roomMaintenanceToggle/getRoomStayPage/orderRefund)board.vue 与 room.vue 的房间状态标签/颜色为前端硬编码映射(statusLabelMap/statusColorMap),与 AGENTS.md 5.7「字典禁止硬编码」不一致,待补 hotel_room_status 字典后改 DictTagstore/hotel-order.js:roomInfo 增 stayId/roomStatus;setRoomInfo 检测会话变更自动清空购物车(退房后新客人全新购物车)room-confirm.vue:非入住中房间拦截点餐(“该房间暂未入住,如需点餐请联系前台”)orders.vue:订单列表改为按 stayId 过滤(同会话共享可见,退房后隔离),无会话时退回按房间号兼容存量数据;状态映射补 11=已取消order-status.vue:状态 11 文案/图标/提示补齐(“房间已退房,该订单已自动取消”)order-confirm.vue:下单已传 roomId,后端负责会话查找与拦截(双重保险)空闲/打扫中 --入住--> 入住中 --退房--> 打扫中 --打扫完成--> 空闲;空闲 <--> 维护中。
退房时:待支付订单自动取消(11);进行中订单(2/3/4/5/8)需前台二次确认后强制退房。
| 适配项 | jeeplus(源) | Forge(目标) |
|---|---|---|
| 实体基类 | BaseEntity |
TenantEntity(含 tenantId + 审计字段) |
| ID 生成 | UUID.randomUUID() |
@TableId(type = IdType.ASSIGN_ID) 雪花算法 |
| 响应体 | ResponseEntity / ResponseUtil |
RespInfo.success(data) / RespInfo.error(msg) |
| 注入方式 | @Resource |
@RequiredArgsConstructor + private final |
| 权限注解 | @PreAuthorize("hasAuthority('xxx')") |
@SaCheckPermission("xxx") |
| 日志注解 | @ApiLog |
@OperationLog |
| SQL 位置 | Service 层 QueryWrapper |
Mapper XML(DataScopeInterceptor 要求) |
| 逻辑删除 | 手动 setDelFlag(1) + updateById |
@TableLogic(value="0", delval="id") 自动 |
| 租户隔离 | 无 | TenantLineInnerInterceptor 自动追加 tenant_id |
| 字典 | 硬编码状态值 | DictSelect / DictTag / useDict() |
| 前端列表 | 手写 NInput/NSelect | AiCrudPage 配置化 |
| 分页参数 | Page<T> |
pageNum + pageSize(@RequestParam) |
| 分布式锁 | synchronized |
Redisson(@Idempotent 或手动) |
✅ 1. room(房间/房型管理) ← 已完成
✅ 2. qrcode(二维码管理) ← 已完成
✅ 3. open(开放扫码接口) ← 已完成
✅ 4. dish-spec(菜品规格管理) ← 已完成
✅ 5. business-hours(营业时段)← 已完成
⏸️ 6. hotelconfig(酒店配置) ← 暂缓(配送费/配送时长待讨论)
7. dish(加料/日志) ← 待开发
✅ 8. order(订单管理) ← 全部完成(后端+PC管理端+H5顾客端+支付系统)
✅ 9. notification(实时通知) ← 已完成(SSE + 声音提醒 + 桌面通知)
✅ 9.1 stay(在住会话+退款) ← 全部完成(入住/退房/打扫/维护 + 退房联动 + 自动/手动退款)
| 表名 | 说明 |
|---|---|
hotel_qr_code |
二维码表 |
hotel_qr_bind_log |
二维码绑定日志表 |
hotel_room |
房间表 |
hotel_room_type |
房型表 |
| 表名 | 说明 | 迁移脚本 |
|---|---|---|
hotel_order |
订单主表(23+字段 + 4索引,V1.0.105 新增 payStatus/payExpireTime/paySource) | V1.0.104 + V1.0.105 |
hotel_order_item |
订单明细表(13字段 + 1索引) | V1.0.104 |
| 表名 | 说明 | 迁移脚本 |
|---|---|---|
hotel_pay_log |
支付流水表(outTradeNo/tradeNo/payAmount/payStatus/payTime/notifyContent) | V1.0.106 |
hotel_room_stay |
房间在住会话表(roomId/guestName/guestPhone/checkInTime/checkOutTime/status 0=在住 | 1=已退房) |
V1.0.107__add_hotel_room_board_menu.sql:无建表,仅新增「房态看板」菜单(/hotel/board → hotel/board,sort=9,动态查找 酒店管理 父菜单 + NOT EXISTS 防重)
hotel_order 扩展字段(V1.0.106):stay_id(在住会话ID + 索引)、refund_amount(实际退款金额)、refund_trade_no(支付宝退款交易号)、refund_status(0=未退款/1=成功/2=失败可重试)
| 表名 | 说明 | 所属模块 |
|---|---|---|
hotel_config |
酒店基础配置 | hotelconfig(暂缓) |
| 表名 | 说明 | 迁移脚本 |
|---|---|---|
hotel_dish |
菜品(含主图/附加图片/主厨推荐/售罄/上下架) | V1.0.101 |
hotel_dish_category |
菜品分类 | V1.0.101 |
hotel_dish_spec_group |
菜品规格组 | V1.0.101(建表)+ V1.0.102(菜单) |
hotel_dish_spec_option |
规格选项 | V1.0.101(建表) |
hotel_dish_addition |
加料 | V1.0.101 |
hotel_dish_log |
菜品操作日志 | V1.0.101 |
hotel_business_hours |
营业时段 | V1.0.103(建表 + 菜单 + 字典) |
| 字典类型 | 说明 | 迁移脚本 |
|---|---|---|
hotel_dish_status |
菜品状态(在售/下架) | V1.0.101 |
hotel_dish_sold_out |
售罄状态(正常/售罄) | V1.0.101 |
hotel_meal_type |
餐段类型(早餐/午餐/晚餐) | V1.0.103 |
hotel_business_hours_status |
营业时段状态(启用/禁用) | V1.0.103 |
| 字典类型 | 说明 | 迁移脚本 |
|---|---|---|
hotel_order_status |
订单状态(0~11,含待支付/超时取消/11=退房联动已取消) | V1.0.104 + V1.0.105 + V1.0.106 |
hotel_pay_method |
支付方式(MOCK/CASH/ONLINE/CREDIT) | V1.0.104 |
hotel_delivery_time_type |
配送时间类型(ASAP/CUSTOM) | V1.0.104 |
hotel_room_stay_status |
在住会话状态(0=在住/1=已退房) | V1.0.106 |
hotel_refund_status |
订单退款状态(0=未退款/1=退款成功/2=退款失败可重试) | V1.0.106 |
| 字典类型 | 说明 | 所属模块 |
|---|---|---|
| (暂无) |
| 页面 | 路径 | 组件 | 说明 |
|---|---|---|---|
| 二维码管理 | views/hotel/qrcode.vue |
AiCrudPage | 批量生成/绑定/解绑/批量下载 ZIP |
| 房态看板 | views/hotel/board.vue |
自定义卡片网格 | 房间状态 Tab + 筛选 + 入住/退房/打扫/维护 + 退房二次确认 + 入住记录弹窗 |
| 房间管理 | views/hotel/room.vue |
AiCrudPage | 房间纯 CRUD(业务操作已拆到房态看板) |
| 房型管理 | views/hotel/roomType.vue |
AiCrudPage | 房型 CRUD |
| 菜品管理 | views/hotel/dish.vue |
AiCrudPage | 图片预览/上下架/售罄/主厨推荐 |
| 菜品分类 | views/hotel/dishCategory.vue |
AiCrudPage | 分类 CRUD + 启禁用 |
| 菜品规格 | views/hotel/dishSpec.vue |
AiCrudPage | 规格组列表 + 选项管理弹窗 |
| 营业时段 | views/hotel/businessHours.vue |
AiCrudPage | 时段列表 + 时间段下拉选择 + 启禁用 |
| 扫码绑定 (H5) | forge-h5-ui/src/pages/hotel/scan-bind.vue |
UniApp | 扫码绑定房间(管理侧) |
| 扫码页 (H5) | forge-h5-ui/src/pages/hotel/qr-scanner.vue |
UniApp | html5-qrcode 相机扫码 |
| 页面 | 路径 | 组件 | 说明 |
|---|---|---|---|
| 订单管理 | views/hotel/order.vue |
AiCrudPage | 看板统计 + 流程操作 + 详情弹窗 + 退单审核 + 退款状态列 + 手动退款 |
| 页面 | 路径 | Tab | 说明 |
|---|---|---|---|
| 房号确认 | forge-h5-ui/src/pages/hotel/customer/room-confirm.vue |
入口 | 扫码验证房间、非入住拦截、房间卡片、开始点餐 |
| 点餐菜单 | forge-h5-ui/src/pages/hotel/customer/menu.vue |
Tab1 | 分类导航、菜品列表、搜索、购物车浮层 |
| 菜品详情 | forge-h5-ui/src/pages/hotel/customer/dish-detail.vue |
子页 | 大图、规格选择、加料、备注、加入购物车 |
| 购物车 | forge-h5-ui/src/pages/hotel/customer/cart.vue |
Tab3 | 商品列表、数量控制、备注、费用汇总、结算 |
| 确认下单 | forge-h5-ui/src/pages/hotel/customer/order-confirm.vue |
子页 | 配送信息、送达时间、明细、提交订单(已移除硬编码支付方式) |
| 支付确认 | forge-h5-ui/src/pages/hotel/customer/pay.vue |
子页 | 支付宝 H5 WAP Pay + 轮询 + 主动查询兜底 + 倒计时 |
| 订单状态 | forge-h5-ui/src/pages/hotel/customer/order-status.vue |
Tab2 | 进度条、状态卡片、10秒轮询、自定义退单弹窗 |
| 历史订单 | forge-h5-ui/src/pages/hotel/customer/orders.vue |
Tab2 | 订单卡片列表(按在住会话 stayId 过滤)、分页加载、状态标签、待支付"去支付"按钮 |
| 页面 | 路径 | 说明 | 源框架参考 |
|---|---|---|---|
| 酒店配置 | views/hotel/config.vue |
单例配置表单(暂缓) | HotelConfigManagement.vue |
| 厨房待备餐大屏 | 待定 | 待备餐列表 + 出餐 + 语音播报 + 小票打印(需求 4.3,未开发) | KitchenOrders.vue |
| 数据看板 | 待定 | 热门菜品/平均送达时长/趋势图(需求 4.5,现有 5 指标集成在 order.vue) | 无直接参考 |
views/hotel/orderDashboard.vue |
无直接参考 |
| 模块 | 原因 | 待讨论点 |
|---|---|---|
| hotelconfig(酒店基础配置) | 暂不需要 | 配送费规则(按距离/区域/固定?)、预计配送时长(固定/动态?) |
| 决策 | 说明 |
|---|---|
| 规格组统一命名 | 源框架同时存在 hotel_dish_spec 和 hotel_dish_spec_group,Forge 统一使用 hotel_dish_spec_group |
| 营业时段时间选择 | 使用下拉选择(09:00~23:30,每 30 分钟一档),而非时间选择器 |
| 餐段类型 | 仅保留早餐/午餐/晚餐三种,移除夜宵 |
| 前端组件规范 | 统一使用 AiCrudPage 配置化页面,保持分页/筛选/操作列格式一致 |
| 订单状态值 | 使用数字 0~11 连续编号(0=待支付, 1~9 原有状态, 10=超时取消, 11=退房联动取消),非英文字符串常量 |
| 订单金额 | 使用 BigDecimal + 元(DECIMAL(10,2)),与 dish 模块保持一致 |
| 订单模块包结构 | 独立 order/ 子包,与已有 hotel 代码分离 |
| 看板统计集成 | 订单看板统计集成到 AiCrudPage 工具栏 #toolbar-start slot,不单独建页面 |
| H5 顾客端框架 | Vue 3 <script setup> + Pinia + uni-app,从旧框架 Vue 2 Options API + Vuex 迁移 |
| H5 设计风格 | 亚朵酒店深墨绿主题(#2D5016),暖灰背景 #F7F7F7,充足留白,自然温暖 |
| H5 TabBar 架构 | 自定义 HotelTabBar 组件 + uni.reLaunch 导航,3-tab(点餐/订单/购物车),移除"我的"避免与系统 tabBar 页面冲突 |
| H5 支付页金额 | 支付页通过 api.hotelOrderDetail() 从后端获取真实金额,不依赖前端 URL 参数(购物车清空后 URL 参数失效) |
| H5 退单弹窗 | 自定义弹窗替代 uni.showModal,包含标题/提示/原因输入框/取消确定按钮,样式统一 |
| H5 购物车 Store | Pinia + pinia-plugin-persistedstate 持久化,specKey 合并相同规格商品 |
| H5 订单轮询 | order-status.vue 对未完成订单每 10 秒轮询刷新,onUnmounted 清理定时器 |
| H5 后端对接 | 订单状态使用数字 0~11;后端按 dishId 从数据库重算 unitPrice,不信任前端价格。🔴 当前重算只取菜品基础价,规格加价 price_extra 与加料加价 extra_price 被丢弃(hotel_order_item 无规格/加料 ID 字段),导致少收款且支付页金额小于下单页 —— 详见 酒店模块需求缺口清单.md 3.1,属待修资金缺陷 |
| 支付宝 H5 WAP Pay | 使用 AlipayTradeWapPayRequest + pageExecute() 返回 HTML 表单,前端渲染后自动提交跳转支付宝收银台 |
| 支付回调租户上下文 | 支付宝回调无登录态/租户上下文,需从 payLog 提取 tenantId 后用 TenantContextHolder.executeWithTenant() 包裹后续 DB 操作 |
| 支付回调幂等 | UPDATE WHERE pay_status != 1 利用数据库行锁保证原子性,替代 Java 层 if 检查 |
| 支付回调异常处理 | catch 块返回 "fail" 让支付宝自动重试(之前返回 "success" 导致异常时支付宝不重试) |
| 支付轮询机制 | 递归 setTimeout(非 setInterval),首次延迟 3 秒给回调留处理时间,超时后主动查支付宝兜底 |
| vConsole 调试工具 | 开发阶段通过 CDN + 环境变量开启,联调完成后从 index.html、App.vue、.env.production 三处彻底移除 |
| H5 按钮越界修复 | width: 100% + padding 组合需配合 box-sizing: border-box 防止溢出(cart/order-confirm/pay 三个页面) |
| 在住会话隔离 | 入住=开新会话、退房=关会话,订单挂 stay_id;H5 订单按 stayId 过滤、购物车随 stayId 变更自动清空,实现退房后新客人全新体验 |
| 房间状态只走操作流转 | 编辑表单/接口禁止直接改房间状态,仅通过入住/退房/打扫/维护接口流转;在住中房间禁止删除 |
| 退房两步交互 | 存在进行中订单时后端返回 needConfirm + 订单清单,前台确认后 force=true 强制退房;待支付订单直接自动取消(11) |
| 退款策略 | 仅全额退款;拒单/顾客退单/前台退单/审核通过 4 个触发点自动退;退款失败标记可重试不阻断流转;退房竞态异常单由前台手动退款 |
| 支付回调竞态 | 已取消订单(7/9/10/11)收到回调不复活,流水标记 [竞态异常-订单已取消],人工介入退款 |
| 下单房号以数据库为准 | orderCreate 不信任前端传的 roomNo,按 roomId 查房间实体回填,避免旧缓存/二维码改绑串单 |
| 房态看板与房间管理拆分 | 房间业务操作(入住/退房/打扫/维护/入住记录)独立为 board.vue,room.vue 回归 AiCrudPage 纯 CRUD;菜单由 V1.0.107 写入(sort=9,动态查父菜单 + NOT EXISTS 防重) |
| 支付超时取消用定时任务 | PayTimeoutTask 以 @Scheduled(fixedDelay=120000, initialDelay=30000) 轮询,配 TenantContextHolder.executeIgnore 跨租户扫描 selectExpiredUnpaidOrderIds → cancelTimeoutOrder(状态 10),不引入延迟消息中间件 |
| 放弃待支付订单物理删除 | abandonOrder 对未支付订单做物理删除(订单 + 明细),依据 AGENTS.md 5.11「无恢复/审计要求的中间态」例外;已支付订单一律走逻辑删除 + 退款 |
| 支付宝授权接口预留 | /hotel/open/alipay-auth/getUserInfo(authCode → 姓名,加密响应 → 手机号)先落地,为后续小程序化取用户信息预留,当前 H5 未调用 |
| 跨服务 SSE 通知转发 | 8583 AppServer 与 8580 AdminServer 双 JVM 内存不共享,支付成功后由 AppServer HTTP POST 调 AdminServer /hotel/notification/remote/notifyNewOrder,以 server.type 配置区分服务角色 |
| 🔴 开放接口鉴权现状(待加固) | /hotel/open/** 在 SaTokenConfig 中同时排除登录与 API 权限校验,tenantId 由前端传参、订单不校验 stayId 归属、deliveryFee 采用前端传值 —— 详见 酒店模块需求缺口清单.md 3.2,需签名 token 加固 |
| 文档职责拆分 | 本文档只承载「代码地图与实现进度」;需求验收对照、P0/P1 缺口台账、补齐顺序一律进 酒店模块需求缺口清单.md,缺口关闭后细节转入 code-copilot/changes/<变更名>/ |
| 营业时间校验接入顾客端 | 后端新增 BusinessHoursStatusVO + currentStatus() 推导 + GET /hotel/open/customer/businessHours 免登录接口;H5 三页接入(room-confirm 入口整页拦截 / menu 菜品区独立校验 / order-confirm 提交阻断)+ 后端 orderCreate() 兜底校验;删除 room-confirm.vue 硬编码 '10:00 - 22:00'。变更目录:code-copilot/changes/hotel-customer-business-hours-check/ |
文档最后更新:2026-09-03(营业时间校验接入顾客端:后端新增 BusinessHoursStatusVO + currentStatus() + 开放接口 + 下单校验;H5 三页接入入口整页拦截/菜品区拦截/提交阻断;删除硬编码假营业时间;后端编译通过 + H5 构建通过。详见 code-copilot/changes/hotel-customer-business-hours-check/。需求视角的验收对照见同目录 酒店模块需求缺口清单.md)