yanghao 3 дней назад
Родитель
Сommit
4973e8e637
2 измененных файлов с 70 добавлено и 55 удалено
  1. 1 0
      components.d.ts
  2. 69 55
      src/views/flow/index.vue

+ 1 - 0
components.d.ts

@@ -26,6 +26,7 @@ declare module 'vue' {
     ElInput: typeof import('element-plus/es')['ElInput']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
     ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
+    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']

+ 69 - 55
src/views/flow/index.vue

@@ -28,53 +28,51 @@
     <!-- 任务统计 -->
     <!-- 任务统计 -->
     <section class="total">
     <section class="total">
       <div class="total-card" v-for="(item, index) in stats" :key="index">
       <div class="total-card" v-for="(item, index) in stats" :key="index">
-        <el-skeleton
-          :rows="1"
-          :animated="true"
-          class="w-full"
-          v-if="item.number === 0"
+        <el-popover
+          placement="top"
+          :width="200"
+          trigger="hover"
+          popper-class="glass-popover"
+          :disabled="getDetailList(index).length === 0"
+          raw-content
+          transition="el-zoom-in-top"
         >
         >
-          <el-popover
-            placement="top"
-            :width="200"
-            trigger="hover"
-            popper-class="glass-popover"
-            :disabled="getDetailList(index).length === 0"
-            raw-content
-            transition="el-zoom-in-top"
-          >
-            <template #reference>
-              <div class="card-wrapper">
-                <!-- ... 图标和内容 ... -->
-                <div
-                  class="card-icon"
-                  :style="{ backgroundColor: item.bgcolor }"
-                >
-                  <Icon :icon="item.icon" :color="item.color" />
-                </div>
-                <div class="card-content">
-                  <p class="card-title">{{ item.title }}</p>
-                  <p class="card-number">{{ item.number }}</p>
-                </div>
-              </div>
-            </template>
-
-            <div class="detail-list">
-              <div
-                v-for="(task, idx) in getDetailList(index)"
-                :key="idx"
-                class="detail-item"
-                @click="handleDetailClick(task, item.title)"
-              >
-                <span class="detail-name">{{ task.name }}</span>
-                <span class="detail-val">{{ task.value }}</span>
+          <template #reference>
+            <div class="card-wrapper">
+              <!-- ... 图标和内容 ... -->
+              <div class="card-icon" :style="{ backgroundColor: item.bgcolor }">
+                <Icon :icon="item.icon" :color="item.color" />
               </div>
               </div>
-              <div v-if="getDetailList(index).length === 0" class="empty-tip">
-                暂无详细数据
+              <div class="card-content">
+                <p class="card-title">{{ item.title }}</p>
+                <el-skeleton :rows="1" :animated="true" :loading="statsLoading">
+                  <template #template>
+                    <el-skeleton-item
+                      variant="text"
+                      style="width: 60%; height: 32px; border-radius: 50px"
+                    />
+                  </template>
+                  <p class="card-number">{{ item.number }}</p>
+                </el-skeleton>
               </div>
               </div>
             </div>
             </div>
-          </el-popover>
-        </el-skeleton>
+          </template>
+
+          <div class="detail-list">
+            <div
+              v-for="(task, idx) in getDetailList(index)"
+              :key="idx"
+              class="detail-item"
+              @click="handleDetailClick(task, item.title)"
+            >
+              <span class="detail-name">{{ task.name }}</span>
+              <span class="detail-val">{{ task.value }}</span>
+            </div>
+            <div v-if="getDetailList(index).length === 0" class="empty-tip">
+              暂无详细数据
+            </div>
+          </div>
+        </el-popover>
       </div>
       </div>
     </section>
     </section>
 
 
@@ -462,6 +460,7 @@ const handleDetailClick = (task, categoryTitle) => {
 
 
 let oaTasks = ref([]);
 let oaTasks = ref([]);
 let crmTasks = ref([]);
 let crmTasks = ref([]);
+const statsLoading = ref(true);
 
 
 const stats = ref([
 const stats = ref([
   {
   {
@@ -538,11 +537,24 @@ onMounted(async () => {
   });
   });
 
 
   if (userStore.getUser.username) {
   if (userStore.getUser.username) {
-    const res = await getOATasks(userStore.getUser.username);
-    oaTasks.value = res;
+    try {
+      const res = await getOATasks(userStore.getUser.username);
+      oaTasks.value = res;
+
+      const crmRes = await getCRMTasks(userStore.getUser.username);
+      crmTasks.value = crmRes;
+
+      stats.value[0].number =
+        Number(oaTasks.value.todoCount) + Number(crmTasks.value.todoCount);
+
+      todoCount.value = [
+        { name: "OA", value: oaTasks.value.todoCount ?? 0 },
+        { name: "CRM", value: crmTasks.value.todoCount ?? 0 },
+      ];
+    } finally {
+      statsLoading.value = false;
+    }
 
 
-    const crmRes = await getCRMTasks(userStore.getUser.username);
-    crmTasks.value = crmRes;
     setInterval(
     setInterval(
       async () => {
       async () => {
         const res = await getOATasks(userStore.getUser.username);
         const res = await getOATasks(userStore.getUser.username);
@@ -550,18 +562,20 @@ onMounted(async () => {
 
 
         const crmRes = await getCRMTasks(userStore.getUser.username);
         const crmRes = await getCRMTasks(userStore.getUser.username);
         crmTasks.value = crmRes;
         crmTasks.value = crmRes;
+
+        stats.value[0].number =
+          Number(oaTasks.value.todoCount) + Number(crmTasks.value.todoCount);
+
+        todoCount.value = [
+          { name: "OA", value: oaTasks.value.todoCount ?? 0 },
+          { name: "CRM", value: crmTasks.value.todoCount ?? 0 },
+        ];
       },
       },
       5 * 60 * 1000,
       5 * 60 * 1000,
     ); // 每5分钟刷新一次
     ); // 每5分钟刷新一次
+  } else {
+    statsLoading.value = false;
   }
   }
-
-  stats.value[0].number =
-    Number(oaTasks.value.todoCount) + Number(crmTasks.value.todoCount);
-
-  todoCount.value = [
-    { name: "OA", value: oaTasks.value.todoCount },
-    { name: "CRM", value: crmTasks.value.todoCount },
-  ];
 });
 });
 
 
 // 组件卸载时移除监听,防止内存泄漏
 // 组件卸载时移除监听,防止内存泄漏