yanghao пре 22 часа
родитељ
комит
24d322a302

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

@@ -328,8 +328,7 @@ import dayjs from 'dayjs'
 import { ref, reactive, onMounted, computed, watch } from 'vue'
 
 /** 项目信息 列表 */
-// eslint-disable-next-line vue/component-definition-name-casing
-defineOptions({ name: 'iotProjectInfo' })
+defineOptions({ name: 'IotProjectInfo' })
 
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化

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

@@ -83,6 +83,7 @@ interface ListItem {
   createTime: string
   deptName: string
   taskName: string
+  techniqueNames: string
   rdStatus: string
   productionStatus: string
   nextPlan: string
@@ -397,6 +398,7 @@ onMounted(() => {
                 :real-value="formCreateTime" />
               <zm-table-column prop="deptName" label="施工队伍" />
               <zm-table-column prop="taskName" label="任务" />
+              <zm-table-column prop="techniqueNames" label="施工工艺" />
               <zm-table-column
                 prop="rdStatus"
                 :label="t('project.status')"

+ 1 - 1
src/views/pms/iotrddailyreport/statistics.vue

@@ -9,7 +9,7 @@ import { useDebounceFn } from '@vueuse/core'
 import IotRdDailyReportForm from './IotRdDailyReportForm.vue'
 import download from '@/utils/download'
 
-defineOptions({ name: 'IotRdDailyReport' })
+defineOptions({ name: 'IotRdDailyReportStatistics' })
 
 const { t } = useI18n()
 const router = useRouter()

+ 14 - 2
src/views/pms/iotrhdailyreport/rh-form.vue

@@ -1,4 +1,4 @@
-<script lang="ts" setup generic="T">
+<script lang="ts" setup>
 import { IotRhDailyReportApi } from '@/api/pms/iotrhdailyreport'
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
 import { FormInstance, FormRules } from 'element-plus'
@@ -47,6 +47,7 @@ interface FormOriginal {
   relatedTasks: Record<string, string> | null
   dailyGasInjection: number
   dailyWaterInjection: number
+  dailyPowerUsage: number
   dailyInjectGasTime: number
   dailyInjectWaterTime: number
   constructionStatus: string
@@ -92,6 +93,7 @@ const FORM_KEYS: (keyof FormOriginal)[] = [
   'relatedTasks',
   'dailyGasInjection',
   'dailyWaterInjection',
+  'dailyPowerUsage',
   'dailyInjectGasTime',
   'dailyInjectWaterTime',
   'constructionStatus',
@@ -497,7 +499,17 @@ const handleAudit = async (auditStatus: 20 | 30) => {
             align="left"
             :disabled="isMainFieldDisabled" />
         </el-form-item>
-        <el-form-item class="col-span-2" label="施工区域" prop="location">
+        <el-form-item label="用电量(kWh)" prop="dailyPowerUsage">
+          <el-input-number
+            v-model="form.dailyPowerUsage"
+            class="!w-full"
+            :min="0"
+            :precision="2"
+            :controls="false"
+            align="left"
+            :disabled="isMainFieldDisabled" />
+        </el-form-item>
+        <el-form-item label="施工区域" prop="location">
           <el-input v-model="form.location" disabled />
         </el-form-item>
         <el-form-item class="col-span-2" label="生产动态" prop="productionStatus">

+ 217 - 0
src/views/pms/iotrhdailyreport/rh-summary.vue

@@ -0,0 +1,217 @@
+<script setup lang="ts">
+import dayjs from 'dayjs'
+import { rangeShortcuts } from '@/utils/formatTime'
+import { resolveDailyReportDeptId } from '@/utils/dailyReportDept'
+import { useUserStore } from '@/store/modules/user'
+import DailyStatistics from './components/DailyStatistics.vue'
+import NonProductionEfficiency from './components/NonProductionEfficiency.vue'
+
+defineOptions({
+  name: 'RhSummary'
+})
+
+const route = useRoute()
+const pageRouteName = route.name
+const TOP_DEPT_ID = 157
+const deptId = resolveDailyReportDeptId(useUserStore().getUser.deptId, TOP_DEPT_ID)
+
+interface Query {
+  pageNo: number
+  pageSize: number
+  deptId: number
+  contractName?: string
+  taskName?: string
+  createTime: string[]
+}
+
+const id = deptId
+
+const createDefaultQuery = (): Query => ({
+  pageNo: 1,
+  pageSize: 10,
+  deptId: deptId,
+  contractName: '',
+  taskName: '',
+  createTime: [
+    ...rangeShortcuts[1].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
+  ]
+})
+
+const query = ref<Query>(createDefaultQuery())
+const activeTab = ref<'日报统计' | '非生产时效'>('日报统计')
+const defaultView = ref<'表格' | '看板'>('表格')
+const deptName = ref('瑞恒兴域')
+const refreshKey = ref(0)
+
+const getRouteCreateTime = () => {
+  const createTime = route.query.createTime
+
+  if (Array.isArray(createTime)) {
+    const values = createTime.filter((item): item is string => typeof item === 'string')
+    return values.length === 2 ? values : undefined
+  }
+
+  if (typeof createTime === 'string') {
+    const values = createTime.split(',').filter(Boolean)
+    return values.length === 2 ? values : undefined
+  }
+
+  return undefined
+}
+
+const getRouteActiveTab = () => {
+  return route.query.activeTab === '非生产时效' ? '非生产时效' : '日报统计'
+}
+
+const getRouteDefaultView = () => {
+  return route.query.view === 'kanban' || route.query.defaultView === '看板' ? '看板' : '表格'
+}
+
+const syncQueryFromRoute = () => {
+  if (route.name !== pageRouteName) return
+
+  const createTime = getRouteCreateTime()
+
+  if (createTime) {
+    query.value.createTime = createTime
+  }
+
+  activeTab.value = getRouteActiveTab()
+  defaultView.value = getRouteDefaultView()
+  handleQuery()
+}
+
+const handleDeptNodeClick = (node: any) => {
+  deptName.value = node.name
+  handleQuery()
+}
+
+const handleQuery = () => {
+  query.value.pageNo = 1
+  refreshKey.value += 1
+}
+
+const resetQuery = () => {
+  query.value = createDefaultQuery()
+  deptName.value = '瑞恒兴域'
+  handleQuery()
+}
+
+onMounted(() => {
+  syncQueryFromRoute()
+})
+
+watch(
+  () => [route.query.createTime, route.query.activeTab],
+  () => {
+    syncQueryFromRoute()
+  }
+)
+</script>
+
+<template>
+  <div
+    class="grid grid-cols-[auto_1fr] grid-rows-[48px_44px_1fr] gap-3 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
+    <DeptTreeSelect
+      :dept-id="id"
+      :top-id="TOP_DEPT_ID"
+      v-model="query.deptId"
+      :init-select="false"
+      @node-click="handleDeptNodeClick"
+      class="row-span-3" />
+    <el-form
+      size="small"
+      class="summary-query-form bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-5 flex items-center justify-between">
+      <div class="flex items-center gap-5 min-w-0">
+        <el-form-item label="项目">
+          <el-input
+            v-model="query.contractName"
+            placeholder="请输入项目"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-220px" />
+        </el-form-item>
+        <el-form-item label="任务">
+          <el-input
+            v-model="query.taskName"
+            placeholder="请输入任务"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-220px" />
+        </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-260px" />
+        </el-form-item>
+      </div>
+      <el-form-item class="summary-query-actions">
+        <el-button size="small" type="primary" @click="handleQuery()">
+          <Icon icon="ep:search" class="mr-5px" /> 搜索
+        </el-button>
+        <el-button size="small" @click="resetQuery">
+          <Icon icon="ep:refresh" class="mr-5px" /> 重置
+        </el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-button-group class="justify-self-start self-center">
+      <el-button
+        size="default"
+        :type="activeTab === '日报统计' ? 'primary' : 'default'"
+        @click="activeTab = '日报统计'">
+        日报统计
+      </el-button>
+      <el-button
+        size="default"
+        :type="activeTab === '非生产时效' ? 'primary' : 'default'"
+        @click="activeTab = '非生产时效'">
+        非生产时效
+      </el-button>
+    </el-button-group>
+
+    <DailyStatistics
+      v-if="activeTab === '日报统计'"
+      :query="query"
+      :dept-name="deptName"
+      :default-view="defaultView"
+      :refresh-key="refreshKey" />
+    <NonProductionEfficiency
+      v-else
+      :query="query"
+      :dept-name="deptName"
+      :refresh-key="refreshKey" />
+  </div>
+</template>
+
+<style scoped>
+:deep(.el-form-item) {
+  margin-bottom: 0;
+}
+
+.summary-query-form {
+  min-height: 48px;
+
+  :deep(.el-form-item__label) {
+    height: 28px;
+    line-height: 28px;
+  }
+}
+
+.summary-query-actions {
+  :deep(.el-form-item__content) {
+    flex-wrap: nowrap;
+    gap: 8px;
+  }
+
+  :deep(.el-button + .el-button) {
+    margin-left: 0;
+  }
+}
+</style>

+ 1 - 1
src/views/pms/iotrydailyreport/equipment.vue

@@ -6,7 +6,7 @@ import dayjs from 'dayjs'
 import EquipmentForm from './components/equipment-form.vue'
 import { useUserStore } from '../../../store/modules/user.js'
 
-defineOptions({ name: 'IotRyEquipmentDailyReport' })
+defineOptions({ name: 'RyEquipment' })
 
 interface ReportRow {
   id: number

+ 166 - 0
src/views/pms/iotrydailyreport/ry-summary.vue

@@ -0,0 +1,166 @@
+<script setup lang="ts">
+import dayjs from 'dayjs'
+import { rangeShortcuts } from '@/utils/formatTime'
+import { resolveDailyReportDeptId } from '@/utils/dailyReportDept'
+import { useUserStore } from '@/store/modules/user'
+import DailyStatistics from './components/DailyStatistics.vue'
+import NonProductionEfficiency from './components/NonProductionEfficiency.vue'
+
+defineOptions({
+  name: 'RySummary'
+})
+
+const TOP_DEPT_ID = 158
+const deptId = resolveDailyReportDeptId(useUserStore().getUser.deptId, TOP_DEPT_ID)
+
+interface Query {
+  pageNo: number
+  pageSize: number
+  deptId: number
+  contractName?: string
+  taskName?: string
+  createTime: string[]
+  projectClassification: 1
+}
+
+const id = deptId
+
+const createDefaultQuery = (): Query => ({
+  pageNo: 1,
+  pageSize: 10,
+  deptId,
+  contractName: '',
+  taskName: '',
+  createTime: [
+    ...rangeShortcuts[1].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
+  ],
+  projectClassification: 1
+})
+
+const query = ref<Query>(createDefaultQuery())
+const activeTab = ref<'日报统计' | '非生产时效'>('日报统计')
+const deptName = ref('瑞鹰国际钻井')
+const refreshKey = ref(0)
+
+const handleDeptNodeClick = (node: any) => {
+  deptName.value = node.name
+  handleQuery()
+}
+
+const handleQuery = () => {
+  query.value.pageNo = 1
+  refreshKey.value += 1
+}
+
+const resetQuery = () => {
+  query.value = createDefaultQuery()
+  deptName.value = '瑞鹰国际钻井'
+  handleQuery()
+}
+</script>
+
+<template>
+  <div
+    class="grid grid-cols-[auto_1fr] grid-rows-[48px_44px_1fr] gap-3 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
+    <DeptTreeSelect
+      :dept-id="id"
+      :top-id="TOP_DEPT_ID"
+      v-model="query.deptId"
+      :init-select="false"
+      @node-click="handleDeptNodeClick"
+      class="row-span-3" />
+    <el-form
+      size="small"
+      class="summary-query-form bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-5 flex items-center justify-between">
+      <div class="flex items-center gap-5 min-w-0">
+        <el-form-item label="项目">
+          <el-input
+            v-model="query.contractName"
+            placeholder="请输入项目"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-220px" />
+        </el-form-item>
+        <el-form-item label="任务">
+          <el-input
+            v-model="query.taskName"
+            placeholder="请输入任务"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-220px" />
+        </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-260px" />
+        </el-form-item>
+      </div>
+      <el-form-item class="summary-query-actions">
+        <el-button size="small" type="primary" @click="handleQuery()">
+          <Icon icon="ep:search" class="mr-5px" /> 搜索
+        </el-button>
+        <el-button size="small" @click="resetQuery">
+          <Icon icon="ep:refresh" class="mr-5px" /> 重置
+        </el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-button-group class="justify-self-start self-center">
+      <el-button
+        size="default"
+        :type="activeTab === '日报统计' ? 'primary' : 'default'"
+        @click="activeTab = '日报统计'">
+        日报统计
+      </el-button>
+      <el-button
+        size="default"
+        :type="activeTab === '非生产时效' ? 'primary' : 'default'"
+        @click="activeTab = '非生产时效'">
+        非生产时效
+      </el-button>
+    </el-button-group>
+
+    <DailyStatistics
+      v-if="activeTab === '日报统计'"
+      :query="query"
+      :dept-name="deptName"
+      :refresh-key="refreshKey" />
+    <NonProductionEfficiency
+      v-else
+      :query="query"
+      :dept-name="deptName"
+      :refresh-key="refreshKey" />
+  </div>
+</template>
+
+<style scoped>
+:deep(.el-form-item) {
+  margin-bottom: 0;
+}
+
+.summary-query-form {
+  min-height: 48px;
+
+  :deep(.el-form-item__label) {
+    height: 28px;
+    line-height: 28px;
+  }
+}
+
+.summary-query-actions {
+  :deep(.el-form-item__content) {
+    flex-wrap: nowrap;
+    gap: 8px;
+  }
+
+  :deep(.el-button + .el-button) {
+    margin-left: 0;
+  }
+}
+</style>

+ 166 - 0
src/views/pms/iotrydailyreport/ry-xj-summary.vue

@@ -0,0 +1,166 @@
+<script setup lang="ts">
+import dayjs from 'dayjs'
+import { rangeShortcuts } from '@/utils/formatTime'
+import { resolveDailyReportDeptId } from '@/utils/dailyReportDept'
+import { useUserStore } from '@/store/modules/user'
+import XjDailyStatistics from './components/XjDailyStatistics.vue'
+import XjNonProductionEfficiency from './components/XjNonProductionEfficiency.vue'
+
+defineOptions({
+  name: 'RyXjSummary'
+})
+
+const TOP_DEPT_ID = 158
+const deptId = resolveDailyReportDeptId(useUserStore().getUser.deptId, TOP_DEPT_ID)
+
+interface Query {
+  pageNo: number
+  pageSize: number
+  deptId: number
+  contractName?: string
+  taskName?: string
+  createTime: string[]
+  projectClassification: 2
+}
+
+const id = deptId
+
+const createDefaultQuery = (): Query => ({
+  pageNo: 1,
+  pageSize: 10,
+  deptId,
+  contractName: '',
+  taskName: '',
+  createTime: [
+    ...rangeShortcuts[1].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
+  ],
+  projectClassification: 2
+})
+
+const query = ref<Query>(createDefaultQuery())
+const activeTab = ref<'日报统计' | '非生产时效'>('日报统计')
+const deptName = ref('瑞鹰国际修井')
+const refreshKey = ref(0)
+
+const handleDeptNodeClick = (node: any) => {
+  deptName.value = node.name
+  handleQuery()
+}
+
+const handleQuery = () => {
+  query.value.pageNo = 1
+  refreshKey.value += 1
+}
+
+const resetQuery = () => {
+  query.value = createDefaultQuery()
+  deptName.value = '瑞鹰国际修井'
+  handleQuery()
+}
+</script>
+
+<template>
+  <div
+    class="grid grid-cols-[auto_1fr] grid-rows-[48px_44px_1fr] gap-3 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
+    <DeptTreeSelect
+      :dept-id="id"
+      :top-id="TOP_DEPT_ID"
+      v-model="query.deptId"
+      :init-select="false"
+      @node-click="handleDeptNodeClick"
+      class="row-span-3" />
+    <el-form
+      size="small"
+      class="summary-query-form bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-5 flex items-center justify-between">
+      <div class="flex items-center gap-5 min-w-0">
+        <el-form-item label="项目">
+          <el-input
+            v-model="query.contractName"
+            placeholder="请输入项目"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-220px" />
+        </el-form-item>
+        <el-form-item label="任务">
+          <el-input
+            v-model="query.taskName"
+            placeholder="请输入任务"
+            clearable
+            @keyup.enter="handleQuery()"
+            class="!w-220px" />
+        </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-260px" />
+        </el-form-item>
+      </div>
+      <el-form-item class="summary-query-actions">
+        <el-button size="small" type="primary" @click="handleQuery()">
+          <Icon icon="ep:search" class="mr-5px" /> 搜索
+        </el-button>
+        <el-button size="small" @click="resetQuery">
+          <Icon icon="ep:refresh" class="mr-5px" /> 重置
+        </el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-button-group class="justify-self-start self-center">
+      <el-button
+        size="default"
+        :type="activeTab === '日报统计' ? 'primary' : 'default'"
+        @click="activeTab = '日报统计'">
+        日报统计
+      </el-button>
+      <el-button
+        size="default"
+        :type="activeTab === '非生产时效' ? 'primary' : 'default'"
+        @click="activeTab = '非生产时效'">
+        非生产时效
+      </el-button>
+    </el-button-group>
+
+    <XjDailyStatistics
+      v-if="activeTab === '日报统计'"
+      :query="query"
+      :dept-name="deptName"
+      :refresh-key="refreshKey" />
+    <XjNonProductionEfficiency
+      v-else
+      :query="query"
+      :dept-name="deptName"
+      :refresh-key="refreshKey" />
+  </div>
+</template>
+
+<style scoped>
+:deep(.el-form-item) {
+  margin-bottom: 0;
+}
+
+.summary-query-form {
+  min-height: 48px;
+
+  :deep(.el-form-item__label) {
+    height: 28px;
+    line-height: 28px;
+  }
+}
+
+.summary-query-actions {
+  :deep(.el-form-item__content) {
+    flex-wrap: nowrap;
+    gap: 8px;
+  }
+
+  :deep(.el-button + .el-button) {
+    margin-left: 0;
+  }
+}
+</style>

+ 10 - 19
src/views/pms/iotrydailyreport/xapproval.vue

@@ -8,7 +8,7 @@ import dayjs from 'dayjs'
 import ryXjForm from './ry-xj-form.vue'
 import RyXjTable from './ry-xj-table.vue'
 
-defineOptions({ name: 'IotRyDailyReportApproval' })
+defineOptions({ name: 'IotRyXjDailyReportApproval' })
 
 const TOP_DEPT_ID = 158
 const id = resolveDailyReportDeptId(useUserStore().getUser.deptId, TOP_DEPT_ID)
@@ -110,21 +110,18 @@ onMounted(() => {
 
 <template>
   <div
-    class="grid grid-cols-[auto_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
-  >
+    class="grid grid-cols-[auto_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
     <DeptTreeSelect
       :top-id="TOP_DEPT_ID"
       :dept-id="deptId"
       v-model="query.deptId"
       :init-select="false"
       :show-title="false"
-      class="row-span-2"
-    />
+      class="row-span-2" />
     <!-- <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg row-span-2"> </div> -->
     <el-form
       size="default"
-      class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center justify-between"
-    >
+      class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center justify-between">
       <div class="flex items-center gap-8">
         <el-form-item label="项目">
           <el-input
@@ -132,8 +129,7 @@ onMounted(() => {
             placeholder="请输入项目"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="任务">
           <el-input
@@ -141,8 +137,7 @@ onMounted(() => {
             placeholder="请输入任务"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="创建时间">
           <el-date-picker
@@ -153,8 +148,7 @@ onMounted(() => {
             end-placeholder="结束日期"
             :shortcuts="rangeShortcuts"
             :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-            class="!w-220px"
-          />
+            class="!w-220px" />
         </el-form-item>
       </div>
       <el-form-item>
@@ -171,15 +165,13 @@ onMounted(() => {
       :page-no="query.pageNo"
       :page-size="query.pageSize"
       @current-change="handleCurrentChange"
-      @size-change="handleSizeChange"
-    >
+      @size-change="handleSizeChange">
       <template #action="{ row }">
         <el-button
           link
           type="success"
           @click="handleOpenForm(row.id, 'readonly')"
-          v-hasPermi="['pms:iot-ry-daily-report:query']"
-        >
+          v-hasPermi="['pms:iot-ry-daily-report:query']">
           查看
         </el-button>
         <el-button
@@ -187,8 +179,7 @@ onMounted(() => {
           link
           type="primary"
           @click="handleOpenForm(row.id, 'edit')"
-          v-hasPermi="['pms:iot-ry-daily-report:update']"
-        >
+          v-hasPermi="['pms:iot-ry-daily-report:update']">
           审批
         </el-button>
       </template>

+ 10 - 19
src/views/pms/iotrydailyreport/xfill.vue

@@ -8,7 +8,7 @@ import dayjs from 'dayjs'
 import ryXjForm from './ry-xj-form.vue'
 import RyXjTable from './ry-xj-table.vue'
 
-defineOptions({ name: 'IotRyDailyReportFill' })
+defineOptions({ name: 'IotRyXjDailyReportFill' })
 
 const TOP_DEPT_ID = 158
 const id = resolveDailyReportDeptId(useUserStore().getUser.deptId, TOP_DEPT_ID)
@@ -110,21 +110,18 @@ onMounted(() => {
 
 <template>
   <div
-    class="grid grid-cols-[auto_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
-  >
+    class="grid grid-cols-[auto_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
     <DeptTreeSelect
       :top-id="TOP_DEPT_ID"
       :dept-id="deptId"
       v-model="query.deptId"
       :init-select="false"
       :show-title="false"
-      class="row-span-2"
-    />
+      class="row-span-2" />
     <!-- <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg row-span-2"> </div> -->
     <el-form
       size="default"
-      class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center justify-between"
-    >
+      class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center justify-between">
       <div class="flex items-center gap-8">
         <el-form-item label="项目">
           <el-input
@@ -132,8 +129,7 @@ onMounted(() => {
             placeholder="请输入项目"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="任务">
           <el-input
@@ -141,8 +137,7 @@ onMounted(() => {
             placeholder="请输入任务"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="创建时间">
           <el-date-picker
@@ -153,8 +148,7 @@ onMounted(() => {
             end-placeholder="结束日期"
             :shortcuts="rangeShortcuts"
             :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-            class="!w-220px"
-          />
+            class="!w-220px" />
         </el-form-item>
       </div>
       <el-form-item>
@@ -171,15 +165,13 @@ onMounted(() => {
       :page-no="query.pageNo"
       :page-size="query.pageSize"
       @current-change="handleCurrentChange"
-      @size-change="handleSizeChange"
-    >
+      @size-change="handleSizeChange">
       <template #action="{ row }">
         <el-button
           link
           type="success"
           @click="handleOpenForm(row.id, 'readonly')"
-          v-hasPermi="['pms:iot-ry-daily-report:query']"
-        >
+          v-hasPermi="['pms:iot-ry-daily-report:query']">
           查看
         </el-button>
         <el-button
@@ -187,8 +179,7 @@ onMounted(() => {
           link
           type="primary"
           @click="handleOpenForm(row.id, 'edit')"
-          v-hasPermi="['pms:iot-ry-daily-report:create']"
-        >
+          v-hasPermi="['pms:iot-ry-daily-report:create']">
           编辑
         </el-button>
       </template>

+ 2 - 0
src/views/report-statistics/costs.vue

@@ -8,6 +8,8 @@ import download from '@/utils/download'
 import { rangeShortcuts } from '@/utils/formatTime'
 import { useTableComponents } from '@/components/ZmTable/useTableComponents'
 
+defineOptions({ name: 'Costs' })
+
 // 定义时间类型
 type TimeType = 'year' | 'month' | 'day'
 

+ 46 - 54
src/views/report-statistics/device_book/index2.vue

@@ -21,8 +21,7 @@
                   <Echart
                     v-if="statusChartOption.series && statusChartOption.series[0].data.length > 0"
                     :options="statusChartOption"
-                    :height="160"
-                  />
+                    :height="160" />
                   <div v-else class="flex items-center justify-center h-full text-gray-500">
                     暂无数据
                   </div>
@@ -46,8 +45,7 @@
                   style="height: 30px"
                   @keyup.enter="handleQuery"
                   v-model="queryParams.deviceCode"
-                  placeholder="请输入设备编码"
-                />
+                  placeholder="请输入设备编码" />
               </el-form-item>
 
               <el-form-item label="设备名称" prop="deviceName">
@@ -55,8 +53,7 @@
                   style="height: 30px"
                   @keyup.enter="handleQuery"
                   v-model="queryParams.deviceName"
-                  placeholder="请输入设备名称"
-                />
+                  placeholder="请输入设备名称" />
               </el-form-item>
 
               <el-form-item>
@@ -94,7 +91,7 @@
       </el-row>
 
       <!-- 列表 -->
-      <ContentWrap style="border: 0; margin-top: 10px">
+      <ContentWrap style="margin-top: 10px; border: 0">
         <zm-table
           :loading="loading"
           :data="list"
@@ -102,8 +99,7 @@
           :show-overflow-tooltip="true"
           @sort-change="handleSortChange"
           ref="tableRef"
-          :height="tableHeight"
-        >
+          :height="tableHeight">
           <zm-table-column :label="t('iotDevice.serial')" width="70" align="center" fixed="left">
             <template #default="scope">
               {{ scope.$index + 1 }}
@@ -115,8 +111,7 @@
             sortable
             align="center"
             prop="deviceCode"
-            fixed="left"
-          />
+            fixed="left" />
           <zm-table-column :label="t('iotDevice.name')" sortable align="center" prop="deviceName">
             <template #default="scope">
               <el-link :underline="false" type="primary" @click="handleDetail(scope.row.id)">
@@ -130,8 +125,7 @@
             :label="t('iotDevice.status')"
             align="center"
             prop="deviceStatus"
-            min-width="90"
-          >
+            min-width="90">
             <template #default="scope">
               <dict-tag :type="DICT_TYPE.PMS_DEVICE_STATUS" :value="scope.row.deviceStatus" />
             </template>
@@ -140,8 +134,7 @@
             :label="t('iotDevice.assets')"
             align="center"
             prop="assetProperty"
-            min-width="110"
-          >
+            min-width="110">
             <template #default="scope">
               <dict-tag :type="DICT_TYPE.PMS_ASSET_PROPERTY" :value="scope.row.assetProperty" />
             </template>
@@ -150,8 +143,7 @@
             :label="t('iotDevice.assetClass')"
             align="center"
             prop="assetClassName"
-            min-width="170"
-          />
+            min-width="170" />
           <zm-table-column label="生产厂家" align="center" prop="manufacturer" />
           <zm-table-column label="生产日期" align="center" min-width="120">
             <template #default="scope">
@@ -172,8 +164,7 @@
           :total="total"
           v-model:page="queryParams.pageNo"
           v-model:limit="queryParams.pageSize"
-          @pagination="getList"
-        />
+          @pagination="getList" />
       </ContentWrap>
 
       <!-- <el-dialog
@@ -237,7 +228,7 @@ import download from '@/utils/download'
 const message = useMessage() // 消息弹窗
 let isLeftContentCollapsed = ref(false)
 /** 设备台账 列表 */
-defineOptions({ name: 'IotDevicePms' })
+defineOptions({ name: 'DeviceBook' })
 
 const { t } = useI18n() // 国际化
 const { push } = useRouter() // 路由跳转
@@ -640,28 +631,40 @@ onMounted(async () => {
 </script>
 
 <style scoped>
+/* 响应式调整 */
+@media (width <= 768px) {
+  .export-checkbox-group {
+    grid-template-columns: 1fr;
+  }
+
+  .export-dialog {
+    width: 90% !important;
+  }
+}
+
 .stat-card {
+  height: 230px;
   padding: 20px;
-  border-radius: 10px;
+  font-size: 14px;
   color: white;
   text-align: center;
-  font-size: 14px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  border-radius: 10px;
+  box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
   transition:
     transform 0.3s ease,
     box-shadow 0.3s ease;
   backdrop-filter: blur(12px);
-  height: 230px;
 }
+
 .stat-card::before {
   position: absolute;
-  filter: blur(20px);
   z-index: -1;
+  filter: blur(20px);
 }
 
 .stat-card:hover {
   transform: translateY(-4px);
-  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
+  box-shadow: 0 8px 20px rgb(0 0 0 / 20%);
 }
 
 .card-title {
@@ -670,9 +673,9 @@ onMounted(async () => {
 }
 
 .card-value {
+  margin: 8px 0;
   font-size: 28px;
   font-weight: bold;
-  margin: 8px 0;
 }
 
 .card-trend {
@@ -682,17 +685,17 @@ onMounted(async () => {
 
 /* 毛玻璃渐变背景 —— 不再使用 background-image */
 .bg-blue-gradient {
-  background: linear-gradient(135deg, rgba(77, 147, 255, 0.5), rgba(75, 132, 254));
+  background: linear-gradient(135deg, rgb(77 147 255 / 50%), rgb(75 132 254));
 }
 
 .bg-green-gradient {
-  background: linear-gradient(135deg, rgba(101, 226, 136, 0.1), #52d7a2);
-  background-color: rgba(76, 175, 80, 0.1);
+  background: linear-gradient(135deg, rgb(101 226 136 / 10%), #52d7a2);
+  background-color: rgb(76 175 80 / 10%);
 }
 
 .bg-orange-gradient {
   background: linear-gradient(135deg, #ff9800, #f57c00);
-  background-color: rgba(255, 152, 0, 0.5);
+  background-color: rgb(255 152 0 / 50%);
 }
 
 /* 确保内容不溢出 */
@@ -708,14 +711,14 @@ onMounted(async () => {
 
 ::v-deep .el-table__header-wrapper {
   position: sticky !important;
-  width: 100%;
-  top: 0px;
+  top: 0;
   z-index: 2000;
+  width: 100%;
 }
 
 .export-dialog :deep(.el-dialog) {
   border-radius: 12px;
-  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
+  box-shadow: 0 10px 30px rgb(0 0 0 / 15%);
 }
 
 .export-dialog-content {
@@ -727,25 +730,25 @@ onMounted(async () => {
 }
 
 .export-title {
+  margin: 0 0 4px;
   font-size: 16px;
   font-weight: 600;
   color: #303133;
-  margin: 0 0 4px 0;
 }
 
 .export-subtitle {
+  margin: 0;
   font-size: 14px;
   color: #909399;
-  margin: 0;
 }
 
 .export-options-container {
   max-height: 300px;
-  overflow-y: auto;
   padding: 8px;
+  overflow-y: auto;
+  background-color: #fafafa;
   border: 1px solid #e4e7ed;
   border-radius: 6px;
-  background-color: #fafafa;
 }
 
 .export-checkbox-group {
@@ -756,24 +759,24 @@ onMounted(async () => {
 }
 
 .export-checkbox-item {
-  margin-bottom: 8px;
   padding: 8px 12px;
-  border-radius: 6px;
+  margin-bottom: 8px;
+  background-color: #fff;
   border: 1px solid #ebeef5;
+  border-radius: 6px;
   transition: all 0.3s ease;
-  background-color: #fff;
 }
 
 .export-checkbox-item:hover {
   background-color: #f5f7fa;
   border-color: #dcdfe6;
   transform: translateY(-1px);
-  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
+  box-shadow: 0 2px 6px rgb(0 0 0 / 8%);
 }
 
 .export-checkbox-item:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
-  color: #409eff;
   font-weight: 500;
+  color: #409eff;
 }
 
 .checkbox-text {
@@ -810,15 +813,4 @@ onMounted(async () => {
 .export-options-container::-webkit-scrollbar-thumb:hover {
   background: #a8a8a8;
 }
-
-/* 响应式调整 */
-@media (max-width: 768px) {
-  .export-checkbox-group {
-    grid-template-columns: 1fr;
-  }
-
-  .export-dialog {
-    width: 90% !important;
-  }
-}
 </style>

+ 19 - 19
src/views/report-statistics/fault_report/index.vue

@@ -5,7 +5,7 @@
       <!-- 统计卡片 -->
       <el-row :gutter="18" class="mb-4">
         <el-col :span="4">
-          <div style="background-color: transparent; border-radius: 10px; cursor: pointer">
+          <div style="cursor: pointer; background-color: transparent; border-radius: 10px">
             <div
               class="stat-card bg-blue-gradient"
               :class="{ 'stat-card-selected': statusList.all }"
@@ -175,7 +175,7 @@
       </el-row>
 
       <!-- 列表 -->
-      <ContentWrap style="border: 0; margin-top: 10px">
+      <ContentWrap style="margin-top: 10px; border: 0">
         <zm-table
           :loading="loading"
           :data="list"
@@ -267,7 +267,7 @@ import download from '@/utils/download'
 
 const { params } = useRoute()
 /** 巡检工单 列表 */
-defineOptions({ name: 'IotInspectOrder' })
+defineOptions({ name: 'FaultReport' })
 
 const { t } = useI18n() // 国际化
 const loading = ref(true) // 列表的加载中
@@ -484,29 +484,28 @@ watch(
 }
 
 .stat-card {
+  height: 170px;
   padding: 14px 16px;
-  border-radius: 10px;
-  text-align: center;
+  overflow: hidden; /* 防止闪光效果溢出 */
   font-size: 14px;
+  color: #6b7280;
+  text-align: center;
+  cursor: pointer;
+  background: linear-gradient(180deg, #fff 0%, #f7faff 100%);
+  border-radius: 10px;
+  box-shadow: 0 4px 12px rgb(31 91 184 / 8%);
   transition:
     transform 0.3s ease,
     box-shadow 0.3s ease,
     border-color 0.3s ease;
-  height: 170px;
-  cursor: pointer;
-  overflow: hidden; /* 防止闪光效果溢出 */
-  background: linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
-
-  box-shadow: 0 4px 12px rgb(31 91 184 / 8%);
-  color: #6b7280;
 }
 
 .card-title {
   margin: 8px 0;
   font-size: 14px;
   font-weight: 600;
-  color: #6b7280;
   line-height: 1.4;
+  color: #6b7280;
 }
 
 .card-value {
@@ -524,11 +523,12 @@ watch(
 
 /* 毛玻璃渐变背景 —— 不再使用 background-image */
 .bg-blue-gradient {
-  background: linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
+  background: linear-gradient(180deg, #fff 0%, #f7faff 100%);
   border-color: #e4ecf7;
 }
+
 .bg-blue-gradient2 {
-  background: linear-gradient(180deg, #ffffff 0%, #a5d1ff 100%);
+  background: linear-gradient(180deg, #fff 0%, #a5d1ff 100%);
   border-color: #e4ecf7;
 }
 
@@ -576,16 +576,16 @@ watch(
 
 ::v-deep .el-table__header-wrapper {
   position: sticky !important;
-  width: 100%;
-  top: 0px;
+  top: 0;
   z-index: 2000;
+  width: 100%;
 }
 
 .stat-card-selected {
   position: relative;
+  border-color: #bfd5ee;
   transform: translateY(-2px);
-  transition: all 0.2s;
   box-shadow: 0 10px 20px rgb(31 91 184 / 12%);
-  border-color: #bfd5ee;
+  transition: all 0.2s;
 }
 </style>

+ 17 - 16
src/views/report-statistics/inspection_order/index.vue

@@ -162,7 +162,7 @@
       </el-row>
 
       <!-- 列表 -->
-      <ContentWrap style="border: 0; margin-top: 10px">
+      <ContentWrap style="margin-top: 10px; border: 0">
         <!-- 异常设备 -->
         <zm-table
           v-if="isException"
@@ -330,7 +330,7 @@ let isLeftContentCollapsed = ref(false)
 const { push } = useRouter()
 const { params } = useRoute()
 /** 巡检工单 列表 */
-defineOptions({ name: 'IotInspectOrder' })
+defineOptions({ name: 'InspectionOrder' })
 
 const { t } = useI18n() // 国际化
 const loading = ref(true) // 列表的加载中
@@ -689,29 +689,30 @@ onMounted(() => {
 }
 
 .stat-card {
+  height: 170px;
   padding: 14px 16px;
-  background: linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
+  overflow: hidden;
+  font-size: 14px;
+  color: #6b7280;
+  text-align: center;
+  cursor: pointer;
+  background: linear-gradient(180deg, #fff 0%, #f7faff 100%);
+
   /* border: 1px solid #e4ecf7; */
   border-radius: 10px;
   box-shadow: 0 4px 12px rgb(31 91 184 / 8%);
-  text-align: center;
-  font-size: 14px;
   transition:
     transform 0.3s ease,
     box-shadow 0.3s ease,
     border-color 0.3s ease;
-  color: #6b7280;
-  height: 170px;
-  cursor: pointer;
-  overflow: hidden;
 }
 
 .card-title {
   margin: 8px 0;
   font-size: 14px;
   font-weight: 600;
-  color: #6b7280;
   line-height: 1.4;
+  color: #6b7280;
 }
 
 .card-value {
@@ -728,7 +729,7 @@ onMounted(() => {
 }
 
 .bg-blue-gradient {
-  background: linear-gradient(180deg, #ffffff 0%, #f7faff 100%);
+  background: linear-gradient(180deg, #fff 0%, #f7faff 100%);
   border-color: #e4ecf7;
 }
 
@@ -772,7 +773,7 @@ onMounted(() => {
   color: #d97706;
 }
 
-/* ???????????*/
+/* ??????????? */
 :deep(.el-row) {
   flex-wrap: wrap;
 }
@@ -785,16 +786,16 @@ onMounted(() => {
 
 ::v-deep .el-table__header-wrapper {
   position: sticky !important;
-  width: 100%;
-  top: 0px;
+  top: 0;
   z-index: 2000;
+  width: 100%;
 }
 
 .stat-card-selected {
   position: relative;
+  border-color: #bfd5ee;
   transform: translateY(-2px);
-  transition: all 0.2s;
   box-shadow: 0 10px 20px rgb(31 91 184 / 12%);
-  border-color: #bfd5ee;
+  transition: all 0.2s;
 }
 </style>

+ 162 - 31
src/views/report-statistics/rd-daily-report.vue

@@ -5,9 +5,11 @@ import { useDebounceFn } from '@vueuse/core'
 import dayjs from 'dayjs'
 import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 import { useUserStore } from '@/store/modules/user'
+import { resolveDailyReportDeptId } from '@/utils/dailyReportDept'
 import download from '@/utils/download'
+import CountTo from '@/components/count-to1.vue'
 
-defineOptions({ name: 'DailyReport' })
+defineOptions({ name: 'RdDailyReport' })
 
 const tab = ref('井')
 const tabOptions = ['井', '队伍']
@@ -268,7 +270,8 @@ function rowClassName(data: { row: List; rowIndex: number }) {
   return ''
 }
 
-const id = useUserStore().getUser.deptId ?? 157
+const TOP_DEPT_ID = 163
+const id = resolveDailyReportDeptId(useUserStore().getUser.deptId, TOP_DEPT_ID)
 
 const deptId = id
 
@@ -291,6 +294,14 @@ const query = ref<Query>({
   ]
 })
 
+const taskName = computed({
+  get: () => query.value.taskName,
+  set: (value: string | undefined) => {
+    query.value.taskName = value
+    query.value.wellName = value
+  }
+})
+
 function handleSizeChange(val: number) {
   query.value.pageSize = val
   handleQuery()
@@ -306,6 +317,114 @@ const loading = ref(false)
 const list = ref<List[]>([])
 const total = ref(0)
 
+const totalWorkKeys: [string, string | undefined, string, string, number][] = [
+  [
+    'cumulativeBridgePlug',
+    undefined,
+    '桥塞',
+    'i-material-symbols:check-circle-outline-rounded text-emerald',
+    0
+  ],
+  [
+    'cumulativeRunCount',
+    undefined,
+    '趟数',
+    'i-material-symbols:check-circle-outline-rounded text-emerald',
+    0
+  ],
+  [
+    'cumulativeWorkingWell',
+    undefined,
+    '井数',
+    'i-material-symbols:check-circle-outline-rounded text-emerald',
+    0
+  ],
+  [
+    'cumulativeWorkingLayers',
+    undefined,
+    '段数',
+    'i-material-symbols:check-circle-outline-rounded text-emerald',
+    0
+  ],
+  [
+    'cumulativeHourCount',
+    undefined,
+    '小时(H)',
+    'i-material-symbols:nest-clock-farsight-analog-outline-rounded text-emerald',
+    2
+  ],
+  [
+    'cumulativeWaterVolume',
+    '方',
+    '水方量',
+    'i-material-symbols:water-drop-outline-rounded text-sky',
+    2
+  ],
+  ['taici', undefined, '台次', 'i-material-symbols:check-circle-outline-rounded text-emerald', 0],
+  [
+    'utilizationRate',
+    '%',
+    '设备利用率',
+    'i-material-symbols:check-circle-outline-rounded text-emerald',
+    0
+  ],
+  [
+    'cumulativeFuels',
+    '万升',
+    '累计油耗',
+    'i-material-symbols:directions-car-outline-rounded text-sky',
+    2
+  ]
+]
+
+const totalWork = ref<Record<string, number>>({
+  cumulativeFuels: 0,
+  taici: 0,
+  cumulativeBridgePlug: 0,
+  cumulativeRunCount: 0,
+  cumulativeWorkingWell: 0,
+  cumulativeWorkingLayers: 0,
+  cumulativeHourCount: 0,
+  cumulativeWaterVolume: 0,
+  utilizationRate: 0
+})
+
+const totalLoading = ref(false)
+
+const loadTotalWorkload = useDebounceFn(async () => {
+  totalLoading.value = true
+  try {
+    const {
+      pageNo: _pageNo,
+      pageSize: _pageSize,
+      wellName: _wellName,
+      ...totalWorkloadQuery
+    } = query.value
+
+    void _pageNo
+    void _pageSize
+    void _wellName
+
+    const data = await IotRdDailyReportApi.totalWorkload(totalWorkloadQuery)
+
+    totalWork.value = {
+      ...totalWork.value,
+      taici: data.taici || 0,
+      cumulativeBridgePlug: data.cumulativeBridgePlug || 0,
+      cumulativeRunCount: data.cumulativeRunCount || 0,
+      cumulativeWorkingWell: data.cumulativeWorkingWell || 0,
+      cumulativeWorkingLayers: data.cumulativeWorkingLayers || 0,
+      cumulativeHourCount: data.cumulativeHourCount || 0,
+      cumulativeWaterVolume: data.cumulativeWaterVolume || 0,
+      ...data,
+      cumulativeFuels: (data.cumulativeFuels || 0) / 10000,
+      utilizationRate: Number(((data.utilizationRate || 0) * 100).toFixed(2))
+    }
+  } finally {
+    totalLoading.value = false
+  }
+}, 500)
+
 const loadList = useDebounceFn(async function () {
   loading.value = true
   try {
@@ -336,15 +455,17 @@ function handleQuery(setPage = true) {
     query.value.pageNo = 1
   }
   loadList()
+  loadTotalWorkload()
 }
 
 function resetQuery() {
   query.value = {
     pageNo: 1,
     pageSize: 10,
-    deptId: 157,
+    deptId: id,
     contractName: '',
     taskName: '',
+    wellName: '',
     createTime: [
       ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
     ]
@@ -390,12 +511,10 @@ const handleExport = () => {
 
 <template>
   <div
-    class="daily-report-page grid grid-cols-[auto_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
-  >
+    class="daily-report-page grid grid-cols-[auto_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"
-    >
+      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>
@@ -406,17 +525,15 @@ const handleExport = () => {
             placeholder="请输入项目"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item v-show="tab !== '井'" label="任务">
           <el-input
-            v-model="query.taskName"
+            v-model="taskName"
             placeholder="请输入任务"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="创建时间">
           <el-date-picker
@@ -427,8 +544,7 @@ const handleExport = () => {
             end-placeholder="结束日期"
             :shortcuts="rangeShortcuts"
             :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-            class="!w-220px"
-          />
+            class="!w-220px" />
         </el-form-item>
       </div>
       <el-form-item class="ml-auto">
@@ -445,25 +561,43 @@ const handleExport = () => {
     <!-- 第二行左侧:自动落入第 2 行第 1 列 -->
     <DeptTreeSelect
       v-show="tab === '队伍'"
-      :top-id="163"
-      :deptId="deptId"
+      :top-id="TOP_DEPT_ID"
+      :dept-id="deptId"
       v-model="query.deptId"
+      :init-select="false"
       title="队伍"
-      class="daily-report-side"
-    />
+      class="daily-report-side row-span-2" />
     <WellSelect
       v-show="tab === '井'"
-      :deptId="163"
-      v-model="query.wellName"
+      :dept-id="deptId"
+      v-model="taskName"
       v-model:contract-name="query.contractName"
-      class="daily-report-side"
-    />
+      class="daily-report-side row-span-2" />
     <!-- <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg h-full"> </div> -->
 
+    <div class="grid grid-cols-9 gap-4" v-loading="totalLoading">
+      <div
+        v-for="info in totalWorkKeys"
+        :key="info[0]"
+        class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-1 py-2 flex flex-col items-center justify-center gap-0.5 min-w-0">
+        <div class="size-6.5" :class="info[3]"></div>
+        <count-to
+          class="text-xl font-medium leading-6"
+          :start-val="0"
+          :end-val="totalWork[info[0]]"
+          :decimals="info[4]">
+          <span class="text-xs leading-8 text-[var(--el-text-color-regular)]">暂无数据</span>
+        </count-to>
+        <div
+          class="text-xs font-medium leading-5 text-[var(--el-text-color-regular)] whitespace-nowrap">
+          {{ info[1] ? info[2] + '(' + info[1] + ')' : info[2] }}
+        </div>
+      </div>
+    </div>
+
     <!-- 第二行右侧:自动落入第 2 行第 2 列 -->
     <div
-      class="daily-report-table-card bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col min-h-0"
-    >
+      class="daily-report-table-card bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col min-h-0">
       <div class="flex-1 relative min-h-0">
         <el-auto-resizer class="absolute">
           <template #default="{ width, height }">
@@ -481,13 +615,11 @@ const handleExport = () => {
               row-key="id"
               scrollbar-always-on
               :expand-row-keys="expandRowKeys"
-              border
-            >
+              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)]"
-                  >
+                    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.groupIdBridgePlug }} </el-tag>
                     <el-tag>趟数: {{ row.groupIdRunCount }} </el-tag>
                     <el-tag>井数: {{ row.groupIdCumulativeWorkingWell }} </el-tag>
@@ -531,8 +663,7 @@ const handleExport = () => {
           :total="total"
           layout="total, sizes, prev, pager, next, jumper"
           @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
+          @current-change="handleCurrentChange" />
       </div>
     </div>
   </div>
@@ -540,7 +671,7 @@ const handleExport = () => {
 
 <style scoped>
 .daily-report-page {
-  grid-template-rows: 62px minmax(0, 1fr);
+  grid-template-rows: 62px 96px minmax(0, 1fr);
 }
 
 .daily-report-side {

+ 12 - 23
src/views/report-statistics/ry-daily-report.vue

@@ -8,7 +8,7 @@ import { TableColumnCtx } from 'element-plus/es/components/table/src/table-colum
 import { useUserStore } from '@/store/modules/user'
 import download from '@/utils/download'
 
-defineOptions({ name: 'DailyReport' })
+defineOptions({ name: 'RyDailyReport' })
 
 const tab = ref('井')
 const tabOptions = ['井', '队伍']
@@ -556,12 +556,10 @@ const handleExport = () => {
 
 <template>
   <div
-    class="daily-report-page grid grid-cols-[auto_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
-  >
+    class="daily-report-page grid grid-cols-[auto_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"
-    >
+      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>
@@ -572,8 +570,7 @@ const handleExport = () => {
             placeholder="请输入项目"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item v-show="tab !== '井'" label="任务">
           <el-input
@@ -581,8 +578,7 @@ const handleExport = () => {
             placeholder="请输入任务"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="创建时间">
           <el-date-picker
@@ -593,8 +589,7 @@ const handleExport = () => {
             end-placeholder="结束日期"
             :shortcuts="rangeShortcuts"
             :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-            class="!w-220px"
-          />
+            class="!w-220px" />
         </el-form-item>
       </div>
       <el-form-item class="ml-auto">
@@ -613,15 +608,13 @@ const handleExport = () => {
       :deptId="deptId"
       v-model="query.deptId"
       title="队伍"
-      class="daily-report-side"
-    />
+      class="daily-report-side" />
     <WellSelect
       v-show="tab === '井'"
       :deptId="158"
       v-model="query.wellName"
       v-model:contract-name="query.contractName"
-      class="daily-report-side"
-    />
+      class="daily-report-side" />
 
     <!-- 第二行左侧:自动落入第 2 行第 1 列 -->
     <!-- <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg h-full">
@@ -630,8 +623,7 @@ const handleExport = () => {
 
     <!-- 第二行右侧:自动落入第 2 行第 2 列 -->
     <div
-      class="daily-report-table-card bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col min-h-0"
-    >
+      class="daily-report-table-card bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col min-h-0">
       <div class="flex-1 relative min-h-0">
         <el-auto-resizer class="absolute">
           <template #default="{ width, height }">
@@ -650,13 +642,11 @@ const handleExport = () => {
               row-key="id"
               scrollbar-always-on
               :expand-row-keys="expandRowKeys"
-              border
-            >
+              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)]"
-                  >
+                    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>
@@ -702,8 +692,7 @@ const handleExport = () => {
           :total="total"
           layout="total, sizes, prev, pager, next, jumper"
           @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
+          @current-change="handleCurrentChange" />
       </div>
     </div>
   </div>

+ 12 - 23
src/views/report-statistics/ry-xj-daily-report.vue

@@ -8,7 +8,7 @@ import { TableColumnCtx } from 'element-plus/es/components/table/src/table-colum
 import { useUserStore } from '@/store/modules/user'
 import download from '@/utils/download'
 
-defineOptions({ name: 'DailyReport' })
+defineOptions({ name: 'RyXjDailyReport' })
 
 const tab = ref('井')
 const tabOptions = ['井', '队伍']
@@ -497,12 +497,10 @@ const handleExport = () => {
 
 <template>
   <div
-    class="daily-report-page grid grid-cols-[auto_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
-  >
+    class="daily-report-page grid grid-cols-[auto_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"
-    >
+      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>
@@ -513,8 +511,7 @@ const handleExport = () => {
             placeholder="请输入项目"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item v-show="tab !== '井'" label="任务">
           <el-input
@@ -522,8 +519,7 @@ const handleExport = () => {
             placeholder="请输入任务"
             clearable
             @keyup.enter="handleQuery()"
-            class="!w-240px"
-          />
+            class="!w-240px" />
         </el-form-item>
         <el-form-item label="创建时间">
           <el-date-picker
@@ -534,8 +530,7 @@ const handleExport = () => {
             end-placeholder="结束日期"
             :shortcuts="rangeShortcuts"
             :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-            class="!w-220px"
-          />
+            class="!w-220px" />
         </el-form-item>
       </div>
       <el-form-item class="ml-auto">
@@ -555,15 +550,13 @@ const handleExport = () => {
       :deptId="deptId"
       v-model="query.deptId"
       title="队伍"
-      class="daily-report-side"
-    />
+      class="daily-report-side" />
     <WellSelect
       v-show="tab === '井'"
       :deptId="158"
       v-model="query.wellName"
       v-model:contract-name="query.contractName"
-      class="daily-report-side"
-    />
+      class="daily-report-side" />
     <!-- 第二行左侧:自动落入第 2 行第 1 列 -->
     <!-- <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg h-full">
 
@@ -571,8 +564,7 @@ const handleExport = () => {
 
     <!-- 第二行右侧:自动落入第 2 行第 2 列 -->
     <div
-      class="daily-report-table-card bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col min-h-0"
-    >
+      class="daily-report-table-card bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col min-h-0">
       <div class="flex-1 relative min-h-0">
         <el-auto-resizer class="absolute">
           <template #default="{ width, height }">
@@ -591,13 +583,11 @@ const handleExport = () => {
               row-key="id"
               scrollbar-always-on
               :expand-row-keys="expandRowKeys"
-              border
-            >
+              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)]"
-                  >
+                    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>
@@ -643,8 +633,7 @@ const handleExport = () => {
           :total="total"
           layout="total, sizes, prev, pager, next, jumper"
           @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
+          @current-change="handleCurrentChange" />
       </div>
     </div>
   </div>

+ 17 - 30
src/views/report-statistics/work-order-completion.vue

@@ -9,6 +9,8 @@ import { rangeShortcuts } from '@/utils/formatTime'
 import download from '@/utils/download'
 import { useTableComponents } from '@/components/ZmTable/useTableComponents'
 
+defineOptions({ name: 'WorkOrderCompletion' })
+
 // 定义时间类型
 type TimeType = 'year' | 'month' | 'day'
 
@@ -280,29 +282,25 @@ async function handleExport() {
 
 <template>
   <div
-    class="grid grid-cols-[auto_1fr] grid-rows-[208px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
-  >
+    class="grid grid-cols-[auto_1fr] grid-rows-[208px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
     <DeptTreeSelect
       :top-id="156"
       :deptId="156"
       v-model="query.deptId"
       :init-select="false"
       :show-title="false"
-      class="row-span-2"
-    />
+      class="row-span-2" />
     <!-- <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg row-span-2"> </div> -->
     <div class="flex flex-col gap-4 h-full">
       <div
         class="grid grid-cols-1 md:grid-cols-3 xl:grid-cols-5 gap-4 flex-1"
-        v-loading="dataLoading"
-      >
+        v-loading="dataLoading">
         <section
           v-for="item in statList"
           :key="item.key"
           class="bg-white dark:bg-[#1d1e1f] rounded-xl shadow flex justify-between items-stretch min-h-[140px] border border-gray-200 dark:border-gray-700/50 relative overflow-hidden group transition-colors duration-300 transition-transform hover:scale-105 duration-500"
           :class="{ 'scale-105': item.type === query.type }"
-          @click="selectType(item.type)"
-        >
+          @click="selectType(item.type)">
           <div class="flex flex-col justify-between z-10 p-4 pb-2 pr-0 gap-1">
             <div class="text-gray-500 dark:text-gray-400 text-sm font-medium">
               {{ item.title }}
@@ -322,16 +320,14 @@ async function handleExport() {
                     item.tb >= 0
                       ? 'bg-emerald-100 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-400'
                       : 'bg-rose-100 text-rose-600 dark:bg-rose-500/20 dark:text-rose-400'
-                  "
-                >
+                  ">
                   <div
                     :class="
                       item.tb >= 0
                         ? 'i-material-symbols:trending-up'
                         : 'i-material-symbols:trending-down'
                     "
-                    class="text-sm"
-                  ></div>
+                    class="text-sm"></div>
                   <span>{{ Math.abs(item.hb) }}%</span>
                 </div>
                 <span class="w-6 text-xs text-gray-500 dark:text-gray-400">同比</span>
@@ -343,16 +339,14 @@ async function handleExport() {
                     item.hb >= 0
                       ? 'bg-emerald-100 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-400'
                       : 'bg-rose-100 text-rose-600 dark:bg-rose-500/20 dark:text-rose-400'
-                  "
-                >
+                  ">
                   <div
                     :class="
                       item.hb >= 0
                         ? 'i-material-symbols:trending-up'
                         : 'i-material-symbols:trending-down'
                     "
-                    class="text-sm"
-                  ></div>
+                    class="text-sm"></div>
                   <span>{{ Math.abs(item.hb) }}%</span>
                 </div>
                 <span class="min-w-8 text-xs text-gray-500 dark:text-gray-400">环比</span>
@@ -367,8 +361,7 @@ async function handleExport() {
 
           <!-- 背景装饰:颜色自适应 -->
           <div
-            class="absolute -right-6 -bottom-6 opacity-[0.05] pointer-events-none transition-transform group-hover:scale-150 duration-500 text-black dark:text-white"
-          >
+            class="absolute -right-6 -bottom-6 opacity-[0.05] pointer-events-none transition-transform group-hover:scale-150 duration-500 text-black dark:text-white">
             <div :class="item.icon" class="text-9xl"></div>
           </div>
         </section>
@@ -387,15 +380,13 @@ async function handleExport() {
             @clear="handleClear"
             @change="handleChange"
             :clearable="false"
-            :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          />
+            :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" />
           <el-button-group size="default">
             <el-button
               v-for="item in timeOptions"
               :key="item.value"
               :type="activeTimeType === item.value ? 'primary' : ''"
-              @click="handleTimeChange(item.value)"
-            >
+              @click="handleTimeChange(item.value)">
               {{ item.label }}
             </el-button>
           </el-button-group>
@@ -409,8 +400,7 @@ async function handleExport() {
             :loading="exportLoading"
             size="default"
             plain
-            type="success"
-          >
+            type="success">
             <Icon icon="ep:download" class="mr-5px" /> 导出
           </el-button>
         </div>
@@ -426,15 +416,13 @@ async function handleExport() {
               :width="width"
               :height="height"
               :max-height="height"
-              show-border
-            >
+              show-border>
               <ZmTableColumn
                 label="序号"
                 type="index"
                 :width="70"
                 fixed="left"
-                hide-in-column-settings
-              />
+                hide-in-column-settings />
               <ZmTableColumn label="工单类别" prop="type" min-width="110" />
               <ZmTableColumn label="生成日期" prop="createTime" min-width="140">
                 <template #default="{ row }">
@@ -461,8 +449,7 @@ async function handleExport() {
           :total="total"
           layout="total, sizes, prev, pager, next, jumper"
           @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
+          @current-change="handleCurrentChange" />
       </div>
     </div>
   </div>