280 lines
4.5 KiB
Markdown
280 lines
4.5 KiB
Markdown
# 03 技术架构
|
||||
|
|
|
|||
|
|
## 1. 总体选择
|
|||
|
|
|
|||
|
|
优先采用“TypeScript 全栈 + 模块化单体 + MySQL + Redis + 对象存储 + Docker”。
|
|||
|
|
|
|||
|
|
推荐:
|
|||
|
|
|
|||
|
|
### 微信小程序
|
|||
|
|
|
|||
|
|
- 微信小程序原生框架
|
|||
|
|
- TypeScript
|
|||
|
|
- TDesign Miniprogram(优先复用成熟组件)
|
|||
|
|
- 自建 API Client
|
|||
|
|
- 不使用重量级跨端框架作为 V1 默认方案
|
|||
|
|
|
|||
|
|
### 管理后台
|
|||
|
|
|
|||
|
|
- Vue 3
|
|||
|
|
- TypeScript
|
|||
|
|
- Vite
|
|||
|
|
- Pinia
|
|||
|
|
- Vue Router
|
|||
|
|
- TDesign Vue Next 或成熟国内 UI 组件库
|
|||
|
|
- ECharts(仅统计图表需要时)
|
|||
|
|
|
|||
|
|
### API
|
|||
|
|
|
|||
|
|
- Node.js LTS
|
|||
|
|
- NestJS
|
|||
|
|
- TypeScript
|
|||
|
|
- REST API
|
|||
|
|
- Prisma 或 TypeORM 二选一;建议 Prisma,但一旦项目启动后不得混用
|
|||
|
|
- OpenAPI/Swagger
|
|||
|
|
- Zod/class-validator 统一选一种 DTO 校验体系,NestJS 默认可使用 class-validator
|
|||
|
|
|
|||
|
|
### 数据
|
|||
|
|
|
|||
|
|
- MySQL 8.x
|
|||
|
|
- Redis 7.x
|
|||
|
|
- 对象存储:腾讯云 COS 为生产默认实现
|
|||
|
|
- 本地开发:MinIO 兼容 S3 API
|
|||
|
|
|
|||
|
|
### 部署
|
|||
|
|
|
|||
|
|
- Docker
|
|||
|
|
- Docker Compose
|
|||
|
|
- Nginx
|
|||
|
|
- 腾讯云 CVM / 轻量云服务器可作为早期部署载体
|
|||
|
|
- 数据库生产优先托管 MySQL;预算有限时也可独立数据库容器,但必须有可靠备份
|
|||
|
|
- HTTPS
|
|||
|
|
- 国内域名和备案按实际上线要求办理
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 为什么不做微服务
|
|||
|
|
|
|||
|
|
当前机构规模和 V1 业务复杂度不需要微服务。
|
|||
|
|
|
|||
|
|
模块化单体优点:
|
|||
|
|
|
|||
|
|
- 部署简单;
|
|||
|
|
- 成本低;
|
|||
|
|
- 调试简单;
|
|||
|
|
- 事务一致性容易保证;
|
|||
|
|
- Codex 更容易保持全局一致;
|
|||
|
|
- 后续真有规模需求时可按模块拆分。
|
|||
|
|
|
|||
|
|
模块边界仍必须清晰。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. API 模块建议
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
auth
|
|||
|
|
users
|
|||
|
|
profiles
|
|||
|
|
beneficiaries
|
|||
|
|
service-applications
|
|||
|
|
service-cases
|
|||
|
|
service-records
|
|||
|
|
follow-ups
|
|||
|
|
projects
|
|||
|
|
activities
|
|||
|
|
volunteers
|
|||
|
|
content
|
|||
|
|
files
|
|||
|
|
notifications
|
|||
|
|
statistics
|
|||
|
|
audit
|
|||
|
|
permissions
|
|||
|
|
system
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
每模块:
|
|||
|
|
|
|||
|
|
- controller
|
|||
|
|
- service
|
|||
|
|
- repository
|
|||
|
|
- dto
|
|||
|
|
- entities/model
|
|||
|
|
- policy/permission
|
|||
|
|
- tests
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 分层规则
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
Controller
|
|||
|
|
↓
|
|||
|
|
Application Service
|
|||
|
|
↓
|
|||
|
|
Domain Rules / Policy
|
|||
|
|
↓
|
|||
|
|
Repository / Adapter
|
|||
|
|
↓
|
|||
|
|
Database / External Service
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
禁止:
|
|||
|
|
|
|||
|
|
- Controller 直接访问 ORM;
|
|||
|
|
- 页面直接写 SQL;
|
|||
|
|
- 业务层直接调用 COS/微信 SDK;
|
|||
|
|
- 前端自己判断权限代替后端校验。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 外部 Adapter
|
|||
|
|
|
|||
|
|
必须封装:
|
|||
|
|
|
|||
|
|
- WeChatAuthAdapter
|
|||
|
|
- WeChatSubscribeMessageAdapter
|
|||
|
|
- ObjectStorageAdapter
|
|||
|
|
- SmsAdapter(若以后使用)
|
|||
|
|
- AIAdapter(二期)
|
|||
|
|
- GeocodingAdapter(二期)
|
|||
|
|
|
|||
|
|
这样可更换供应商。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. API 规范
|
|||
|
|
|
|||
|
|
统一前缀:
|
|||
|
|
|
|||
|
|
`/api/v1`
|
|||
|
|
|
|||
|
|
响应:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"data": {},
|
|||
|
|
"requestId": "..."
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
错误:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": false,
|
|||
|
|
"error": {
|
|||
|
|
"code": "APPLICATION_NOT_FOUND",
|
|||
|
|
"message": "未找到该服务申请"
|
|||
|
|
},
|
|||
|
|
"requestId": "..."
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
HTTP 状态码必须正确使用,不得永远 200。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 认证
|
|||
|
|
|
|||
|
|
### 小程序端
|
|||
|
|
|
|||
|
|
- wx.login 获取 code;
|
|||
|
|
- 后端换取微信身份;
|
|||
|
|
- 服务端创建自己的 session/token;
|
|||
|
|
- token 轮换/过期;
|
|||
|
|
- 手机号绑定按微信开放能力和实际授权流程实现;
|
|||
|
|
- openid/unionid 绝不作为前端授权依据。
|
|||
|
|
|
|||
|
|
### 后台
|
|||
|
|
|
|||
|
|
推荐:
|
|||
|
|
|
|||
|
|
- 用户名/手机号 + 强密码;
|
|||
|
|
- 生产可增加 MFA;
|
|||
|
|
- HttpOnly Secure Cookie 优先;
|
|||
|
|
- 管理后台不把长期 Token 放 localStorage。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 权限
|
|||
|
|
|
|||
|
|
RBAC + 资源级 Policy。
|
|||
|
|
|
|||
|
|
示例:
|
|||
|
|
|
|||
|
|
- STAFF 可以看自己负责的工单;
|
|||
|
|
- PROJECT_MANAGER 可以看自己项目范围;
|
|||
|
|
- ADMIN 可跨项目;
|
|||
|
|
- VOLUNTEER 只能查看分配给自己的最小必要任务信息;
|
|||
|
|
- 普通小程序用户只能查看自己提交或合法关联的申请。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 状态机
|
|||
|
|
|
|||
|
|
服务申请、工单、活动、志愿者审批必须采用明确状态机。
|
|||
|
|
|
|||
|
|
所有 transition:
|
|||
|
|
|
|||
|
|
- 验证当前状态;
|
|||
|
|
- 验证目标状态;
|
|||
|
|
- 验证权限;
|
|||
|
|
- 事务写入;
|
|||
|
|
- 写 history;
|
|||
|
|
- 写 audit;
|
|||
|
|
- 事务提交后再触发通知。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. 幂等
|
|||
|
|
|
|||
|
|
以下必须防重复:
|
|||
|
|
|
|||
|
|
- 服务申请提交
|
|||
|
|
- 活动报名
|
|||
|
|
- 状态变更
|
|||
|
|
- 服务记录提交
|
|||
|
|
- 回访提交
|
|||
|
|
- 文件关联
|
|||
|
|
- 微信回调(若未来有)
|
|||
|
|
|
|||
|
|
方案:
|
|||
|
|
|
|||
|
|
- clientRequestId / idempotencyKey
|
|||
|
|
- 数据库唯一索引
|
|||
|
|
- 事务
|
|||
|
|
- 必要时 Redis 短锁
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. 可观测性
|
|||
|
|
|
|||
|
|
必须:
|
|||
|
|
|
|||
|
|
- requestId
|
|||
|
|
- structured logging
|
|||
|
|
- error tracking
|
|||
|
|
- health endpoint
|
|||
|
|
- readiness/liveness
|
|||
|
|
- 慢接口日志
|
|||
|
|
- 数据库慢查询
|
|||
|
|
- 关键任务状态
|
|||
|
|
|
|||
|
|
日志中禁止敏感数据。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. 备份
|
|||
|
|
|
|||
|
|
至少:
|
|||
|
|
|
|||
|
|
- MySQL 每日自动备份;
|
|||
|
|
- 保留 7/30 天策略可配置;
|
|||
|
|
- 对象存储版本/生命周期按预算配置;
|
|||
|
|
- 每季度至少做一次恢复演练;
|
|||
|
|
- 恢复步骤写入 `infra/backup/README.md`。
|
|||
|
|
|
|||
|
|
备份成功≠可恢复,必须验证恢复。
|