|
|
# 账号管理
|
|
|
|
|
|
> 模块编码:account
|
|
|
> 端侧:Web专属(仅超级管理员)
|
|
|
> 关联文档:01-模块划分 §1.1~1.4 / 02-功能清单-超级管理员 §1 / 03-业务流转逻辑-超级管理员 §1~3 / 05-接口规范 §9.2 / 06-项目技术要求 §4.1~4.3
|
|
|
> 强制规范遵循 `07-前端界面开发规范.md`
|
|
|
|
|
|
## 功能概览
|
|
|
|
|
|
| 项目 | 说明 |
|
|
|
|------|------|
|
|
|
| 菜单名称 | 账号管理 |
|
|
|
| 子菜单 | 医院信息管理、物业公司信息管理、医院账号管理、物业公司管理员账号管理、到期账号管理、到期提醒规则配置 |
|
|
|
| 功能编号 | SA-A-01 ~ SA-A-08 |
|
|
|
| 权限编码前缀 | permission:user:* / permission:config:* |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面1:医院信息管理列表页
|
|
|
|
|
|
**页面编号**:SA-A-01-P01
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/hospitals
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 医院信息管理 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [查询条件区] │
|
|
|
│ 医院名称[____] 状态[▼] 联系人[____] [查询] [重置] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [操作栏] [新增医院] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [列表区] │
|
|
|
│ 序号 | 医院名称 | 院区数 | 联系人 | 联系电话 | 状态 | 操作 │
|
|
|
│ 1 | XX医院 | 3 | 张三 | 138****1234| 启用 | 编辑 停用 │
|
|
|
│ 2 | YY医院 | 1 | 李四 | 139****5678| 停用 | 编辑 启用 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [分页] 共50条 每页[20▼] < 1 2 3 > │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 查询条件
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 说明 |
|
|
|
|--------|----------|------|--------|------|
|
|
|
| 医院名称 | 文本输入 | 否 | — | 模糊匹配 |
|
|
|
| 状态 | 下拉单选 | 否 | 全部 | 启用/停用 |
|
|
|
| 联系人 | 文本输入 | 否 | — | 模糊匹配 |
|
|
|
|
|
|
### 列表字段
|
|
|
|
|
|
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|
|
|
|------|--------|------|----------|------|
|
|
|
| 1 | 序号 | 60px | — | 自增序号 |
|
|
|
| 2 | 医院名称 | 180px | 是 | — |
|
|
|
| 3 | 院区数 | 80px | 否 | 显示关联院区数量,点击展开院区列表 |
|
|
|
| 4 | 联系人 | 100px | 否 | — |
|
|
|
| 5 | 联系电话 | 130px | 否 | 脱敏显示 |
|
|
|
| 6 | 创建时间 | 150px | 是 | 默认倒序 |
|
|
|
| 7 | 状态 | 80px | 是 | 启用(绿色)/停用(红色)标签 |
|
|
|
| 8 | 操作 | 140px | — | 编辑/启停 |
|
|
|
|
|
|
### 操作按钮
|
|
|
|
|
|
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|
|
|
|------|----------|------|----------|------|
|
|
|
| 新增医院 | permission:user:create | 操作栏 | 始终 | 跳转新增页 |
|
|
|
| 编辑 | permission:user:update | 行操作 | 始终 | 跳转编辑页 |
|
|
|
| 启用/停用 | permission:user:update | 行操作 | 始终 | 二次确认弹窗 |
|
|
|
|
|
|
### 角色差异化视图
|
|
|
|
|
|
| 角色 | 可见按钮 | 数据范围 | 备注 |
|
|
|
|------|----------|----------|------|
|
|
|
| 超级管理员 | 全部按钮 | 全部医院 | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 调用 `GET /api/v1/hospitals` 加载列表数据(默认第1页,每页20条,创建时间倒序)
|
|
|
- 并行加载下拉选项:状态下拉(启用/停用)
|
|
|
- 列表为空时显示空状态插图 + "暂无医院信息" 提示文字
|
|
|
- 加载中显示 `el-table` 骨架屏(skeleton)效果
|
|
|
|
|
|
2. **查询交互流程**
|
|
|
- 用户填写查询条件 → 点击"查询"按钮 → 前端校验无特殊限制 → 调用API携带筛选参数 → 重新渲染列表(重置到第1页)
|
|
|
- 点击"重置"→ 清空所有查询条件 → 重新加载默认列表
|
|
|
- 支持回车键触发查询
|
|
|
|
|
|
3. **行内操作流程**
|
|
|
- **编辑**:点击"编辑"→ 路由跳转至 `/account/hospitals/:id/edit`
|
|
|
- **启用/停用**:点击"启用"或"停用"→ 弹出 `el-message-box` 二次确认("确认停用XX医院?停用后该医院下所有账号将无法登录")→ 确认后调用 `PUT /api/v1/hospitals/{id}/toggle-status` → 成功后 `el-message` 提示"操作成功" → 刷新当前列表
|
|
|
|
|
|
4. **异常处理**
|
|
|
- API请求失败 → `el-message.error` 提示错误信息,列表保持原数据
|
|
|
- 网络超时 → 提示"网络异常,请稍后重试"
|
|
|
- 启停操作失败 → 提示具体错误原因(如"该医院下存在进行中的工单,无法停用")
|
|
|
|
|
|
5. **权限控制交互**
|
|
|
- 无 `permission:user:create` 权限 → "新增医院"按钮不渲染
|
|
|
- 无 `permission:user:update` 权限 → 行操作列不渲染"编辑"和"启用/停用"按钮
|
|
|
|
|
|
6. **[H1]防重复请求**
|
|
|
- 查询/筛选:点击"查询"按钮后立即 disabled=true + 显示loading态,API返回后恢复;查询期间再次点击无效
|
|
|
- 行内操作(编辑/启停):点击操作按钮后该行所有操作按钮禁用 + 按钮显示loading旋转图标;操作完成后恢复
|
|
|
- 分页切换:切换页码时取消上一页未完成请求(abortController)后再发起新请求
|
|
|
- 页面初始化并行请求(列表+下拉数据)之间互不阻塞
|
|
|
|
|
|
7. **[H2]超时与加载反馈**
|
|
|
- 列表查询API:timeout=15秒;加载中表格区显示v-loading骨架屏遮罩
|
|
|
- 启停等写操作API:timeout=30秒;操作按钮:loading态
|
|
|
- 超时处理:自动中断 → ElMessage.error("请求超时,请检查网络后重试") → 按钮恢复可用
|
|
|
- 列表加载超过2秒时显示全局ElLoading进度提示
|
|
|
|
|
|
8. **[H3]操作确认机制**
|
|
|
- 启用/停用操作:ElMessageBox.confirm("确定要{启用/停用}「{对象名称}」吗?停用后该账号将无法登录", "操作确认", { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
|
|
|
- 确认弹窗期间底层页面不可点击(modal遮罩)
|
|
|
|
|
|
9. **[H8]操作结果反馈**
|
|
|
- 成功操作:ElMessage.success("{操作}成功",duration=2000ms) → silent方式刷新列表数据(不带loading闪烁)
|
|
|
- 失败:ElMessage.error(后端message或"操作失败,请稍后重试",duration=0手动关闭)
|
|
|
- 网络异常:提示"网络连接异常,请检查网络后重试"+ 提供"重试"文字按钮
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 查询条件区 | el-form | inline, label-width="auto" |
|
|
|
| 医院名称/联系人 | el-input | clearable, maxlength=50, placeholder="请输入" |
|
|
|
| 状态下拉 | el-select | clearable, placeholder="请选择" |
|
|
|
| 查询按钮 | el-button | type="primary", icon="Search" |
|
|
|
| 重置按钮 | el-button | icon="Refresh" |
|
|
|
| 列表 | el-table | stripe, border, size="default", v-loading |
|
|
|
| 状态标签 | el-tag | 启用:type="success", 停用:type="danger" |
|
|
|
| 院区数(可点击) | el-link | type="primary", underline=false |
|
|
|
| 操作按钮 | el-button | type="primary", link, size="small" |
|
|
|
| 分页 | el-pagination | layout="total, sizes, prev, pager, next", :page-sizes="[10,20,50]" |
|
|
|
| 新增医院 | el-button | type="primary", icon="Plus" |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 医院名称(查询) | 最大50字符 | — |
|
|
|
| 联系人(查询) | 最大20字符 | — |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 查询条件区一行排列;列表完整展示所有列 |
|
|
|
| 1024-1279px(Pad横屏) | 查询条件区一行排列;"联系人"列隐藏,"创建时间"列隐藏 |
|
|
|
| 768-1023px(Pad竖屏) | 查询条件区两行排列;列表仅显示:序号、医院名称、状态、操作;其余列折叠,点击行展开详情 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面2:医院信息新增/编辑页
|
|
|
|
|
|
**页面编号**:SA-A-01-P02
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/hospitals/create 或 /account/hospitals/:id/edit
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 医院信息管理 > 新增医院 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ ── 基本信息 ────────────────────────────────────────────────── │
|
|
|
│ 医院名称:[____________] 状态:[●启用 ○停用] │
|
|
|
│ 医院地址:[____________________________] │
|
|
|
│ 联系人: [__________] 联系电话:[____________] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ ── 院区信息 ────────────────────────────────────────────────── │
|
|
|
│ [ + 添加院区 ] │
|
|
|
│ ┌────────────────────────────────────────────────────────────┐ │
|
|
|
│ │ 院区1 名称:[主院区] 地址:[____] 联系人:[____] [删除] │ │
|
|
|
│ │ 院区2 名称:[东院区] 地址:[____] 联系人:[____] [删除] │ │
|
|
|
│ └────────────────────────────────────────────────────────────┘ │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [取消] [保存] │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 表单字段(基本信息)
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|
|
|
|--------|----------|------|--------|----------|----------|
|
|
|
| 医院名称 | 文本输入 | 是 | — | 自填 | 最大50字,全局唯一 |
|
|
|
| 状态 | 单选按钮 | 是 | 启用 | 固定选项 | — |
|
|
|
| 医院地址 | 文本输入 | 否 | — | 自填 | 最大200字 |
|
|
|
| 联系人 | 文本输入 | 否 | — | 自填 | 最大20字 |
|
|
|
| 联系电话 | 文本输入 | 否 | — | 自填 | 手机号格式 |
|
|
|
|
|
|
### 表单字段(院区信息,支持多条)
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|
|
|
|--------|----------|------|--------|----------|----------|
|
|
|
| 院区名称 | 文本输入 | 是 | — | 自填 | 最大30字,同医院内唯一 |
|
|
|
| 院区地址 | 文本输入 | 是 | — | 自填 | 最大200字 |
|
|
|
| 联系人 | 文本输入 | 否 | — | 自填 | 最大20字 |
|
|
|
|
|
|
### 通知触发
|
|
|
|
|
|
| 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 |
|
|
|
|----------|----------|----------|----------|----------|
|
|
|
| 创建医院 | — | — | — | 仅记录操作日志 |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 新增医院 | /api/v1/hospitals | POST | 含院区列表 |
|
|
|
| 编辑医院 | /api/v1/hospitals/{id} | PUT | 含院区列表 |
|
|
|
| 查询详情 | /api/v1/hospitals/{id} | GET | 编辑时回填 |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 新增模式:页面空白表单,状态默认"启用"
|
|
|
- 编辑模式:根据路由参数 `:id` 调用 `GET /api/v1/hospitals/{id}` 回填表单数据
|
|
|
- 加载中显示表单骨架屏
|
|
|
|
|
|
2. **表单填写与提交流程**
|
|
|
- 用户逐项填写基本信息 → 动态添加/删除院区行 → 点击"保存"→ 前端校验 → 调用API → 成功后 `el-message.success` → 路由跳转回列表页
|
|
|
- 编辑模式下保存 → 调用 `PUT /api/v1/hospitals/{id}` → 成功后返回列表页
|
|
|
|
|
|
3. **院区动态表单交互**
|
|
|
- 点击"+添加院区"→ 在院区列表末尾新增一行空表单
|
|
|
- 点击"删除"→ 二次确认后移除该院区行(至少保留一个院区)
|
|
|
- 院区行内字段实时校验
|
|
|
|
|
|
4. **联动交互**
|
|
|
- 无特殊联动逻辑
|
|
|
|
|
|
5. **异常处理**
|
|
|
- 唯一性校验失败(医院名称重复)→ 对应字段下方显示红色错误提示"该医院名称已存在"
|
|
|
- API失败 → `el-message.error` 提示错误信息,表单保持当前数据不丢失
|
|
|
- 编辑模式下详情加载失败 → 提示"数据加载失败"并提供"返回列表"按钮
|
|
|
|
|
|
6. **权限控制交互**
|
|
|
- 无保存权限时 → "保存"按钮禁用
|
|
|
|
|
|
7. **[H1]防重复请求**
|
|
|
- 点击"保存"按钮后:按钮 :loading=true + 文案变为"保存中..." + 按钮disabled;API返回(成功/失败/超时)后恢复
|
|
|
- 保存期间不允许再次点击保存或关闭页面
|
|
|
- 院区行动态增删操作:删除院区确认弹窗pending期间禁用其他删除按钮
|
|
|
|
|
|
8. **[H2]超时与加载反馈**
|
|
|
- 新增/编辑提交API(POST/PUT):timeout=30秒
|
|
|
- 编辑模式详情回填API(GET):timeout=15秒
|
|
|
- 提交中保存按钮保持:loading态 + 表单区域不可编辑(半透明遮罩可选)
|
|
|
- 超时处理:中断请求 → 提示"保存超时,请检查网络后重试" → 按钮恢复
|
|
|
|
|
|
9. **[H3]操作确认机制**
|
|
|
- 删除院区行前 ElMessageBox.confirm("确定要删除该院区吗?删除后数据无法恢复", "删除确认", { type: 'warning' })
|
|
|
|
|
|
10. **[H4]脏数据检测**
|
|
|
- 编辑模式进入时deep clone表单初始数据作为快照
|
|
|
- 用户修改任意字段后标记isDirty=true
|
|
|
- 点击"取消"按钮或浏览器后退时:
|
|
|
* isDirty=true → ElMessageBox.confirm("当前修改尚未保存,离开后将丢失未保存的内容,是否确认离开?") → 确认则离开/取消则停留
|
|
|
* isDirty=false → 直接执行离开操作
|
|
|
- 使用vue-router的beforeRouteLeave导航守卫拦截路由切换
|
|
|
- 保存成功后将当前数据设为新快照,重置isDirty=false
|
|
|
|
|
|
11. **[H8]操作结果反馈**
|
|
|
- 保存成功:ElMessage.success("保存成功", duration=2000) → 延迟300ms后router.back()返回列表页
|
|
|
- 保存失败:ElMessage.error(错误信息, duration=0);表单数据保持不丢失
|
|
|
- 唯一性校验失败:对应字段下方红色文字提示,不弹message
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 基本信息表单 | el-form | label-width="100px", :model, :rules |
|
|
|
| 医院名称 | el-input | maxlength=50, show-word-limit, clearable |
|
|
|
| 状态 | el-radio-group | el-radio label="启用"/"停用" |
|
|
|
| 医院地址 | el-input | maxlength=200, show-word-limit |
|
|
|
| 联系人 | el-input | maxlength=20 |
|
|
|
| 联系电话 | el-input | maxlength=11, type="tel" |
|
|
|
| 院区列表 | 动态表单行 | v-for 渲染, 动态增删 |
|
|
|
| 院区名称 | el-input | maxlength=30, show-word-limit |
|
|
|
| 院区地址 | el-input | maxlength=200 |
|
|
|
| 保存按钮 | el-button | type="primary", :loading |
|
|
|
| 取消按钮 | el-button | @click="router.back()" |
|
|
|
| 添加院区 | el-button | type="primary", plain, icon="Plus" |
|
|
|
| 删除院区 | el-button | type="danger", link, icon="Delete" |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 医院名称 | 必填, 2-50字符, 全局唯一 | "请输入医院名称" / "医院名称长度2-50字符" / "该医院名称已存在" |
|
|
|
| 状态 | 必填 | "请选择状态" |
|
|
|
| 医院地址 | 最大200字符 | "医院地址不能超过200字符" |
|
|
|
| 联系人 | 最大20字符 | "联系人不能超过20字符" |
|
|
|
| 联系电话 | 手机号格式(/^1[3-9]\d{9}$/) | "请输入正确的手机号" |
|
|
|
| 院区名称 | 必填, 2-30字符, 同医院内唯一 | "请输入院区名称" / "院区名称长度2-30字符" / "该院区名称已存在" |
|
|
|
| 院区地址 | 必填, 最大200字符 | "请输入院区地址" / "院区地址不能超过200字符" |
|
|
|
| 院区列表 | 至少1个院区 | "请至少添加一个院区" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 基本信息两列排列(医院名称+状态一行,地址独占一行,联系人+电话一行);院区信息卡片宽度100% |
|
|
|
| 1024-1279px(Pad横屏) | 基本信息两列排列;院区信息卡片宽度100% |
|
|
|
| 768-1023px(Pad竖屏) | 基本信息单列排列(每行一个字段);院区信息卡片宽度100%,院内行单列 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面3:物业公司信息管理列表页
|
|
|
|
|
|
**页面编号**:SA-A-02-P01
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/property-companies
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 物业公司信息管理 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [查询条件区] │
|
|
|
│ 公司名称[____] 状态[▼] 联系人[____] [查询] [重置] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [操作栏] [新增物业公司] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [列表区] │
|
|
|
│ 序号 | 公司名称 | 服务医院 | 联系人 | 联系电话 | 状态 | 操作 │
|
|
|
│ 1 | XX物业 | A医院 | 王五 | 137****9012| 启用 | 编辑 停用 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [分页] 共30条 每页[20▼] < 1 2 > │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 查询条件
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 说明 |
|
|
|
|--------|----------|------|--------|------|
|
|
|
| 公司名称 | 文本输入 | 否 | — | 模糊匹配 |
|
|
|
| 状态 | 下拉单选 | 否 | 全部 | 启用/停用 |
|
|
|
| 联系人 | 文本输入 | 否 | — | 模糊匹配 |
|
|
|
|
|
|
### 列表字段
|
|
|
|
|
|
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|
|
|
|------|--------|------|----------|------|
|
|
|
| 1 | 序号 | 60px | — | 自增序号 |
|
|
|
| 2 | 公司名称 | 180px | 是 | — |
|
|
|
| 3 | 服务医院 | 150px | 否 | 显示关联医院名称列表 |
|
|
|
| 4 | 联系人 | 100px | 否 | — |
|
|
|
| 5 | 联系电话 | 130px | 否 | 脱敏显示 |
|
|
|
| 6 | 创建时间 | 150px | 是 | 默认倒序 |
|
|
|
| 7 | 状态 | 80px | 是 | 启用/停用标签 |
|
|
|
| 8 | 操作 | 140px | — | 编辑/启停 |
|
|
|
|
|
|
### 操作按钮
|
|
|
|
|
|
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|
|
|
|------|----------|------|----------|------|
|
|
|
| 新增物业公司 | permission:user:create | 操作栏 | 始终 | 跳转新增页 |
|
|
|
| 编辑 | permission:user:update | 行操作 | 始终 | — |
|
|
|
| 启用/停用 | permission:user:update | 行操作 | 始终 | 二次确认 |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 列表查询 | /api/v1/property-companies | GET | 分页查询 |
|
|
|
| 启用/停用 | /api/v1/property-companies/{id}/toggle-status | PUT | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 调用 `GET /api/v1/property-companies` 加载列表(默认第1页,每页20条,创建时间倒序)
|
|
|
- 并行加载下拉选项:状态下拉
|
|
|
- 列表为空时显示空状态插图 + "暂无物业公司信息"
|
|
|
|
|
|
2. **查询交互流程**
|
|
|
- 填写查询条件 → 点击"查询"→ 调用API → 重置到第1页渲染
|
|
|
- 点击"重置"→ 清空条件 → 重新加载
|
|
|
|
|
|
3. **行内操作流程**
|
|
|
- **编辑**:点击"编辑"→ 路由跳转至 `/account/property-companies/:id/edit`
|
|
|
- **启用/停用**:二次确认弹窗("确认停用XX物业?停用后该物业下所有账号将无法登录")→ 确认后调用API → 成功提示 → 刷新列表
|
|
|
|
|
|
4. **异常处理**
|
|
|
- 同页面1通用异常处理规则
|
|
|
|
|
|
5. **权限控制交互**
|
|
|
- 无 `permission:user:create` → "新增物业公司"按钮不渲染
|
|
|
- 无 `permission:user:update` → 行操作列不渲染
|
|
|
|
|
|
6. **[H1]防重复请求**
|
|
|
- 查询/筛选:点击"查询"按钮后立即 disabled=true + 显示loading态,API返回后恢复;查询期间再次点击无效
|
|
|
- 行内操作(编辑/启停):点击操作按钮后该行所有操作按钮禁用 + 按钮显示loading旋转图标;操作完成后恢复
|
|
|
- 分页切换:切换页码时取消上一页未完成请求(abortController)后再发起新请求
|
|
|
- 页面初始化并行请求(列表+下拉数据)之间互不阻塞
|
|
|
|
|
|
7. **[H2]超时与加载反馈**
|
|
|
- 列表查询API:timeout=15秒;加载中表格区显示v-loading骨架屏遮罩
|
|
|
- 启停等写操作API:timeout=30秒;操作按钮:loading态
|
|
|
- 超时处理:自动中断 → ElMessage.error("请求超时,请检查网络后重试") → 按钮恢复可用
|
|
|
- 列表加载超过2秒时显示全局ElLoading进度提示
|
|
|
|
|
|
8. **[H3]操作确认机制**
|
|
|
- 启用/停用操作:ElMessageBox.confirm("确定要{启用/停用}「{对象名称}」吗?停用后该账号将无法登录", "操作确认", { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
|
|
|
- 确认弹窗期间底层页面不可点击(modal遮罩)
|
|
|
|
|
|
9. **[H8]操作结果反馈**
|
|
|
- 成功操作:ElMessage.success("{操作}成功",duration=2000ms) → silent方式刷新列表数据(不带loading闪烁)
|
|
|
- 失败:ElMessage.error(后端message或"操作失败,请稍后重试",duration=0手动关闭)
|
|
|
- 网络异常:提示"网络连接异常,请检查网络后重试"+ 提供"重试"文字按钮
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 列表 | el-table | stripe, border, v-loading |
|
|
|
| 服务医院(可点击) | el-link | type="primary" |
|
|
|
| 状态标签 | el-tag | 启用:type="success", 停用:type="danger" |
|
|
|
| 操作按钮 | el-button | type="primary", link, size="small" |
|
|
|
| 分页 | el-pagination | layout="total, sizes, prev, pager, next" |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 公司名称(查询) | 最大50字符 | — |
|
|
|
| 联系人(查询) | 最大20字符 | — |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 查询条件一行排列;列表完整展示所有列 |
|
|
|
| 1024-1279px(Pad横屏) | 查询条件一行排列;"联系人""联系电话"列隐藏 |
|
|
|
| 768-1023px(Pad竖屏) | 查询条件两行排列;列表仅显示:序号、公司名称、状态、操作 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面4:物业公司信息新增/编辑页
|
|
|
|
|
|
**页面编号**:SA-A-02-P02
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/property-companies/create 或 /account/property-companies/:id/edit
|
|
|
|
|
|
### 表单字段
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|
|
|
|--------|----------|------|--------|----------|----------|
|
|
|
| 公司名称 | 文本输入 | 是 | — | 自填 | 最大50字,全局唯一 |
|
|
|
| 公司地址 | 文本输入 | 否 | — | 自填 | 最大200字 |
|
|
|
| 联系人 | 文本输入 | 是 | — | 自填 | 最大20字 |
|
|
|
| 联系电话 | 文本输入 | 是 | — | 自填 | 手机号格式 |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 新增 | /api/v1/property-companies | POST | — |
|
|
|
| 编辑 | /api/v1/property-companies/{id} | PUT | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 新增模式:空白表单
|
|
|
- 编辑模式:根据路由参数 `:id` 调用 `GET /api/v1/property-companies/{id}` 回填数据
|
|
|
|
|
|
2. **表单填写与提交流程**
|
|
|
- 填写表单 → 点击"保存"→ 前端校验 → 调用API → 成功提示 → 返回列表页
|
|
|
- 校验失败 → 定位到第一个错误字段,滚动到可见区域
|
|
|
|
|
|
3. **异常处理**
|
|
|
- 唯一性校验失败 → 字段下方红色提示"该公司名称已存在"
|
|
|
- API失败 → 提示错误信息,表单数据不丢失
|
|
|
|
|
|
4. **[H1]防重复请求**
|
|
|
- 点击"保存"按钮后:按钮 :loading=true + 文案变为"保存中..." + 按钮disabled;API返回(成功/失败/超时)后恢复
|
|
|
- 保存期间不允许再次点击保存或关闭页面
|
|
|
|
|
|
5. **[H2]超时与加载反馈**
|
|
|
- 新增/编辑提交API(POST/PUT):timeout=30秒
|
|
|
- 编辑模式详情回填API(GET):timeout=15秒
|
|
|
- 提交中保存按钮保持:loading态 + 表单区域不可编辑(半透明遮罩可选)
|
|
|
- 超时处理:中断请求 → 提示"保存超时,请检查网络后重试" → 按钮恢复
|
|
|
|
|
|
6. **[H4]脏数据检测**
|
|
|
- 编辑模式进入时deep clone表单初始数据作为快照
|
|
|
- 用户修改任意字段后标记isDirty=true
|
|
|
- 点击"取消"按钮或浏览器后退时:
|
|
|
* isDirty=true → ElMessageBox.confirm("当前修改尚未保存,离开后将丢失未保存的内容,是否确认离开?") → 确认则离开/取消则停留
|
|
|
* isDirty=false → 直接执行离开操作
|
|
|
- 使用vue-router的beforeRouteLeave导航守卫拦截路由切换
|
|
|
- 保存成功后将当前数据设为新快照,重置isDirty=false
|
|
|
|
|
|
7. **[H8]操作结果反馈**
|
|
|
- 保存成功:ElMessage.success("保存成功", duration=2000) → 延迟300ms后router.back()返回列表页
|
|
|
- 保存失败:ElMessage.error(错误信息, duration=0);表单数据保持不丢失
|
|
|
- 唯一性校验失败:对应字段下方红色文字提示,不弹message
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 表单 | el-form | label-width="100px", :model, :rules |
|
|
|
| 公司名称 | el-input | maxlength=50, show-word-limit |
|
|
|
| 公司地址 | el-input | maxlength=200 |
|
|
|
| 联系人 | el-input | maxlength=20 |
|
|
|
| 联系电话 | el-input | maxlength=11, type="tel" |
|
|
|
| 保存按钮 | el-button | type="primary", :loading |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 公司名称 | 必填, 2-50字符, 全局唯一 | "请输入公司名称" / "公司名称长度2-50字符" / "该公司名称已存在" |
|
|
|
| 公司地址 | 最大200字符 | "公司地址不能超过200字符" |
|
|
|
| 联系人 | 必填, 最大20字符 | "请输入联系人" / "联系人不能超过20字符" |
|
|
|
| 联系电话 | 必填, 手机号格式 | "请输入联系电话" / "请输入正确的手机号" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 表单两列排列(公司名称+联系人一行,地址独占一行) |
|
|
|
| 1024-1279px(Pad横屏) | 表单两列排列 |
|
|
|
| 768-1023px(Pad竖屏) | 表单单列排列 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面5:医院账号管理列表页
|
|
|
|
|
|
**页面编号**:SA-A-03-P01
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/hospital-accounts
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 医院账号管理 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [查询条件区] │
|
|
|
│ 登录账号[____] 绑定医院[▼] 状态[▼] 有效期[▼] [查询] [重置] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [操作栏] [新增医院账号] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [列表区] │
|
|
|
│ 序号 | 登录账号 | 绑定医院 | 角色 | 有效期至 | 状态 | 操作 │
|
|
|
│ 1 | hospital01| XX医院 | 医院查看 | 2027-04-16| 正常 | 编辑 续期│
|
|
|
│ 2 | hospital02| YY医院 | 医院查看 | 2026-03-01| 即将到期| 续期 │
|
|
|
│ 3 | hospital03| ZZ医院 | 医院查看 | 2026-01-01| 已过期| 续期 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [分页] 共20条 每页[20▼] < 1 > │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 查询条件
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 说明 |
|
|
|
|--------|----------|------|--------|------|
|
|
|
| 登录账号 | 文本输入 | 否 | — | 精确匹配 |
|
|
|
| 绑定医院 | 下拉单选 | 否 | 全部 | 数据来源:医院信息管理 |
|
|
|
| 状态 | 下拉单选 | 否 | 全部 | 正常/即将到期/已过期/已停用 |
|
|
|
| 有效期 | 下拉单选 | 否 | 全部 | 已过期/7天内到期/30天内到期/正常 |
|
|
|
|
|
|
### 列表字段
|
|
|
|
|
|
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|
|
|
|------|--------|------|----------|------|
|
|
|
| 1 | 序号 | 60px | — | 自增 |
|
|
|
| 2 | 登录账号 | 130px | 否 | — |
|
|
|
| 3 | 绑定医院 | 150px | 是 | — |
|
|
|
| 4 | 角色 | 120px | 否 | 显示分配的角色名称 |
|
|
|
| 5 | 有效期至 | 120px | 是 | 即将到期=橙色,已过期=红色 |
|
|
|
| 6 | 状态 | 100px | 是 | 正常(绿)/即将到期(橙)/已过期(红)/已停用(灰) |
|
|
|
| 7 | 操作 | 200px | — | 编辑/续期/启停/重置密码 |
|
|
|
|
|
|
### 操作按钮
|
|
|
|
|
|
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|
|
|
|------|----------|------|----------|------|
|
|
|
| 新增医院账号 | permission:user:create | 操作栏 | 始终 | — |
|
|
|
| 编辑 | permission:user:update | 行操作 | 始终 | — |
|
|
|
| 续期 | permission:user:update | 行操作 | 始终 | 修改有效期 |
|
|
|
| 启用/禁用 | permission:user:update | 行操作 | 始终 | 二次确认,禁用立即生效 |
|
|
|
| 重置密码 | permission:user:update | 行操作 | 始终 | 重置为默认密码 |
|
|
|
|
|
|
### 通知触发
|
|
|
|
|
|
| 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 |
|
|
|
|----------|----------|----------|----------|----------|
|
|
|
| 账号禁用 | 被禁用账号 | — | 已登录session立即失效 | 03-超级管理员 §2 |
|
|
|
| 重置密码 | 账号持有人 | — | 下次登录使用新密码 | — |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 列表查询 | /api/v1/accounts/hospital | GET | 分页查询 |
|
|
|
| 启用/禁用 | /api/v1/accounts/{id}/toggle-status | PUT | 禁用立即失效session |
|
|
|
| 续期 | /api/v1/accounts/{id}/renew | PUT | 修改有效期 |
|
|
|
| 重置密码 | /api/v1/accounts/{id}/reset-password | PUT | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 并行调用:列表查询API + 绑定医院下拉数据 + 状态下拉 + 有效期下拉
|
|
|
- 加载中骨架屏 → 数据渲染列表
|
|
|
|
|
|
2. **查询交互流程**
|
|
|
- 填写查询条件 → 点击"查询"→ 调用API → 重置到第1页
|
|
|
- "绑定医院"下拉支持搜索过滤(filterable)
|
|
|
|
|
|
3. **行内操作流程**
|
|
|
- **编辑**:点击"编辑"→ 路由跳转编辑页(如存在独立编辑页)
|
|
|
- **续期**:点击"续期"→ 弹出续期弹窗(`el-dialog`,选择新有效期日期)→ 确认后调用 `PUT /api/v1/accounts/{id}/renew` → 成功提示 → 刷新列表
|
|
|
- **启用/禁用**:二次确认("确认禁用该账号?禁用后该账号将立即无法登录")→ 确认后调用API → 成功提示 → 刷新列表
|
|
|
- **重置密码**:二次确认("确认重置密码?重置后密码将恢复为默认密码")→ 确认后调用API → 成功后弹窗展示新密码,支持一键复制
|
|
|
|
|
|
4. **联动交互**
|
|
|
- 绑定医院下拉数据来源于医院信息管理中的启用状态医院
|
|
|
|
|
|
5. **异常处理**
|
|
|
- 禁用失败(账号已禁用等)→ 提示具体原因
|
|
|
- 续期时新有效期早于当前日期 → 前端校验拦截,提示"有效期不能早于当前日期"
|
|
|
- 重置密码失败 → 提示错误信息
|
|
|
|
|
|
6. **权限控制交互**
|
|
|
- 无对应权限 → 行操作按钮不渲染
|
|
|
|
|
|
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("确定要{启用/禁用}「{对象名称}」吗?禁用后该账号将无法登录", "操作确认", { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
|
|
|
- 重置密码:ElMessageBox.confirm("确定要重置「{账号}」的密码吗?重置后将恢复为默认密码", "操作确认", { type: 'warning' })
|
|
|
- 确认弹窗期间底层页面不可点击(modal遮罩)
|
|
|
|
|
|
10. **[H8]操作结果反馈**
|
|
|
- 成功操作:ElMessage.success("{操作}成功",duration=2000ms) → silent方式刷新列表数据(不带loading闪烁)
|
|
|
- 失败:ElMessage.error(后端message或"操作失败,请稍后重试",duration=0手动关闭)
|
|
|
- 网络异常:提示"网络连接异常,请检查网络后重试"+ 提供"重试"文字按钮
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 绑定医院下拉 | el-select | filterable, clearable, remote, placeholder="请选择医院" |
|
|
|
| 有效期至 | el-tag | 正常:type="success", 即将到期:type="warning", 已过期:type="danger" |
|
|
|
| 状态标签 | el-tag | 正常:type="success", 即将到期:type="warning", 已过期:type="danger", 已停用:type="info" |
|
|
|
| 续期弹窗 | el-dialog | width="400px", :close-on-click-modal=false |
|
|
|
| 续期日期选择 | el-date-picker | type="date", :disabled-date="禁用过去日期" |
|
|
|
| 重置密码结果弹窗 | el-dialog | 展示新密码 + 复制按钮 |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 续期日期 | 必填, 不早于当前日期 | "请选择有效期" / "有效期不能早于当前日期" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 查询条件一行排列;列表完整展示所有列 |
|
|
|
| 1024-1279px(Pad横屏) | 查询条件一行排列;"角色"列隐藏 |
|
|
|
| 768-1023px(Pad竖屏) | 查询条件两行排列;列表仅显示:序号、登录账号、绑定医院、状态、操作 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面6:新增医院账号页
|
|
|
|
|
|
**页面编号**:SA-A-03-P02
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/hospital-accounts/create
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 医院账号管理 > 新增医院账号 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ 登录账号:[____________] 初始密码:[________](自动生成) │
|
|
|
│ 绑定医院:[▼必选] │
|
|
|
│ 有效期至:[日期选择] (必填) │
|
|
|
│ 分配角色:[▼多选] □ 医院查看模板 □ 自定义... │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [取消] [保存] │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 表单字段
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|
|
|
|--------|----------|------|--------|----------|----------|
|
|
|
| 登录账号 | 文本输入 | 是 | — | 自填 | 4~20位字母数字,全局唯一 |
|
|
|
| 初始密码 | 文本输入 | 是 | 系统生成 | 自动生成 | 可手动修改,6~20位 |
|
|
|
| 绑定医院 | 下拉单选 | 是 | — | 医院信息列表 | — |
|
|
|
| 有效期至 | 日期选择 | 是 | — | 自填 | 不早于当前日期 |
|
|
|
| 分配角色 | 下拉多选 | 是 | — | 角色管理-医院适用角色 | 至少选一个 |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 新增 | /api/v1/accounts/hospital | POST | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 并行加载:绑定医院下拉(仅启用状态医院)+ 角色下拉(仅医院适用范围角色)
|
|
|
- 自动生成初始密码(8位随机字母数字),显示在密码输入框中
|
|
|
- 有效期默认为当前日期+1年
|
|
|
|
|
|
2. **表单填写与提交流程**
|
|
|
- 填写登录账号 → 实时校验唯一性(失焦时调用后端校验接口)
|
|
|
- 选择绑定医院 → 选择有效期 → 分配角色 → 点击"保存"→ 前端校验全部通过 → 调用API → 成功提示 → 返回列表页
|
|
|
|
|
|
3. **联动交互**
|
|
|
- 绑定医院下拉:数据来源于医院信息管理中启用状态的医院
|
|
|
- 分配角色下拉:数据来源于权限管理中"适用范围=医院账号"的启用角色
|
|
|
|
|
|
4. **异常处理**
|
|
|
- 登录账号重复 → 失焦校验后即时提示"该登录账号已存在"
|
|
|
- 保存失败 → 提示错误信息,表单数据不丢失
|
|
|
|
|
|
5. **权限控制交互**
|
|
|
- 无保存权限时 → "保存"按钮禁用
|
|
|
|
|
|
6. **[H1]防重复请求**
|
|
|
- 点击"保存"按钮后:按钮 :loading=true + 文案变为"保存中..." + 按钮disabled;API返回(成功/失败/超时)后恢复
|
|
|
- 保存期间不允许再次点击保存或关闭页面
|
|
|
|
|
|
7. **[H2]超时与加载反馈**
|
|
|
- 新增提交API(POST):timeout=30秒
|
|
|
- 提交中保存按钮保持:loading态 + 表单区域不可编辑(半透明遮罩可选)
|
|
|
- 超时处理:中断请求 → 提示"保存超时,请检查网络后重试" → 按钮恢复
|
|
|
|
|
|
8. **[H4]脏数据检测**
|
|
|
- 页面进入时deep clone表单初始数据作为快照
|
|
|
- 用户修改任意字段后标记isDirty=true
|
|
|
- 点击"取消"按钮或浏览器后退时:
|
|
|
* isDirty=true → ElMessageBox.confirm("当前修改尚未保存,离开后将丢失未保存的内容,是否确认离开?") → 确认则离开/取消则停留
|
|
|
* isDirty=false → 直接执行离开操作
|
|
|
- 使用vue-router的beforeRouteLeave导航守卫拦截路由切换
|
|
|
- 保存成功后将当前数据设为新快照,重置isDirty=false
|
|
|
|
|
|
9. **[H8]操作结果反馈**
|
|
|
- 保存成功:ElMessage.success("保存成功", duration=2000) → 延迟300ms后router.back()返回列表页
|
|
|
- 保存失败:ElMessage.error(错误信息, duration=0);表单数据保持不丢失
|
|
|
- 唯一性校验失败:对应字段下方红色文字提示,不弹message
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 表单 | el-form | label-width="100px", :model, :rules |
|
|
|
| 登录账号 | el-input | maxlength=20, clearable, placeholder="4-20位字母数字" |
|
|
|
| 初始密码 | el-input | maxlength=20, show-password, readonly=false |
|
|
|
| 绑定医院 | el-select | filterable, clearable, placeholder="请选择医院" |
|
|
|
| 有效期至 | el-date-picker | type="date", :disabled-date="禁用过去日期", value-format="YYYY-MM-DD" |
|
|
|
| 分配角色 | el-select | multiple, filterable, collapse-tags, placeholder="请选择角色" |
|
|
|
| 保存按钮 | el-button | type="primary", :loading |
|
|
|
| 取消按钮 | el-button | @click="router.back()" |
|
|
|
| 刷新密码按钮 | el-button | icon="Refresh", circle, @click="generatePassword" |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 登录账号 | 必填, 4-20位字母数字(/^[a-zA-Z0-9]{4,20}$/), 全局唯一 | "请输入登录账号" / "登录账号为4-20位字母数字" / "该登录账号已存在" |
|
|
|
| 初始密码 | 必填, 6-20位 | "请输入初始密码" / "密码长度6-20位" |
|
|
|
| 绑定医院 | 必填 | "请选择绑定医院" |
|
|
|
| 有效期至 | 必填, 不早于当前日期 | "请选择有效期" / "有效期不能早于当前日期" |
|
|
|
| 分配角色 | 必填, 至少选一个 | "请选择至少一个角色" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 表单两列排列(登录账号+初始密码一行,绑定医院+有效期一行,角色独占一行) |
|
|
|
| 1024-1279px(Pad横屏) | 表单两列排列 |
|
|
|
| 768-1023px(Pad竖屏) | 表单单列排列,每个字段独占一行 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面7:物业公司管理员账号管理列表页
|
|
|
|
|
|
**页面编号**:SA-A-04-P01
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/property-accounts
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 物业管理员账号管理 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [查询条件区] │
|
|
|
│ 登录账号[____] 绑定物业公司[▼] 服务医院[▼] 状态[▼] [查询] [重置] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [操作栏] [新增物业管理员账号] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [列表区] │
|
|
|
│ 序号 | 登录账号 | 绑定物业 | 服务医院 | 角色 | 有效期至 | 状态 | 操作│
|
|
|
│ 1 | prop01 | XX物业 | A医院 | 管理员| 2027-04| 正常 | ...│
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [分页] 共40条 每页[20▼] < 1 2 > │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 查询条件
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 说明 |
|
|
|
|--------|----------|------|--------|------|
|
|
|
| 登录账号 | 文本输入 | 否 | — | 精确匹配 |
|
|
|
| 绑定物业公司 | 下拉单选 | 否 | 全部 | 数据来源:物业公司信息管理 |
|
|
|
| 服务医院 | 下拉单选 | 否 | 全部 | 数据来源:医院信息管理 |
|
|
|
| 状态 | 下拉单选 | 否 | 全部 | 正常/即将到期/已过期/已停用 |
|
|
|
|
|
|
### 列表字段
|
|
|
|
|
|
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|
|
|
|------|--------|------|----------|------|
|
|
|
| 1 | 序号 | 60px | — | 自增 |
|
|
|
| 2 | 登录账号 | 120px | 否 | — |
|
|
|
| 3 | 绑定物业公司 | 120px | 是 | — |
|
|
|
| 4 | 服务医院 | 120px | 是 | — |
|
|
|
| 5 | 角色 | 120px | 否 | — |
|
|
|
| 6 | 有效期至 | 110px | 是 | 颜色标记同医院账号 |
|
|
|
| 7 | 状态 | 90px | 是 | 同医院账号 |
|
|
|
| 8 | 操作 | 200px | — | 编辑/续期/启停/重置密码 |
|
|
|
|
|
|
### 操作按钮
|
|
|
|
|
|
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|
|
|
|------|----------|------|----------|------|
|
|
|
| 新增物业管理员账号 | permission:user:create | 操作栏 | 始终 | — |
|
|
|
| 编辑 | permission:user:update | 行操作 | 始终 | — |
|
|
|
| 续期 | permission:user:update | 行操作 | 始终 | — |
|
|
|
| 启用/禁用 | permission:user:update | 行操作 | 始终 | 禁用时下属账号同步失效 |
|
|
|
| 重置密码 | permission:user:update | 行操作 | 始终 | — |
|
|
|
|
|
|
### 通知触发
|
|
|
|
|
|
| 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 |
|
|
|
|----------|----------|----------|----------|----------|
|
|
|
| 账号禁用 | 物业管理员 | — | session失效+小程序同步下线 | 03-超级管理员 §2 |
|
|
|
| 账号禁用 | 下属人员 | 小程序推送 | 关联下属账号同步失效 | 01 §1.4 |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 列表查询 | /api/v1/accounts/property-admin | GET | 分页查询 |
|
|
|
| 启用/禁用 | /api/v1/accounts/{id}/toggle-status | PUT | 禁用同步下线下属 |
|
|
|
| 续期 | /api/v1/accounts/{id}/renew | PUT | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 并行加载:列表数据 + 绑定物业公司下拉 + 服务医院下拉 + 状态下拉
|
|
|
- 加载中骨架屏
|
|
|
|
|
|
2. **查询交互流程**
|
|
|
- 填写条件 → 点击"查询"→ 调用API → 重置到第1页
|
|
|
- "绑定物业公司"和"服务医院"下拉均支持搜索过滤
|
|
|
|
|
|
3. **行内操作流程**
|
|
|
- **编辑**:跳转编辑页
|
|
|
- **续期**:弹出续期弹窗 → 选择新有效期 → 确认 → API调用 → 刷新列表
|
|
|
- **启用/禁用**:二次确认("确认禁用?禁用后该管理员及所有下属账号将同步失效")→ 确认 → API调用 → 刷新列表
|
|
|
- **重置密码**:二次确认 → API调用 → 弹窗展示新密码
|
|
|
|
|
|
4. **联动交互**
|
|
|
- 物业公司下拉数据来源于物业公司信息管理中的启用状态公司
|
|
|
- 选择物业公司后,服务医院下拉可联动过滤该物业关联的医院
|
|
|
|
|
|
5. **异常处理**
|
|
|
- 禁用操作提示级联影响范围:"该操作将同步禁用X个下属账号"
|
|
|
- 其他同页面5
|
|
|
|
|
|
6. **权限控制交互**
|
|
|
- 同页面5
|
|
|
|
|
|
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("确定要{启用/禁用}「{对象名称}」吗?禁用后将同步禁用所有下属账号", "操作确认", { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
|
|
|
- 重置密码:ElMessageBox.confirm("确定要重置「{账号}」的密码吗?重置后将恢复为默认密码", "操作确认", { type: 'warning' })
|
|
|
- 确认弹窗期间底层页面不可点击(modal遮罩)
|
|
|
|
|
|
10. **[H8]操作结果反馈**
|
|
|
- 成功操作:ElMessage.success("{操作}成功",duration=2000ms) → silent方式刷新列表数据(不带loading闪烁)
|
|
|
- 失败:ElMessage.error(后端message或"操作失败,请稍后重试",duration=0手动关闭)
|
|
|
- 网络异常:提示"网络连接异常,请检查网络后重试"+ 提供"重试"文字按钮
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 绑定物业公司下拉 | el-select | filterable, clearable |
|
|
|
| 服务医院下拉 | el-select | filterable, clearable |
|
|
|
| 状态标签 | el-tag | 同页面5颜色规则 |
|
|
|
| 操作按钮 | el-button | type="primary", link, size="small" |
|
|
|
| 续期弹窗 | el-dialog | width="400px" |
|
|
|
| 续期日期选择 | el-date-picker | type="date", :disabled-date |
|
|
|
| 重置密码结果弹窗 | el-dialog | 展示新密码 + 复制按钮 |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 续期日期 | 必填, 不早于当前日期 | "请选择有效期" / "有效期不能早于当前日期" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 查询条件一行排列;列表完整展示所有列 |
|
|
|
| 1024-1279px(Pad横屏) | 查询条件两行排列;"角色"列隐藏 |
|
|
|
| 768-1023px(Pad竖屏) | 查询条件两行排列;列表仅显示:序号、登录账号、绑定物业、状态、操作 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面8:新增物业管理员账号页
|
|
|
|
|
|
**页面编号**:SA-A-04-P02
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/property-accounts/create
|
|
|
|
|
|
### 表单字段
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|
|
|
|--------|----------|------|--------|----------|----------|
|
|
|
| 登录账号 | 文本输入 | 是 | — | 自填 | 4~20位字母数字,全局唯一 |
|
|
|
| 初始密码 | 文本输入 | 是 | 系统生成 | 自动生成 | 可修改 |
|
|
|
| 绑定物业公司 | 下拉单选 | 是 | — | 物业公司信息列表 | — |
|
|
|
| 服务医院 | 下拉单选 | 是 | — | 医院信息列表 | — |
|
|
|
| 有效期至 | 日期选择 | 是 | — | 自填 | 不早于当前日期 |
|
|
|
| 分配角色 | 下拉多选 | 是 | — | 角色管理-物业适用角色 | 至少选一个 |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 新增 | /api/v1/accounts/property-admin | POST | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 并行加载:绑定物业公司下拉 + 服务医院下拉 + 角色下拉(物业适用范围)
|
|
|
- 自动生成初始密码,有效期默认当前日期+1年
|
|
|
|
|
|
2. **表单填写与提交流程**
|
|
|
- 填写登录账号 → 失焦时校验唯一性
|
|
|
- 选择物业公司 → 选择服务医院 → 选择有效期 → 分配角色 → 点击"保存"→ 校验 → API → 成功返回列表页
|
|
|
|
|
|
3. **联动交互**
|
|
|
- 绑定物业公司下拉:来源于物业公司信息管理中启用状态的公司
|
|
|
- 选择物业公司后,服务医院下拉联动过滤该物业关联的医院
|
|
|
- 分配角色下拉:仅显示"适用范围=物业管理员"的启用角色
|
|
|
|
|
|
4. **异常处理**
|
|
|
- 登录账号重复 → 失焦时即时提示
|
|
|
- API失败 → 提示错误,表单不丢失
|
|
|
|
|
|
5. **权限控制交互**
|
|
|
- 无保存权限时 → "保存"按钮禁用
|
|
|
|
|
|
6. **[H1]防重复请求**
|
|
|
- 点击"保存"按钮后:按钮 :loading=true + 文案变为"保存中..." + 按钮disabled;API返回(成功/失败/超时)后恢复
|
|
|
- 保存期间不允许再次点击保存或关闭页面
|
|
|
|
|
|
7. **[H2]超时与加载反馈**
|
|
|
- 新增提交API(POST):timeout=30秒
|
|
|
- 提交中保存按钮保持:loading态 + 表单区域不可编辑(半透明遮罩可选)
|
|
|
- 超时处理:中断请求 → 提示"保存超时,请检查网络后重试" → 按钮恢复
|
|
|
|
|
|
8. **[H4]脏数据检测**
|
|
|
- 页面进入时deep clone表单初始数据作为快照
|
|
|
- 用户修改任意字段后标记isDirty=true
|
|
|
- 点击"取消"按钮或浏览器后退时:
|
|
|
* isDirty=true → ElMessageBox.confirm("当前修改尚未保存,离开后将丢失未保存的内容,是否确认离开?") → 确认则离开/取消则停留
|
|
|
* isDirty=false → 直接执行离开操作
|
|
|
- 使用vue-router的beforeRouteLeave导航守卫拦截路由切换
|
|
|
- 保存成功后将当前数据设为新快照,重置isDirty=false
|
|
|
|
|
|
9. **[H8]操作结果反馈**
|
|
|
- 保存成功:ElMessage.success("保存成功", duration=2000) → 延迟300ms后router.back()返回列表页
|
|
|
- 保存失败:ElMessage.error(错误信息, duration=0);表单数据保持不丢失
|
|
|
- 唯一性校验失败:对应字段下方红色文字提示,不弹message
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 表单 | el-form | label-width="120px", :model, :rules |
|
|
|
| 登录账号 | el-input | maxlength=20, clearable |
|
|
|
| 初始密码 | el-input | maxlength=20, show-password |
|
|
|
| 绑定物业公司 | el-select | filterable, clearable |
|
|
|
| 服务医院 | el-select | filterable, clearable |
|
|
|
| 有效期至 | el-date-picker | type="date", :disabled-date, value-format="YYYY-MM-DD" |
|
|
|
| 分配角色 | el-select | multiple, filterable, collapse-tags |
|
|
|
| 保存按钮 | el-button | type="primary", :loading |
|
|
|
| 刷新密码按钮 | el-button | icon="Refresh", circle |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 登录账号 | 必填, 4-20位字母数字, 全局唯一 | "请输入登录账号" / "登录账号为4-20位字母数字" / "该登录账号已存在" |
|
|
|
| 初始密码 | 必填, 6-20位 | "请输入初始密码" / "密码长度6-20位" |
|
|
|
| 绑定物业公司 | 必填 | "请选择绑定物业公司" |
|
|
|
| 服务医院 | 必填 | "请选择服务医院" |
|
|
|
| 有效期至 | 必填, 不早于当前日期 | "请选择有效期" / "有效期不能早于当前日期" |
|
|
|
| 分配角色 | 必填, 至少选一个 | "请选择至少一个角色" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 表单两列排列 |
|
|
|
| 1024-1279px(Pad横屏) | 表单两列排列 |
|
|
|
| 768-1023px(Pad竖屏) | 表单单列排列 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面9:到期账号管理页
|
|
|
|
|
|
**页面编号**:SA-A-07-P01
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/expiring
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 到期账号管理 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [统计卡片区] │
|
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
|
│ │已过期 │ │7天内到期 │ │30天内到期 │ │
|
|
|
│ │ 3 │ │ 5 │ │ 12 │ │
|
|
|
│ └──────────┘ └──────────┘ └──────────┘ │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [查询条件区] │
|
|
|
│ 账号类型[▼] 到期状态[▼] [查询] [重置] │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [列表区] │
|
|
|
│ 序号 | 登录账号 | 账号类型 | 绑定单位 | 有效期至 | 剩余天数 | 操作 │
|
|
|
│ 1 | hospital01| 医院 | XX医院 | 2026-04-20| 4天 | 续期 │
|
|
|
│ 2 | prop01 | 物业 | XX物业 | 2026-03-01| -46天 | 续期 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [分页] 共20条 每页[20▼] < 1 > │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 查询条件
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 说明 |
|
|
|
|--------|----------|------|--------|------|
|
|
|
| 账号类型 | 下拉单选 | 否 | 全部 | 医院/物业管理员 |
|
|
|
| 到期状态 | 下拉单选 | 否 | 全部 | 已过期/7天内到期/30天内到期 |
|
|
|
|
|
|
### 列表字段
|
|
|
|
|
|
| 序号 | 字段名 | 列宽 | 支持排序 | 说明 |
|
|
|
|------|--------|------|----------|------|
|
|
|
| 1 | 序号 | 60px | — | 自增 |
|
|
|
| 2 | 登录账号 | 130px | 否 | — |
|
|
|
| 3 | 账号类型 | 100px | 否 | 医院/物业管理员 |
|
|
|
| 4 | 绑定单位 | 150px | 否 | 医院名称或物业公司名称 |
|
|
|
| 5 | 有效期至 | 120px | 是 | — |
|
|
|
| 6 | 剩余天数 | 90px | 是 | 已过期显示负数,红色标记 |
|
|
|
| 7 | 操作 | 100px | — | 续期 |
|
|
|
|
|
|
### 操作按钮
|
|
|
|
|
|
| 按钮 | 权限编码 | 位置 | 显示条件 | 说明 |
|
|
|
|------|----------|------|----------|------|
|
|
|
| 续期 | permission:user:update | 行操作 | 始终 | 弹窗修改有效期 |
|
|
|
|
|
|
### 通知触发
|
|
|
|
|
|
| 触发操作 | 通知对象 | 通知方式 | 消息模板 | 文档来源 |
|
|
|
|----------|----------|----------|----------|----------|
|
|
|
| 续期成功 | 被续期账号 | — | 账号恢复可用,记录操作日志 | 03-超级管理员 §3 |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 列表查询 | /api/v1/accounts/expiring | GET | 筛选到期账号 |
|
|
|
| 续期 | /api/v1/accounts/{id}/renew | PUT | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 并行调用:统计卡片数据 + 列表数据 + 下拉选项
|
|
|
- 统计卡片数据优先渲染,列表加载中显示骨架屏
|
|
|
- 点击统计卡片可快速筛选(点击"已过期"卡片 → 自动填充到期状态=已过期 → 触发查询)
|
|
|
|
|
|
2. **查询交互流程**
|
|
|
- 填写条件 → 点击"查询"→ 调用API → 重置到第1页
|
|
|
- 统计卡片数据随查询条件联动刷新
|
|
|
|
|
|
3. **行内操作流程**
|
|
|
- **续期**:点击"续期"→ 弹出续期弹窗(选择新有效期)→ 确认 → API调用 → 成功提示"续期成功"→ 刷新列表和统计卡片
|
|
|
|
|
|
4. **联动交互**
|
|
|
- 统计卡片点击 → 联动查询条件 → 触发筛选
|
|
|
|
|
|
5. **异常处理**
|
|
|
- 续期失败 → 提示错误信息
|
|
|
- 统计数据加载失败 → 卡片显示"--"占位,不影响列表操作
|
|
|
|
|
|
6. **权限控制交互**
|
|
|
- 无 `permission:user:update` → 行"续期"按钮不渲染
|
|
|
|
|
|
7. **[H1]防重复请求**
|
|
|
- 查询/筛选:点击"查询"按钮后立即 disabled=true + 显示loading态,API返回后恢复;查询期间再次点击无效
|
|
|
- 行内操作(续期):点击操作按钮后该行所有操作按钮禁用 + 按钮显示loading旋转图标;操作完成后恢复
|
|
|
- 分页切换:切换页码时取消上一页未完成请求(abortController)后再发起新请求
|
|
|
- 页面初始化并行请求(统计卡片+列表+下拉数据)之间互不阻塞
|
|
|
|
|
|
8. **[H2]超时与加载反馈**
|
|
|
- 列表查询API:timeout=15秒;加载中表格区显示v-loading骨架屏遮罩
|
|
|
- 续期写操作API:timeout=30秒;操作按钮:loading态
|
|
|
- 统计卡片数据加载API:timeout=15秒
|
|
|
- 超时处理:自动中断 → ElMessage.error("请求超时,请检查网络后重试") → 按钮恢复可用
|
|
|
- 列表加载超过2秒时显示全局ElLoading进度提示
|
|
|
|
|
|
9. **[H3]操作确认机制**
|
|
|
- 续期弹窗本身即为操作确认机制:选择新有效期后需用户点击"确定"才提交
|
|
|
- 确认弹窗期间底层页面不可点击(modal遮罩)
|
|
|
|
|
|
10. **[H8]操作结果反馈**
|
|
|
- 成功操作:ElMessage.success("{操作}成功",duration=2000ms) → silent方式刷新列表数据和统计卡片(不带loading闪烁)
|
|
|
- 失败:ElMessage.error(后端message或"操作失败,请稍后重试",duration=0手动关闭)
|
|
|
- 网络异常:提示"网络连接异常,请检查网络后重试"+ 提供"重试"文字按钮
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 统计卡片 | el-card | shadow="hover", :body-style="{padding:'20px',cursor:'pointer'}" |
|
|
|
| 卡片数字 | div | font-size=28px, font-weight=bold |
|
|
|
| 已过期数字 | — | color=var(--el-color-danger) |
|
|
|
| 7天内到期数字 | — | color=var(--el-color-warning) |
|
|
|
| 30天内到期数字 | — | color=var(--el-color-primary) |
|
|
|
| 剩余天数 | el-tag | 已过期:type="danger", ≤7天:type="warning", 其他:type="info" |
|
|
|
| 续期弹窗 | el-dialog | width="400px", :close-on-click-modal=false |
|
|
|
| 续期日期选择 | el-date-picker | type="date", :disabled-date |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 续期日期 | 必填, 不早于当前日期 | "请选择有效期" / "有效期不能早于当前日期" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 统计卡片一行三个;列表完整展示所有列 |
|
|
|
| 1024-1279px(Pad横屏) | 统计卡片一行三个;"账号类型"列隐藏 |
|
|
|
| 768-1023px(Pad竖屏) | 统计卡片一行三个(缩小间距);列表仅显示:序号、登录账号、绑定单位、剩余天数、操作 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 页面10:到期提醒规则配置页
|
|
|
|
|
|
**页面编号**:SA-A-08-P01
|
|
|
**端侧归属**:Web专属
|
|
|
**页面路径**:/account/expiry-settings
|
|
|
|
|
|
### 界面布局
|
|
|
|
|
|
```
|
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
|
│ [面包屑] 账号管理 > 到期提醒规则配置 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ ── 提醒天数配置 ──────────────────────────────────────────── │
|
|
|
│ 提前提醒天数:[7] [15] [30] 天 (可多选,点击添加/移除) │
|
|
|
│ │
|
|
|
│ ── 提醒方式 ────────────────────────────────────────────── │
|
|
|
│ ☑ 用户登录时弹窗提醒 │
|
|
|
│ ☐ 邮件提醒(暂未开放) │
|
|
|
│ │
|
|
|
│ ── 提醒行为 ────────────────────────────────────────────── │
|
|
|
│ 提醒弹窗关闭后:☑ 可正常使用 ☐ 限制部分功能 │
|
|
|
│ 账号过期后: ☑ 禁止登录 ☐ 仅提醒 │
|
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
|
│ [取消] [保存] │
|
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 表单字段
|
|
|
|
|
|
| 字段名 | 控件类型 | 必填 | 默认值 | 数据来源 | 校验规则 |
|
|
|
|--------|----------|------|--------|----------|----------|
|
|
|
| 提前提醒天数 | 标签多选 | 是 | 7, 15, 30 | — | 至少选一个 |
|
|
|
| 用户登录弹窗 | 开关 | 是 | 开 | — | — |
|
|
|
| 弹窗关闭后行为 | 单选 | 是 | 可正常使用 | 固定选项 | — |
|
|
|
| 过期后行为 | 单选 | 是 | 禁止登录 | 固定选项 | — |
|
|
|
|
|
|
### API端点
|
|
|
|
|
|
| 页面操作 | API路径 | 方法 | 说明 |
|
|
|
|----------|---------|------|------|
|
|
|
| 查询配置 | /api/v1/system/configs/expiry-reminder | GET | — |
|
|
|
| 保存配置 | /api/v1/system/configs/expiry-reminder | PUT | — |
|
|
|
|
|
|
### 交互流程要求
|
|
|
|
|
|
1. **页面加载流程**
|
|
|
- 进入页面 → 调用 `GET /api/v1/system/configs/expiry-reminder` 加载当前配置 → 回填表单
|
|
|
- 加载中表单显示骨架屏
|
|
|
|
|
|
2. **表单填写与提交流程**
|
|
|
- 修改配置项 → 点击"保存"→ 前端校验(至少选一个提醒天数)→ 调用 `PUT` API → 成功提示"配置保存成功"
|
|
|
- 无需返回列表页,停留在当前页
|
|
|
|
|
|
3. **标签多选交互**
|
|
|
- "提前提醒天数"使用标签多选(预设7/15/30/60/90天选项),点击标签切换选中/取消
|
|
|
- 支持自定义天数输入(输入框+添加按钮)
|
|
|
- 至少保留一个选中项
|
|
|
|
|
|
4. **联动交互**
|
|
|
- "用户登录弹窗"关闭时 → "弹窗关闭后行为"选项才可编辑
|
|
|
- "过期后行为"选择"限制部分功能"时 → 显示附加配置(限制哪些功能)
|
|
|
|
|
|
5. **异常处理**
|
|
|
- 保存失败 → 提示错误信息,表单数据不丢失
|
|
|
- 配置加载失败 → 提示"配置加载失败",提供"重试"按钮
|
|
|
|
|
|
6. **权限控制交互**
|
|
|
- 无 `permission:config:update` → 表单所有控件禁用,"保存"按钮不渲染
|
|
|
|
|
|
7. **[H1]防重复请求**
|
|
|
- 点击"保存"按钮后:按钮 :loading=true + 文案变为"保存中..." + 按钮disabled;API返回(成功/失败/超时)后恢复
|
|
|
- 保存期间不允许再次点击保存或关闭页面
|
|
|
|
|
|
8. **[H2]超时与加载反馈**
|
|
|
- 保存配置提交API(PUT):timeout=30秒
|
|
|
- 查询配置回填API(GET):timeout=15秒
|
|
|
- 提交中保存按钮保持:loading态 + 表单区域不可编辑(半透明遮罩可选)
|
|
|
- 超时处理:中断请求 → 提示"保存超时,请检查网络后重试" → 按钮恢复
|
|
|
|
|
|
9. **[H4]脏数据检测**
|
|
|
- 页面进入时deep clone表单初始数据作为快照
|
|
|
- 用户修改任意字段后标记isDirty=true
|
|
|
- 点击"取消"按钮或浏览器后退时:
|
|
|
* isDirty=true → ElMessageBox.confirm("当前修改尚未保存,离开后将丢失未保存的内容,是否确认离开?") → 确认则离开/取消则停留
|
|
|
* isDirty=false → 直接执行离开操作
|
|
|
- 使用vue-router的beforeRouteLeave导航守卫拦截路由切换
|
|
|
- 保存成功后将当前数据设为新快照,重置isDirty=false
|
|
|
|
|
|
10. **[H8]操作结果反馈**
|
|
|
- 保存成功:ElMessage.success("配置保存成功", duration=2000);停留在当前页不跳转
|
|
|
- 保存失败:ElMessage.error(错误信息, duration=0);表单数据保持不丢失
|
|
|
- 唯一性校验失败:对应字段下方红色文字提示,不弹message(本页面无唯一性字段)
|
|
|
|
|
|
### 组件规范
|
|
|
|
|
|
| 元素 | 组件 | 配置参数 |
|
|
|
|------|------|----------|
|
|
|
| 表单 | el-form | label-width="140px", :model, :rules |
|
|
|
| 提前提醒天数 | el-check-tag | 多选模式,预设7/15/30/60/90 |
|
|
|
| 自定义天数输入 | el-input-number | :min=1, :max=365, :step=1 |
|
|
|
| 用户登录弹窗 | el-switch | active-text="开启", inactive-text="关闭" |
|
|
|
| 弹窗关闭后行为 | el-radio-group | el-radio label="可正常使用"/"限制部分功能" |
|
|
|
| 过期后行为 | el-radio-group | el-radio label="禁止登录"/"仅提醒" |
|
|
|
| 保存按钮 | el-button | type="primary", :loading |
|
|
|
| 取消按钮 | el-button | @click="resetForm" |
|
|
|
|
|
|
### 校验规则
|
|
|
|
|
|
| 字段 | 规则 | 错误提示 |
|
|
|
|------|------|----------|
|
|
|
| 提前提醒天数 | 必填, 至少选一个 | "请至少选择一个提醒天数" |
|
|
|
| 自定义天数 | 1-365整数 | "天数范围1-365" |
|
|
|
|
|
|
### 响应式布局
|
|
|
|
|
|
| 断点 | 布局调整 |
|
|
|
|------|----------|
|
|
|
| ≥1280px(桌面端) | 表单标签宽度140px,输入区域宽度400px |
|
|
|
| 1024-1279px(Pad横屏) | 表单标签宽度120px,输入区域宽度350px |
|
|
|
| 768-1023px(Pad竖屏) | 表单标签宽度100px,输入区域宽度100% |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 需求追溯
|
|
|
|
|
|
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|
|
|
|------------|----------|----------|----------|----------|
|
|
|
| SA-A-01 | 医院信息管理 | 02-超级管理员 §1 / 03-超级管理员 §1 | 创建医院→创建医院账号 | 医院账号管理(绑定医院) |
|
|
|
| SA-A-02 | 物业公司信息管理 | 02-超级管理员 §1 / 03-超级管理员 §1 | 创建物业公司→创建物业账号 | 物业管理员账号管理(绑定物业) |
|
|
|
| SA-A-03 | 医院账号管理 | 02-超级管理员 §1 / 03-超级管理员 §1~2 | 账号创建→权限分配 | 权限管理(角色绑定) |
|
|
|
| SA-A-04 | 物业管理员账号管理 | 02-超级管理员 §1 / 03-超级管理员 §1~2 | 账号创建→权限分配,禁用→下属同步失效 | 权限管理(角色绑定) / 物业组织架构(下属账号) |
|
|
|
| SA-A-05 | 账号有效期设置 | 02-超级管理员 §1 / 03-超级管理员 §3 / 01 §1.4 | 创建时设置有效期 | 到期账号管理 / 到期提醒规则 |
|
|
|
| SA-A-06 | 账号可用性控制 | 02-超级管理员 §1 / 03-超级管理员 §2 | 禁用→session立即失效+小程序下线 | 操作日志(记录启停操作) |
|
|
|
| SA-A-07 | 到期账号管理 | 02-超级管理员 §1 / 03-超级管理员 §3 / 01 §1.4 | 手动续期→账号恢复 | 到期提醒规则配置 |
|
|
|
| SA-A-08 | 到期提醒规则配置 | 02-超级管理员 §1 / 03-超级管理员 §3 / 01 §1.4 | 配置→系统按规则自动提醒 | 到期账号管理 / 系统配置 |
|
|
|
|
|
|
## 业务规则
|
|
|
|
|
|
1. **新建使用单位流程**:医院信息→物业公司信息→医院账号→物业管理员账号,四步顺序创建(来源:03-超级管理员 §1)
|
|
|
2. **账号有效期必填**:创建医院/物业管理员账号时必须设置有效期(来源:01 §1.4)
|
|
|
3. **物业下属不单独设有效期**:下属人员随物业公司管理员账号到期而自动失效(来源:01 §1.4 / 03-超级管理员 §3)
|
|
|
4. **禁用立即生效**:禁用账号后session立即失效,小程序同步下线(来源:03-超级管理员 §2)
|
|
|
5. **到期提醒弹窗**:到期前N天登录时弹窗提醒,关闭后可正常使用(来源:01 §1.4 / 03-超级管理员 §3)
|
|
|
6. **过期禁止登录**:账号过期后禁止登录,需超管手动续期(来源:01 §1.4 / 03-超级管理员 §3)
|
|
|
7. **超管不涉及业务数据**:超级管理员仅管理系统配置与账号数据,不查看任何业务数据(来源:01 §1.3 / 03-超级管理员 §7)
|
|
|
8. **所有操作记录日志**:账号创建/启停/续期等操作自动记录操作日志(来源:06-项目技术要求 §4.5)
|