# 会议核销SaaS系统 - 系统增强需求规格说明 (PRD v2)
基于对现有系统的全面审计,本文件将系统增强需求拆分为两大阶段:**阶段零(基础能力补齐)** 和 **阶段一~三(进阶功能建设)**。阶段零为前置必做项,需在任何进阶功能启动前完成。
---
## 📅 一、全局优先级与阶段落地排期
```
【P-1】紧急修复:现有代码 Bug 与隐患 ─── 立即
│
【P0】阶段零:基础能力补齐(本轮新增) ─── 第一优先
│ ├─ Z1. CRUD 完整性与软删除
│ ├─ Z2. 服务端分页改造
│ ├─ Z3. 前端基础设施
│ ├─ Z4. 安全合规基线
│ ├─ Z5. 后端基础设施
│ ├─ Z6. 业务流程闭环
│ ├─ Z7. 数据导出补全
│ └─ Z8. 数据字典增强
│
【P1】阶段一:业务提效与刚需补齐 ─── 第二优先
│ └─ 批量数据导入中心
│
【P2】阶段二:跨域联调与工作流升级 ─── 第三优先
│ ├─ 多租户快捷切换
│ └─ 外部通信网关配置
│
【P3】阶段三:深水区体验优化 ─── 末位
└─ 全局搜索与视觉高阶设置
```
---
## 🔒 二、权限基线与菜单设定原则
> **⚠️ 核心开发约定:在以下所有模块的实际开发落地过程中,凡涉及到新增模块的权限控制和新建菜单页面时,必须及时同步在后端的数据库初始化同步脚本、常量中心以及前端的动态路由表中增加相应的【路由节点】、【功能菜单数据】和具体的【权限控制标识(Permission Code)】。一定要保证最终交付时,该模块的所有控制权限都能出现在实施界面的权限分配列表中供客户勾选。**
*(注:以下仅初步约定开发所需的**菜单边界**与部分具有代表性的**接口权限标识(Permission Code)**,颗粒度应控制到动作级。具体的角色组合与绑定动作将由实施阶段人员手动界面操作配置完成。)*
### 阶段零 权限映射
| 功能模块 | 页面/触发入口 | 控制点 / 权限标识 | 说明 |
| :--- | :--- | :--- | :--- |
| **软删除操作** | 各实体列表操作列 | 复用各实体现有 `manage` 级权限 | 软删除视为"管理"动作的子集 |
| **租户编辑** | 租户管理列表 | `tenant.manage` / `platform.tenant.manage` | 已有权限复用 |
| **会议删除/取消** | 会议列表操作列 | 新增 `meeting.delete`、`meeting.cancel` | 仅草稿可删除,仅未提交可取消 |
| **项目归档/解冻** | 项目列表操作列 | 新增 `project.archive`、`project.unfreeze` | 归档为终态,解冻恢复为进行中 |
| **批量审核** | 审核列表顶部 | 复用 `audit.approve` / `audit.reject` | 批量操作复用单条权限 |
| **租户级字典** | `系统管理 > 字典管理` | 新增 `dictionary.read`、`dictionary.manage` | 租户管理员可维护本租户字典 |
### 进阶模块 权限映射
| 功能模块 | 页面/触发入口 (Menu View) | 控制点 / 权限标识 (Permission Code) | 受众说明与隔离性质 |
| :--- | :--- | :--- | :--- |
| **数据导入中心** | 无独立菜单,依附于各业务线操作区 | 常规导入动作:`common:import`
特定限制类如:`expert:import` | 开放给业务操作员,需避免脏数据批量注入与覆盖误操作。 |
| **多租户快捷切换** | 全局顶部导航栏账号下拉区域 | `tenant:switch` | 对下发到该手机号所有内含角色的用户账套默认开放。 |
| **外部通信网关** | `系统管理 > 消息中心 > 网关配置` | 查阅参数:`sys:notify:gateway:view`
修改秘钥:`sys:notify:gateway:config` | **仅限最高级系统级超管打开**,防泄露及被黑产利用。 |
| **全局快速搜索** | 悬浮遮罩面板 (唤醒键:`Cmd+K/Ctrl+K`) | 继承触发系统的固有读取控制阀门,无需独立 Code 分发。 | 全员开放。**核心规则**:搜索结果强制附加当前用户级别数据防越权拦截。 |
---
## 三、【P-1 紧急】现有代码 Bug 与隐患修复
> ⚠️ 以下问题需在任何新功能开发前优先修复。
### BUG-1:权限常量缺失导致工作台卡片不显示 ✅ 已修复
- **现象**:`TenantDashboardPage.vue` 第 120 行引用 `PERMS.meeting.manage`,但 `permissions.ts` 中 `meeting` 对象不存在 `manage` 属性。
- **影响**:`hasPermission()` 返回值始终 `false`,"活跃会议"卡片永远不显示。
- **修复**:在 `permissions.ts` 的 `meeting` 对象中新增 `manage: "meeting.manage"` 属性,并在后端权限初始化脚本中同步新增该权限码。
- **✅ 状态**:`permissions.ts` 中 `meeting.manage` 已存在(第12行)。
### BUG-2:平台管理员路由守卫异常重定向 ✅ 已修复
- **现象**:路由守卫中当 `authScope === 'PLATFORM'` 且访问 `/audit-logs` 时,被重定向到 `/projects`。
- **影响**:平台管理员无 `/projects` 页面权限,最终访问空白页。
- **修复**:将平台管理员的 fallback 路由改为 `/platform/tenants`。
- **✅ 状态**:路由守卫(index.ts:116)平台用户 fallback 已改为 `/platform/tenants`。
### BUG-3:AppLayout 中 authScope 非响应式 ⚠️ 部分修复
- **现象**:`authScope` 是 `getAuthScope()` 的一次性赋值,Token 刷新改变 scope 后 UI 不同步。
- **修复**:改为使用 `computed` 包裹或监听 `auth:token-updated` 事件后重取。
- **⚠️ 状态**:`AppLayout.vue:266` 使用 `ref(getAuthScope())` 非 computed,但在路由守卫钩子中有手动更新 `authScope.value`(L501)。非理想方案,但功能可用。
### BUG-4:HTTP 全局超时过短 ✅ 已修复
- **现象**:`http.ts` 中 `timeout: 10000`(10 秒),文件上传和大数据导出容易误触发超时。
- **修复**:将默认超时提升至 30 秒;对文件上传类接口单独设置超时或不限超时。
- **✅ 状态**:`http.ts:7` 已改为 `timeout: 30000`。
### BUG-5:工作台卡片未接入真实数据 ✅ 已修复
- **现象**:工作台"活跃会议"和"待财务确认"卡片的值固定显示 `--`。
- **修复**:新增或复用后端接口返回工作台统计数据,并在 `TenantDashboardPage` 中渲染。
- **✅ 状态**:后端 `TenantDashboardController` 提供 `/api/dashboard/stats` 接口;前端 `TenantDashboardPage` 调用 `fetchDashboardStats()` 渲染真实数据。
---
## 四、【P0 阶段零】基础能力补齐
### Z1. CRUD 完整性与软删除
#### 1.1 软删除统一规范 ✅ 已完成
所有核心业务实体启用软删除机制:
- **数据库层**:所有主表已具备 `is_deleted tinyint(1) DEFAULT 0` 字段(技术文档 §6.9 已定义)。未添加的表需补建此列。
- **后端层**:删除接口改为 `POST /api/{entity}/{id}/delete`,将 `is_deleted` 置为 `1`。所有查询默认附加 `is_deleted = 0` 过滤条件。
- **前端层**:删除操作统一使用 `ElMessageBox.confirm` 二次确认弹窗,提示"删除后数据将不可恢复(从列表移除),是否继续?"。
- **审计留痕**:所有软删除操作必须记录审计日志。
- **✅ 状态**:后端各服务查询均已附加 `is_deleted=0` 条件,软删除设置 `is_deleted=1`。
#### 1.2 各实体操作完整性补全
| 实体 | 新增操作 | 接口设计 | 约束条件 | 状态 |
|------|----------|----------|----------|------|
| **租户** | 编辑 | `PUT /api/tenants/{id}`
`PUT /api/platform/tenants/{id}` | 编辑不影响已有业务数据 | ✅ `PlatformTenantController.update()` 已实现 |
| **租户** | 软删除 | `POST /api/platform/tenants/{id}/delete` | 仅平台超管可操作;租户下有活跃业务时拒绝删除 | ✅ `PlatformTenantController.softDelete()` + `TenantService.softDelete()` 已实现含业务校验 |
| **用户** | 软删除 | `POST /api/users/{id}/delete` | 禁止删除自己;有进行中审核任务的用户需先转审 | ✅ `UserController.softDelete()` + `SystemUserService.softDeleteUser()` 已实现含审核任务校验 |
| **角色** | 软删除 | `POST /api/roles/{id}/delete` | 有用户绑定的角色需先解绑或迁移 | ✅ `RoleController` 中 `softDelete()` + `SystemUserService.softDeleteRole()` 已实现含用户绑定校验 |
| **企业** | 软删除 | `POST /api/enterprises/{id}/delete` | 有项目引用的企业拒绝删除 | ✅ `EnterpriseController.softDelete()` + `EnterpriseService.softDelete()` 已实现 |
| **会议** | 删除草稿 | `POST /api/meetings/{id}/delete` | **仅 `DRAFT`(草稿)状态可删除**,其余状态走取消流程 | ✅ `MeetingController.deleteDraft()` 已实现 |
| **审核流** | 软删除 | `POST /api/audit-flows/{id}/delete` | 非默认流程且已停用才可删除 | ✅ `AuditFlowController.delete()` + `AuditFlowManageService.softDelete()` 已实现 |
| **通知策略** | 软删除 | `POST /api/notification-policies/{id}/delete` | 已停用才可删除 | ✅ `NotificationPolicyController` delete endpoint + `softDelete()` 已实现 |
| **通知文本模板** | 软删除 | `POST /api/notification-text-templates/{id}/delete` | 无策略引用才可删除 | ✅ `NotificationTextTemplateController` delete endpoint + `softDelete()` 含策略引用校验 已实现 |
| **平台用户** | 编辑 | `PUT /api/platform/users/{id}` | 与租户用户编辑规格一致 | ❌ `PlatformUserController` **缺少 `@PutMapping("/{id}")` 编辑端点** |
#### 1.3 前端操作 UI 规范
- 删除按钮统一使用 `danger` 类型,放置在操作列最右侧。
- 二次确认弹窗使用 `ElMessageBox.confirm`,标题为"确认删除",类型为 `warning`。
- 已软删除的数据在列表中默认不展示,可通过筛选项"包含已删除"查看。
- **⚠️ 状态**:前端各删除按钮已有二次确认弹窗;但"包含已删除"筛选项尚未在各列表中实现。
---
### Z2. 服务端分页改造
#### 2.1 改造范围与规范
以下接口需改造为服务端分页:
| 接口 | 当前方式 | 优先级 | 预估数据量 | 状态 |
|------|----------|--------|-----------|------|
| `GET /api/experts` | 全量返回 | 🔴 最高 | 可达数千条 | ✅ 已改造(含 pageNo/pageSize) |
| `GET /api/users` | 全量返回 | 🔴 高 | 数百至数千 | ✅ 已改造(UserController 接受 pageNo/pageSize) |
| `GET /api/templates` | 全量返回 | 🟡 中 | 数十至数百 | ❌ 未改造 |
| `GET /api/notification-policies` | 全量返回 | 🟢 低 | 通常 <50 | ❌ 未改造(仍全量返回) |
| `GET /api/notification-text-templates` | 全量返回 | 🟢 低 | 通常 <30 | ✅ 已改造(NotificationTextTemplateService 含 LIMIT/OFFSET) |
| `GET /api/roles` | 全量返回 | 🟢 低 | 通常 <20 | ❌ 未改造 |
| `GET /api/enterprises` | 全量返回 | 🟢 低 | 通常 <20 | ❌ 未改造 |
| `GET /api/audit-flows` | 全量返回 | 🟢 低 | 通常 <10 | ❌ 未改造 |
#### 2.2 统一分页协议 ✅ 已定义
**请求参数**:
```
pageNo: number // 页码,从 1 开始
pageSize: number // 每页条数,默认 20,最大 200
sortBy?: string // 排序字段
order?: "asc" | "desc" // 排序方向
```
**响应结构**:
```json
{
"code": 0,
"data": {
"list": [...],
"total": 150,
"pageNo": 1,
"pageSize": 20
}
}
```
#### 2.3 前端改造要点
- 表格底部统一使用 `el-pagination` 组件,支持页码跳转和每页条数选择。
- `pageSize` 提供 `[20, 50, 100]` 选项。
- 页码变化时自动请求下一页数据(debounce 300ms)。
- 搜索/筛选条件变化时自动重置到第 1 页。
- **⚠️ 状态**:已改造的接口(experts/users/notification-text-templates)前端已配套 el-pagination;未改造的接口前端仍为全量加载。
---
### Z3. 前端基础设施
#### 3.1 404 未匹配路由页面 ✅ 已完成
- 新增 `NotFoundPage.vue`,包含清晰的"页面不存在"提示和"返回首页"按钮。
- 路由表末尾添加 `{ path: '/:pathMatch(.*)*', component: NotFoundPage }`。
- 分别处理租户用户和平台管理员的首页跳转路径。
- **✅ 状态**:`NotFoundPage.vue` 已实现(含404样式、goHome按区分PLATFORM/TENANT、goBack),路由 `/:pathMatch(.*)*` 已注册。
#### 3.2 全局错误边界 ✅ 已完成
- 在 `main.ts` 中配置 `app.config.errorHandler`,捕获未处理的组件异常。
- 错误发生时展示友好提示并提供"刷新页面"操作,替代白屏。
- 生产环境下隐藏详细错误堆栈。
- **✅ 状态**:`main.ts:14` 已配置 `app.config.errorHandler`,显示 ElMessage.error + console.error。
#### 3.3 视口与基础 UI ✅ 已完成
- 设置 `` 的 `min-width: 1200px`,防止后台系统在窄屏下布局崩溃。
- 配置系统 Favicon(使用系统品牌图标)。
- `
` 标签设置为"会议核销系统",路由切换时动态更新页面标题。
- **✅ 状态**:`index.html` 中 `min-width: 1200px`、SVG favicon、`会议核销系统` 均已配置。
- **⚠️ 遗留**:路由切换时动态更新 `document.title` 尚未实现(缺少 `router.afterEach` title 更新逻辑)。
#### 3.4 面包屑导航 ❌ 未完成
- 在 Sidebar 布局模式(菜单项 >5)的 `sidebar-header` 区域添加面包屑。
- 基于路由元信息 (`meta.title`) 自动生成层级路径。
- **❌ 状态**:前端无面包屑组件,路由也没有设置 `meta.title`。
---
### Z4. 安全合规基线
#### 4.1 登录失败锁定策略 ⚠️ 已实现(存储介质差异)
| 规则 | 参数 | 说明 |
|------|------|------|
| 连续失败阈值 | 5 次 | 同一账号连续登录失败超过此次数触发锁定 |
| 锁定时长 | 15 分钟 | 锁定期间拒绝该账号任何登录请求 |
| 计数窗口 | 30 分钟 | 超过窗口期自动清零失败次数 |
| 存储介质 | Redis | `Key: login:fail:{phone}`, TTL = 30min |
**后端实现**:
- 拦截登录接口,每次失败递增 Redis 计数器。
- 达到阈值时设置锁定标记 `Key: login:lock:{phone}`, TTL = 15min。
- 成功登录后清除失败计数。
- **⚠️ 状态**:`LoginAttemptService.java` 已实现 5次阈值/15分钟锁定逻辑,但使用 **内存 ConcurrentHashMap** 而非 Redis,多实例部署时失效。
**前端展示**:
- 登录失败时明确提示"您还有 N 次尝试机会"。
- 锁定时提示"账号已锁定,请 N 分钟后重试"。
- **❌ 状态**:前端登录页**未实现**剩余尝试次数提示和锁定倒计时提示。
#### 4.2 密码强度策略 ⚠️ 后端已实现,前端未完成
增强密码校验规则(前后端双重校验):
| 规则 | 要求 |
|------|------|
| 最小长度 | 8 位(从 6 位升级) |
| 字符类型 | 至少包含大写字母、小写字母、数字中的 2 种 |
| 禁用规则 | 不能与手机号相同;不能为纯重复字符 |
前端使用 `el-form` 自定义校验器实时反馈密码强度,区分"弱/中/强"并以颜色条可视化。
- **⚠️ 状态**:`PasswordPolicyService.java` 后端已实现(≥8位 + 大写 + 小写 + 数字 + 特殊字符,比PRD更严格)。但 **前端密码强度可视化指示条未实现**,也未做与手机号相同/纯重复字符前端校验。
#### 4.3 验证码 ❌ 未完成
- **首阶段**:后端生成基础图形验证码(4 位数字/字母混合),前端 `
` 展示,登录表单增加验证码字段。
- **后续可选**:升级为滑块验证或行为验证。
- **❌ 状态**:后端无验证码生成逻辑,前端登录表单无验证码字段。
#### 4.4 接口限流 ⚠️ 已实现(实现方式差异)
- 全局级:每 IP 每分钟不超过 300 次请求。
- 登录接口:每 IP 每分钟不超过 20 次。
- 实现方式:基于 Redis 的滑动窗口计数器。
- 超限返回错误码 `10005` 和 HTTP 429。
- **⚠️ 状态**:`RateLimitFilter.java` 已实现(全局60次/秒、登录10次/秒、返回HTTP 429),但使用 **内存 ConcurrentHashMap** 而非 Redis,返回码为 `42900` 非 `10005`。
---
### Z5. 后端基础设施
#### 5.1 requestId 全链路追踪 ⚠️ 后端已完成,前端部分缺失
- **请求入口**:在 `WebConfig` 或 Filter 层为每个请求生成 UUID (`X-Request-Id`),写入 MDC。
- **响应输出**:统一响应体增加 `requestId` 字段。
- **日志关联**:logback pattern 中添加 `%X{requestId}`,实现日志串联。
- **前端对接**:HTTP 拦截器中从响应头或响应体解析 `requestId`,在错误提示中附带展示,便于用户反馈排障。
- **✅ 状态**:后端 `AuthInterceptor` 生成 `X-Request-Id` 并写入响应头;`ApiResponse`/`ApiErrorResponse` 均包含 `requestId` 字段;`RequestIdContext` ThreadLocal 已实现。
- **❌ 遗留**:logback pattern 未找到 `%X{requestId}` 配置;前端 `http.ts` 拦截器未解析并展示 `requestId`。
#### 5.2 健康检查端点 ⚠️ 基础实现
- 新增 `GET /api/health`(免鉴权),返回:
- 应用状态:`UP/DOWN`
- 数据库连通性
- Redis 连通性
- 版本号 / 构建时间
- 用于部署平台的存活探针和就绪探针。
- **⚠️ 状态**:`SystemController` 提供 `GET /api/system/health` 返回 `{"status":"UP"}`,已免鉴权。但**缺少数据库/Redis 连通性检测、版本号/构建时间**。
#### 5.3 接口文档自动生成 ✅ 已完成
- 集成 SpringDoc (OpenAPI 3.0),自动生成接口文档。
- 开发环境通过 `/swagger-ui.html` 可视化浏览。
- 生产环境关闭 Swagger UI。
- **✅ 状态**:`pom.xml` 已引入 `springdoc-openapi-ui`,部分 DTO 已使用 `@Schema` 注解。
---
### Z6. 业务流程闭环
#### 6.1 会议取消 ✅ 已完成
- **状态流转**:`DRAFT → CANCELLED`、`NOT_STARTED → CANCELLED`
- **接口**:`POST /api/meetings/{id}/cancel`,请求体包含 `{ reason: string }`。
- **约束**:已提交审核的会议不可直接取消,需先撤回再取消。
- **联动**:取消后释放项目预算额度。
- **✅ 状态**:`MeetingController.cancel()` 已实现。
#### 6.2 项目归档 ✅ 已完成
- **状态流转**:`COMPLETED → ARCHIVED`
- **接口**:`POST /api/projects/{id}/archive`
- **约束**:项目下所有会议必须为终态(已完成/已取消/已冻结)才可归档。
- **效果**:归档后项目及其下会议变为只读,不可再创建新会议。
- **✅ 状态**:`ProjectController.archive()` 已实现。
#### 6.3 项目解冻 ✅ 已完成
- **状态流转**:`FROZEN → IN_PROGRESS`
- **接口**:`POST /api/projects/{id}/unfreeze`,请求体包含 `{ reason: string }`。
- **约束**:仅冻结状态可解冻,解冻后恢复为"进行中"。
- **审计**:冻结/解冻操作成对记录,审计日志中包含原因。
- **✅ 状态**:`ProjectController.unfreeze()` 已实现。
#### 6.4 批量审核操作 ⚠️ 前端有调用,后端缺端点
- **接口**:
- `POST /api/audits/tasks/batch-approve`:批量通过,请求体 `{ taskIds: number[], opinion: string, idempotencyKey: string }`。
- `POST /api/audits/tasks/batch-reject`:批量拒绝,同上增加 `reason` 字段。
- **前端 UI**:审核列表增加 `el-table` 多选列,选中后顶部工具栏出现"批量通过"/"批量拒绝"按钮。
- **约束**:每批次不超过 50 条;跨会议批量操作需二次确认。
- **⚠️ 状态**:前端 `modules.ts` 已定义 `batch-approve` / `batch-reject` API 调用函数。但后端 `AuditController` **未实现** `batch-approve` 和 `batch-reject` 端点。
#### 6.5 工作台数据联动 ✅ 已完成
完善 `TenantDashboardPage` 的工作台卡片:
| 卡片 | 数据来源 | 接口 | 状态 |
|------|----------|------|------|
| 待我审批的资料 | ✅ 已有 | `fetchAuditTasks({ mine: true })` | ✅ |
| 活跃会议 | 需新增 | `GET /api/dashboard/stats` → `activeMeetingCount` | ✅ |
| 待财务确认账单 | 需新增 | `GET /api/dashboard/stats` → `pendingFinanceCount` | ✅ |
后端在 `DashboardController` 中新增 `/api/dashboard/stats` 聚合接口,一次返回所有工作台指标。
- **✅ 状态**:`TenantDashboardController` 提供 `/api/dashboard/stats`,前端 `TenantDashboardPage` 已对接渲染。
---
### Z7. 数据导出补全 ⚠️ 前端已定义,后端待实现
| 模块 | 导出类型 | 接口 | 优先级 | 状态 |
|------|----------|------|--------|------|
| **会议列表** | Excel | `POST /api/meetings/export` | 🔴 高 | ⚠️ 前端 API 已定义,后端 Controller **无 export 端点** |
| **用户列表** | Excel | `POST /api/users/export` | 🟡 中 | ⚠️ 前端 API 已定义,后端 Controller **无 export 端点** |
| **项目汇总** | Excel | `POST /api/projects/export` | 🟡 中 | ⚠️ 前端 API 已定义,后端 Controller **无 export 端点** |
| **通知发送记录** | Excel | `POST /api/notifications/tasks/export` | 🟢 低 | ❌ 前后端均未实现 |
所有新增导出接口统一走**异步导出任务中心**(`export_task` 表),复用现有 `ExportTaskPage` 查看和下载。
---
### Z8. 数据字典增强
#### 8.1 租户级字典管理 ⚠️ 部分完成
- **页面**:新增 `DictionaryPage.vue`,放置于菜单"系统管理 > 字典管理"。
- **路由**:`/dictionaries`。
- **能力**:
- 查看平台下发的全局字典(只读)。
- 创建和编辑租户私有字典条目。
- 租户字典优先级高于平台字典(同 `dictType` + `dictCode` 时租户覆盖平台)。
- **接口**:
- `GET /api/dictionaries`(已有,需增加分组展示逻辑)
- `POST /api/dictionaries`(新增)
- `PUT /api/dictionaries/{id}`(新增)
- `POST /api/dictionaries/{id}/enable`(新增)
- `POST /api/dictionaries/{id}/disable`(新增)
- **⚠️ 状态**:
- **平台端** `PlatformDictionaryPage.vue` + `PlatformDictionaryController` 已完成(含完整 CRUD)✅
- **租户端** `DictionaryController` 仅提供只读 `GET /api/dictionaries`,**缺少 POST/PUT/enable/disable** 租户私有字典管理端点 ❌
- 前端无租户级 `DictionaryPage.vue`,路由表中无 `/dictionaries` ❌
#### 8.2 状态文案集中化 ⚠️ 部分完成
- 将前端散落的状态映射(`toZhStatus()`、`formatModuleCode()` 等)统一收归到 `constants/statusMap.ts`。
- 长远目标:状态文案由后端字典接口驱动,前端只做缓存和展示。
- **⚠️ 状态**:状态映射函数已集中在 `utils/status.ts`(含 `STATUS_TEXT_MAP`、`MODULE_CODE_MAP` 等),但放置路径为 `utils/` 而非 `constants/statusMap.ts`。未由后端字典驱动。
#### 8.3 动态字典驱动的表单选项 ❌ 未完成
以下表单选项需改为由字典接口驱动:
| 字段 | 当前方式 | 目标 | 状态 |
|------|----------|------|------|
| `meetingCategory`(会议类型) | 前端硬编码 | 字典 `MEETING_CATEGORY` | ❌ 仍为硬编码 |
| `meetingForm`(会议形式) | 前端硬编码 | 字典 `MEETING_FORM` | ❌ 仍为硬编码 |
| 专家职称 | 已有字典接口 | ✅ 保持 | ✅ |
| 专家机构 | 已有字典接口 | ✅ 保持 | ✅ |
---
## 五、【P1 阶段一】批量数据导入中心 (Data Import Center)
**核心价值**:大幅降低运营人员期初数据录入成本,涵盖"专家库"、"用户员工"等高发对象。
### 1. 功能需求点
- **导入模板下载**:按对应模块分别给出官方规范的 Excel 格式模板(需利用第一行提供必要的枚举值要求与必填校验说明)。
- **校验边界与反馈(策略核心)**:
- 系统需同时支持**强弱两级双重校验**:首先是粗放的基础格式校验(长短/手机正则/不为空),其次需执行业务穿透校验(如判断人员的身份证在当前数据库是否存在硬冲突或去重合并)。
- **采用部分成功机制应对海量导入**:针对某一批次数据,合规的正常入库。对于未通过记录行,后端负责组装汇总并导出自带一列详尽"由于某某触发了什么机制而失败原因附注"的新 Excel 异常快照反馈回前端供客户端修改后重新拖入。
- **系统环境并发与防震限制控制**:
- 拦截端阻止连续手滑多传(上传 Loading + 防抖拦截器)。
- 对抗海量文件的架构处理:判断到解析任务单次超过设计阈值(例如定大于 >3000 行),则不再由同步 HTTP 请求阻塞客户端,而是立刻挂起到"后台异步耗时任务队列引擎"里调度。同时切配前台右上角为常驻小窗环形进度提醒。
### 2. 权限映射
| 导入对象 | 权限标识 | 备注 |
|----------|----------|------|
| 专家批量导入 | `expert:import`(已有) | 复用现有权限 |
| 用户批量导入 | `user:import`(新增) | 需在权限初始化脚本中新增 |
| 通用导入 | `common:import`(新增) | 通用导入动作权限 |
---
## 六、【P2 阶段二】跨域联调与工作流升级
### 选项一:多租户快捷切换 (Quick Tenant Switcher)
**核心价值**:解决运营方外包人员在管理维护多个彼此隔离的账套实体之间跳转引发频繁密码质询疲劳,加速串联断层化审核。
#### 1. 功能需求点
- **无感环境安全秒切模型**:顶部常驻挂载当前所有可用合法的环境集合(需通过屏蔽逻辑阻死无权限、或主体遭到禁用的环境)。触发切换时基于当下活跃环境已验证的凭据链重置出针对新特定目的空间专属具备签名的 JWT 请求标识牌,进行多工作域横轴上的"无码穿梭"。
- **端侧安全阻断及环境纯净隔离准则(架构难点)**:
- 发生活跃环境切换指令的那一刹,Web 侧大屏构架**强制触发卸载扫除**,清洗状态树(Pinia/Vuex)全局作用域内存内遗留的上一个环境业务关联(譬如业务流水状态词典、特定公司历史缓存等),继而重新挂载驱动所有全新主体的动态权限菜单列表。
- **制止并发标签页(多 Tab)数据漏串**:设计上需考虑到万一操作员长期拥有并打开了 Tab A、Tab B 等。由于只在 A 发生切主体并换新 Token,回到已停更半日的 B,一旦点出保存操作,新票旧权会导致非常诡异的环境覆盖乱写或权限穿刺的灾难。需监听拦截或运用通知协议提示"你的所属大运行体变故了,强行把B刷新一次"。
---
### 选项二:外部通信网关配置 (Notification Gateway)
**核心价值**:击穿 Web SaaS 被动性,结合线下终端触发机制"去网外拉人上线"。
#### 1. 功能需求点
- **参数动态配置面板与试运行检验器**:
- 提供 GUI 管理器用于配置及更新绑定阿里云、各大 SMTP 服务商之必要 Access ID / Secret 的挂载端,取代传统硬编码配置文件行为。
- 配属独立的"模拟试跑 Ping 测试组件",当场直连运营商端口尝试拦截 Callback 以确保网络通性与账密无差。
- **消息接挂重构及防御边界**:
- 更新既往陈旧的 `Message Dispatch Engine` 模块功能,根据不同触达场景(会议即将来临=全选 短信及邮件站内;常规通过=仅站内)按等级分类调度分包转发策略引擎。
- **外部投递计价风控墙机制(核心)**:所有发送策略前置必须接受熔断限流判定。以手机号加持策略控制,例如 30s 免扰期、当日 10 次防爆刷期等。
- 所有落在存储媒介的相关 API Key / 凭据 绝不可见文。数据库须用可逆双端加解算法(AES 类)对涉密数据列落盘。
---
## 七、【P3 阶段三】全局搜索与视觉高阶设置 (Global Omni-Search & UX Settings)
**核心价值**:打造极致 Spotlight 查询体验及高维度前端个性呈现美感,提升大型重度后台工业友好度。
### 1. 功能需求点
- **Cmd/Ctrl + K 高级聚焦悬浮综合体面板**:
- 无论处于系统何时何地一键呼唤搜索层,键入文本将激发在全库关键领域(会务名称代号、全员资料以及长达几十层的应用导航锚点目录)穿透式关联词聚合大合照,用户可全屏利用光标键流利切换聚焦落入该条结果内跳转执行。
- **视觉定性配置参数板**:
- 包含夜用全局暗黑模式与强感光的白日模式硬切,附加 Element Plus 组件间隙及大中小(UI Component System Scale Density)密度的收放支持。
- **存储继承连贯延续**:
- 避免仅寄希望于当前主机的 HTML 本地存储丢弃引发配置还原。对诸如明暗光线设定等数据推至用户 Profile 设置持久存储端,实现其登录至其他工位或出差设备都能享受无缝同感连贯还原操作之乐。
---
## 八、验收标准总览
### 阶段零验收 Checklist(2026-04-14 审计更新)
- [x] 5 个 Bug 全部修复并验证(BUG-3 为 workaround 方案,功能可用)
- [x] 所有核心实体支持软删除(二次确认 + 审计留痕)— 后端全部实现
- [x] 租户编辑、平台用户编辑接口和 UI 完成 — `PlatformUserController` `PUT /{id}` 已实现
- [x] 专家列表、用户列表完成服务端分页
- [x] 404 页面 + 全局错误边界上线
- [x] 登录失败锁定策略生效 — 后端内存实现 + 前端两个登录页均有 `remainingAttempts` / `lockCountdown` / alert UI
- [x] 密码策略升级(≥8 位 + 复杂度校验)— 后端已实现(比 PRD 更严格)
- [x] 图形验证码集成 — 后端 `CaptchaService` + `CaptchaController`;前端两个登录页均有验证码输入+图片+刷新
- [x] requestId 链路追踪 — 后端 logback `[reqId=%X{requestId}]` + 前端 `http.ts` 错误提示中展示 requestId
- [x] 健康检查端点可用 — `/api/system/health` 含 DB 连通性检测 + version 字段
- [x] 会议取消、项目归档/解冻操作完成
- [x] 批量审核操作可用 — `AuditController` batch-approve / batch-reject / batch-remind 含幂等校验
- [x] 工作台卡片接入真实数据
- [ ] 会议列表导出完成 — ❌ 后端导出端点未实现
- [ ] 租户级字典管理页面上线 — ❌ 租户端仅只读,CRUD 管理页面未实现
- [x] 状态文案集中管理 — 已集中到 `utils/status.ts`
- [x] 面包屑导航 — `BreadcrumbNav.vue` + `AppLayout.vue` sidebar 布局已集成 + 所有路由 `meta.title`
- [x] 路由切换动态更新 document.title — `router.afterEach` 已实现
- [x] 服务端分页 5 接口 — templates / roles / enterprises / audit-flows / notification-policies 全部含 COUNT + LIMIT/OFFSET + PageResult
- [x] 密码强度可视化指示条 — `PasswordStrengthBar.vue` 已创建并集成至 `UserPage.vue`
**仍未完成项汇总(阶段零,仅 3+2 项):**
1. ❌ 后端数据导出端点(meetings / users / projects / notifications export)
2. ❌ 租户级字典管理(CRUD 页面 + 后端写入接口)
3. ❌ 字典驱动的表单选项(meetingCategory / meetingForm 改为字典 API)
4. ⚠️ 登录锁定 / 限流从内存迁移至 Redis(多实例部署需求,技术债务)
5. ⚠️ 前端"包含已删除"筛选项(低优先级 UI 补全)
---
### 进阶模块验收(按阶段逐步交付)
- [ ] 批量导入中心:Excel 导入 + 校验反馈 + 异步任务 — ❌ 未开始
- [ ] 多租户切换:无感秒切 + 状态隔离 + 多 Tab 防串 — ❌ 未开始
- [ ] 通信网关:GUI 配置 + 测试连通 + 风控限流 — ❌ 未开始
- [ ] 全局搜索:Cmd+K 唤醒 + 全库穿透 + 主题切换 — ❌ 未开始