# Frontend 会话列表底部用户区域块 — Design Spec **日期:** 2026-08-06 **状态:** Approved ## 背景 `src/views/frontend/index.vue` 是核心 AI 对话页面,左侧是 `ConversationSidebar`(会话列表)。当前侧边栏底部没有任何用户相关的入口:用户无法在不离开页面的情况下查看自己的头像/昵称、退出登录、或跳转到智能体广场。 ## 目标 在会话列表底部新增一个区域块,提供: 1. 用户头像 + 昵称展示,点击打开「个人资料」修改弹窗(可改头像、昵称) 2. 「退出」按钮(二次确认后退出登录) 3. 「前往智能体广场」按钮 侧边栏收起时,该区域块仅显示一个小头像,点击弹出菜单。 ## 非目标 - 不修改智能体广场页本身 - 不修改会话列表的样式或行为 - 不引入新的退出 / 上传头像后端接口 ## 方案概览 新增两个组件,`ConversationSidebar` 引入并放在底部。 ### 新增文件 - `src/views/frontend/components/UserArea.vue` - 展示用户头像 + 昵称、退出按钮、前往智能体广场按钮 - 接收 `collapsed` prop(来自 `ConversationSidebar`) - 展开时:完整展示三块内容;收起时:仅显示小圆形头像,点击弹出 dropdown 菜单 - 通过 `defineExpose` 暴露 `openInfoDialog()` 方法,父组件 `ConversationSidebar` 用 ref 调用(与现有 `defineExpose({ refresh: fetchSessions, ... })` 风格一致) - `src/views/frontend/components/UserInfoDialog.vue` - Element Plus `el-dialog`,标题"个人资料",宽 500px - 内容:头像裁剪上传区(vue-cropper 固定 1:1)+ 昵称输入框 - 接收 `modelValue` / `user` props,emit `update:modelValue`、`saved` - 保存时调用: - `uploadAvatar()` — `PUT /system/user/profile/avatar` - `updateUserProfile({ nickName })` — `PUT /system/user/profile` - 保存成功后更新 `useUserStore()` 的 `avatar`、`nickName`,并 emit `saved`,父组件 ElMessage 成功提示 ### 修改文件 - `src/views/frontend/components/ConversationSidebar.vue` - 在 `sidebar-content` 内的 `` 下方引入 `` - 把 `` 的 `height` 由 `calc(100vh - 160px)` 改为 `calc(100vh - 240px)`(预留底部 user-area 高度) - 把 `sidebar-content` 改为 flex 布局,使 `` 占中间,`` 占底部固定高度 ## 组件契约 ### UserArea.vue | 名称 | 类型 | 说明 | | --- | --- | --- | | Props | | | | collapsed | Boolean | 侧边栏是否收起 | | Methods (expose) | | | | openInfoDialog() | () => void | 打开个人资料弹窗 | ### UserInfoDialog.vue | 名称 | 类型 | 说明 | | --- | --- | --- | | Props | | | | modelValue | Boolean | 弹窗显隐(v-model) | | user | Object | 当前用户 `{ avatar, nickName }` | | Emit | | | | update:modelValue | (val: Boolean) | 显隐变化 | | saved | (user: Object) | 保存成功后回调 | ## 数据流 1. `ConversationSidebar` 通过 `useUserStore()` 取用户信息,传给 `UserArea` 和 `UserInfoDialog` 2. 用户点击头像 → `UserArea.openInfoDialog()` → 内部把 `infoDialogVisible.value = true` → `` 3. `UserInfoDialog` 内部: - 选择本地图片 → `vue-cropper` 裁剪 → 用户点"保存" - 调 `uploadAvatar(formData)` → 成功后调 `updateUserProfile({ nickName })` → 更新 store 4. `UserInfoDialog` 关闭后 `ConversationSidebar` 触发 `ElMessage.success('修改成功')` ## 错误处理 - 上传头像失败:`ElMessage.error('头像上传失败')`,弹窗保持打开以便重试 - 更新昵称失败:`ElMessage.error('修改失败')` - 退出失败:`ElMessage.error('退出失败,请稍后重试')` - 网络异常:依赖 `request.js` 的统一错误处理 ## 视觉规范 - 与现有侧边栏保持一致色系:`#e4e7ed` 分割线、`#409eff` 主色、`#f56c6c` 危险色 - 头像 36×36 圆形(收起时 28×28) - 昵称省略号截断 `text-overflow: ellipsis` - 按钮文字与图标间距 6px - 顶部细分割线:`border-top: 1px solid #e4e7ed` ## 测试 - 手动测试:本地 `yarn dev`,访问 `/frontend/index` - 头像昵称正确展示 - 点击头像 → 弹窗打开 → 修改头像/昵称 → 保存 → 列表头像昵称同步刷新 - 点击退出 → 确认 → 跳转到 `/login` - 点击「前往智能体广场」 → 跳转到 `/frontend/marketplace` - 收起侧边栏 → 仅显示小头像 → hover 出 tooltip → 点击出 dropdown 菜单 ## 风险 - 头像上传接口需要登录态,已通过 `request.js` 自动带 token 处理 - 弹窗高度可能在小屏幕溢出,宽度固定 500px,自适应垂直 ## 后续可扩展(不在本次范围) - 收起状态下的 dropdown 也可改成 popover - 头像昵称展示支持在线状态