Zimo пре 4 дана
родитељ
комит
f9e8938f20

+ 1 - 1
.env.local

@@ -4,7 +4,7 @@ NODE_ENV=development
 VITE_DEV=true
 
 # 请求路径  http://192.168.188.149:48080  https://iot.deepoil.cc
-VITE_BASE_URL='http://192.168.188.149:48080'
+VITE_BASE_URL='https://iot.deepoil.cc'
 
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
 VITE_UPLOAD_TYPE=server

+ 1 - 1
src/components/count-to1.vue

@@ -87,7 +87,7 @@ defineExpose({
 </script>
 
 <template>
-  <span>
+  <span class="flex">
     <span v-if="endVal">{{ value }}</span>
     <slot v-else></slot>
   </span>

+ 26 - 17
src/views/pms/iotrddailyreport/summary.vue

@@ -42,11 +42,10 @@ const totalWorkKeys: [string, string | undefined, string, string, number][] = [
     'i-material-symbols:directions-car-outline-rounded text-sky',
     2
   ],
-  ['taici', undefined, '台次', 'i-material-symbols:check-circle-outline-rounded text-emerald', 0],
   [
     'cumulativeBridgePlug',
     undefined,
-    '个数',
+    '桥塞',
     'i-material-symbols:check-circle-outline-rounded text-emerald',
     0
   ],
@@ -74,10 +73,18 @@ const totalWorkKeys: [string, string | undefined, string, string, number][] = [
   [
     'cumulativeHourCount',
     undefined,
-    'H',
+    '小时(H)',
     'i-material-symbols:nest-clock-farsight-analog-outline-rounded text-emerald',
     2
-  ]
+  ],
+  [
+    'cumulativeWaterVolume',
+    '方',
+    '水方量',
+    'i-material-symbols:water-drop-outline-rounded text-sky',
+    2
+  ],
+  ['taici', undefined, '台次', 'i-material-symbols:check-circle-outline-rounded text-emerald', 0]
 ]
 
 const totalWork = ref({
@@ -87,7 +94,8 @@ const totalWork = ref({
   cumulativeRunCount: 0,
   cumulativeWorkingWell: 0,
   cumulativeWorkingLayers: 0,
-  cumulativeHourCount: 0
+  cumulativeHourCount: 0,
+  cumulativeWaterVolume: 0
 })
 
 const totalLoading = ref(false)
@@ -120,6 +128,7 @@ const getTotal = useDebounceFn(async () => {
       cumulativeWorkingWell: res2.cumulativeWorkingWell || 0,
       cumulativeWorkingLayers: res2.cumulativeWorkingLayers || 0,
       cumulativeHourCount: res2.cumulativeHourCount || 0,
+      cumulativeWaterVolume: res2.cumulativeWaterVolume || 0,
       ...res2,
       cumulativeFuels: (res2.cumulativeFuels || 0) / 10000
     }
@@ -153,6 +162,10 @@ const columns = (type: string) => {
       label: type === '2' ? '项目部' : '队伍',
       prop: 'name'
     },
+    {
+      label: '油耗(万升)',
+      prop: 'totalDailyFuel'
+    },
     {
       label: '桥塞',
       prop: 'cumulativeBridgePlug'
@@ -166,20 +179,16 @@ const columns = (type: string) => {
       prop: 'cumulativeWorkingWell'
     },
     {
-      label: '小时(H)',
-      prop: 'cumulativeHourCount'
+      label: '段数',
+      prop: 'cumulativeWorkingLayers'
     },
     {
-      label: '油耗(万升)',
-      prop: 'totalDailyFuel'
+      label: '小时(H)',
+      prop: 'cumulativeHourCount'
     },
     {
       label: '水方量(方)',
       prop: 'cumulativeWaterVolume'
-    },
-    {
-      label: '段数',
-      prop: 'cumulativeWorkingLayers'
     }
   ]
 }
@@ -228,7 +237,7 @@ const tab = ref<'表格' | '看板'>('表格')
 
 const currentTab = ref<'表格' | '看板'>('表格')
 
-const deptName = ref('瑞恒兴域')
+const deptName = ref('四川瑞都')
 
 const direction = ref<'left' | 'right'>('right')
 
@@ -252,7 +261,7 @@ const legend = ref<string[][]>([
   ['个数', 'cumulativeBridgePlug'],
   ['井数', 'cumulativeWorkingWell'],
   ['小时 (H)', 'cumulativeHourCount'],
-  ['油耗 (万升)', 'totalDailyFuel'],
+  ['油耗 (万升)', 'cumulativeFuels'],
   ['水方量 (方)', 'cumulativeWaterVolume'],
   ['台次(泵车)', 'cumulativePumpTrips'],
   ['段数', 'cumulativeWorkingLayers'],
@@ -279,7 +288,7 @@ const getChart = useDebounceFn(async () => {
       cumulativeBridgePlug: res.map((item) => item.cumulativeBridgePlug || 0),
       cumulativeWorkingWell: res.map((item) => item.cumulativeWorkingWell || 0),
       cumulativeHourCount: res.map((item) => item.cumulativeHourCount || 0),
-      totalDailyFuel: res.map((item) => (item.totalDailyFuel || 0) / 10000),
+      cumulativeFuels: res.map((item) => (item.cumulativeFuels || 0) / 10000),
       cumulativeWaterVolume: res.map((item) => item.cumulativeWaterVolume || 0),
       cumulativeWorkingLayers: res.map((item) => item.cumulativeWorkingLayers || 0),
       cumulativePumpTrips: res.map((item) => item.cumulativePumpTrips || 0),
@@ -546,7 +555,7 @@ const tolist = (id: number) => {
           <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         </el-form-item>
       </el-form>
-      <div class="grid grid-cols-7 gap-8">
+      <div class="grid grid-cols-8 gap-8">
         <div
           v-for="info in totalWorkKeys"
           :key="info[0]"

+ 7 - 0
src/views/pms/iotrhdailyreport/summary.vue

@@ -123,6 +123,7 @@ interface List {
   cumulativePowerConsumption: number | null
   cumulativeFuelConsumption: number | null
   transitTime: number | null
+  nonProductiveTime: number | null
 }
 
 const list = ref<List[]>([])
@@ -168,6 +169,10 @@ const columns = (type: string) => {
       label: '平均时效(%)',
       prop: 'transitTime'
     },
+    {
+      label: '非生产时效(%)',
+      prop: 'nonProductiveTime'
+    },
     ...(type === '2' && checkIsSameDay(query.value.createTime)
       ? [
           {
@@ -196,6 +201,8 @@ const listLoading = ref(false)
 const formatter = (row: List, column: any) => {
   if (column.property === 'transitTime') {
     return (Number(row.transitTime ?? 0) * 100).toFixed(2) + '%'
+  } else if (column.property === 'nonProductiveTime') {
+    return (Number(row.nonProductiveTime ?? 0) * 100).toFixed(2) + '%'
   } else return row[column.property] ?? 0
 }
 

+ 7 - 0
src/views/pms/iotrydailyreport/summary.vue

@@ -117,6 +117,7 @@ interface List {
   cumulativePowerConsumption: number | null
   cumulativeFuelConsumption: number | null
   transitTime: number | null
+  nonProductiveTime: number | null
 }
 
 const list = ref<List[]>([])
@@ -144,6 +145,10 @@ const columns = (type: string) => {
     {
       label: '平均时效(%)',
       prop: 'transitTime'
+    },
+    {
+      label: '非生产时效(%)',
+      prop: 'nonProductiveTime'
     }
   ]
 }
@@ -153,6 +158,8 @@ const listLoading = ref(false)
 const formatter = (row: List, column: any) => {
   if (column.property === 'transitTime') {
     return (Number(row.transitTime ?? 0) * 100).toFixed(2) + '%'
+  } else if (column.property === 'nonProductiveTime') {
+    return (Number(row.nonProductiveTime ?? 0) * 100).toFixed(2) + '%'
   } else return row[column.property] ?? 0
 }
 

+ 7 - 0
src/views/pms/iotrydailyreport/xsummary.vue

@@ -119,6 +119,7 @@ interface List {
   cumulativePowerConsumption: number | null
   cumulativeFuelConsumption: number | null
   transitTime: number | null
+  nonProductiveTime: number | null
 }
 
 const list = ref<List[]>([])
@@ -150,6 +151,10 @@ const columns = (type: string) => {
     {
       label: '平均时效(%)',
       prop: 'transitTime'
+    },
+    {
+      label: '非生产时效(%)',
+      prop: 'nonProductiveTime'
     }
   ]
 }
@@ -159,6 +164,8 @@ const listLoading = ref(false)
 const formatter = (row: List, column: any) => {
   if (column.property === 'transitTime') {
     return (Number(row.transitTime ?? 0) * 100).toFixed(2) + '%'
+  } else if (column.property === 'nonProductiveTime') {
+    return (Number(row.nonProductiveTime ?? 0) * 100).toFixed(2) + '%'
   } else return row[column.property] ?? 0
 }
 

+ 83 - 28
src/views/report-statistics/costs.vue

@@ -13,6 +13,7 @@ interface Query {
   createTime?: [string, string]
   pageNo: number
   pageSize: number
+  type?: string
 }
 
 // 选项配置数组
@@ -58,15 +59,18 @@ interface StatItem {
   key: string
   title: string
   icon: string
+  type: string
   class: { bg1: string; bg2: string; text: string }
   value: number
-  trend: number
+  tb: number
+  hb: number
 }
 
 const defaultStats: StatItem[] = [
   {
     key: 'repair',
-    title: '维修成本',
+    title: '内部维修成本',
+    type: '维修',
     icon: 'i-material-symbols:home-repair-service-outline',
     class: {
       bg1: 'bg-[var(--el-color-success-light-7)]',
@@ -74,11 +78,13 @@ const defaultStats: StatItem[] = [
       text: 'text-[var(--el-color-success)]'
     },
     value: 0,
-    trend: 0
+    tb: 0,
+    hb: 0
   },
   {
     key: 'byFee',
     title: '保养成本',
+    type: '保养',
     icon: 'i-material-symbols:construction-rounded',
     class: {
       bg1: 'bg-[var(--el-color-primary-light-7)]',
@@ -86,11 +92,13 @@ const defaultStats: StatItem[] = [
       text: 'text-[var(--el-color-primary)]'
     },
     value: 0,
-    trend: 0
+    tb: 0,
+    hb: 0
   },
   {
     key: 'out',
     title: '委外维修',
+    type: '委外维修',
     icon: 'i-material-symbols:work-outline',
     class: {
       bg1: 'bg-[var(--el-color-warning-light-7)]',
@@ -98,7 +106,8 @@ const defaultStats: StatItem[] = [
       text: 'text-[var(--el-color-warning)]'
     },
     value: 0,
-    trend: 0
+    tb: 0,
+    hb: 0
   }
 ]
 
@@ -108,12 +117,23 @@ const dataLoading = ref(false)
 const loadData = useDebounceFn(async function () {
   dataLoading.value = true
   try {
-    const { pageNo, pageSize, ...other } = query.value
-    const res = await IotReportApi.getCostsFee(other)
-    statList.value.forEach((item) => {
-      item.value = res[item.key] || 0
-      item.trend = res[`${item.key}Trend`] || 0
-    })
+    const { pageNo, pageSize, type, ...other } = query.value
+    const res = await IotReportApi.getCostsFee({ ...other, timeType: activeTimeType.value })
+    const repair = statList.value[0]!
+    const out = statList.value[2]!
+    const byFee = statList.value[1]!
+
+    out.value = res[out.key].total || 0
+    out.tb = Number(((res[out.key].tb || 0) * 100).toFixed(0))
+    out.hb = Number(((res[out.key].hb || 0) * 100).toFixed(0))
+
+    repair.value = (res[repair.key].total ?? 0) - out.value
+    repair.tb = Number(((res[repair.key].tb || 0) * 100).toFixed(0))
+    repair.hb = Number(((res[repair.key].hb || 0) * 100).toFixed(0))
+
+    byFee.value = res[byFee.key].total || 0
+    byFee.tb = Number(((res[byFee.key].tb || 0) * 100).toFixed(0))
+    byFee.hb = Number(((res[byFee.key].hb || 0) * 100).toFixed(0))
   } catch (error) {
     console.log('error :>> ', error)
   } finally {
@@ -170,11 +190,17 @@ watch(
   },
   { immediate: true }
 )
+
+function selectType(type: string) {
+  query.value.type = type
+  query.value.pageNo = 1
+  loadList()
+}
 </script>
 
 <template>
   <div
-    class="grid grid-cols-[15%_1fr] grid-rows-[196px_1fr] gap-4 h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
+    class="grid grid-cols-[15%_1fr] grid-rows-[196px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
   >
     <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg row-span-2">
       <DeptTreeSelect
@@ -191,8 +217,9 @@ watch(
         <section
           v-for="item in statList"
           :key="item.key"
-          class="flex flex-col items-center gap-y-4 rounded-lg shadow p-4"
-          :class="item.class.bg1"
+          class="flex flex-col items-center gap-y-4 rounded-lg shadow p-4 transition-transform hover:scale-105 duration-500"
+          :class="{ [item.class.bg1]: true, 'scale-105': item.type === query.type }"
+          @click="selectType(item.type)"
         >
           <!-- 头部:图标 + 标题 -->
           <div class="flex items-center gap-x-3">
@@ -210,6 +237,8 @@ watch(
             :start-val="0"
             :end-val="item.value"
             :decimals="2"
+            suffix="元"
+            :duration="1000"
           >
             <!-- 插槽内容:当数据为空或0时的显示 (根据 count-to 组件的具体实现决定是否显示) -->
             <span class="text-xs leading-8 text-[var(--el-text-color-regular)]">暂无数据</span>
@@ -217,20 +246,41 @@ watch(
 
           <!-- 底部:环比数据 -->
           <!-- 根据 trend 正负动态改变图标和颜色 -->
-          <div class="mt-2 flex items-center gap-x-1 text-xs font-medium" :class="item.class.text">
-            <!-- 动态图标:大于等于0向上,小于0向下 -->
+          <div class="mt-2 flex items-center gap-x-4">
             <div
-              :class="
-                item.trend >= 0
-                  ? 'i-material-symbols:arrow-warm-up-rounded'
-                  : 'i-material-symbols:arrow-cool-down-rounded'
-              "
-            ></div>
-
-            <span class="vertical-middle">
-              {{ item.trend > 0 ? '+' + item.trend : item.trend }}
-            </span>
-            <span>环比</span>
+              v-show="item.hb"
+              class="flex items-center gap-x-1 text-xs font-medium"
+              :class="item.class.text"
+            >
+              <!-- 动态图标:大于等于0向上,小于0向下 -->
+              <div
+                :class="
+                  item.hb >= 0
+                    ? 'i-material-symbols:arrow-warm-up-rounded'
+                    : 'i-material-symbols:arrow-cool-down-rounded'
+                "
+              ></div>
+
+              <span class="vertical-middle"> {{ item.hb > 0 ? '+' + item.hb : item.hb }}% </span>
+              <span>环比</span>
+            </div>
+            <div
+              v-show="item.tb"
+              class="flex items-center gap-x-1 text-xs font-medium"
+              :class="item.class.text"
+            >
+              <!-- 动态图标:大于等于0向上,小于0向下 -->
+              <div
+                :class="
+                  item.tb >= 0
+                    ? 'i-material-symbols:arrow-warm-up-rounded'
+                    : 'i-material-symbols:arrow-cool-down-rounded'
+                "
+              ></div>
+
+              <span class="vertical-middle"> {{ item.tb > 0 ? '+' + item.tb : item.tb }}% </span>
+              <span>同比</span>
+            </div>
           </div>
         </section>
       </div>
@@ -265,7 +315,12 @@ watch(
               <el-table-column label="类别" prop="type" align="center" />
               <el-table-column label="设备编号" prop="deviceCode" align="center" />
               <el-table-column label="设备名称" prop="deviceName" align="center" />
-              <el-table-column label="成本" prop="cost" align="center" />
+              <el-table-column
+                label="成本"
+                prop="cost"
+                align="center"
+                :formatter="(row) => (row.cost ?? 0) + '元'"
+              />
             </el-table>
           </template>
         </el-auto-resizer>

+ 4 - 4
src/views/report-statistics/daily-report.vue

@@ -434,7 +434,7 @@ const expandRowKeys = computed(() => {
 
 <template>
   <div
-    class="grid grid-cols-[15%_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
+    class="grid grid-cols-[15%_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
   >
     <el-form
       size="default"
@@ -530,9 +530,9 @@ const expandRowKeys = computed(() => {
                     <el-tag size="default">累计注水量(方): {{ row.groupIdWaterInjection }} </el-tag>
                     <el-tag size="default">累计用电量(kWh) : {{ row.groupIdPower }} </el-tag>
                     <el-tag size="default">累计油耗(L) : {{ row.groupIdFuel }} </el-tag>
-                    <el-tag size="default">累计注气时间H : {{ row.groupIdGasTime }} </el-tag>
-                    <el-tag size="default"
-                      >累计非生产时间H : {{ row.groupIdNoProductTime }}
+                    <el-tag size="default">累计注气时间(H) : {{ row.groupIdGasTime }} </el-tag>
+                    <el-tag size="default">
+                      累计非生产时间(H) : {{ row.groupIdNoProductTime }}
                     </el-tag>
                   </div>
                 </template>

+ 1 - 1
src/views/report-statistics/rd-daily-report.vue

@@ -370,7 +370,7 @@ const expandRowKeys = computed(() => {
 
 <template>
   <div
-    class="grid grid-cols-[15%_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
+    class="grid grid-cols-[15%_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
   >
     <el-form
       size="default"

+ 1 - 1
src/views/report-statistics/ry-daily-report.vue

@@ -553,7 +553,7 @@ const expandRowKeys = computed(() => {
 
 <template>
   <div
-    class="grid grid-cols-[15%_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
+    class="grid grid-cols-[15%_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
   >
     <el-form
       size="default"

+ 96 - 49
src/views/report-statistics/work-order-completion.vue

@@ -12,6 +12,7 @@ type TimeType = 'year' | 'month' | 'day'
 interface Query {
   deptId?: number
   createTime?: [string, string]
+  type?: string
   pageNo: number
   pageSize: number
 }
@@ -24,10 +25,12 @@ interface ChartDataItem {
 interface StatItem {
   key: string
   title: string
+  type: string
   icon: string
   total: number
   charts: ChartDataItem[]
-  trend: number
+  tb: number
+  hb: number
 }
 
 // 选项配置数组
@@ -47,42 +50,52 @@ const defaultStats: StatItem[] = [
   {
     key: 'yx',
     title: '运行记录',
+    type: '运行记录',
     icon: 'i-material-symbols:list-alt-outline',
     total: 0,
     charts: [],
-    trend: 0
+    tb: 0,
+    hb: 0
   },
   {
     key: 'rb',
     title: '生产日报',
+    type: '日报',
     icon: 'i-material-symbols:calendar-today-outline',
     total: 0,
     charts: [],
-    trend: 0
+    tb: 0,
+    hb: 0
   },
   {
     key: 'wx',
     title: '维修工单',
+    type: '维修工单',
     icon: 'i-material-symbols:home-repair-service-outline',
     total: 0,
     charts: [],
-    trend: 0
+    tb: 0,
+    hb: 0
   },
   {
     key: 'by',
     title: '保养工单',
+    type: '保养工单',
     icon: 'i-material-symbols:construction-rounded',
     total: 0,
     charts: [],
-    trend: 0
+    tb: 0,
+    hb: 0
   },
   {
     key: 'xj',
     title: '巡检工单',
+    type: '巡检工单',
     icon: 'i-material-symbols:warning-outline',
     total: 0,
     charts: [],
-    trend: 0
+    tb: 0,
+    hb: 0
   }
 ]
 
@@ -141,18 +154,22 @@ const labelMap = {
 const loadData = useDebounceFn(async function () {
   dataLoading.value = true
 
-  const { pageNo, pageSize, ...other } = query.value
+  const { pageNo, pageSize, type, ...other } = query.value
 
-  const res = await IotReportApi.getOrderNumber(other)
+  const res = await IotReportApi.getOrderNumber({ ...other, timeType: activeTimeType.value })
 
   statList.value.forEach((item) => {
-    const data = res[item.key] || []
-
-    item.total = data.reduce((acc, cur) => acc + cur.num, 0)
-    item.charts = data.map((d) => ({
-      label: labelMap[item.key + d.status],
-      num: d.num
-    }))
+    const data = res[item.key] ?? {}
+
+    item.total = data.total?.total ?? 0
+    item.tb = data.total?.tb ?? 0
+    item.hb = data.total?.hb ?? 0
+    item.charts = data.status
+      .filter((d) => d.num !== 0)
+      .map((d) => ({
+        label: labelMap[item.key + d.status],
+        num: d.num
+      }))
   })
 
   dataLoading.value = false
@@ -219,11 +236,17 @@ watch(
   },
   { immediate: true }
 )
+
+function selectType(type: string) {
+  query.value.type = type
+  query.value.pageNo = 1
+  loadList()
+}
 </script>
 
 <template>
   <div
-    class="grid grid-cols-[15%_1fr] grid-rows-[196px_1fr] gap-4 h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
+    class="grid grid-cols-[15%_1fr] grid-rows-[208px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
   >
     <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg row-span-2">
       <DeptTreeSelect
@@ -234,48 +257,72 @@ watch(
         :show-title="false"
       />
     </div>
-    <div class="flex flex-col gap-4 h-full overflow-hidden">
-      <div class="grid grid-cols-1 md:grid-cols-3 xl:grid-cols-5 gap-4" v-loading="dataLoading">
+    <div class="flex flex-col gap-4 h-full">
+      <div
+        class="grid grid-cols-1 md:grid-cols-3 xl:grid-cols-5 gap-4 flex-1"
+        v-loading="dataLoading"
+      >
         <section
           v-for="item in statList"
           :key="item.key"
-          class="bg-white dark:bg-[#1d1e1f] rounded-xl shadow flex justify-between items-stretch min-h-[140px] border border-gray-200 dark:border-gray-700/50 relative overflow-hidden group transition-colors duration-300"
+          class="bg-white dark:bg-[#1d1e1f] rounded-xl shadow flex justify-between items-stretch min-h-[140px] border border-gray-200 dark:border-gray-700/50 relative overflow-hidden group transition-colors duration-300 transition-transform hover:scale-105 duration-500"
+          :class="{ 'scale-105': item.type === query.type }"
+          @click="selectType(item.type)"
         >
-          <!-- 左侧:文字信息 -->
-          <div class="flex flex-col justify-between z-10 p-4 pr-0">
-            <div>
-              <!-- 标题:白底深灰,黑底浅灰 -->
-              <div class="text-gray-500 dark:text-gray-400 text-sm font-medium mb-1">
-                {{ item.title }}
-              </div>
-              <!-- 数值:白底黑色,黑底白色 -->
-              <div class="text-3xl font-bold tracking-tight text-gray-900! dark:text-white! mt-1">
-                <count-to :start-val="0" :end-val="item.total" :duration="100" />
-              </div>
+          <div class="flex flex-col justify-between z-10 p-4 pb-2 pr-0 gap-1">
+            <div class="text-gray-500 dark:text-gray-400 text-sm font-medium">
+              {{ item.title }}
             </div>
-
-            <!-- 环比 -->
-            <div class="flex items-center gap-2 mt-2">
-              <!-- 标签:针对亮色/暗色分别设置背景和文字颜色 -->
-              <div
-                class="px-2 py-0.5 rounded text-xs font-bold flex items-center space-x-1"
-                :class="
-                  item.trend >= 0
-                    ? 'bg-emerald-100 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-400'
-                    : 'bg-rose-100 text-rose-600 dark:bg-rose-500/20 dark:text-rose-400'
-                "
-              >
+            <div class="text-3xl font-bold tracking-tight text-gray-900! dark:text-white! mt-2">
+              <count-to :start-val="0" :end-val="item.total" :duration="100">
+                <span class="text-xs leading-9 text-[var(--el-text-color-regular)]">
+                  暂无数据
+                </span>
+              </count-to>
+            </div>
+            <div class="flex flex-col gap-2 w-24">
+              <div v-show="item.tb !== 0" class="flex items-center gap-1">
+                <div
+                  class="px-2 py-0.5 rounded text-xs font-bold flex items-center space-x-1"
+                  :class="
+                    item.tb >= 0
+                      ? 'bg-emerald-100 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-400'
+                      : 'bg-rose-100 text-rose-600 dark:bg-rose-500/20 dark:text-rose-400'
+                  "
+                >
+                  <div
+                    :class="
+                      item.tb >= 0
+                        ? 'i-material-symbols:trending-up'
+                        : 'i-material-symbols:trending-down'
+                    "
+                    class="text-sm"
+                  ></div>
+                  <span>{{ Math.abs(item.hb) }}%</span>
+                </div>
+                <span class="w-6 text-xs text-gray-500 dark:text-gray-400">同比</span>
+              </div>
+              <div v-show="item.hb !== 0" class="flex items-center gap-1">
                 <div
+                  class="px-2 py-0.5 rounded text-xs font-bold flex items-center space-x-1"
                   :class="
-                    item.trend >= 0
-                      ? 'i-material-symbols:trending-up'
-                      : 'i-material-symbols:trending-down'
+                    item.hb >= 0
+                      ? 'bg-emerald-100 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-400'
+                      : 'bg-rose-100 text-rose-600 dark:bg-rose-500/20 dark:text-rose-400'
                   "
-                  class="text-sm"
-                ></div>
-                <span>{{ Math.abs(item.trend) }}%</span>
+                >
+                  <div
+                    :class="
+                      item.hb >= 0
+                        ? 'i-material-symbols:trending-up'
+                        : 'i-material-symbols:trending-down'
+                    "
+                    class="text-sm"
+                  ></div>
+                  <span>{{ Math.abs(item.hb) }}%</span>
+                </div>
+                <span class="min-w-8 text-xs text-gray-500 dark:text-gray-400">环比</span>
               </div>
-              <span class="text-xs text-gray-500 dark:text-gray-400">环比</span>
             </div>
           </div>