car-wash-java/
├── car-wash-entity/ # 实体、VO、SQL 迁移脚本
├── car-wash-mapper/ # MyBatis-Plus Mapper
├── car-wash-service/ # 核心业务逻辑
├── car-wash-common/ # 共享工具(Sa-Token、Redis、AOP)
├── car-wash-admin/ # 管理后台 API(Spring Boot)
├── car-wash-miniapp/ # 微信小程序 API(Spring Boot)
├── car-wash-mp/ # 微信公众号 API(Spring Boot)
├── admin-web/ # 运营管理后台前端(Vue 3 + Element Plus + Vite)
├── admin-h5/ # 运营商 H5(uni-app)
└── admin-web-new/ # 管理后台前端重构版(Vite + Vue 3)
| 表 | 用途 |
|---|---|
t_user |
微信小程序用户(station_id 标识归属站点) |
t_wash_order |
洗车订单(is_cross 标记是否跨店消费) |
t_split_record |
分账流水,按类型追踪站点间资金流向 |
t_settlement_record |
月度结算单(幂等键 uk_station_period) |
t_station_account |
站点账户余额(available_balance 可提现额) |
t_wallet_detail |
用户钱包流水(充值/消费/退款) |
t_pay_log |
微信支付日志(out_trade_no 商户订单号,transaction_id 微信交易号) |
t_recharge_config |
充值配置(归属 group_id 分组) |
t_recharge_config_group |
充值配置分组(is_default=1 为默认分组) |
月度结算由 SettlementServiceImpl.executeMonthlySettlement() 驱动,每月对上月数据进行结算。
SplitRecord 资金类型:
| 类型 | 值 | 方向 |
|---|---|---|
| TYPE_RECHARGE | 1 | 同一站点收支,from=to |
| TYPE_CROSS_EXPEND | 4 | 跨店:归属站 → 消费站 |
| TYPE_CROSS_INCOME | 6 | 跨店:归属站 → 消费站(与 EXPEND 配对) |
| TYPE_REFUND | 5 | 退款支出 |
月结公式:
feeBase = totalRecharge - totalRefund - totalCrossExpend + totalCrossIncome
platformFee = feeBase × 10%
available = openingBalance + feeBase - platformFee
available > 0 时正常结算,转入站点可提现余额,同时记录平台服务费。负数则结转下期。
shortId 确定 stationId(UserServiceImpl.java:135-137)stationId = null,首次消费时在 WashOrderServiceImpl.createOrder() 中自动归属WxPayServiceImpl.wxNotify() 中创建 SplitRecord(TYPE_RECHARGE, from=stationId, to=stationId)OrderSettlementServiceImpl.backfillUnattributedRecharges() 在首次消费结算时追溯补建createOrder() → 扣预付款,设置 isCross 标记settleOrder() → 扣款,回填无归属充值,本店跳过/跨店创建分账SaToken 注解 @SaIgnore 需要确保被 Spring 代理拦截才能生效tradeNo 与微信支付 transactionId 对应,通过 t_pay_log 桥接 WalletDetailuk_station_period),重复执行不会产生重复结算单