docs: 建立 devdocs 开发文档集(13 份模块文档)
This commit is contained in:
1 parent
3e9592b006
commit
3b3496559b
15 files changed
+1685
-2
No files matched your search
@@ -0,0 +1,169 @@
|
||||
# 03 · 技术选型与架构
|
||||
|
||||
> 所属:运动会积分榜系统 · 开发文档集
|
||||
> 版本:v0.1(讨论稿) · 2026-09-09
|
||||
> 上游:[README](./README.md) · 相关:[04-数据模型](./04-数据模型.md)、[10-部署与现场方案](./10-部署与现场方案.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 技术选型
|
||||
|
||||
### 1.1 候选方案对比
|
||||
|
||||
| 维度 | A. Node + TS + Fastify + Socket.IO | B. Go 单二进制 | C. Python + FastAPI |
|
||||
| --- | --- | --- | --- |
|
||||
| 实时推送 | Socket.IO 成熟(房间/重连/降级) | 需自己写重连与降级 | WebSocket 原生,重连自己写 |
|
||||
| 前端生态 | 最强(Vue / Element Plus / 动效库) | 前端仍要 Node 构建 | 同左 |
|
||||
| 现场部署 | 需装 Node 运行时 | **单文件,最优** | 需装 Python + 依赖 |
|
||||
| 原生依赖风险 | better-sqlite3 需预编译二进制 | 纯 Go SQLite,无 cgo | 无 |
|
||||
| 开发效率 | 高 | 中 | 中 |
|
||||
| 单赛事规模(≤300 人、≤50 小项) | 绰绰有余 | 绰绰有余 | 绰绰有余 |
|
||||
|
||||
### 1.2 ✅ 建议结论
|
||||
|
||||
**主方案 A:Node.js 22 + TypeScript + Fastify + Socket.IO + SQLite + Vue 3 + Vite + Pinia。**
|
||||
|
||||
理由:
|
||||
|
||||
1. 本项目 90% 的复杂度在**两个前端界面 + 实时同步**,Node 生态在这块最省事。
|
||||
2. 数据规模极小(几百行成绩),SQLite 同步读写完全够用,`better-sqlite3` 性能过剩。
|
||||
3. 单一语言贯穿前后端,类型可共享(前后端共用 `shared/types`),减少字段对不上的低级错误。
|
||||
4. 部署难点(运行时)可用「绿色部署包」化解:Node 运行时 + 构建产物 + 启动脚本打包,现场解压双击即可,见 [10-部署与现场方案](./10-部署与现场方案.md)。
|
||||
|
||||
**降级条件**:若现场主机无法运行 Node(极端受限环境),切方案 B。**切换成本主要在服务端,前端可完全复用**,因此架构上把「领域逻辑」与「运行时」隔离,便于将来移植。
|
||||
|
||||
### 1.3 关键依赖(初稿,编码时锁版本)
|
||||
|
||||
**服务端**
|
||||
|
||||
| 依赖 | 用途 | 备注 |
|
||||
| --- | --- | --- |
|
||||
| `fastify` | HTTP 框架 | 比 Express 快、TS 友好、插件体系清晰 |
|
||||
| `@fastify/static` | 托管前端构建产物 | 单端口对外 |
|
||||
| `@fastify/cookie` + `@fastify/csrf-protection` | 会话与 CSRF | 若用 cookie 会话 |
|
||||
| `socket.io` | 实时推送 | 房间、自动重连 |
|
||||
| `better-sqlite3` | SQLite 驱动 | 同步 API,简单可靠;备选 `node:sqlite` |
|
||||
| `zod` | 入参校验 | 与前端共享 schema |
|
||||
| `argon2` / `bcrypt` | 密码哈希 | 优先 argon2id |
|
||||
| `exceljs` | Excel 导出 | 导出成绩册 |
|
||||
| `pino` | 日志 | Fastify 默认 |
|
||||
| `vitest` | 单元测试 | 与 Vite 同族 |
|
||||
|
||||
**前端**
|
||||
|
||||
| 依赖 | 用途 |
|
||||
| --- | --- |
|
||||
| `vue` 3 + `vite` + `typescript` | 基础 |
|
||||
| `pinia` | 状态管理 |
|
||||
| `vue-router` | 管理端路由 |
|
||||
| `element-plus` | 管理端组件库(表格/表单/对话框) |
|
||||
| `socket.io-client` | 实时客户端 |
|
||||
| `dayjs` | 时间处理 |
|
||||
| `@vueuse/core` | 常用组合式工具 |
|
||||
|
||||
> 大屏端**不用组件库**,手写 CSS(设计令牌待视觉定稿,见 D13),保证视觉可控与渲染性能。
|
||||
|
||||
---
|
||||
|
||||
## 2. 系统架构
|
||||
|
||||
### 2.1 部署拓扑
|
||||
|
||||
```
|
||||
┌──────────────────────────────┐
|
||||
│ 现场主机(唯一服务端) │
|
||||
│ │
|
||||
大屏机 A ──HTTP──▶│ Node 进程 │
|
||||
(Chrome kiosk) │ ├─ HTTP API (/api) │
|
||||
│ ├─ 静态资源 (/display /admin)│
|
||||
大屏机 B ──HTTP──▶│ ├─ Socket.IO (/socket.io) │
|
||||
│ └─ SQLite (data/scoreboard.db)│
|
||||
平板/笔记本 ─HTTP─▶│ │
|
||||
(管理面板) └──────────────────────────────┘
|
||||
│
|
||||
└── data/backups/ 自动备份
|
||||
```
|
||||
|
||||
- **单进程、单端口**,不引入 Nginx / Redis / 消息队列——现场少一个组件就少一个故障点。
|
||||
- 大屏机与管理端都是浏览器,不需要额外安装客户端。
|
||||
|
||||
### 2.2 服务端模块划分
|
||||
|
||||
```
|
||||
server/src/
|
||||
├── main.ts 启动、装配、优雅退出
|
||||
├── config.ts 配置(端口/路径/赛事默认值),支持环境变量覆盖
|
||||
├── db/
|
||||
│ ├── client.ts 连接、PRAGMA(WAL/foreign_keys/busy_timeout)
|
||||
│ ├── migrations/ 版本化迁移(001_init.sql …)
|
||||
│ └── seed.ts 首次运行初始化(默认管理员、默认积分模板)
|
||||
├── domain/ ★纯逻辑,无 IO,最需要测试
|
||||
│ ├── scoring/ 名次→积分、并列处理、权重
|
||||
│ ├── standings/ 总分聚合、排序、tie-break、奖牌计数
|
||||
│ ├── records/ 纪录比较与破纪录判定
|
||||
│ └── ledger/ 积分流水的追加/作废/重算
|
||||
├── services/ 事务编排(domain + db)
|
||||
├── routes/ HTTP 接口层(薄)
|
||||
├── realtime/ Socket.IO:房间、快照、增量、心跳
|
||||
├── middleware/ 认证、权限、审计、错误处理、限流
|
||||
└── util/
|
||||
```
|
||||
|
||||
**原则**:`domain/` 不 import 任何 fastify / socket.io / sqlite,输入输出都是普通对象。这样积分规则能被彻底单测,也方便将来移植到 Go。
|
||||
|
||||
### 2.3 数据流(一次成绩发布)
|
||||
|
||||
```
|
||||
HTTP POST /api/results/publish
|
||||
→ 校验权限 + 校验入参(zod)
|
||||
→ 开启事务
|
||||
├─ 写入/更新 results
|
||||
├─ 作废旧积分流水,追加新流水
|
||||
├─ 重算受影响单位的总分与名次
|
||||
├─ 写 change_log(version++)
|
||||
└─ 写 audit_log
|
||||
→ 事务提交
|
||||
→ realtime.broadcast(version, changes)
|
||||
├─ room "display" → 大屏
|
||||
└─ room "admin" → 其他管理端(多人协作时保持同步)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 目录结构
|
||||
|
||||
```
|
||||
Scoreboard/
|
||||
├── devdocs/ # 本文档集
|
||||
├── server/ # Node + TS 服务端
|
||||
│ ├── src/{db,domain,services,routes,realtime,middleware,util}
|
||||
│ ├── tests/
|
||||
│ └── package.json
|
||||
├── web/ # Vue 3 + Vite
|
||||
│ ├── src/
|
||||
│ │ ├── shared/ # 类型、API 客户端、Socket 客户端、设计令牌
|
||||
│ │ ├── display/ # 大屏入口
|
||||
│ │ └── admin/ # 管理端入口
|
||||
│ ├── display.html
|
||||
│ ├── admin.html
|
||||
│ └── index.html # 导航页
|
||||
├── deploy/ # systemd / 启动脚本 / 打包脚本
|
||||
├── data/ # 运行时数据(gitignore)
|
||||
├── package.json # pnpm workspace 根
|
||||
├── pnpm-workspace.yaml
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 编码规范
|
||||
|
||||
| 项 | 约定 |
|
||||
| --- | --- |
|
||||
| TypeScript | `strict: true`;前后端共享类型放 `web/src/shared` 或独立 `shared/` 包 |
|
||||
| 命名 | 数据库表/字段 `snake_case`,TS 变量 `camelCase`,组件 `PascalCase` |
|
||||
| 提交信息 | Conventional Commits(`feat:` / `fix:` / `docs:` / `test:` / `chore:`) |
|
||||
| 分支 | `main` 保护,功能分支 `feat/xxx` |
|
||||
| 代码风格 | Prettier + ESLint,提交前 lint-staged 校验 |
|
||||
| 分层红线 | `domain/` 禁止引入 IO 依赖(见 2.2) |
|
||||
| 注释 | 只在解释「为什么」时写;不写复述代码的注释 |
|
||||
Reference in new issue
Block a user