# 权限管理 > 模块编码:permission > 端侧:Web专属(仅超级管理员) > 关联文档:01-模块划分 §8 / 02-功能清单-超级管理员 §2 / 03-业务流转逻辑-超级管理员 §4~6 / 05-接口规范 §4.2~4.3 / 06-项目技术要求 §4.2 > 强制规范遵循 `07-前端界面开发规范.md` ## 功能概览 | 项目 | 说明 | |------|------| | 菜单名称 | 权限管理 | | 子菜单 | 角色管理、权限配置注册、权限审计日志 | | 功能编号 | SA-P-01 ~ SA-P-10 | | 权限编码前缀 | permission:role:* / permission:config:* | --- ## 页面1:角色管理列表页 **页面编号**:SA-P-01-P01 **端侧归属**:Web专属 **页面路径**:/permission/roles ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [面包屑] 权限管理 > 角色管理 │ ├──────────────────────────────────────────────────────────────────┤ │ [查询条件区] │ │ 角色名称[____] 适用范围[▼] 状态[▼] [查询] [重置] │ ├──────────────────────────────────────────────────────────────────┤ │ [操作栏] [新增角色] │ ├──────────────────────────────────────────────────────────────────┤ │ [列表区] │ │ 序号 | 角色名称 | 适用范围 | 预设模板 | 关联账号数 | 状态 | 操作 │ │ 1 | 医院查看 | 医院 | 是 | 5 | 启用 | 编辑 停用│ │ 2 | 巡检主管 | 物业下属| 否 | 8 | 启用 | 编辑 停用│ │ 3 | 维修员 | 物业下属| 是 | 23 | 启用 | 编辑 停用│ ├──────────────────────────────────────────────────────────────────┤ │ [分页] 共15条 每页[20▼] < 1 > │ └──────────────────────────────────────────────────────────────────┘ ``` ### 查询条件 | 字段名 | 控件类型 | 必填 | 默认值 | 说明 | |--------|----------|------|--------|------| | 角色名称 | 文本输入 | 否 | — | 模糊匹配 | | 适用范围 | 下拉单选 | 否 | 全部 | 医院账号/物业管理员/物业下属 | | 状态 | 下拉单选 | 否 | 全部 | 启用/停用 | ### 列表字段 | 序号 | 字段名 | 列宽 | 支持排序 | 说明 | |------|--------|------|----------|------| | 1 | 序号 | 60px | — | 自增 | | 2 | 角色名称 | 150px | 是 | — | | 3 | 适用范围 | 120px | 否 | 医院账号/物业管理员/物业下属 | | 4 | 预设模板 | 80px | 否 | 是/否标签 | | 5 | 关联账号数 | 100px | 是 | 点击查看关联账号列表 | | 6 | 状态 | 80px | 是 | 启用/停用 | | 7 | 操作 | 220px | — | 编辑/权限预览/停用/删除 | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 新增角色 | permission:role:create | 操作栏 | 始终 | 跳转新增页 | | 编辑 | permission:role:update | 行操作 | 始终 | 跳转编辑页 | | 权限预览 | permission:role:view | 行操作 | 始终 | 弹窗展示完整权限清单 | | 停用 | permission:role:update | 行操作 | 状态=启用 | 二次确认 | | 删除 | permission:role:delete | 行操作 | 关联账号数=0 | 二次确认 | ### 角色差异化视图 | 角色 | 可见按钮 | 数据范围 | 备注 | |------|----------|----------|------| | 超级管理员 | 全部按钮 | 全部角色 | — | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 列表查询 | /api/v1/roles | GET | 分页查询 | | 停用角色 | /api/v1/roles/{id}/disable | PUT | — | | 删除角色 | /api/v1/roles/{id} | DELETE | 仅无关联账号时可删 | ### 交互流程要求 1. **页面加载流程** - 进入页面 → 调用 `GET /api/v1/roles` 加载列表(默认第1页,创建时间倒序) - 并行加载下拉选项:适用范围、状态 - 列表为空时显示空状态插图 + "暂无角色" 2. **查询交互流程** - 填写查询条件 → 点击"查询"→ 调用API → 重置到第1页 - 点击"重置"→ 清空条件 → 重新加载 3. **行内操作流程** - **编辑**:点击"编辑"→ 路由跳转 `/permission/roles/:id/edit` - **权限预览**:点击"权限预览"→ 弹窗展示该角色的完整权限清单(调用 `GET /api/v1/roles/{id}/permissions`) - **停用**:二次确认("确认停用角色XX?停用后关联账号将失去该角色的权限")→ 调用 `PUT /api/v1/roles/{id}/disable` → 成功提示 → 刷新列表 - **删除**:仅关联账号数=0时显示 → 二次确认("确认删除角色XX?此操作不可恢复")→ 调用 `DELETE /api/v1/roles/{id}` → 成功提示 → 刷新列表 4. **联动交互** - "关联账号数"可点击 → 弹窗展示使用该角色的账号列表 5. **异常处理** - 删除角色失败(存在关联账号)→ 提示"该角色下存在关联账号,无法删除" - 停用角色失败 → 提示具体原因 - API失败 → 通用错误提示 6. **权限控制交互** - 无 `permission:role:create` → "新增角色"按钮不渲染 - 无 `permission:role:update` → "编辑""停用"按钮不渲染 - 无 `permission:role:delete` → "删除"按钮不渲染 - 无 `permission:role:view` → "权限预览"按钮不渲染 7. **[H1]防重复请求** - 查询/筛选:点击"查询"按钮后立即 disabled=true + 显示loading态,API返回后恢复;查询期间再次点击无效 - 行内操作(停用/删除等):点击操作按钮后该行所有操作按钮禁用 + 按钮显示loading旋转图标;操作完成后恢复 - 分页切换:切换页码时取消上一页未完成请求(abortController)后再发起新请求 - 页面初始化并行请求之间互不阻塞 8. **[H2]超时与加载反馈** - 列表查询API:timeout=15秒;加载中表格区显示v-loading骨架屏遮罩 - 停用/删除等写操作API:timeout=30秒;操作按钮:loading态 - 超时处理:自动中断 → ElMessage.error("请求超时,请检查网络后重试") → 按钮恢复可用 - 列表加载超过2秒时显示全局ElLoading进度提示 9. **[H3]操作确认机制** - 停用角色:ElMessageBox.confirm("确定要停用「{角色名}」吗?停用后关联账号将失去该角色的权限", "操作确认", { type: 'warning' }) - 删除角色:ElMessageBox.confirm("确定要删除「{角色名}」吗?此操作不可恢复", "删除确认", { type: 'error' }) - 确认弹窗期间底层页面不可点击 10. **[H8]操作结果反馈** - 成功:ElMessage.success(duration=2000ms) → silent刷新列表 - 失败:ElMessage.error(duration=0手动关闭) - 网络异常:提示"网络连接异常"+ 重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 查询条件区 | el-form | inline, label-width="auto" | | 适用范围下拉 | el-select | clearable, placeholder="请选择" | | 状态标签 | el-tag | 启用:type="success", 停用:type="danger" | | 预设模板标签 | el-tag | 是:type="primary", 否:type="info" | | 关联账号数 | el-link | type="primary", underline=false, @click="showRelatedAccounts" | | 操作按钮 | el-button | type="primary", link, size="small" | | 删除按钮 | el-button | type="danger", link, size="small" | | 分页 | el-pagination | layout="total, sizes, prev, pager, next" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 角色名称(查询) | 最大30字符 | — | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 查询条件一行排列;列表完整展示所有列 | | 1024-1279px(Pad横屏) | 查询条件一行排列;"预设模板"列隐藏 | | 768-1023px(Pad竖屏) | 查询条件两行排列;列表仅显示:序号、角色名称、适用范围、状态、操作 | --- ## 页面2:角色新增/编辑页 **页面编号**:SA-P-01-P02 **端侧归属**:Web专属 **页面路径**:/permission/roles/create 或 /permission/roles/:id/edit ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [面包屑] 权限管理 > 角色管理 > 新增角色 │ ├──────────────────────────────────────────────────────────────────┤ │ ── 基本信息 ── │ │ 角色名称:[____________] │ │ 角色描述:[____________________________] │ │ 适用范围:[▼] (医院账号/物业管理员/物业下属) │ │ 选择预设模板:[▼可选] 选择后自动填充权限,可微调 │ ├──────────────────────────────────────────────────────────────────┤ │ ── 权限分配(四级树形勾选)── │ │ ☑ 功能菜单:在线报修 │ │ ├── ☑ 页面:工单列表 │ │ │ ├── ☑ 功能点:工单管理 │ │ │ │ ├── ☑ 查看 ☑ 新增 ☑ 编辑 │ │ │ │ ├── ☐ 删除 ☐ 审批 ☑ 导出 ☑ 分配 │ │ │ └── ☑ 功能点:批量操作 │ │ │ ├── ☑ 查看 ☐ 新增 ☐ 编辑 │ │ │ └── ☐ 删除 ☐ 审批 ☐ 导出 ☐ 分配 │ │ ├── ☑ 页面:工单详情 │ │ │ ├── ☑ 功能点:延期审批 │ │ │ │ ├── ☑ 查看 ☐ 新增 ☐ 编辑 │ │ │ │ └── ☐ 删除 ☑ 审批 ☐ 导出 ☐ 分配 │ │ │ └── ☑ 功能点:工单验收 │ │ │ ├── ☑ 查看 ☐ 新增 ☐ 编辑 │ │ │ └── ☐ 删除 ☑ 审批 ☐ 导出 ☐ 分配 │ │ └── ☐ 页面:报修类型管理 │ │ ... │ │ ☐ 功能菜单:巡检管理 │ │ ... │ ├──────────────────────────────────────────────────────────────────┤ │ [取消] [权限预览] [保存] │ └──────────────────────────────────────────────────────────────────┘ ``` ### 表单字段(基本信息) | 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 | |--------|----------|------|--------|----------|----------| | 角色名称 | 文本输入 | 是 | — | 自填 | 最大30字,全局唯一 | | 角色描述 | 多行文本 | 否 | — | 自填 | 最大200字 | | 适用范围 | 下拉单选 | 是 | — | 固定选项 | 医院账号/物业管理员/物业下属 | | 预设模板 | 下拉单选 | 否 | — | 预设模板列表 | 选择后自动填充权限 | ### 预设模板选项 | 模板名称 | 适用对象 | 典型权限 | 文档来源 | |----------|----------|----------|----------| | 物业管理员模板 | 物业公司管理员 | 全部日常业务管理权限 | 01 §8.4 | | 主管模板 | 主管 | 本班组管理+审批+查看+导出 | 01 §8.4 | | 班组长模板 | 班组长 | 本班组查看+分配+导出 | 01 §8.4 | | 维修员模板 | 维修人员 | 接单+完工+延期申请 | 01 §8.4 | | 巡检员模板 | 巡检人员 | 巡检执行+打卡+异常上报 | 01 §8.4 | | 保洁员模板 | 保洁人员 | 保洁执行+打卡确认 | 01 §8.4 | | 医院查看模板 | 医院账号 | 全部日常数据查看+合同+招标 | 01 §8.4 | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 权限预览 | permission:role:view | 底部操作栏 | 始终 | 弹窗展示已勾选的完整权限清单 | | 保存 | permission:role:create/update | 底部操作栏 | 始终 | 保存后权限审计日志+实时生效 | ### 通知触发 | 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 | |----------|----------|----------|----------|----------| | 权限变更 | 关联账号用户 | Redis Pub/Sub | 毫秒级刷新权限缓存,无需重新登录 | 03-超级管理员 §6 | | 权限变更 | 关联账号用户 | 小程序 | 下次接口请求时返回新权限集 | 03-超级管理员 §6 | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 新增角色 | /api/v1/roles | POST | — | | 编辑角色 | /api/v1/roles/{id} | PUT | — | | 获取权限树 | /api/v1/permissions/tree | GET | 四级权限树结构 | | 权限预览 | /api/v1/roles/{id}/permissions | GET | 已分配的完整权限列表 | ### 交互流程要求 1. **页面加载流程** - 新增模式:空白表单 + 调用 `GET /api/v1/permissions/tree` 加载权限树 - 编辑模式:并行调用权限树 + 角色详情(`GET /api/v1/roles/{id}`)→ 回填表单 + 勾选已有权限 - 权限树加载中显示加载动画 2. **表单填写与提交流程** - 填写基本信息 → 选择预设模板(可选)→ 自动填充权限树勾选 → 微调权限 → 点击"保存" - 保存前校验:角色名称必填、适用范围必选、至少勾选一个权限项 - 保存成功 → 记录权限审计日志 → 权限实时生效(Redis Pub/Sub)→ 返回列表页 3. **权限树交互** - 四级展开:功能菜单→页面→功能点→动作 - 勾选父节点 → 自动勾选所有子节点 - 取消父节点 → 自动取消所有子节点 - 子节点全选 → 父节点自动勾选 - 子节点部分选 → 父节点半选(indeterminate) - 支持搜索过滤权限名称 4. **预设模板联动** - 选择预设模板 → 弹出确认("选择模板将覆盖当前权限配置,是否继续?")→ 确认后自动勾选模板权限 - 模板填充后仍可手动微调 5. **权限预览交互** - 点击"权限预览"→ 弹窗展示当前已勾选的权限清单(非保存后的,而是实时的) - 权限预览弹窗同页面3格式 6. **异常处理** - 角色名称重复 → 提示"该角色名称已存在" - 权限树加载失败 → 提示"权限配置加载失败",提供"重试"按钮 - 保存失败 → 提示错误信息,表单数据不丢失 7. **权限控制交互** - 无保存权限 → "保存"按钮禁用 8. **[H1]防重复请求** - 点击"保存"按钮后::loading=true + 文案"保存中..." + disabled;API返回后恢复 9. **[H2]超时与加载反馈** - 提交API(POST/PUT):timeout=30秒;回填API(GET):timeout=15秒 - 超时处理:中断 → 提示"保存超时..." → 按钮恢复 10. **[H3]操作确认机制** - 选择预设模板时:ElMessageBox.confirm("选择模板将覆盖当前权限配置,是否继续?", { type: 'warning' }) 11. **[H4]脏数据检测** - 编辑模式进入时deep clone初始数据为快照 - 修改任意字段→isDirty=true - 取消/路由离开时:isDirty则ElMessageBox.confirm("当前修改尚未保存...") - beforeRouteLeave导航守卫拦截 - 保存成功后重置快照和isDirty 12. **[H8]操作结果反馈** - 成功:ElMessage.success("保存成功") → 延迟300ms返回列表页 - 失败:ElMessage.error(duration=0);表单数据保持不丢失 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 表单 | el-form | label-width="100px", :model, :rules | | 角色名称 | el-input | maxlength=30, show-word-limit, clearable | | 角色描述 | el-input | type="textarea", maxlength=200, show-word-limit, :rows=3 | | 适用范围 | el-select | clearable, placeholder="请选择适用范围" | | 预设模板 | el-select | clearable, placeholder="可选,选择后自动填充权限" | | 权限树 | el-tree | show-checkbox, check-strictly=false, default-expand-all=false, :data="permissionTree", node-key="code", :filter-node-method | | 权限搜索 | el-input | placeholder="搜索权限名称", clearable, prefix-icon="Search" | | 权限预览按钮 | el-button | type="info", plain | | 保存按钮 | el-button | type="primary", :loading | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 角色名称 | 必填, 2-30字符, 全局唯一 | "请输入角色名称" / "角色名称长度2-30字符" / "该角色名称已存在" | | 适用范围 | 必填 | "请选择适用范围" | | 权限勾选 | 至少勾选一个 | "请至少分配一项权限" | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 基本信息两列排列;权限树区域宽度100%,高度500px可滚动 | | 1024-1279px(Pad横屏) | 基本信息两列排列;权限树区域高度400px | | 768-1023px(Pad竖屏) | 基本信息单列排列;权限树区域高度350px,默认折叠到第二级 | --- ## 页面3:权限预览弹窗 **页面编号**:SA-P-06-P01 **端侧归属**:Web专属 **页面路径**:弹窗形式 ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ 权限预览 — 巡检主管 [×] │ ├──────────────────────────────────────────────────────────────────┤ │ ☑ 在线报修 │ │ ├─ ☑ 工单列表 │ │ │ ├─ ☑ 工单管理:查看 ✓ 新增 ✗ 编辑 ✓ 删除 ✗ 审批 ✓ 导出 ✓ 分配 ✗│ │ │ └─ ☐ 批量操作 │ │ ├─ ☑ 工单详情 │ │ │ ├─ ☑ 延期审批:查看 ✓ 审批 ✓ │ │ │ └─ ☑ 工单验收:查看 ✓ 审批 ✓ │ │ └─ ☐ 报修类型管理 │ │ ☑ 巡检管理 │ │ ├─ ☑ 巡检计划:查看 ✓ 新增 ✓ 编辑 ✓ │ │ ... │ ├──────────────────────────────────────────────────────────────────┤ │ [关闭] │ └──────────────────────────────────────────────────────────────────┘ ``` ### 说明 - 展示角色当前已分配的完整权限清单 - 四级展开:功能菜单→页面→功能点→动作 - 每个动作用 ✓/✗ 标识是否有权限 - 支持搜索功能菜单/页面名称 ### 交互流程要求 1. **弹窗打开流程** - 从角色列表页或角色编辑页触发 → 调用 `GET /api/v1/roles/{id}/permissions` 加载权限数据 → 渲染权限树 - 加载中弹窗内显示loading 2. **弹窗内交互** - 搜索框输入关键词 → 实时过滤权限树,高亮匹配项 - 点击展开/折叠节点 - 只读模式,不可修改勾选状态 3. **弹窗关闭** - 点击"关闭"按钮或右上角× → 关闭弹窗 - 支持ESC键关闭 4. **[H1]防重复请求** - 弹窗打开时:调用API期间"关闭"按钮禁用 + 弹窗内显示v-loading遮罩;数据返回后恢复 5. **[H2]超时与加载反馈** - 权限查询API(GET):timeout=15秒;加载中弹窗内显示loading骨架屏 - 超时处理:中断 → ElMessage.error("权限数据加载超时") → 提供"重试"按钮 6. **[H8]操作结果反馈** - 加载失败:ElMessage.error(duration=0手动关闭) + 弹窗内展示重试按钮 - 网络异常:提示"网络连接异常"+ 重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 弹窗 | el-dialog | width="600px", :close-on-click-modal=true, title="权限预览" | | 权限树 | el-tree | :data, default-expand-all, :props, :filter-node-method | | 搜索框 | el-input | placeholder="搜索权限名称", clearable, prefix-icon="Search" | | 权限标识 | el-tag | 有权限:type="success", ✓; 无权限:type="info", ✗ | | 关闭按钮 | el-button | @click="dialogVisible=false" | ### 校验规则 无表单校验(只读展示页) ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 弹窗宽度600px | | 1024-1279px(Pad横屏) | 弹窗宽度550px | | 768-1023px(Pad竖屏) | 弹窗宽度90vw,最大500px | --- ## 页面4:权限配置注册页 **页面编号**:SA-P-10-P01 **端侧归属**:Web专属 **页面路径**:/permission/registry ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [面包屑] 权限管理 > 权限配置注册 │ ├──────────────────────────────────────────────────────────────────┤ │ [说明] 此页面展示系统自动注册的权限配置(来源:IModulePlugin), │ │ 开发新增功能时自动同步,超级管理员可查看但不可手动编辑 │ ├──────────────────────────────────────────────────────────────────┤ │ [查询条件区] │ │ 模块名称[____] 页面名称[____] [查询] [重置] │ ├──────────────────────────────────────────────────────────────────┤ │ [列表区] │ │ 模块编码 | 模块名称 | 页面编码 | 页面名称 | 功能点 | 可用动作 │ │ repair | 在线报修 | repair_list| 工单列表 | 工单管理 | 查看,新增..│ │ repair | 在线报修 | repair_detail|工单详情| 延期审批| 查看,审批 │ │ ... │ ├──────────────────────────────────────────────────────────────────┤ │ [分页] 共120条 每页[20▼] < 1 2 3 ... 6 > │ └──────────────────────────────────────────────────────────────────┘ ``` ### 查询条件 | 字段名 | 控件类型 | 必填 | 默认值 | 说明 | |--------|----------|------|--------|------| | 模块名称 | 文本输入 | 否 | — | 模糊匹配 | | 页面名称 | 文本输入 | 否 | — | 模糊匹配 | ### 列表字段 | 序号 | 字段名 | 列宽 | 支持排序 | 说明 | |------|--------|------|----------|------| | 1 | 模块编码 | 100px | 否 | — | | 2 | 模块名称 | 100px | 否 | — | | 3 | 页面编码 | 130px | 否 | — | | 4 | 页面名称 | 120px | 否 | — | | 5 | 功能点编码 | 140px | 否 | — | | 6 | 功能点名称 | 120px | 否 | — | | 7 | 可用动作 | 200px | 否 | view,create,update,delete,approve,export,assign | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | — | — | — | — | 此页面只读,数据由IModulePlugin自动注册 | ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 列表查询 | /api/v1/permissions/registry | GET | 查看已注册的权限配置 | | 刷新 | /api/v1/permissions/registry/refresh | POST | 手动触发权限重新扫描 | ### 交互流程要求 1. **页面加载流程** - 进入页面 → 调用 `GET /api/v1/permissions/registry` 加载权限配置列表 - 页面顶部显示说明提示条(el-alert),说明此页面为只读 2. **查询交互流程** - 填写查询条件 → 点击"查询"→ 筛选列表 → 重置到第1页 3. **操作流程** - **刷新**:点击"刷新"按钮 → 二次确认("确认重新扫描权限配置?可能需要数秒")→ 调用 `POST /api/v1/permissions/registry/refresh` → 成功提示 → 重新加载列表 - 无其他操作按钮(只读页面) 4. **异常处理** - 刷新失败 → 提示"权限扫描失败,请稍后重试" 5. **权限控制交互** - 此页面仅超级管理员可见 6. **[H1]防重复请求** - 查询/筛选:点击"查询"按钮后立即 disabled=true + 显示loading态,API返回后恢复;查询期间再次点击无效 - 刷新操作:点击"刷新"按钮后:loading=true + disabled;API返回后恢复 - 分页切换:切换页码时取消上一页未完成请求(abortController)后再发起新请求 - 页面初始化并行请求之间互不阻塞 7. **[H2]超时与加载反馈** - 列表查询API:timeout=15秒;加载中表格区显示v-loading骨架屏遮罩 - 刷新操作API(POST):timeout=30秒;操作按钮:loading态 - 超时处理:自动中断 → ElMessage.error("请求超时,请检查网络后重试") → 按钮恢复可用 - 列表加载超过2秒时显示全局ElLoading进度提示 8. **[H3]操作确认机制** - 刷新权限配置:ElMessageBox.confirm("确认重新扫描权限配置?可能需要数秒", "操作确认", { type: 'warning' }) - 确认弹窗期间底层页面不可点击 9. **[H8]操作结果反馈** - 成功:ElMessage.success(duration=2000ms) → silent刷新列表 - 失败:ElMessage.error(duration=0手动关闭) - 网络异常:提示"网络连接异常"+ 重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 说明提示条 | el-alert | type="info", :closable=false, show-icon | | 列表 | el-table | stripe, border, v-loading | | 可用动作 | el-tag | v-for 循环渲染, type="info", size="small" | | 刷新按钮 | el-button | type="warning", icon="Refresh", plain | | 分页 | el-pagination | layout="total, sizes, prev, pager, next" | ### 校验规则 无表单校验(只读页面) ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 列表完整展示所有列 | | 1024-1279px(Pad横屏) | "功能点编码"列隐藏 | | 768-1023px(Pad竖屏) | 列表仅显示:模块名称、页面名称、功能点名称、可用动作 | --- ## 页面5:权限审计日志页 **页面编号**:SA-P-08-P01 **端侧归属**:Web专属 **页面路径**:/permission/audit-log ### 界面布局 ``` ┌──────────────────────────────────────────────────────────────────┐ │ [面包屑] 权限管理 > 权限审计日志 │ ├──────────────────────────────────────────────────────────────────┤ │ [查询条件区] │ │ 操作人[____] 操作类型[▼] 角色[____] 日期[起始]~[结束] [查询] [重置]│ ├──────────────────────────────────────────────────────────────────┤ │ [列表区] │ │ 序号 | 操作时间 | 操作人 | 操作类型 | 目标角色 | 变更详情 | 操作 │ │ 1 | 14:00 | admin | 权限修改 | 巡检主管 | [+2项][-1项]| 查看│ │ 2 | 11:30 | admin | 角色创建 | 保洁主管 | — | 查看│ ├──────────────────────────────────────────────────────────────────┤ │ [分页] 共80条 每页[20▼] < 1 2 3 4 > │ └──────────────────────────────────────────────────────────────────┘ ``` ### 查询条件 | 字段名 | 控件类型 | 必填 | 默认值 | 说明 | |--------|----------|------|--------|------| | 操作人 | 文本输入 | 否 | — | 模糊匹配 | | 操作类型 | 下拉单选 | 否 | 全部 | 角色创建/权限修改/角色分配/角色移除 | | 角色 | 文本输入 | 否 | — | 模糊匹配角色名称 | | 日期范围 | 日期范围 | 否 | — | 操作时间范围 | ### 列表字段 | 序号 | 字段名 | 列宽 | 支持排序 | 说明 | |------|--------|------|----------|------| | 1 | 序号 | 60px | — | 自增 | | 2 | 操作时间 | 150px | 是 | 默认倒序 | | 3 | 操作人 | 100px | 否 | — | | 4 | 操作类型 | 100px | 否 | 标签样式 | | 5 | 目标角色 | 120px | 否 | — | | 6 | 变更详情 | 120px | 否 | [+N项][-M项],简洁展示 | | 7 | 操作 | 80px | — | 查看详情 | ### 操作按钮 | 按钮 | 权限编码 | 位置 | 显示条件 | 说明 | |------|----------|------|----------|------| | 查看详情 | audit-log:permission:view | 行操作 | 始终 | 弹窗展示变更前后对比 | ### 审计日志详情弹窗 ``` ┌──────────────────────────────────────────────────────────────────┐ │ 权限变更详情 [×] │ ├──────────────────────────────────────────────────────────────────┤ │ 角色:巡检主管 │ │ 操作人:超级管理员(admin) │ │ 操作时间:2026-04-16 14:00:00 │ │ 操作类型:权限修改 │ ├──────────────────────────────────────────────────────────────────┤ │ 变更对比: │ │ [+新增] 在线报修 → 工单详情 → 延期审批 → 审批 │ │ [+新增] 在线报修 → 工单列表 → 工单管理 → 导出 │ │ [-移除] 巡检管理 → 巡检计划 → 计划管理 → 删除 │ ├──────────────────────────────────────────────────────────────────┤ │ [关闭] │ └──────────────────────────────────────────────────────────────────┘ ``` ### API端点 | 页面操作 | API路径 | 方法 | 说明 | |----------|---------|------|------| | 列表查询 | /api/v1/audit-logs/permission | GET | 分页查询 | | 详情查询 | /api/v1/audit-logs/permission/{id} | GET | 含变更前后对比 | ### 交互流程要求 1. **页面加载流程** - 进入页面 → 调用 `GET /api/v1/audit-logs/permission` 加载列表(默认倒序) - 并行加载下拉选项:操作类型 - 列表为空时显示空状态 2. **查询交互流程** - 填写条件 → 点击"查询"→ 调用API → 重置到第1页 - 日期范围选择器限制最多查询90天 3. **行内操作流程** - **查看详情**:点击"查看"→ 弹窗展示变更前后对比(调用 `GET /api/v1/audit-logs/permission/{id}`) - 新增权限用绿色 `[+新增]` 标记,移除权限用红色 `[-移除]` 标记 4. **异常处理** - 详情加载失败 → 提示错误信息 - 日期范围超限 → 提示"查询时间范围不能超过90天" 5. **权限控制交互** - 无 `audit-log:permission:view` → 页面不可见 6. **[H1]防重复请求** - 查询/筛选:点击"查询"按钮后立即 disabled=true + 显示loading态,API返回后恢复;查询期间再次点击无效 - 行内操作(查看详情):点击"查看"按钮后该行操作按钮禁用 + 按钮显示loading旋转图标;弹窗打开后恢复 - 分页切换:切换页码时取消上一页未完成请求(abortController)后再发起新请求 - 页面初始化并行请求之间互不阻塞 7. **[H2]超时与加载反馈** - 列表查询API:timeout=15秒;加载中表格区显示v-loading骨架屏遮罩 - 详情查询API:timeout=15秒;加载中弹窗内显示v-loading遮罩 - 超时处理:自动中断 → ElMessage.error("请求超时,请检查网络后重试") → 按钮恢复可用 - 列表加载超过2秒时显示全局ElLoading进度提示 8. **[H8]操作结果反馈** - 成功:ElMessage.success(duration=2000ms) → silent刷新列表 - 失败:ElMessage.error(duration=0手动关闭) - 网络异常:提示"网络连接异常"+ 重试按钮 ### 组件规范 | 元素 | 组件 | 配置参数 | |------|------|----------| | 日期范围选择 | el-date-picker | type="daterange", value-format="YYYY-MM-DD", :disabled-date | | 操作类型标签 | el-tag | 角色创建:type="success", 权限修改:type="warning", 角色分配:type="primary", 角色移除:type="danger" | | 变更摘要 | span | [+N项] color=green, [-M项] color=red | | 详情弹窗 | el-dialog | width="650px", :close-on-click-modal=false | | 新增权限 | div | color=var(--el-color-success), 前缀"[+新增]" | | 移除权限 | div | color=var(--el-color-danger), 前缀"[-移除]" | | 关闭按钮 | el-button | @click="dialogVisible=false" | ### 校验规则 | 字段 | 规则 | 错误提示 | |------|------|----------| | 日期范围 | 最多90天 | "查询时间范围不能超过90天" | ### 响应式布局 | 断点 | 布局调整 | |------|----------| | ≥1280px(桌面端) | 查询条件一行排列;列表完整展示所有列;详情弹窗650px | | 1024-1279px(Pad横屏) | 查询条件两行排列;"目标角色"列隐藏;详情弹窗600px | | 768-1023px(Pad竖屏) | 查询条件两行排列;列表仅显示:序号、操作时间、操作人、操作类型、操作;详情弹窗90vw | --- ## 需求追溯 | 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 | |------------|----------|----------|----------|----------| | SA-P-01 | 角色定义 | 02-超级管理员 §2 / 03-超级管理员 §4 | 创建角色→权限分配 | 账号管理(角色绑定) | | SA-P-02 | 角色权限分配 | 02-超级管理员 §2 / 03-超级管理员 §4 / 01 §8.1 | 权限变更→审计日志+实时生效 | 权限审计日志 / 权限实时生效 | | SA-P-03 | 角色管理 | 02-超级管理员 §2 | 停用→关联账号权限失效 | 账号管理(角色绑定) | | SA-P-04 | 权限预设模板 | 02-超级管理员 §2 / 01 §8.4 | 选择模板→自动填充权限 | 角色新增页(模板选择) | | SA-P-05 | 账号角色绑定 | 02-超级管理员 §2 / 03-超级管理员 §4 | 在账号管理中操作 | 账号管理 / 物业组织架构(下属角色分配) | | SA-P-06 | 权限预览 | 02-超级管理员 §2 | 预览→确认权限分配 | 角色新增/编辑页 | | SA-P-07 | 权限自动同步 | 02-超级管理员 §2 / 03-超级管理员 §5 / 01 §8.2 | IModulePlugin注册→权限树自动更新 | 权限配置注册页 | | SA-P-08 | 权限审计日志 | 02-超级管理员 §2 / 03-超级管理员 §8.2 / 01 §8.5 | 权限变更→自动记录 | 操作日志 | | SA-P-09 | 权限实时生效 | 02-超级管理员 §2 / 03-超级管理员 §6 / 01 §8.3 | Redis Pub/Sub毫秒级生效 | — | | SA-P-10 | 权限配置注册 | 02-超级管理员 §2 / 03-超级管理员 §5 | 查看IModulePlugin注册的权限 | 05-接口规范 §4.2 | ## 业务规则 1. **四级权限粒度**:功能菜单→页面→功能点→动作,7种动作类型(view/create/update/delete/approve/export/assign)(来源:01 §8.1 / 06 §4.2) 2. **权限自动同步**:新模块通过IModulePlugin.getPermissionDefinitions()自动注册,权限管理页面自动渲染新可勾选项(来源:01 §8.2 / 05 §4.2) 3. **权限实时生效**:权限变更后通过Redis Pub/Sub毫秒级生效,无需重新登录(来源:01 §8.3 / 03-超级管理员 §6 / 06 §3.1) 4. **权限审计日志**:记录操作人、时间、类型、变更前后对比(来源:01 §8.5 / 03-超级管理员 §8.2) 5. **角色删除条件**:仅关联账号数为0时才可删除(来源:02-超级管理员 SA-P-03) 6. **预设模板使用**:创建角色时选择模板→系统自动填充权限→管理员微调后保存(来源:01 §8.4) 7. **权限配置表只读**:权限配置注册页数据来源于IModulePlugin自动注册,超管只可查看不可手动编辑(来源:03-超级管理员 §5)