Ver Fonte

月报汇总

yanghao há 3 dias atrás
pai
commit
b3c0424b3c

+ 6 - 5
src/views/pms/qhse/monthlyReport/MonthlyReportAdd.vue

@@ -416,7 +416,7 @@
             <span>其他信息</span>
           </div>
         </template>
-        <el-row :gutter="16">
+        <!-- <el-row :gutter="16">
           <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
             <el-form-item label="工单填报人" prop="dutyPerson">
               <el-select
@@ -433,7 +433,7 @@
               </el-select>
             </el-form-item>
           </el-col>
-        </el-row>
+        </el-row> -->
         <el-row :gutter="16">
           <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
             <el-form-item label="备注" prop="remark">
@@ -568,13 +568,14 @@ const handleSubmit = async () => {
   // 校验表单
   const valid = await formRef.value.validate()
   if (!valid) return
-
+  reportInfo.dutyPerson = userInfo.value.id
   submitLoading.value = true
   try {
     await QhseMonthReportApi.updateQhseMonthReport(reportInfo)
-    message.success('新增成功')
+    message.success('提交成功')
     // 返回列表页或上一页
-    router.back()
+    delView(unref(router.currentRoute))
+    router.push({ name: 'QhseMonthlyReport', params: {} })
   } catch (error) {
     console.error('提交失败:', error)
   } finally {

+ 265 - 0
src/views/pms/qhse/reportSummary/index.vue

@@ -0,0 +1,265 @@
+<script lang="ts" setup>
+import { QhseMonthReportApi } from '@/api/pms/qhse'
+import { useTableComponents } from '@/components/ZmTable/useTableComponents'
+import QhseMonthReportPreviewDrawer from './preview-drawer.vue'
+import type { QhseMonthReportItem, QhseMonthReportListItem } from './types'
+import dayjs from 'dayjs'
+
+const loading = ref(false)
+const list = ref<QhseMonthReportListItem[]>([])
+const total = ref(0)
+const visible = ref(false)
+const currentId = ref<number>()
+
+const queryFormRef = ref()
+const queryParams = reactive({
+  title: '',
+  createTime: undefined as string[] | undefined
+})
+const pagination = reactive({
+  pageNo: 1,
+  pageSize: 10
+})
+
+const { ZmTable, ZmTableColumn } = useTableComponents<QhseMonthReportListItem>()
+
+async function getList() {
+  loading.value = true
+  try {
+    const res = await QhseMonthReportApi.getQhseMonthReportPage({
+      ...queryParams,
+      pageNo: pagination.pageNo,
+      pageSize: pagination.pageSize
+    })
+    list.value = res?.list || []
+    total.value = res?.total || 0
+  } finally {
+    loading.value = false
+  }
+}
+
+function handleQuery() {
+  pagination.pageNo = 1
+  getList()
+}
+
+function resetQuery() {
+  queryFormRef.value?.resetFields()
+  pagination.pageNo = 1
+  getList()
+}
+
+function handleView(row: QhseMonthReportItem) {
+  currentId.value = row.id
+  visible.value = true
+}
+
+function handleSizeChange(pageSize: number) {
+  pagination.pageSize = pageSize
+  pagination.pageNo = 1
+  getList()
+}
+
+function handleCurrentChange(pageNo: number) {
+  pagination.pageNo = pageNo
+  getList()
+}
+
+function formatDate(value?: string | number | Date) {
+  if (!value) return '-'
+  const date = dayjs(value)
+  return date.isValid() ? date.format('YYYY-MM-DD') : '-'
+}
+
+onMounted(() => {
+  getList()
+})
+</script>
+
+<template>
+  <div
+    class="report-summary-page min-w-0 overflow-x-hidden grid grid-rows-[auto_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
+    <el-form
+      ref="queryFormRef"
+      :model="queryParams"
+      inline
+      label-position="left"
+      class="report-summary-query min-w-0 overflow-hidden rounded-lg bg-white p-4 shadow dark:bg-[#1d1e1f]">
+      <el-form-item label="月报标题" prop="title">
+        <el-input v-model="queryParams.title" placeholder="请输入月报标题" clearable />
+      </el-form-item>
+      <el-form-item label="创建日期" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          type="daterange"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          class="!w-300px" />
+      </el-form-item>
+      <el-form-item class="report-summary-query__actions">
+        <el-button type="primary" @click="handleQuery">搜索</el-button>
+        <el-button @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <div class="report-summary-data-panel bg-white dark:bg-[#1d1e1f] shadow rounded-lg flex flex-col p-4 min-h-0">
+      <div class="flex-1 min-h-0 relative">
+        <el-auto-resizer class="report-summary-table-view absolute">
+          <template #default="{ width, height }">
+            <zm-table
+              :data="list"
+              :loading="loading"
+              :width="width"
+              :max-height="height"
+              :height="height"
+              show-border>
+              <ZmTableColumn label="月报标题" prop="title" :min-width="260" />
+              <ZmTableColumn label="工单填报人" prop="personName" width="160" />
+              <ZmTableColumn
+                label="创建日期"
+                prop="createTime"
+                cover-formatter
+                :real-value="({ createTime }) => formatDate(createTime)"
+                width="160" />
+              <ZmTableColumn label="操作" width="100" fixed="right">
+                <template #default="{ row }">
+                  <el-button size="default" link type="success" @click="handleView(row)">
+                    查看
+                  </el-button>
+                </template>
+              </ZmTableColumn>
+            </zm-table>
+          </template>
+        </el-auto-resizer>
+
+        <div v-loading="loading" class="report-summary-card-view">
+          <template v-if="list.length">
+            <article v-for="item in list" :key="item.id" class="report-summary-card">
+              <div class="report-summary-card__title">
+                <span>月报标题</span>
+                <strong>{{ item.title || '-' }}</strong>
+              </div>
+              <div class="report-summary-card__field">
+                <span>填报人</span>
+                <strong>{{ item.personName || '-' }}</strong>
+              </div>
+              <div class="report-summary-card__field">
+                <span>创建日期</span>
+                <strong>{{ formatDate(item.createTime) }}</strong>
+              </div>
+              <div class="report-summary-card__actions">
+                <el-button size="default" link type="success" @click="handleView(item)">
+                  查看
+                </el-button>
+              </div>
+            </article>
+          </template>
+          <el-empty v-else description="暂无数据" :image-size="80" />
+        </div>
+      </div>
+
+      <div class="mt-4 flex justify-end">
+        <el-pagination
+          v-model:current-page="pagination.pageNo"
+          v-model:page-size="pagination.pageSize"
+          :total="total"
+          layout="total, sizes, prev, pager, next, jumper"
+          background
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+
+  <QhseMonthReportPreviewDrawer
+    v-model:visible="visible"
+    :id="currentId"
+    @update:visible="visible = $event" />
+</template>
+
+<style scoped lang="scss">
+.report-summary-query {
+  :deep(.el-form-item) {
+    margin-bottom: 0;
+  }
+}
+
+.report-summary-query__actions {
+  :deep(.el-form-item__content) {
+    gap: 12px;
+  }
+}
+
+.report-summary-table-view {
+  display: block;
+}
+
+.report-summary-card-view {
+  display: none;
+}
+
+.report-summary-card {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+  padding: 14px;
+  background: var(--el-bg-color);
+  border: 1px solid var(--el-border-color-lighter);
+  border-radius: 10px;
+}
+
+.report-summary-card__title,
+.report-summary-card__field {
+  display: grid;
+  gap: 4px;
+}
+
+.report-summary-card__title span,
+.report-summary-card__field span {
+  font-size: 12px;
+  color: var(--el-text-color-secondary);
+}
+
+.report-summary-card__title strong,
+.report-summary-card__field strong {
+  font-size: 14px;
+  line-height: 1.5;
+  color: var(--el-text-color-primary);
+  overflow-wrap: anywhere;
+}
+
+.report-summary-card__actions {
+  display: flex;
+  justify-content: flex-end;
+  padding-top: 4px;
+  border-top: 1px solid var(--el-border-color-lighter);
+}
+
+@media (width < 768px) {
+  .report-summary-page {
+    height: auto;
+    min-height: calc(
+      100vh - 20px - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height)
+    );
+    gap: 12px;
+  }
+
+  .report-summary-data-panel {
+    min-height: 280px;
+    padding: 12px;
+  }
+
+  .report-summary-table-view {
+    display: none;
+  }
+
+  .report-summary-card-view {
+    display: flex;
+    flex: 1;
+    flex-direction: column;
+    gap: 12px;
+    overflow-y: auto;
+  }
+}
+</style>

+ 306 - 0
src/views/pms/qhse/reportSummary/preview-drawer.vue

@@ -0,0 +1,306 @@
+<script lang="ts" setup>
+import { QhseMonthReportApi } from '@/api/pms/qhse'
+import type { QhseMonthReportItem, ReportMetricRow } from './types'
+import dayjs from 'dayjs'
+
+interface Props {
+  visible: boolean
+  id?: number
+}
+
+const props = defineProps<Props>()
+const emits = defineEmits(['update:visible'])
+
+const loading = ref(false)
+const report = ref<QhseMonthReportItem>()
+
+const metricRows: ReportMetricRow[] = [
+  { category: '人工时与里程', label: '员工人数', field: 'employee', unit: '人' },
+  { category: '人工时与里程', label: '分包商人数', field: 'subcontractors', unit: '人' },
+  {
+    category: '人工时与里程',
+    label: '安全行驶里程数(公里)',
+    field: 'drivingMileage',
+    unit: '公里'
+  },
+  { category: '人工时与里程', label: '总人工时数(小时)', field: 'totalManHours', unit: '小时' },
+  { category: '被动性指标', label: '无事故累计天数(天)', field: 'withoutAccident', unit: '天' },
+  { category: '被动性指标', label: '死亡事故(起)', field: 'fatality', unit: '起' },
+  { category: '被动性指标', label: '损失工时事故(起)', field: 'injury', unit: '起' },
+  { category: '被动性指标', label: '工作受限事件(起)', field: 'restrictedCase', unit: '起' },
+  { category: '被动性指标', label: '医疗处理事件(起)', field: 'medicalCase', unit: '起' },
+  { category: '被动性指标', label: '急救箱事件(起)', field: 'firstAidCase', unit: '起' },
+  { category: '被动性指标', label: '交通事故(起)', field: 'vehicleAccident', unit: '起' },
+  { category: '被动性指标', label: '未遂事件(起)', field: 'nearMiss', unit: '起' },
+  { category: '被动性指标', label: '泄漏事件(起)', field: 'spill', unit: '起' },
+  { category: '被动性指标', label: '违反保命规则的次数(次)', field: 'lifeSavingRules', unit: '次' },
+  { category: '主动性指标', label: '班前会(次)', field: 'toolboxTalk', unit: '次' },
+  { category: '主动性指标', label: 'QHSE管理委员会会议', field: 'committeeMeeting', unit: '次' },
+  { category: '主动性指标', label: 'QHSE月度例会', field: 'monthlyMeeting', unit: '次' },
+  { category: '主动性指标', label: '公司级隐患排查', field: 'companyHazard', unit: '次' },
+  { category: '主动性指标', label: 'QHSE检查', field: 'qhseInspection', unit: '次' },
+  { category: '主动性指标', label: '安全观察卡', field: 'socCards', unit: '张' },
+  { category: '主动性指标', label: '工作许可审核', field: 'ptwAudit', unit: '份' },
+  { category: '主动性指标', label: '工作安全分析', field: 'jsa', unit: '次' },
+  { category: '主动性指标', label: '演练次数', field: 'drills', unit: '次' },
+  { category: '主动性指标', label: 'QHSE培训次数', field: 'training', unit: '次' },
+  { category: '主动性指标', label: 'QHSE培训人次', field: 'participantsTraining', unit: '人次' },
+  { category: '主动性指标', label: 'QHSE培训学时数', field: 'trainingsHours', unit: '小时' },
+  { category: '环境数据', label: '水消耗', field: 'waterConsumption', unit: '吨' },
+  { category: '环境数据', label: '柴油消耗', field: 'dieselConsumption', unit: '升' },
+  { category: '环境数据', label: '用电量', field: 'electricityConsumption', unit: '千瓦·小时' },
+  { category: '环境数据', label: '天然气消耗量', field: 'naturalGasConsumption', unit: '立方米' },
+  { category: '其他信息', label: '备注', field: 'remark', unit: '/' }
+]
+
+const categoryRowSpanMap = computed(() => {
+  return metricRows.reduce<Record<string, number>>((acc, item) => {
+    acc[item.category] = (acc[item.category] || 0) + 1
+    return acc
+  }, {})
+})
+
+const firstRowIndexByCategory = computed(() => {
+  return metricRows.reduce<Record<string, number>>((acc, item, index) => {
+    if (acc[item.category] === undefined) {
+      acc[item.category] = index
+    }
+    return acc
+  }, {})
+})
+
+async function loadDetail(id: number) {
+  loading.value = true
+  try {
+    const res = await QhseMonthReportApi.getQhseMonthReport(id)
+    report.value = ((res as any)?.data ?? res ?? {}) as QhseMonthReportItem
+  } finally {
+    loading.value = false
+  }
+}
+
+function handleVisibleChange(visible: boolean) {
+  emits('update:visible', visible)
+  if (!visible) {
+    report.value = undefined
+  }
+}
+
+function formatDisplayValue(field: keyof QhseMonthReportItem) {
+  const value = report.value?.[field]
+  if (value === undefined || value === null || value === '') return '-'
+  if (field === 'createTime') {
+    const date = dayjs(value)
+    return date.isValid() ? date.format('YYYY-MM-DD') : String(value)
+  }
+  return String(value)
+}
+
+watch(
+  () => [props.visible, props.id] as const,
+  ([visible, id]) => {
+    if (!visible || !id) return
+    loadDetail(id)
+  },
+  { immediate: true }
+)
+</script>
+
+<template>
+  <el-drawer
+    :model-value="visible"
+    :size="'100%'"
+    :with-header="false"
+    destroy-on-close
+    body-class="qhse-report-preview-drawer__body"
+    @update:model-value="handleVisibleChange">
+    <div class="qhse-report-preview" v-loading="loading">
+      <div class="qhse-report-preview__toolbar">
+        <div class="qhse-report-preview__heading">
+          <h2>{{ report?.title || 'QHSE月报汇总' }}</h2>
+          <p>按月报模板预览,包含横向列头与纵向分类行头</p>
+        </div>
+        <el-button @click="handleVisibleChange(false)">关闭</el-button>
+      </div>
+
+      <div class="qhse-report-preview__sheet">
+        <div class="qhse-report-preview__sheet-title">QHSE 月度报告</div>
+        <div class="qhse-report-preview__meta">
+          <span>年月:{{ formatDisplayValue('yearMonths') }}</span>
+          <span>填报人:{{ formatDisplayValue('personName') }}</span>
+          <span>创建日期:{{ formatDisplayValue('createTime') }}</span>
+        </div>
+
+        <div class="qhse-report-preview__table-wrap">
+          <table class="qhse-report-preview__table">
+            <thead>
+              <tr>
+                <th class="is-sticky-col">基本信息</th>
+                <th>单位</th>
+                <th>瑞恒兴域</th>
+                <th>四川瑞都</th>
+                <th>陕西瑞鹰</th>
+                <th>俄油服</th>
+                <th>瑞气能源</th>
+                <th>瑞霖技术</th>
+                <th>北京总部</th>
+                <th>汇总</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr v-for="(row, index) in metricRows" :key="`${row.category}-${row.field}`">
+                <th
+                  v-if="firstRowIndexByCategory[row.category] === index"
+                  class="is-sticky-col is-category"
+                  :rowspan="categoryRowSpanMap[row.category]">
+                  {{ row.category }}
+                </th>
+                <th class="is-label">{{ row.label }}</th>
+                <td>{{ row.unit }}</td>
+                <td class="is-value">{{ formatDisplayValue(row.field) }}</td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+    </div>
+  </el-drawer>
+</template>
+
+<style scoped lang="scss">
+.qhse-report-preview {
+  display: flex;
+  min-height: 100%;
+  flex-direction: column;
+  gap: 20px;
+  background: linear-gradient(180deg, #eef4ff 0%, #f7f9fc 220px, #eef2f7 100%);
+  padding: 24px;
+}
+
+.qhse-report-preview__toolbar {
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  gap: 16px;
+}
+
+.qhse-report-preview__heading {
+  h2 {
+    margin: 0;
+    font-size: 26px;
+    font-weight: 700;
+    color: #1f2a44;
+  }
+
+  p {
+    margin: 8px 0 0;
+    color: #5f6b85;
+    font-size: 14px;
+  }
+}
+
+.qhse-report-preview__sheet {
+  display: flex;
+  min-height: 0;
+  flex: 1;
+  flex-direction: column;
+  gap: 16px;
+  background: #fff;
+  border: 1px solid #d8e0ef;
+  border-radius: 20px;
+  box-shadow: 0 18px 50px rgb(35 51 84 / 10%);
+  padding: 24px;
+}
+
+.qhse-report-preview__sheet-title {
+  text-align: center;
+  font-size: 28px;
+  font-weight: 700;
+  letter-spacing: 2px;
+  color: #203354;
+}
+
+.qhse-report-preview__meta {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px 24px;
+  color: #52627f;
+  font-size: 14px;
+}
+
+.qhse-report-preview__table-wrap {
+  overflow: auto;
+  border: 1px solid #cfd8e6;
+}
+
+.qhse-report-preview__table {
+  width: 100%;
+  min-width: 820px;
+  border-collapse: collapse;
+  table-layout: fixed;
+  font-size: 14px;
+  color: #26334d;
+
+  th,
+  td {
+    border: 1px solid #cfd8e6;
+    padding: 12px 14px;
+    text-align: center;
+    vertical-align: middle;
+    background: #fff;
+  }
+
+  thead th {
+    position: sticky;
+    top: 0;
+    z-index: 3;
+    background: #dbe8ff;
+    color: #183153;
+    font-weight: 700;
+  }
+}
+
+.is-sticky-col {
+  position: sticky;
+  left: 0;
+  z-index: 2;
+}
+
+.is-category {
+  background: #edf3ff !important;
+  font-weight: 700;
+  min-width: 140px;
+}
+
+.is-label {
+  background: #f8fbff;
+  font-weight: 600;
+}
+
+.is-value {
+  font-weight: 600;
+  color: #0f3f8f;
+}
+
+@media (width < 768px) {
+  .qhse-report-preview {
+    padding: 12px;
+    gap: 12px;
+  }
+
+  .qhse-report-preview__toolbar {
+    flex-direction: column;
+    align-items: stretch;
+  }
+
+  .qhse-report-preview__sheet {
+    padding: 14px;
+    border-radius: 14px;
+  }
+
+  .qhse-report-preview__sheet-title {
+    font-size: 22px;
+    letter-spacing: 1px;
+  }
+}
+</style>

+ 50 - 0
src/views/pms/qhse/reportSummary/types.ts

@@ -0,0 +1,50 @@
+export interface QhseMonthReportItem {
+  id: number
+  title?: string
+  yearMonths?: string
+  deptId?: number
+  deptName?: string
+  personName?: string
+  createTime?: string
+  employee?: string | number
+  subcontractors?: string | number
+  drivingMileage?: string | number
+  totalManHours?: string | number
+  withoutAccident?: string | number
+  fatality?: string | number
+  injury?: string | number
+  restrictedCase?: string | number
+  medicalCase?: string | number
+  firstAidCase?: string | number
+  vehicleAccident?: string | number
+  nearMiss?: string | number
+  spill?: string | number
+  lifeSavingRules?: string | number
+  toolboxTalk?: string | number
+  committeeMeeting?: string | number
+  monthlyMeeting?: string | number
+  companyHazard?: string | number
+  qhseInspection?: string | number
+  socCards?: string | number
+  ptwAudit?: string | number
+  jsa?: string | number
+  drills?: string | number
+  training?: string | number
+  participantsTraining?: string | number
+  trainingsHours?: string | number
+  waterConsumption?: string | number
+  dieselConsumption?: string | number
+  electricityConsumption?: string | number
+  naturalGasConsumption?: string | number
+  dutyPerson?: number
+  remark?: string
+}
+
+export type QhseMonthReportListItem = QhseMonthReportItem
+
+export interface ReportMetricRow {
+  category: string
+  label: string
+  field: keyof QhseMonthReportItem
+  unit: string
+}

+ 97 - 77
src/views/report-statistics/inspection_order/index.vue

@@ -14,17 +14,15 @@
                   queryParams.pageNo = 1
                   getList('all')
                 }
-              "
-            >
-              <Icon icon="ep:histogram" :size="40" />
-              <div class="card-title">工单数量</div>
+              ">
+              <Icon icon="ep:histogram" class="text-[#2563eb]!" :size="40" />
+              <div class="card-title text-[#6b7280]!">工单数量</div>
 
               <div class="card-value pt-5">
                 <CountTo
-                  class="text-2xl"
+                  class="text-3xl text-[#2563eb]!"
                   :end-val="deviceCount.finished + deviceCount.ignore + deviceCount.todo || 0"
-                  :decimals="0"
-                />
+                  :decimals="0" />
               </div>
             </div>
           </div>
@@ -39,13 +37,15 @@
                 getList('finished')
               }
             "
-            :class="{ 'stat-card-selected': statusList.finished }"
-          >
+            :class="{ 'stat-card-selected': statusList.finished }">
             <div class="stat-card bg-green-gradient">
-              <Icon icon="ep:finished" :size="40" />
+              <Icon icon="ep:finished" class="text-[#219241]!" :size="40" />
               <div class="card-title">完成数量</div>
               <div class="card-value pt-5">
-                <CountTo class="text-2xl" :end-val="deviceCount.finished || 0" :decimals="0" />
+                <CountTo
+                  class="text-3xl text-[#219241]!"
+                  :end-val="deviceCount.finished || 0"
+                  :decimals="0" />
               </div>
             </div>
           </div>
@@ -60,13 +60,15 @@
                 getList('todo')
               }
             "
-            :class="{ 'stat-card-selected': statusList.todo }"
-          >
+            :class="{ 'stat-card-selected': statusList.todo }">
             <div class="stat-card bg-orange-gradient">
-              <Icon icon="ep:more-filled" :size="40" />
+              <Icon icon="ep:more-filled" class="text-[#fc9a03]!" :size="40" />
               <div class="card-title">未完成数量</div>
               <div class="card-value pt-5">
-                <CountTo class="text-2xl" :end-val="deviceCount.todo || 0" :decimals="0" />
+                <CountTo
+                  class="text-3xl text-[#fc9a03]!"
+                  :end-val="deviceCount.todo || 0"
+                  :decimals="0" />
               </div>
             </div>
           </div>
@@ -81,13 +83,15 @@
                 getList('ignore')
               }
             "
-            :class="{ 'stat-card-selected': statusList.ignore }"
-          >
+            :class="{ 'stat-card-selected': statusList.ignore }">
             <div class="stat-card bg-green-gradient">
               <Icon icon="ep:hide" :size="40" />
               <div class="card-title">已忽略</div>
               <div class="card-value pt-5">
-                <CountTo class="text-2xl" :end-val="deviceCount.ignore || 0" :decimals="0" />
+                <CountTo
+                  class="text-3xl text-[#6b7280]!"
+                  :end-val="deviceCount.ignore || 0"
+                  :decimals="0" />
               </div>
             </div>
           </div>
@@ -101,16 +105,17 @@
                 queryParams.pageNo = 1
                 getExceptionList()
               }
-            "
-          >
+            ">
             <div
               class="stat-card bg-red-gradient"
-              :class="{ 'stat-card-selected': statusList.exception }"
-            >
-              <Icon icon="ep:bell" :size="40" />
+              :class="{ 'stat-card-selected': statusList.exception }">
+              <Icon icon="ep:bell" class="text-[#d45336]!" :size="40" />
               <div class="card-title">异常设备数量</div>
               <div class="card-value pt-5">
-                <CountTo class="text-2xl" :end-val="exceptions?.exceptionNum || 0" :decimals="0" />
+                <CountTo
+                  class="text-3xl text-[#d45336]!"
+                  :end-val="exceptions?.exceptionNum || 0"
+                  :decimals="0" />
               </div>
             </div>
           </div>
@@ -124,16 +129,17 @@
                 queryParams.pageNo = 1
                 getExceptionPoint()
               }
-            "
-          >
+            ">
             <div
               class="stat-card bg-warn-gradient"
-              :class="{ 'stat-card-selected': statusList.exceptionPoint }"
-            >
-              <Icon icon="ep:info-filled" :size="40" />
+              :class="{ 'stat-card-selected': statusList.exceptionPoint }">
+              <Icon icon="ep:info-filled" class="text-[#e6a23c]!" :size="40" />
               <div class="card-title">异常点数量</div>
               <div class="card-value pt-5">
-                <CountTo class="text-2xl" :end-val="exceptionPoint.value || 0" :decimals="0" />
+                <CountTo
+                  class="text-3xl text-[#e6a23c]!"
+                  :end-val="exceptionPoint.value || 0"
+                  :decimals="0" />
               </div>
             </div>
           </div>
@@ -163,8 +169,7 @@
           :loading="loading"
           :data="list3"
           :stripe="true"
-          :show-overflow-tooltip="true"
-        >
+          :show-overflow-tooltip="true">
           <zm-table-column :label="t('iotDevice.serial')" width="70" align="center">
             <template #default="scope">
               {{ scope.$index + 1 }}
@@ -188,8 +193,7 @@
           :loading="loading"
           :data="list2"
           :stripe="true"
-          :show-overflow-tooltip="true"
-        >
+          :show-overflow-tooltip="true">
           <zm-table-column :label="t('iotDevice.serial')" width="70" align="center">
             <template #default="scope">
               {{ scope.$index + 1 }}
@@ -211,8 +215,7 @@
             :label="t('inspect.exceptionDes')"
             align="center"
             prop="description"
-            action
-          />
+            action />
         </zm-table>
 
         <zm-table
@@ -222,8 +225,7 @@
           :data="list"
           :show-overflow-tooltip="true"
           @row-click="handleRowClick"
-          height="48vh"
-        >
+          height="48vh">
           <zm-table-column :label="t('iotDevice.serial')" width="70" align="center">
             <template #default="scope">
               {{ scope.$index + 1 }}
@@ -238,14 +240,12 @@
             :label="t('route.orderType')"
             align="center"
             prop="type"
-            min-width="90"
-          />
+            min-width="90" />
           <zm-table-column
             :label="t('operationFill.status')"
             align="center"
             prop="status"
-            min-width="95"
-          >
+            min-width="95">
             <template #default="scope">
               <dict-tag :type="DICT_TYPE.PMS_INSPECT_ORDER_STATUS" :value="scope.row.status" />
             </template>
@@ -258,16 +258,14 @@
           <zm-table-column
             :label="t('iotMaintain.PersonInCharge')"
             align="center"
-            prop="chargeName"
-          />
+            prop="chargeName" />
 
           <zm-table-column
             :label="t('iotMaintain.operation')"
             align="center"
             min-width="150px"
             fixed="right"
-            action
-          >
+            action>
             <template #default="scope">
               <el-button link type="primary" @click="openForm(scope.row.id)">
                 异常巡检点
@@ -281,8 +279,7 @@
           :total="total"
           v-model:page="queryParams.pageNo"
           v-model:limit="queryParams.pageSize"
-          @pagination="getAllList"
-        />
+          @pagination="getAllList" />
       </ContentWrap>
     </el-col>
   </el-row>
@@ -310,16 +307,14 @@
         :label="t('inspect.exceptionDes')"
         align="center"
         prop="description"
-        action
-      />
+        action />
     </zm-table>
 
     <Pagination
       :total="detailTotal"
       v-model:page="detailQueryParams.pageNo"
       v-model:limit="detailQueryParams.pageSize"
-      @pagination="goDetail(detailQueryParams.deviceCode)"
-    />
+      @pagination="goDetail(detailQueryParams.deviceCode)" />
   </el-drawer>
 </template>
 
@@ -694,35 +689,37 @@ onMounted(() => {
 }
 
 .stat-card {
-  padding: 20px;
+  padding: 14px 16px;
+  background: linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
+  border: 1px solid #e4ecf7;
   border-radius: 10px;
-  color: white;
+  box-shadow: 0 4px 12px rgb(31 91 184 / 8%);
   text-align: center;
   font-size: 14px;
-  /* box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); */
   transition:
     transform 0.3s ease,
-    box-shadow 0.3s ease;
-  backdrop-filter: blur(12px);
+    box-shadow 0.3s ease,
+    border-color 0.3s ease;
+  color: #6b7280;
   height: 170px;
   cursor: pointer;
-  overflow: hidden; /* 防止闪光效果溢出 */
-}
-.stat-card::before {
-  position: absolute;
-  filter: blur(20px);
-  z-index: -1;
+  overflow: hidden;
 }
 
 .card-title {
   margin: 8px 0;
-  font-size: 16px;
+  font-size: 14px;
+  font-weight: 600;
+  color: #6b7280;
+  line-height: 1.4;
 }
 
 .card-value {
-  font-size: 28px;
-  font-weight: bold;
   margin: 8px 0;
+  font-size: 28px;
+  font-weight: 700;
+  line-height: 1;
+  color: #1f5bb8;
 }
 
 .card-trend {
@@ -730,28 +727,52 @@ onMounted(() => {
   opacity: 0.9;
 }
 
-/* 毛玻璃渐变背景 —— 不再使用 background-image */
 .bg-blue-gradient {
-  background: linear-gradient(135deg, rgba(77, 147, 255, 0.5), rgba(75, 132, 254));
+  background: linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
+  border-color: #e4ecf7;
+}
+
+.bg-blue-gradient .card-value {
+  color: #2563eb;
 }
 
 .bg-green-gradient {
-  background: linear-gradient(135deg, rgba(101, 226, 136, 0.3), #52d7a2);
+  background: linear-gradient(180deg, #f7fcf8 0%, #edf8f1 100%);
+  border-color: #d6efdc;
+}
+
+.bg-green-gradient .card-value {
+  color: #16a34a;
 }
 
 .bg-orange-gradient {
-  background: linear-gradient(135deg, rgba(152, 82, 4, 0.5), rgba(255, 152, 4, 0.6));
+  background: linear-gradient(180deg, #fff8ef 0%, #ffeed9 100%);
+  border-color: #ffd7a1;
+}
+
+.bg-orange-gradient .card-value {
+  color: #d97706;
 }
 
 .bg-red-gradient {
-  background: linear-gradient(135deg, rgba(232, 65, 51), rgba(252, 242, 236));
+  background: linear-gradient(180deg, #fff4f4 0%, #ffe8e8 100%);
+  border-color: #ffcfcf;
+}
+
+.bg-red-gradient .card-value {
+  color: #de3b3b;
 }
 
 .bg-warn-gradient {
-  background: linear-gradient(135deg, rgba(255, 201, 103), rgba(243, 162, 152));
+  background: linear-gradient(180deg, #fff8ef 0%, #ffeed9 100%);
+  border-color: #ffd7a1;
+}
+
+.bg-warn-gradient .card-value {
+  color: #d97706;
 }
 
-/* 确保内容不溢出 */
+/* ???????????*/
 :deep(.el-row) {
   flex-wrap: wrap;
 }
@@ -771,10 +792,9 @@ onMounted(() => {
 
 .stat-card-selected {
   position: relative;
-  transform: scale(1.06);
+  transform: translateY(-2px);
   transition: all 0.2s;
-  box-shadow:
-    0 10px 20px rgba(0, 80, 179, 0.5),
-    0 0 10px rgba(0, 120, 255, 0.4) inset;
+  box-shadow: 0 10px 20px rgb(31 91 184 / 12%);
+  border-color: #bfd5ee;
 }
 </style>