# 第一次升级

## 1. 升级目标
- 不改 PostgreSQL 现有数据与表结构。
- 不改服务器文件存储路径（`UPLOAD_DIR` / `UPLOAD_FALLBACK_DIRS`）。
- 通过“代码 + 前端构建产物”发布完成升级。
- 修复现有高优先级缺陷并增强安全性与稳定性。

## 2. 约束与发布原则
- 不执行任何初始化/造数脚本（如 `init-db`、`seed`、`create_db`、`setup`）。
- 服务器 `.env` 保持原值（尤其数据库与上传目录相关配置）。
- 采用兼容式修改，避免破坏现网接口与数据。

## 3. 升级计划（逐项完成）

状态说明：
- `[ ]` 待处理
- `[-]` 处理中
- `[x]` 已完成

- [x] 01. 建立本升级文档与执行清单
- [x] 02. 修复成果编辑接口运行时错误与权限判断
- [x] 03. 前端移除 URL token 传递（导出/下载改为 Header 认证）
- [x] 04. 上传安全加固（文件大小/数量限制、通知附件类型限制）
- [x] 05. 上传失败时清理已落盘文件，避免孤儿文件
- [x] 06. 数据库配置兼容修复（`DB_DATABASE`/`DB_NAME`）
- [x] 07. 数据库连接池错误策略优化（避免进程直接退出）
- [x] 08. 整体回归检查与发布说明整理

## 4. 变更记录
- 2026-02-25：创建文档与首轮升级清单。
- 2026-02-25：修复 `GET /api/achievements/:id` 的运行时错误（移除未定义变量 `parsedContributors` 的错误逻辑）。
- 2026-02-25：修复 `PUT /api/achievements/:id` 事务提前返回未回滚问题（补充 `ROLLBACK`）。
- 2026-02-25：修复 `DELETE /api/achievements/:id` 事务提前返回未回滚问题（补充 `ROLLBACK`）。
- 2026-02-25：成果上传接口补充 JSON 解析失败时的落盘文件清理。
- 2026-02-25：通知发布接口补充附件限制与异常清理，`content` 改为净化后入库（不改表结构）。
- 2026-02-25：前端导出/下载去除 URL token，统一改为 `Authorization` Header + Blob 下载。
- 2026-02-25：数据库连接配置兼容 `DB_DATABASE` / `DB_NAME`，连接池 idle error 不再 `process.exit(-1)`。
- 2026-02-25：后端语法检查通过；前端 `npm run build` 编译通过。
- 2026-02-25：本次新增与更新内容全部按 UTF-8 编码保存。
- 2026-02-26：统计页新增“统计口径说明”和 AI 安全说明文案；新增“部门独立完成 / 合作项目统计表”。
- 2026-02-26：AI Prompt 优化为结构化管理汇报模板（执行摘要/关键发现/独立合作解读/风险/行动建议/一句话结论）。
- 2026-02-26：修复统计接口 500（`text <> varchar[]/text[]` 类型兼容问题），统一在 SQL 中显式转换为 `text[]`，并同步修复 AI 分析同口径查询。
- 2026-02-26：AI 分析结果前端改为 Markdown 渲染（支持标题/列表/表格等格式），提升可读性。
- 2026-02-26：AI 提示词精简；传给模型的数据改为语义化摘要（类型/状态中文化、TopN 与占比、近 24 个月趋势），降低上下文长度并提升分析速度。
- 2026-02-26：AI 分析新增流式输出（边生成边显示）；前端新增“清空输出”按钮（生成中可中止并清空）。
- 2026-02-26：取消后端 `max_tokens` 人工上限（输出长度不再由项目侧硬限制，受模型侧能力约束）。
- 2026-02-26：AI 功能权限扩展至 `senior_user`（高级用户）与 `intermediate_user`（中级用户），前后端权限口径保持一致。
- 2026-02-26：成果列表/成果详情/导出接口的 `assigned_departments` 返回口径统一排除院领导部门（与统计页口径一致）。
- 2026-02-26：修正部门过滤边界：若某条成果过滤院领导部门后为空，则回退显示原始部门，避免“无归属部门”展示问题。
- 2026-02-26：成果归属部门计算改为“全体完成人手机号对应部门去重后统计”，并在写库时过滤院领导部门（不再仅按主要完成人计算）。
- 2026-02-26：归属部门规则再次调整为“单归属部门”：
  - 优先按主要完成人顺序取部门；
  - 若命中院领导部门则按顺序回退到下一个完成人，取第一个非院领导部门；
  - 若全部均为院领导部门，则回退首个部门，保证每条成果只有 1 个归属部门。
- 2026-02-27：统计页下线“部门独立完成 / 合作项目统计表”（当前每个项目仅归属 1 个部门，该表不再提供有效增量信息）。
- 2026-02-27：成果相关全入口口径收敛为单归属部门（成果公示/全部成果/我的成果/详情权限/部门筛选/统计/AI 分析统一），并对历史多部门数据按“首个非院领导，否则首个部门”规则读取时归一。
- 2026-02-27：统计页新增“AI 年份筛选与图表年份联动”：在 AI 卡片选择年份后，下方部门分布/类型分布/部门种类统计三图同步切换；年份来源保持动态，无硬编码年份。

## 5. 服务器端操作（全部完成后填写）
- 1. 先备份服务器现有代码目录和前端静态目录（保留可回滚版本）。
- 2. 保持服务器 `.env` 不变，尤其是 `DB_*`、`UPLOAD_DIR`、`UPLOAD_FALLBACK_DIRS`。
- 3. 只上传本次变更的后端代码与前端构建产物（`client/build` 或你实际部署目录下的 dist）。
- 4. 不执行任何数据库初始化、迁移、造数脚本（`init-db`/`seed`/`create_db`/`setup`）。
- 5. 重启 Node 服务进程（`pm2 restart ...` 或 `systemctl restart ...`，按你现网方式）。
- 6. 发布后烟测：
  - 成果详情页打开（`GET /api/achievements/:id`）。
  - 成果修改/删除权限验证（普通用户、超管各测一次）。
  - 成果附件下载、CSV 导出、ZIP 导出。
  - 通知发布（带附件与异常附件各测一次）。
  - 统计分析页：部门统计已排除院领导部门；每条成果仅计入一个归属部门。
  - 统计分析页：不再显示“部门独立完成 / 合作项目统计表”。
  - AI 分析：可在 `auto / qwen / deepseek` 切换，返回提供方与尝试顺序。
- 7. 若异常，先回滚代码与前端静态文件，不回滚数据库（本次未做数据库结构变更）。

## 6. 功能扩展：AI 分析（2026-02-25）

### 6.1 功能目标
- 在“统计分析”页面增加 AI 分析入口。
- 使用后端调用大模型 API 生成分析结论，前端仅展示结果。
- 保持数据库与文件存储路径不变，不做任何表结构变更。

### 6.2 安全策略（已实现）
- 不向大模型发送附件内容。
- 不向大模型发送附件路径与文件名。
- 不向大模型发送完成人手机号和姓名。
- 仅发送脱敏后的聚合统计数据（类型分布、状态分布、部门分布、月度趋势、质量计数）。
- 接口权限限制为管理员/超级管理员可用。

### 6.3 本次新增文件与改动
- 新增后端路由：`server/routes/aiAnalysis.js`
- 挂载后端路由：`server/index.js` -> `/api/ai-analysis`
- 新增 AI 配置示例：`server/.env.example`
- 前端入口与交互：`client/src/pages/Statistics.js`
- 新增提供方选择：自动 / 千问 / DeepSeek / custom
- 新增自动回退：按优先级依次尝试（可配置）

### 6.4 服务器端新增配置
在服务器 `.env` 新增（或确认）以下变量：

```env
AI_DEFAULT_PROVIDER=auto
AI_PROVIDER_PRIORITY=qwen,deepseek,custom

QWEN_API_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
QWEN_API_KEY=你的千问Key
QWEN_MODEL=qwen-plus

DEEPSEEK_API_BASE_URL=https://api.deepseek.com/v1
DEEPSEEK_API_KEY=你的DeepSeekKey
DEEPSEEK_MODEL=deepseek-chat

# 可选：自定义网关/代理
AI_API_BASE_URL=
AI_API_KEY=
AI_MODEL=

AI_TIMEOUT_MS=45000
AI_MAX_TOKENS=1600
```

说明：
- `AI_DEFAULT_PROVIDER=auto` 时，按 `AI_PROVIDER_PRIORITY` 顺序尝试。
- 前端可手动指定单一提供方，也可选“自动”。
- 私有网段网关可放在 `AI_API_BASE_URL`（custom）中使用（http/https 均支持）。

### 6.5 上线后测试点
- 1. 管理员/超管登录，进入“统计分析”页面，确认出现“AI 智能分析（脱敏）”卡片。
- 2. 选择筛选条件并输入问题，点击“生成 AI 分析”应返回文本结果。
- 3. 普通用户账号不应可用该功能（无入口或接口返回 403）。
- 4. 服务器日志确认无附件路径、文件名、手机号、姓名外发日志。

### 6.6 统计口径调整（院领导部门过滤）
- 部门相关统计（部门分布、部门类型交叉、部门趋势）统一排除 `dict_leader_departments` 中配置的院领导部门。
- 成果归属采用“单归属部门”写库规则（按主要完成人顺序回退到首个非院领导部门；若均为院领导则回退首个部门）。
- 统计页已下线“部门独立完成 / 合作项目统计表”。
- AI 分析入参与统计页保持同口径（排除院领导部门，不再传递独立/合作统计字段）。

### 6.7 文案与 Prompt 优化（2026-02-26）
- 前端统计页新增口径提示文案，明确“排除院领导部门 + 单归属部门计数”。
- AI 卡片新增安全提示文案，明确仅发送脱敏聚合数据，不发送附件信息和个人敏感信息。
- AI 系统提示词改为结构化输出，支持直接用于院级管理汇报。
- 输出要求强调“先结论、后证据、再建议”，并在数据不足时必须显式提示证据不足。
