4.9 KiB
4.9 KiB
Frontend 会话列表底部用户区域块 — Design Spec
日期: 2026-08-06 状态: Approved
背景
src/views/frontend/index.vue 是核心 AI 对话页面,左侧是 ConversationSidebar(会话列表)。当前侧边栏底部没有任何用户相关的入口:用户无法在不离开页面的情况下查看自己的头像/昵称、退出登录、或跳转到智能体广场。
目标
在会话列表底部新增一个区域块,提供:
- 用户头像 + 昵称展示,点击打开「个人资料」修改弹窗(可改头像、昵称)
- 「退出」按钮(二次确认后退出登录)
- 「前往智能体广场」按钮
侧边栏收起时,该区域块仅显示一个小头像,点击弹出菜单。
非目标
- 不修改智能体广场页本身
- 不修改会话列表的样式或行为
- 不引入新的退出 / 上传头像后端接口
方案概览
新增两个组件,ConversationSidebar 引入并放在底部。
新增文件
-
src/views/frontend/components/UserArea.vue- 展示用户头像 + 昵称、退出按钮、前往智能体广场按钮
- 接收
collapsedprop(来自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/userprops,emitupdate:modelValue、saved - 保存时调用:
uploadAvatar()—PUT /system/user/profile/avatarupdateUserProfile({ nickName })—PUT /system/user/profile
- 保存成功后更新
useUserStore()的avatar、nickName,并 emitsaved,父组件 ElMessage 成功提示
- Element Plus
修改文件
src/views/frontend/components/ConversationSidebar.vue- 在
sidebar-content内的<el-scrollbar>下方引入<UserArea ref="userAreaRef" :collapsed="collapsed" /> - 把
<el-scrollbar>的height由calc(100vh - 160px)改为calc(100vh - 240px)(预留底部 user-area 高度) - 把
sidebar-content改为 flex 布局,使<el-scrollbar>占中间,<UserArea>占底部固定高度
- 在
组件契约
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) | 保存成功后回调 |
数据流
ConversationSidebar通过useUserStore()取用户信息,传给UserArea和UserInfoDialog- 用户点击头像 →
UserArea.openInfoDialog()→ 内部把infoDialogVisible.value = true→<UserInfoDialog v-model="infoDialogVisible" :user="user" @saved="onSaved" /> UserInfoDialog内部:- 选择本地图片 →
vue-cropper裁剪 → 用户点"保存" - 调
uploadAvatar(formData)→ 成功后调updateUserProfile({ nickName })→ 更新 store
- 选择本地图片 →
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
- 头像昵称展示支持在线状态