docs: 完成前端、移动端、平台支撑核心文档建设,建立全量开发者文档体系
This commit is contained in:
@@ -17,4 +17,27 @@
|
||||
- **应用层只能向下依赖**:`apps` 里的代码可以依赖 `packages/*` 里的代码,但 `packages` 里的代码绝对不能反向依赖 `apps` 里的任何东西。
|
||||
|
||||
### 2. `packages` 共享层
|
||||
共享层是沉淀业务无关
|
||||
共享层是沉淀业务无关的基础组件和工具的地方:
|
||||
- `components`:通用 UI 组件(如自定义 Table、Upload)。
|
||||
- `utils`:纯函数工具类(日期格式化、树结构转换)。
|
||||
- `types`:全局 TypeScript 接口定义。
|
||||
- `stores`:全局状态(不包含业务状态)。
|
||||
|
||||
**红线规定:**
|
||||
- **Dumb 组件隔离**:`packages/components` 下的组件必须是“Dumb Component(木偶组件)”。它们只通过 `props` 接收数据,通过 `emits` 抛出事件。
|
||||
- **禁止网络请求**:共享层组件**严禁直接发起 Axios 请求**,也**严禁耦合 Pinia 状态**。如果一个组件自己去调了后端的 `/api/v1/xxx`,它就必须被移出 `packages`,放到 `apps` 的对应 `views/` 目录下!
|
||||
|
||||
## 二、业务视图分域(Views)
|
||||
|
||||
前端的 `views` 目录,禁止按照“列表页、详情页、表单页”这种视觉逻辑平铺。
|
||||
**必须与后端的微服务领域保持 1:1 对齐**:
|
||||
|
||||
```
|
||||
views/
|
||||
├── system/ # 对应 module-system(用户、角色、字典)
|
||||
├── infra/ # 对应 module-infra(定时任务、代码生成)
|
||||
├── ops/ # 对应 module-ops(工单、巡检、排班)
|
||||
└── iot/ # 对应 module-iot(设备监控、物模型、规则引擎)
|
||||
```
|
||||
|
||||
**好处**:当后端 `module-ops` 发生 API 变更或状态机修改时,前端开发者可以明确知道该去改 `views/ops/`,缩小爆炸半径。
|
||||
43
开发者文档/04-前端开发/02-API交互与状态管理规范.md
Normal file
43
开发者文档/04-前端开发/02-API交互与状态管理规范.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# 02-API交互与状态管理规范
|
||||
|
||||
前端对接后端的 API 层是协作矛盾的高发地。本系统通过强类型的 API 封装和严格的状态管理原则来约束开发。
|
||||
|
||||
## 一、API 封装规范
|
||||
|
||||
### 1. 绝对禁止在页面内联请求
|
||||
**错误示范(打回重构):**
|
||||
```typescript
|
||||
// 在 view/ops/TicketList.vue 中
|
||||
axios.get('/api/ops/ticket/list').then(...)
|
||||
```
|
||||
|
||||
**正确规范:**
|
||||
1. 所有请求必须在 `api/` 目录下按业务域归类集中管理。
|
||||
2. 页面中只允许调用 `import { getTicketList } from '@/api/ops/ticket'`。
|
||||
|
||||
### 2. 强制 TypeScript 契约
|
||||
- 后端 Swagger/YApi 中更新了接口契约,前端必须在 `api/` 下定义对应的 `ReqVO` 和 `RespVO`。
|
||||
- **禁止 AnyScript**:不允许在 API 响应处使用 `any` 糊弄。任何因为 `any` 导致的线上字段报错(如后端改了驼峰命名前端没发现),由前端开发者负全责。
|
||||
|
||||
## 二、Pinia 状态管理瘦身原则
|
||||
|
||||
很多前端项目后期变卡的罪魁祸首是“把所有东西都塞进全局 Store”。
|
||||
|
||||
### 1. 什么数据可以进 Pinia
|
||||
- 登录用户信息、Token。
|
||||
- 字典数据(静态常量、枚举值)。
|
||||
- 用户动态路由和菜单树。
|
||||
- 全局主题与布局配置。
|
||||
|
||||
### 2. 什么数据禁止进 Pinia
|
||||
- 列表的翻页数据(`pageNum`, `pageSize`, `total`)。
|
||||
- 表单编辑的中间脏状态。
|
||||
- 特定页面的业务缓存。
|
||||
|
||||
**红线**:业务页面的状态闭环必须保留在 Vue 的 Composition API(`ref`, `reactive`)中,页面销毁时数据必须自然回收,禁止污染全局 Store。
|
||||
|
||||
## 三、统一异常与提示拦截
|
||||
|
||||
- 业务层报错(HTTP 200,但后端 `Result.code != 0`):统一在 Axios Interceptor 中拦截并抛出 `Message.error`。页面代码中只需关注 `if (res.code === 0)` 的正常逻辑。
|
||||
- 鉴权失败(HTTP 401):拦截器统一清除 Token 并强跳登录页。
|
||||
- 禁止在每个页面的 `catch` 块里手写 `alert('请求失败')`,保持交互一致性。
|
||||
47
开发者文档/04-前端开发/03-RBAC权限控制与开发规范.md
Normal file
47
开发者文档/04-前端开发/03-RBAC权限控制与开发规范.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 03-RBAC权限控制与开发规范
|
||||
|
||||
管理后台的安全性要求极高,权限控制必须做实做细,严禁“靠隐藏按钮防黑客”。
|
||||
|
||||
## 一、动态路由基础
|
||||
|
||||
系统的左侧菜单树并非前端写死,而是基于用户的角色权限,登录后从后端 `system/menu/get-routers` 接口动态获取并挂载(addRoute)。
|
||||
|
||||
- **无权限的页面,连路由都不存在**,前端访问直接 404,不依赖后端的接口拦截兜底。
|
||||
|
||||
## 二、按钮级细粒度权限 (`v-hasPermi`)
|
||||
|
||||
前端通过自定义指令进行页面内部按钮的显隐控制。
|
||||
|
||||
### 1. 标准用法
|
||||
在需要验权的按钮上使用 `v-hasPermi`,绑定后端统一定义的权限标识(Permission String)。
|
||||
|
||||
```html
|
||||
<!-- 正确:有修改工单权限才显示按钮 -->
|
||||
<a-button v-hasPermi="['ops:ticket:update']" @click="handleEdit">编辑</a-button>
|
||||
|
||||
<!-- 错误:硬编码角色名判断(严禁) -->
|
||||
<a-button v-if="userStore.role === 'admin'">编辑</a-button>
|
||||
```
|
||||
|
||||
**为什么严禁硬编码角色名?**
|
||||
由于系统的 RBAC 支持动态分配权限给任意角色,一旦写死 `role === 'admin'`,如果某天产品要求普通运维主管也能编辑工单,前端就得发版改代码。通过权限标识解耦,只需后端改一条配置即可。
|
||||
|
||||
### 2. JS 逻辑内的权限判断
|
||||
对于不能使用指令的场景(如表格内基于权限动态渲染列、或者触发隐藏逻辑),使用官方提供的 `usePermission` Hook:
|
||||
|
||||
```typescript
|
||||
import { usePermission } from '@/hooks/web/usePermission'
|
||||
const { hasPermission } = usePermission()
|
||||
|
||||
if (hasPermission('ops:ticket:audit')) {
|
||||
// 执行审核相关前端逻辑
|
||||
}
|
||||
```
|
||||
|
||||
## 三、权限配置同步规范
|
||||
|
||||
当后端新增了一个接口并打上了 `@PreAuthorize("@ss.hasPermi('iot:device:reboot')")` 注解时:
|
||||
|
||||
1. **必须在 SQL 初始化脚本中补充该菜单/按钮记录**。
|
||||
2. 前端无需发版,系统管理员在界面分配该权限后,前端 `v-hasPermi` 自动生效。
|
||||
3. **禁止前端私造权限标识**,所有标识字符串必须与后端 Controller 对齐。
|
||||
39
开发者文档/05-移动端开发/02-硬件交互与弱网离线策略.md
Normal file
39
开发者文档/05-移动端开发/02-硬件交互与弱网离线策略.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 02-硬件交互与弱网离线策略
|
||||
|
||||
在 AIOT 场景下,移动端(手机/智能工牌)往往面临地下室、机房等极度恶劣的网络环境。
|
||||
如果把移动端写成“点一下请求一次接口,报错就白屏”,现场人员将无法工作。
|
||||
|
||||
## 一、双重定位与防伪打卡机制
|
||||
|
||||
Ops 领域的巡检与到岗打卡不依赖单一的 GPS,而是通过 LBS + Beacon 混合实现。前端必须配合以下策略:
|
||||
|
||||
### 1. LBS 室外粗筛
|
||||
- **获取方式**:调用 `uni.getLocation`。
|
||||
- **作用**:判断人员是否在大致的作业园区(如距离目标点 500 米内)。前端可以在调用接口前直接进行经纬度计算,粗筛不通过直接提示,不发无效请求。
|
||||
|
||||
### 2. 蓝牙信标 (BEACON) 室内精核
|
||||
这是防作弊的核心。
|
||||
- **获取方式**:调用 `uni.openBluetoothAdapter` 与 `uni.startBluetoothDevicesDiscovery`。
|
||||
- **上报数据**:前端不需要做解密,只需把扫描到的周边信标 MAC 地址集合及其 RSSI(信号强度)打包为 `DetectedBeaconVO` 数组。
|
||||
- **动作约束**:前端必须在点击【到达现场】或【提交巡检】的**那一刻**,将蓝牙列表作为必填 payload 一起提交给后端 `verifyLocation`,绝不允许前端自己判定成功就放行。
|
||||
|
||||
## 二、防抖与幂等重试(弱网防线)
|
||||
|
||||
### 1. UI 层强防抖
|
||||
保洁员在手套潮湿或网络卡顿时,可能会疯狂连点“完工”按钮。
|
||||
- **规范**:所有提交类按钮(Submit, Accept, Complete),必须使用 `loading` 状态。一旦点击,立即 `disabled`,直到接口返回(无论成功还是 HTTP 超时抛错)才恢复。
|
||||
|
||||
### 2. 弱网下的离线写操作队列 (Action Queue)
|
||||
针对地下车库等偶发断网场景:
|
||||
- 对于非阻断型操作(如“记录一项巡检正常”),如果请求超时,前端应将操作序列化存入 `Storage`(离线队列)。
|
||||
- 当网络恢复(监听到 `onNetworkStatusChange` 变为 online),或者用户回到首页时,前端静默将离线队列中的积压操作异步批量上报。
|
||||
- ⚠️ 注意:工单接单、完工等**强状态扭转**操作不支持离线缓存,必须强联网。
|
||||
|
||||
## 三、基础数据本地化缓存
|
||||
|
||||
避免每次打开 App 都看到漫长的骨架屏。
|
||||
|
||||
- **`Stale-while-revalidate` 策略**:
|
||||
对于系统字典库(如保洁类型、异常原因枚举)以及用户的基本权限树,移动端应在成功登录后写入 `Storage`。
|
||||
下次冷启动时,**先用本地缓存渲染界面**,同时在后台静默请求最新数据。如果有更新,再静默替换缓存。
|
||||
- **大图压缩**:保洁对比照、安保异常现场照,严禁直接上传几 MB 的原图。前端必须调用 `uni.compressImage` 压缩后再走 OSS 上传接口,这在弱网下是保命机制。
|
||||
@@ -1,8 +1,20 @@
|
||||
# 支撑平台总览
|
||||
# 00-支撑平台总览
|
||||
|
||||
## 目标与面向读者
|
||||
介绍 DevOps、运维部署及中间件相关的内容。
|
||||
本文档是 AIOT 系统的中间件、DevOps 流水线及底层支撑组件(Framework)的全局说明。
|
||||
支撑平台为 Ops 和 IoT 提供弹药,自身不包含业务逻辑,但它定下了全团队必须遵守的架构红线。
|
||||
|
||||
## 后续规划
|
||||
- 补充 CI/CD 流程说明。
|
||||
- 补充 Redis、RabbitMQ/Kafka 等中间件的使用规范。
|
||||
## 一、支撑范围与定位
|
||||
|
||||
- **微服务底座**:`viewsh-gateway`(唯一流量入口)与 `viewsh-framework`(安全/缓存/日志组件)。
|
||||
- **中间件依赖**:Nacos(服务发现/配置中心)、Redis(高频状态缓存/分布式锁)、消息队列(解耦/削峰/大数据流)。
|
||||
- **CI/CD 流水线**:代码从 Git 提交到容器化上线的整套标准化流程。
|
||||
- **数据库设计**:MySQL 的逻辑表结构及分域管理。
|
||||
|
||||
## 二、阅读指引
|
||||
|
||||
任何后端开发在引入新的组件依赖、修改系统配置前,必须遵守以下核心规约:
|
||||
|
||||
1. **[[01-统一网关入口规范.md]]**:明确所有 API 请求的流量入口和鉴权控制。
|
||||
2. **[[02-中间件使用规约.md]]**:明确 Redis 命名规范、Kafka 与 RabbitMQ 的适用场景,以及 Nacos 配置项的外置化红线。
|
||||
3. **[[03-CICD与部署流水线规范.md]]**:研发环境到生产环境的打包规范,明确禁止任何形式的手工构建产物直上生产。
|
||||
4. **[[08-数据库/01-数据域划分与表关系思路.md]]**:MySQL 的基础结构约定与关联查询底线。
|
||||
24
开发者文档/06-平台支撑/01-统一网关入口规范.md
Normal file
24
开发者文档/06-平台支撑/01-统一网关入口规范.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# 01-统一网关入口规范
|
||||
|
||||
在微服务架构下,`viewsh-gateway` 是系统对外的唯一防线。
|
||||
|
||||
## 一、路由分发与黑白名单
|
||||
|
||||
网关基于 Spring Cloud Gateway,拦截所有的客户端 HTTP/HTTPS 请求。
|
||||
- **内部调用**:内部微服务之间的调用(如 `module-ops` 调 `module-system`)虽然通常走 Feign Client,但如果外部调用 API,必须先通过网关。
|
||||
- **白名单机制**:只有极少数接口(如 `/api/auth/login`、`/api/device/webhook`,或者微信小程序的回调)被允许放入无需 Token 校验的配置白名单中。任何开发者新写一个免密接口,必须向架构负责人报备并在 Nacos 网关配置中显式放行。
|
||||
|
||||
## 二、统一鉴权与 Token 透传
|
||||
|
||||
我们采用 JWT 作为全局身份凭证。
|
||||
网关会统一提取 Authorization 头的 Bearer Token,并在网关层验证其合法性(防篡改、是否过期)。
|
||||
|
||||
**红线规定:**
|
||||
1. 网关验证通过后,负责将解析出的 `userId`、`tenantId`(多租户场景)通过内部 HTTP Header `X-User-Id` 等字段**透传**给下游业务微服务。
|
||||
2. **微服务不要自己去解 JWT**。业务逻辑层直接通过 `viewsh-framework` 中封装好的 `SecurityFrameworkUtils.getLoginUserId()` 获取上下文信息。如果业务服务自己拦截报错说解不出 Token,通常是网关的 Filter 没配好或透传漏了。
|
||||
|
||||
## 三、限流与熔断降级
|
||||
|
||||
系统接入了 Sentinel 或 Redis 限流组件(根据配置)。
|
||||
1. 对高频接口(特别是 Ops 的并发抢单、移动端的密集心跳)配置 QPS 阈值。
|
||||
2. 当某微服务不可用(如 `module-iot` 宕机)时,网关必须配置友好的 Fallback 降级提示(返回标准的 `ErrorCodeConstants`),绝对禁止向前端直接抛出 `503 Service Unavailable` 或 `502 Bad Gateway` 的白屏堆栈。
|
||||
35
开发者文档/06-平台支撑/02-中间件使用规约.md
Normal file
35
开发者文档/06-平台支撑/02-中间件使用规约.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# 02-中间件使用规约
|
||||
|
||||
## 一、Nacos 配置外置化铁律
|
||||
|
||||
在本项目中,Nacos 不仅做服务注册发现,更是全平台的统一配置中心。
|
||||
|
||||
**强制红线:**
|
||||
1. 代码仓库中的 `application.yaml` 或 `bootstrap.yml` 只能保留**最基础的引导信息**(应用名、Nacos Server 地址、当前 Profile 环境:dev/test/prod)。
|
||||
2. **任何包含敏感信息的配置**(数据库账号密码、Redis 密码、第三方支付 Key、MQTT Broker 鉴权秘钥)**必须全部存放在 Nacos 配置中心**。
|
||||
3. 若新开发功能引入了新的配置项,必须在 PR 中同步提交 Nacos 配置变更说明。否则由于缺配置导致流水线部署失败的,直接打回。
|
||||
|
||||
## 二、Redis 规范与防雪崩
|
||||
|
||||
Redis 在 AIOT 系统中承担着两重重任:一个是高频查询缓存(如字典、基础数据),另一个是并发控制与状态存储(如 `ops:grab:lock:` 抢单锁、设备在线状态的心跳)。
|
||||
|
||||
### 1. Key 命名规范
|
||||
所有存入 Redis 的 Key 必须按业务模块加上冒号分层,绝不能随意平铺。
|
||||
- 格式:`{系统标识}:{模块名}:{实体名}:{具体属性}`
|
||||
- 示例:`aiot:ops:ticket:grab_lock:1002`
|
||||
|
||||
### 2. 严禁使用大 Key 与无过期时间
|
||||
- **防雪崩与击穿**:写入缓存的数据必须带有随机波动的 TTL(过期时间),如 `24小时 + Random(0~30)分钟`,避免大量 Key 在同一秒失效导致请求砸穿 MySQL。
|
||||
- 存储长文本或巨型 JSON 数组时,考虑是否真的必须使用 Redis。
|
||||
|
||||
## 三、RabbitMQ 与 Kafka 的适用场景隔离
|
||||
|
||||
作为解耦和异步处理的核心,我们区分两套消息队列的定位(根据具体部署情况选型,但逻辑必须隔离):
|
||||
|
||||
1. **RabbitMQ / RocketMQ (业务消息首选)**
|
||||
- **特点**:支持延迟队列、死信队列(DLX)、高可靠事务消息。
|
||||
- **场景**:适用于 Ops 业务。例如:“工单派发后 15 分钟未接单触发超时退回”(延迟消息),“巡检不合格异步定责后生成整改单”(业务解耦)。
|
||||
|
||||
2. **Kafka (数据管道首选)**
|
||||
- **特点**:超高吞吐量,顺序写入。
|
||||
- **场景**:适用于 IoT 业务。例如:“网关每秒接收 10000 台设备上报的温湿度遥测数据”(Telemetry),需要进行实时流式计算或清洗入库时。严禁拿 Kafka 去做复杂的带重试的业务工单分发。
|
||||
42
开发者文档/06-平台支撑/03-CICD与部署流水线规范.md
Normal file
42
开发者文档/06-平台支撑/03-CICD与部署流水线规范.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 03-CICD与部署流水线规范
|
||||
|
||||
稳定的构建与发布是保证项目质量的关键。任何绕过标准流程的手工“热修补”都是系统崩坏的开始。
|
||||
|
||||
## 一、分支管理与集成策略
|
||||
|
||||
本项目采用改良的 Git Flow 模型:
|
||||
|
||||
1. **`master` 分支 (基线与生产)**:
|
||||
- 绝对受保护的分支,禁止任何人直接 `push` 或在本地修改。
|
||||
- 只有测试通过的 Release 或 Hotfix 分支才能 Merge 进 `master`。
|
||||
- 任何提交合并至 `master`,必须伴随对应版本号(Tag)的打入。
|
||||
|
||||
2. **`feat/` 与 `fix/` 分支 (日常开发)**:
|
||||
- 任何新需求,必须基于最新的 `master` 切出 `feat/工单号-需求简述`。
|
||||
- 开发完成并自测后,提交 Merge Request (MR) / Pull Request (PR)。
|
||||
|
||||
3. **`test` 分支 (提测验证)**:
|
||||
- 开发者将功能合入 `test` 分支,由 Jenkins 自动触发构建部署到测试环境。
|
||||
|
||||
## 二、禁止手工打包与直连生产
|
||||
|
||||
**红线规定:**
|
||||
1. **绝对禁止**研发在本地执行 `mvn clean package` 或 `pnpm build` 后,通过 FTP/SCP 将 JAR 包或 `dist/` 压缩包直接丢到服务器上运行!
|
||||
2. 所有的制品(Artifacts),必须由 Jenkins / GitLab CI 等流水线平台统一拉取 Git 代码进行构建。
|
||||
3. 任何对服务器的环境修改,必须固化在 `Dockerfile` 和 CI 脚本(如 `Jenkinsfile`)中,确保环境可复现。
|
||||
|
||||
## 三、流水线关键检查节点
|
||||
|
||||
一个合规的后端/前端构建流水线,必须包含(或规划接入)以下节点:
|
||||
|
||||
1. **编译检查**:确保代码能成功通过 `maven compile` 或 `tsc --noEmit`。
|
||||
2. **代码质量扫描 (SonarQube)**:
|
||||
- 如果新增代码引入了 Blocker 级别漏洞(如硬编码的密码、明显的 SQL 注入拼接),流水线直接熔断变红,不允许部署。
|
||||
3. **单元测试 (如有)**:对于核心的 Ops 抢单逻辑、IoT 规则引擎,如果在 CI 跑挂了单测,不允许进入镜像构建环节。
|
||||
4. **Docker 镜像构建与发布**:
|
||||
- 镜像必须打上当前的 Commit Hash 或业务版本号(如 `viewsh-server:v1.2.0-a8b4f`),绝不能一直覆盖推送名为 `latest` 的 Tag,这会导致回滚时无法找到上一个稳定版本。
|
||||
|
||||
## 四、优雅停机与无损发布
|
||||
|
||||
- Spring Boot 服务在容器化部署时,必须开启优雅停机(Graceful Shutdown)配置。
|
||||
- 保证当容器收到 `SIGTERM` 信号(如发布新版本杀老进程)时,已经进入网关的 HTTP 请求或正在被处理的 MQ 消息能处理完再销毁进程,避免工单处理到一半因为上线而状态丢失。
|
||||
Reference in New Issue
Block a user