# 系统增强 PRD v2 未完成项清单

基于 `system_enhancement_prd_v2.md` 与当前前后端代码核对，本文只列出当前仍属于 **部分实现** 或 **未实现** 的功能项。

> 核对时间：2026-04-20

---

## 一、阶段零 P0：已完成

结合当前代码，以及“Redis 相关能力已调整为 MySQL 实现”的最新约束，阶段零 P0 项目当前已不再属于未完成项。

### 1. 数据导出

**当前状态：已完成**

- 已提供以下导出入口：
  - `POST /api/meetings/export`
  - `POST /api/users/export`
  - `POST /api/projects/export`
  - `POST /api/notifications/tasks/export`
- `ExportTaskService.processTask()` 已按 `taskCode` 查询业务数据并生成真实 CSV 内容。
- 导出文件会上传到 OSS，并在下载接口中返回真实 `signedUrl`。
- 当前实现覆盖：
  - `MEETING_EXPORT`
  - `USER_EXPORT`
  - `PROJECT_EXPORT`
  - `NOTIFICATION_TASK_EXPORT`

**相关代码**

- `backend/src/main/java/com/writeoff/module/export/service/ExportTaskService.java`
- `backend/src/main/java/com/writeoff/module/export/controller/ExportTaskController.java`
- `backend/src/main/java/com/writeoff/module/meeting/controller/MeetingController.java`
- `backend/src/main/java/com/writeoff/module/system/controller/UserController.java`
- `backend/src/main/java/com/writeoff/module/project/controller/ProjectController.java`
- `backend/src/main/java/com/writeoff/module/notification/controller/NotificationDispatchController.java`

### 2. 登录失败锁定策略

**当前状态：已完成**

- 后端 `LoginAttemptService` 已基于 MySQL 表实现失败计数、30 分钟计数窗口、5 次失败锁定 15 分钟。
- 前端平台登录页和租户登录页已展示剩余尝试次数与锁定倒计时。
- 该项原分析中关于 Redis 的缺口已不再适用。

**相关代码**

- `backend/src/main/java/com/writeoff/security/LoginAttemptService.java`
- `backend/src/main/java/com/writeoff/module/auth/controller/AuthController.java`
- `frontend/src/views/modules/PlatformLoginPage.vue`
- `frontend/src/views/modules/TenantLoginPage.vue`

### 3. 接口限流

**当前状态：已完成**

- 后端 `RateLimitFilter` 已对 `/api/` 路径执行限流。
- `RateLimitService` 已基于 MySQL 计数器实现每 IP 每分钟限流。
- 当前规则已对齐：
  - 全局接口：每 IP 每分钟不超过 300 次
  - 登录接口：每 IP 每分钟不超过 20 次
- 超限统一返回 HTTP `429`，业务错误码为 `10005`。
- 该项原分析中关于 Redis 滑动窗口的缺口已不再适用。

**相关代码**

- `backend/src/main/java/com/writeoff/security/RateLimitFilter.java`
- `backend/src/main/java/com/writeoff/security/RateLimitService.java`
- `backend/src/main/java/com/writeoff/common/exception/ErrorCodes.java`

### 4. 健康检查端点

**当前状态：已完成**

- 后端已同时支持：
  - `GET /api/system/health`
  - `GET /api/health`
- 返回字段已包含 `status`、`timestamp`、`version`、`buildTime`、`database`。
- 运行时版本号与构建时间均已改为配置注入，不再是硬编码常量。
- 鉴于当前状态存储方案已调整为 MySQL，实现中不再要求 Redis 连通性检测。

**相关代码**

- `backend/src/main/java/com/writeoff/module/system/controller/SystemController.java`
- `backend/src/main/java/com/writeoff/security/AuthInterceptor.java`

### 5. 软删除列表筛选

**当前状态：已完成**

- 会议、项目、用户等列表查询已支持 `includeDeleted`。
- 前端页面已提供“包含已删除”筛选项。
- 已删除记录在列表中有明确“已删除”标识。
- 筛选状态已与列表刷新、分页或树形子级加载联动。

**相关代码**

- `backend/src/main/java/com/writeoff/module/meeting/dto/MeetingQueryRequest.java`
- `backend/src/main/java/com/writeoff/module/meeting/service/MeetingService.java`
- `backend/src/main/java/com/writeoff/module/project/controller/ProjectController.java`
- `backend/src/main/java/com/writeoff/module/project/service/ProjectService.java`
- `backend/src/main/java/com/writeoff/module/system/controller/UserController.java`
- `backend/src/main/java/com/writeoff/module/system/service/SystemUserService.java`
- `frontend/src/views/modules/MeetingPage.vue`
- `frontend/src/views/modules/meeting-page/MeetingQueryToolbar.vue`
- `frontend/src/views/modules/ProjectPage.vue`
- `frontend/src/views/modules/UserPage.vue`

---

## 二、阶段一 P1：未实现或仅有雏形

### 1. 批量数据导入中心

**当前状态：部分实现**

- 当前已提供：
  - 专家批量导入接口 `/api/experts/import`
  - 平台专家批量导入接口 `/api/platform/experts/import`
  - 用户批量导入接口 `/api/users/import`
  - 平台用户批量导入接口 `/api/platform/users/import`
- 前端专家页、用户页、平台用户页已提供模板下载、CSV/制表符文本导入入口、导入预览与结果回显。
- 后端已支持“部分成功”导入，返回成功数、失败数和行级错误明细。
- 前端已支持失败行快照 CSV 下载，便于修正后再次导入。
- 已补充 `user.import` 权限初始化。
- 但当前仍属于“轻量导入能力”：
  - 模板下载由前端生成 CSV，不是独立导入中心页面
  - 仍未实现 Excel 文件解析
  - 仍未实现大文件异步任务导入

**相关代码**

- `backend/src/main/java/com/writeoff/module/expert/controller/ExpertController.java`
- `backend/src/main/java/com/writeoff/module/expert/controller/PlatformExpertController.java`
- `backend/src/main/java/com/writeoff/module/system/controller/UserController.java`
- `backend/src/main/java/com/writeoff/module/system/controller/PlatformUserController.java`
- `backend/src/main/java/com/writeoff/module/expert/service/ExpertService.java`
- `backend/src/main/java/com/writeoff/module/expert/service/PlatformExpertService.java`
- `backend/src/main/java/com/writeoff/module/system/service/SystemUserService.java`
- `backend/src/main/java/com/writeoff/module/system/service/PlatformIamService.java`
- `frontend/src/views/modules/ExpertPage.vue`
- `frontend/src/views/modules/UserPage.vue`
- `frontend/src/views/modules/PlatformUserPage.vue`
- `frontend/src/utils/batchImport.ts`
- `frontend/src/api/modules.ts`

**待补齐**

- 增加统一导入中心页面或统一入口。
- 增加 Excel 导入模板与 Excel 文件解析。
- 增加强弱两级校验机制。
- 大文件导入接入异步任务队列。
- 增加前端上传 Loading、防重复提交、防抖拦截。
- 评估是否还需要 `common.import` 等统一导入权限模型。

---

## 三、阶段二 P2：部分实现

### 1. 多租户快捷切换

**当前状态：核心闭环已补齐，仍有增强项待补**

- 后端已补齐租户切换核心接口：
  - `GET /api/auth/switchable-tenants`
  - `POST /api/auth/switch-tenant`
- 后端已补充 `tenant.switch` 权限初始化，并授予各租户 `TENANT_ADMIN` 角色。
- 前端布局顶部已增加租户快捷切换入口，并在切换后重签 JWT、刷新菜单、刷新租户 Logo 与未读通知状态。
- 前端鉴权存储已增加 `authVersion` 广播键，并通过 `storage` 事件对多 Tab 登录态变化进行提示与强制刷新。
- 当前实现已增强为：若目标租户仍具备当前页面对应菜单/权限，则尽量保留原路由；否则回退到 `/dashboard`，避免落到未授权页面。
- 当前“同一账号可跨租户切换”已升级为独立的跨租户账号关联键：
  - 已为 `sys_user` 新增 `tenant_switch_account_key`
  - 历史数据按原有 `phone + password_hash` 分组规则回填关联键
  - 新建用户、导入用户与租户管理员初始化链路会复用同手机号已存在账号的关联键
  - 后续单租户改密不再破坏跨租户切换能力

**待补齐**

- 若未来业务需要支持“同手机号但并非同一主体”的更严格识别，仍可继续演进为显式账号主表/账号绑定关系表。
- 当前前端已补充基于租户上下文的 `RouterView` 重建机制，切换租户后即使保留原路由也会强制重建页面组件，降低旧租户页面状态残留风险。
- 若后续引入 Pinia/更完整的前端全局缓存，仍需要继续补充 store 级别的业务缓存清理机制。
- 可参考仓库中的 `frontend_pinia_adoption_plan.md` 作为前端状态管理演进方案。
- 可继续补充更精细的路由保留策略，例如针对详情页、抽屉态或更复杂 query/hash 的业务上下文恢复。
- 增补切换链路的自动化测试与前端交互回归测试。

**相关代码**

- `backend/src/main/java/com/writeoff/module/auth/controller/AuthController.java`
- `backend/src/main/java/com/writeoff/module/auth/dto/SwitchTenantRequest.java`
- `backend/src/main/java/com/writeoff/module/auth/model/TenantSwitchOption.java`
- `backend/src/main/resources/db/migration/V86__tenant_switch_permission.sql`
- `frontend/src/api/modules.ts`
- `frontend/src/constants/permissions.ts`
- `frontend/src/utils/auth.ts`
- `frontend/src/views/layout/AppLayout.vue`

---

### 2. 外部通信网关配置

**当前状态：部分实现**

- 已新增平台级通知网关配置中心，提供：
  - `GET /api/platform/notify-gateways`
  - `PUT /api/platform/notify-gateways/{channelCode}`
  - `POST /api/platform/notify-gateways/{channelCode}/test`
- 已新增 `platform.notify-gateway.read` / `platform.notify-gateway.manage` 平台权限，并为 `PLATFORM_SUPER_ADMIN` 赋权。
- 已新增平台菜单 `/platform/notify-gateways`，前端提供“邮件网关 / 短信网关”双标签配置页。
- 已新增 `platform_notify_gateway` 配置表，敏感字段通过可逆加密后落库。
- 邮件通道已切换为统一读取平台通知网关中的 SMTP 配置发送，不再依赖配置文件中的 `spring.mail.*`。
- 短信通道已支持读取平台配置，并在 `ALIYUN_SMS` 模式下按真实阿里云短信 RPC 接口发起发送，请求中会携带 `OutId=task-{taskId}` 以便后续回执映射。
- 已补充短信供应商回执适配入口 `POST /api/notifications/receipts/providers/aliyun-sms`，支持单条 JSON、JSON 数组和供应商表单参数三种输入形态，可按 `outId + bizId` 将供应商回执映射回内部通知任务。
- 已新增外部投递保护能力：
  - 短信同一手机号默认 30 秒静默窗口
  - 短信同一手机号默认单日 10 次上限
  - 邮件/短信渠道默认连续失败 3 次后熔断，默认冷却 300 秒
  - 上述阈值已可在平台网关配置页调整

**待补齐**

- 若后续要支持更多短信厂商，仍需抽象多供应商适配层和各自的回执字段映射。
- 当前已覆盖阿里云短信常见回执转发形态；若后续接入更多供应商，仍需继续抽象统一的回执适配协议与字段映射规则。
- 当前仅支持平台统一网关，若未来要做租户级独立网关，还需扩展作用域模型。
- 可进一步补充“测试成功后再启用”的流程约束和更细的配置校验提示。

**相关代码**

- `backend/src/main/resources/db/migration/V87__platform_notify_gateway.sql`
- `backend/src/main/java/com/writeoff/module/notification/controller/PlatformNotifyGatewayController.java`
- `backend/src/main/java/com/writeoff/module/notification/service/PlatformNotifyGatewayService.java`
- `backend/src/main/java/com/writeoff/module/notification/service/PlatformNotifyGatewayTestService.java`
- `backend/src/main/java/com/writeoff/module/notification/service/NotificationGatewayCryptoService.java`
- `backend/src/main/java/com/writeoff/module/notification/service/NotificationDeliveryProtectionService.java`
- `backend/src/main/java/com/writeoff/module/notification/provider/EmailNotificationProvider.java`
- `backend/src/main/java/com/writeoff/module/notification/provider/SmsNotificationProvider.java`
- `backend/src/main/java/com/writeoff/module/notification/controller/NotificationDispatchController.java`
- `backend/src/main/java/com/writeoff/module/notification/dto/AliyunSmsReceiptRequest.java`
- `frontend/src/views/modules/PlatformNotifyGatewayPage.vue`
- `frontend/src/api/modules.ts`
- `frontend/src/constants/permissions.ts`

---

## 四、阶段三 P3：未实现

### 1. 全局快速搜索

**当前状态：部分实现（P3.1 Lite 已完成）**

- 已新增 `Cmd+K / Ctrl+K` 全局搜索入口，并在主布局中提供统一搜索弹层。
- 已新增统一搜索接口 `GET /api/search/global`。
- 当前已支持聚合搜索：
  - 当前用户可访问菜单
  - 会议
  - 租户用户
  - 平台用户（平台端）
- 会议与租户用户结果已接入权限/数据范围过滤。
- 已支持键盘上下选择、回车跳转。

**待补齐**

- 若要做完整版，仍可继续扩展专家、项目等更多业务对象的聚合搜索。
- 当前用户搜索跳转落点为对应管理页筛选结果，若要做到“直接打开目标记录详情/编辑态”，仍需补更细的深链协议。
- 可继续增强结果排序权重、高亮命中词、最近搜索记录与空态推荐。

**相关代码**

- `backend/src/main/java/com/writeoff/module/system/controller/GlobalSearchController.java`
- `backend/src/main/java/com/writeoff/module/system/service/GlobalSearchService.java`
- `frontend/src/components/GlobalSearchLauncher.vue`
- `frontend/src/views/layout/AppLayout.vue`
- `frontend/src/views/modules/MeetingPage.vue`
- `frontend/src/views/modules/UserPage.vue`
- `frontend/src/views/modules/PlatformUserPage.vue`

---

### 2. 视觉高阶设置

**当前状态：部分实现（P3.2 基础版已完成）**

- 已新增用户界面偏好读写接口：
  - `GET /api/profile/preferences`
  - `PUT /api/profile/preferences`
- 已在 `sys_user` / `platform_user` 中新增并持久化：
  - `ui_theme_mode`
  - `ui_density`
- 已支持主题模式切换：
  - 跟随系统
  - 浅色
  - 深色
- 已支持界面密度切换：
  - 舒适
  - 紧凑
- 已在个人中心“界面偏好”中提供可视化设置入口，保存后当前页面即时生效。
- 登录、刷新令牌和租户切换后，会通过鉴权载荷恢复已保存的外观偏好。
- 应用外壳样式已接入主题 token，覆盖顶部布局、侧边栏布局、卡片边框和头像等核心区域。

**待补齐**

- 若要做完整高级版，仍可继续补充更多个性化项，例如字号、导航样式、品牌色方案等。
- 当前“紧凑”模式主要覆盖 Element Plus 组件尺寸与主布局间距，若要进一步细化到更多业务页面，仍可继续补充专属样式适配。
- 多设备保持一致已具备后端持久化基础，但跨设备的最终生效时机仍依赖登录态刷新、重新登录或页面初始化同步链路。

---

## 五、已从“未完成”中剔除的项

以下内容在 PRD 前半段中曾标为未完成或部分完成，但当前代码中已经能看到实现，故不列入未完成项：

- 平台用户编辑接口。
- 服务端分页改造中的 `templates / roles / enterprises / audit-flows / notification-policies`。
- 面包屑导航。
- 路由切换动态更新 `document.title`。
- 图形验证码。
- 登录剩余次数提示与锁定倒计时。
- requestId 日志与前端错误提示展示。
- 批量审核 `batch-approve / batch-reject`。
- 通知发送记录导出入口。
