Jelajahi Sumber

feat(tabs): 实现标签页右键刷新功能

- tabs store 添加 tabRefreshTrigger 状态和 triggerTabRefresh 方法
- 页面标签页通过组件 key 变化强制重新渲染
- 浏览器标签页通过 defineExpose 暴露 reload 方法
- MainLayout 中根据标签页类型调用不同的刷新逻辑

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Ethanfly 19 jam lalu
induk
melakukan
68fc47de8a

+ 5 - 0
client/src/components/BrowserTab.vue

@@ -4207,6 +4207,11 @@ watch(() => props.tab.id, () => {
   stopAutoCheck();
   stopAIAnalysis();
 });
+
+// 暴露方法给父组件调用
+defineExpose({
+  reload,
+});
 </script>
 
 <style lang="scss" scoped>

+ 19 - 7
client/src/layouts/MainLayout.vue

@@ -244,17 +244,18 @@
               class="tab-content-item"
             >
               <!-- 浏览器标签页 -->
-              <BrowserTab 
-                v-if="tab.type === 'browser'" 
+              <BrowserTab
+                v-if="tab.type === 'browser'"
+                :ref="(el: any) => { if (el) browserTabRefs[tab.id] = el }"
                 :tab="tab"
                 @account-saved="handleAccountSaved"
                 @close="tabsStore.closeTab(tab.id)"
               />
               <!-- 页面标签页 -->
-              <component 
+              <component
                 v-else-if="tab.type === 'page' && getPageComponent(tab.path || '')"
                 :is="getPageComponent(tab.path || '')"
-                :key="tab.path"
+                :key="`${tab.path}-${tabsStore.tabRefreshTrigger[tab.id] || 0}`"
               />
             </div>
           </template>
@@ -375,6 +376,9 @@ const tabsStore = useTabsStore();
 // 窗口状态
 const isMaximized = ref(false);
 
+// 浏览器标签页的 ref 引用(用于刷新)
+const browserTabRefs = ref<Record<string, { reload: () => void }>>({});
+
 // 关闭按钮右键菜单
 const closeMenuVisible = ref(false);
 const closeMenuX = ref(0);
@@ -597,11 +601,19 @@ function closeContextMenu() {
 }
 
 function handleRefreshTab() {
-  // 刷新标签页(重新加载组件)
+  // 刷新标签页
   const tab = contextMenu.value.tab;
   if (tab) {
-    // 可以通过 key 变化来强制重新渲染
-    // 这里简单处理,只是关闭菜单
+    if (tab.type === 'browser') {
+      // 浏览器标签页:调用 reload 方法
+      const browserTab = browserTabRefs.value[tab.id];
+      if (browserTab) {
+        browserTab.reload();
+      }
+    } else {
+      // 页面标签页:通过触发器强制重新渲染
+      tabsStore.triggerTabRefresh(tab.id);
+    }
   }
   closeContextMenu();
 }

+ 17 - 1
client/src/stores/tabs.ts

@@ -54,6 +54,9 @@ export const useTabsStore = defineStore('tabs', () => {
   
   // 账号列表刷新计数器(当计数器变化时,Accounts 页面会刷新)
   const accountRefreshTrigger = ref(0);
+
+  // 标签页刷新计数器(用于触发标签页刷新)
+  const tabRefreshTrigger = ref<Record<string, number>>({});
   
   // 当前激活的标签页
   const activeTab = computed(() => 
@@ -278,12 +281,23 @@ export const useTabsStore = defineStore('tabs', () => {
   function triggerAccountRefresh() {
     accountRefreshTrigger.value++;
   }
-  
+
+  // 触发标签页刷新
+  function triggerTabRefresh(tabId: string) {
+    tabRefreshTrigger.value[tabId] = (tabRefreshTrigger.value[tabId] || 0) + 1;
+  }
+
+  // 获取标签页刷新触发器
+  function getTabRefreshTrigger(tabId: string) {
+    return computed(() => tabRefreshTrigger.value[tabId] || 0);
+  }
+
   return {
     // 状态
     tabs,
     activeTabId,
     accountRefreshTrigger,
+    tabRefreshTrigger,
     // 计算属性
     activeTab,
     browserTabs,
@@ -303,5 +317,7 @@ export const useTabsStore = defineStore('tabs', () => {
     findTabBySessionId,
     getActivePagePath,
     triggerAccountRefresh,
+    triggerTabRefresh,
+    getTabRefreshTrigger,
   };
 });