优化: 设置域体验完善

- 校验失败红框定位字段,保存反馈改持久化成功后
- 数值越界钳制,双提示队列化不再重叠
- 搜索防抖跳分类,托盘气泡文案进多语言
This commit is contained in:
lxy
2026-10-03 17:57:43 +08:00
parent f67e65633b
commit 8396849d04
19 changed files with 329 additions and 93 deletions
+18 -2
View File
@@ -289,6 +289,10 @@ const projectsStore = useProjectStore()
// 滚动边沿/跟随意图重置随 MessageList 迁移,由子组件自管。
watch(() => store.state.activeConversationId, () => {
if (editingMsgId.value) cancelEdit()
// UX-P3: 队列编辑态(editingQueueIdx/editingQueueText)绑定旧会话队列在 activeQueue
// 视图内的下标,切会话后 activeQueue 已换成新会话的集合,残留 idx/text 会错挂到
// 新会话同下标队列项上,随消息编辑态一并重置。
if (editingQueueIdx.value !== null) cancelEditQueued()
})
@@ -331,7 +335,14 @@ function onGlobalKeydown(e: KeyboardEvent) {
// Ctrl+R: 重新生成末条回复(替代浏览器刷新,Tauri 下 preventDefault 可靠)
if (ctrl && (e.key === 'r' || e.key === 'R')) {
e.preventDefault()
if (!store.state.streaming) store.regenerate()
// UX-P3: 末条非 assistant 等场景 regenerate() 会 reject(regenerateUnavailable),原样裸调
// 成 unhandled rejection 用户无感;对齐 MessageList.handleRetry 的 catch + toast。
if (!store.state.streaming) {
store.regenerate().catch((e: unknown) => {
const msg = e instanceof Error ? e.message : String(e)
showToast(t('aiChat.regenerateFailed', { msg }), 'error')
})
}
return
}
// Ctrl+L: 清空当前对话(带 confirm;生成中跳过避免删流式中消息)
@@ -510,9 +521,14 @@ async function handleSendQueuedNow(idx: number) {
* cancelQueued 内部经 activeQueueRealIndex 做过滤视图下标映射,越界 no-op;
* 项携带技能时按名找回 SkillInfo 回挂 chip,找不到(技能已卸载)只回填文本,
* 与队列原地编辑只保 text 同一取舍。 */
function backfillQueued(idx: number) {
async function backfillQueued(idx: number) {
const item = activeQueue.value[idx]
if (!item) return
// UX-P3: 输入框已有未发送草稿(文本/图片/技能 chip 任一非空)时回填会静默覆盖,
// 先 confirm 确认;取消则直接返回,队列项原样保留(尚未 cancelQueued)。
if (chatInputRef.value?.hasUnsentInput()) {
if (!await confirmDialog(t('aiChat.backfillOverwriteConfirm'))) return
}
const skill = item.skill
? store.state.skills.find(s => s.name === item.skill) ?? null
: null