wsh5485 9d6fb59fd1 docs: add Platform+Subsystem architecture proposal
12 节方案:
1. 目标
2. 顶层架构(Platform 在中间 / N 个 Subsystem 围着)
3. Subsystem Manifest 协议(6 个标准端点 + JSON Schema 设置)
4. SSO(JWT + 30min 短期 token)
5. 数据模型(Platform DB carplatform 5 张表 / 子系统各自独立 DB)
6. 集成方式对比(推荐 iframe 嵌入 + 独立部署 fallback)
7. 5 步改造路线图
8. 技术选型
9. 风险 & 缓解
10. Roadmap(W1~W8+)
11. 不做的事
12. 立即动手清单

决策依据:
- Q1: 10+ 子系统 → 完整的平台层
- Q2: 同构为主偶尔异构 → manifest + 6 端点语言无关
- Q3: 基座 DB + 子系统独立 DB
- Q4: 永远单用户 → 不要 RBAC / 多租户
2026-06-20 22:01:54 +08:00

洗车管理系统

给我自己的私家车记账用的。

养车这件事最容易稀里糊涂——洗车/加油/充电/保养/保险,哪个花了多少全靠记性。这玩意儿就是把每笔账都记下来,顺带把天气、Grocy 汽美用品库存、保养预测都塞进一个面板里。所有数据存自己服务器上,不上云。

跑了一年多,V2.8 还在迭代。下面是当前状态。

功能

  • :CRUD + 软删除 + 健康卡片(油耗/电耗/保养预测)
  • 洗车:CRUD + 4 种类型 + 自动抓天气 + AI 截图 OCR 自动填表 + 前后对比照
  • 加油:CRUD + 自动算百公里油耗(仅加满记录)+ 油价趋势图
  • 充电CRUD + 自动算百公里电耗
  • 保养:CRUD + 动态项目(机油/机滤/空滤...)+ OCR
  • 保险CRUD + 到期提醒 + 附件上传
  • 化学品:Grocy 镜像同步 + 库存扣减 + 低库存预警
  • 仪表盘:30 天频次 + 同比环比 + 油价 + 年均养护 + 季节频率 + 各车成本
  • 月度报表Excel6 sheet+ PDF
  • 提醒中心:加油/保养/洗车超期阈值可配
  • 全局搜索:跨 7 领域带高亮(车牌/商家/保单号...)
  • 标签:给记录打 #打蜡 #通勤 之类的,可查频率
  • 通知中心OCR/同步/备份结果持久化
  • 成就:14 个预置成就(洗车新手→狂魔,万里征程...)
  • PWAiOS/Android 可装到桌面 + 离线缓存

API 总共 60+ 端点,完整列表跑起来后看 /api/docs

技术栈

后端 Node 18 + Express + MySQL 8(主)/ SQLite(回退)。前端 Vue 3 + Vite + Pinia。PWA 用 vite-plugin-pwa。OCR 接 MiniMax M3 多模态或任意 OpenAI 兼容端点。

部署

我自己在宝塔上跑。详见 docs/install/INSTALL-BT-NODE.md

最简步骤:

cd /www/wwwroot/carwash
unzip 洗车管理系统-v2.8-源码.zip
npm install --prefix server
npm install --prefix client && npm run build --prefix client
node server/src/bin/migrate.js          # 自动跑 18 个 SQL
pm2 start server/src/bin/serve.js --name carlog
# Nginx 反代 127.0.0.1:8787

数据库配置走 .env

DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=carlog
DB_PASSWORD=xxx
DB_NAME=carlog
SESSION_SECRET=random-32-bytes

默认账号

admin / carwash2026。登录后到「设置 → 账户」改密码。

测试

npm test

当前 101 个测试全过。覆盖 CSRF / 登录锁定 / IP 限流 / CRUD / 标签 / 通知 / 提醒 / 同比 / stats 等。

一些坑(避免后人踩)

  • DB 用 mysql2 timezone: 'Z',所有 server 端 DATETIME 字符串必须用 getUTCHours() 等 UTC 方法,别用本地时区。否则锁定时间会错 8 小时。
  • Pinia setup store 的 ref 在 store proxy 上自动解包,外部调用用 store.ref = x别写 store.ref.value = x
  • 1×1 透明 PNG68 字节)会被 MiniMax 内容审查判敏感,OCR 测试图必须用真实上传图。
  • mysql2 pool 默认不开 enableKeepAliveidle 连接会被 MySQL wait_timeout 杀掉,下次 query 报 ETIMEDOUT。已开 keepAlive + 自动 retry。

仓库

https://gitea.img2img.com/wsh5485/CarLog

License

MIT

S
Description
No description provided
0
Readme 530 KiB
Languages
JavaScript 52.8%
Vue 46.2%
CSS 0.7%
HTML 0.3%