修复: 审批浮窗 3 bug(打开面板权限/审批后空转自关/关闭顺序)
This commit is contained in:
+28
-13
@@ -30,7 +30,8 @@
|
||||
<!-- 待审批列表 -->
|
||||
<div class="popup-body">
|
||||
<div v-if="approvals.length === 0" class="popup-empty">
|
||||
<span class="popup-empty-spinner"></span>
|
||||
<!-- BUG2 修复:空态不再永久转圈(原 popup-empty-spinner 致「处理完仍转圈」误判卡死)。
|
||||
空态正常会被 maybeAutoClose 即时关窗;此 hint 仅作防御性兜底(close 失败时给可见反馈)。 -->
|
||||
<span class="popup-empty-hint">{{ $t('aiChat.popupEmptyHint') }}</span>
|
||||
</div>
|
||||
<div
|
||||
@@ -144,6 +145,8 @@ onMounted(async () => {
|
||||
ApprovalPopupEvents.EVT_UPDATE,
|
||||
(e) => {
|
||||
approvals.value = e.payload?.approvals || []
|
||||
// BUG2 修复:主窗口推空快照(所有 pending 已清)→ 立即关浮窗,避免停留在空态转圈
|
||||
void maybeAutoClose()
|
||||
},
|
||||
)
|
||||
} catch (e) {
|
||||
@@ -175,6 +178,8 @@ async function onApprove(tc: AiToolCallInfo) {
|
||||
}
|
||||
// 乐观移除(主窗口 listener 收后端 emit 后会推新快照覆盖,此乐观仅缩短视觉延迟)
|
||||
approvals.value = approvals.value.filter(a => a.id !== tc.id)
|
||||
// BUG2 修复:乐观移除后若列表空,立即关浮窗(避免空列表停留在 popup-empty 永久转圈态)
|
||||
await maybeAutoClose()
|
||||
} catch (e) {
|
||||
console.error('[ApprovalPopup] 批准失败:', e)
|
||||
} finally {
|
||||
@@ -193,6 +198,7 @@ async function onReject(tc: AiToolCallInfo) {
|
||||
await aiApi.approve(tc.id, false)
|
||||
}
|
||||
approvals.value = approvals.value.filter(a => a.id !== tc.id)
|
||||
await maybeAutoClose()
|
||||
} catch (e) {
|
||||
console.error('[ApprovalPopup] 拒绝失败:', e)
|
||||
} finally {
|
||||
@@ -200,6 +206,20 @@ async function onReject(tc: AiToolCallInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 列表清空时自动关浮窗。
|
||||
* 场景:用户处理完最后一条审批 / 主窗口推空快照(EVT_UPDATE approvals:[])。
|
||||
* 修复 BUG2:原实现空列表渲染 popup-empty + 永久 popup-empty-spinner,用户看到「列表空 + 一直转」
|
||||
* 误以为卡死。空 = 完成,应即时关浮窗(不等待主窗口 watch closePopup 的跨窗口往返)。 */
|
||||
async function maybeAutoClose() {
|
||||
if (approvals.value.length > 0) return
|
||||
try {
|
||||
const { emit } = await import('@tauri-apps/api/event')
|
||||
// 先关窗(确保用户立刻看到反馈),再 emit 清主窗口引用(顺序与 onClose 一致)
|
||||
await getCurrentWebviewWindow().close()
|
||||
await emit(ApprovalPopupEvents.EVT_CLOSED, {})
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
/** 点击「打开审批面板」:emit 主窗口聚焦 + togglePanel */
|
||||
async function onActivate() {
|
||||
try {
|
||||
@@ -208,12 +228,17 @@ async function onActivate() {
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
/** 关闭浮窗(用户主动关 → emit closed 让主窗口清引用,允许下次有新审批再弹) */
|
||||
/** 关闭浮窗(用户主动关 → emit closed 让主窗口清引用,允许下次有新审批再弹)
|
||||
* 修复 BUG3:原顺序 emit→close,若 emit 跨窗口分发阻塞/异常(close 永不执行)→ 关闭按钮「无效」。
|
||||
* 改为先 close(即时反馈,core:window:allow-close 已授权),再 emit 清主窗口引用;
|
||||
* 即便 emit 失败,主窗口 win.once('tauri://destroyed') 也会清 _popupWin(双保险)。 */
|
||||
async function onClose() {
|
||||
try {
|
||||
await getCurrentWebviewWindow().close()
|
||||
} catch { /* ignore */ }
|
||||
try {
|
||||
const { emit } = await import('@tauri-apps/api/event')
|
||||
await emit(ApprovalPopupEvents.EVT_CLOSED, {})
|
||||
await getCurrentWebviewWindow().close()
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
@@ -323,16 +348,6 @@ function onDragEnd() { isDragging.value = false }
|
||||
min-height: 80px;
|
||||
padding: 16px;
|
||||
}
|
||||
.popup-empty-spinner {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: 2px solid var(--df-border, #444);
|
||||
border-top-color: var(--df-accent);
|
||||
border-radius: 50%;
|
||||
animation: df-spin 0.8s linear infinite;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.popup-empty-hint {
|
||||
font-size: 11px;
|
||||
color: var(--df-text-dim);
|
||||
|
||||
Reference in New Issue
Block a user