docs: 移动端开发文档扩展 + 附录术语表/错误码
05-移动端开发: - 01-移动端工程结构与页面分域.md - 补充 UniApp 分包策略(主包 2MB 限制) - 页面路由配置与生命周期规范 - Token 双 Token 无感刷新逻辑 - 内存泄漏防护清单 - 02-硬件交互与弱网离线策略.md - 智能工牌蓝牙通信协议(BadgeStatus/NotifyType) - iBeacon 协议格式与信标配置 - 蓝牙扫描 Hook 实现(useBluetoothScan) - 权限处理与超时机制 08-附录: - 01-术语表.md - IoT 设备术语(工牌、信标、RSSI) - 工单状态机(Mermaid 状态图) - 优先级与触发来源 - 移动端 BLE 术语 - 02-错误码清单.md - 后端统一错误码(全局 + OPS 模块) - 前端 ResultEnum 状态码 - 蓝牙扫描状态与错误处理 - 错误码对照速查表
This commit is contained in:
@@ -38,33 +38,71 @@ aiot-uniapp/
|
||||
│ │ └── helpers.ts # 通用辅助函数
|
||||
│ │
|
||||
│ ├── pages/ # 【主包】核心页面
|
||||
│ │ ├── login/
|
||||
│ │ │ ├── index.vue # 登录页
|
||||
│ │ │ └── auth.vue # 静默授权回调
|
||||
│ │ ├── index/
|
||||
│ │ │ └── index.vue # 工作台首页(Tab Bar)
|
||||
│ │ ├── scan/
|
||||
│ │ │ ├── index.vue # 扫码入口
|
||||
│ │ │ └── bluetooth-debug/ # 蓝牙调试页
|
||||
│ │ ├── user/
|
||||
│ │ │ └── index.vue # 个人中心
|
||||
│ │ └── contact/
|
||||
│ │ └── index.vue # 通讯录
|
||||
│ │
|
||||
│ ├── pages-core/ # 【分包】核心功能(登录、设置)
|
||||
│ │ ├── auth/
|
||||
│ │ │ ├── login.vue # 账号密码登录
|
||||
│ │ │ ├── code-login.vue # 验证码登录
|
||||
│ │ │ └── forget-password.vue
|
||||
│ │ └── user/
|
||||
│ │ └── index.vue # 个人中心
|
||||
│ │ ├── profile/
|
||||
│ │ ├── settings/
|
||||
│ │ └── security/
|
||||
│ │
|
||||
│ ├── pages-ops/ # 【分包】Ops 现场作业
|
||||
│ │ ├── work-order/
|
||||
│ │ │ ├── list.vue # 工单列表
|
||||
│ │ │ ├── index.vue # 工单列表
|
||||
│ │ │ ├── detail.vue # 工单详情
|
||||
│ │ │ ├── arrival.vue # 到岗打卡(信标扫描)
|
||||
│ │ │ └── complete.vue # 完工提交
|
||||
│ │ │ ├── create.vue # 创建工单
|
||||
│ │ │ └── stats.vue # 工单统计
|
||||
│ │ ├── inspection/
|
||||
│ │ │ ├── list.vue # 巡检任务列表
|
||||
│ │ │ ├── scan.vue # 扫码巡检
|
||||
│ │ │ └── record.vue # 巡检记录填报
|
||||
│ │ └── queue/
|
||||
│ │ └── index.vue # 我的队列
|
||||
│ │ │ ├── index.vue # 巡检任务列表
|
||||
│ │ │ ├── detail.vue # 巡检详情
|
||||
│ │ │ └── components/
|
||||
│ │ │ └── bluetooth-verify.vue # 蓝牙信标验证
|
||||
│ │ └── inspection/composables/
|
||||
│ │ └── use-bluetooth-scan.ts # 蓝牙扫描 Hook
|
||||
│ │
|
||||
│ ├── pages-iot/ # 【分包】IoT 设备管理
|
||||
│ │ ├── device/
|
||||
│ │ │ ├── list.vue
|
||||
│ │ │ └── detail.vue
|
||||
│ │ └── alarm/
|
||||
│ │ └── index.vue
|
||||
│ ├── pages-system/ # 【分包】系统管理
|
||||
│ │ ├── area/
|
||||
│ │ ├── dept/
|
||||
│ │ ├── user/
|
||||
│ │ └── dict/
|
||||
│ │
|
||||
│ ├── pages-bpm/ # 【分包】工作流
|
||||
│ │
|
||||
│ ├── pages-infra/ # 【分包】基础设施
|
||||
│ │
|
||||
│ ├── api/ # API 接口定义
|
||||
│ │ ├── ops/ # Ops 业务 API
|
||||
│ │ │ ├── order-center/ # 工单中心
|
||||
│ │ │ ├── cleaning/ # 保洁业务
|
||||
│ │ │ ├── security/ # 安保业务
|
||||
│ │ │ └── inspection/ # 巡检业务
|
||||
│ │ ├── iot/ # IoT 设备 API
|
||||
│ │ ├── system/ # 系统管理 API
|
||||
│ │ └── login.ts # 登录相关 API
|
||||
│ │
|
||||
│ ├── store/ # Pinia 状态管理
|
||||
│ │ ├── token.ts # Token 管理(双 Token 刷新)
|
||||
│ │ ├── user.ts # 用户信息
|
||||
│ │ ├── dict.ts # 字典缓存
|
||||
│ │ └── theme.ts # 主题配置
|
||||
│ │
|
||||
│ ├── http/ # HTTP 请求封装
|
||||
│ │ ├── http.ts # 核心 HTTP 方法
|
||||
│ │ ├── types.ts # 类型定义
|
||||
│ │ └── tools/
|
||||
│ │ └── enum.ts # ResultEnum 状态码
|
||||
│ │
|
||||
│ ├── static/ # 静态资源
|
||||
│ │ ├── images/
|
||||
@@ -94,9 +132,10 @@ aiot-uniapp/
|
||||
|
||||
| 目录 | 说明 | 体积控制 |
|
||||
|-----|------|---------|
|
||||
| `/pages/login/` | 登录、验证码、静默授权页 | < 200KB |
|
||||
| `/pages/index/` | 工作台首页(Tab Bar) | < 300KB |
|
||||
| `/pages/user/` | 个人中心基础设置 | < 100KB |
|
||||
| `/pages/scan/` | 扫码入口 | < 200KB |
|
||||
| `/pages/user/` | 个人中心 | < 100KB |
|
||||
| `/pages/contact/` | 通讯录 | < 150KB |
|
||||
| `components/` | 全局共享的基础 UI 组件库 | < 200KB |
|
||||
|
||||
**严禁将具体的业务流程(如填写工单、扫描设备)塞入主包。**
|
||||
@@ -109,27 +148,36 @@ aiot-uniapp/
|
||||
// pages.json
|
||||
{
|
||||
"pages": [
|
||||
{ "path": "pages/login/index" },
|
||||
{ "path": "pages/index/index" },
|
||||
{ "path": "pages/user/index" }
|
||||
{ "path": "pages/scan/index" },
|
||||
{ "path": "pages/user/index" },
|
||||
{ "path": "pages/contact/index" }
|
||||
],
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "pages-ops",
|
||||
"root": "pages-core",
|
||||
"pages": [
|
||||
{ "path": "work-order/list" },
|
||||
{ "path": "work-order/detail" },
|
||||
{ "path": "work-order/arrival" },
|
||||
{ "path": "inspection/list" },
|
||||
{ "path": "inspection/scan" }
|
||||
{ "path": "auth/login" },
|
||||
{ "path": "auth/code-login" },
|
||||
{ "path": "user/profile/index" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages-iot",
|
||||
"root": "pages-ops",
|
||||
"pages": [
|
||||
{ "path": "device/list" },
|
||||
{ "path": "device/detail" },
|
||||
{ "path": "alarm/index" }
|
||||
{ "path": "work-order/index" },
|
||||
{ "path": "work-order/detail" },
|
||||
{ "path": "work-order/create" },
|
||||
{ "path": "inspection/index" },
|
||||
{ "path": "inspection/detail" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages-system",
|
||||
"pages": [
|
||||
{ "path": "area/index" },
|
||||
{ "path": "dept/index" },
|
||||
{ "path": "user/index" }
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -150,21 +198,103 @@ aiot-uniapp/
|
||||
|
||||
---
|
||||
|
||||
## 三、页面状态与生命周期规约
|
||||
## 三、页面路由与导航
|
||||
|
||||
移动端页面的生命周期(`onLoad`, `onShow`, `onReady`)与 Vue 组件(`created`, `mounted`)有重叠,必须规范使用:
|
||||
### 3.1 路由配置(pages.json)
|
||||
|
||||
### 3.1 生命周期使用规范
|
||||
```json
|
||||
{
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"type": "home",
|
||||
"style": { "navigationStyle": "custom" }
|
||||
},
|
||||
{
|
||||
"path": "pages/scan/index",
|
||||
"style": { "navigationBarTitleText": "扫码巡检" }
|
||||
}
|
||||
],
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "pages-ops",
|
||||
"pages": [
|
||||
{ "path": "work-order/index", "style": { "navigationStyle": "custom" } },
|
||||
{ "path": "work-order/detail", "style": { "navigationStyle": "custom" } },
|
||||
{ "path": "inspection/index", "style": { "navigationStyle": "custom" } },
|
||||
{ "path": "inspection/detail", "style": { "navigationStyle": "custom" } }
|
||||
]
|
||||
}
|
||||
],
|
||||
"tabBar": {
|
||||
"custom": true,
|
||||
"color": "#999999",
|
||||
"selectedColor": "#f97316",
|
||||
"list": [
|
||||
{ "text": "工作台", "pagePath": "pages/index/index" },
|
||||
{ "text": "我的", "pagePath": "pages/user/index" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 页面跳转方法
|
||||
|
||||
```typescript
|
||||
// 基础导航
|
||||
import { navigateBackPlus } from '@/utils'
|
||||
|
||||
// 跳转到工单详情(带参数)
|
||||
function goToWorkOrderDetail(orderId: number) {
|
||||
uni.navigateTo({
|
||||
url: `/pages-ops/work-order/detail?id=${orderId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 返回上一页(封装版,支持指定 fallback)
|
||||
navigateBackPlus('/pages-ops/work-order/index')
|
||||
|
||||
// 重定向(关闭当前页面)
|
||||
uni.redirectTo({ url: '/pages/index/index' })
|
||||
|
||||
// 切换到 TabBar 页面
|
||||
uni.switchTab({ url: '/pages/index/index' })
|
||||
```
|
||||
|
||||
### 3.3 页面参数接收
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow, onUnload } from '@dcloudio/uni-app';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import WorkOrderService from '@/services/ops/WorkOrderService';
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
const orderId = ref('');
|
||||
const orderDetail = ref<OrderDetail | null>(null);
|
||||
const loading = ref(false);
|
||||
const props = defineProps<{
|
||||
id: string // URL 参数通过 defineProps 接收
|
||||
}>()
|
||||
|
||||
onLoad((options) => {
|
||||
// options 包含 URL 参数
|
||||
console.log(options?.id)
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、页面状态与生命周期规约
|
||||
|
||||
移动端页面的生命周期(`onLoad`, `onShow`, `onReady`)与 Vue 组件(`created`, `mounted`)有重叠,必须规范使用:
|
||||
|
||||
### 4.1 生命周期使用规范
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { onLoad, onShow, onUnload } from '@dcloudio/uni-app'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getOrderDetail } from '@/api/ops/order-center'
|
||||
|
||||
const orderId = ref('')
|
||||
const orderDetail = ref<OrderDetail | null>(null)
|
||||
const loading = ref(false)
|
||||
|
||||
/**
|
||||
* onLoad: 只做初始化
|
||||
@@ -173,13 +303,13 @@ const loading = ref(false);
|
||||
* - 绝不操作 DOM 节点
|
||||
*/
|
||||
onLoad((options) => {
|
||||
orderId.value = options?.id || '';
|
||||
orderId.value = options?.id || ''
|
||||
if (!orderId.value) {
|
||||
uni.showToast({ title: '参数错误', icon: 'none' });
|
||||
return;
|
||||
uni.showToast({ title: '参数错误', icon: 'none' })
|
||||
return
|
||||
}
|
||||
fetchOrderDetail();
|
||||
});
|
||||
fetchOrderDetail()
|
||||
})
|
||||
|
||||
/**
|
||||
* onShow: 处理从后台切回前台的数据刷新
|
||||
@@ -190,9 +320,9 @@ onShow(() => {
|
||||
// 场景1:从其他页面返回,可能需要刷新状态
|
||||
// 场景2:从后台切回,检查工单状态是否有变化
|
||||
if (orderId.value && !loading.value) {
|
||||
checkStatusUpdate();
|
||||
checkStatusUpdate()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
/**
|
||||
* Vue onMounted: 可操作 DOM,但小程序中受限
|
||||
@@ -200,7 +330,7 @@ onShow(() => {
|
||||
*/
|
||||
onMounted(() => {
|
||||
// 主要用于 Web 端逻辑
|
||||
});
|
||||
})
|
||||
|
||||
/**
|
||||
* onUnload: 清理动作
|
||||
@@ -210,124 +340,98 @@ onMounted(() => {
|
||||
*/
|
||||
onUnload(() => {
|
||||
// 断开工牌蓝牙连接
|
||||
BleManager.disconnect();
|
||||
// BleManager.disconnect()
|
||||
|
||||
// 取消正在进行的请求
|
||||
requestCancelToken.cancel('页面卸载');
|
||||
});
|
||||
// requestCancelToken.cancel('页面卸载')
|
||||
})
|
||||
|
||||
async function fetchOrderDetail() {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
try {
|
||||
orderDetail.value = await WorkOrderService.getDetail(orderId.value);
|
||||
orderDetail.value = await getOrderDetail(Number(orderId.value))
|
||||
} finally {
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function checkStatusUpdate() {
|
||||
// 静默检查状态变化
|
||||
const latest = await WorkOrderService.getStatus(orderId.value);
|
||||
const latest = await getOrderDetail(Number(orderId.value))
|
||||
if (latest.status !== orderDetail.value?.status) {
|
||||
// 状态变化,刷新详情
|
||||
fetchOrderDetail();
|
||||
fetchOrderDetail()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3.2 内存泄漏防护
|
||||
### 4.2 内存泄漏防护
|
||||
|
||||
| 资源类型 | 注册位置 | 必须清理位置 | 清理方式 |
|
||||
|---------|---------|-------------|---------|
|
||||
| WebSocket | `onLoad` / `onShow` | `onUnload` / `onHide` | `ws.close()` |
|
||||
| EventBus 监听 | `onLoad` | `onUnload` | `uni.$off()` |
|
||||
| 蓝牙连接 | 用户操作后 | `onUnload` | `BleManager.disconnect()` |
|
||||
| 蓝牙连接 | 用户操作后 | `onUnload` | `uni.closeBLEConnection()` |
|
||||
| 定时器 | 任意 | `onUnload` | `clearInterval()` |
|
||||
| 页面级 Store | `onLoad` | `onUnload` | `store.$reset()` |
|
||||
|
||||
---
|
||||
|
||||
## 四、状态管理设计
|
||||
## 五、状态管理设计
|
||||
|
||||
### 4.1 分层状态管理
|
||||
### 5.1 分层状态管理
|
||||
|
||||
```
|
||||
全局状态 (Pinia Store)
|
||||
├── userStore # 用户信息、登录态
|
||||
├── configStore # 系统配置、字典缓存
|
||||
└── bleStore # 蓝牙连接状态、当前工牌
|
||||
├── token.ts # Token 管理(双 Token 无感刷新)
|
||||
├── user.ts # 用户信息、登录态
|
||||
├── dict.ts # 系统字典缓存
|
||||
└── theme.ts # 主题配置
|
||||
|
||||
页面级状态 (Composable / setup)
|
||||
├── useWorkOrder() # 单个工单页面的状态
|
||||
├── useInspection() # 巡检页面的状态
|
||||
└── useUpload() # 图片上传的状态
|
||||
└── useBluetoothScan() # 蓝牙扫描状态
|
||||
```
|
||||
|
||||
### 4.2 Store 示例
|
||||
### 5.2 Token 管理(双 Token 无感刷新)
|
||||
|
||||
```typescript
|
||||
// stores/ble.ts
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref, computed } from 'vue';
|
||||
import BleManager from '@/services/ble/BleManager';
|
||||
// store/token.ts
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useBleStore = defineStore('ble', () => {
|
||||
// State
|
||||
const connectedDevice = ref<BadgeDevice | null>(null);
|
||||
const connectionState = ref<'disconnected' | 'connecting' | 'connected'>('disconnected');
|
||||
const lastHeartbeat = ref<number>(0);
|
||||
interface TokenInfo {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
expiresTime: number
|
||||
}
|
||||
|
||||
// Getters
|
||||
const isConnected = computed(() => connectionState.value === 'connected');
|
||||
const isDeviceOnline = computed(() => {
|
||||
if (!lastHeartbeat.value) return false;
|
||||
return Date.now() - lastHeartbeat.value < 5 * 60 * 1000; // 5分钟内有心跳
|
||||
});
|
||||
|
||||
// Actions
|
||||
async function connect(deviceId: string) {
|
||||
connectionState.value = 'connecting';
|
||||
try {
|
||||
const success = await BleManager.connect(deviceId);
|
||||
if (success) {
|
||||
connectionState.value = 'connected';
|
||||
// 监听心跳
|
||||
BleManager.on('heartbeat', (data) => {
|
||||
lastHeartbeat.value = data.timestamp;
|
||||
});
|
||||
} else {
|
||||
connectionState.value = 'disconnected';
|
||||
}
|
||||
} catch (error) {
|
||||
connectionState.value = 'disconnected';
|
||||
throw error;
|
||||
}
|
||||
export const useTokenStore = defineStore('token', () => {
|
||||
const tokenInfo = ref<TokenInfo | null>(null)
|
||||
|
||||
async function refreshToken() {
|
||||
// 调用刷新接口,更新 accessToken
|
||||
const res = await http.post('/system/auth/refresh-token', {
|
||||
refreshToken: tokenInfo.value?.refreshToken
|
||||
})
|
||||
tokenInfo.value = res
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
BleManager.disconnect();
|
||||
connectedDevice.value = null;
|
||||
connectionState.value = 'disconnected';
|
||||
|
||||
function logout() {
|
||||
tokenInfo.value = null
|
||||
uni.removeStorageSync('token_info')
|
||||
}
|
||||
|
||||
return {
|
||||
connectedDevice,
|
||||
connectionState,
|
||||
lastHeartbeat,
|
||||
isConnected,
|
||||
isDeviceOnline,
|
||||
connect,
|
||||
disconnect
|
||||
};
|
||||
});
|
||||
|
||||
return { tokenInfo, refreshToken, logout }
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、关键实现要点
|
||||
## 六、关键实现要点
|
||||
|
||||
### 5.1 工程结构红线
|
||||
### 6.1 工程结构红线
|
||||
|
||||
| 红线项 | 说明 | 后果 |
|
||||
|-------|------|------|
|
||||
@@ -336,22 +440,23 @@ export const useBleStore = defineStore('ble', () => {
|
||||
| **必须预加载** | 首页应预加载高频分包 | 用户点击后白屏时间过长 |
|
||||
| **清理必须配对** | 有注册必须有卸载 | 内存泄漏、页面异常 |
|
||||
|
||||
### 5.2 目录命名规范
|
||||
### 6.2 目录命名规范
|
||||
|
||||
| 类型 | 命名规范 | 示例 |
|
||||
|-----|---------|------|
|
||||
| 页面目录 | kebab-case | `work-order/`, `inspection-scan/` |
|
||||
| 组件文件 | kebab-case | `app-badge.vue`, `app-upload.vue` |
|
||||
| 服务文件 | PascalCase | `BleManager.ts`, `WorkOrderService.ts` |
|
||||
| 工具文件 | camelCase | `request.ts`, `helpers.ts` |
|
||||
| 常量文件 | UPPER_SNAKE | `constants.ts` (内部常量) |
|
||||
| 页面目录 | kebab-case | `work-order/`, `inspection/` |
|
||||
| 组件文件 | kebab-case | `bluetooth-verify.vue` |
|
||||
| 服务文件 | PascalCase | `BleManager.ts` |
|
||||
| 工具文件 | camelCase | `use-bluetooth-scan.ts` |
|
||||
| API 文件 | camelCase | `order-center/index.ts` |
|
||||
|
||||
### 5.3 相关代码入口
|
||||
### 6.3 相关代码入口
|
||||
|
||||
| 模块 | 文件路径 | 说明 |
|
||||
|-----|---------|------|
|
||||
| 页面路由 | `src/pages.json` | 主包 + 分包配置 |
|
||||
| 应用配置 | `src/manifest.json` | 小程序 AppID、权限声明 |
|
||||
| 请求封装 | `src/utils/request.ts` | 拦截器、错误处理 |
|
||||
| 蓝牙服务 | `src/services/ble/BleManager.ts` | BLE 连接管理 |
|
||||
| 全局组件 | `src/components/` | 复用 UI 组件 |
|
||||
| 请求封装 | `src/http/http.ts` | 拦截器、Token 刷新、错误处理 |
|
||||
| 蓝牙扫描 | `src/pages-ops/inspection/composables/use-bluetooth-scan.ts` | iBeacon 扫描 Hook |
|
||||
| 字典常量 | `src/utils/constants/dict-enum.ts` | DICT_TYPE 定义 |
|
||||
| 状态码 | `src/http/tools/enum.ts` | ResultEnum 定义 |
|
||||
File diff suppressed because it is too large
Load Diff
200
开发者文档/08-附录/01-术语表.md
Normal file
200
开发者文档/08-附录/01-术语表.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# 01-术语表
|
||||
|
||||
本文档汇总 AIOT 系统中使用的专业术语,按领域分类整理。
|
||||
|
||||
---
|
||||
|
||||
## 一、IoT 设备术语
|
||||
|
||||
### 1.1 工牌(Badge)
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 智能工牌 | Smart Badge | 保洁/安保人员佩戴的 BLE 设备,用于接收工单通知、上报位置 |
|
||||
| 工牌状态 | Badge Status | IDLE(空闲) / BUSY(忙碌) / PAUSED(暂停) / OFFLINE(离线) |
|
||||
| 工牌通知 | Badge Notify | 向工牌发送震动/语音通知 |
|
||||
| 心跳 | Heartbeat | 工牌定期上报在线状态 |
|
||||
| 电量 | Battery Level | 工牌剩余电量百分比 (0-100) |
|
||||
| RSSI | Received Signal Strength Indicator | 信号强度指示,单位 dBm |
|
||||
|
||||
### 1.2 信标(Beacon)
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 蓝牙信标 | Bluetooth Beacon | 固定部署的 BLE 广播设备,用于定位 |
|
||||
| iBeacon | Apple iBeacon | Apple 制定的 BLE 广播协议 |
|
||||
| UUID | Universally Unique Identifier | 信标唯一标识,16字节 |
|
||||
| Major | Major ID | 主标识,通常对应区域ID |
|
||||
| Minor | Minor ID | 次标识,通常对应信标ID |
|
||||
| 信号阈值 | RSSI Threshold | 最小可接收信号强度,如 -75dBm |
|
||||
|
||||
### 1.3 设备状态
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 未激活 | Inactive | 设备未激活状态 |
|
||||
| 在线 | Online | 设备正常连接 |
|
||||
| 离线 | Offline | 设备断开连接 |
|
||||
|
||||
---
|
||||
|
||||
## 二、工单业务术语
|
||||
|
||||
### 2.1 工单类型
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 保洁工单 | Cleaning Order | 保洁作业任务 |
|
||||
| 安保工单 | Security Order | 安保处理任务 |
|
||||
| 维修工单 | Repair Order | 设备维修任务 |
|
||||
| 客服工单 | Service Order | 客服服务任务 |
|
||||
|
||||
### 2.2 工单状态(状态机)
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> PENDING: 创建
|
||||
PENDING --> QUEUED: 进入队列
|
||||
QUEUED --> DISPATCHED: 推送到工牌
|
||||
DISPATCHED --> CONFIRMED: 保洁员确认
|
||||
CONFIRMED --> ARRIVED: 到达现场
|
||||
ARRIVED --> COMPLETED: 完成作业
|
||||
ARRIVED --> PAUSED: 暂停
|
||||
PAUSED --> ARRIVED: 恢复
|
||||
PENDING --> CANCELLED: 取消
|
||||
QUEUED --> CANCELLED: 取消
|
||||
DISPATCHED --> CANCELLED: 取消
|
||||
CONFIRMED --> CANCELLED: 取消
|
||||
ARRIVED --> CANCELLED: 取消
|
||||
```
|
||||
|
||||
| 状态 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 待分配 | PENDING | 工单已创建,等待分配 |
|
||||
| 排队中 | QUEUED | 已推荐保洁员,在队列中等待 |
|
||||
| 已推送 | DISPATCHED | 已推送到工牌,等待确认 |
|
||||
| 已确认 | CONFIRMED | 保洁员按下确认按钮 |
|
||||
| 已到岗 | ARRIVED | 到达现场,开始作业 |
|
||||
| 进行中 | IN_PROGRESS | 作业进行中 |
|
||||
| 已暂停 | PAUSED | 临时暂停 |
|
||||
| 已完成 | COMPLETED | 作业完成 |
|
||||
| 已取消 | CANCELLED | 工单取消 |
|
||||
|
||||
### 2.3 优先级
|
||||
|
||||
| 优先级 | 英文 | 说明 |
|
||||
|-------|------|------|
|
||||
| P0 紧急 | P0 Urgent | 最高优先级,可打断当前任务 |
|
||||
| P1 重要 | P1 High | 高优先级,优先处理 |
|
||||
| P2 普通 | P2 Normal | 普通优先级 |
|
||||
| P3 低优 | P3 Low | 低优先级 |
|
||||
|
||||
### 2.4 触发来源
|
||||
|
||||
| 来源 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 蓝牙信标 | IOT_BEACON | 信标触发(如厕所溢水) |
|
||||
| 客流阈值 | IOT_TRAFFIC | 客流统计触发 |
|
||||
| 视频告警 | VIDEO_ALARM | AI 视频分析告警 |
|
||||
| 门禁告警 | ACCESS_ALARM | 门禁系统告警 |
|
||||
| 巡更告警 | PATROL_ALARM | 巡更异常告警 |
|
||||
| 紧急按钮 | PANIC_BUTTON | 紧急求助按钮 |
|
||||
| 手动创建 | MANUAL | 人工创建工单 |
|
||||
|
||||
---
|
||||
|
||||
## 三、巡检术语
|
||||
|
||||
### 3.1 巡检要素
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 巡检区域 | Inspection Area | 需要巡检的物理区域 |
|
||||
| 巡检模板 | Inspection Template | 该区域检查项的配置 |
|
||||
| 检查项 | Inspection Item | 具体的检查内容 |
|
||||
| 巡检记录 | Inspection Record | 一次巡检的结果记录 |
|
||||
|
||||
### 3.2 巡检结果
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 合格 | Passed | 检查项通过 |
|
||||
| 不合格 | Failed | 检查项未通过 |
|
||||
| 位置异常 | Location Exception | 未在指定区域完成巡检 |
|
||||
| 归属判定 | Attribution | 异常原因:个人责任/突发状况/正常 |
|
||||
|
||||
---
|
||||
|
||||
## 四、人员术语
|
||||
|
||||
### 4.1 角色
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 保洁员 | Cleaner | 执行保洁任务的人员 |
|
||||
| 安保员 | Security Guard | 执行安保任务的人员 |
|
||||
| 维修员 | Repairman | 执行维修任务的人员 |
|
||||
| 巡检员 | Inspector | 执行巡检任务的人员 |
|
||||
| 调度员 | Dispatcher | 负责工单分配的人员 |
|
||||
|
||||
### 4.2 人员状态
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 空闲 | IDLE | 可接受新任务 |
|
||||
| 忙碌 | BUSY | 正在执行任务 |
|
||||
| 暂停 | PAUSED | 临时离开 |
|
||||
| 离线 | OFFLINE | 不在线 |
|
||||
|
||||
---
|
||||
|
||||
## 五、区域术语
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 区域 | Area | 物理空间划分 |
|
||||
| 父区域 | Parent Area | 上级区域 |
|
||||
| 子区域 | Child Area | 下级区域 |
|
||||
| 功能类型 | Function Type | 区域功能:厕所/电梯/大堂等 |
|
||||
| 地理围栏 | Geo-fence | 虚拟边界,用于位置校验 |
|
||||
|
||||
---
|
||||
|
||||
## 六、移动端术语
|
||||
|
||||
### 6.1 小程序
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| 主包 | Main Package | 小程序主包,2MB 限制 |
|
||||
| 分包 | SubPackage | 业务分包,2MB 限制 |
|
||||
| 预加载 | Preload | 提前加载分包资源 |
|
||||
| TabBar | Tab Bar | 底部导航栏 |
|
||||
|
||||
### 6.2 蓝牙
|
||||
|
||||
| 术语 | 英文 | 说明 |
|
||||
|-----|------|------|
|
||||
| BLE | Bluetooth Low Energy | 低功耗蓝牙 |
|
||||
| GATT | Generic Attribute Profile | 通用属性配置文件 |
|
||||
| MTU | Maximum Transmission Unit | 最大传输单元,默认20字节 |
|
||||
| Notify | Notification | BLE 通知机制 |
|
||||
| 广播 | Advertising | BLE 设备广播数据 |
|
||||
| 扫描 | Scanning | 搜索周围 BLE 设备 |
|
||||
|
||||
---
|
||||
|
||||
## 七、缩写对照
|
||||
|
||||
| 缩写 | 全称 | 中文 |
|
||||
|-----|------|------|
|
||||
| AIOT | Artificial Intelligence of Things | 智联网 |
|
||||
| BLE | Bluetooth Low Energy | 低功耗蓝牙 |
|
||||
| RSSI | Received Signal Strength Indicator | 接收信号强度指示 |
|
||||
| UUID | Universally Unique Identifier | 通用唯一标识符 |
|
||||
| API | Application Programming Interface | 应用程序接口 |
|
||||
| HTTP | HyperText Transfer Protocol | 超文本传输协议 |
|
||||
| JSON | JavaScript Object Notation | JavaScript 对象表示法 |
|
||||
| DOM | Document Object Model | 文档对象模型 |
|
||||
| Pinia | - | Vue 状态管理库 |
|
||||
| UniApp | - | 跨端开发框架 |
|
||||
242
开发者文档/08-附录/02-错误码清单.md
Normal file
242
开发者文档/08-附录/02-错误码清单.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# 02-错误码清单
|
||||
|
||||
本文档汇总 AIOT 系统中使用的错误码,包括后端统一错误码和前端/移动端特定错误。
|
||||
|
||||
---
|
||||
|
||||
## 一、后端统一错误码
|
||||
|
||||
### 1.1 全局错误码(0-999)
|
||||
|
||||
| 错误码 | 错误信息 | 说明 |
|
||||
|-------|---------|------|
|
||||
| 0 | 成功 | 请求成功 |
|
||||
| 400 | 请求参数不正确 | 参数校验失败 |
|
||||
| 401 | 账号未登录 | Token 过期或无效 |
|
||||
| 403 | 没有该操作权限 | 权限不足 |
|
||||
| 404 | 请求未找到 | 资源不存在 |
|
||||
| 405 | 请求方法不正确 | HTTP 方法错误 |
|
||||
| 423 | 请求失败,请稍后重试 | 并发请求锁定 |
|
||||
| 429 | 请求过于频繁,请稍后重试 | 限流触发 |
|
||||
| 500 | 系统异常 | 服务器内部错误 |
|
||||
| 501 | 功能未实现/未开启 | 功能未开放 |
|
||||
| 502 | 错误的配置项 | 配置错误 |
|
||||
| 900 | 重复请求,请稍后重试 | 重复提交 |
|
||||
| 901 | 演示模式,禁止写操作 | Demo 模式限制 |
|
||||
| 999 | 未知错误 | 未分类错误 |
|
||||
|
||||
### 1.2 OPS 模块错误码(1-020-xxx-xxx)
|
||||
|
||||
#### 区域管理(1-020-001-xxx)
|
||||
|
||||
| 错误码 | 错误信息 | 说明 |
|
||||
|-------|---------|------|
|
||||
| 1020001000 | 区域不存在 | AREA_NOT_FOUND |
|
||||
| 1020001001 | 该区域下存在子区域,请先处理子区域 | AREA_HAS_CHILDREN |
|
||||
| 1020001002 | 该区域已绑定设备,请先解除绑定 | AREA_HAS_DEVICES |
|
||||
| 1020001003 | 不能将父级设置为自己或子孙节点 | AREA_PARENT_LOOP |
|
||||
| 1020001004 | 区域编码已存在 | AREA_CODE_EXISTS |
|
||||
|
||||
#### 区域设备关联(1-020-002-xxx)
|
||||
|
||||
| 错误码 | 错误信息 | 说明 |
|
||||
|-------|---------|------|
|
||||
| 1020002000 | 设备不存在 | DEVICE_NOT_FOUND |
|
||||
| 1020002001 | 该工牌已绑定至此区域 | DEVICE_ALREADY_BOUND |
|
||||
| 1020002002 | 该区域已绑定{类型},一个区域只能绑定一个 | DEVICE_TYPE_ALREADY_BOUND |
|
||||
| 1020002003 | 设备关联关系不存在 | DEVICE_RELATION_NOT_FOUND |
|
||||
| 1020002004 | IoT 设备服务不可用,请稍后重试 | IOT_SERVICE_UNAVAILABLE |
|
||||
|
||||
#### 安保工单(1-020-003-xxx)
|
||||
|
||||
| 错误码 | 错误信息 | 说明 |
|
||||
|-------|---------|------|
|
||||
| 1020003000 | 工单不存在 | SECURITY_ORDER_NOT_FOUND |
|
||||
| 1020003001 | 工单类型不匹配,期望安保工单 | SECURITY_ORDER_TYPE_MISMATCH |
|
||||
| 1020003002 | 该安保人员已绑定到此区域 | SECURITY_AREA_USER_DUPLICATE |
|
||||
| 1020003003 | 绑定记录不存在 | SECURITY_AREA_USER_NOT_FOUND |
|
||||
| 1020003004 | 目标安保人员未绑定到工单所属区域或已停用 | SECURITY_ASSIGNEE_NOT_BOUND_TO_AREA |
|
||||
| 1020003005 | 当前工单状态不允许手动派单,仅 PENDING 状态可操作 | SECURITY_ORDER_STATUS_NOT_ALLOW_DISPATCH |
|
||||
| 1020003006 | 已完成或已取消的工单不允许升级优先级 | SECURITY_ORDER_PRIORITY_UPGRADE_NOT_ALLOWED |
|
||||
|
||||
#### 巡检模块(1-020-004-xxx)
|
||||
|
||||
| 错误码 | 错误信息 | 说明 |
|
||||
|-------|---------|------|
|
||||
| 1020004000 | 巡检模板不存在 | INSPECTION_TEMPLATE_NOT_FOUND |
|
||||
| 1020004001 | 巡检记录不存在 | INSPECTION_RECORD_NOT_FOUND |
|
||||
| 1020004002 | 该区域未启用,无法巡检 | INSPECTION_AREA_NOT_ACTIVE |
|
||||
|
||||
---
|
||||
|
||||
## 二、前端/移动端错误码
|
||||
|
||||
### 2.1 HTTP 状态码(ResultEnum)
|
||||
|
||||
```typescript
|
||||
// http/tools/enum.ts
|
||||
|
||||
export enum ResultEnum {
|
||||
Success0 = 0, // 成功
|
||||
Success200 = 200, // 成功
|
||||
Error = 400, // 错误
|
||||
Unauthorized = 401, // 未授权
|
||||
Forbidden = 403, // 禁止访问
|
||||
NotFound = 404, // 未找到
|
||||
MethodNotAllowed = 405, // 方法不允许
|
||||
RequestTimeout = 408, // 请求超时
|
||||
InternalServerError = 500, // 服务器错误
|
||||
NotImplemented = 501, // 未实现
|
||||
BadGateway = 502, // 网关错误
|
||||
ServiceUnavailable = 503, // 服务不可用
|
||||
GatewayTimeout = 504, // 网关超时
|
||||
HttpVersionNotSupported = 505, // HTTP版本不支持
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 蓝牙扫描状态(ScanStatus)
|
||||
|
||||
```typescript
|
||||
// pages-ops/inspection/composables/use-bluetooth-scan.ts
|
||||
|
||||
export type ScanStatus =
|
||||
| 'idle' // 空闲
|
||||
| 'scanning' // 扫描中
|
||||
| 'success' // 定位成功
|
||||
| 'failed' // 定位失败
|
||||
| 'no-permission' // 缺少权限
|
||||
```
|
||||
|
||||
### 2.3 蓝牙扫描错误信息
|
||||
|
||||
| 状态 | 错误信息 | 处理建议 |
|
||||
|-----|---------|---------|
|
||||
| no-permission | 蓝牙权限已被拒绝,请在设置中开启 | 引导用户打开设置 |
|
||||
| no-permission | 需要蓝牙权限才能进行定位验证 | 申请蓝牙权限 |
|
||||
| failed | 启动蓝牙扫描失败 | 检查蓝牙是否开启 |
|
||||
| failed | 定位超时,未能验证位置 | 靠近信标重试 |
|
||||
|
||||
### 2.4 网络错误提示
|
||||
|
||||
```typescript
|
||||
// http/tools/enum.ts
|
||||
|
||||
export function ShowMessage(status: number | string): string {
|
||||
switch (status) {
|
||||
case 400: return '请求错误(400),请检查网络或联系管理员!'
|
||||
case 401: return '未授权,请重新登录(401),请检查网络或联系管理员!'
|
||||
case 403: return '拒绝访问(403),请检查网络或联系管理员!'
|
||||
case 404: return '请求出错(404),请检查网络或联系管理员!'
|
||||
case 408: return '请求超时(408),请检查网络或联系管理员!'
|
||||
case 500: return '服务器错误(500),请检查网络或联系管理员!'
|
||||
case 501: return '服务未实现(501),请检查网络或联系管理员!'
|
||||
case 502: return '网络错误(502),请检查网络或联系管理员!'
|
||||
case 503: return '服务不可用(503),请检查网络或联系管理员!'
|
||||
case 504: return '网络超时(504),请检查网络或联系管理员!'
|
||||
case 505: return 'HTTP版本不受支持(505),请检查网络或联系管理员!'
|
||||
default: return `连接出错(${status})!,请检查网络或联系管理员!`
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、错误码处理规范
|
||||
|
||||
### 3.1 后端错误处理
|
||||
|
||||
```java
|
||||
// Java 后端统一返回格式
|
||||
public class CommonResult<T> {
|
||||
private Integer code; // 错误码
|
||||
private String msg; // 错误信息
|
||||
private T data; // 数据
|
||||
|
||||
public static <T> CommonResult<T> success(T data) {
|
||||
return new CommonResult<>(0, "成功", data);
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> error(ErrorCode errorCode) {
|
||||
return new CommonResult<>(errorCode.getCode(), errorCode.getMsg(), null);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 前端错误处理
|
||||
|
||||
```typescript
|
||||
// http/http.ts 统一错误处理
|
||||
|
||||
success: async (res) => {
|
||||
const { code, msg } = responseData
|
||||
|
||||
// Token 过期处理
|
||||
if (res.statusCode === 401 || code === 401) {
|
||||
const tokenStore = useTokenStore()
|
||||
if (!isDoubleTokenMode) {
|
||||
tokenStore.logout()
|
||||
toLoginPage()
|
||||
return reject(res)
|
||||
}
|
||||
// 无感刷新 Token...
|
||||
}
|
||||
|
||||
// 业务错误处理
|
||||
if (code !== ResultEnum.Success0 && code !== ResultEnum.Success200) {
|
||||
uni.showToast({
|
||||
title: msg || '请求错误',
|
||||
icon: 'none',
|
||||
})
|
||||
return reject(responseData)
|
||||
}
|
||||
|
||||
return resolve(responseData.data)
|
||||
},
|
||||
|
||||
fail(err) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '网络错误,换个网络试试',
|
||||
})
|
||||
reject(err)
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 错误码对照表
|
||||
|
||||
| 场景 | 后端错误码 | 前端处理 |
|
||||
|-----|-----------|---------|
|
||||
| 参数错误 | 400 | Toast 提示具体错误 |
|
||||
| Token 过期 | 401 | 自动刷新或跳转登录 |
|
||||
| 权限不足 | 403 | Toast 提示无权限 |
|
||||
| 资源不存在 | 404 | 显示空状态或返回 |
|
||||
| 服务器错误 | 500 | Toast 提示系统异常 |
|
||||
| 请求频繁 | 429 | Toast 提示稍后重试 |
|
||||
| 蓝牙权限拒绝 | - | 引导打开系统设置 |
|
||||
| 定位超时 | - | 提示靠近信标重试 |
|
||||
| 网络断开 | - | Toast 提示网络错误 |
|
||||
|
||||
---
|
||||
|
||||
## 四、错误码速查
|
||||
|
||||
### 4.1 按模块速查
|
||||
|
||||
| 模块 | 错误码范围 | 文件 |
|
||||
|-----|-----------|------|
|
||||
| 全局 | 0-999 | GlobalErrorCodeConstants.java |
|
||||
| 区域 | 1-020-001-xxx | ErrorCodeConstants.java |
|
||||
| 设备 | 1-020-002-xxx | ErrorCodeConstants.java |
|
||||
| 安保 | 1-020-003-xxx | ErrorCodeConstants.java |
|
||||
| 巡检 | 1-020-004-xxx | ErrorCodeConstants.java |
|
||||
|
||||
### 4.2 按场景速查
|
||||
|
||||
| 场景 | 常见错误码 | 解决方案 |
|
||||
|-----|-----------|---------|
|
||||
| 登录失败 | 401 | 检查账号密码,重新登录 |
|
||||
| 派单失败 | 1020003005 | 确认工单状态为 PENDING |
|
||||
| 信标绑定失败 | 1020002001 | 解绑后重新绑定 |
|
||||
| 巡检提交失败 | 1020004002 | 确认区域已启用 |
|
||||
| 蓝牙扫描失败 | no-permission | 开启蓝牙和定位权限 |
|
||||
| 图片上传失败 | 408/504 | 压缩图片后重试 |
|
||||
Reference in New Issue
Block a user