Files
laundry-desk/docs/superpowers/specs/2026-04-23-laundry-desk-design.md
manpengan 426fa54621 docs: add laundry-desk design spec (M0)
洗衣店柜台管理系统的初始设计文档。单店单机 Electron + SQLite,
Apple HIG UI,4 期交付(M1 基础 → M2 收款统计 → M3 拍照打印
→ M4 员工短信)。实现交给 Gemini,Claude 守门禁,Codex 二审。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-23 09:18:36 +08:00

8.9 KiB
Raw Permalink Blame History

title, date, status, authors
title date status authors
laundry-desk 设计文档 2026-04-23 approved (M0 — 待 Gemini 实现) claude (brainstorm), manpengan (decision)

laundry-desk — 洗衣店柜台管理系统

1. 目标与场景

单店单机 Windows 桌面系统,覆盖洗衣店柜台全流程:收件登记 / 取件 / 客户 / 收款 / 统计 / 打印 / 短信。

  • 运行Windows 10/11NSIS .exe 安装器)
  • 开发macOS 交叉打包GitHub Actions windows-latest 为准)
  • 数据:本地 SQLiteWAL + 每日自动备份)

典型场景:

  • 收件:查回头客 → 录物品明细 → 计价收款 → 生成 4 位取件码 → 打印登记单
  • 取件:客户报取件码 / 电话 / 单号 → 查询 → 收尾款 → 标记已取 → 打印取件条
  • 管理:店主查看日/月营业额、逾期未取、回头率

2. 范围

In Scopev1.0.0 收件、取件、订单列表、客户自动去重(按电话)、按件计费、付款方式与欠款、日/月统计、逾期未取、58mm 热敏打印、物品照片、腾讯云 SMS、多员工账号 + 审计日志、Excel 导入导出、自动备份。

Out of Scope 多门店 / 云端同步 / 会员积分储值 / 微信小程序 / RFID / 自动称重。

3. 技术栈

选型
应用框架 Electron 32+
前端 React 19 + TypeScript 5 (strict)
UI Tailwind CSS 4 + shadcn/ui
动效 Framer Motion 11
字体 SF Pro Display/Text + PingFang SC
状态 Zustand
路由 React Router 7
数据库 better-sqlite3 + Drizzle ORM
密码哈希 @node-rs/argon2
构建 Vite + electron-vite
打包 electron-builderNSIS
图表 Recharts
打印 electron-pos-printer58mm ESC/POS
短信 @tencentcloud/tencentcloud-sdk-nodejs-sms
Excel exceljs
测试 Vitest单测+ PlaywrightE2E
CI GitHub Actionswindows-latest 构建 + artifact

UI 视觉规范Apple HIG SF Pro + PingFang SC、圆角 1216px、半透明/毛玻璃卡片、macOS System ColorssystemBlue #007AFF、Framer Motion 过渡、深色模式跟随系统、窗口 titleBarStyle: 'hiddenInset'Mac 开发态)/ Windows 下降级为圆角无边框。

4. 数据模型SQLite + Drizzle

金额一律用整数分存储(杜绝浮点)。

关键字段
customers id, name, phone (unique), vip_level, total_orders, total_spent, created_at, updated_at
orders id, order_no (unique, YYYYMMDD-NNNN), pickup_code (char(4)), customer_id (fk), status (pending/ready/picked_up/cancelled), total_amount, paid_amount, payment_method (cash/wechat/alipay/card/unpaid), receive_date, expected_pickup_date, actual_pickup_at, staff_id (fk), picked_up_by (fk nullable), notes, created_at, updated_at
order_items id, order_id (fk cascade), item_type, service_type (wash/dry_clean/iron), quantity, unit_price, subtotal, item_notes
order_photos id, order_id (fk cascade), file_path (相对 userData), taken_at
staffs id, username (unique), password_hash (Argon2), display_name, role (admin/staff), is_active, created_at, last_login_at
sms_log id, order_id (fk), phone, content, status (pending/sent/failed), provider_response (json), sent_at
settings key (pk), value (json), updated_at
audit_log id, staff_id (fk nullable), action (create/update/delete/pickup/cancel/login/export), entity, entity_id, diff (json), created_at

索引: orders(pickup_code)orders(customer_id, status, receive_date)audit_log(created_at)customers(phone) uniqueorders(order_no) unique

取件码策略: 00:00 重置当日池,随机 4 位数字,事务内冲突重试 ≤ 3 次(单店同日 1 万单封顶完全够用)。

订单号策略: YYYYMMDD-NNNN 顺序号(事务内 SELECT max(nnnn)+1,同日 9999 封顶)。

默认 settings keys shop.nameshop.addressprinter.enabledprinter.widthsms.enabledsms.tencent.secret_idsms.tencent.secret_keyM4 加密存储)、sms.template_idprice_templatesJSON 数组)。

备份: %APPDATA%/laundry-desk/backups/ 下每日 03:00 zip .db,保留最新 30 份滚动删除;设置页提供"立即备份 / 从备份还原"。

5. 架构分层

src/
  main/           # Node 主进程(持有 DB
    db/           # Drizzle schema / migrations / backup
    services/     # 业务逻辑(无 Electron 依赖,可单测)
    ipc/          # IPC handlers按领域分组
    window.ts
    index.ts
  preload/        # 桥接,暴露类型安全 window.api
  renderer/       # React UI
    routes/       # Home / Receive / Pickup / Orders / OrderDetail / Customers / Stats / Settings / Login
    components/ui/  # shadcn/ui 定制
    stores/       # Zustand
    lib/api.ts    # window.api 封装
    styles/globals.css
  shared/         # main ↔ renderer 共享类型 + Zod schema + 错误码
  tests/

硬约束:

  • contextIsolation: true / nodeIntegration: false / sandbox: true / CSP 严格
  • Renderer 零 Node/DB 访问,全走 IPC
  • IPC 命名 <domain>:<action>(如 orders:create);入参一律过 Zod返回 { ok: true, data } | { ok: false, error: { code, message } }
  • Service 层无 Electron 依赖;接受 db client 注入(测试用 in-memory SQLite
  • 单文件 ≤ 400 行、函数 ≤ 50 行、嵌套 ≤ 4 层;金额零浮点;无硬编码密钥

6. 核心工作流

6.1 收件

电话查回头客 → 明细多行 → 付款方式 + 实收 → 事务生成 pickup_code + order_no → 写 orders + order_items+ 可选 order_photos)→ 更新 customers.total_orders/total_spentaudit_logM3打印登记单。

6.2 取件

取件码(优先)/ 电话 / 单号 / 姓名查询 → 多条时列表选 → 有欠款先收 → status = picked_upactual_pickup_atpicked_up_byaudit_logM3打印取件条。

6.3 自动备份

app.ready 启动 node-cron 03:00 → PRAGMA wal_checkpoint(TRUNCATE) → 复制 .db → zip → 滚动保留 30 份。

6.4 短信通知M4

手动/批量触发 → Service 调腾讯云 SMS SDK → 写 sms_logpending → sent/failed→ 状态回填订单详情。

7. 分期路线图

Tag 交付
M1 v0.1.0 项目骨架 + Apple HIG 设计系统 + 收件/取件/列表/详情 + 客户自动去重 + 自动备份 + Windows NSIS 打包
M2 v0.2.0 价格模板 + 按件计费 + 折扣 + 付款/欠款 + 日/月报表Recharts+ 逾期未取 + Excel 导入导出
M3 v0.3.0 收件拍照13 张,存 userData/photos/YYYY-MM/+ 58mm 热敏打印登记单 / 取件条
M4 v0.4.0v1.0.0 登录Argon2+ 权限admin/staff+ 审计日志全面绑定 + 腾讯云 SMS 可取件通知(可关闭)

8. 验收门禁(每期必过)

质量: TS strict 零错、ESLint/Prettier 零警、文件/函数/嵌套红线、无硬编码密钥、所有 IPC 过 Zod。 测试: Service 单测覆盖率 ≥ 70%、Playwright E2E 覆盖本期核心路径、备份可从 zip 还原到新安装。 交付: GH Actions windows-latest 构建绿灯Windows 10/11 实机冒烟manpengan.exe 大小记录基线GitHub Release 附安装器 + SHA256。 文档: README.md 截图更新;docs/CHANGELOG.md 本期条目。

9. 分工

角色 职责 工具
Claude (Opus 4.7) brainstorm / spec / 门禁验收 / code review Claude Code
Codex 关键节点二次审查(架构 / 安全 / 并发) Codex CLI
Gemini M1~M4 主力实现、测试编写、修 build Gemini CLI
manpengan 决策 / UI 走查 / 发版

节奏: 每期开始 Claude 在 milestone issue 补实施细节 → Gemini 提 PR → Claude 审 → Codex 关键点复审 → Claude 过门禁清单 → manpengan tag release。

10. 风险与缓解

风险 缓解
Mac 交叉打 Windows exebetter-sqlite3 native 模块失败 GH Actions windows-latest 为准;本地 pnpm rebuildelectron-builder buildDependenciesFromSource: false
打印机型号差异 M3 抽象 PrinterDriver 接口,先支持 58mm 通用 ESC/POS型号配置化
腾讯云 SMS 模板审核周期 Provider 可替换;模板 id 从 settings 读;无短信时仍可发版
SQLite 单文件损坏 WAL + 每日 zip + 备份校验任务
Electron XSS → 任意代码 contextIsolation + sandbox + CSP + 所有 IPC 过 Zod
密钥泄漏(短信 SecretKey M4 用 OS keychainkeytar)加密存储,非明文入库

11. 假设

单店单机;日单量 ≤ 1000员工 ≤ 10打印机 58mm ESC/POS 兼容;柜台机器可联外网(为 SMS / 备份到外部 NAS 留空间v1 不做GitHub 用户名 manpengan,仓库 public

12. Open Questions

无。后续变更走 docs/adr/YYYY-MM-DD-<topic>.md