mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-19 10:22:04 +08:00
- 给 localStorage 访问加了 try/catch + 可用性判断:dashboard/src/utils/chatConfigBinding.ts:13 - 新增 getFromLocalStorage/setToLocalStorage(在受限存储/无痕模式下异常时回退/忽略) - getStoredDashboardUsername() / getStoredSelectedChatConfigId() 改为走安全读取:dashboard/src/utils/chatConfigBinding.ts:36 - 新增 setStoredSelectedChatConfigId(),写入失败静默忽略:dashboard/src/utils/chatConfigBinding.ts:44 - 把 ConfigSelector.vue 里直接 localStorage.getItem/setItem 全部替换为上述安全方法:dashboard/src/components/chat/ConfigSelector.vue:81 - 已重新跑过 pnpm run typecheck,通过。
7.5 KiB
7.5 KiB
Chat 新会话配置绑定修复说明
0. 变更摘要(改了哪些文件)
dashboard/src/utils/chatConfigBinding.tsdashboard/src/composables/useSessions.tsdashboard/src/components/chat/ConfigSelector.vuedashboard/src/components/chat/StandaloneChat.vuedashboard/src/components/chat/Chat.vue
1. 问题背景
Dashboard 在创建新会话时会调用接口:
GET /api/chat/new_session
但创建完成后,并没有把“当前选择的配置文件(abconf)”绑定到新会话对应的对话路由上,导致新会话会继续使用后端的默认配置。
在现有实现中,配置文件与对话的绑定关系依赖配置路由接口:
POST /api/config/umo_abconf_route/update
ConfigSelector.vue 已经使用该接口来把配置绑定到当前对话(通过 UMO 作为 key),但“新会话创建”流程没有做同样的绑定操作,因此会出现新会话配置丢失的问题。
2. 修复思路(做了什么)
核心思路:新会话创建成功后,立刻根据该会话的 UMO 调用 /api/config/umo_abconf_route/update 进行绑定。
UMO 的构造与 ConfigSelector.vue 保持一致(platformId:messageType:sessionKey),避免“前端绑定的 UMO 与后端路由表 key 不一致”导致绑定无效。
同时为了不影响正常使用,绑定失败不会阻断会话创建(仅输出错误日志)。
3. 具体改动(逐文件)
3.1 dashboard/src/composables/useSessions.ts
修改点:newSession()
- 读取用户最近一次选择的配置 id:
- 来源:
localStorage的chat.selectedConfigId(通过getStoredSelectedChatConfigId()读取)
- 来源:
- 创建新会话后(拿到
sessionId、platformId),在满足以下条件时自动绑定:selectedConfigId !== 'default'platformId === 'webchat'(当前 UMO 构造逻辑为 webchat 专用)
- 绑定方式:
- 使用
buildWebchatUmoDetails(sessionId, false)生成umo - 调用:
POST /api/config/umo_abconf_route/update- payload:
{ umo, conf_id: selectedConfigId }
- 使用
- 错误处理:
- 绑定失败不会 throw,避免导致新会话创建失败;仅
console.error('Failed to bind config to session', err)
- 绑定失败不会 throw,避免导致新会话创建失败;仅
- 清理调试代码:
- 移除临时加入的
console.warn(...)调试日志 - 移除调试用的二次校验请求(不再请求
GET /api/config/umo_abconf_routes)
- 移除临时加入的
关键代码(简化后):
const selectedConfigId = getStoredSelectedChatConfigId();
const { session_id: sessionId, platform_id: platformId } = (await axios.get('/api/chat/new_session')).data.data;
currSessionId.value = sessionId;
if (selectedConfigId !== 'default' && platformId === 'webchat') {
const { umo } = buildWebchatUmoDetails(sessionId, false);
await axios.post('/api/config/umo_abconf_route/update', { umo, conf_id: selectedConfigId });
}
为什么这样改:
useSessions.newSession()是主聊天页创建新会话的唯一入口(Chat.vue通过它创建会话),把绑定逻辑放在这里可以一次性修复所有创建新会话的场景。- 使用与
ConfigSelector.vue相同的 UMO 格式,确保后端路由表能正确命中。 - 限制
platformId === 'webchat'是为了避免对非 webchat 平台生成错误 UMO 并写入路由表。
3.2 dashboard/src/components/chat/StandaloneChat.vue
修改点:bindConfigToSession() / newSession()
bindConfigToSession(sessionId):- 若
props.configId为空或为default则跳过 - 使用
buildWebchatUmoDetails(sessionId, false)生成umo - 调用
POST /api/config/umo_abconf_route/update绑定conf_id: props.configId
- 若
newSession():GET /api/chat/new_session成功后,优先调用bindConfigToSession(sessionId)(best-effort)- 绑定完成后再设置
currSessionId
- 清理调试代码:
- 移除临时加入的
console.warn(...)调试日志 - 移除调试用的二次校验请求(不再请求
GET /api/config/umo_abconf_routes)
- 移除临时加入的
关键代码(简化后):
async function bindConfigToSession(sessionId: string) {
const confId = (props.configId || '').trim();
if (!confId || confId === 'default') return;
const { umo } = buildWebchatUmoDetails(sessionId, false);
await axios.post('/api/config/umo_abconf_route/update', { umo, conf_id: confId });
}
async function newSession() {
const sessionId = (await axios.get('/api/chat/new_session')).data.data.session_id;
await bindConfigToSession(sessionId);
currSessionId.value = sessionId;
}
为什么这样改:
StandaloneChat.vue自己实现了会话创建逻辑(不走useSessions),因此需要在这个组件内补齐同样的绑定动作。- 先绑定后激活
currSessionId,可以降低“UI 已开始使用该会话但配置尚未绑定”的窗口期(尤其是首次进入组件时的自动建会话)。
3.3 dashboard/src/components/chat/Chat.vue
修改点:仅清理调试日志(无业务逻辑变更)
- 移除调试用的
console.warn(...),包括:- 组件加载/挂载日志
- 发送消息前“无会话则创建会话”的提示日志
为什么这样改:
- 这些日志用于验证修复是否被调用,确认生效后应移除,避免污染浏览器控制台与用户反馈日志。
3.4 dashboard/src/utils/chatConfigBinding.ts
修改点:新增公共工具(集中管理 “选择的配置 id” 与 UMO 构造)
- 新增常量:
CHAT_SELECTED_CONFIG_STORAGE_KEY = 'chat.selectedConfigId'
- 新增方法:
getStoredSelectedChatConfigId():从localStorage读取当前选中的配置 id(为空则返回default)getStoredDashboardUsername():读取localStorage.user(为空则返回guest)setStoredSelectedChatConfigId(configId):向localStorage写入当前选中的配置 id(写入失败时静默忽略)buildWebchatUmoDetails(sessionId, isGroup):按platformId:messageType:sessionKey的格式生成 webchat 的 UMO(与ConfigSelector.vue逻辑一致)
- 增加安全性:
- 对
localStorage.getItem/setItem增加try/catch与可用性判断,避免在 Safari 无痕/受限存储等环境中抛异常导致页面崩溃
- 对
为什么这样改:
- 之前
ConfigSelector.vue、useSessions.ts、StandaloneChat.vue都需要同一套“storage key / UMO 拼接”规则,分散实现容易出现不一致(导致绑定不生效)。 - 抽成一个 utils 后,可以保证新会话绑定与配置选择器使用完全一致的 UMO/Key。
- 同时把 localStorage 访问集中到一个位置做防护,减少各处自行访问带来的稳定性风险。
3.5 dashboard/src/components/chat/ConfigSelector.vue
修改点:复用公共 storage 访问与 username 读取(无业务逻辑变化)
- 不再直接访问
localStorage,改为复用chatConfigBinding.ts中的安全方法:getStoredDashboardUsername()getStoredSelectedChatConfigId()setStoredSelectedChatConfigId()
为什么这样改:
- 避免多个文件分别访问
localStorage导致实现不一致或因受限存储环境抛异常。 - 让
useSessions.ts读取到的“上次选择配置 id”与ConfigSelector.vue持久化/回写的是同一份数据与同一套兼容逻辑。
4. 额外说明
- 本次修复复用并遵循现有的配置绑定机制(
umo_abconf_route路由表),不改变后端接口语义。 - 绑定失败不会阻止新会话创建:这样即使后端配置路由接口异常,用户仍可继续使用默认配置进行聊天,避免前端功能不可用。