Browse Source

feat(case): 打开案件时增加全屏 loading 与防重复点击

- 复用 useLoading,在 openCase 期间显示「正在打开案件…」/「正在打开「案件名」…」
- 打开期间禁用其它打开按钮并防止重复触发
- 成功、失败或页面卸载时关闭遮罩
cc 1 day ago
parent
commit
5f3385773d
1 changed files with 31 additions and 3 deletions
  1. 31 3
      ai-electron/frontend/src/plat/views/case/case.vue

+ 31 - 3
ai-electron/frontend/src/plat/views/case/case.vue

@@ -83,7 +83,12 @@
                   </p>
 
                   <div class="case-card__ops">
-                    <button class="case-card__open" type="button" @click="handleOpen(item.id!)">
+                    <button
+                      class="case-card__open"
+                      type="button"
+                      :disabled="openingCaseId !== null"
+                      @click="handleOpen(item.id!)"
+                    >
                       <FolderOpenOutlined />
                       打开案件
                     </button>
@@ -147,7 +152,7 @@
 </template>
 
 <script lang="ts" setup>
-  import { computed, onMounted, ref, toRaw } from 'vue';
+  import { computed, onBeforeUnmount, onMounted, ref, toRaw } from 'vue';
   import { Button, Modal, Spin, Tooltip } from 'ant-design-vue';
   import {
     CloseCircleOutlined,
@@ -162,6 +167,7 @@
   import { useMessage } from '@/core/hooks/web/useMessage';
   import { useUserStore } from '@/core/store/modules/case';
   import { useModal } from '@/core/components/Modal';
+  import { useLoading } from '@/core/components/Loading';
   import { EmptyState } from '@/core/components/EmptyState';
   import { AppHeader } from '@/core/components/Application';
   import { UserDropdown } from '@/core/layouts/default/header/components';
@@ -179,6 +185,11 @@
   const deleteModalVisible = ref(false);
   const deleteLoading = ref(false);
   const currentDeleteId = ref<number>(0);
+  /** 正在打开的案件 id:打开期间禁用其它打开操作并显示全局 loading */
+  const openingCaseId = ref<number | null>(null);
+  const [showOpeningLoading, hideOpeningLoading, setOpeningTip] = useLoading({
+    tip: '正在打开案件…',
+  });
 
   const [registerModal, { openModal }] = useModal();
 
@@ -196,6 +207,11 @@
     loadCaseList();
   });
 
+  onBeforeUnmount(() => {
+    // loading 挂在 document.body 上,页面卸载时要主动移除
+    hideOpeningLoading();
+  });
+
   function getCaseSortTime(item: CaseInfo) {
     const rawTime = item.createTime?.trim();
     if (!rawTime) return 0;
@@ -265,8 +281,17 @@
   }
 
   async function doOpenCase(id: number) {
+    // 打开案件要初始化数据源、重建路由并跳转,期间给一层全局 loading,避免界面像卡死
+    if (openingCaseId.value !== null) {
+      return false;
+    }
+
+    const matchedCase = caseList.value.find((item) => Number(item.id) === Number(id));
+    openingCaseId.value = id;
+    setOpeningTip(matchedCase?.name ? `正在打开「${matchedCase.name}」…` : '正在打开案件…');
+    showOpeningLoading();
+
     try {
-      const matchedCase = caseList.value.find((item) => Number(item.id) === Number(id));
       if (matchedCase?.name) {
         userStore.setPageCache('currentCaseName', matchedCase.name);
       }
@@ -291,6 +316,9 @@
       }
       console.log(error);
       return false;
+    } finally {
+      hideOpeningLoading();
+      openingCaseId.value = null;
     }
   }