保洁管理
模块编码: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 |
— |
交互流程要求
- 页面加载流程:进入页面 → 调用区域树接口 GET /api/v1/cleaning-areas/tree → 渲染左侧五级树形结构 → 默认选中第一个项目节点 → 右侧展示该节点详情信息
- 查询/筛选交互流程:点击树形节点 → 右侧实时刷新展示选中区域的详情(区域路径、责任人、蓝牙Beacon、当前排班)
- 表单填写与提交流程:点击[新增区域] → 弹窗表单 → 填写区域名称、选择上级区域(级联)、选择责任人、选择蓝牙Beacon、选择保洁清单 → 点击确认 → 提交 POST /api/v1/cleaning-areas → 成功后刷新树形结构并选中新节点
- 弹窗/抽屉交互流程:新增/编辑弹窗宽度520px,上级区域级联选择器懒加载展开,提交后自动关闭弹窗
- 行内操作流程:点击[编辑] → 弹窗回填当前区域数据 → 修改后提交 PUT /api/v1/cleaning-areas/{id} → 刷新右侧详情;点击[删除] → 二次确认弹窗("删除后不可恢复,确认删除?") → 确认后调用 DELETE → 刷新树形
- 异常与错误处理:区域名称重复提示"该区域名称已存在";存在排班关联时删除按钮置灰并Tooltip提示"该区域存在排班关联,不可删除";网络异常显示全局错误提示
- 联动/级联交互:上级区域级联选择器联动下级选项;选择项目后区域选项刷新,选择区域后楼栋选项刷新,依次类推
- 权限控制交互表现:无 cleaning:area:create 权限时[新增区域]按钮隐藏;无 cleaning:area:update 权限时[编辑]按钮隐藏;无 cleaning:area:delete 权限时[删除]按钮隐藏
- 【H1 防重复请求】:
- 区域树加载:进入页面时调用 GET /api/v1/cleaning-areas/tree,loading 状态禁用树形节点点击;切换节点时右侧详情区展示 skeleton 加载占位
- 新增/提交:弹窗确认按钮
:loading + :disabled 防重复提交
- 行内操作:[编辑][删除]按钮操作中 disabled+loading 图标,防止连续点击
- 【H2 统一超时】:
- GET(区域树)15s 超时;POST(新增)/PUT(编辑)/DELETE(删除)30s 超时
- 超时后中断请求、提示"请求超时,请检查网络后重试"、按钮状态恢复
- 响应时间 >3s 时自动显示全局 ElLoading 全屏遮罩提示"数据加载中..."
- 【H3 操作确认(不可逆操作)】:
- 删除操作必须调用 confirm("确定要删除区域「{区域名称}」?删除后将不可恢复且关联排班将被影响", { type: "error", confirmButtonText: "确认删除", cancelButtonText: "取消" })
- 无排班关联时可执行删除,关联存在时按钮置灰并 Tooltip 提示
- 【H4 脏数据检测(弹窗编辑)】:
- 编辑模式进入时对当前区域数据进行 deep clone 快照(JSON.parse(JSON.stringify(row)))
- 弹窗内通过 watch/deepWatch 监测 isDirty 状态变化
- 关闭弹窗时若 isDirty 为 true,拦截并弹出 confirm("修改未保存,确定要关闭吗?")
- 【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 |
分页查询+看板数据 |
交互流程要求
- 页面加载流程:进入页面 → 默认查询条件为"今天+全部班组+全部状态" → 调用 GET /api/v1/cleaning-tasks → 渲染看板三列(待执行/执行中/已完成)及任务卡片
- 查询/筛选交互流程:修改日期/班组/人员/状态筛选条件 → 点击[查询] → 重新请求接口刷新看板数据;点击[重置] → 恢复默认条件并刷新
- 表单填写与提交流程:本页面无表单提交操作,仅查询展示
- 弹窗/抽屉交互流程:点击任务卡片[查看详情] → 跳转至任务详情页(新页面路由)
- 行内操作流程:点击任务卡片 → 展开卡片详情浮层(区域、人员、时间、清单);点击[查看详情]按钮 → 路由跳转至详情页
- 异常与错误处理:接口超时时显示"数据加载失败,请重试";无数据时看板列显示空状态el-empty;超时任务卡片边框红色高亮
- 联动/级联交互:筛选条件中班组与人员联动,选择班组后人员下拉仅显示该班组人员
- 权限控制交互表现:无 cleaning:task:view 权限时[查看详情]按钮隐藏,卡片仅展示基本信息
- 【H1 防重复请求】:
- 查询按钮:点击后
:loading + :disabled 防止重复点击
- 看板加载:数据请求期间看板三列展示 skeleton 占位卡片
- 分页/翻页:切换日期或筛选条件时 abort 上一个未完成请求再发起新请求
- 【H2 统一超时】:
- GET 任务列表 15s 超时
- 超时后中断请求、提示"数据加载超时"、查询按钮恢复可用
- 响应时间 >3s 时显示全局 ElLoading 提示"任务数据加载中..."
- 【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 |
交互流程要求
-
页面加载流程:进入页面 → 默认显示本周周视图 → 调用排班查询API GET /api/v1/cleaning-schedules → 渲染周视图排班表格(区域×日期矩阵),同时加载班组下拉选项
-
查询/筛选交互流程:切换周视图/月视图 → 重新请求对应维度数据;点击左右箭头切换周/月 → 重新加载;选择班组 → 过滤显示该班组的排班数据
-
表单填写与提交流程:点击排班单元格 → 弹出编辑弹窗 → 选择保洁人员、班次、时间范围 → 确认后暂存到前端;点击[保存排班] → 批量提交所有变更 → 成功后刷新排班视图;点击[复制上周排班] → 调用复制API → 成功后刷新本周视图
-
弹窗/抽屉交互流程:排班编辑弹窗宽度420px,点击单元格打开;点击[清空本周] → 二次确认"确认清空本周所有排班数据?" → 确认后调用清空API
-
行内操作流程:点击排班单元格 → 弹出编辑弹窗 → 修改后暂存;已有排班数据的单元格显示人员和班次信息;空白单元格可点击新增
-
异常与错误处理:同一人员同一时段排班冲突时提示"该人员此时段已有排班";保存失败显示ElMessage.error;复制上周无数据时提示"上周无排班数据"
-
联动/级联交互:班次选择后自动填充时间范围(早班06:00-14:00/晚班14:00-22:00/全天08:00-17:00);周视图/月视图切换联动数据刷新
-
权限控制交互表现:无 cleaning:schedule:create 权限时[复制上周排班]按钮隐藏;无 cleaning:schedule:update 权限时排班单元格不可点击编辑;无 cleaning:schedule:delete 权限时[清空本周]按钮隐藏
-
[H1]防重复请求
- [保存排班]按钮点击后::loading=true + 文案"保存中..." + disabled + 排班表格区域半透明遮罩;API返回后恢复
- [复制上周排班]按钮点击后立即 disabled + loading态,API返回后恢复
- [清空本周]按钮点击后 disabled + loading态(确认弹窗通过后执行)
- 单元格编辑弹窗保存后:弹窗内保存按钮 :loading + 弹窗关闭期间父页面不可操作
- 周视图/月视图切换、左右箭头切换:abort上一请求再发新请求
-
[H2]超时与加载反馈
- 排班数据查询(GET列表/周/月视图):timeout=15秒
- 保存排班/复制上周/清空本周(POST):timeout=30秒
- 超时 → ElMessage.error("请求超时,请检查网络后重试") + 按钮恢复
- 加载>2秒显示全局ElLoading
-
[H3]操作确认机制
- 清空本周:ElMessageBox.confirm("确认清空本周所有排班数据?清开后数据无法恢复", "清空确认", { type: 'warning', confirmButtonText: '确认清空', cancelButtonText: '取消' })
- 复制上周:ElMessageBox.confirm("确定复制上周排班数据到本周?将覆盖本周已有排班", { type: 'info' })
-
[H4]脏数据检测
- 用户编辑任一单元格后排班表标记 isDirty=true
- 切换周/月视图时:若 isDirty → ElMessageBox.confirm("当前有未保存的排班变更,切换视图将丢失未保存内容,是否继续?")
- 离开页面时:beforeRouteLeave 导航守卫拦截,isDirty 则弹出确认提示
- 保存成功后将当前状态设为新快照,重置 isDirty=false
-
[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 |
— |
交互流程要求
- 页面加载流程:进入页面 → 调用列表查询API GET /api/v1/cleaning-beacon-points → 渲染Beacon列表表格,同时加载区域级联数据;默认按Beacon名称排列
- 查询/筛选交互流程:选择区域/选择Beacon状态/选择电量状态 → 筛选条件变更后自动触发查询(无需手动点击查询按钮);区域级联选择逐级展开
- 表单填写与提交流程:点击[编辑绑定] → 弹窗选择要绑定的区域 → 确认后调用绑定API → 成功后刷新列表;点击[解绑] → 二次确认"确认解绑该Beacon与区域的绑定关系?" → 确认后调用解绑API
- 弹窗/抽屉交互流程:编辑绑定弹窗宽度480px,展示当前Beacon信息+区域级联选择器;点击遮罩层可关闭
- 行内操作流程:点击[编辑绑定] → 弹窗选择新区域 → 提交 → 刷新行数据;点击[解绑](已绑定时显示)→ 二次确认 → 解绑 → 刷新行数据
- 异常与错误处理:解绑未绑定的Beacon时提示"该Beacon未绑定区域";API请求失败显示ElMessage.error;Beacon离线状态实时刷新(每30秒轮询心跳数据)
- 联动/级联交互:区域筛选级联选择——选择项目→加载区域→选择区域→加载楼栋;Beacon状态根据心跳数据实时更新;电量<20%显示红色低电量标签
- 权限控制交互表现:无 cleaning:area:update 权限时[编辑绑定][解绑]按钮隐藏
- [H1]防重复请求
- 行内操作点击后该行禁用 + loading态
- 筛选条件变更自动触发查询时 abort 上一个未完成请求再发新请求
- [H2]超时与加载反馈
- GET列表查询 timeout=15秒;POST/PUT写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
- 加载>2秒显示全局loading
- [H3]操作确认机制(有不可逆操作时)
- 解绑: ElMessageBox.confirm("确认解绑该Beacon与区域的绑定关系?", { type: 'warning' })
- [H4]脏数据检测
- 编辑模式进入时deep clone快照
- isDirty检测 + 取消/离开拦截
- [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 |
仅显示超时任务 |
交互流程要求
- 页面加载流程:进入页面 → 调用超时列表API GET /api/v1/cleaning-tasks/timeouts → 渲染超时任务表格,默认按超时时长降序排列
- 查询/筛选交互流程:本页无独立筛选条件,仅展示超时任务列表;数据由后端自动筛选超时任务
- 表单填写与提交流程:点击[催办] → 调用催办API → 发送小程序推送通知对应保洁人员 → 成功后刷新该行状态;点击[查看] → 跳转任务详情页
- 弹窗/抽屉交互流程:催办操作弹出确认弹窗"将向保洁人员发送催办通知,确认?" → 确认后发送催办
- 行内操作流程:点击[催办] → 二次确认 → 发送催办通知 → 刷新行数据;点击[查看] → 跳转任务详情页
- 异常与错误处理:催办失败提示"催办通知发送失败,请重试";列表无数据时显示ElEmpty"暂无超时任务,太棒了!"
- 联动/级联交互:超时时长列红色标记,时长越长颜色越深;催办后更新催办状态
- 权限控制交互表现:本页仅物业管理员和主管可见;主管仅看本班组超时数据
- [H1]防重复请求
- 催办按钮点击后 disabled + loading态,API返回后恢复
- [H2]超时与加载反馈
- GET列表查询 timeout=15秒;POST催办 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
- 加载>2秒显示全局loading
- [H3]操作确认机制(有不可逆操作时)
- 催办: ElMessageBox.confirm("将向保洁人员发送催办通知,确认?", { type: 'warning' })
- [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 |
— |
交互流程要求
- 页面加载流程:进入页面 → 调用抽查列表API GET /api/v1/cleaning-spot-checks → 渲染抽查记录表格,默认按抽查时间倒序排列
- 查询/筛选交互流程:选择抽查结果/输入抽查人/选择日期范围 → 点击[查询] → 重新加载数据 → 点击[重置]清空条件并重新加载
- 表单填写与提交流程:点击[标记抽查] → 弹窗选择合格/不合格,不合格时必填原因 → 确认后调用标记抽查API → 成功后刷新列表
- 弹窗/抽屉交互流程:标记抽查弹窗宽度480px,选择结果后不合格显示原因输入框;点击遮罩层不关闭
- 行内操作流程:不合格记录点击[重新生成] → 二次确认"将为该区域重新生成保洁任务,确认?" → 确认后调用重新生成API → 刷新行数据
- 异常与错误处理:重复标记提示"该任务已抽查过";重新生成失败提示ElMessage.error;列表无数据时显示ElEmpty
- 联动/级联交互:选择"不合格"时自动显示原因输入框;不合格记录自动触发重新生成按钮
- 权限控制交互表现:无 cleaning:spot-check:approve 权限时[标记抽查][重新生成]按钮隐藏
- [H1]防重复请求
- 查询按钮点击后 disabled + loading态,API返回后恢复
- 行内操作点击后该行禁用 + loading态
- 分页切换 abort上一请求再发新请求
- [H2]超时与加载反馈
- GET列表查询 timeout=15秒;POST/PUT写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
- 加载>2秒显示全局loading
- [H3]操作确认机制(有不可逆操作时)
- 重新生成: ElMessageBox.confirm("将为该区域重新生成保洁任务,确认?", { type: 'warning' })
- [H4]脏数据检测
- 编辑模式进入时deep clone快照
- isDirty检测 + 取消/离开拦截
- [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 |
行操作 |
审核状态=待审核 |
通过/驳回 |
交互流程要求
- 页面加载流程:进入页面 → 调用补录列表API → 渲染补录数据表格,默认按补录时间倒序排列,每页20条;同时加载审核状态下拉选项
- 查询/筛选交互流程:选择审核状态/输入补录人/选择日期范围 → 点击[查询] → 重新加载数据 → 点击[重置]清空条件
- 表单填写与提交流程:本页无新增表单,补录数据由小程序端提交
- 弹窗/抽屉交互流程:点击[审核](审核状态=待审核时显示)→ 弹出审核弹窗,选择"通过"或"驳回",驳回时必填驳回原因 → 确认后调用审核API → 成功后关闭弹窗并刷新列表
- 行内操作流程:点击[审核] → 弹窗选择通过/驳回 → 提交 → 刷新该行审核状态和审核人/审核时间
- 异常与错误处理:审核已审核过的记录时提示"该记录已审核";API请求失败显示ElMessage.error;列表无数据时显示ElEmpty
- 联动/级联交互:审核状态筛选影响列表展示;补录数据标记规范中is_supplement=true的数据在此页面展示
- 权限控制交互表现:无 cleaning:supplement:approve 权限时[审核]按钮隐藏
- 【H1 防重复请求】:
- 查询按钮
:loading + :disabled 防重复点击
- 分页切换时 abort 上一个未完成请求再发新请求
- [审核]按钮及弹窗确认按钮操作中 disabled+loading
- 【H2 统一超时】:
- GET(补录列表)15s 超时;PUT(审核)30s 超时
- 超时后中断请求、提示"请求超时"
- 响应时间 >3s 时全局 ElLoading
- 【H3 操作确认(不可逆操作):
- 审核通过:confirm("确认通过该补录数据?通过后数据将纳入正常统计", { type: "info", confirmButtonText: "确认通过", cancelButtonText: "取消" })
- 审核驳回:confirm("确认驳回该补录数据?驳回后需补录人重新提交", { type: "warning", confirmButtonText: "确认驳回", cancelButtonText: "取消",含后果说明 })
- 【H4 脏数据检测(审核弹窗)】:
- 审核弹窗打开时初始化空审核表单快照
- 选择通过/驳回或填写驳回原因后检测 isDirty
- 关闭弹窗若 isDirty 为 true 拦截并 confirm("审核结果未提交,确定要关闭?")
- 【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 |
审核→通知补录人 |
操作日志→补录日志 |
业务规则
- 五级架构:项目→区域→楼栋→楼层→区域责任人,最末级必须指定责任人(来源:02-物业公司 PR-C-01)
- 排班自动生成任务:根据排班数据自动生成每日保洁任务(来源:03-物业公司 §3)
- 蓝牙打卡确认:策略=REQUIRED时必须连接Beacon后才可确认完成,失败进入补录模式(来源:06 §4.4)
- 蓝牙双模式:策略=OPTIONAL时允许手动打卡(check_type=MANUAL)(来源:06 §4.4)
- 超时预警:任务超过计划完成时间未完成,系统自动预警推送主管(来源:02-物业公司 PR-C-05 / 03-物业公司 §3)
- 抽查不合格:主管标记不合格后,系统自动重新生成该区域保洁任务(来源:03-物业公司 §3)
- 补录流程:与巡检一致,补录需主管审核(来源:03-物业公司 §2.2)