# 巡检管理模块重构规格文档 ## 1. 概述 ### 1.1 背景 当前巡检管理模块存在以下问题需要重构: 1. 巡检点管理不够独立,缺少批量创建和二维码/NFC支持 2. 巡检计划缺少路径编排功能 3. 缺少执行人排班管理 4. 任务详情缺少路径比对和问题标记 ### 1.2 目标 - 完善巡检点管理功能,支持批量创建、二维码生成、NFC写入 - 实现巡检计划路径编排,支持巡检点顺序和间隔时间设置 - 增加执行人排班管理,支持按周循环排班 - 完善任务详情,支持路径比对和问题标记 - 支持巡检计划复制功能 ## 2. 功能需求 ### 2.1 巡检点管理(独立Tab页) #### 2.1.1 批量创建巡检点 **需求描述**:支持批量创建多个巡检点,采用混合模式。 **交互设计**: - 提供表格形式的批量创建界面 - 支持手动输入每个巡检点名称 - 支持自动编号功能:输入前缀+起始编号,系统自动生成如"巡检点-001、巡检点-002..." - 支持混合模式:空白行可自动填充编号 **数据结构**: ```typescript interface BatchCreateInspectionPointRequest { points: Array<{ name: string; // 巡检点名称 location?: string; // 位置描述 type: string; // 巡检点类型 spaceNodeId?: string; // 关联空间节点 longitude?: number; // 经度 latitude?: number; // 纬度 }>; autoNumbering?: { enabled: boolean; prefix: string; // 名称前缀 startNumber: number; // 起始编号 padding: number; // 编号位数,如3表示001 }; } ``` #### 2.1.2 二维码生成 **需求描述**:每个巡检点可生成唯一二维码,存储完整信息。 **二维码内容(JSON格式)**: ```json { "type": "INSPECTION_POINT", "id": "uuid", "code": "PT202502200001", "name": "巡检点名称", "projectId": "project-uuid", "location": "位置描述", "createdAt": "2025-02-20T10:00:00Z", "signature": "数字签名(可选,用于防伪)" } ``` **功能要求**: - 支持单个巡检点二维码生成和下载 - 支持批量生成二维码(ZIP打包下载) - 二维码格式:QR Code,尺寸可配置(默认200x200px) - 支持打印模板:A4纸每页10个二维码 #### 2.1.3 NFC写入 **需求描述**:支持将巡检点信息写入NFC贴片。 **NFC数据格式**: - 使用NDEF格式存储 - 存储与二维码相同的JSON数据 - 支持手机NFC功能写入(待定具体实现) **功能要求**: - 提供NFC写入界面(Web NFC API或移动端App) - 支持批量写入模式 - 记录NFC标签ID用于验证 ### 2.2 巡检计划路径编排 #### 2.2.1 路径编排功能 **需求描述**:将已录入的巡检点进行先后顺序编排,形成巡检路径。 **数据结构**: ```typescript interface InspectionPathPoint { pointId: string; // 巡检点ID pointName: string; // 巡检点名称 pointCode: string; // 巡检点编码 order: number; // 顺序号 minIntervalMinutes: number; // 与上一个巡检点的最小间隔时间(分钟) estimatedMinutes: number; // 预计停留时间(分钟) location?: string; // 位置描述 } interface InspectionPath { id: string; planId: string; points: InspectionPathPoint[]; totalEstimatedMinutes: number; // 总预计时间 createdAt: string; updatedAt: string; } ``` **交互设计**: - 提供拖拽排序界面 - 左侧显示可选巡检点列表 - 右侧显示已选巡检点路径 - 支持设置每个巡检点的最小间隔时间 - 实时显示总预计时间 #### 2.2.2 最小间隔时间 **需求描述**:设置相邻巡检点之间的最小到达时间间隔。 **业务规则**: - 从上一个巡检点打卡到下一个巡检点打卡的最小时间差 - 如果实际间隔小于设置值,标记为"时间间隔不足"问题 - 可设置默认值(如5分钟),也可单独设置每个点 ### 2.3 巡检计划周期设置 #### 2.3.1 多种周期类型 **需求描述**:支持多种巡检周期类型。 **周期类型**: - 每日(DAILY) - 每周(WEEKLY)- 可指定星期几 - 每两周(BIWEEKLY) - 每月(MONTHLY)- 可指定日期 - 每季度(QUARTERLY) - 每半年(SEMIANNUAL) - 每年(YEARLY) #### 2.3.2 周期内最少完成次数 **需求描述**:设置每个周期内需要完成的最少巡检次数。 **数据结构**: ```typescript interface InspectionPlanCycle { cycle: string; // 周期类型 cycleDay?: number; // 执行日期(如每月几号) cycleDays?: number[]; // 执行日期数组(如每周几) executeTime: string; // 执行时间(HH:mm) minCompletionsPerCycle: number; // 周期内最少完成次数 endDate?: string; // 计划结束日期 } ``` ### 2.4 巡检计划负责人和执行人 #### 2.4.1 角色定义 **负责人**: - 管理巡检计划 - 监督巡检任务完成情况 - 查看巡检报告和统计数据 - 调整计划和排班 **执行人**: - 完成巡检任务 - 扫码打卡 - 上报巡检问题 #### 2.4.2 人员选择器 **需求描述**:选择负责人和执行人时,只能选择符合条件的人员。 **筛选条件**: - 本部门及下级部门的人员 - 具备本项目执行巡检任务权限的人员 **数据结构**: ```typescript interface InspectionPlanPersonnel { planId: string; managerId: string; // 负责人ID managerName: string; // 负责人姓名 executorIds: string[]; // 执行人ID列表 executorNames: string[]; // 执行人姓名列表 } ``` ### 2.5 执行人排班管理 #### 2.5.1 按周循环排班 **需求描述**:为多个执行人设置按周循环的排班。 **数据结构**: ```typescript interface InspectionSchedule { id: string; planId: string; weekSchedules: WeekSchedule[]; createdAt: string; updatedAt: string; } interface WeekSchedule { dayOfWeek: number; // 1-7 表示周一到周日 executorId: string; // 执行人ID executorName: string; // 执行人姓名 timeSlot?: string; // 时间段(可选) } ``` **业务规则**: - 每天可指定一个执行人 - 未指定的日期默认由所有执行人轮流 - 只要求多人里有一人完成任务即可标记完成 #### 2.5.2 任务完成判定 **需求描述**:多执行人情况下,只要有一人完成即标记任务完成。 **判定逻辑**: 1. 根据排班表确定当天执行人 2. 当天执行人扫码打卡完成巡检 3. 系统自动标记任务为完成状态 4. 记录实际执行人信息 ### 2.6 任务详情路径比对 #### 2.6.1 时间线对比展示 **需求描述**:在任务详情中展示计划路径与实际路径的对比。 **数据结构**: ```typescript interface InspectionTaskPath { taskId: string; plannedPath: PlannedPathPoint[]; actualPath: ActualPathPoint[]; issues: PathIssue[]; summary: TaskSummary; } interface PlannedPathPoint { order: number; pointId: string; pointName: string; minIntervalMinutes: number; estimatedMinutes: number; } interface ActualPathPoint { order: number; pointId: string; pointName: string; scannedAt: string; // 扫码时间 scannedBy: string; // 扫码人 scannedByName: string; intervalFromPrevious: number; // 与上一个点的实际间隔(分钟) issues?: string[]; // 问题列表 } interface PathIssue { type: 'ORDER_ERROR' | 'TIME_INTERVAL_ERROR' | 'POINT_SKIPPED' | 'INSPECTION_ISSUE'; severity: 'WARNING' | 'ERROR'; pointId?: string; pointName?: string; description: string; details?: any; } interface TaskSummary { totalPoints: number; completedPoints: number; skippedPoints: number; orderErrors: number; timeIntervalErrors: number; inspectionIssues: number; startedAt: string; completedAt: string; totalDuration: number; // 总耗时(分钟) } ``` **交互设计**: - 使用时间线组件展示 - 计划路径用虚线表示 - 实际路径用实线表示 - 问题点用红色标记 - 点击节点显示详细信息 #### 2.6.2 问题标记 **需求描述**:标记路径问题和巡检问题。 **问题类型**: 1. **路径问题**: - 顺序错误(ORDER_ERROR):未按计划顺序巡检 - 时间间隔不足(TIME_INTERVAL_ERROR):两点之间时间过短 - 巡检点跳过(POINT_SKIPPED):未巡检计划中的点 2. **巡检问题**: - 设备故障 - 环境异常 - 安全隐患 - 其他问题 **问题展示**: - 在任务详情顶部显示问题简报 - 问题点用不同颜色标记 - 支持查看问题详情和照片 ### 2.7 巡检计划复制 #### 2.7.1 复制功能 **需求描述**:支持复制巡检计划,创建新计划。 **复制内容**: - 计划基本信息(名称需修改) - 巡检点路径 - 执行人设置 - 排班配置 **不复制内容**: - 计划ID - 创建时间 - 已生成的任务 **API设计**: ``` POST /api/v1/ops/inspection/plans/{id}/copy Request: { name: string; // 新计划名称 startDate?: string; // 新计划开始日期 endDate?: string; // 新计划结束日期 } Response: InspectionPlan ``` ## 3. 数据库设计 ### 3.1 新增表 #### 3.1.1 巡检路径表 (ops_inspection_path) ```sql CREATE TABLE ops_inspection_path ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id UUID NOT NULL, plan_id UUID NOT NULL, name VARCHAR(100), description VARCHAR(500), total_estimated_minutes INTEGER DEFAULT 0, enabled BOOLEAN NOT NULL DEFAULT true, version BIGINT DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_by UUID, updated_by UUID, CONSTRAINT fk_path_plan FOREIGN KEY (plan_id) REFERENCES ops_inspection_plan(id) ON DELETE CASCADE ); CREATE INDEX idx_path_project ON ops_inspection_path(project_id); CREATE INDEX idx_path_plan ON ops_inspection_path(plan_id); ``` #### 3.1.2 巡检路径点表 (ops_inspection_path_point) ```sql CREATE TABLE ops_inspection_path_point ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), path_id UUID NOT NULL, point_id UUID NOT NULL, point_order INTEGER NOT NULL, min_interval_minutes INTEGER DEFAULT 5, estimated_minutes INTEGER DEFAULT 5, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_point_path FOREIGN KEY (path_id) REFERENCES ops_inspection_path(id) ON DELETE CASCADE, CONSTRAINT fk_point_inspection FOREIGN KEY (point_id) REFERENCES ops_inspection_point(id) ); CREATE INDEX idx_path_point_path ON ops_inspection_path_point(path_id); CREATE INDEX idx_path_point_order ON ops_inspection_path_point(path_id, point_order); ``` #### 3.1.3 执行人排班表 (ops_inspection_schedule) ```sql CREATE TABLE ops_inspection_schedule ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id UUID NOT NULL, plan_id UUID NOT NULL, executor_id UUID NOT NULL, executor_name VARCHAR(100), day_of_week INTEGER NOT NULL CHECK (day_of_week BETWEEN 1 AND 7), time_slot VARCHAR(50), enabled BOOLEAN NOT NULL DEFAULT true, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_by UUID, updated_by UUID, CONSTRAINT fk_schedule_plan FOREIGN KEY (plan_id) REFERENCES ops_inspection_plan(id) ON DELETE CASCADE ); CREATE INDEX idx_schedule_project ON ops_inspection_schedule(project_id); CREATE INDEX idx_schedule_plan ON ops_inspection_schedule(plan_id); CREATE INDEX idx_schedule_day ON ops_inspection_schedule(plan_id, day_of_week); ``` #### 3.1.4 任务打卡记录表 (ops_inspection_checkin) ```sql CREATE TABLE ops_inspection_checkin ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id UUID NOT NULL, task_id UUID NOT NULL, point_id UUID NOT NULL, point_order INTEGER, checkin_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, checkin_type VARCHAR(20) NOT NULL, -- QR_CODE, NFC executor_id UUID NOT NULL, executor_name VARCHAR(100), longitude DECIMAL(10, 7), latitude DECIMAL(10, 7), location_verified BOOLEAN DEFAULT false, issues JSONB, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_checkin_task FOREIGN KEY (task_id) REFERENCES ops_inspection_task(id) ON DELETE CASCADE, CONSTRAINT fk_checkin_point FOREIGN KEY (point_id) REFERENCES ops_inspection_point(id) ); CREATE INDEX idx_checkin_project ON ops_inspection_checkin(project_id); CREATE INDEX idx_checkin_task ON ops_inspection_checkin(task_id); CREATE INDEX idx_checkin_point ON ops_inspection_checkin(point_id); CREATE INDEX idx_checkin_time ON ops_inspection_checkin(checkin_time); ``` ### 3.2 修改表 #### 3.2.1 巡检计划表 (ops_inspection_plan) ```sql ALTER TABLE ops_inspection_plan ADD COLUMN IF NOT EXISTS min_completions_per_cycle INTEGER DEFAULT 1; ALTER TABLE ops_inspection_plan ADD COLUMN IF NOT EXISTS executor_ids JSONB; ALTER TABLE ops_inspection_plan ADD COLUMN IF NOT EXISTS executor_names JSONB; ALTER TABLE ops_inspection_plan ADD COLUMN IF NOT EXISTS path_id UUID; ``` #### 3.2.2 巡检点表 (ops_inspection_point) ```sql ALTER TABLE ops_inspection_point ADD COLUMN IF NOT EXISTS qr_data JSONB; ALTER TABLE ops_inspection_point ADD COLUMN IF NOT EXISTS nfc_data JSONB; ``` #### 3.2.3 巡检任务表 (ops_inspection_task) ```sql ALTER TABLE ops_inspection_task ADD COLUMN IF NOT EXISTS path_id UUID; ALTER TABLE ops_inspection_task ADD COLUMN IF NOT EXISTS planned_path JSONB; ALTER TABLE ops_inspection_task ADD COLUMN IF NOT EXISTS actual_path JSONB; ALTER TABLE ops_inspection_task ADD COLUMN IF NOT EXISTS path_issues JSONB; ALTER TABLE ops_inspection_task ADD COLUMN IF NOT EXISTS task_summary JSONB; ``` ## 4. API设计 ### 4.1 巡检点管理API #### 4.1.1 批量创建巡检点 ``` POST /api/v1/ops/inspection/points/batch Request: BatchCreateInspectionPointRequest Response: InspectionPoint[] ``` #### 4.1.2 生成二维码 ``` POST /api/v1/ops/inspection/points/{id}/generate-qrcode Response: { qrCode: string, qrData: string, qrImage: string } ``` #### 4.1.3 批量生成二维码 ``` POST /api/v1/ops/inspection/points/batch-qrcode Request: { pointIds: string[] } Response: { downloadUrl: string } ``` #### 4.1.4 NFC写入准备 ``` GET /api/v1/ops/inspection/points/{id}/nfc-data Response: { nfcData: string, pointId: string, pointName: string } ``` ### 4.2 巡检路径API #### 4.2.1 创建巡检路径 ``` POST /api/v1/ops/inspection/plans/{planId}/path Request: { name: string; points: Array<{ pointId: string; minIntervalMinutes: number; estimatedMinutes: number; }>; } Response: InspectionPath ``` #### 4.2.2 更新巡检路径 ``` PUT /api/v1/ops/inspection/plans/{planId}/path Request: { name: string; points: Array<{ pointId: string; minIntervalMinutes: number; estimatedMinutes: number; }>; } Response: InspectionPath ``` #### 4.2.3 获取巡检路径 ``` GET /api/v1/ops/inspection/plans/{planId}/path Response: InspectionPath ``` ### 4.3 排班管理API #### 4.3.1 设置排班 ``` POST /api/v1/ops/inspection/plans/{planId}/schedule Request: { schedules: Array<{ dayOfWeek: number; executorId: string; executorName: string; timeSlot?: string; }>; } Response: InspectionSchedule[] ``` #### 4.3.2 获取排班 ``` GET /api/v1/ops/inspection/plans/{planId}/schedule Response: InspectionSchedule[] ``` ### 4.4 打卡API #### 4.4.1 扫码打卡 ``` POST /api/v1/ops/inspection/checkin Request: { taskId: string; qrCode?: string; nfcTag?: string; longitude?: number; latitude?: number; } Response: InspectionCheckin ``` #### 4.4.2 获取打卡记录 ``` GET /api/v1/ops/inspection/tasks/{taskId}/checkins Response: InspectionCheckin[] ``` ### 4.5 任务路径比对API #### 4.5.1 获取任务路径比对 ``` GET /api/v1/ops/inspection/tasks/{taskId}/path-comparison Response: InspectionTaskPath ``` ### 4.6 计划复制API #### 4.6.1 复制计划 ``` POST /api/v1/ops/inspection/plans/{id}/copy Request: { name: string; startDate?: string; endDate?: string; } Response: InspectionPlan ``` ## 5. 前端页面设计 ### 5.1 巡检点管理页面 #### 5.1.1 页面结构 ``` 巡检点管理 ├── 搜索栏 │ ├── 关键词搜索 │ ├── 类型筛选 │ └── 状态筛选 ├── 操作栏 │ ├── 新增巡检点 │ ├── 批量创建 │ └── 批量生成二维码 ├── 数据表格 │ ├── 巡检点编码 │ ├── 巡检点名称 │ ├── 类型 │ ├── 位置 │ ├── 二维码 │ ├── NFC状态 │ ├── 状态 │ └── 操作 └── 批量创建弹窗 ├── 表格形式输入 ├── 自动编号设置 └── 导入功能 ``` #### 5.1.2 二维码弹窗 ``` 二维码详情 ├── 巡检点信息 ├── 二维码图片 ├── 下载按钮 └── 打印按钮 ``` ### 5.2 巡检计划页面 #### 5.2.1 页面结构 ``` 巡检计划 ├── 搜索栏 ├── 操作栏 │ ├── 新增计划 │ └── 生成任务 ├── 数据表格 │ ├── 计划编码 │ ├── 计划名称 │ ├── 类型 │ ├── 周期 │ ├── 最少完成次数 │ ├── 负责人 │ ├── 执行人数 │ ├── 状态 │ └── 操作 └── 计划详情/编辑弹窗 ├── 基本信息 Tab ├── 巡检路径 Tab ├── 执行人 Tab └── 排班管理 Tab ``` #### 5.2.2 路径编排界面 ``` 路径编排 ├── 左侧:可选巡检点列表 │ ├── 搜索 │ └── 巡检点列表(可拖拽) ├── 右侧:已选巡检点路径 │ ├── 路径列表(可拖拽排序) │ ├── 每个点设置间隔时间 │ └── 总预计时间显示 └── 操作按钮 ├── 保存 └── 重置 ``` #### 5.2.3 排班管理界面 ``` 排班管理 ├── 周视图 │ ├── 周一至周日 │ └── 每天显示执行人 ├── 执行人列表 │ └── 勾选参与排班的人员 └── 快速排班 ├── 轮流排班 └── 指定排班 ``` ### 5.3 任务详情页面 #### 5.3.1 页面结构 ``` 任务详情 ├── 任务简报 │ ├── 任务状态 │ ├── 完成进度 │ └── 问题摘要 ├── 路径比对 │ ├── 时间线视图 │ ├── 计划路径(虚线) │ ├── 实际路径(实线) │ └── 问题标记(红色) ├── 打卡记录列表 │ ├── 序号 │ ├── 巡检点 │ ├── 打卡时间 │ ├── 执行人 │ ├── 间隔时间 │ └── 状态 └── 问题详情 ├── 问题描述 ├── 问题照片 └── 处理状态 ``` ## 6. 开发任务 ### 6.1 后端开发任务 1. **数据库变更** - 创建新表 - 修改现有表结构 - 编写数据迁移脚本 2. **实体和Repository** - 创建InspectionPath实体 - 创建InspectionPathPoint实体 - 创建InspectionSchedule实体 - 创建InspectionCheckin实体 - 修改InspectionPlan实体 - 修改InspectionPoint实体 - 修改InspectionTask实体 3. **Service层** - 实现批量创建巡检点服务 - 实现二维码生成服务 - 实现NFC数据准备服务 - 实现路径编排服务 - 实现排班管理服务 - 实现打卡服务 - 实现路径比对服务 - 实现计划复制服务 4. **Controller层** - 实现巡检点批量API - 实现二维码API - 实现NFC API - 实现路径API - 实现排班API - 实现打卡API - 实现路径比对API - 实现计划复制API ### 6.2 前端开发任务 1. **巡检点管理页面** - 实现批量创建组件 - 实现二维码生成和显示 - 实现NFC写入界面 2. **巡检计划页面** - 实现路径编排组件 - 实现执行人选择器 - 实现排班管理组件 3. **任务详情页面** - 实现时间线对比组件 - 实现问题标记展示 - 实现简报组件 4. **API集成** - 集成所有新增API ### 6.3 测试任务 1. **单元测试** - 后端Service层测试 - 前端组件测试 2. **集成测试** - API集成测试 - 业务流程测试 3. **E2E测试** - 巡检点批量创建流程 - 路径编排流程 - 排班管理流程 - 打卡流程 - 路径比对流程 ## 7. 风险和注意事项 ### 7.1 技术风险 1. **NFC写入**:Web NFC API支持有限,可能需要移动端App支持 2. **二维码批量生成**:大量二维码生成可能影响性能,需要异步处理 3. **路径比对算法**:需要考虑各种边界情况 ### 7.2 业务风险 1. **排班冲突**:同一执行人可能被分配到多个计划 2. **路径变更**:计划执行中修改路径需要处理已生成任务 3. **数据迁移**:现有数据需要兼容新结构 ### 7.3 注意事项 1. 保持向后兼容性 2. 做好数据备份 3. 分阶段上线 4. 充分测试边界情况