Browse Source

Merge branch 'refactor/export'

Zimo 1 week ago
parent
commit
7d9117a507
31 changed files with 1293 additions and 457 deletions
  1. 2 2
      .env.local
  2. 8 0
      src/api/pms/device/index.ts
  3. 1 1
      src/api/pms/iotlockstock/index.ts
  4. 11 1
      src/api/pms/iotmainworkorder/index.ts
  5. 5 5
      src/api/pms/iotprojectinfo/index.ts
  6. 2 2
      src/api/pms/iotprojecttask/index.ts
  7. 10 0
      src/api/pms/iotrddailyreport/index.ts
  8. 6 0
      src/api/pms/iotrydailyreport/index.ts
  9. 1 1
      src/api/pms/iotsapstock/index.ts
  10. 3 3
      src/api/pms/maintenance/index.ts
  11. 3 0
      src/api/pms/report/index.ts
  12. 4 4
      src/views/oli-connection/monitoring/detail.vue
  13. 21 14
      src/views/pms/device/allotlog/DeviceAllot.vue
  14. 2 2
      src/views/pms/iotdeviceallotlog/index.vue
  15. 194 113
      src/views/pms/iotlockstock/index.vue
  16. 22 28
      src/views/pms/iotmainworkorder/IotDeviceMainAlarm.vue
  17. 1 4
      src/views/pms/iotmainworkorder/index.vue
  18. 2 9
      src/views/pms/iotprojectinfo/index.vue
  19. 2 9
      src/views/pms/iotprojecttask/index.vue
  20. 3 23
      src/views/pms/iotrddailyreport/fillDailyReport.vue
  21. 3 23
      src/views/pms/iotrddailyreport/index.vue
  22. 20 27
      src/views/pms/iotrddailyreport/statistics.vue
  23. 3 2
      src/views/pms/iotrddailyreport/summary.vue
  24. 16 24
      src/views/pms/iotrydailyreport/index.vue
  25. 15 23
      src/views/pms/iotrydailyreport/xjindex.vue
  26. 200 112
      src/views/pms/iotsapstock/index.vue
  27. 0 2
      src/views/pms/maintenance/index.vue
  28. 25 1
      src/views/report-statistics/costs.vue
  29. 21 0
      src/views/report-statistics/rd-daily-report.vue
  30. 26 22
      src/views/report-statistics/ry-daily-report.vue
  31. 661 0
      src/views/report-statistics/ry-xj-daily-report.vue

+ 2 - 2
.env.local

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

+ 8 - 0
src/api/pms/device/index.ts

@@ -152,6 +152,14 @@ export const IotDeviceApi = {
   exportIotDevice: async (params) => {
     return await request.download({ url: `/rq/iot-device/export-excel`, params })
   },
+
+  exportIotDeviceAllot: async (params) => {
+    return await request.download({ url: `/pms/iot-device-allot-log/export-excel`, params })
+  },
+
+  exportIotDeviceMainAlarm: async (params) => {
+    return await request.download({ url: `/pms/iot-main-work-order/exportMaintenances`, params })
+  },
   getIotDeviceTdPage: async (params: any) => {
     return await request.get({ url: `/rq/iot-device/td/page`, params })
   },

+ 1 - 1
src/api/pms/iotlockstock/index.ts

@@ -65,5 +65,5 @@ export const IotLockStockApi = {
   // 导出PMS 本地 库存 Excel
   exportIotLockStock: async (params) => {
     return await request.download({ url: `/pms/iot-lock-stock/export-excel`, params })
-  },
+  }
 }

+ 11 - 1
src/api/pms/iotmainworkorder/index.ts

@@ -62,7 +62,10 @@ export const IotMainWorkOrderApi = {
   },
 
   getDeviceIotWorkOrder: async (orderId: number, deviceId: number) => {
-    return await request.get({ url: `/pms/iot-main-work-order/deviceWorkOrder?workOrderId=` + orderId+'&deviceId='+deviceId })
+    return await request.get({
+      url:
+        `/pms/iot-main-work-order/deviceWorkOrder?workOrderId=` + orderId + '&deviceId=' + deviceId
+    })
   },
 
   // 新增保养工单
@@ -99,4 +102,11 @@ export const IotMainWorkOrderApi = {
   exportIotMainWorkOrder: async (params) => {
     return await request.download({ url: `/pms/iot-main-work-order/export-excel`, params })
   },
+
+  exportIotMainWorkOrderIndex: async (params) => {
+    return await request.download({
+      url: `/pms/iot-main-work-order/exportMaintenanceOrders`,
+      params
+    })
+  }
 }

+ 5 - 5
src/api/pms/iotprojectinfo/index.ts

@@ -1,5 +1,5 @@
 import request from '@/config/axios'
-import {RouteParamValue} from "vue-router";
+import { RouteParamValue } from 'vue-router'
 
 // 项目信息 VO
 export interface IotProjectInfoVO {
@@ -17,8 +17,8 @@ export interface IotProjectInfoVO {
   payment: string // 施工工艺
   userName: string // 用户名
   userId: number // 用户id
-  manufacturerId:number
-  manufactureName:string
+  manufacturerId: number
+  manufactureName: string
 }
 
 // 项目信息 API
@@ -30,7 +30,7 @@ export const IotProjectInfoApi = {
 
   //根据用户获取项目信息
   getIotProjectInfoUser: async (deptId: string | RouteParamValue[]) => {
-    return await request.get({ url: `/rq/iot-project-info/projectList?deptId=`+deptId })
+    return await request.get({ url: `/rq/iot-project-info/projectList?deptId=` + deptId })
   },
   // 查询项目信息详情
   getIotProjectInfo: async (id: string | RouteParamValue[]) => {
@@ -55,5 +55,5 @@ export const IotProjectInfoApi = {
   // 导出项目信息 Excel
   exportIotProjectInfo: async (params) => {
     return await request.download({ url: `/rq/iot-project-info/export-excel`, params })
-  },
+  }
 }

+ 2 - 2
src/api/pms/iotprojecttask/index.ts

@@ -12,7 +12,7 @@ export interface IotProjectTaskVO {
   userName: string // 用户名
   userId: number // 用户id
   remark: string // 备注
-  deptIds:[]
+  deptIds: []
 }
 
 // 项目信息任务拆分 API
@@ -47,5 +47,5 @@ export const IotProjectTaskApi = {
   // 导出项目信息任务拆分 Excel
   exportIotProjectTask: async (params) => {
     return await request.download({ url: `/rq/iot-project-task/export-excel`, params })
-  },
+  }
 }

+ 10 - 0
src/api/pms/iotrddailyreport/index.ts

@@ -113,5 +113,15 @@ export const IotRdDailyReportApi = {
   },
   getIotRdDailyReportSummaryPolyline: async (params: any) => {
     return await request.get({ url: `/pms/iot-rd-daily-report/polylineStatistics`, params })
+  },
+
+  exportRdDailyReportStatistics: async (params) => {
+    return await request.download({ url: `/pms/iot-rd-daily-report/exportStatistics`, params })
+  },
+  exportIotRdDailyReportWell: async (params) => {
+    return await request.download({ url: `/pms/iot-rd-daily-report/exportSingleWells`, params })
+  },
+  exportIotRdDailyReportTeam: async (params) => {
+    return await request.download({ url: `/pms/iot-rd-daily-report/exportSingleTeams`, params })
   }
 }

+ 6 - 0
src/api/pms/iotrydailyreport/index.ts

@@ -123,5 +123,11 @@ export const IotRyDailyReportApi = {
 
   approvalIotRyDailyReport: async (data: { id: number; auditStatus: 20 | 30; opinion: string }) => {
     return await request.put({ url: `/pms/iot-ry-daily-report/approval`, data })
+  },
+  exportIotRyDailyReportWell: async (params) => {
+    return await request.download({ url: `/pms/iot-ry-daily-report/exportSingleWells`, params })
+  },
+  exportIotRyDailyReportTeam: async (params) => {
+    return await request.download({ url: `/pms/iot-ry-daily-report/exportSingleTeams`, params })
   }
 }

+ 1 - 1
src/api/pms/iotsapstock/index.ts

@@ -64,5 +64,5 @@ export const IotSapStockApi = {
   // 导出PMS SAP 库存(通用库存/项目部库存) Excel
   exportIotSapStock: async (params) => {
     return await request.download({ url: `/pms/iot-sap-stock/export-excel`, params })
-  },
+  }
 }

+ 3 - 3
src/api/pms/maintenance/index.ts

@@ -39,7 +39,7 @@ export const IotMaintenancePlanApi = {
     return await request.post({ url: `/rq/iot-maintenance-plan/updatePlan`, data })
   },
 
-  updatePlanStatus : (id: number, status: number) => {
+  updatePlanStatus: (id: number, status: number) => {
     const data = {
       id,
       status
@@ -54,6 +54,6 @@ export const IotMaintenancePlanApi = {
 
   // 导出保养计划 Excel
   exportIotMaintenancePlan: async (params) => {
-    return await request.download({ url: `/rq/iot-maintenance-plan/export-excel`, params })
-  },
+    return await request.download({ url: `/pms/iot-maintenance-bom/exportPlans`, params })
+  }
 }

+ 3 - 0
src/api/pms/report/index.ts

@@ -13,5 +13,8 @@ export const IotReportApi = {
   },
   getOrderPage: async (params: any) => {
     return await request.get({ url: `/rq/report/order/page`, params })
+  },
+  exportCosts: async (params) => {
+    return await request.download({ url: `/rq/report/repair/report/export-excel`, params })
   }
 }

+ 4 - 4
src/views/oli-connection/monitoring/detail.vue

@@ -596,13 +596,13 @@ onUnmounted(() => {
 
 <template>
   <div
-    class="w-full bg-gradient-to-r from-blue-100 to-white rounded-lg p-6 shadow"
+    class="w-full bg-gradient-to-r from-blue-100 to-white rounded-lg p-4 shadow"
     id="td-device-info"
   >
     <h2 class="flex items-center gap-2">
       <el-icon class="text-sky!"><Odometer /></el-icon> 设备基础信息
     </h2>
-    <el-form size="large" label-position="top" class="mt-4 grid grid-cols-3 gap-4">
+    <el-form size="default" label-position="top" class="mt-4 grid grid-cols-4 gap-2">
       <el-form-item label="资产编码"> {{ data.deviceCode }} </el-form-item>
       <el-form-item label="设备类别"> {{ data.deviceName }} </el-form-item>
       <el-form-item label="所在部门"> {{ data.dept }} </el-form-item>
@@ -652,7 +652,7 @@ onUnmounted(() => {
     <div
       v-loading="dimensionLoading"
       element-loading-background="transparent"
-      class="w-full mt-4 grid grid-cols-4 gap-4 min-h-30"
+      class="w-full mt-4 grid grid-cols-5 gap-2 min-h-30"
       id="dimension"
     >
       <button
@@ -680,7 +680,7 @@ onUnmounted(() => {
     class="mt-4 w-full rounded-lg bg-gradient-to-r from-blue-100 to-white p-4 shadow"
   >
     <header class="font-medium text-center w-full">中航北斗</header>
-    <div class="w-full mt-4 grid grid-cols-4 gap-4" id="dimension">
+    <div class="w-full mt-4 grid grid-cols-5 gap-2 min-h-30" id="dimension">
       <button
         v-for="item in carDimensions"
         :key="item.identifier"

+ 21 - 14
src/views/pms/device/allotlog/DeviceAllot.vue

@@ -16,7 +16,11 @@
           :inline="true"
           label-width="68px"
         >
-          <el-form-item :label="t('devicePerson.deviceCode')" prop="deviceCode" style="margin-left: 25px">
+          <el-form-item
+            :label="t('devicePerson.deviceCode')"
+            prop="deviceCode"
+            style="margin-left: 25px"
+          >
             <el-input
               v-model="queryParams.deviceCode"
               :placeholder="t('devicePerson.codeHolder')"
@@ -49,7 +53,12 @@
               />
             </el-select>
           </el-form-item>
-          <el-form-item v-show="ifShow" :label="t('devicePerson.status')" label-width="85px" prop="deviceStatus">
+          <el-form-item
+            v-show="ifShow"
+            :label="t('devicePerson.status')"
+            label-width="85px"
+            prop="deviceStatus"
+          >
             <el-select
               v-model="queryParams.deviceStatus"
               :placeholder="t('devicePerson.status')"
@@ -93,10 +102,12 @@
 
           <el-form-item>
             <el-button v-if="!ifShow" @click="moreQuery(true)" type="warning"
-              ><Icon icon="ep:search" class="mr-5px" /> {{ t('devicePerson.moreSearch') }}</el-button
+              ><Icon icon="ep:search" class="mr-5px" />
+              {{ t('devicePerson.moreSearch') }}</el-button
             >
             <el-button v-if="ifShow" @click="moreQuery(false)" type="danger"
-              ><Icon icon="ep:search" class="mr-5px" /> {{ t('devicePerson.closeSearch') }}</el-button
+              ><Icon icon="ep:search" class="mr-5px" />
+              {{ t('devicePerson.closeSearch') }}</el-button
             >
             <el-button @click="handleQuery"
               ><Icon icon="ep:search" class="mr-5px" /> {{ t('devicePerson.search') }}</el-button
@@ -133,7 +144,7 @@
               {{ scope.$index + 1 }}
             </template>
           </el-table-column>
-          <el-table-column :label="t('monitor.deviceCode')"  align="center" prop="deviceCode" />
+          <el-table-column :label="t('monitor.deviceCode')" align="center" prop="deviceCode" />
           <el-table-column :label="t('monitor.deviceName')" align="center" prop="deviceName">
             <template #default="scope">
               <el-link :underline="false" type="primary" @click="handleDetail(scope.row.id)">
@@ -180,7 +191,7 @@
   </el-row>
   <DeviceAllotLogDrawer
     :model-value="drawerVisible"
-    @update:model-value="val => drawerVisible = val"
+    @update:model-value="(val) => (drawerVisible = val)"
     :device-id="currentDeviceId"
     ref="showDrawer"
   />
@@ -190,10 +201,9 @@
 import download from '@/utils/download'
 import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
-import { dateFormatter } from '@/utils/formatTime'
 import DeptTree from '@/views/system/user/DeptTree.vue'
 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
-import DeviceAllotLogDrawer from "@/views/pms/device/allotlog/DeviceAllotLogDrawer.vue";
+import DeviceAllotLogDrawer from '@/views/pms/device/allotlog/DeviceAllotLogDrawer.vue'
 
 /** 设备调拨 列表 */
 defineOptions({ name: 'IotDeviceAllot' })
@@ -320,7 +330,7 @@ const resultOptions = computed(() => [
   {
     label: '否',
     value: 'N' // 空值会触发 clearable 效果
-  },
+  }
 ])
 
 const handleDetail = (id: number) => {
@@ -334,12 +344,9 @@ const handleUpload = (id: number) => {
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
     exportLoading.value = true
-    const data = await IotDeviceApi.exportIotDevice(queryParams)
-    download.excel(data, '设备台账.xls')
+    const data = await IotDeviceApi.exportIotDeviceAllot(queryParams)
+    download.excel(data, '设备调拨记录.xls')
   } catch {
   } finally {
     exportLoading.value = false

+ 2 - 2
src/views/pms/iotdeviceallotlog/index.vue

@@ -161,7 +161,7 @@ const queryParams = reactive({
   newDeptId: undefined,
   reason: undefined,
   remark: undefined,
-  createTime: [],
+  createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
@@ -228,4 +228,4 @@ const handleExport = async () => {
 onMounted(() => {
   getList()
 })
-</script>
+</script>

+ 194 - 113
src/views/pms/iotlockstock/index.vue

@@ -8,8 +8,19 @@
       :inline="true"
       label-width="68px"
     >
-      <el-form-item :label="t('workOrderMaterial.factory')" prop="factoryId" v-if="!shouldHideComponents">
-        <el-select v-model="queryParams.factoryId" clearable filterable :placeholder="t('faultForm.choose')" class="!w-240px" @change="selectedFactoryChange">
+      <el-form-item
+        :label="t('workOrderMaterial.factory')"
+        prop="factoryId"
+        v-if="!shouldHideComponents"
+      >
+        <el-select
+          v-model="queryParams.factoryId"
+          clearable
+          filterable
+          :placeholder="t('faultForm.choose')"
+          class="!w-240px"
+          @change="selectedFactoryChange"
+        >
           <el-option
             v-for="item in factoryList"
             :key="item.id"
@@ -19,8 +30,18 @@
         </el-select>
       </el-form-item>
 
-      <el-form-item :label="t('workOrderMaterial.costCenter')" prop="costCenterId" v-if="!shouldHideComponents">
-        <el-select v-model="queryParams.costCenterId" clearable filterable :placeholder="t('faultForm.choose')" class="!w-240px">
+      <el-form-item
+        :label="t('workOrderMaterial.costCenter')"
+        prop="costCenterId"
+        v-if="!shouldHideComponents"
+      >
+        <el-select
+          v-model="queryParams.costCenterId"
+          clearable
+          filterable
+          :placeholder="t('faultForm.choose')"
+          class="!w-240px"
+        >
           <el-option
             v-for="item in filteredCostCenterList"
             :key="item.id"
@@ -59,8 +80,12 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> {{ t('operationFill.search') }}</el-button>
-        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> {{ t('operationFill.reset') }}</el-button>
+        <el-button @click="handleQuery"
+          ><Icon icon="ep:search" class="mr-5px" /> {{ t('operationFill.search') }}</el-button
+        >
+        <el-button @click="resetQuery"
+          ><Icon icon="ep:refresh" class="mr-5px" /> {{ t('operationFill.reset') }}</el-button
+        >
         <el-button
           type="primary"
           plain
@@ -69,13 +94,8 @@
         >
           <Icon icon="ep:plus" class="mr-5px" />{{ t('operationFill.add') }}
         </el-button>
-        <el-button
-          type="success"
-          plain
-          @click="handleExport"
-          :loading="exportLoading"
-          v-hasPermi="['pms:iot-lock-stock:export']"
-        >
+        <!-- v-hasPermi="['pms:iot-lock-stock:export']" -->
+        <el-button type="success" plain @click="handleExport" :loading="exportLoading">
           <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
       </el-form-item>
@@ -92,7 +112,15 @@
         </div>
         <div class="stat-item">
           <span class="stat-label">{{ t('stock.totalAmount') }}:</span>
-          <span class="stat-value">¥ {{ totalAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}</span>
+          <span class="stat-value"
+            >¥
+            {{
+              totalAmount.toLocaleString(undefined, {
+                minimumFractionDigits: 2,
+                maximumFractionDigits: 2
+              })
+            }}</span
+          >
         </div>
       </div>
     </el-card>
@@ -100,16 +128,58 @@
 
   <!-- 列表 -->
   <ContentWrap ref="tableContainerRef" class="table-container">
-    <el-table ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="false" style="width: 100%">
-      <el-table-column :label="t('workOrderMaterial.factory')" align="center" prop="factory" :width="columnWidths.factory"/>
-      <el-table-column :label="t('workOrderMaterial.costCenter')" align="center" prop="costCenter" :width="columnWidths.costCenter"/>
-      <el-table-column :label="t('chooseMaintain.materialCode')" align="center" prop="materialCode" :width="columnWidths.materialCode"/>
-      <el-table-column :label="t('chooseMaintain.materialName')" align="left" prop="materialName" :width="columnWidths.materialName"/>
-      <el-table-column :label="t('route.quantity')" align="center" prop="quantity"
-                       :formatter="erpPriceTableColumnFormatter" :width="columnWidths.quantity"/>
-      <el-table-column :label="t('workOrderMaterial.unitPrice')" align="center" prop="unitPrice"
-                       :formatter="erpPriceTableColumnFormatter" :width="columnWidths.unitPrice"/>
-      <el-table-column :label="t('workOrderMaterial.unit')" align="center" prop="unit" :width="columnWidths.unit"/>
+    <el-table
+      ref="tableRef"
+      v-loading="loading"
+      :data="list"
+      :stripe="true"
+      :show-overflow-tooltip="false"
+      style="width: 100%"
+    >
+      <el-table-column
+        :label="t('workOrderMaterial.factory')"
+        align="center"
+        prop="factory"
+        :width="columnWidths.factory"
+      />
+      <el-table-column
+        :label="t('workOrderMaterial.costCenter')"
+        align="center"
+        prop="costCenter"
+        :width="columnWidths.costCenter"
+      />
+      <el-table-column
+        :label="t('chooseMaintain.materialCode')"
+        align="center"
+        prop="materialCode"
+        :width="columnWidths.materialCode"
+      />
+      <el-table-column
+        :label="t('chooseMaintain.materialName')"
+        align="left"
+        prop="materialName"
+        :width="columnWidths.materialName"
+      />
+      <el-table-column
+        :label="t('route.quantity')"
+        align="center"
+        prop="quantity"
+        :formatter="erpPriceTableColumnFormatter"
+        :width="columnWidths.quantity"
+      />
+      <el-table-column
+        :label="t('workOrderMaterial.unitPrice')"
+        align="center"
+        prop="unitPrice"
+        :formatter="erpPriceTableColumnFormatter"
+        :width="columnWidths.unitPrice"
+      />
+      <el-table-column
+        :label="t('workOrderMaterial.unit')"
+        align="center"
+        prop="unit"
+        :width="columnWidths.unit"
+      />
       <el-table-column
         :label="t('stock.storageTime')"
         align="center"
@@ -117,7 +187,6 @@
         :formatter="dateFormatter"
         :width="columnWidths.storageTime"
       />
-
     </el-table>
     <!-- 分页 -->
     <Pagination
@@ -137,9 +206,9 @@ import { dateFormatter } from '@/utils/formatTime'
 import download from '@/utils/download'
 import { IotLockStockApi, IotLockStockVO } from '@/api/pms/iotlockstock'
 import IotLockStockForm from './IotLockStockForm.vue'
-import {erpPriceTableColumnFormatter} from "@/utils";
+import { erpPriceTableColumnFormatter } from '@/utils'
 import { useUserStore } from '@/store/modules/user'
-import { SapOrgApi, SapOrgVO } from "@/api/system/saporg";
+import { SapOrgApi, SapOrgVO } from '@/api/system/saporg'
 import { checkRole } from '@/utils/permission'
 import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
 
@@ -179,18 +248,18 @@ const queryParams = reactive({
   processInstanceId: undefined,
   auditStatus: undefined,
   remark: undefined,
-  createTime: [],
+  createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
 
-const factoryList = ref([] as SapOrgVO[])   // 工厂列表
+const factoryList = ref([] as SapOrgVO[]) // 工厂列表
 const storageLocationList = ref([] as SapOrgVO[]) // 库存地点列表
 const costCenterList = ref([] as SapOrgVO[]) // SAP成本中心列表
 
 // 统计变量
-const totalQuantity = ref(0)   // 总数量
-const totalAmount = ref(0)     // 总金额
+const totalQuantity = ref(0) // 总数量
+const totalAmount = ref(0) // 总金额
 
 // 表格容器和表格的引用
 const tableContainerRef = ref()
@@ -220,54 +289,66 @@ const columnWidths = ref({
 
 /** 获取滚动条宽度 */
 const getScrollbarWidth = () => {
-  const outer = document.createElement('div');
-  outer.style.visibility = 'hidden';
-  outer.style.overflow = 'scroll';
-  document.body.appendChild(outer);
+  const outer = document.createElement('div')
+  outer.style.visibility = 'hidden'
+  outer.style.overflow = 'scroll'
+  document.body.appendChild(outer)
 
-  const inner = document.createElement('div');
-  outer.appendChild(inner);
+  const inner = document.createElement('div')
+  outer.appendChild(inner)
 
-  const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
-  outer.parentNode?.removeChild(outer);
+  const scrollbarWidth = outer.offsetWidth - inner.offsetWidth
+  outer.parentNode?.removeChild(outer)
 
-  return scrollbarWidth;
-};
+  return scrollbarWidth
+}
 
 /** 计算文本宽度 */
 const getTextWidth = (text: string, fontSize = 14) => {
-  const span = document.createElement('span');
-  span.style.visibility = 'hidden';
-  span.style.position = 'absolute';
-  span.style.whiteSpace = 'nowrap';
-  span.style.fontSize = `${fontSize}px`;
-  span.style.fontFamily = 'inherit';
-  span.innerText = text;
-
-  document.body.appendChild(span);
-  const width = span.offsetWidth;
-  document.body.removeChild(span);
-
-  return width;
-};
+  const span = document.createElement('span')
+  span.style.visibility = 'hidden'
+  span.style.position = 'absolute'
+  span.style.whiteSpace = 'nowrap'
+  span.style.fontSize = `${fontSize}px`
+  span.style.fontFamily = 'inherit'
+  span.innerText = text
+
+  document.body.appendChild(span)
+  const width = span.offsetWidth
+  document.body.removeChild(span)
+
+  return width
+}
 
 /** 计算列宽度 */
 const calculateColumnWidths = () => {
-  const MIN_WIDTH = 80; // 最小列宽
-  const PADDING = 25; // 列内边距
-  const FLEXIBLE_COLUMN = 'materialName'; // 可伸缩列
-  const scrollbarWidth = getScrollbarWidth(); // 动态获取滚动条宽度
+  const MIN_WIDTH = 80 // 最小列宽
+  const PADDING = 25 // 列内边距
+  const FLEXIBLE_COLUMN = 'materialName' // 可伸缩列
+  const scrollbarWidth = getScrollbarWidth() // 动态获取滚动条宽度
 
-  if (!tableContainerRef.value?.$el || list.value.length === 0) return;
+  if (!tableContainerRef.value?.$el || list.value.length === 0) return
 
-  const containerWidth = tableContainerRef.value.$el.clientWidth;
+  const containerWidth = tableContainerRef.value.$el.clientWidth
 
   // 需要自适应的列配置
   const autoColumns = [
     { key: 'factory', label: t('workOrderMaterial.factory'), getValue: (row) => row.factory },
-    { key: 'costCenter', label: t('workOrderMaterial.costCenter'), getValue: (row) => row.costCenter },
-    { key: 'materialCode', label: t('chooseMaintain.materialCode'), getValue: (row) => row.materialCode },
-    { key: 'materialName', label: t('chooseMaintain.materialName'), getValue: (row) => row.materialName },
+    {
+      key: 'costCenter',
+      label: t('workOrderMaterial.costCenter'),
+      getValue: (row) => row.costCenter
+    },
+    {
+      key: 'materialCode',
+      label: t('chooseMaintain.materialCode'),
+      getValue: (row) => row.materialCode
+    },
+    {
+      key: 'materialName',
+      label: t('chooseMaintain.materialName'),
+      getValue: (row) => row.materialName
+    },
     {
       key: 'quantity',
       label: t('route.quantity'),
@@ -284,63 +365,65 @@ const calculateColumnWidths = () => {
       label: t('stock.storageTime'),
       getValue: (row) => dateFormatter(null, null, row.storageTime)
     }
-  ];
+  ]
 
-  const newWidths: Record<string, string> = {};
-  let totalFixedWidth = 0; // 所有固定列的总宽度
+  const newWidths: Record<string, string> = {}
+  let totalFixedWidth = 0 // 所有固定列的总宽度
 
   // 计算除可伸缩列外的所有列宽度
-  autoColumns.forEach(col => {
-    if (col.key === FLEXIBLE_COLUMN) return;
+  autoColumns.forEach((col) => {
+    if (col.key === FLEXIBLE_COLUMN) return
 
-    const headerText = col.label;
-    const headerWidth = getTextWidth(headerText) * 1.3; // 表头宽度(加粗效果增加20%)
+    const headerText = col.label
+    const headerWidth = getTextWidth(headerText) * 1.3 // 表头宽度(加粗效果增加20%)
 
     // 计算内容最大宽度
-    let contentMaxWidth = 0;
-    list.value.forEach(row => {
-      const text = col.getValue ? String(col.getValue(row)) : String(row[col.key] || '');
-      const textWidth = getTextWidth(text);
-      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth;
-    });
+    let contentMaxWidth = 0
+    list.value.forEach((row) => {
+      const text = col.getValue ? String(col.getValue(row)) : String(row[col.key] || '')
+      const textWidth = getTextWidth(text)
+      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth
+    })
 
     // 取表头宽度、内容最大宽度和最小宽度的最大值
-    const finalWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING;
-    newWidths[col.key] = `${finalWidth}px`;
-    totalFixedWidth += finalWidth;
-  });
+    const finalWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING
+    newWidths[col.key] = `${finalWidth}px`
+    totalFixedWidth += finalWidth
+  })
 
   // 处理可伸缩列(materialName)
-  const flexibleCol = autoColumns.find(col => col.key === FLEXIBLE_COLUMN);
+  const flexibleCol = autoColumns.find((col) => col.key === FLEXIBLE_COLUMN)
   if (flexibleCol) {
-    const headerText = flexibleCol.label;
-    const headerWidth = getTextWidth(headerText) * 1.3;
-
-    let contentMaxWidth = 0;
-    list.value.forEach(row => {
-      const text = flexibleCol.getValue ? String(flexibleCol.getValue(row)) : String(row[flexibleCol.key] || '');
-      const textWidth = getTextWidth(text);
-      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth;
-    });
+    const headerText = flexibleCol.label
+    const headerWidth = getTextWidth(headerText) * 1.3
+
+    let contentMaxWidth = 0
+    list.value.forEach((row) => {
+      const text = flexibleCol.getValue
+        ? String(flexibleCol.getValue(row))
+        : String(row[flexibleCol.key] || '')
+      const textWidth = getTextWidth(text)
+      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth
+    })
 
-    const baseWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING;
+    const baseWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING
 
     // 剩余空间 = 容器宽度 - 其他列总宽度 - 垂直滚动条宽度(17px)
-    const remainingWidth = containerWidth - totalFixedWidth - scrollbarWidth;
+    const remainingWidth = containerWidth - totalFixedWidth - scrollbarWidth
 
     // 可伸缩列的宽度取剩余空间和基础宽度的最大值
-    const flexibleWidth = Math.max(remainingWidth, baseWidth);
-    newWidths[FLEXIBLE_COLUMN] = `${flexibleWidth}px`;
+    const flexibleWidth = Math.max(remainingWidth, baseWidth)
+    newWidths[FLEXIBLE_COLUMN] = `${flexibleWidth}px`
   }
 
   // 更新列宽度
-  columnWidths.value = newWidths;
+  columnWidths.value = newWidths
 
   // 重新布局表格
   nextTick(() => {
-    tableRef.value?.doLayout();
-  });
-};
+    tableRef.value?.doLayout()
+  })
+}
 
 /** 查询列表 */
 const getList = async () => {
@@ -413,7 +496,7 @@ const openForm = (type: string, id?: number) => {
     formRef.value.open(type, id)
     return
   }
-  push({ name: 'LockStockAdd', params:{} })
+  push({ name: 'LockStockAdd', params: {} })
 }
 
 /** 删除按钮操作 */
@@ -460,24 +543,21 @@ const selectedFactoryChange = async (selectedId: number | undefined) => {
   }
 
   // 获取选中的工厂对象
-  const selectedFactory = factoryList.value.find(item => item.id === selectedId)
+  const selectedFactory = factoryList.value.find((item) => item.id === selectedId)
   if (!selectedFactory) return
 
   // 根据工厂代码过滤成本中心
   filteredCostCenterList.value = costCenterList.value.filter(
-    item => item.factoryCode === selectedFactory.factoryCode
+    (item) => item.factoryCode === selectedFactory.factoryCode
   )
 }
 
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
     exportLoading.value = true
     const data = await IotLockStockApi.exportIotLockStock(queryParams)
-    download.excel(data, 'PMS 本地 库存.xls')
+    download.excel(data, 'PMS 本地库存.xls')
   } catch {
   } finally {
     exportLoading.value = false
@@ -497,10 +577,13 @@ onUnmounted(() => {
 })
 
 // 监听列表数据变化,重新计算列宽
-watch(list, () => {
-  nextTick(calculateColumnWidths)
-}, { deep: true })
-
+watch(
+  list,
+  () => {
+    nextTick(calculateColumnWidths)
+  },
+  { deep: true }
+)
 </script>
 
 <style scoped>
@@ -530,7 +613,7 @@ watch(list, () => {
 .stat-value {
   font-size: 18px;
   font-weight: bold;
-  color: #409EFF;
+  color: #409eff;
 }
 
 /* 表格容器样式 - 确保可以水平滚动 */
@@ -550,7 +633,6 @@ watch(list, () => {
   white-space: nowrap;
 }
 
-
 /* 防止表格内容换行 */
 :deep(.el-table .cell) {
   white-space: nowrap !important;
@@ -577,5 +659,4 @@ watch(list, () => {
   overflow: visible;
   text-overflow: unset;
 }
-
 </style>

+ 22 - 28
src/views/pms/iotmainworkorder/IotDeviceMainAlarm.vue

@@ -37,11 +37,10 @@
 
           <el-form-item>
             <el-button @click="handleQuery"
-              ><Icon icon="ep:search" class="mr-5px" />
-              {{ t('file.search') }}</el-button
+              ><Icon icon="ep:search" class="mr-5px" /> {{ t('file.search') }}</el-button
             >
             <el-button @click="resetQuery"
-              ><Icon icon="ep:refresh" class="mr-5px" />  {{ t('file.reset') }}</el-button
+              ><Icon icon="ep:refresh" class="mr-5px" /> {{ t('file.reset') }}</el-button
             >
             <el-button
               type="success"
@@ -125,17 +124,17 @@
       </ContentWrap>
     </el-col>
   </el-row>
-  <DeviceAlarmBomList ref="modelFormRef" :flag = "flag" />
+  <DeviceAlarmBomList ref="modelFormRef" :flag="flag" />
 </template>
 
 <script setup lang="ts">
 import download from '@/utils/download'
 import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
-import { IotMainWorkOrderApi, IotMainWorkOrderVO } from '@/api/pms/iotmainworkorder'
-import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
+import { IotMainWorkOrderApi } from '@/api/pms/iotmainworkorder'
+import { DICT_TYPE } from '@/utils/dict'
 import DeptTree from '@/views/system/user/DeptTree.vue'
-import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
-import DeviceAlarmBomList from "@/views/pms/iotmainworkorder/DeviceAlarmBomList.vue";
+import { useCache } from '@/hooks/web/useCache'
+import DeviceAlarmBomList from '@/views/pms/iotmainworkorder/DeviceAlarmBomList.vue'
 
 /** 设备台账 列表 */
 defineOptions({ name: 'IotDeviceMainAlarm' })
@@ -219,35 +218,33 @@ const resetQuery = () => {
 }
 
 const getDistanceClass = (distance: number | string | null) => {
-  if (distance === null || distance === undefined) return '';
+  if (distance === null || distance === undefined) return ''
 
   // 如果是数字类型,直接处理
   if (typeof distance === 'number') {
-    return distance < 0 ? 'negative-distance' :
-      distance > 0 ? 'positive-distance' : '';
+    return distance < 0 ? 'negative-distance' : distance > 0 ? 'positive-distance' : ''
   }
 
   // 如果是字符串,提取数字部分
   if (typeof distance === 'string') {
     // 使用正则提取数字部分(包括负号、小数点和科学计数法)
-    const numericPart = distance.match(/[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?/)?.[0];
+    const numericPart = distance.match(/[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?/)?.[0]
 
     // 如果提取到数字部分,转换为数值
     if (numericPart) {
-      const num = parseFloat(numericPart);
-      return num < 0 ? 'negative-distance' :
-        num > 0 ? 'positive-distance' : '';
+      const num = parseFloat(numericPart)
+      return num < 0 ? 'negative-distance' : num > 0 ? 'positive-distance' : ''
     }
   }
 
-  return '';
-};
+  return ''
+}
 
 // 判断是否有保养计划
 const hasMaintenancePlan = (mainDistance: any) => {
   // 检查:非null、非undefined、非空字符串
-  return mainDistance != null && mainDistance !== '';
-};
+  return mainDistance != null && mainDistance !== ''
+}
 
 const handleDetail = (id: number) => {
   push({ name: 'DeviceDetailInfo', params: { id } })
@@ -265,10 +262,10 @@ const openBomForm = async (row) => {
     model: row.model // 新增 model 属性
   }
   if (row.workOrderId) {
-    flag.value = 'workOrder';
+    flag.value = 'workOrder'
     modelFormRef.value.open(row.workOrderId, flag.value, row.id)
   } else if (row.planId) {
-    flag.value = 'plan';
+    flag.value = 'plan'
     modelFormRef.value.open(row.planId, flag.value, deviceInfo)
   }
 }
@@ -276,12 +273,9 @@ const openBomForm = async (row) => {
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
     exportLoading.value = true
-    const data = await IotDeviceApi.exportIotDevice(queryParams)
-    download.excel(data, '设备台账.xls')
+    const data = await IotDeviceApi.exportIotDeviceMainAlarm(queryParams)
+    download.excel(data, '保养查询.xls')
   } catch {
   } finally {
     exportLoading.value = false
@@ -296,7 +290,7 @@ onMounted(() => {
 <style scoped>
 /* 正数样式 - 淡绿色 */
 .positive-distance {
-  color: #67c23a;  /* element-plus 成功色 */
+  color: #67c23a; /* element-plus 成功色 */
   background-color: rgba(103, 194, 58, 0.1); /* 10% 透明度的淡绿色背景 */
   padding: 2px 8px;
   border-radius: 4px;
@@ -305,7 +299,7 @@ onMounted(() => {
 
 /* 负数样式 - 淡红色 */
 .negative-distance {
-  color: #f56c6c;  /* element-plus 危险色 */
+  color: #f56c6c; /* element-plus 危险色 */
   background-color: rgba(245, 108, 108, 0.1); /* 10% 透明度的淡红色背景 */
   padding: 2px 8px;
   border-radius: 4px;

+ 1 - 4
src/views/pms/iotmainworkorder/index.vue

@@ -726,11 +726,8 @@ const detail = (id?: number) => {
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
     exportLoading.value = true
-    const data = await IotMainWorkOrderApi.exportIotMainWorkOrder(queryParams)
+    const data = await IotMainWorkOrderApi.exportIotMainWorkOrderIndex(queryParams)
     download.excel(data, '保养工单.xls')
   } catch {
   } finally {

+ 2 - 9
src/views/pms/iotprojectinfo/index.vue

@@ -73,13 +73,8 @@
         >
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
-        <el-button
-          type="success"
-          plain
-          @click="handleExport"
-          :loading="exportLoading"
-          v-hasPermi="['rq:iot-project-info:export']"
-        >
+        <!-- v-hasPermi="['rq:iot-project-info:export']" -->
+        <el-button type="success" plain @click="handleExport" :loading="exportLoading">
           <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
       </el-form-item>
@@ -1001,8 +996,6 @@ const handleDelete = async (id: number) => {
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
     // 发起导出
     exportLoading.value = true
     const data = await IotProjectInfoApi.exportIotProjectInfo(queryParams)

+ 2 - 9
src/views/pms/iotprojecttask/index.vue

@@ -104,13 +104,8 @@
         >
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button> -->
-        <el-button
-          type="success"
-          plain
-          @click="handleExport"
-          :loading="exportLoading"
-          v-hasPermi="['rq:iot-project-task:export']"
-        >
+        <!-- v-hasPermi="['rq:iot-project-task:export']" -->
+        <el-button type="success" plain @click="handleExport" :loading="exportLoading">
           <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
       </el-form-item>
@@ -740,8 +735,6 @@ const handleDelete = async (id: number) => {
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
     // 发起导出
     exportLoading.value = true
     const data = await IotProjectTaskApi.exportIotProjectTask(queryParams)

+ 3 - 23
src/views/pms/iotrddailyreport/fillDailyReport.vue

@@ -60,13 +60,7 @@
             >
               <Icon icon="ep:plus" class="mr-5px" /> 新增
             </el-button>
-            <el-button
-              type="success"
-              plain
-              @click="handleExport"
-              :loading="exportLoading"
-              v-hasPermi="['pms:iot-rd-daily-report:export']"
-            >
+            <el-button type="success" plain @click="handleExport" :loading="exportLoading">
               <Icon icon="ep:download" class="mr-5px" /> 导出
             </el-button>
           </el-form-item>
@@ -167,7 +161,6 @@
 
 <script setup lang="ts">
 import { dateFormatter2 } from '@/utils/formatTime'
-import download from '@/utils/download'
 import { IotRdDailyReportApi, IotRdDailyReportVO } from '@/api/pms/iotrddailyreport'
 import { DICT_TYPE } from '@/utils/dict'
 import DeptTree2 from '@/views/pms/iotrhdailyreport/DeptTree2.vue'
@@ -328,7 +321,6 @@ const queryParams = reactive({
   createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
 
 /** 查询列表 */
 const getList = async () => {
@@ -399,20 +391,8 @@ const handleDetail = async (id: number) => {
   }
 }
 
-/** 导出按钮操作 */
-const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await IotRdDailyReportApi.exportIotRdDailyReport(queryParams)
-    download.excel(data, '瑞都日报.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
+const exportLoading = ref(false)
+const handleExport = async () => {}
 
 /** 初始化 **/
 onMounted(() => {

+ 3 - 23
src/views/pms/iotrddailyreport/index.vue

@@ -60,13 +60,7 @@
             >
               <Icon icon="ep:plus" class="mr-5px" /> 新增
             </el-button>
-            <el-button
-              type="success"
-              plain
-              @click="handleExport"
-              :loading="exportLoading"
-              v-hasPermi="['pms:iot-rd-daily-report:export']"
-            >
+            <el-button type="success" plain @click="handleExport" :loading="exportLoading">
               <Icon icon="ep:download" class="mr-5px" /> 导出
             </el-button>
           </el-form-item>
@@ -283,7 +277,6 @@
 
 <script setup lang="ts">
 import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
-import download from '@/utils/download'
 import { IotRdDailyReportApi, IotRdDailyReportVO } from '@/api/pms/iotrddailyreport'
 import IotRdDailyReportForm from './IotRdDailyReportForm.vue'
 import { DICT_TYPE } from '@/utils/dict'
@@ -447,7 +440,6 @@ const queryParams = reactive({
   createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
 
 const rootDeptId = ref(163)
 
@@ -695,20 +687,8 @@ const handleDelete = async (id: number) => {
   } catch {}
 }
 
-/** 导出按钮操作 */
-const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await IotRdDailyReportApi.exportIotRdDailyReport(queryParams)
-    download.excel(data, '瑞都日报.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
+const exportLoading = ref(false)
+const handleExport = async () => {}
 
 // 声明 ResizeObserver 实例
 let resizeObserver: ResizeObserver | null = null

+ 20 - 27
src/views/pms/iotrddailyreport/statistics.vue

@@ -46,12 +46,12 @@
             />
           </el-form-item>
           <el-form-item>
-            <el-button @click="handleQuery"
-              ><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button
-            >
-            <el-button @click="resetQuery"
-              ><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button
-            >
+            <el-button @click="handleQuery">
+              <Icon icon="ep:search" class="mr-5px" /> 搜索
+            </el-button>
+            <el-button @click="resetQuery">
+              <Icon icon="ep:refresh" class="mr-5px" /> 重置
+            </el-button>
             <el-button
               type="primary"
               plain
@@ -60,13 +60,7 @@
             >
               <Icon icon="ep:plus" class="mr-5px" /> 新增
             </el-button>
-            <el-button
-              type="success"
-              plain
-              @click="handleExport"
-              :loading="exportLoading"
-              v-hasPermi="['pms:iot-rd-daily-report:export']"
-            >
+            <el-button type="success" plain @click="handleExport" :loading="exportLoading">
               <Icon icon="ep:download" class="mr-5px" /> 导出
             </el-button>
           </el-form-item>
@@ -210,7 +204,6 @@
 
 <script setup lang="ts">
 import { dateFormatter } from '@/utils/formatTime'
-import download from '@/utils/download'
 import { IotRdDailyReportApi, IotRdDailyReportVO } from '@/api/pms/iotrddailyreport'
 import IotRdDailyReportForm from './IotRdDailyReportForm.vue'
 import { DICT_TYPE, getDictLabel } from '@/utils/dict'
@@ -219,6 +212,7 @@ import DeptTree2 from '@/views/pms/iotrhdailyreport/DeptTree2.vue'
 
 import dayjs from 'dayjs'
 import quarterOfYear from 'dayjs/plugin/quarterOfYear'
+import download from '@/utils/download'
 
 dayjs.extend(quarterOfYear)
 
@@ -369,7 +363,7 @@ const queryParams = reactive({
   createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
+// 导出的加载中
 
 const rootDeptId = ref(163)
 
@@ -609,19 +603,18 @@ const handleDelete = async (id: number) => {
   } catch {}
 }
 
-/** 导出按钮操作 */
+const exportLoading = ref(false)
 const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await IotRdDailyReportApi.exportIotRdDailyReport(queryParams)
-    download.excel(data, '瑞都日报.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
+  const res = await IotRdDailyReportApi.exportIotRdDailyReport({
+    createTime: queryParams.createTime,
+    contractName: queryParams.contractName,
+    taskName: queryParams.taskName,
+    // pageNo: queryParams.pageNo,
+    // pageSize: queryParams.pageSize,
+    deptId: queryParams.deptId
+  })
+
+  download.excel(res, '瑞都日报汇总.xlsx')
 }
 
 // 声明 ResizeObserver 实例

+ 3 - 2
src/views/pms/iotrddailyreport/summary.vue

@@ -11,6 +11,7 @@ import { Motion, AnimatePresence } from 'motion-v'
 import { rangeShortcuts } from '@/utils/formatTime'
 
 import { useUserStore } from '@/store/modules/user'
+import download from '@/utils/download'
 
 const deptId = useUserStore().getUser.deptId
 
@@ -476,8 +477,8 @@ const exportChart = () => {
 }
 
 const exportData = async () => {
-  // const res = await IotRdDailyReportApi.exportRdDailyReportStatistics(query.value)
-  // download.excel(res, '瑞恒日报统计数据.xlsx')
+  const res = await IotRdDailyReportApi.exportRdDailyReportStatistics(query.value)
+  download.excel(res, '瑞都日报统计数据.xlsx')
 }
 
 const exportAll = async () => {

+ 16 - 24
src/views/pms/iotrydailyreport/index.vue

@@ -63,21 +63,15 @@
             <el-button @click="resetQuery"
               ><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button
             >
-            <el-button
+            <!-- <el-button
               type="primary"
               plain
               @click="openForm('create')"
               v-hasPermi="['pms:iot-ry-daily-report:create']"
             >
               <Icon icon="ep:plus" class="mr-5px" /> 新增
-            </el-button>
-            <el-button
-              type="success"
-              plain
-              @click="handleExport"
-              :loading="exportLoading"
-              v-hasPermi="['pms:iot-ry-daily-report:export']"
-            >
+            </el-button> -->
+            <el-button type="success" plain @click="handleExport" :loading="exportLoading">
               <Icon icon="ep:download" class="mr-5px" /> 导出
             </el-button>
           </el-form-item>
@@ -441,7 +435,6 @@
 
 <script setup lang="ts">
 import { dateFormatter, dateFormatter2, rangeShortcuts } from '@/utils/formatTime'
-import download from '@/utils/download'
 import { IotRyDailyReportApi, IotRyDailyReportVO } from '@/api/pms/iotrydailyreport'
 import IotRyDailyReportForm from './IotRyDailyReportForm.vue'
 import { DICT_TYPE } from '@/utils/dict'
@@ -452,6 +445,7 @@ import quarterOfYear from 'dayjs/plugin/quarterOfYear'
 import { useDebounceFn } from '@vueuse/core'
 
 import { useUserStore } from '@/store/modules/user'
+import download from '@/utils/download'
 
 dayjs.extend(quarterOfYear)
 
@@ -513,7 +507,6 @@ let queryParams = reactive({
   nonProductFlag: 'N'
 })
 const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
 
 // 表格引用
 const tableRef = ref()
@@ -909,21 +902,20 @@ const handleDeptNodeClick = async (row) => {
   await getList()
 }
 
-/** 导出按钮操作 */
+const exportLoading = ref(false)
 const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await IotRyDailyReportApi.exportIotRyDailyReport(queryParams)
-    download.excel(data, '瑞鹰日报.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
+  const res = await IotRyDailyReportApi.exportIotRyDailyReport({
+    createTime: queryParams.createTime,
+    contractName: queryParams.contractName,
+    taskName: queryParams.taskName,
+    // pageNo: queryParams.pageNo,
+    // pageSize: queryParams.pageSize,
+    deptId: queryParams.deptId,
+    projectClassification: queryParams.projectClassification
+  })
 
+  download.excel(res, '瑞鹰钻井日报.xlsx')
+}
 // 声明 ResizeObserver 实例
 let resizeObserver: ResizeObserver | null = null
 

+ 15 - 23
src/views/pms/iotrydailyreport/xjindex.vue

@@ -63,21 +63,15 @@
             <el-button @click="resetQuery"
               ><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button
             >
-            <el-button
+            <!-- <el-button
               type="primary"
               plain
               @click="openForm('create')"
               v-hasPermi="['pms:iot-rh-daily-report:create']"
             >
               <Icon icon="ep:plus" class="mr-5px" /> 新增
-            </el-button>
-            <el-button
-              type="success"
-              plain
-              @click="handleExport"
-              :loading="exportLoading"
-              v-hasPermi="['pms:iot-rh-daily-report:export']"
-            >
+            </el-button> -->
+            <el-button type="success" plain @click="handleExport" :loading="exportLoading">
               <Icon icon="ep:download" class="mr-5px" /> 导出
             </el-button>
           </el-form-item>
@@ -470,7 +464,6 @@ let queryParams = reactive({
   nonProductFlag: 'N'
 })
 const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
 
 const rootDeptId = ref(useUserStore().getUser.deptId)
 
@@ -922,21 +915,20 @@ const handleDeptNodeClick = async (row) => {
   await getList()
 }
 
-/** 导出按钮操作 */
+const exportLoading = ref(false)
 const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await IotRyDailyReportApi.exportIotRyDailyReport(queryParams)
-    download.excel(data, '瑞鹰日报.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
+  const res = await IotRyDailyReportApi.exportIotRyDailyReport({
+    createTime: queryParams.createTime,
+    contractName: queryParams.contractName,
+    taskName: queryParams.taskName,
+    // pageNo: queryParams.pageNo,
+    // pageSize: queryParams.pageSize,
+    deptId: queryParams.deptId,
+    projectClassification: queryParams.projectClassification
+  })
 
+  download.excel(res, '瑞鹰修井日报.xlsx')
+}
 // 声明 ResizeObserver 实例
 let resizeObserver: ResizeObserver | null = null
 

+ 200 - 112
src/views/pms/iotsapstock/index.vue

@@ -9,7 +9,14 @@
       label-width="68px"
     >
       <el-form-item :label="t('workOrderMaterial.factory')" prop="factoryId">
-        <el-select v-model="queryParams.factoryId" clearable filterable :placeholder="t('faultForm.choose')" class="!w-240px" @change="selectedFactoryChange">
+        <el-select
+          v-model="queryParams.factoryId"
+          clearable
+          filterable
+          :placeholder="t('faultForm.choose')"
+          class="!w-240px"
+          @change="selectedFactoryChange"
+        >
           <el-option
             v-for="item in factoryList"
             :key="item.id"
@@ -18,8 +25,18 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item :label="t('workOrderMaterial.storageLocation')" prop="storageLocationId" style="margin-left: 28px">
-        <el-select v-model="queryParams.storageLocationId" clearable filterable :placeholder="t('faultForm.choose')" class="!w-240px">
+      <el-form-item
+        :label="t('workOrderMaterial.storageLocation')"
+        prop="storageLocationId"
+        style="margin-left: 28px"
+      >
+        <el-select
+          v-model="queryParams.storageLocationId"
+          clearable
+          filterable
+          :placeholder="t('faultForm.choose')"
+          class="!w-240px"
+        >
           <el-option
             v-for="item in storageLocationList"
             :key="item.id"
@@ -73,15 +90,14 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> {{ t('operationFill.search') }}</el-button>
-        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />  {{ t('operationFill.reset') }}</el-button>
-        <el-button
-          type="success"
-          plain
-          @click="handleExport"
-          :loading="exportLoading"
-          v-hasPermi="['pms:iot-sap-stock:export']"
+        <el-button @click="handleQuery"
+          ><Icon icon="ep:search" class="mr-5px" /> {{ t('operationFill.search') }}</el-button
+        >
+        <el-button @click="resetQuery"
+          ><Icon icon="ep:refresh" class="mr-5px" /> {{ t('operationFill.reset') }}</el-button
         >
+        <!-- v-hasPermi="['pms:iot-sap-stock:export']" -->
+        <el-button type="success" plain @click="handleExport" :loading="exportLoading">
           <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
       </el-form-item>
@@ -98,7 +114,15 @@
         </div>
         <div class="stat-item">
           <span class="stat-label">{{ t('stock.totalAmount') }}:</span>
-          <span class="stat-value">¥ {{ totalAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}</span>
+          <span class="stat-value"
+            >¥
+            {{
+              totalAmount.toLocaleString(undefined, {
+                minimumFractionDigits: 2,
+                maximumFractionDigits: 2
+              })
+            }}</span
+          >
         </div>
       </div>
     </el-card>
@@ -106,18 +130,62 @@
 
   <!-- 列表 -->
   <ContentWrap ref="tableContainerRef" class="table-container">
-    <el-table ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="false" style="width: 100%">
-      <el-table-column :label="t('workOrderMaterial.factory')" align="center" prop="factory" :width="columnWidths.factory"/>
-      <el-table-column :label="t('workOrderMaterial.storageLocation')" align="center"
-                       prop="projectDepartment" :width="columnWidths.projectDepartment"/>
-      <el-table-column :label="t('chooseMaintain.materialCode')" align="center"
-                       prop="materialCode" :width="columnWidths.materialCode"/>
-      <el-table-column :label="t('chooseMaintain.materialName')" align="left"
-                       prop="materialName" :width="columnWidths.materialName"/>
-      <el-table-column :label="t('route.quantity')" align="center" prop="quantity" :width="columnWidths.quantity"/>
-      <el-table-column :label="t('workOrderMaterial.unitPrice')" align="center" prop="unitPrice" :width="columnWidths.unitPrice"/>
-      <el-table-column :label="t('workOrderMaterial.unit')" align="center" prop="unit" :width="columnWidths.unit"/>
-      <el-table-column :label="t('route.safetyStock')" align="center" prop="safetyStock" :width="columnWidths.safetyStock"/>
+    <el-table
+      ref="tableRef"
+      v-loading="loading"
+      :data="list"
+      :stripe="true"
+      :show-overflow-tooltip="false"
+      style="width: 100%"
+    >
+      <el-table-column
+        :label="t('workOrderMaterial.factory')"
+        align="center"
+        prop="factory"
+        :width="columnWidths.factory"
+      />
+      <el-table-column
+        :label="t('workOrderMaterial.storageLocation')"
+        align="center"
+        prop="projectDepartment"
+        :width="columnWidths.projectDepartment"
+      />
+      <el-table-column
+        :label="t('chooseMaintain.materialCode')"
+        align="center"
+        prop="materialCode"
+        :width="columnWidths.materialCode"
+      />
+      <el-table-column
+        :label="t('chooseMaintain.materialName')"
+        align="left"
+        prop="materialName"
+        :width="columnWidths.materialName"
+      />
+      <el-table-column
+        :label="t('route.quantity')"
+        align="center"
+        prop="quantity"
+        :width="columnWidths.quantity"
+      />
+      <el-table-column
+        :label="t('workOrderMaterial.unitPrice')"
+        align="center"
+        prop="unitPrice"
+        :width="columnWidths.unitPrice"
+      />
+      <el-table-column
+        :label="t('workOrderMaterial.unit')"
+        align="center"
+        prop="unit"
+        :width="columnWidths.unit"
+      />
+      <el-table-column
+        :label="t('route.safetyStock')"
+        align="center"
+        prop="safetyStock"
+        :width="columnWidths.safetyStock"
+      />
       <el-table-column
         :label="t('chooseMaintain.createTime')"
         align="center"
@@ -144,7 +212,7 @@ import { dateFormatter } from '@/utils/formatTime'
 import download from '@/utils/download'
 import { IotSapStockApi, IotSapStockVO } from '@/api/pms/iotsapstock'
 import IotSapStockForm from './IotSapStockForm.vue'
-import * as SapOrgApi from "@/api/system/saporg";
+import * as SapOrgApi from '@/api/system/saporg'
 
 /** PMS SAP 库存(通用库存/项目部库存) 列表 */
 defineOptions({ name: 'IotSapStock' })
@@ -152,11 +220,11 @@ defineOptions({ name: 'IotSapStock' })
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
-const factoryList = ref([] as SapOrgApi.SapOrgVO[])   // 工厂列表
+const factoryList = ref([] as SapOrgApi.SapOrgVO[]) // 工厂列表
 const storageLocationList = ref([] as SapOrgApi.SapOrgVO[]) // 库存地点列表
 // 新增统计变量
-const totalQuantity = ref(0)   // 总数量
-const totalAmount = ref(0)     // 总金额
+const totalQuantity = ref(0) // 总数量
+const totalAmount = ref(0) // 总金额
 
 const loading = ref(true) // 列表的加载中
 const list = ref<IotSapStockVO[]>([]) // 列表的数据
@@ -187,7 +255,7 @@ const queryParams = reactive({
   status: undefined,
   remark: undefined,
   configFlag: 'A',
-  createTime: [],
+  createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
@@ -211,120 +279,142 @@ const columnWidths = ref({
 
 /** 获取滚动条宽度 */
 const getScrollbarWidth = () => {
-  const outer = document.createElement('div');
-  outer.style.visibility = 'hidden';
-  outer.style.overflow = 'scroll';
-  document.body.appendChild(outer);
+  const outer = document.createElement('div')
+  outer.style.visibility = 'hidden'
+  outer.style.overflow = 'scroll'
+  document.body.appendChild(outer)
 
-  const inner = document.createElement('div');
-  outer.appendChild(inner);
+  const inner = document.createElement('div')
+  outer.appendChild(inner)
 
-  const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
-  outer.parentNode?.removeChild(outer);
+  const scrollbarWidth = outer.offsetWidth - inner.offsetWidth
+  outer.parentNode?.removeChild(outer)
 
-  return scrollbarWidth;
-};
+  return scrollbarWidth
+}
 
 /** 计算文本宽度 */
 const getTextWidth = (text: string, fontSize = 14) => {
-  const span = document.createElement('span');
-  span.style.visibility = 'hidden';
-  span.style.position = 'absolute';
-  span.style.whiteSpace = 'nowrap';
-  span.style.fontSize = `${fontSize}px`;
-  span.style.fontFamily = 'inherit';
-  span.innerText = text;
-
-  document.body.appendChild(span);
-  const width = span.offsetWidth;
-  document.body.removeChild(span);
-
-  return width;
-};
+  const span = document.createElement('span')
+  span.style.visibility = 'hidden'
+  span.style.position = 'absolute'
+  span.style.whiteSpace = 'nowrap'
+  span.style.fontSize = `${fontSize}px`
+  span.style.fontFamily = 'inherit'
+  span.innerText = text
+
+  document.body.appendChild(span)
+  const width = span.offsetWidth
+  document.body.removeChild(span)
+
+  return width
+}
 
 /** 计算列宽度 */
 const calculateColumnWidths = () => {
-  const MIN_WIDTH = 80; // 最小列宽
-  const PADDING = 25; // 列内边距
-  const FLEXIBLE_COLUMN = 'materialName'; // 可伸缩列
-  const scrollbarWidth = getScrollbarWidth(); // 动态获取滚动条宽度
+  const MIN_WIDTH = 80 // 最小列宽
+  const PADDING = 25 // 列内边距
+  const FLEXIBLE_COLUMN = 'materialName' // 可伸缩列
+  const scrollbarWidth = getScrollbarWidth() // 动态获取滚动条宽度
 
-  if (!tableContainerRef.value?.$el || list.value.length === 0) return;
+  if (!tableContainerRef.value?.$el || list.value.length === 0) return
 
-  const containerWidth = tableContainerRef.value.$el.clientWidth;
+  const containerWidth = tableContainerRef.value.$el.clientWidth
 
   // 需要自适应的列配置
   const autoColumns = [
     { key: 'factory', label: t('workOrderMaterial.factory'), getValue: (row) => row.factory },
-    { key: 'projectDepartment', label: t('workOrderMaterial.storageLocation'), getValue: (row) => row.projectDepartment },
-    { key: 'materialCode', label: t('chooseMaintain.materialCode'), getValue: (row) => row.materialCode },
-    { key: 'materialName', label: t('chooseMaintain.materialName'), getValue: (row) => row.materialName },
+    {
+      key: 'projectDepartment',
+      label: t('workOrderMaterial.storageLocation'),
+      getValue: (row) => row.projectDepartment
+    },
+    {
+      key: 'materialCode',
+      label: t('chooseMaintain.materialCode'),
+      getValue: (row) => row.materialCode
+    },
+    {
+      key: 'materialName',
+      label: t('chooseMaintain.materialName'),
+      getValue: (row) => row.materialName
+    },
     { key: 'quantity', label: t('route.quantity'), getValue: (row) => String(row.quantity) },
-    { key: 'unitPrice', label: t('workOrderMaterial.unitPrice'), getValue: (row) => String(row.unitPrice) },
+    {
+      key: 'unitPrice',
+      label: t('workOrderMaterial.unitPrice'),
+      getValue: (row) => String(row.unitPrice)
+    },
     { key: 'unit', label: t('workOrderMaterial.unit'), getValue: (row) => row.unit },
-    { key: 'safetyStock', label: t('route.safetyStock'), getValue: (row) => String(row.safetyStock) },
+    {
+      key: 'safetyStock',
+      label: t('route.safetyStock'),
+      getValue: (row) => String(row.safetyStock)
+    },
     {
       key: 'createTime',
       label: t('chooseMaintain.createTime'),
       getValue: (row) => dateFormatter(null, null, row.createTime)
     }
-  ];
+  ]
 
-  const newWidths: Record<string, string> = {};
-  let totalFixedWidth = 0; // 所有固定列的总宽度
+  const newWidths: Record<string, string> = {}
+  let totalFixedWidth = 0 // 所有固定列的总宽度
 
   // 计算除可伸缩列外的所有列宽度
-  autoColumns.forEach(col => {
-    if (col.key === FLEXIBLE_COLUMN) return;
+  autoColumns.forEach((col) => {
+    if (col.key === FLEXIBLE_COLUMN) return
 
-    const headerText = col.label;
-    const headerWidth = getTextWidth(headerText) * 1.3; // 表头宽度(加粗效果增加30%)
+    const headerText = col.label
+    const headerWidth = getTextWidth(headerText) * 1.3 // 表头宽度(加粗效果增加30%)
 
     // 计算内容最大宽度
-    let contentMaxWidth = 0;
-    list.value.forEach(row => {
-      const text = col.getValue ? String(col.getValue(row)) : String(row[col.key] || '');
-      const textWidth = getTextWidth(text);
-      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth;
-    });
+    let contentMaxWidth = 0
+    list.value.forEach((row) => {
+      const text = col.getValue ? String(col.getValue(row)) : String(row[col.key] || '')
+      const textWidth = getTextWidth(text)
+      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth
+    })
 
     // 取表头宽度、内容最大宽度和最小宽度的最大值
-    const finalWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING;
-    newWidths[col.key] = `${finalWidth}px`;
-    totalFixedWidth += finalWidth;
-  });
+    const finalWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING
+    newWidths[col.key] = `${finalWidth}px`
+    totalFixedWidth += finalWidth
+  })
 
   // 处理可伸缩列(materialName)
-  const flexibleCol = autoColumns.find(col => col.key === FLEXIBLE_COLUMN);
+  const flexibleCol = autoColumns.find((col) => col.key === FLEXIBLE_COLUMN)
   if (flexibleCol) {
-    const headerText = flexibleCol.label;
-    const headerWidth = getTextWidth(headerText) * 1.3;
-
-    let contentMaxWidth = 0;
-    list.value.forEach(row => {
-      const text = flexibleCol.getValue ? String(flexibleCol.getValue(row)) : String(row[flexibleCol.key] || '');
-      const textWidth = getTextWidth(text);
-      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth;
-    });
+    const headerText = flexibleCol.label
+    const headerWidth = getTextWidth(headerText) * 1.3
+
+    let contentMaxWidth = 0
+    list.value.forEach((row) => {
+      const text = flexibleCol.getValue
+        ? String(flexibleCol.getValue(row))
+        : String(row[flexibleCol.key] || '')
+      const textWidth = getTextWidth(text)
+      if (textWidth > contentMaxWidth) contentMaxWidth = textWidth
+    })
 
-    const baseWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING;
+    const baseWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING
 
     // 剩余空间 = 容器宽度 - 其他列总宽度 - 垂直滚动条宽度
-    const remainingWidth = containerWidth - totalFixedWidth - scrollbarWidth;
+    const remainingWidth = containerWidth - totalFixedWidth - scrollbarWidth
 
     // 可伸缩列的宽度取剩余空间和基础宽度的最大值
-    const flexibleWidth = Math.max(remainingWidth, baseWidth);
-    newWidths[FLEXIBLE_COLUMN] = `${flexibleWidth}px`;
+    const flexibleWidth = Math.max(remainingWidth, baseWidth)
+    newWidths[FLEXIBLE_COLUMN] = `${flexibleWidth}px`
   }
 
   // 更新列宽度
-  columnWidths.value = newWidths;
+  columnWidths.value = newWidths
 
   // 重新布局表格
   nextTick(() => {
-    tableRef.value?.doLayout();
-  });
-};
+    tableRef.value?.doLayout()
+  })
+}
 
 /** 查询列表 */
 const getList = async () => {
@@ -381,9 +471,8 @@ const selectedFactoryReqVO = ref({
 
 /** 已经选择了 SAP工厂 */
 const selectedFactoryChange = async (selectedId: number | undefined) => {
-
   // 获取选中的factoryCode数组
-  const selectedFactory = factoryList.value.find(item => item.id === selectedId)
+  const selectedFactory = factoryList.value.find((item) => item.id === selectedId)
   const selectedFactoryCodes = selectedFactory ? [selectedFactory.factoryCode] : []
 
   // 获得已经选择的 SAP 工厂 数组
@@ -408,7 +497,7 @@ const resultOptions = computed(() => [
   {
     label: '否',
     value: 'N' // 空值会触发 clearable 效果
-  },
+  }
 ])
 
 /** 删除按钮操作 */
@@ -427,12 +516,9 @@ const handleDelete = async (id: number) => {
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
     exportLoading.value = true
     const data = await IotSapStockApi.exportIotSapStock(queryParams)
-    download.excel(data, 'PMS SAP 库存(通用库存/项目部库存).xls')
+    download.excel(data, 'SPA库存.xls')
   } catch {
   } finally {
     exportLoading.value = false
@@ -452,10 +538,13 @@ onUnmounted(() => {
 })
 
 // 监听列表数据变化,重新计算列宽
-watch(list, () => {
-  nextTick(calculateColumnWidths)
-}, { deep: true })
-
+watch(
+  list,
+  () => {
+    nextTick(calculateColumnWidths)
+  },
+  { deep: true }
+)
 </script>
 
 <style scoped>
@@ -485,7 +574,7 @@ watch(list, () => {
 .stat-value {
   font-size: 18px;
   font-weight: bold;
-  color: #409EFF;
+  color: #409eff;
 }
 
 /* 表格容器样式 - 确保可以水平滚动 */
@@ -526,5 +615,4 @@ watch(list, () => {
   overflow: visible;
   text-overflow: unset;
 }
-
 </style>

+ 0 - 2
src/views/pms/maintenance/index.vue

@@ -252,8 +252,6 @@ const handleDelete = async (id: number) => {
 /** 导出按钮操作 */
 const handleExport = async () => {
   try {
-    // 导出的二次确认
-    await message.exportConfirm()
     // 发起导出
     exportLoading.value = true
     const data = await IotMaintenancePlanApi.exportIotMaintenancePlan(queryParams)

+ 25 - 1
src/views/report-statistics/costs.vue

@@ -4,6 +4,7 @@ import dayjs from 'dayjs'
 import CountTo from '@/components/count-to1.vue'
 import { IotReportApi } from '@/api/pms/report'
 import { useDebounceFn } from '@vueuse/core'
+import download from '@/utils/download'
 
 // 定义时间类型
 type TimeType = 'year' | 'month' | 'day'
@@ -201,6 +202,18 @@ function handleReset() {
   handleTimeChange('year')
   selectType(undefined)
 }
+
+const exportLoading = ref(false)
+
+const handleExport = async () => {
+  exportLoading.value = true
+  try {
+    const data = await IotReportApi.exportCosts(query.value)
+    download.excel(data, '运维成本.xls')
+  } finally {
+    exportLoading.value = false
+  }
+}
 </script>
 
 <template>
@@ -300,7 +313,18 @@ function handleReset() {
             {{ item.label }}
           </el-button>
         </el-button-group>
-        <el-button size="default" @click="handleReset">重置</el-button>
+        <div class="flex items-center gap-2">
+          <el-button size="default" @click="handleReset">重置</el-button>
+          <el-button
+            size="default"
+            plain
+            type="success"
+            @click="handleExport"
+            :loading="exportLoading"
+          >
+            <Icon icon="ep:download" class="mr-5px" /> 导出
+          </el-button>
+        </div>
       </div>
     </div>
     <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col mt-4">

+ 21 - 0
src/views/report-statistics/rd-daily-report.vue

@@ -5,6 +5,7 @@ import { useDebounceFn } from '@vueuse/core'
 import dayjs from 'dayjs'
 import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 import { useUserStore } from '@/store/modules/user'
+import download from '@/utils/download'
 
 defineOptions({ name: 'DailyReport' })
 
@@ -366,6 +367,23 @@ watch(
 const expandRowKeys = computed(() => {
   return list.value.filter((item) => item.lastGroupIdFlag).map((item) => item.id.toString())
 })
+
+const exportLoading = ref(false)
+
+const handleExport = () => {
+  exportLoading.value = true
+  if (tab.value === '井') {
+    IotRdDailyReportApi.exportIotRdDailyReportWell(query.value).then((data) => {
+      download.excel(data, '瑞都井日报统计.xls')
+      exportLoading.value = false
+    })
+  } else {
+    IotRdDailyReportApi.exportIotRdDailyReportTeam(query.value).then((data) => {
+      download.excel(data, '瑞都队伍日报统计.xls')
+      exportLoading.value = false
+    })
+  }
+}
 </script>
 
 <template>
@@ -416,6 +434,9 @@ const expandRowKeys = computed(() => {
           <Icon icon="ep:search" class="mr-5px" /> 搜索
         </el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
+        <el-button plain type="success" @click="handleExport" :loading="exportLoading">
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
       </el-form-item>
     </el-form>
 

+ 26 - 22
src/views/report-statistics/ry-daily-report.vue

@@ -6,6 +6,7 @@ import dayjs from 'dayjs'
 import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 import { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'
 import { useUserStore } from '@/store/modules/user'
+import download from '@/utils/download'
 
 defineOptions({ name: 'DailyReport' })
 
@@ -116,26 +117,6 @@ const columns = ref<Column[]>([
     dictType: DICT_TYPE.PMS_PROJECT_TASK_RY_SCHEDULE,
     fixed: 'left'
   },
-  // {
-  //   label: '审批状态',
-  //   prop: 'auditStatus',
-  //   'min-width': '120px',
-  //   isTag: true,
-  //   formatter: (row: List) => {
-  //     switch (row.auditStatus) {
-  //       case 0:
-  //         return '待提交'
-  //       case 10:
-  //         return '待审批'
-  //       case 20:
-  //         return '审批通过'
-  //       case 30:
-  //         return '审批拒绝'
-  //       default:
-  //         return ''
-  //     }
-  //   }
-  // },
   {
     label: '设备型号',
     prop: 'equipmentType',
@@ -460,6 +441,7 @@ interface Query {
   taskName?: string
   wellName?: string
   createTime: string[]
+  projectClassification: number
 }
 
 const query = ref<Query>({
@@ -468,7 +450,8 @@ const query = ref<Query>({
   deptId: id,
   createTime: [
     ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
-  ]
+  ],
+  projectClassification: 1
 })
 
 function handleSizeChange(val: number) {
@@ -527,7 +510,8 @@ function resetQuery() {
     taskName: '',
     createTime: [
       ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
-    ]
+    ],
+    projectClassification: 1
   }
   handleQuery()
 }
@@ -549,6 +533,23 @@ watch(
 const expandRowKeys = computed(() => {
   return list.value.filter((item) => item.lastGroupIdFlag).map((item) => item.id.toString())
 })
+
+const exportLoading = ref(false)
+
+const handleExport = () => {
+  exportLoading.value = true
+  if (tab.value === '井') {
+    IotRyDailyReportApi.exportIotRyDailyReportWell(query.value).then((data) => {
+      download.excel(data, '瑞鹰钻井井日报统计.xls')
+      exportLoading.value = false
+    })
+  } else {
+    IotRyDailyReportApi.exportIotRyDailyReportTeam(query.value).then((data) => {
+      download.excel(data, '瑞鹰钻井队伍日报统计.xls')
+      exportLoading.value = false
+    })
+  }
+}
 </script>
 
 <template>
@@ -599,6 +600,9 @@ const expandRowKeys = computed(() => {
           <Icon icon="ep:search" class="mr-5px" /> 搜索
         </el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
+        <el-button plain type="success" @click="handleExport" :loading="exportLoading">
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
       </el-form-item>
     </el-form>
 

+ 661 - 0
src/views/report-statistics/ry-xj-daily-report.vue

@@ -0,0 +1,661 @@
+<script lang="ts" setup>
+import { IotRyDailyReportApi } from '@/api/pms/iotrydailyreport'
+import { rangeShortcuts } from '@/utils/formatTime'
+import { useDebounceFn } from '@vueuse/core'
+import dayjs from 'dayjs'
+import { DICT_TYPE, getDictOptions } from '@/utils/dict'
+import { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'
+import { useUserStore } from '@/store/modules/user'
+import download from '@/utils/download'
+
+defineOptions({ name: 'DailyReport' })
+
+const tab = ref('井')
+const tabOptions = ['井', '队伍']
+
+interface List {
+  id: number
+  deptId: number
+  projectId: number
+  taskId: number
+  projectClassification: string
+  relocationDays: number
+  latestWellDoneTime: number
+  currentDepth: number
+  dailyFootage: number
+  monthlyFootage: number
+  annualFootage: number
+  dailyPowerUsage: number
+  monthlyPowerUsage: number
+  dailyFuel: number
+  monthlyFuel: number
+  dailyOilVolume: number
+  remainDieselVolume: number
+  productionTime: number
+  nonProductionTime: number
+  ryNptReason: string
+  drillingWorkingTime: number
+  otherProductionTime: number
+  accidentTime: number
+  repairTime: number
+  selfStopTime: number
+  complexityTime: number
+  relocationTime: number
+  rectificationTime: number
+  waitingStopTime: number
+  winterBreakTime: number
+  constructionStartDate: number
+  constructionEndDate: number
+  productionStatus: string
+  currentOperation: string
+  nextPlan: string
+  rigStatus: string
+  repairStatus: string
+  personnel: string
+  totalStaffNum: number
+  leaveStaffNum: number
+  mudDensity: number
+  mudViscosity: number
+  lateralLength: number
+  wellInclination: number
+  azimuth: number
+  remark: string
+  status: number
+  processInstanceId: string
+  auditStatus: number
+  opinion: string
+  createTime: number
+  deptName: string
+  contractName: string
+  taskName: string
+  designWellDepth: number
+  designWellStruct: number
+  totalConstructionWells: number
+  completedWells: number
+  equipmentType: string
+  transitTime: number
+  lastCurrentDepth: number
+  lastGroupIdFlag: boolean
+  technique: string
+  wellCategory: string
+  casingPipeSize: number
+  wellControlLevel: string
+  ratedProductionTime: number
+  onDutyStaffNum: number
+  offDutyStaffNum: number
+}
+
+interface Column {
+  prop?: keyof List
+  label: string
+  'min-width'?: string
+  isTag?: boolean
+  fixed?: 'left' | 'right'
+  formatter?: (row: List) => any
+  children?: Column[]
+  dictType?: string
+}
+
+const { t } = useI18n()
+
+const columns = ref<Column[]>([
+  {
+    label: '日期',
+    prop: 'createTime',
+    'min-width': '120px',
+    formatter: (row: List) => dayjs(row.createTime).format('YYYY-MM-DD'),
+    fixed: 'left'
+  },
+  {
+    label: '施工队伍',
+    prop: 'deptName',
+    'min-width': '120px',
+    fixed: 'left'
+  },
+  {
+    label: '任务',
+    prop: 'taskName',
+    'min-width': '120px',
+    fixed: 'left'
+  },
+  {
+    label: '施工状态',
+    prop: 'rigStatus',
+    'min-width': '120px',
+    isTag: true,
+    dictType: DICT_TYPE.PMS_PROJECT_TASK_RY_SCHEDULE,
+    fixed: 'left'
+  },
+  {
+    label: '总施工井数',
+    prop: 'totalConstructionWells',
+    'min-width': '120px'
+  },
+  {
+    label: '完工井数',
+    prop: 'completedWells',
+    'min-width': '120px'
+  },
+  {
+    label: t('project.technology'),
+    prop: 'technique',
+    'min-width': '120px',
+    isTag: true,
+    dictType: DICT_TYPE.PMS_PROJECT_RY_TECHNOLOGY
+  },
+  {
+    label: '井别',
+    prop: 'wellCategory',
+    'min-width': '120px'
+  },
+  {
+    label: '井深(m)',
+    prop: 'designWellDepth',
+    'min-width': '120px'
+  },
+  {
+    label: '套生段产管尺寸(mm)',
+    prop: 'casingPipeSize',
+    'min-width': '120px'
+  },
+  {
+    label: '井控级别',
+    prop: 'wellControlLevel',
+    'min-width': '120px'
+  },
+  {
+    label: '当日',
+    children: [
+      {
+        label: '用电量(MWh)',
+        prop: 'dailyPowerUsage',
+        'min-width': '120px'
+      },
+      {
+        label: '油耗(升)',
+        prop: 'dailyFuel',
+        'min-width': '120px'
+      }
+    ]
+  },
+  {
+    label: t('project.currentOperation'),
+    prop: 'currentOperation',
+    'min-width': '120px'
+  },
+  {
+    label: t('project.nextPlan'),
+    prop: 'nextPlan',
+    'min-width': '120px'
+  },
+  {
+    label: t('project.transitTime'),
+    prop: 'transitTime',
+    'min-width': '120px',
+    formatter: (row: List) => (row.transitTime ? (row.transitTime * 100).toFixed(2) + '%' : '-')
+  },
+  {
+    label: '额定生产时间(H)',
+    prop: 'ratedProductionTime',
+    'min-width': '120px'
+  },
+  {
+    label: '生产时间(H)',
+    prop: 'productionTime',
+    'min-width': '120px'
+  },
+  {
+    label: '非生产时间(H)',
+    prop: 'nonProductionTime',
+    'min-width': '120px'
+  },
+  {
+    label: '非生产时间原因',
+    prop: 'ryNptReason',
+    'min-width': '120px',
+    isTag: true,
+    dictType: DICT_TYPE.PMS_PROJECT_RY_NPT_REASON
+  },
+  {
+    label: '生产动态',
+    prop: 'productionStatus',
+    'min-width': '120px'
+  },
+  {
+    label: '项目',
+    prop: 'contractName',
+    'min-width': '120px'
+  },
+  {
+    label: '全员数量',
+    prop: 'totalStaffNum',
+    'min-width': '120px'
+  },
+  {
+    label: '在岗人数',
+    prop: 'onDutyStaffNum',
+    'min-width': '120px',
+    formatter: (row: List) => (Number(row.totalStaffNum) || 0) - (Number(row.offDutyStaffNum) || 0)
+  },
+  {
+    label: '休假人员数量',
+    prop: 'leaveStaffNum',
+    'min-width': '120px'
+  }
+])
+
+const getTextWidth = (text: string, fontSize = 12) => {
+  const span = document.createElement('span')
+  span.style.visibility = 'hidden'
+  span.style.position = 'absolute'
+  span.style.whiteSpace = 'nowrap'
+  span.style.fontSize = `${fontSize}px`
+  span.style.fontFamily = 'PingFang SC'
+  span.innerText = text
+
+  document.body.appendChild(span)
+  const width = span.offsetWidth
+  document.body.removeChild(span)
+
+  return width
+}
+
+const calculateColumnWidths = (colums: Column[]) => {
+  for (const col of colums) {
+    let { formatter, prop, label, 'min-width': minWidth, isTag, children } = col
+
+    if (children && children.length > 0) {
+      calculateColumnWidths(children)
+      continue
+    }
+
+    minWidth =
+      Math.min(
+        ...[
+          Math.max(
+            ...[
+              getTextWidth(label),
+              ...list.value.map((v) => {
+                let tagLabel = ''
+                if (col.dictType) {
+                  const option = getDictOptions(col.dictType).find(
+                    (item) => item.value === v[prop!]
+                  )
+                  if (option) tagLabel = option.label
+                }
+                return getTextWidth(
+                  formatter ? formatter(v) : Boolean(tagLabel) ? tagLabel : v[prop!]
+                )
+              })
+            ]
+          ) + (isTag ? 40 : 20),
+          ...(isTag ? [] : [200])
+        ]
+      ) + 'px'
+
+    col['min-width'] = minWidth
+  }
+}
+
+function checkTimeSumEquals24(row: List) {
+  // 获取三个字段的值,转换为数字,如果为空则视为0
+  const gasTime = row.drillingWorkingTime || 0
+  const waterTime = row.otherProductionTime || 0
+  const nonProdTime =
+    row.accidentTime ||
+    0 + row.repairTime ||
+    0 + row.selfStopTime ||
+    0 + row.complexityTime ||
+    0 + row.relocationTime ||
+    0 + row.rectificationTime ||
+    0 + row.waitingStopTime ||
+    0 + row.winterBreakTime ||
+    0
+
+  // 计算总和
+  const sum = gasTime + waterTime + nonProdTime
+
+  // 返回是否等于24(允许一定的浮点数误差)
+  return Math.abs(sum - 24) < 0.01 // 使用0.01作为误差范围
+}
+
+function cellStyle(data: {
+  row: List
+  column: TableColumnCtx<List>
+  rowIndex: number
+  columnIndex: number
+}) {
+  const { row, column } = data
+
+  if (column.property === 'dailyFuel') {
+    const originalValue = row.dailyFuel ?? 0
+
+    if (originalValue > 9000)
+      return {
+        color: 'red',
+        fontWeight: 'bold'
+      }
+  }
+
+  const timeFields = [
+    'drillingWorkingTime',
+    'otherProductionTime',
+    'accidentTime',
+    'repairTime',
+    'selfStopTime',
+    'complexityTime',
+    'relocationTime',
+    'rectificationTime',
+    'waitingStopTime',
+    'winterBreakTime'
+  ]
+  if (timeFields.includes(column.property)) {
+    if (!checkTimeSumEquals24(row)) {
+      return {
+        color: 'orange',
+        fontWeight: 'bold'
+      }
+    }
+  }
+
+  // 默认返回空对象,不应用特殊样式
+  return {}
+}
+
+function rowClassName(data: { row: List; rowIndex: number }) {
+  const { row } = data
+  if (!row.lastGroupIdFlag) {
+    return 'hide-expand-icon'
+  }
+  return ''
+}
+
+const id = useUserStore().getUser.deptId
+
+const deptId = id
+
+interface Query {
+  pageNo: number
+  pageSize: number
+  deptId: number
+  contractName?: string
+  taskName?: string
+  wellName?: string
+  createTime: string[]
+  projectClassification: number
+}
+
+const query = ref<Query>({
+  pageNo: 1,
+  pageSize: 10,
+  deptId: id,
+  createTime: [
+    ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
+  ],
+  projectClassification: 2
+})
+
+function handleSizeChange(val: number) {
+  query.value.pageSize = val
+  handleQuery()
+}
+
+function handleCurrentChange(val: number) {
+  query.value.pageNo = val
+  loadList()
+}
+
+const loading = ref(false)
+
+const list = ref<List[]>([])
+const total = ref(0)
+
+const loadList = useDebounceFn(async function () {
+  loading.value = true
+  try {
+    if (tab.value === '井') {
+      const { deptId, taskName, wellName, ...other } = query.value
+      const data = await IotRyDailyReportApi.getIotRyDailyReportTeamPage({
+        ...other,
+        taskName: wellName
+      })
+      list.value = data.list
+      total.value = data.total
+    } else {
+      const data = await IotRyDailyReportApi.getIotRyDailyReportWellPage(query.value)
+      list.value = data.list
+      total.value = data.total
+    }
+
+    nextTick(() => {
+      calculateColumnWidths(columns.value)
+    })
+  } finally {
+    loading.value = false
+  }
+}, 500)
+
+function handleQuery(setPage = true) {
+  if (setPage) {
+    query.value.pageNo = 1
+  }
+  loadList()
+}
+
+function resetQuery() {
+  query.value = {
+    pageNo: 1,
+    pageSize: 10,
+    deptId: 157,
+    contractName: '',
+    taskName: '',
+    createTime: [
+      ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
+    ],
+    projectClassification: 2
+  }
+  handleQuery()
+}
+
+watch(
+  [
+    () => query.value.createTime,
+    () => query.value.deptId,
+    () => query.value.taskName,
+    () => query.value.contractName,
+    () => query.value.wellName
+  ],
+  () => {
+    handleQuery()
+  },
+  { immediate: true }
+)
+
+const expandRowKeys = computed(() => {
+  return list.value.filter((item) => item.lastGroupIdFlag).map((item) => item.id.toString())
+})
+
+const exportLoading = ref(false)
+
+const handleExport = () => {
+  exportLoading.value = true
+  if (tab.value === '井') {
+    IotRyDailyReportApi.exportIotRyDailyReportWell(query.value).then((data) => {
+      download.excel(data, '瑞鹰修井井日报统计.xls')
+      exportLoading.value = false
+    })
+  } else {
+    IotRyDailyReportApi.exportIotRyDailyReportTeam(query.value).then((data) => {
+      download.excel(data, '瑞鹰修井队伍日报统计.xls')
+      exportLoading.value = false
+    })
+  }
+}
+</script>
+
+<template>
+  <div
+    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"
+      class="col-span-2 bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center"
+    >
+      <div class="flex items-center gap-8">
+        <el-segmented class="h-12" v-model="tab" :options="tabOptions" @change="handleQuery()" />
+      </div>
+      <div class="flex items-center gap-8">
+        <el-form-item label="项目">
+          <el-input
+            v-model="query.contractName"
+            placeholder="请输入项目"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-240px"
+          />
+        </el-form-item>
+        <el-form-item v-show="tab !== '井'" label="任务">
+          <el-input
+            v-model="query.taskName"
+            placeholder="请输入任务"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-240px"
+          />
+        </el-form-item>
+        <el-form-item label="创建时间">
+          <el-date-picker
+            v-model="query.createTime"
+            value-format="YYYY-MM-DD HH:mm:ss"
+            type="daterange"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            :shortcuts="rangeShortcuts"
+            :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+            class="!w-220px"
+          />
+        </el-form-item>
+      </div>
+      <el-form-item class="ml-auto">
+        <el-button type="primary" @click="handleQuery()">
+          <Icon icon="ep:search" class="mr-5px" /> 搜索
+        </el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
+        <el-button plain type="success" @click="handleExport" :loading="exportLoading">
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 第二行左侧:自动落入第 2 行第 1 列 -->
+    <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg h-full">
+      <DeptTreeSelect
+        v-show="tab === '队伍'"
+        :top-id="158"
+        :deptId="deptId"
+        v-model="query.deptId"
+        title="队伍"
+      />
+      <WellSelect
+        v-show="tab === '井'"
+        :deptId="158"
+        v-model="query.wellName"
+        v-model:contract-name="query.contractName"
+      />
+    </div>
+
+    <!-- 第二行右侧:自动落入第 2 行第 2 列 -->
+    <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col">
+      <div class="flex-1 relative">
+        <el-auto-resizer class="absolute">
+          <template #default="{ width, height }">
+            <el-table
+              :data="list"
+              v-loading="loading"
+              stripe
+              class="absolute"
+              :max-height="height"
+              :height="height"
+              show-overflow-tooltip
+              :width="width"
+              :cell-style="cellStyle"
+              :row-class-name="rowClassName"
+              :tree-props="{ hasChildren: 'lastGroupIdFlag' }"
+              row-key="id"
+              scrollbar-always-on
+              :expand-row-keys="expandRowKeys"
+              border
+            >
+              <el-table-column type="expand" fixed="left">
+                <template #default="{ row }">
+                  <div
+                    class="flex items-center gap-8 h-10 px-14 sticky left-0 w-fit box-border bg-[var(--el-bg-color)]"
+                  >
+                    <el-tag>累计进尺: {{ row.groupIdFootage }} </el-tag>
+                    <el-tag>累计进尺工作时间: {{ row.groupIdFootageTime }} </el-tag>
+                    <el-tag>累计其它生产时间H(钻井) : {{ row.groupIdOtherProductTime }} </el-tag>
+                    <el-tag>累计非生产时间H(钻井) : {{ row.groupIdZjNoProductTime }} </el-tag>
+                    <el-tag>累计生产时间(修井) : {{ row.groupIdProductTime }} </el-tag>
+                    <el-tag>累计非生产时间H(修井) : {{ row.groupIdXjNoProductTime }} </el-tag>
+                    <el-tag>累计用电量(MWh) : {{ row.groupIdPower }} </el-tag>
+                    <el-tag>累计油耗(升) : {{ row.groupIdFuel }} </el-tag>
+                    <el-tag>平均运行时效 : {{ row.groupIdTransitTime }} </el-tag>
+                    <el-tag>累计施工井数 : {{ row.groupConstructionWells }} </el-tag>
+                    <el-tag>累计完工井数 : {{ row.groupCompletedWells }} </el-tag>
+                  </div>
+                </template>
+              </el-table-column>
+              <DailyTableColumn :columns="columns" />
+              <!-- <el-table-column label="操作" width="120px" align="center" fixed="right">
+                <template #default="{ row }">
+                  <el-button link type="success" v-hasPermi="['pms:iot-rh-daily-report:query']">
+                    查看
+                  </el-button>
+                  <el-button
+                    v-show="row.status === 0"
+                    link
+                    type="primary"
+                    v-hasPermi="['pms:iot-rh-daily-report:create']"
+                  >
+                    编辑
+                  </el-button>
+                </template>
+              </el-table-column> -->
+            </el-table>
+          </template>
+        </el-auto-resizer>
+      </div>
+      <div class="h-10 mt-4 flex items-center justify-end">
+        <el-pagination
+          size="default"
+          v-show="total > 0"
+          v-model:current-page="query.pageNo"
+          v-model:page-size="query.pageSize"
+          :background="true"
+          :page-sizes="[10, 20, 30, 50, 100]"
+          :total="total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+:deep(.el-form-item) {
+  margin-bottom: 0;
+}
+
+.el-segmented {
+  --el-border-radius-base: 8px;
+  --el-segmented-padding: 8px;
+}
+
+:deep(.hide-expand-icon) {
+  .el-table__expand-icon {
+    display: none;
+  }
+}
+</style>