# 保洁管理 > 模块编码:cleaning > 端侧:Web + 小程序(双端) > 关联文档:01-模块划分 §3.3 / 02-功能清单-物业公司 §3 / 03-业务流转逻辑-物业公司 §3 / 05-接口规范 §9.2 / 06-项目技术要求 §4.4 > 强制规范遵循 `07-前端界面开发规范.md` ## 功能概览 | 项目 | 说明 | |------|------| | 菜单名称 | 保洁管理 | | 子菜单 | 保洁区域管理、保洁任务看板、人员排班、蓝牙点位管理、超时预警、保洁抽查、数据补录 | | 功能编号 | PR-C-01 ~ PR-C-08 | | 权限编码前缀 | cleaning:area:* / cleaning:task:* / cleaning:schedule:* / cleaning:spot-check:* / cleaning:supplement:* | --- ## 页面1:保洁区域管理页 **页面编号**:PR-C-01-P01 **端侧归属**:Web专属 **页面路径**:/cleaning/areas ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [面包屑] 保洁管理 > 保洁区域管理 │ ├──────────────────────────────────────────────────────────────────┤ │ [操作栏] [新增区域] │ ├──────────────────────────────────────────────────────────────────┤ │ [树形+列表] │ │ ┌──────────────┐ ┌──────────────────────────────────────────┐ │ │ │ 主院区(项目) │ │ 区域:主院区 > 门诊楼 > 3层 > 公共区域 │ │ │ │ ├ 门诊楼 │ │ 区域责任人:张三 │ │ │ │ │ ├ 1层 │ │ 蓝牙Beacon:B-010 (在线) │ │ │ │ │ │ ├ 大厅 │ │ 当前排班:早班(06:00-14:00) │ │ │ │ │ │ └ 走廊 │ │ [编辑] [删除]│ │ │ │ │ ├ 2层 │ └──────────────────────────────────────────┘ │ │ │ │ └ 3层 │ │ │ │ └ 住院楼 │ │ │ └──────────────┘ │ └──────────────────────────────────────────────────────────────────┘ ``` ### 五级架构 | 层级 | 说明 | 示例 | |------|------|------| | 项目 | 最顶层 | 主院区 | | 区域 | 建筑分区 | 门诊楼 | | 楼栋 | 单独楼 | 1号楼 | | 楼层 | 楼层 | 3层 | | 区域责任人 | 最末级+负责人 | 公共区域(张三) | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 新增区域 | cleaning:area:create | 操作栏 | 始终 | 弹窗 | | 编辑 | cleaning:area:update | 详情区 | 始终 | — | | 删除 | cleaning:area:delete | 详情区 | 无排班关联时 | 二次确认 | ### 表单字段(新增/编辑弹窗) | 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 | |--------|----------|------|--------|----------|----------| | 区域名称 | 文本输入 | 是 | — | 自填 | 最大30字 | | 上级区域 | 级联选择 | 是 | — | 区域树 | — | | 区域责任人 | 下拉单选 | 是 | — | 组织架构-人员 | — | | 蓝牙Beacon | 下拉单选 | 是 | — | 蓝牙设备管理 | — | | 保洁清单 | 下拉多选 | 是 | — | 保洁清单模板 | 至少选一个 | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 区域树 | /api/v1/cleaning-areas/tree | GET | 五级树形结构 | | 新增 | /api/v1/cleaning-areas | POST | — | | 编辑 | /api/v1/cleaning-areas/{id} | PUT | — | | 删除 | /api/v1/cleaning-areas/{id} | DELETE | — | ### 交互流程要求 1. **页面加载流程**:进入页面 → 调用区域树接口 GET /api/v1/cleaning-areas/tree → 渲染左侧五级树形结构 → 默认选中第一个项目节点 → 右侧展示该节点详情信息 2. **查询/筛选交互流程**:点击树形节点 → 右侧实时刷新展示选中区域的详情(区域路径、责任人、蓝牙Beacon、当前排班) 3. **表单填写与提交流程**:点击[新增区域] → 弹窗表单 → 填写区域名称、选择上级区域(级联)、选择责任人、选择蓝牙Beacon、选择保洁清单 → 点击确认 → 提交 POST /api/v1/cleaning-areas → 成功后刷新树形结构并选中新节点 4. **弹窗/抽屉交互流程**:新增/编辑弹窗宽度520px,上级区域级联选择器懒加载展开,提交后自动关闭弹窗 5. **行内操作流程**:点击[编辑] → 弹窗回填当前区域数据 → 修改后提交 PUT /api/v1/cleaning-areas/{id} → 刷新右侧详情;点击[删除] → 二次确认弹窗("删除后不可恢复,确认删除?") → 确认后调用 DELETE → 刷新树形 6. **异常与错误处理**:区域名称重复提示"该区域名称已存在";存在排班关联时删除按钮置灰并Tooltip提示"该区域存在排班关联,不可删除";网络异常显示全局错误提示 7. **联动/级联交互**:上级区域级联选择器联动下级选项;选择项目后区域选项刷新,选择区域后楼栋选项刷新,依次类推 8. **权限控制交互表现**:无 cleaning:area:create 权限时[新增区域]按钮隐藏;无 cleaning:area:update 权限时[编辑]按钮隐藏;无 cleaning:area:delete 权限时[删除]按钮隐藏 9. **【H1 防重复请求】**: - 区域树加载:进入页面时调用 GET /api/v1/cleaning-areas/tree,loading 状态禁用树形节点点击;切换节点时右侧详情区展示 skeleton 加载占位 - 新增/提交:弹窗确认按钮 `:loading` + `:disabled` 防重复提交 - 行内操作:[编辑][删除]按钮操作中 disabled+loading 图标,防止连续点击 10. **【H2 统一超时】**: - GET(区域树)15s 超时;POST(新增)/PUT(编辑)/DELETE(删除)30s 超时 - 超时后中断请求、提示"请求超时,请检查网络后重试"、按钮状态恢复 - 响应时间 >3s 时自动显示全局 ElLoading 全屏遮罩提示"数据加载中..." 11. **【H3 操作确认(不可逆操作)】**: - 删除操作必须调用 confirm("确定要删除区域「{区域名称}」?删除后将不可恢复且关联排班将被影响", { type: "error", confirmButtonText: "确认删除", cancelButtonText: "取消" }) - 无排班关联时可执行删除,关联存在时按钮置灰并 Tooltip 提示 12. **【H4 脏数据检测(弹窗编辑)】**: - 编辑模式进入时对当前区域数据进行 deep clone 快照(JSON.parse(JSON.stringify(row))) - 弹窗内通过 watch/deepWatch 监测 isDirty 状态变化 - 关闭弹窗时若 isDirty 为 true,拦截并弹出 confirm("修改未保存,确定要关闭吗?") 13. **【H8 操作结果反馈】**: - 新增成功:ElMessage.success("区域创建成功", duration=2000),2秒后 silent 刷新树形结构并选中新节点 - 编辑成功:ElMessage.success("区域更新成功"),silent 刷新右侧详情 - 删除成功:ElMessage.success("删除成功"),刷新树形结构 - 失败:ElMessage.error(接口返回错误信息, duration=0) - 网络异常:ElMessage.error("网络连接异常,请检查网络") + 显示重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 区域树 | el-tree | :data="areaTree" node-key="id" :props="{label:'name',children:'children'}" highlight-current :expand-on-click-node="false" @node-click="handleNodeClick" | | 新增区域按钮 | el-button | type="primary" @click="showAddDialog" v-hasPermission="['cleaning:area:create']" | | 编辑按钮 | el-button | type="primary" link @click="showEditDialog" v-hasPermission="['cleaning:area:update']" | | 删除按钮 | el-button | type="danger" link @click="handleDelete" :disabled="hasScheduleBind" v-hasPermission="['cleaning:area:delete']" | | 新增/编辑弹窗 | el-dialog | :title="dialogTitle" v-model="dialogVisible" width="520px" :close-on-click-modal="false" | | 区域名称 | el-input | v-model="form.name" maxlength="30" show-word-limit placeholder="请输入区域名称" | | 上级区域 | el-cascader | v-model="form.parentId" :options="areaOptions" :props="{checkStrictly:true,emitPath:false,value:'id',label:'name'}" placeholder="请选择上级区域" clearable | | 区域责任人 | el-select | v-model="form.responsibleId" filterable placeholder="请选择责任人" | | 蓝牙Beacon | el-select | v-model="form.beaconId" filterable placeholder="请选择蓝牙Beacon" | | 保洁清单 | el-select | v-model="form.checklistIds" multiple collapse-tags collapse-tags-tooltip placeholder="请选择保洁清单" | | 删除确认 | el-message-box | confirmButtonText="确认" cancelButtonText="取消" type="warning" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 区域名称 | 必填,长度1-30字符 | 请输入区域名称 / 区域名称不能超过30个字符 | | 上级区域 | 必填 | 请选择上级区域 | | 区域责任人 | 必填 | 请选择区域责任人 | | 蓝牙Beacon | 必填 | 请选择蓝牙Beacon | | 保洁清单 | 必填,至少选择1项 | 请至少选择一个保洁清单 | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 左侧树形面板固定宽度280px,右侧详情区自适应剩余宽度,弹窗宽度520px | | 1024-1279px(Pad横屏) | 左侧树形面板宽度缩减至220px,右侧详情区自适应,弹窗宽度480px | | 768-1023px(Pad竖屏) | 树形面板折叠为顶部下拉选择器,详情区全宽展示,弹窗宽度90% | --- ## 页面2:保洁任务看板页 **页面编号**:PR-C-02-P01 **端侧归属**:Web专属 **页面路径**:/cleaning/tasks ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [面包屑] 保洁管理 > 保洁任务看板 │ ├──────────────────────────────────────────────────────────────────┤ │ [看板视图] │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 待执行(5) │ │ 执行中(3) │ │ 已完成(12)│ │ │ │ ┌──────┐ │ │ ┌──────┐ │ │ ┌──────┐ │ │ │ │ │门诊1层│ │ │ │门诊3层│ │ │ │门诊2层│ │ │ │ │ │张三 │ │ │ │李四 │ │ │ │王五 │ │ │ │ │ │06:00 │ │ │ │06:15 │ │ │ │07:00 │ │ │ │ │ └──────┘ │ │ └──────┘ │ │ └──────┘ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ ├──────────────────────────────────────────────────────────────────┤ │ [查询条件区] │ │ 日期[____] 班组[▼] 人员[____] 状态[▼] [查询] [重置] │ └──────────────────────────────────────────────────────────────────┘ ``` ### 查询条件 | 字段名 | 控件类型 | 必填 | 默认值 | 说明 | |--------|----------|------|--------|------| | 日期 | 日期选择 | 否 | 今天 | — | | 班组 | 下拉单选 | 否 | 全部 | — | | 人员 | 文本输入 | 否 | — | 模糊匹配 | | 状态 | 下拉单选 | 否 | 全部 | 待执行/执行中/已完成/超时 | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 查看详情 | cleaning:task:view | 卡片/行操作 | 始终 | 跳转任务详情 | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 任务列表 | /api/v1/cleaning-tasks | GET | 分页查询+看板数据 | ### 交互流程要求 1. **页面加载流程**:进入页面 → 默认查询条件为"今天+全部班组+全部状态" → 调用 GET /api/v1/cleaning-tasks → 渲染看板三列(待执行/执行中/已完成)及任务卡片 2. **查询/筛选交互流程**:修改日期/班组/人员/状态筛选条件 → 点击[查询] → 重新请求接口刷新看板数据;点击[重置] → 恢复默认条件并刷新 3. **表单填写与提交流程**:本页面无表单提交操作,仅查询展示 4. **弹窗/抽屉交互流程**:点击任务卡片[查看详情] → 跳转至任务详情页(新页面路由) 5. **行内操作流程**:点击任务卡片 → 展开卡片详情浮层(区域、人员、时间、清单);点击[查看详情]按钮 → 路由跳转至详情页 6. **异常与错误处理**:接口超时时显示"数据加载失败,请重试";无数据时看板列显示空状态el-empty;超时任务卡片边框红色高亮 7. **联动/级联交互**:筛选条件中班组与人员联动,选择班组后人员下拉仅显示该班组人员 8. **权限控制交互表现**:无 cleaning:task:view 权限时[查看详情]按钮隐藏,卡片仅展示基本信息 9. **【H1 防重复请求】**: - 查询按钮:点击后 `:loading` + `:disabled` 防止重复点击 - 看板加载:数据请求期间看板三列展示 skeleton 占位卡片 - 分页/翻页:切换日期或筛选条件时 abort 上一个未完成请求再发起新请求 10. **【H2 统一超时】**: - GET 任务列表 15s 超时 - 超时后中断请求、提示"数据加载超时"、查询按钮恢复可用 - 响应时间 >3s 时显示全局 ElLoading 提示"任务数据加载中..." 11. **【H8 操作结果反馈】**: - 数据加载成功:正常渲染看板,无需额外提示 - 加载失败:ElMessage.error("任务数据加载失败", duration=0) - 空数据:各列展示 el-empty "暂无任务数据" - 超时卡片边框红色高亮,配合 ElMessage.warning("存在超时任务,请及时处理") ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 看板容器 | 自定义看板组件 | 三列布局,每列header显示状态名+数量,列内任务卡片纵向排列 | | 任务卡片 | el-card | shadow="hover" :body-style="{padding:'12px'}" @click="viewDetail" | | 状态标签 | el-tag | :type="statusType" 待执行=info 执行中=warning 已完成=success 超时=danger | | 日期筛选 | el-date-picker | v-model="query.date" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" | | 班组筛选 | el-select | v-model="query.teamId" clearable placeholder="全部班组" | | 人员筛选 | el-input | v-model="query.staffName" clearable placeholder="输入人员姓名" | | 状态筛选 | el-select | v-model="query.status" clearable placeholder="全部状态" | | 查询按钮 | el-button | type="primary" @click="handleQuery" | | 重置按钮 | el-button | @click="handleReset" | | 查看详情按钮 | el-button | type="primary" link @click="viewDetail" v-hasPermission="['cleaning:task:view']" | | 空状态 | el-empty | description="暂无任务数据" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 日期 | 非必填,格式YYYY-MM-DD | 日期格式不正确 | | 人员 | 非必填,最大20字符 | — | | 状态 | 非必填,枚举值:pending/ongoing/completed/timeout | — | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 看板三列横向排列,每列宽度均分,查询条件区水平排列 | | 1024-1279px(Pad横屏) | 看板三列横向排列,卡片内容字号略减,查询条件区水平排列 | | 768-1023px(Pad竖屏) | 看板改为纵向堆叠,每列占满宽度;查询条件区换行排列,每行2个条件 | --- ## 页面3:人员排班页 **页面编号**:PR-C-03-P01 **端侧归属**:Web专属 **页面路径**:/cleaning/schedules ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [面包屑] 保洁管理 > 人员排班 │ ├──────────────────────────────────────────────────────────────────┤ │ [视图切换] 📅周视图 📆月视图 [◀ 本周 ▶] [复制上周排班] │ ├──────────────────────────────────────────────────────────────────┤ │ [周视图] │ │ 区域/人员 | 周一 | 周二 | 周三 | ... | 周日 │ │ 门诊1层大厅 | 张三早班| 张三早班| 李四早班| ... | 张三早班 │ │ 门诊2层走廊 | 王五早班| 王五早班| 王五早班| ... | — │ │ 住院1层 | 李四晚班| 李四晚班| — | ... | 李四晚班 │ ├──────────────────────────────────────────────────────────────────┤ │ [操作] [保存排班] [清空本周] [导出排班表] │ └──────────────────────────────────────────────────────────────────┘ ``` ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 复制上周排班 | cleaning:schedule:create | 操作栏 | 始终 | 一键复制上周排班到本周 | | 保存排班 | cleaning:schedule:update | 操作栏 | 始终 | — | | 清空本周 | cleaning:schedule:delete | 操作栏 | 始终 | 二次确认 | | 导出排班表 | cleaning:schedule:export | 操作栏 | 始终 | 导出Excel | ### 表单字段(排班编辑弹窗) | 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 | |--------|----------|------|--------|----------|----------| | 保洁人员 | 下拉单选 | 是 | — | 组织架构-保洁人员 | — | | 班次 | 下拉单选 | 是 | — | 字典管理-班次 | 早班/晚班/全天 | | 时间范围 | 时间范围 | 是 | — | 自填 | — | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 排班查询 | /api/v1/cleaning-schedules | GET | 按周/月查询 | | 保存排班 | /api/v1/cleaning-schedules/batch | POST | 批量保存 | | 复制排班 | /api/v1/cleaning-schedules/copy | POST | 从指定周复制 | | 导出 | /api/v1/cleaning-schedules/export | GET | 导出Excel | ### 交互流程要求 1. **页面加载流程**:进入页面 → 默认显示本周周视图 → 调用排班查询API GET /api/v1/cleaning-schedules → 渲染周视图排班表格(区域×日期矩阵),同时加载班组下拉选项 2. **查询/筛选交互流程**:切换周视图/月视图 → 重新请求对应维度数据;点击左右箭头切换周/月 → 重新加载;选择班组 → 过滤显示该班组的排班数据 3. **表单填写与提交流程**:点击排班单元格 → 弹出编辑弹窗 → 选择保洁人员、班次、时间范围 → 确认后暂存到前端;点击[保存排班] → 批量提交所有变更 → 成功后刷新排班视图;点击[复制上周排班] → 调用复制API → 成功后刷新本周视图 4. **弹窗/抽屉交互流程**:排班编辑弹窗宽度420px,点击单元格打开;点击[清空本周] → 二次确认"确认清空本周所有排班数据?" → 确认后调用清空API 5. **行内操作流程**:点击排班单元格 → 弹出编辑弹窗 → 修改后暂存;已有排班数据的单元格显示人员和班次信息;空白单元格可点击新增 6. **异常与错误处理**:同一人员同一时段排班冲突时提示"该人员此时段已有排班";保存失败显示ElMessage.error;复制上周无数据时提示"上周无排班数据" 7. **联动/级联交互**:班次选择后自动填充时间范围(早班06:00-14:00/晚班14:00-22:00/全天08:00-17:00);周视图/月视图切换联动数据刷新 8. **权限控制交互表现**:无 cleaning:schedule:create 权限时[复制上周排班]按钮隐藏;无 cleaning:schedule:update 权限时排班单元格不可点击编辑;无 cleaning:schedule:delete 权限时[清空本周]按钮隐藏 9. **[H1]防重复请求** - [保存排班]按钮点击后::loading=true + 文案"保存中..." + disabled + 排班表格区域半透明遮罩;API返回后恢复 - [复制上周排班]按钮点击后立即 disabled + loading态,API返回后恢复 - [清空本周]按钮点击后 disabled + loading态(确认弹窗通过后执行) - 单元格编辑弹窗保存后:弹窗内保存按钮 :loading + 弹窗关闭期间父页面不可操作 - 周视图/月视图切换、左右箭头切换:abort上一请求再发新请求 10. **[H2]超时与加载反馈** - 排班数据查询(GET列表/周/月视图):timeout=15秒 - 保存排班/复制上周/清空本周(POST):timeout=30秒 - 超时 → ElMessage.error("请求超时,请检查网络后重试") + 按钮恢复 - 加载>2秒显示全局ElLoading 11. **[H3]操作确认机制** - 清空本周:ElMessageBox.confirm("确认清空本周所有排班数据?清开后数据无法恢复", "清空确认", { type: 'warning', confirmButtonText: '确认清空', cancelButtonText: '取消' }) - 复制上周:ElMessageBox.confirm("确定复制上周排班数据到本周?将覆盖本周已有排班", { type: 'info' }) 12. **[H4]脏数据检测** - 用户编辑任一单元格后排班表标记 isDirty=true - 切换周/月视图时:若 isDirty → ElMessageBox.confirm("当前有未保存的排班变更,切换视图将丢失未保存内容,是否继续?") - 离开页面时:beforeRouteLeave 导航守卫拦截,isDirty 则弹出确认提示 - 保存成功后将当前状态设为新快照,重置 isDirty=false 13. **[H8]操作结果反馈** - 保存成功:ElMessage.success("排班保存成功", duration=2000) + silent刷新排班视图 - 复制成功:ElMessage.success("已复制上周排班到本周") + 刷新 - 清空成功:ElMessage.success("已清空本周排班") + 刷新 - 冲突提示:ElMessage.warning("该人员此时段已有排班") + 标红冲突单元格 - 失败:ElMessage.error(错误信息, duration=0) ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 视图切换 | el-radio-group + el-radio-button | v-model="viewMode", size="default" | | 周导航 | 自定义组件 | 左右箭头+周显示,@prev/@next | | 班组筛选 | el-select | clearable, filterable, placeholder="全部班组" | | 周视图表格 | 自定义排班表格 | 行=区域,列=周一~周日,单元格可点击 | | 排班编辑弹窗 | el-dialog | title="编辑排班", width="420px", :close-on-click-modal="false" | | 保洁人员 | el-select | v-model="form.staffId", filterable, placeholder="请选择保洁人员" | | 班次 | el-select | v-model="form.shift", placeholder="请选择班次", @change="fillTimeRange" | | 时间范围 | el-time-picker | is-range, format="HH:mm", range-separator="至" | | 保存排班按钮 | el-button | type="primary", :loading="saving" | | 清空本周按钮 | el-button | type="danger" | | 复制上周按钮 | el-button | type="success" | | 导出按钮 | el-button | type="success", icon="Download" | | 二次确认 | el-message-box | type="warning", confirmButtonText="确认", cancelButtonText="取消" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 保洁人员 | 必选 | "请选择保洁人员" | | 班次 | 必选 | "请选择班次" | | 时间范围 | 必选,结束时间>开始时间 | "请选择时间范围" / "结束时间必须晚于开始时间" | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 周视图完整7列展示,排班编辑弹窗420px | | 1024-1279px(Pad横屏) | 周视图列宽缩窄,单元格字号略减,弹窗宽度380px | | 768-1023px(Pad竖屏) | 周视图改为3天一组展示(今天+后2天),左右滑动切换日期范围;弹窗宽度90vw | --- ## 页面4:蓝牙点位管理页 **页面编号**:PR-C-04-P01 **端侧归属**:Web专属 **页面路径**:/cleaning/beacon-points ### 查询条件 | 字段名 | 控件类型 | 必填 | 默认值 | 说明 | |--------|----------|------|--------|------| | 区域 | 级联选择 | 否 | 全部 | — | | Beacon状态 | 下拉单选 | 否 | 全部 | 在线/离线 | | 电量 | 下拉单选 | 否 | 全部 | 正常/低电量 | ### 列表字段 | 序号 | 字段名 | 列宽 | 支持排序 | 说明 | |------|--------|------|----------|------| | 1 | Beacon名称 | 120px | 否 | — | | 2 | UUID | 180px | 否 | — | | 3 | 绑定区域 | 150px | 否 | — | | 4 | 状态 | 80px | 是 | 在线(绿)/离线(红) | | 5 | 电量 | 80px | 是 | <20%=红色低电量 | | 6 | 最后心跳 | 140px | 是 | 超过15分钟=离线 | | 7 | 操作 | 100px | — | 编辑绑定/解绑 | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 编辑绑定 | cleaning:area:update | 行操作 | 始终 | 绑定/更换区域 | | 解绑 | cleaning:area:update | 行操作 | 已绑定 | 二次确认 | ### 通知触发 | 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 | |----------|----------|----------|----------|----------| | Beacon离线 | 物业管理员 | 系统内通知 | Beacon离线预警 | 05 §5.2 (BEACON_OFFLINE) | | Beacon低电量 | 物业管理员 | 系统内通知 | Beacon低电量预警 | 05 §5.2 (BEACON_LOW_BATTERY) | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 列表查询 | /api/v1/cleaning-beacon-points | GET | — | | 绑定 | /api/v1/cleaning-beacon-points/{id}/bind | PUT | 绑定区域 | | 解绑 | /api/v1/cleaning-beacon-points/{id}/unbind | PUT | — | ### 交互流程要求 1. **页面加载流程**:进入页面 → 调用列表查询API GET /api/v1/cleaning-beacon-points → 渲染Beacon列表表格,同时加载区域级联数据;默认按Beacon名称排列 2. **查询/筛选交互流程**:选择区域/选择Beacon状态/选择电量状态 → 筛选条件变更后自动触发查询(无需手动点击查询按钮);区域级联选择逐级展开 3. **表单填写与提交流程**:点击[编辑绑定] → 弹窗选择要绑定的区域 → 确认后调用绑定API → 成功后刷新列表;点击[解绑] → 二次确认"确认解绑该Beacon与区域的绑定关系?" → 确认后调用解绑API 4. **弹窗/抽屉交互流程**:编辑绑定弹窗宽度480px,展示当前Beacon信息+区域级联选择器;点击遮罩层可关闭 5. **行内操作流程**:点击[编辑绑定] → 弹窗选择新区域 → 提交 → 刷新行数据;点击[解绑](已绑定时显示)→ 二次确认 → 解绑 → 刷新行数据 6. **异常与错误处理**:解绑未绑定的Beacon时提示"该Beacon未绑定区域";API请求失败显示ElMessage.error;Beacon离线状态实时刷新(每30秒轮询心跳数据) 7. **联动/级联交互**:区域筛选级联选择——选择项目→加载区域→选择区域→加载楼栋;Beacon状态根据心跳数据实时更新;电量<20%显示红色低电量标签 8. **权限控制交互表现**:无 cleaning:area:update 权限时[编辑绑定][解绑]按钮隐藏 9. **[H1]防重复请求** - 行内操作点击后该行禁用 + loading态 - 筛选条件变更自动触发查询时 abort 上一个未完成请求再发新请求 10. **[H2]超时与加载反馈** - GET列表查询 timeout=15秒;POST/PUT写操作 timeout=30秒 - 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复 - 加载>2秒显示全局loading 11. **[H3]操作确认机制**(有不可逆操作时) - 解绑: ElMessageBox.confirm("确认解绑该Beacon与区域的绑定关系?", { type: 'warning' }) 12. **[H4]脏数据检测** - 编辑模式进入时deep clone快照 - isDirty检测 + 取消/离开拦截 13. **[H8]操作结果反馈** - 成功: success(2s) + silent刷新 - 失败: error(0手动关闭) - 网络: 异常提示+重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 区域筛选 | el-cascader | :props="{checkStrictly:true, emitPath:false}", clearable, filterable, placeholder="选择区域" | | Beacon状态筛选 | el-select | clearable, placeholder="全部状态" | | 电量筛选 | el-select | clearable, placeholder="全部" | | 列表 | el-table | stripe, border, :data="tableData" | | Beacon状态标签 | el-tag | 在线=success / 离线=danger | | 电量显示 | el-progress | :percentage="row.battery", :color="batteryColor", :stroke-width="8", :text-inside="true" | | 绑定区域 | el-link | type="primary", @click="viewArea" | | 编辑绑定按钮 | el-button | type="primary", link | | 解绑按钮 | el-button | type="danger", link, v-if="row.bindAreaId" | | 编辑绑定弹窗 | el-dialog | title="编辑Beacon绑定", width="480px", :close-on-click-modal="true" | | 区域选择 | el-cascader | :props="{checkStrictly:true, emitPath:false}", filterable, placeholder="请选择绑定区域" | | 解绑确认 | el-message-box | type="warning", confirmButtonText="确认解绑", cancelButtonText="取消" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 绑定区域 | 编辑绑定时必选 | "请选择绑定区域" | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 筛选条件区水平排列,表格完整展示全部7列 | | 1024-1279px(Pad横屏) | 筛选条件区换行排列,表格隐藏"UUID"列 | | 768-1023px(Pad竖屏) | 筛选条件区垂直堆叠,表格仅显示Beacon名称、绑定区域、状态、操作列 | --- ## 页面5:超时预警页 **页面编号**:PR-C-05-P01 **端侧归属**:Web专属 **页面路径**:/cleaning/timeouts ### 列表字段 | 序号 | 字段名 | 列宽 | 支持排序 | 说明 | |------|--------|------|----------|------| | 1 | 任务区域 | 150px | 否 | — | | 2 | 保洁人员 | 80px | 否 | — | | 3 | 计划完成时间 | 140px | 是 | — | | 4 | 超时时长 | 80px | 是 | 红色标记 | | 5 | 当前状态 | 100px | 否 | 超时未开始/超时未完成 | | 6 | 操作 | 100px | — | 催办/查看 | ### 通知触发 | 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 | |----------|----------|----------|----------|----------| | 任务超时 | 物业主管 | 小程序推送 | 保洁超时预警 | 01 §7.1 / 05 §5.2 (CLEANING_TIMEOUT) | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 超时列表 | /api/v1/cleaning-tasks/timeouts | GET | 仅显示超时任务 | ### 交互流程要求 1. **页面加载流程**:进入页面 → 调用超时列表API GET /api/v1/cleaning-tasks/timeouts → 渲染超时任务表格,默认按超时时长降序排列 2. **查询/筛选交互流程**:本页无独立筛选条件,仅展示超时任务列表;数据由后端自动筛选超时任务 3. **表单填写与提交流程**:点击[催办] → 调用催办API → 发送小程序推送通知对应保洁人员 → 成功后刷新该行状态;点击[查看] → 跳转任务详情页 4. **弹窗/抽屉交互流程**:催办操作弹出确认弹窗"将向保洁人员发送催办通知,确认?" → 确认后发送催办 5. **行内操作流程**:点击[催办] → 二次确认 → 发送催办通知 → 刷新行数据;点击[查看] → 跳转任务详情页 6. **异常与错误处理**:催办失败提示"催办通知发送失败,请重试";列表无数据时显示ElEmpty"暂无超时任务,太棒了!" 7. **联动/级联交互**:超时时长列红色标记,时长越长颜色越深;催办后更新催办状态 8. **权限控制交互表现**:本页仅物业管理员和主管可见;主管仅看本班组超时数据 9. **[H1]防重复请求** - 催办按钮点击后 disabled + loading态,API返回后恢复 10. **[H2]超时与加载反馈** - GET列表查询 timeout=15秒;POST催办 timeout=30秒 - 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复 - 加载>2秒显示全局loading 11. **[H3]操作确认机制**(有不可逆操作时) - 催办: ElMessageBox.confirm("将向保洁人员发送催办通知,确认?", { type: 'warning' }) 12. **[H8]操作结果反馈** - 成功: success(2s) + silent刷新 - 失败: error(0手动关闭) - 网络: 异常提示+重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 列表 | el-table | stripe, border, :data="timeoutList", :row-class-name="timeoutRowClass" | | 超时时长 | el-tag | type="danger", 超时越长字体越大 | | 当前状态标签 | el-tag | 超时未开始=danger / 超时未完成=danger, effect="dark" | | 催办按钮 | el-button | type="warning", link, icon="Bell" | | 查看按钮 | el-button | type="primary", link | | 催办确认 | el-message-box | type="warning", confirmButtonText="确认催办", cancelButtonText="取消" | | 空状态 | el-empty | description="暂无超时任务,太棒了!" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | — | — | — | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 表格完整展示全部6列 | | 1024-1279px(Pad横屏) | 表格隐藏"计划完成时间"列 | | 768-1023px(Pad竖屏) | 表格仅显示任务区域、保洁人员、超时时长、操作列 | --- ## 页面6:保洁抽查页 **页面编号**:PR-C-06-P01 **端侧归属**:Web专属 **页面路径**:/cleaning/spot-checks ### 查询条件 | 字段名 | 控件类型 | 必填 | 默认值 | 说明 | |--------|----------|------|--------|------| | 抽查结果 | 下拉单选 | 否 | 全部 | 合格/不合格 | | 抽查人 | 文本输入 | 否 | — | 模糊匹配 | | 日期范围 | 日期范围 | 否 | — | — | ### 列表字段 | 序号 | 字段名 | 列宽 | 支持排序 | 说明 | |------|--------|------|----------|------| | 1 | 任务区域 | 150px | 否 | — | | 2 | 保洁人员 | 80px | 否 | — | | 3 | 抽查人 | 80px | 否 | 主管名称 | | 4 | 抽查时间 | 140px | 是 | 默认倒序 | | 5 | 抽查结果 | 80px | 否 | 合格(绿)/不合格(红) | | 6 | 不合格原因 | 150px | 否 | — | | 7 | 操作 | 100px | — | 标记抽查 | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 标记抽查 | cleaning:spot-check:approve | 操作栏 | 始终 | 弹窗选择合格/不合格 | | 不合格→重新生成 | cleaning:spot-check:approve | 行操作 | 结果=不合格 | 重新生成该区域保洁任务 | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 抽查列表 | /api/v1/cleaning-spot-checks | GET | — | | 标记抽查 | /api/v1/cleaning-spot-checks | POST | — | ### 交互流程要求 1. **页面加载流程**:进入页面 → 调用抽查列表API GET /api/v1/cleaning-spot-checks → 渲染抽查记录表格,默认按抽查时间倒序排列 2. **查询/筛选交互流程**:选择抽查结果/输入抽查人/选择日期范围 → 点击[查询] → 重新加载数据 → 点击[重置]清空条件并重新加载 3. **表单填写与提交流程**:点击[标记抽查] → 弹窗选择合格/不合格,不合格时必填原因 → 确认后调用标记抽查API → 成功后刷新列表 4. **弹窗/抽屉交互流程**:标记抽查弹窗宽度480px,选择结果后不合格显示原因输入框;点击遮罩层不关闭 5. **行内操作流程**:不合格记录点击[重新生成] → 二次确认"将为该区域重新生成保洁任务,确认?" → 确认后调用重新生成API → 刷新行数据 6. **异常与错误处理**:重复标记提示"该任务已抽查过";重新生成失败提示ElMessage.error;列表无数据时显示ElEmpty 7. **联动/级联交互**:选择"不合格"时自动显示原因输入框;不合格记录自动触发重新生成按钮 8. **权限控制交互表现**:无 cleaning:spot-check:approve 权限时[标记抽查][重新生成]按钮隐藏 9. **[H1]防重复请求** - 查询按钮点击后 disabled + loading态,API返回后恢复 - 行内操作点击后该行禁用 + loading态 - 分页切换 abort上一请求再发新请求 10. **[H2]超时与加载反馈** - GET列表查询 timeout=15秒;POST/PUT写操作 timeout=30秒 - 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复 - 加载>2秒显示全局loading 11. **[H3]操作确认机制**(有不可逆操作时) - 重新生成: ElMessageBox.confirm("将为该区域重新生成保洁任务,确认?", { type: 'warning' }) 12. **[H4]脏数据检测** - 编辑模式进入时deep clone快照 - isDirty检测 + 取消/离开拦截 13. **[H8]操作结果反馈** - 成功: success(2s) + silent刷新 - 失败: error(0手动关闭) - 网络: 异常提示+重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 抽查结果筛选 | el-select | clearable, placeholder="全部结果" | | 抽查人输入 | el-input | clearable, maxlength=20, placeholder="请输入抽查人" | | 日期范围 | el-date-picker | type="daterange", value-format="YYYY-MM-DD", range-separator="至" | | 列表 | el-table | stripe, border, :data="tableData" | | 抽查结果标签 | el-tag | 合格=success / 不合格=danger | | 标记抽查按钮 | el-button | type="primary", icon="Check" | | 重新生成按钮 | el-button | type="warning", link, v-if="row.result==='unqualified'" | | 标记抽查弹窗 | el-dialog | title="标记抽查", width="480px", :close-on-click-modal="false" | | 抽查结果 | el-radio-group | v-model="checkForm.result" | | 不合格原因 | el-input | type="textarea", :rows="3", maxlength=200, show-word-limit, v-if="checkForm.result==='unqualified'" | | 二次确认 | el-message-box | type="warning" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 抽查结果 | 必选 | "请选择抽查结果" | | 不合格原因 | 不合格时必填,maxlength=200 | "请填写不合格原因" | | 日期范围 | 结束日期≥开始日期 | "结束日期不能早于开始日期" | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 查询条件区水平排列,表格完整展示全部7列 | | 1024-1279px(Pad横屏) | 查询条件区换行排列,表格隐藏"不合格原因"列 | | 768-1023px(Pad竖屏) | 查询条件区垂直堆叠,表格仅显示任务区域、保洁人员、抽查结果、操作列 | --- ## 页面7:数据补录与补录审核页 **页面编号**:PR-C-07-P01 / PR-C-08-P01 **端侧归属**:Web专属 **页面路径**:/cleaning/supplement ### 补录数据标记规范 | 标记项 | 说明 | |--------|------| | is_supplement | true | | supplement_reason | 蓝牙故障/系统异常/定位失败/其他 | | supplement_audit_status | 待审核/通过/驳回 | | 统计排除 | 补录数据在统计中单独标记 | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 审核 | cleaning:supplement:approve | 行操作 | 审核状态=待审核 | 通过/驳回 | ### 交互流程要求 1. **页面加载流程**:进入页面 → 调用补录列表API → 渲染补录数据表格,默认按补录时间倒序排列,每页20条;同时加载审核状态下拉选项 2. **查询/筛选交互流程**:选择审核状态/输入补录人/选择日期范围 → 点击[查询] → 重新加载数据 → 点击[重置]清空条件 3. **表单填写与提交流程**:本页无新增表单,补录数据由小程序端提交 4. **弹窗/抽屉交互流程**:点击[审核](审核状态=待审核时显示)→ 弹出审核弹窗,选择"通过"或"驳回",驳回时必填驳回原因 → 确认后调用审核API → 成功后关闭弹窗并刷新列表 5. **行内操作流程**:点击[审核] → 弹窗选择通过/驳回 → 提交 → 刷新该行审核状态和审核人/审核时间 6. **异常与错误处理**:审核已审核过的记录时提示"该记录已审核";API请求失败显示ElMessage.error;列表无数据时显示ElEmpty 7. **联动/级联交互**:审核状态筛选影响列表展示;补录数据标记规范中is_supplement=true的数据在此页面展示 8. **权限控制交互表现**:无 cleaning:supplement:approve 权限时[审核]按钮隐藏 9. **【H1 防重复请求】**: - 查询按钮 `:loading` + `:disabled` 防重复点击 - 分页切换时 abort 上一个未完成请求再发新请求 - [审核]按钮及弹窗确认按钮操作中 disabled+loading 10. **【H2 统一超时】**: - GET(补录列表)15s 超时;PUT(审核)30s 超时 - 超时后中断请求、提示"请求超时" - 响应时间 >3s 时全局 ElLoading 11. **【H3 操作确认(不可逆操作)**: - 审核通过:confirm("确认通过该补录数据?通过后数据将纳入正常统计", { type: "info", confirmButtonText: "确认通过", cancelButtonText: "取消" }) - 审核驳回:confirm("确认驳回该补录数据?驳回后需补录人重新提交", { type: "warning", confirmButtonText: "确认驳回", cancelButtonText: "取消",含后果说明 }) 12. **【H4 脏数据检测(审核弹窗)】**: - 审核弹窗打开时初始化空审核表单快照 - 选择通过/驳回或填写驳回原因后检测 isDirty - 关闭弹窗若 isDirty 为 true 拦截并 confirm("审核结果未提交,确定要关闭?") 13. **【H8 操作结果反馈】**: - 审核成功:ElMessage.success(审核结果 === 'pass' ? "审核通过" : "已驳回"),silent 刷新列表行状态 - 重复审核:ElMessage.warning("该记录已审核") - 操作失败:ElMessage.error(错误信息, duration=0) - 网络异常:ElMessage.error("网络连接异常") + 重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 审核状态筛选 | el-select | clearable, placeholder="全部状态" | | 补录人输入 | el-input | clearable, maxlength=20, placeholder="请输入补录人" | | 日期范围 | el-date-picker | type="daterange", value-format="YYYY-MM-DD", range-separator="至" | | 列表 | el-table | stripe, border, :data="tableData" | | 分页 | el-pagination | layout="total, sizes, prev, pager, next", :page-sizes="[10,20,50]" | | 审核状态标签 | el-tag | 待审核=warning / 已通过=success / 已驳回=danger | | 审核按钮 | el-button | type="primary", link, v-if="row.auditStatus==='pending'" | | 审核弹窗 | el-dialog | title="审核补录", width="500px", :close-on-click-modal="false" | | 审核结果 | el-radio-group | v-model="auditForm.result" | | 驳回原因 | el-input | type="textarea", :rows="3", maxlength=200, show-word-limit, v-if="auditForm.result==='reject'" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 审核结果 | 必选 | "请选择审核结果" | | 驳回原因 | 驳回时必填,maxlength=200 | "请填写驳回原因" | | 日期范围 | 结束日期≥开始日期 | "结束日期不能早于开始日期" | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 查询条件区水平排列,表格完整展示,弹窗宽度500px | | 1024-1279px(Pad横屏) | 查询条件区换行排列,表格隐藏次要列,弹窗宽度460px | | 768-1023px(Pad竖屏) | 查询条件区垂直堆叠,表格仅显示关键列,弹窗宽度90vw | --- ## 需求追溯 | 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 | |------------|----------|----------|----------|----------| | PR-C-01 | 保洁区域管理 | 02-物业公司 §3 / 03-物业公司 §3 | 五级架构→排班→任务生成 | 巡检区域管理(复用架构) | | PR-C-02 | 保洁任务看板 | 02-物业公司 §3 / 03-物业公司 §3 | — | 小程序端今日保洁(MP-CL-01) | | PR-C-03 | 人员排班 | 02-物业公司 §3 / 03-物业公司 §3 | 排班→自动生成每日任务 | 组织架构→人员管理 | | PR-C-04 | 蓝牙点位管理 | 02-物业公司 §3 | 区域→Beacon绑定 | 系统配置→蓝牙设备管理 | | PR-C-05 | 超时预警 | 02-物业公司 §3 / 03-物业公司 §3 | 超时→推送主管 | 通知机制 | | PR-C-06 | 保洁抽查 | 02-物业公司 §3 / 03-物业公司 §3 | 不合格→重新生成任务 | 小程序端抽查标记(MP-CL-05) | | PR-C-07 | 数据补录 | 02-物业公司 §3 / 03-物业公司 §2.2 | 补录→审核 | 小程序端异常数据补录(MP-CL-07) | | PR-C-08 | 补录审核 | 02-物业公司 §3 / 03-物业公司 §2.2 | 审核→通知补录人 | 操作日志→补录日志 | ## 业务规则 1. **五级架构**:项目→区域→楼栋→楼层→区域责任人,最末级必须指定责任人(来源:02-物业公司 PR-C-01) 2. **排班自动生成任务**:根据排班数据自动生成每日保洁任务(来源:03-物业公司 §3) 3. **蓝牙打卡确认**:策略=REQUIRED时必须连接Beacon后才可确认完成,失败进入补录模式(来源:06 §4.4) 4. **蓝牙双模式**:策略=OPTIONAL时允许手动打卡(check_type=MANUAL)(来源:06 §4.4) 5. **超时预警**:任务超过计划完成时间未完成,系统自动预警推送主管(来源:02-物业公司 PR-C-05 / 03-物业公司 §3) 6. **抽查不合格**:主管标记不合格后,系统自动重新生成该区域保洁任务(来源:03-物业公司 §3) 7. **补录流程**:与巡检一致,补录需主管审核(来源:03-物业公司 §2.2)