You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

718 lines
42 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 组织架构
> 模块编码org
> 端侧Web + 小程序(双端)
> 关联文档01-模块划分 §3.4 / 02-功能清单-物业公司 §4 / 03-业务流转逻辑-物业公司 §4 / 05-接口规范 §9.2
> 强制规范遵循 `07-前端界面开发规范.md`
## 功能概览
| 项目 | 说明 |
|------|------|
| 菜单名称 | 组织架构 |
| 子菜单 | 班组管理、人员管理、人员分配、排班管理、技能管理、打卡点分配、下属账号管理 |
| 功能编号 | PR-O-01 ~ PR-O-11 |
| 权限编码前缀 | org:team:* / org:staff:* |
---
## 页面1班组管理页
**页面编号**PR-O-01-P01
**端侧归属**Web专属
**页面路径**/org/teams
### 界面布局
```
┌──────────────────────────────────────────────────────────────────┐
│ [面包屑] 组织架构 > 班组管理 │
├──────────────────────────────────────────────────────────────────┤
│ [查询条件区] │
│ 班组名称[____] 班组类型[▼] 状态[▼] [查询] [重置] │
├──────────────────────────────────────────────────────────────────┤
│ [操作栏] [新增班组] │
├──────────────────────────────────────────────────────────────────┤
│ [列表区] │
│ 序号| 班组名称 | 类型 | 班组长 | 人数 | 负责区域 | 状态 | 操作 │
│ 1 | 水电维修班| 维修 | 张三 | 8 | 门诊楼 | 启用 | 编辑 停用│
│ 2 | 巡检一班 | 巡检 | 李四 | 5 | 全院 | 启用 | 编辑 停用│
│ 3 | 保洁早班 | 保洁 | 王五 | 12 | 门诊+住院| 启用 | 编辑 停用│
├──────────────────────────────────────────────────────────────────┤
│ [分页] 共10条 │
└──────────────────────────────────────────────────────────────────┘
```
### 表单字段(新增/编辑弹窗)
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|--------|----------|------|--------|----------|----------|
| 班组名称 | 文本输入 | 是 | — | 自填 | 最大30字同租户唯一 |
| 班组类型 | 下拉单选 | 是 | — | 字典管理-班组类型 | 维修/巡检/保洁/综合 |
| 班组长 | 下拉单选 | 是 | — | 人员列表 | — |
| 负责区域 | 级联多选 | 否 | — | 区域五级架构 | — |
| 描述 | 多行文本 | 否 | — | 自填 | 最大200字 |
### 操作按钮
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|------|----------|------|----------|------|
| 新增班组 | org:team:create | 操作栏 | 始终 | — |
| 编辑 | org:team:update | 行操作 | 始终 | — |
| 停用 | org:team:update | 行操作 | 始终 | 有未完成任务时不可停用 |
### API端点
| 页面操作 | API路径 | 方法 | 说明 |
|----------|---------|------|------|
| 列表查询 | /api/v1/teams | GET | — |
| 新增 | /api/v1/teams | POST | — |
| 编辑 | /api/v1/teams/{id} | PUT | — |
### 交互流程要求
1. **页面加载流程**:进入页面 → 并行调用列表查询API GET /api/v1/teams 和下拉选项数据(班组类型字典)→ 渲染表格和筛选条件,默认加载全部班组数据
2. **查询/筛选交互流程**:输入班组名称/选择班组类型/选择状态 → 点击[查询] → 携带筛选参数重新请求 → 点击[重置]清空条件并重新加载;班组名称支持回车触发查询
3. **表单填写与提交流程**:点击[新增班组] → 弹窗表单 → 填写班组名称、班组类型、班组长、负责区域、描述 → 前端校验通过 → 调用新增API → 成功后关闭弹窗并刷新列表
4. **弹窗/抽屉交互流程**:新增/编辑弹窗宽度520px选择班组长时从人员列表中选择支持搜索负责区域使用级联多选点击遮罩层不关闭
5. **行内操作流程**:点击[编辑] → 弹窗回填当前班组数据 → 修改后提交 → 刷新列表;点击[停用] → 二次确认"停用后该班组下人员将无法接收新任务,确认停用?" → 有未完成任务时按钮置灰并提示"该班组存在未完成任务,不可停用"
6. **异常与错误处理**:班组名称重复提示"该班组名称已存在";停用有未完成任务的班组时提示"该班组存在未完成任务,不可停用"API请求失败显示ElMessage.error
7. **联动/级联交互**:选择班组类型后班组长下拉可按类型过滤;负责区域级联选择逐级展开
8. **权限控制交互表现**:无 org:team:create 权限时[新增班组]按钮隐藏;无 org:team:update 权限时[编辑][停用]按钮隐藏
9. **[H1]防重复请求**
- 查询按钮点击后 disabled + loading态API返回后恢复
- 行内操作点击后该行禁用 + loading态
- 分页切换 abort上一请求再发新请求
10. **[H2]超时与加载反馈**
- GET列表查询 timeout=15秒POST/PUT/DELETE写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
- 加载>2秒显示全局loading
11. **[H3]操作确认机制**(有不可逆操作时)
- 删除/停用: ElMessageBox.confirm/Web端或wx.showModal/小程序端
12. **[H4]脏数据检测**
- 编辑模式进入时deep clone快照
- isDirty检测 + 取消/离开拦截
13. **[H8]操作结果反馈**
- 成功: success(2s) + silent刷新
- 失败: error(0手动关闭)
- 网络: 异常提示+重试按钮
### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 班组名称输入 | el-input | placeholder="请输入班组名称", clearable, maxlength=30 |
| 班组类型筛选 | el-select | clearable, placeholder="全部类型" |
| 状态筛选 | el-select | clearable, placeholder="全部状态" |
| 列表 | el-table | stripe, border, :data="tableData" |
| 新增班组按钮 | el-button | type="primary", icon="Plus" |
| 编辑按钮 | el-button | type="primary", link |
| 停用按钮 | el-button | type="warning", link, :disabled="hasPendingTasks" |
| 状态标签 | el-tag | 启用=success / 停用=info |
| 新增/编辑弹窗 | el-dialog | :title="dialogTitle", width="520px", :close-on-click-modal="false" |
| 班组名称 | el-input | maxlength=30, show-word-limit, placeholder="请输入班组名称" |
| 班组类型 | el-select | placeholder="请选择班组类型", filterable |
| 班组长 | el-select | placeholder="请选择班组长", filterable |
| 负责区域 | el-cascader | :props="{multiple:true, checkStrictly:true, emitPath:false}", filterable, clearable |
| 描述 | el-input | type="textarea", :rows="3", maxlength=200, show-word-limit |
| 二次确认 | el-message-box | type="warning" |
### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 班组名称 | 必填maxlength=30同租户唯一 | "请输入班组名称" / "该班组名称已存在" |
| 班组类型 | 必选 | "请选择班组类型" |
| 班组长 | 必选 | "请选择班组长" |
### 响应式布局
| 断点 | 布局调整 |
|------|----------|
| ≥1280px桌面端 | 查询条件区水平排列表格完整展示全部列弹窗宽度520px |
| 1024-1279pxPad横屏 | 查询条件区换行排列,表格隐藏"负责区域"列弹窗宽度480px |
| 768-1023pxPad竖屏 | 查询条件区垂直堆叠表格仅显示班组名称、类型、班组长、状态、操作列弹窗宽度90vw |
---
## 页面2人员管理页
**页面编号**PR-O-02-P01
**端侧归属**Web专属
**页面路径**/org/staffs
### 查询条件
| 字段名 | 控件类型 | 必填 | 默认值 | 说明 |
|--------|----------|------|--------|------|
| 姓名 | 文本输入 | 否 | — | 模糊匹配 |
| 所属班组 | 下拉单选 | 否 | 全部 | — |
| 技能标签 | 下拉多选 | 否 | 全部 | — |
| 状态 | 下拉单选 | 否 | 全部 | 在职/离职 |
### 列表字段
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|------|--------|------|----------|------|
| 1 | 姓名 | 80px | 否 | — |
| 2 | 手机号 | 120px | 否 | 脱敏显示 |
| 3 | 所属班组 | 120px | 是 | 支持一人多班组,逗号分隔 |
| 4 | 技能标签 | 150px | 否 | 标签样式 |
| 5 | 角色 | 100px | 否 | 下属账号角色 |
| 6 | 状态 | 80px | 是 | 在职/离职 |
| 7 | 操作 | 160px | — | 编辑/分配/查看排班 |
### 表单字段(新增/编辑弹窗)
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|--------|----------|------|--------|----------|----------|
| 姓名 | 文本输入 | 是 | — | 自填 | 最大20字 |
| 手机号 | 文本输入 | 是 | — | 自填 | 手机号格式 |
| 所属班组 | 下拉多选 | 是 | — | 班组列表 | 支持一人多班组 |
| 技能标签 | 下拉多选 | 否 | — | 技能管理 | — |
| 入职日期 | 日期选择 | 否 | — | 自填 | — |
### 操作按钮
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|------|----------|------|----------|------|
| 新增人员 | org:staff:create | 操作栏 | 始终 | — |
| 编辑 | org:staff:update | 行操作 | 始终 | — |
| 分配 | org:staff:update | 行操作 | 始终 | 分配到班组/区域 |
### API端点
| 页面操作 | API路径 | 方法 | 说明 |
|----------|---------|------|------|
| 列表查询 | /api/v1/staffs | GET | — |
| 新增 | /api/v1/staffs | POST | — |
| 编辑 | /api/v1/staffs/{id} | PUT | — |
### 交互流程要求
1. **页面加载流程**:进入页面 → 并行调用人员列表API和下拉选项班组列表、技能标签列表→ 渲染表格和筛选条件
2. **查询/筛选交互流程**:输入姓名/选择所属班组/选择技能标签/选择状态 → 点击[查询] → 重新加载数据 → 点击[重置]清空条件
3. **表单填写与提交流程**:点击[新增人员] → 弹窗表单 → 填写姓名、手机号、所属班组(多选)、技能标签、入职日期 → 前端校验通过 → 调用新增API → 成功后关闭弹窗并刷新列表
4. **弹窗/抽屉交互流程**:新增/编辑弹窗宽度520px所属班组支持多选一人多班组使用collapse-tags折叠展示点击遮罩层不关闭
5. **行内操作流程**:点击[编辑] → 弹窗回填当前人员数据 → 修改后提交 → 刷新列表;点击[分配] → 弹窗分配到班组/区域;点击[查看排班] → 跳转排班管理页(带该人员筛选条件)
6. **异常与错误处理**:手机号已存在提示"该手机号已被注册"API请求失败显示ElMessage.error技能标签无数据时显示"暂无技能标签"
7. **联动/级联交互**所属班组多选后技能标签可根据班组关联过滤手机号脱敏显示138****1234
8. **权限控制交互表现**:无 org:staff:create 权限时[新增人员]按钮隐藏;无 org:staff:update 权限时[编辑][分配]按钮隐藏
9. **[H1]防重复请求**
- 查询按钮点击后 disabled + loading态API返回后恢复
- 行内操作点击后该行禁用 + loading态
- 分页切换 abort上一请求再发新请求
10. **[H2]超时与加载反馈**
- GET列表查询 timeout=15秒POST/PUT/DELETE写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
- 加载>2秒显示全局loading
11. **[H4]脏数据检测**
- 编辑模式进入时deep clone快照
- isDirty检测 + 取消/离开拦截
12. **[H8]操作结果反馈**
- 成功: success(2s) + silent刷新
- 失败: error(0手动关闭)
- 网络: 异常提示+重试按钮
### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 姓名输入 | el-input | clearable, maxlength=20, placeholder="请输入姓名" |
| 所属班组筛选 | el-select | clearable, filterable, placeholder="全部班组" |
| 技能标签筛选 | el-select | clearable, multiple, collapse-tags, placeholder="全部标签" |
| 状态筛选 | el-select | clearable, placeholder="全部状态" |
| 列表 | el-table | stripe, border, :data="tableData" |
| 新增人员按钮 | el-button | type="primary", icon="Plus" |
| 编辑按钮 | el-button | type="primary", link |
| 分配按钮 | el-button | type="success", link |
| 查看排班按钮 | el-button | type="primary", link |
| 技能标签列 | el-tag | v-for, type="primary", size="small", style="margin:2px" |
| 状态标签 | el-tag | 在职=success / 离职=info |
| 新增/编辑弹窗 | el-dialog | :title="dialogTitle", width="520px", :close-on-click-modal="false" |
| 姓名 | el-input | maxlength=20, placeholder="请输入姓名" |
| 手机号 | el-input | maxlength=11, placeholder="请输入手机号" |
| 所属班组 | el-select | v-model="form.teamIds", multiple, collapse-tags, filterable, placeholder="请选择所属班组" |
| 技能标签 | el-select | v-model="form.skillIds", multiple, collapse-tags, placeholder="请选择技能标签" |
| 入职日期 | el-date-picker | type="date", value-format="YYYY-MM-DD" |
### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 姓名 | 必填maxlength=20 | "请输入姓名" |
| 手机号 | 必填,正则/^1[3-9]\d{9}$/ | "请输入正确的手机号码" |
| 所属班组 | 必选至少1个 | "请选择所属班组" |
### 响应式布局
| 断点 | 布局调整 |
|------|----------|
| ≥1280px桌面端 | 查询条件区水平排列表格完整展示全部7列弹窗宽度520px |
| 1024-1279pxPad横屏 | 查询条件区换行排列,表格隐藏"技能标签"列弹窗宽度480px |
| 768-1023pxPad竖屏 | 查询条件区垂直堆叠表格仅显示姓名、班组、状态、操作列弹窗宽度90vw |
---
## 页面3排班管理页
**页面编号**PR-O-04-P01
**端侧归属**Web专属
**页面路径**/org/schedules
### 界面布局
```
┌──────────────────────────────────────────────────────────────────┐
│ [面包屑] 组织架构 > 排班管理 │
├──────────────────────────────────────────────────────────────────┤
│ [视图切换] 📅周视图 📆月视图 班组:[▼] [◀ 本周 ▶] │
├──────────────────────────────────────────────────────────────────┤
│ [周视图] │
│ 人员 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日│
│ 张三 | 早班 | 早班 | 晚班 | 早班 | 早班 | 休息 | 休息│
│ 李四 | 晚班 | 晚班 | 早班 | 晚班 | 晚班 | 休息 | 休息│
├──────────────────────────────────────────────────────────────────┤
│ [操作] [保存] [批量排班] [模板排班] [导出] │
└──────────────────────────────────────────────────────────────────┘
```
### 操作按钮
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|------|----------|------|----------|------|
| 批量排班 | org:team:create | 操作栏 | 始终 | 选择多人同一班次 |
| 模板排班 | org:team:create | 操作栏 | 始终 | 从已有模板加载 |
| 保存 | org:team:update | 操作栏 | 始终 | — |
| 导出 | org:team:export | 操作栏 | 始终 | 导出排班表 |
### API端点
| 页面操作 | API路径 | 方法 | 说明 |
|----------|---------|------|------|
| 排班查询 | /api/v1/team-schedules | GET | — |
| 保存 | /api/v1/team-schedules/batch | POST | — |
### 交互流程要求
1. **页面加载流程**:进入页面 → 默认显示本周周视图 → 调用排班查询API GET /api/v1/team-schedules → 渲染排班表格(人员×日期矩阵),同时加载班组下拉选项
2. **查询/筛选交互流程**:切换周视图/月视图 → 重新请求对应数据;点击左右箭头切换周 → 重新加载;选择班组 → 过滤显示该班组人员排班
3. **表单填写与提交流程**:点击排班单元格 → 弹出编辑弹窗选择班次 → 暂存前端;点击[保存] → 批量提交所有变更 → 成功后刷新排班视图;点击[批量排班] → 选择多人+统一班次 → 批量填充 → 保存;点击[模板排班] → 从已有模板加载
4. **弹窗/抽屉交互流程**排班编辑弹窗宽度400px选择班次批量排班弹窗宽度500px选择人员和班次模板排班弹窗宽度480px选择模板
5. **行内操作流程**:点击排班单元格 → 弹出班次选择 → 确认后暂存;点击已有班次可修改或清除
6. **异常与错误处理**:同一人员同一时段排班冲突时提示"排班冲突"保存失败显示ElMessage.error模板无数据时提示"暂无排班模板"
7. **联动/级联交互**:批量排班选择班次后自动填充时间范围;班组筛选联动人员列表刷新
8. **权限控制交互表现**:无 org:team:create 权限时[批量排班][模板排班]按钮隐藏;无 org:team:update 权限时排班单元格不可编辑;无 org:team:export 权限时[导出]按钮隐藏
9. **[H1]防重复请求**
- 查询/视图切换点击后 disabled + loading态API返回后恢复
- 保存操作点击后 disabled + loading态
- 分页切换 abort上一请求再发新请求
10. **[H2]超时与加载反馈**
- GET列表查询 timeout=15秒POST/PUT/DELETE写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
- 加载>2秒显示全局loading
11. **[H8]操作结果反馈**
- 成功: success(2s) + silent刷新
- 失败: error(0手动关闭)
- 网络: 异常提示+重试按钮
### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 视图切换 | el-radio-group + el-radio-button | v-model="viewMode" |
| 周导航 | 自定义组件 | 左右箭头+周显示 |
| 班组筛选 | el-select | clearable, filterable, placeholder="全部班组" |
| 排班表格 | 自定义排班表格 | 行=人员,列=周一~周日,单元格可点击 |
| 排班编辑弹窗 | el-dialog | title="编辑排班", width="400px", :close-on-click-modal="false" |
| 班次选择 | el-select | placeholder="请选择班次" |
| 批量排班弹窗 | el-dialog | title="批量排班", width="500px", :close-on-click-modal="false" |
| 人员多选 | el-select | v-model="batchForm.staffIds", multiple, collapse-tags, filterable |
| 批量班次 | el-select | v-model="batchForm.shift" |
| 模板排班弹窗 | el-dialog | title="选择排班模板", width="480px" |
| 模板列表 | el-select | placeholder="请选择模板" |
| 保存按钮 | el-button | type="primary", :loading="saving" |
| 批量排班按钮 | el-button | type="success" |
| 模板排班按钮 | el-button | type="warning" |
| 导出按钮 | el-button | type="success", icon="Download" |
### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 班次 | 必选 | "请选择班次" |
| 批量排班-人员 | 至少选1人 | "请选择人员" |
| 批量排班-班次 | 必选 | "请选择班次" |
| 模板排班-模板 | 必选 | "请选择排班模板" |
### 响应式布局
| 断点 | 布局调整 |
|------|----------|
| ≥1280px桌面端 | 排班表格完整7列展示操作按钮水平排列 |
| 1024-1279pxPad横屏 | 排班表格列宽缩窄,单元格字号略减 |
| 768-1023pxPad竖屏 | 排班表格改为3天一组展示左右滑动切换操作按钮折叠为下拉菜单 |
---
## 页面4技能管理页
**页面编号**PR-O-05-P01
**端侧归属**Web专属
**页面路径**/org/skills
### 列表字段
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|------|--------|------|----------|------|
| 1 | 技能名称 | 150px | 否 | 如:水电维修、空调维修 |
| 2 | 关联班组 | 150px | 否 | 使用该技能的班组 |
| 3 | 持有人员数 | 100px | 是 | — |
| 4 | 操作 | 100px | — | 编辑/删除 |
### 表单字段(新增/编辑弹窗)
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|--------|----------|------|--------|----------|----------|
| 技能名称 | 文本输入 | 是 | — | 自填 | 最大30字同租户唯一 |
| 关联班组 | 下拉多选 | 否 | — | 班组列表 | — |
| 描述 | 多行文本 | 否 | — | 自填 | 最大200字 |
### 交互流程要求
1. **页面加载流程**:进入页面 → 调用技能列表API → 渲染技能表格,默认按持有人员数降序排列
2. **查询/筛选交互流程**:本页无独立筛选条件,所有技能数据一次加载
3. **表单填写与提交流程**:点击[新增技能](如有操作栏按钮)→ 弹窗表单 → 填写技能名称、关联班组、描述 → 前端校验通过 → 调用新增API → 成功后关闭弹窗并刷新列表
4. **弹窗/抽屉交互流程**:新增/编辑弹窗宽度480px点击遮罩层不关闭
5. **行内操作流程**:点击[编辑] → 弹窗回填技能数据 → 修改后提交 → 刷新列表;点击[删除] → 二次确认"删除后持有该技能的人员将失去此标签,确认删除?" → 确认后调用删除API → 刷新列表
6. **异常与错误处理**:技能名称重复提示"该技能名称已存在";删除被引用的技能时提示"该技能正在使用中,不可删除"API请求失败显示ElMessage.error
7. **联动/级联交互**:关联班组多选后自动关联到该班组人员;持有人员数为实时统计值
8. **权限控制交互表现**:无新增/编辑/删除权限时对应按钮隐藏
9. **[H1]防重复请求**
- 行内操作点击后该行禁用 + loading态
10. **[H2]超时与加载反馈**
- GET列表查询 timeout=15秒POST/PUT/DELETE写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
11. **[H3]操作确认机制**(有不可逆操作时)
- 删除: ElMessageBox.confirm
12. **[H4]脏数据检测**
- 编辑模式进入时deep clone快照
- isDirty检测 + 取消/离开拦截
13. **[H8]操作结果反馈**
- 成功: success(2s) + silent刷新
- 失败: error(0手动关闭)
- 网络: 异常提示+重试按钮
### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 列表 | el-table | stripe, border, :data="skillList" |
| 新增按钮 | el-button | type="primary", icon="Plus" |
| 编辑按钮 | el-button | type="primary", link |
| 删除按钮 | el-button | type="danger", link |
| 新增/编辑弹窗 | el-dialog | :title="dialogTitle", width="480px", :close-on-click-modal="false" |
| 技能名称 | el-input | maxlength=30, show-word-limit, placeholder="请输入技能名称" |
| 关联班组 | el-select | v-model="form.teamIds", multiple, collapse-tags, filterable, placeholder="请选择关联班组" |
| 描述 | el-input | type="textarea", :rows="3", maxlength=200, show-word-limit |
| 删除确认 | el-message-box | type="warning" |
### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 技能名称 | 必填maxlength=30同租户唯一 | "请输入技能名称" / "该技能名称已存在" |
### 响应式布局
| 断点 | 布局调整 |
|------|----------|
| ≥1280px桌面端 | 表格完整展示全部4列弹窗宽度480px |
| 1024-1279pxPad横屏 | 表格隐藏"关联班组"列弹窗宽度440px |
| 768-1023pxPad竖屏 | 表格仅显示技能名称、持有人员数、操作列弹窗宽度90vw |
---
## 页面5打卡点分配页
**页面编号**PR-O-06-P01
**端侧归属**Web专属
**页面路径**/org/check-in-points
### 列表字段
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|------|--------|------|----------|------|
| 1 | 班组 | 120px | 否 | — |
| 2 | 打卡点名称 | 150px | 否 | — |
| 3 | 位置 | 150px | 否 | — |
| 4 | 蓝牙Beacon | 120px | 否 | — |
| 5 | 适用角色 | 100px | 否 | 全部/主管/员工 |
| 6 | 操作 | 100px | — | 编辑/删除 |
### 表单字段(新增/编辑弹窗)
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|--------|----------|------|--------|----------|----------|
| 打卡点名称 | 文本输入 | 是 | — | 自填 | 最大30字 |
| 适用班组 | 下拉单选 | 是 | — | 班组列表 | — |
| 位置描述 | 文本输入 | 是 | — | 自填 | — |
| 蓝牙Beacon | 下拉单选 | 是 | — | 蓝牙设备管理 | — |
| 适用角色 | 下拉多选 | 是 | 全部 | 固定选项 | — |
### 交互流程要求
1. **页面加载流程**:进入页面 → 调用打卡点列表API → 渲染打卡点表格同时加载班组下拉、蓝牙Beacon下拉选项
2. **查询/筛选交互流程**:本页无独立筛选条件,所有打卡点数据一次加载展示;可按班组筛选
3. **表单填写与提交流程**:点击[新增打卡点] → 弹窗表单 → 填写打卡点名称、适用班组、位置描述、蓝牙Beacon、适用角色 → 前端校验通过 → 调用新增API → 成功后关闭弹窗并刷新列表
4. **弹窗/抽屉交互流程**:新增/编辑弹窗宽度480px选择蓝牙Beacon后展示设备在线状态点击遮罩层不关闭
5. **行内操作流程**:点击[编辑] → 弹窗回填数据 → 修改后提交 → 刷新列表;点击[删除] → 二次确认 → 调用删除API → 刷新列表
6. **异常与错误处理**:打卡点名称重复提示"该打卡点名称已存在";删除被引用的打卡点提示"该打卡点正在使用中,不可删除"API请求失败显示ElMessage.error
7. **联动/级联交互**选择适用班组后蓝牙Beacon下拉可按班组区域过滤适用角色多选支持全选/反选
8. **权限控制交互表现**:无新增/编辑/删除权限时对应按钮隐藏
9. **[H1]防重复请求**
- 行内操作点击后该行禁用 + loading态
10. **[H2]超时与加载反馈**
- GET列表查询 timeout=15秒POST/PUT/DELETE写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
11. **[H3]操作确认机制**(有不可逆操作时)
- 删除: ElMessageBox.confirm
12. **[H4]脏数据检测**
- 编辑模式进入时deep clone快照
- isDirty检测 + 取消/离开拦截
13. **[H8]操作结果反馈**
- 成功: success(2s) + silent刷新
- 失败: error(0手动关闭)
- 网络: 异常提示+重试按钮
### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 列表 | el-table | stripe, border, :data="pointList" |
| 新增打卡点按钮 | el-button | type="primary", icon="Plus" |
| 编辑按钮 | el-button | type="primary", link |
| 删除按钮 | el-button | type="danger", link |
| 新增/编辑弹窗 | el-dialog | :title="dialogTitle", width="480px", :close-on-click-modal="false" |
| 打卡点名称 | el-input | maxlength=30, show-word-limit, placeholder="请输入打卡点名称" |
| 适用班组 | el-select | filterable, placeholder="请选择适用班组" |
| 位置描述 | el-input | placeholder="请输入位置描述" |
| 蓝牙Beacon | el-select | filterable, placeholder="请选择蓝牙Beacon" |
| 适用角色 | el-select | v-model="form.roles", multiple, collapse-tags, placeholder="请选择适用角色" |
| 删除确认 | el-message-box | type="warning" |
### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 打卡点名称 | 必填maxlength=30 | "请输入打卡点名称" |
| 适用班组 | 必选 | "请选择适用班组" |
| 位置描述 | 必填 | "请输入位置描述" |
| 蓝牙Beacon | 必选 | "请选择蓝牙Beacon" |
| 适用角色 | 必选至少1项 | "请选择适用角色" |
### 响应式布局
| 断点 | 布局调整 |
|------|----------|
| ≥1280px桌面端 | 表格完整展示全部6列弹窗宽度480px |
| 1024-1279pxPad横屏 | 表格隐藏"位置"列弹窗宽度440px |
| 768-1023pxPad竖屏 | 表格仅显示打卡点名称、班组、操作列弹窗宽度90vw |
---
## 页面6下属账号管理页
**页面编号**PR-O-07-P01
**端侧归属**Web专属
**页面路径**/org/subordinates
### 界面布局
```
┌──────────────────────────────────────────────────────────────────┐
│ [面包屑] 组织架构 > 下属账号管理 │
├──────────────────────────────────────────────────────────────────┤
│ [查询条件区] │
│ 姓名[____] 班组[▼] 角色[▼] 状态[▼] [查询] [重置] │
├──────────────────────────────────────────────────────────────────┤
│ [操作栏] [新增下属] [批量分配角色] [批量启停] │
├──────────────────────────────────────────────────────────────────┤
│ [列表区] │
│ ☐| 姓名 | 手机号 | 班组 | 角色 | 状态 | 操作 │
│ ☐| 张三 | 138****12| 水电班 | 主管 | 启用 | 编辑 角色 权限 启停│
│ ☐| 李四 | 139****34| 水电班 | 维修员 | 启用 | 编辑 角色 权限 启停│
├──────────────────────────────────────────────────────────────────┤
│ [分页] 共50条 每页[20▼] < 1 2 3 > │
└──────────────────────────────────────────────────────────────────┘
```
### 查询条件
| 字段名 | 控件类型 | 必填 | 默认值 | 说明 |
|--------|----------|------|--------|------|
| 姓名 | 文本输入 | 否 | — | 模糊匹配 |
| 班组 | 下拉单选 | 否 | 全部 | — |
| 角色 | 下拉单选 | 否 | 全部 | 数据来源:超管定义的角色 |
| 状态 | 下拉单选 | 否 | 全部 | 启用/禁用 |
### 列表字段
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|------|--------|------|----------|------|
| 1 | ☐勾选 | 40px | — | 批量操作用 |
| 2 | 姓名 | 80px | 否 | — |
| 3 | 手机号 | 120px | 否 | 脱敏 |
| 4 | 所属班组 | 120px | 是 | — |
| 5 | 角色 | 120px | 否 | — |
| 6 | 数据权限 | 100px | 否 | 本班组/指定区域 |
| 7 | 状态 | 80px | 是 | — |
| 8 | 操作 | 220px | — | 编辑/分配角色/权限覆盖/启停 |
### 操作按钮
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|------|----------|------|----------|------|
| 新增下属 | org:staff:create | 操作栏 | 始终 | 弹窗 |
| 批量分配角色 | permission:user:update | 操作栏 | 勾选≥1条 | 弹窗选择角色 |
| 批量启停 | org:staff:update | 操作栏 | 勾选≥1条 | 二次确认 |
| 编辑 | org:staff:update | 行操作 | 始终 | — |
| 分配角色 | permission:user:update | 行操作 | 始终 | 选择角色 |
| 权限覆盖 | permission:user:update | 行操作 | 始终 | 在角色基础上自定义权限(四级树形) |
| 启停 | org:staff:update | 行操作 | 始终 | 二次确认 |
### 新增下属弹窗
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|--------|----------|------|--------|----------|----------|
| 姓名 | 文本输入 | 是 | — | 自填 | 最大20字 |
| 手机号 | 文本输入 | 是 | — | 自填 | 手机号格式 |
| 所属班组 | 下拉多选 | 是 | — | 班组列表 | — |
| 分配角色 | 下拉单选 | 是 | — | 超管定义的角色列表 | — |
| 是否自定义权限 | 开关 | 否 | 否 | — | 开启后显示四级权限树 |
| 数据权限范围 | 下拉单选 | 是 | 本班组 | 固定选项 | 本班组/指定区域 |
### 通知触发
| 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 |
|----------|----------|----------|----------|----------|
| 下属账号创建 | 下属人员 | 小程序推送 | 账号开通通知 | 03-物业公司 §4 |
| 角色变更 | 下属人员 | Redis Pub/Sub | 权限实时生效 | 03-物业公司 §4 |
| 账号禁用 | 下属人员 | — | session失效+小程序下线 | 03-物业公司 §4 |
### API端点
| 页面操作 | API路径 | 方法 | 说明 |
|----------|---------|------|------|
| 列表查询 | /api/v1/subordinates | GET | — |
| 新增 | /api/v1/subordinates | POST | — |
| 分配角色 | /api/v1/subordinates/{id}/assign-role | PUT | — |
| 权限覆盖 | /api/v1/subordinates/{id}/override-permissions | PUT | 四级树形权限 |
| 批量操作 | /api/v1/subordinates/batch | POST | 批量启停/分配角色 |
### 交互流程要求
1. **页面加载流程**:进入页面 → 并行调用下属列表API、班组列表、角色列表 → 渲染表格和筛选条件默认加载第一页数据每页20条
2. **查询/筛选交互流程**:输入姓名/选择班组/选择角色/选择状态 → 点击[查询] → 重新加载数据 → 点击[重置]清空条件
3. **表单填写与提交流程**:点击[新增下属] → 弹窗填写姓名、手机号、所属班组、分配角色、是否自定义权限、数据权限范围 → 前端校验通过 → 调用新增API → 成功后关闭弹窗并刷新列表;开启"自定义权限"后展示四级权限树形勾选
4. **弹窗/抽屉交互流程**新增弹窗宽度600px编辑弹窗宽度520px分配角色弹窗宽度480px权限覆盖弹窗宽度700px展示四级权限树形结构点击遮罩层不关闭
5. **行内操作流程**:点击[编辑] → 弹窗回填数据 → 修改后提交 → 刷新列表;点击[分配角色] → 选择角色 → 提交 → 角色实时生效;点击[权限覆盖] → 四级权限树形勾选 → 提交 → 权限实时生效;点击[启停] → 二次确认 → 提交 → 刷新行状态
6. **异常与错误处理**:手机号已注册提示"该手机号已被注册"角色变更后毫秒级生效Redis Pub/Sub账号禁用后session失效+小程序下线API请求失败显示ElMessage.error
7. **联动/级联交互**:选择所属班组后角色下拉可按班组类型过滤;开启"自定义权限"后动态展示四级权限树;批量分配角色时勾选人员后统一选择角色
8. **权限控制交互表现**:无 org:staff:create 权限时[新增下属]按钮隐藏;无 permission:user:update 权限时[分配角色][权限覆盖]按钮隐藏;无 org:staff:update 权限时[编辑][启停]按钮隐藏;批量操作按钮需勾选后才可点击
9. **[H1]防重复请求**
- 查询按钮点击后 disabled + loading态API返回后恢复
- 行内操作点击后该行禁用 + loading态
- 分页切换 abort上一请求再发新请求
10. **[H2]超时与加载反馈**
- GET列表查询 timeout=15秒POST/PUT/DELETE写操作 timeout=30秒
- 超时 → 提示"请求超时,请检查网络后重试" + 按钮恢复
- 加载>2秒显示全局loading
11. **[H3]操作确认机制**(有不可逆操作时)
- 启停: ElMessageBox.confirm
12. **[H4]脏数据检测**
- 编辑模式进入时deep clone快照
- isDirty检测 + 取消/离开拦截
13. **[H8]操作结果反馈**
- 成功: success(2s) + silent刷新
- 失败: error(0手动关闭)
- 网络: 异常提示+重试按钮
### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 姓名输入 | el-input | clearable, maxlength=20, placeholder="请输入姓名" |
| 班组筛选 | el-select | clearable, filterable, placeholder="全部班组" |
| 角色筛选 | el-select | clearable, placeholder="全部角色" |
| 状态筛选 | el-select | clearable, placeholder="全部状态" |
| 列表 | el-table | stripe, border, :data="tableData", @selection-change |
| 勾选列 | el-table-column | type="selection", width="40" |
| 分页 | el-pagination | layout="total, sizes, prev, pager, next", :page-sizes="[10,20,50]" |
| 新增下属按钮 | el-button | type="primary", icon="Plus" |
| 批量分配角色按钮 | el-button | type="success", :disabled="!selectedRows.length" |
| 批量启停按钮 | el-button | type="warning", :disabled="!selectedRows.length" |
| 编辑按钮 | el-button | type="primary", link |
| 分配角色按钮 | el-button | type="success", link |
| 权限覆盖按钮 | el-button | type="warning", link |
| 启停按钮 | el-button | type="warning", link |
| 状态标签 | el-tag | 启用=success / 禁用=danger |
| 新增弹窗 | el-dialog | title="新增下属", width="600px", :close-on-click-modal="false" |
| 姓名 | el-input | maxlength=20, placeholder="请输入姓名" |
| 手机号 | el-input | maxlength=11, placeholder="请输入手机号" |
| 所属班组 | el-select | v-model="form.teamIds", multiple, collapse-tags, filterable |
| 分配角色 | el-select | placeholder="请选择角色" |
| 自定义权限开关 | el-switch | v-model="form.customPermission" |
| 数据权限范围 | el-select | placeholder="请选择数据权限范围" |
| 四级权限树 | el-tree | :data="permissionTree", show-checkbox, node-key="id", :props="{label:'name',children:'children'}" |
| 分配角色弹窗 | el-dialog | title="分配角色", width="480px", :close-on-click-modal="false" |
| 权限覆盖弹窗 | el-dialog | title="权限覆盖", width="700px", :close-on-click-modal="false" |
| 二次确认 | el-message-box | type="warning" |
### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 姓名 | 必填maxlength=20 | "请输入姓名" |
| 手机号 | 必填,正则/^1[3-9]\d{9}$/ | "请输入正确的手机号码" |
| 所属班组 | 必选至少1个 | "请选择所属班组" |
| 分配角色 | 必选 | "请选择分配角色" |
| 数据权限范围 | 必选 | "请选择数据权限范围" |
| 批量操作-勾选 | 至少勾选1条 | "请至少选择一条记录" |
### 响应式布局
| 断点 | 布局调整 |
|------|----------|
| ≥1280px桌面端 | 查询条件区水平排列表格完整展示全部8列新增弹窗600px权限弹窗700px |
| 1024-1279pxPad横屏 | 查询条件区换行排列,表格隐藏"数据权限""手机号"列弹窗宽度缩减10% |
| 768-1023pxPad竖屏 | 查询条件区垂直堆叠,表格仅显示姓名、班组、角色、状态、操作列;批量操作收入"更多"下拉菜单弹窗宽度90vw |
---
## 需求追溯
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|------------|----------|----------|----------|----------|
| PR-O-01 | 班组管理 | 02-物业公司 §4 | 班组→人员分配→排班 | 巡检管理(巡检班组) / 保洁管理(保洁班组) |
| PR-O-02 | 人员管理 | 02-物业公司 §4 | 人员→技能标签→工单分配 | 在线报修(维修人员) |
| PR-O-03 | 人员分配 | 02-物业公司 §4 | 分配→班组关联 | 班组管理 / 技能管理 |
| PR-O-04 | 排班管理 | 02-物业公司 §4 | 排班→保洁任务生成 | 保洁管理(排班) / 小程序端我的排班(MP-OR-02) |
| PR-O-05 | 技能管理 | 02-物业公司 §4 | 技能→工单自动分配依据 | 在线报修(自动分配) |
| PR-O-06 | 打卡点分配 | 02-物业公司 §4 | 打卡点→考勤蓝牙绑定 | 考勤打卡(打卡点管理) / 系统配置(蓝牙设备) |
| PR-O-07 | 下属账号管理 | 02-物业公司 §4 / 03-物业公司 §4 | 创建下属→分配角色→权限覆盖 | 超管权限管理(角色定义) |
| PR-O-08 | 下属角色分配 | 02-物业公司 §4 | 选择超管定义的角色→分配 | 超管权限管理(角色管理) |
| PR-O-09 | 下属权限覆盖 | 02-物业公司 §4 / 03-物业公司 §4 | 在角色基础上调整权限(四级树形) | 超管权限管理(权限分配) |
| PR-O-10 | 下属批量操作 | 02-物业公司 §4 | 批量启停/分配角色 | — |
| PR-O-11 | 下属数据权限 | 02-物业公司 §4 / 01 §1.3 | 设置数据可见范围 | 数据权限校验 |
## 业务规则
1. **一人多班组**支持一个人员属于多个班组来源02-物业公司 PR-O-02
2. **下属角色来源于超管**物业公司管理员从超管定义的角色中选择分配给下属来源03-物业公司 §4 / 01 §8.4
3. **权限覆盖**可在角色权限基础上自定义调整使用四级树形勾选来源03-物业公司 §4
4. **下属不单独设有效期**随物业公司管理员账号到期而自动失效来源01 §1.4
5. **数据权限**主管仅看本班组数据员工仅看本人数据来源01 §1.3
6. **权限实时生效**:角色/权限变更后毫秒级生效无需重新登录来源01 §8.3
7. **操作日志**下属创建、角色分配、权限覆盖均记录审计日志来源06 §4.5