diff --git a/docs/superpowers/specs/2026-05-25-call-log-add-user-design.md b/docs/superpowers/specs/2026-05-25-call-log-add-user-design.md new file mode 100644 index 0000000..dd420c0 --- /dev/null +++ b/docs/superpowers/specs/2026-05-25-call-log-add-user-design.md @@ -0,0 +1,124 @@ +--- +author: Claude +created_at: 2026-05-25 +purpose: 在管理后台调用日志列表中增加"调用用户"列,显示用户昵称+ID,方便排查用户反馈问题 +--- + +# 调用日志列表增加用户字段设计 + +## 背景 + +管理后台 `/aiconfig/list` AI 配置管理页面的"调用日志"tab 中,列表当前不显示调用用户信息。运营人员排查用户反馈问题时,需要点开每条日志的详情弹窗才能看到 userId,效率低。 + +## 改动范围 + +### 1. 后端 — 实体新增字段 + +**文件**: `backend-single/src/main/java/com/emotion/entity/AiCallLog.java` + +在 `userId` 字段下方新增: + +```java +@TableField("user_name") +private String userName; +``` + +### 2. 数据库 — 表新增列 + +```sql +ALTER TABLE t_ai_call_log ADD COLUMN user_name VARCHAR(100) COMMENT '用户昵称' AFTER user_id; +``` + +### 3. 后端 — 日志保存时写入 userName + +**文件**: `backend-single/src/main/java/com/emotion/service/impl/AiRuntimeServiceImpl.java` + +两处日志创建位置(第 68-73 行 `invokeStream` 方法、第 219-225 行 `invokeEndpointStream` 方法),在 `callLog.setUserId(...)` 之后补充: + +```java +callLog.setUserName(request.getUserName()); +``` + +- `invokeStream` 方法:`request` 已由 `AiRoutingController.withCurrentUser()` 注入 `userName` +- `invokeEndpointStream` 方法:`request` 在 `invokeEndpointStream` 内部创建(第 214 行),已通过 `UserContextHolder.getCurrentUsername()` 注入 `userName` + +### 4. 前端 — 类型定义 + +**文件**: `web-admin/src/types/aiconfig.ts` + +`AiCallLog` 接口中 `userId` 字段下方新增: + +```typescript +userName?: string +``` + +### 5. 前端 — 列表新增列 + +**文件**: `web-admin/src/views/aiconfig/AiRoutingList.vue` + +在调用日志表格的"调用时间"列之后、"场景"列之前,新增一列: + +```vue + + + +``` + +新增辅助函数: + +```typescript +function userDisplay(row: AiCallLog): string { + const name = row.userName + const id = row.userId + if (name && id) return `${name}(${id})` + if (name) return name + if (id) return `-(ID: ${id})` + return '-' +} +``` + +### 6. 前端 — 详情弹窗格式统一 + +**文件**: `web-admin/src/views/aiconfig/components/AiCallLogDetailDialog.vue` + +将基本信息区域中的"用户 ID"行改为"调用用户",显示格式与列表一致: + +```vue +
+ 调用用户 + {{ userDisplay(log) }} +
+``` + +同样复用 `userDisplay` 辅助函数。 + +## 数据流 + +``` +路径 1(场景调用): +用户发起 AI 请求 + → AiRoutingController.withCurrentUser() 注入 userName + → AiRuntimeServiceImpl.invokeStream() 创建 callLog 时写入 userName + → 保存到 t_ai_call_log.user_name + +路径 2(Endpoint 直接调用): +用户发起 Endpoint 请求 + → AiRuntimeServiceImpl.invokeEndpointStream() 内部通过 UserContextHolder.getCurrentUsername() 获取 userName + → 创建 callLog 时写入 userName + → 保存到 t_ai_call_log.user_name + +两条路径最终都: + → 前端查询日志列表,列表/弹窗显示 昵称(ID) +``` + +## 兜底策略 + +- 历史数据 `user_name` 为 NULL 时,列表显示 `-(ID: xxx)` +- `userId` 也为空时,显示 `-` + +## 不做的 + +- 不在筛选栏新增用户搜索框(需求仅列表展示,搜索后续按需扩展) +- 不修改 `AiCallLogQueryRequest`(暂不支持按用户筛选)