From a702235244fe64479db9974ccda3659c94012e73 Mon Sep 17 00:00:00 2001 From: lzh Date: Tue, 7 Apr 2026 01:53:41 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=AE=8C=E6=88=90=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E3=80=81=E7=A7=BB=E5=8A=A8=E7=AB=AF=E3=80=81=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E6=94=AF=E6=92=91=E6=A0=B8=E5=BF=83=E6=96=87=E6=A1=A3=E5=BB=BA?= =?UTF-8?q?=E8=AE=BE=EF=BC=8C=E5=BB=BA=E7=AB=8B=E5=85=A8=E9=87=8F=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E8=80=85=E6=96=87=E6=A1=A3=E4=BD=93=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../04-前端开发/01-前端工程结构与协作边界.md | 25 +++++++++- .../04-前端开发/02-API交互与状态管理规范.md | 43 +++++++++++++++++ .../04-前端开发/03-RBAC权限控制与开发规范.md | 47 +++++++++++++++++++ .../05-移动端开发/02-硬件交互与弱网离线策略.md | 39 +++++++++++++++ 开发者文档/06-平台支撑/00-支撑平台总览.md | 24 +++++++--- 开发者文档/06-平台支撑/01-统一网关入口规范.md | 24 ++++++++++ 开发者文档/06-平台支撑/02-中间件使用规约.md | 35 ++++++++++++++ .../06-平台支撑/03-CICD与部署流水线规范.md | 42 +++++++++++++++++ 8 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 开发者文档/04-前端开发/02-API交互与状态管理规范.md create mode 100644 开发者文档/04-前端开发/03-RBAC权限控制与开发规范.md create mode 100644 开发者文档/05-移动端开发/02-硬件交互与弱网离线策略.md create mode 100644 开发者文档/06-平台支撑/01-统一网关入口规范.md create mode 100644 开发者文档/06-平台支撑/02-中间件使用规约.md create mode 100644 开发者文档/06-平台支撑/03-CICD与部署流水线规范.md diff --git a/开发者文档/04-前端开发/01-前端工程结构与协作边界.md b/开发者文档/04-前端开发/01-前端工程结构与协作边界.md index fd4a4c3..0879ecd 100644 --- a/开发者文档/04-前端开发/01-前端工程结构与协作边界.md +++ b/开发者文档/04-前端开发/01-前端工程结构与协作边界.md @@ -17,4 +17,27 @@ - **应用层只能向下依赖**:`apps` 里的代码可以依赖 `packages/*` 里的代码,但 `packages` 里的代码绝对不能反向依赖 `apps` 里的任何东西。 ### 2. `packages` 共享层 -共享层是沉淀业务无关 \ No newline at end of file +共享层是沉淀业务无关的基础组件和工具的地方: +- `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/`,缩小爆炸半径。 \ No newline at end of file diff --git a/开发者文档/04-前端开发/02-API交互与状态管理规范.md b/开发者文档/04-前端开发/02-API交互与状态管理规范.md new file mode 100644 index 0000000..b758742 --- /dev/null +++ b/开发者文档/04-前端开发/02-API交互与状态管理规范.md @@ -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('请求失败')`,保持交互一致性。 \ No newline at end of file diff --git a/开发者文档/04-前端开发/03-RBAC权限控制与开发规范.md b/开发者文档/04-前端开发/03-RBAC权限控制与开发规范.md new file mode 100644 index 0000000..f8cc45e --- /dev/null +++ b/开发者文档/04-前端开发/03-RBAC权限控制与开发规范.md @@ -0,0 +1,47 @@ +# 03-RBAC权限控制与开发规范 + +管理后台的安全性要求极高,权限控制必须做实做细,严禁“靠隐藏按钮防黑客”。 + +## 一、动态路由基础 + +系统的左侧菜单树并非前端写死,而是基于用户的角色权限,登录后从后端 `system/menu/get-routers` 接口动态获取并挂载(addRoute)。 + +- **无权限的页面,连路由都不存在**,前端访问直接 404,不依赖后端的接口拦截兜底。 + +## 二、按钮级细粒度权限 (`v-hasPermi`) + +前端通过自定义指令进行页面内部按钮的显隐控制。 + +### 1. 标准用法 +在需要验权的按钮上使用 `v-hasPermi`,绑定后端统一定义的权限标识(Permission String)。 + +```html + +编辑 + + +编辑 +``` + +**为什么严禁硬编码角色名?** +由于系统的 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 对齐。 \ No newline at end of file diff --git a/开发者文档/05-移动端开发/02-硬件交互与弱网离线策略.md b/开发者文档/05-移动端开发/02-硬件交互与弱网离线策略.md new file mode 100644 index 0000000..be66cba --- /dev/null +++ b/开发者文档/05-移动端开发/02-硬件交互与弱网离线策略.md @@ -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 上传接口,这在弱网下是保命机制。 \ No newline at end of file diff --git a/开发者文档/06-平台支撑/00-支撑平台总览.md b/开发者文档/06-平台支撑/00-支撑平台总览.md index 5c3a625..90ba31d 100644 --- a/开发者文档/06-平台支撑/00-支撑平台总览.md +++ b/开发者文档/06-平台支撑/00-支撑平台总览.md @@ -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 的基础结构约定与关联查询底线。 \ No newline at end of file diff --git a/开发者文档/06-平台支撑/01-统一网关入口规范.md b/开发者文档/06-平台支撑/01-统一网关入口规范.md new file mode 100644 index 0000000..0858b16 --- /dev/null +++ b/开发者文档/06-平台支撑/01-统一网关入口规范.md @@ -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` 的白屏堆栈。 \ No newline at end of file diff --git a/开发者文档/06-平台支撑/02-中间件使用规约.md b/开发者文档/06-平台支撑/02-中间件使用规约.md new file mode 100644 index 0000000..534711f --- /dev/null +++ b/开发者文档/06-平台支撑/02-中间件使用规约.md @@ -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 去做复杂的带重试的业务工单分发。 \ No newline at end of file diff --git a/开发者文档/06-平台支撑/03-CICD与部署流水线规范.md b/开发者文档/06-平台支撑/03-CICD与部署流水线规范.md new file mode 100644 index 0000000..55ac9d2 --- /dev/null +++ b/开发者文档/06-平台支撑/03-CICD与部署流水线规范.md @@ -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 消息能处理完再销毁进程,避免工单处理到一半因为上线而状态丢失。 \ No newline at end of file