📌 WeWaiter 新后台规划
本文基于已冻结的旧微信小程序、旧 WeWaiter 服务和旧 Manager WinForms 管理端业务认知梳理,目标是把 WeWaiter 从“微信小程序 + 旧管理工具”升级为可独立交付、可部署、可维护的完整餐饮点餐与结算系统。旧后端和旧管理端源码已移除,业务事实以 docs/phase-0-legacy-business-freeze.md 为准。
📌 1. 旧项目现状冻结
📌 1.1 已有前端业务链路
旧小程序是 mpvue 项目,现已迁入 src/WeWaiter.MiniProgram,核心页面和链路如下:
pages/index:微信登录、授权、扫码入口。二维码里带id和seatid,分别代表商家和桌台。pages/goods:根据商家和桌台获取商家信息、分类、菜品,并进入点餐。components/goods、components/shopcart:菜品列表、购物车、数量增减。pages/checkout:提交订单,调用支付。pages/order:当前用户订单列表。pages/order-detail:订单明细、再次支付。
现有请求大致是:
POST /api/WeiXinApp/LoginGET /api/Sellers?id={sellerId}&seatid={seatNo}POST /api/OrdersGET /api/OrdersGET /api/Orders/{id}GET /api/TenPayV3/JsApi/{orderId}
📌 1.2 旧后端模型
旧 WeWaiter 后端曾是 ASP.NET Core + PostgreSQL,源码已从当前仓库移除,但冻结模型如下:
User:微信用户。Seller、SellerInfo:商家和商家扩展信息。Seat:桌台。Catalog:菜品分类。Goods:菜品。Order、BuyItem:订单和订单项。Printer:打印机。
支付侧目前直接使用微信 TenPay V3,小程序通过 wx.requestPayment 拉起微信支付。订单状态主要是 NOTPAY、USERPAYING、SUCCESS、REFUND、REVOKED、CLOSED。
📌 1.3 旧 WinForms 管理端能力
旧 Manager 是 .NET Framework + DevExpress + EF6 的管理端,源码已从当前仓库移除,主要功能曾是:
- 商家管理。
- 分类管理。
- 菜品管理。
- 桌台管理。
- 打印机管理。
- 图片上传到 OSS。
它更像数据库 CRUD 工具,没有完整权限、门店运营、结算、财务、支付通道、设备管理等后台能力。
📌 2. 新系统目标
技术栈目标:
- 后端:ASP.NET Core 10.0、EF Core、PostgreSQL。
- 管理端:Blazor、Element-Blazor、ASP.NET Core 10.0。
- 客户端:微信扫码小程序、支付宝小程序、跨平台 App,后续可扩展低成本点餐平板。
- 支付:微信小程序继续使用微信原生支付;微信小程序之外的支付场景对接
https://member.z-pay.cn/对应的 ZPAY 能力;后端统一封装支付通道。 - 部署:单店/连锁均可独立部署,支持 Docker Compose 或 Windows 服务部署。
Element-Blazor 使用策略:
- 第一版管理端以 Element-Blazor 为组件库基线。
- 初期可优先使用 NuGet 包或源码引用快速推进。
- 如果遇到 Element-Blazor 组件库本身应该具备的通用能力缺口,可将
Element-Blazor/Element-Blazor作为 git 子模块拉入仓库,例如放在external/Element-Blazor。 - 对通用组件能力、通用样式、组件 API、交互一致性、可访问性和缺陷修复,优先修改 Element-Blazor 子模块代码,而不是在
WeWaiter.AdminWeb中写一次性绕行实现。 - 对 WeWaiter 业务专属页面、领域交互和业务校验,保留在
WeWaiter.AdminWeb。 - Element-Blazor 使用 MIT License,修改和分发时必须保留原许可证和版权声明。
业务目标:
- 顾客扫码选桌点餐、下单、支付。
- 商户后台管理门店、桌台、菜品、套餐、规格、库存、打印、订单和退款。
- 平台/商户可查账、对账、结算、导出报表。
- 支付通道可配置,微信小程序默认走微信原生 JSAPI/小程序支付,支付宝小程序、跨平台 App、H5 等微信小程序之外的场景默认走 ZPAY,后续可扩展支付宝直连、现金或店内收银。
- 预留厨房屏、取餐屏、平板点餐、服务员 App、POS 收银端接口。
📌 3. 产品模块规划
📌 3.1 顾客点餐端
- 登录与身份识别:微信 openid、支付宝 userId、App 手机号/游客。
- 扫码入座:二维码包含
tenantId/storeId/tableId/channel或短码。 - 菜单浏览:分类、菜品、规格、做法、加料、口味、沽清、推荐。
- 购物车:同桌加菜、数量修改、规格合并、备注。
- 下单:堂食、外带、预约、人数、餐具、备注。
- 支付:创建支付单、跳转支付、支付回调、支付状态轮询。
- 订单状态:待支付、已支付、已接单、制作中、待取餐、已完成、已取消、退款中、已退款。
- 历史订单:再次点单、开发票预留、售后预留。
📌 3.2 商户管理端
- 总览看板:今日营业额、订单数、客单价、退款、支付成功率、热销菜品。
- 门店管理:门店资料、营业时间、服务电话、公告、堂食/外带开关。
- 桌台管理:区域、桌号、人数、二维码生成。
- 菜品管理:分类、菜品、图片、价格、规格、套餐、口味、库存、上下架。
- 订单中心:实时订单、筛选、接单、取消、退款、改价、补打小票。
- 厨房与打印:打印机、出品档口、打印模板、失败重打。
- 支付配置:微信支付和 ZPAY 商户参数、通道开关、回调地址校验。
- 财务结算:支付流水、退款流水、平台服务费、商户结算单、导出。
- 员工与权限:老板、店长、收银员、后厨、服务员、财务。
- 系统配置:图片存储、短信/通知、数据备份、操作日志。
📌 3.3 平台管理端
如果 WeWaiter 后续要作为 SaaS 或代理商系统,需要平台层:
- 租户/商户开通。
- 套餐和授权期限。
- 平台服务费规则。
- 支付通道总配置。
- 结算审核。
- 平台操作审计。
- 版本和远程升级。
如果只做单商户私有部署,平台层可以保留表结构,后台先隐藏。
📌 3.4 设备端
可分三类设备:
- 厨房屏/KDS:Web PWA 或轻量 App 优先,接收新订单、改状态、催单提醒。
- 点餐平板:低成本设备可以评估 LVGLSharp 或 MewUI,但第一版建议先用 WebView/PWA 降低维护成本。
- 收银/打印网关:独立本地 Agent,负责局域网打印、钱箱、扫码枪、断网缓冲。
低成本平板不建议第一阶段直接押注 LVGLSharp/MewUI。原因是餐饮点餐强依赖图片、滚动、动效、输入法、联网缓存和扫码支付跳转,Web/PWA 更快验证业务。LVGLSharp/MewUI 可以作为“极低成本、固定菜单、弱图片、只内网下单”的第二路径。
📌 4. 推荐架构
📌 4.1 后端项目拆分
建议新建 src 结构:
WeWaiter.Api:HTTP API、认证、OpenAPI。WeWaiter.Application:用例服务、DTO、权限、事务边界。WeWaiter.Domain:领域实体、枚举、规则。WeWaiter.Infrastructure:EF Core、支付、文件存储、打印、消息。WeWaiter.Worker:超时关单、结算生成、支付补偿、打印重试。WeWaiter.AdminWeb:Blazor + Element-Blazor 管理端。WeWaiter.MiniProgram:迁入src的 mpvue 微信小程序。external/Element-Blazor:可选 git 子模块;当 Element-Blazor 需要源码级修改时引入。WeWaiter.Migrations或直接使用 API 项目承载 migrations。
📌 4.2 核心原则
- 订单和支付分离:订单是业务单,支付单是资金请求,退款单是逆向资金请求。
- 菜品价格快照:订单项必须保存下单时名称、规格、单价、图片、税费/服务费等快照,不能依赖菜品后续修改。
- 多租户隔离:所有经营数据带
tenant_id,门店数据带store_id。 - 钱用
decimal(18,2)或以分为单位的long。支付接口建议用分,库内可用numeric(18,2),但要统一转换边界。 - 状态机显式化:订单、支付、退款、结算各自有状态,不混用一个字段。
- 支付回调幂等:以支付平台交易号和本地支付单号做唯一约束,重复回调不重复入账。
- 对账优先:每一笔资金动作都要有流水和原始回调报文。
📌 5. 数据库规划
以下是第一版 PostgreSQL 逻辑表。字段命名建议使用 snake_case,主键统一 uuid,时间统一 timestamptz。
📌 5.1 租户与组织
tenants
idnamecodestatuscontact_namecontact_phonecreated_atupdated_at
stores
idtenant_idnamelogo_urladdressphonebusiness_hoursannouncementstatustimezonecreated_atupdated_at
store_areas
idtenant_idstore_idnamesort_order
dining_tables
idtenant_idstore_idarea_idtable_nodisplay_namecapacityqr_codeqr_payloadstatuscreated_atupdated_at
📌 5.2 账号与权限
staff_users
idtenant_idstore_idusernamephonepassword_hashdisplay_namestatuslast_login_atcreated_at
roles
idtenant_idnamescopepermissions jsonb
staff_user_roles
staff_user_idrole_id
customers
idtenant_idphonenicknameavatar_urlcreated_atlast_active_at
customer_identities
idcustomer_idprovideropenidunionidsession_key_encryptedcreated_at
provider 可取 wechat_miniapp、alipay_miniapp、app_phone、guest。
📌 5.3 菜单与商品
menu_categories
idtenant_idstore_idnamesort_orderis_enabledcreated_at
products
idtenant_idstore_idcategory_idskubarcodenamedescriptionimage_urlthumbnail_urlbase_pricemember_pricecost_pricestock_modestock_quantityis_sold_outis_enabledsort_ordercreated_atupdated_at
product_option_groups
idtenant_idstore_idproduct_idnamemin_selectmax_selectis_requiredsort_order
product_options
idgroup_idnameprice_deltasort_orderis_enabled
combo_groups、combo_items
- 用于套餐和必选组合,第二阶段实现。
📌 5.4 订单
orders
idtenant_idstore_idtable_idcustomer_idorder_nodaily_noorder_typesource_channelpeople_countstatuspay_statustotal_amountdiscount_amountservice_fee_amountpayable_amountpaid_amountremarkcreated_atsubmitted_atpaid_atcompleted_atcancelled_at
order_type:dine_in、takeaway、pickup。
source_channel:wechat_miniapp、alipay_miniapp、app、tablet、pos。
status:draft、pending_payment、paid、accepted、preparing、ready、completed、cancelled、refunding、refunded。
order_items
idtenant_idstore_idorder_idproduct_idproduct_nameproduct_image_urlunit_pricequantityoption_amounttotal_amountremarkkitchen_statussnapshot jsonbcreated_at
order_item_options
idorder_item_idoption_group_nameoption_nameprice_delta
order_status_logs
idorder_idfrom_statusto_statusoperator_typeoperator_idreasoncreated_at
📌 5.5 支付与退款
payment_channels
idtenant_idstore_idprovidernameconfig_encryptedis_enabledcreated_atupdated_at
provider 第一阶段支持 wechat_pay 和 zpay,后续支持 alipay_direct、cash、pos。
payment_orders
idtenant_idstore_idorder_idpayment_channel_idpayment_noproviderprovider_trade_noamountcurrencystatusclient_typecashier_urlminiapp_payload jsonbrequest_payload jsonbnotify_payload jsonbreturn_payload jsonbexpired_atpaid_atcreated_atupdated_at
status:created、pending、paid、failed、closed、expired。
refund_orders
idtenant_idstore_idorder_idpayment_order_idrefund_noprovider_refund_noamountreasonstatusrequest_payload jsonbnotify_payload jsonbcreated_atsucceeded_at
payment_events
idpayment_order_idevent_typeproviderprovider_trade_noraw_payload jsonbsignature_validcreated_at
📌 5.6 结算与财务
ledger_entries
idtenant_idstore_idbiz_typebiz_iddirectionamountfee_amountnet_amountoccurred_atcreated_at
settlement_batches
idtenant_idstore_idsettlement_noperiod_startperiod_endgross_amountrefund_amountfee_amountnet_amountstatuscreated_atconfirmed_at
settlement_items
idsettlement_batch_idledger_entry_idamount
📌 5.7 打印与设备
printers
idtenant_idstore_idnameprinter_typeconnection_typeconfig jsonbstatuscreated_at
print_jobs
idtenant_idstore_idprinter_idorder_idjob_typecontentstatusretry_countlast_errorcreated_atprinted_at
devices
idtenant_idstore_iddevice_typenamedevice_keystatuslast_seen_atconfig jsonb
📌 5.8 系统与审计
files
idtenant_idstore_idstorage_providerbucketobject_keyurlcontent_typesizecreated_at
operation_logs
idtenant_idstore_idoperator_typeoperator_idactiontarget_typetarget_iddiff jsonbipuser_agentcreated_at
outbox_messages
idtopicpayload jsonbstatusretry_countnext_retry_atcreated_at
📌 6. 支付平台对接规划
支付不要写死在订单控制器里,建议定义统一接口:
public interface IPaymentProvider
{
string Provider { get; }
Task<CreatePaymentResult> CreatePaymentAsync(CreatePaymentRequest request, CancellationToken cancellationToken);
Task<PaymentNotifyResult> HandleNotifyAsync(HttpRequest request, CancellationToken cancellationToken);
Task<QueryPaymentResult> QueryAsync(QueryPaymentRequest request, CancellationToken cancellationToken);
Task<ClosePaymentResult> CloseAsync(ClosePaymentRequest request, CancellationToken cancellationToken);
Task<CreateRefundResult> RefundAsync(CreateRefundRequest request, CancellationToken cancellationToken);
}
第一阶段实现两个支付 provider:
WechatMiniProgramPaymentProvider:微信小程序原生支付,延续当前wx.requestPayment体验。ZPayPaymentProvider:微信小程序之外的支付场景,例如支付宝小程序、跨平台 App、H5 或后续聚合支付入口。
支付通道路由规则:
source_channel = wechat_miniapp:默认选择wechat_pay。source_channel = alipay_miniapp:默认选择zpay。source_channel = app:默认选择zpay,也可按 App 内部环境扩展微信/支付宝直连。source_channel = tablet、pos:默认选择店内收银、现金或扫码聚合支付,按门店配置决定。
统一支付流程建议如下:
- 顾客提交订单,后端创建
orders和order_items,订单状态为pending_payment。 - 前端调用
POST /api/client/orders/{id}/payments。 - 后端根据
source_channel和门店支付配置选择 provider,创建payment_orders。 - 微信小程序 provider 调用微信统一下单,返回
wx.requestPayment参数。 - ZPAY provider 调用 ZPAY 创建支付,返回收银台跳转信息、二维码、URL 或小程序跳转参数。
- 支付平台回调后端
notify_url。 - 后端验签、幂等保存
payment_events,更新payment_orders为paid,再更新orders.pay_status/status。 - Worker 定时查询未确认支付单,补偿回调丢失。
微信小程序原生支付流程:
- 前端创建订单后调用
POST /api/client/orders/{id}/payments。 - 后端选择
WechatMiniProgramPaymentProvider。 - 后端使用顾客
openid、订单号、金额、商品摘要调用微信支付。 - 返回
timeStamp、nonceStr、package、signType、paySign。 - 小程序调用
wx.requestPayment。 - 微信支付回调后端,后端验签并更新支付单和订单。
ZPAY 支付流程:
- 非微信小程序客户端创建订单后调用
POST /api/client/orders/{id}/payments。 - 后端选择
ZPayPaymentProvider。 - 后端调用 ZPAY 创建支付单。
- 前端按 ZPAY 返回结果跳转收银台、展示二维码或拉起对应小程序。
- ZPAY 回调后端,后端验签并更新支付单和订单。
重要风险:
- 微信小程序场景不走 ZPAY,避免第三方收银台跳转带来的审核和体验风险。
- 支付宝小程序、App、H5 使用 ZPAY 时,仍需以 ZPAY 当前文档和各平台跳转规则为准。
- 支付金额、订单号、回调签名、重复通知、超时关闭必须在后端兜住。
📌 7. API 边界建议
📌 7.1 顾客端 API
POST /api/client/auth/wechat/loginPOST /api/client/auth/alipay/loginGET /api/client/scan-tickets/{code}GET /api/client/stores/{storeId}/menu?tableId=...POST /api/client/ordersGET /api/client/ordersGET /api/client/orders/{id}POST /api/client/orders/{id}/paymentsGET /api/client/orders/{id}/payment-statusPOST /api/client/orders/{id}/cancel
📌 7.2 管理端 API
POST /api/admin/auth/loginGET /api/admin/dashboard/summaryGET/POST/PUT/DELETE /api/admin/storesGET/POST/PUT/DELETE /api/admin/tablesGET/POST/PUT/DELETE /api/admin/menu-categoriesGET/POST/PUT/DELETE /api/admin/productsGET /api/admin/ordersGET /api/admin/orders/{id}POST /api/admin/orders/{id}/acceptPOST /api/admin/orders/{id}/completePOST /api/admin/orders/{id}/refundGET/PUT /api/admin/payment-channelsGET /api/admin/payment-ordersGET /api/admin/settlementsPOST /api/admin/settlements/{id}/confirmGET/POST/PUT/DELETE /api/admin/printersGET /api/admin/operation-logs
📌 7.3 设备 API
POST /api/device/authGET /api/device/orders/pendingPOST /api/device/orders/{id}/kitchen-statusGET /api/device/print-jobsPOST /api/device/print-jobs/{id}/ackPOST /api/device/heartbeat
📌 8. 管理端页面规划
Blazor + Element-Blazor 管理端建议第一版页面:
- 登录页。
- 工作台:营业概览、待处理订单、支付状态。
- 订单中心:实时订单列表、订单详情抽屉、状态操作、退款。
- 菜品中心:分类、菜品表格、菜品编辑、图片上传、规格/口味。
- 桌台中心:区域、桌台、二维码生成和下载。
- 门店设置:基础信息、营业时间、公告。
- 支付设置:微信支付、ZPAY 参数、回调地址、测试支付。
- 打印设置:打印机、模板、打印记录。
- 财务中心:流水、退款、结算单、导出。
- 员工权限:员工、角色。
- 系统日志:操作日志、异常事件。
UI 风格建议偏运营工具:紧凑、可扫描、少装饰、多表格筛选和批量操作。
📌 9. 部署方案
📌 9.1 单机私有部署
wewaiter-api:ASP.NET Core API。wewaiter-admin:Blazor 管理端,可与 API 同进程托管或独立部署。postgres:业务数据库。redis:缓存、分布式锁、队列可选。wewaiter-worker:定时任务和异步任务。wewaiter-print-agent:可选,本地打印网关。
📌 9.2 Docker Compose
适合 Linux 小主机、云服务器、NAS:
- API、Worker、PostgreSQL、Redis、Nginx 一键启动。
- volumes 保存数据库和上传文件。
.env配置微信支付、ZPAY、JWT、数据库密码、对象存储。
📌 9.3 Windows 服务
适合现有商户电脑:
- API/Worker 作为 Windows Service。
- PostgreSQL 本机安装或内置部署脚本。
- 打印 Agent 作为 Windows 托盘或服务。
📌 10. 迁移路线
📌 阶段 0:冻结旧业务认知
- 梳理旧表字段和小程序接口。
- 固化新枚举:订单状态、支付状态、渠道、设备类型。
- 确认微信原生支付和 ZPAY 当前接口文档。
📌 阶段 1:新后端骨架
- 建立 ASP.NET Core 10.0 项目结构。
- 接入 EF Core + PostgreSQL + migrations。
- 建立租户、门店、桌台、分类、菜品、订单基础表。
- 建立 JWT 登录和 OpenAPI。
- 写入种子数据,复刻现有小程序点餐链路。
📌 阶段 2:支付闭环
- 实现
IPaymentProvider、WechatMiniProgramPaymentProvider和ZPayPaymentProvider。 - 建立支付单、支付事件、回调幂等。
- 完成微信小程序原生支付、支付宝小程序/App 的 ZPAY 支付返回形态。
- 增加超时关单和支付查询补偿。
📌 阶段 3:管理端 MVP
- 登录、门店、桌台、菜品、分类。
- 订单列表、订单详情、状态流转。
- 微信支付和 ZPAY 配置与支付流水查询。
- 图片上传。
- 二维码生成。
📌 阶段 4:结算与报表
- 支付流水、退款流水。
- 日结/周期结算。
- 导出 Excel/CSV。
- 财务权限和操作审计。
📌 阶段 5:设备与出品
- 打印任务和打印模板。
- 本地打印 Agent。
- 厨房屏/KDS。
- 平板点餐 PWA。
- 再评估 LVGLSharp/MewUI 的专用设备版本。
📌 11. 第一批实现建议
建议不要直接在旧 WeWaiter 项目上大改,而是新建 src 新系统,旧系统作为业务参考。第一批代码目标:
- 新建 solution/project 结构。
- 建立 PostgreSQL schema 和 migrations。
- 实现管理端登录、门店、桌台、分类、菜品 API。
- 实现顾客端扫码菜单 API 和创建订单 API。
- 对接真实支付前先做
FakePaymentProvider,把订单/支付状态机跑通。 - 再替换为微信小程序原生支付和真实
ZPayPaymentProvider。
这样可以在没有支付联调账号时继续推进核心业务,避免支付平台细节阻塞整个后台重建。