---
author: Claude
created_at: 2026-05-25
purpose: 在管理后台调用日志列表中增加"调用用户"列，显示用户昵称+ID，方便排查用户反馈问题
---

# 调用日志列表增加用户字段设计

## 背景

管理后台 `/aiconfig/list` AI 配置管理页面的"调用日志"tab 中，列表当前不显示调用用户信息。运营人员排查用户反馈问题时，需要点开每条日志的详情弹窗才能看到 userId，效率低。

## 改动范围

### 1. 后端 — 实体新增字段

**文件**: `server/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

**文件**: `server/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
<el-table-column label="调用用户" width="180" show-overflow-tooltip>
  <template #default="{ row }">
    {{ userDisplay(row) }}
  </template>
</el-table-column>
```

新增辅助函数：

```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
<div class="info-item">
  <span class="info-label">调用用户</span>
  <span class="info-value">{{ userDisplay(log) }}</span>
</div>
```

同样复用 `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`（暂不支持按用户筛选）
