|
|
@@ -1,1339 +1,373 @@
|
|
|
-<template>
|
|
|
- <el-row :gutter="20" class="h-full">
|
|
|
- <el-col :span="4" :xs="24">
|
|
|
- <div class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow p-4 h-full">
|
|
|
- <DeptTreeSelect
|
|
|
- :deptId="rootDeptId"
|
|
|
- :top-id="157"
|
|
|
- v-model="queryParams.deptId"
|
|
|
- @node-click="handleDeptNodeClick"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- <DeptTree2 :deptId="rootDeptId" @node-click="handleDeptNodeClick" /> -->
|
|
|
-
|
|
|
- <!-- </ContentWrap> -->
|
|
|
- </el-col>
|
|
|
- <el-col :span="20" :xs="24">
|
|
|
- <ContentWrap>
|
|
|
- <!-- 搜索工作栏 -->
|
|
|
- <el-form
|
|
|
- class="-mb-15px"
|
|
|
- :model="queryParams"
|
|
|
- ref="queryFormRef"
|
|
|
- :inline="true"
|
|
|
- label-width="80px"
|
|
|
- >
|
|
|
- <el-form-item label="项目" prop="contractName">
|
|
|
- <el-input
|
|
|
- v-model="queryParams.contractName"
|
|
|
- placeholder="请输入项目"
|
|
|
- clearable
|
|
|
- @keyup.enter="handleQuery"
|
|
|
- class="!w-240px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="任务" prop="taskName">
|
|
|
- <el-input
|
|
|
- v-model="queryParams.taskName"
|
|
|
- placeholder="请输入任务"
|
|
|
- clearable
|
|
|
- @keyup.enter="handleQuery"
|
|
|
- class="!w-240px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="创建时间" prop="createTime">
|
|
|
- <el-date-picker
|
|
|
- v-model="queryParams.createTime"
|
|
|
- value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
- type="daterange"
|
|
|
- start-placeholder="开始日期"
|
|
|
- end-placeholder="结束日期"
|
|
|
- :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
|
|
- :shortcuts="rangeShortcuts"
|
|
|
- class="!w-220px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="非生产时效" prop="nonProductFlag">
|
|
|
- <el-switch v-model="queryParams.nonProductFlag" active-value="Y" inactive-value="N" />
|
|
|
- </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
|
|
|
- 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']"
|
|
|
- >
|
|
|
- <Icon icon="ep:download" class="mr-5px" /> 导出
|
|
|
- </el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </ContentWrap>
|
|
|
-
|
|
|
- <!-- 数据统计区域 -->
|
|
|
- <ContentWrap class="mb-15px">
|
|
|
- <div class="statistics-container">
|
|
|
- <div class="stat-item" :style="{ color: totalColor }">
|
|
|
- <span>总数:</span>
|
|
|
- <span>{{ statistics.total || '-' }}</span>
|
|
|
- </div>
|
|
|
- <div class="stat-item" :style="{ color: filledColor }">
|
|
|
- <span>已填报:</span>
|
|
|
- <span>{{ statistics.filled || '-' }}</span>
|
|
|
- </div>
|
|
|
- <div class="stat-item" :style="{ color: unFilledColor }">
|
|
|
- <span>未填报:</span>
|
|
|
- <span
|
|
|
- class="unfilled-link"
|
|
|
- @click="openUnfilledDialog"
|
|
|
- :class="{ disabled: !queryParams.createTime || queryParams.createTime.length === 0 }"
|
|
|
- >
|
|
|
- {{ statistics.unFilled || '-' }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- <div class="stat-item" :style="{ color: '#0099CC' }">
|
|
|
- <span>累计注水量(方):</span>
|
|
|
- <span>{{ statistics.totalWaterInjection || '-' }}</span>
|
|
|
- </div>
|
|
|
- <div class="stat-item" :style="{ color: '#FF9900' }">
|
|
|
- <span>累计注气量(万方):</span>
|
|
|
- <span>{{ statistics.totalGasInjection || '-' }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </ContentWrap>
|
|
|
-
|
|
|
- <ContentWrap class="mb-15px">
|
|
|
- <div class="color-legend">
|
|
|
- <div class="legend-item">
|
|
|
- <span class="color-indicator red"></span>
|
|
|
- <span
|
|
|
- >运行时效=当日注气量/产能 超过120%红色预警</span
|
|
|
- >
|
|
|
- </div>
|
|
|
- <!-- <div class="legend-item">
|
|
|
- <span class="color-indicator orange"></span>
|
|
|
- <span
|
|
|
- >当日注气时间+当日注水时间+非生产时间=24H 否则橙色预警</span
|
|
|
- >
|
|
|
- </div> -->
|
|
|
- </div>
|
|
|
- </ContentWrap>
|
|
|
-
|
|
|
- <!-- 列表 -->
|
|
|
- <ContentWrap ref="tableContainerRef">
|
|
|
- <div class="table-container">
|
|
|
- <el-table
|
|
|
- ref="tableRef"
|
|
|
- v-loading="loading"
|
|
|
- :data="list"
|
|
|
- :stripe="true"
|
|
|
- :style="{ width: '100%' }"
|
|
|
- max-height="600"
|
|
|
- :cell-style="cellStyle"
|
|
|
- show-overflow-tooltip
|
|
|
- border
|
|
|
- >
|
|
|
- <el-table-column
|
|
|
- :label="t('iotDevice.serial')"
|
|
|
- width="56px"
|
|
|
- align="center"
|
|
|
- fixed="left"
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- {{ scope.$index + 1 }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="日期"
|
|
|
- align="center"
|
|
|
- prop="createTime"
|
|
|
- :formatter="dateFormatter2"
|
|
|
- :min-width="columnWidths.createTime.width"
|
|
|
- resizable
|
|
|
- fixed="left"
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="施工队伍"
|
|
|
- align="center"
|
|
|
- prop="deptName"
|
|
|
- :min-width="columnWidths.deptName.width"
|
|
|
- resizable
|
|
|
- fixed="left"
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="任务"
|
|
|
- align="center"
|
|
|
- prop="taskName"
|
|
|
- :min-width="columnWidths.taskName.width"
|
|
|
- resizable
|
|
|
- fixed="left"
|
|
|
- />
|
|
|
- <!-- <el-table-column label="施工状态" align="center" prop="constructionStatus" /> -->
|
|
|
- <el-table-column
|
|
|
- :label="t('project.status')"
|
|
|
- align="center"
|
|
|
- prop="constructionStatus"
|
|
|
- :min-width="columnWidths.constructionStatus.width"
|
|
|
- resizable
|
|
|
- fixed="left"
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag
|
|
|
- :type="DICT_TYPE.PMS_PROJECT_TASK_SCHEDULE"
|
|
|
- :value="scope.row.constructionStatus"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="搬迁安装天数"
|
|
|
- align="center"
|
|
|
- prop="relocationDays"
|
|
|
- :formatter="relocationDaysFormatter"
|
|
|
- :min-width="columnWidths.relocationDays.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="设计注气量(万方)"
|
|
|
- align="center"
|
|
|
- prop="designInjection"
|
|
|
- :min-width="columnWidths.designInjection.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="运行时效"
|
|
|
- align="center"
|
|
|
- prop="transitTime"
|
|
|
- :formatter="percentageFormatter"
|
|
|
- :min-width="columnWidths.transitTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column label="当日" align="center">
|
|
|
- <el-table-column
|
|
|
- label="注气量(万方)"
|
|
|
- align="center"
|
|
|
- prop="dailyGasInjection"
|
|
|
- :formatter="gasInjectionFormatter"
|
|
|
- :min-width="columnWidths.dailyGasInjection.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="注水量(方)"
|
|
|
- align="center"
|
|
|
- prop="dailyWaterInjection"
|
|
|
- :min-width="columnWidths.dailyWaterInjection.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="注气时间(H)"
|
|
|
- align="center"
|
|
|
- prop="dailyInjectGasTime"
|
|
|
- :min-width="columnWidths.dailyInjectGasTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="注水时间(H)"
|
|
|
- align="center"
|
|
|
- prop="dailyInjectWaterTime"
|
|
|
- :min-width="columnWidths.dailyInjectWaterTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="用电量(kWh)"
|
|
|
- align="center"
|
|
|
- prop="dailyPowerUsage"
|
|
|
- :min-width="columnWidths.dailyPowerUsage.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="油耗(L)"
|
|
|
- align="center"
|
|
|
- prop="dailyOilUsage"
|
|
|
- :min-width="columnWidths.dailyOilUsage.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="气电比"
|
|
|
- align="center"
|
|
|
- prop="gasElectricityRatio"
|
|
|
- :min-width="columnWidths.gasElectricityRatio.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="非生产时效"
|
|
|
- align="center"
|
|
|
- prop="nonProductionRate"
|
|
|
- :formatter="nonProductionRateFormatter"
|
|
|
- :min-width="columnWidths.nonProductionRate.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column label="非生产时间" align="center">
|
|
|
- <el-table-column
|
|
|
- label="工程质量"
|
|
|
- align="center"
|
|
|
- prop="accidentTime"
|
|
|
- :min-width="columnWidths.accidentTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="设备故障"
|
|
|
- align="center"
|
|
|
- prop="repairTime"
|
|
|
- :min-width="columnWidths.repairTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="设备保养"
|
|
|
- align="center"
|
|
|
- prop="selfStopTime"
|
|
|
- :min-width="columnWidths.selfStopTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="技术受限"
|
|
|
- align="center"
|
|
|
- prop="complexityTime"
|
|
|
- :min-width="columnWidths.complexityTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="生产配合"
|
|
|
- align="center"
|
|
|
- prop="relocationTime"
|
|
|
- :min-width="columnWidths.relocationTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="生产组织"
|
|
|
- align="center"
|
|
|
- prop="rectificationTime"
|
|
|
- :min-width="columnWidths.rectificationTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="不可抗力"
|
|
|
- align="center"
|
|
|
- prop="waitingStopTime"
|
|
|
- :min-width="columnWidths.waitingStopTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="待命"
|
|
|
- align="center"
|
|
|
- prop="winterBreakTime"
|
|
|
- :min-width="columnWidths.winterBreakTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="甲方设计"
|
|
|
- align="center"
|
|
|
- prop="partyaDesign"
|
|
|
- :min-width="columnWidths.partyaDesign.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="甲方准备"
|
|
|
- align="center"
|
|
|
- prop="partyaPrepare"
|
|
|
- :min-width="columnWidths.partyaPrepare.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="甲方资源"
|
|
|
- align="center"
|
|
|
- prop="partyaResource"
|
|
|
- :min-width="columnWidths.partyaResource.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="其它非生产时间"
|
|
|
- align="center"
|
|
|
- prop="otherNptTime"
|
|
|
- :min-width="columnWidths.otherNptTime.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="其他非生产时间原因"
|
|
|
- align="center"
|
|
|
- prop="otherNptReason"
|
|
|
- :min-width="columnWidths.otherNptReason.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
-
|
|
|
- <!-- <el-table-column
|
|
|
- :label="t('project.nptReason')"
|
|
|
- align="center"
|
|
|
- prop="nptReason"
|
|
|
- :min-width="columnWidths.nptReason.width"
|
|
|
- resizable
|
|
|
- >
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag :type="DICT_TYPE.PMS_PROJECT_NPT_REASON" :value="scope.row.nptReason" />
|
|
|
- </template>
|
|
|
- </el-table-column> -->
|
|
|
- <!-- <el-table-column
|
|
|
- label="施工开始日期"
|
|
|
- align="center"
|
|
|
- prop="constructionStartDate"
|
|
|
- :formatter="dateFormatter"
|
|
|
- :min-width="columnWidths.constructionStartDate.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="施工结束日期"
|
|
|
- align="center"
|
|
|
- prop="constructionEndDate"
|
|
|
- :formatter="dateFormatter"
|
|
|
- :min-width="columnWidths.constructionEndDate.width"
|
|
|
- resizable
|
|
|
- /> -->
|
|
|
- <el-table-column
|
|
|
- label="生产动态"
|
|
|
- align="center"
|
|
|
- :min-width="columnWidths.productionStatus.width"
|
|
|
- prop="productionStatus"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="项目"
|
|
|
- align="center"
|
|
|
- prop="contractName"
|
|
|
- class-name="contract-name-column"
|
|
|
- :min-width="columnWidths.contractName.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column label="井累计" align="center">
|
|
|
- <el-table-column
|
|
|
- label="注气量(万方)"
|
|
|
- align="center"
|
|
|
- prop="wellTotalGasInjection"
|
|
|
- :formatter="gasInjectionFormatter"
|
|
|
- :min-width="columnWidths.totalGasInjection.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="注水量(方)"
|
|
|
- align="center"
|
|
|
- prop="wellTotalWaterInjection"
|
|
|
- :min-width="columnWidths.totalWaterInjection.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="用电量(MWh)"
|
|
|
- align="center"
|
|
|
- prop="wellTotalPower"
|
|
|
- :formatter="gasInjectionFormatter"
|
|
|
- :min-width="columnWidths.yearTotalPower.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="油耗(L)"
|
|
|
- align="center"
|
|
|
- prop="wellTotalFuel"
|
|
|
- :min-width="columnWidths.cumulativeCompletion.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="年累计" align="center">
|
|
|
- <el-table-column
|
|
|
- label="注气量(万方)"
|
|
|
- align="center"
|
|
|
- prop="yearTotalGasInjection"
|
|
|
- :formatter="gasInjectionFormatter"
|
|
|
- :min-width="columnWidths.totalGasInjection.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="注水量(方)"
|
|
|
- align="center"
|
|
|
- prop="yearTotalWaterInjection"
|
|
|
- :min-width="columnWidths.totalWaterInjection.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="用电量(MWh)"
|
|
|
- align="center"
|
|
|
- prop="yearTotalPower"
|
|
|
- :formatter="gasInjectionFormatter"
|
|
|
- :min-width="columnWidths.yearTotalPower.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- label="油耗(L)"
|
|
|
- align="center"
|
|
|
- prop="yearTotalFuel"
|
|
|
- :min-width="columnWidths.cumulativeCompletion.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
- </el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="产能(万方)"
|
|
|
- align="center"
|
|
|
- prop="capacity"
|
|
|
- :formatter="gasInjectionFormatter"
|
|
|
- :min-width="columnWidths.capacity.width"
|
|
|
- resizable
|
|
|
- />
|
|
|
-
|
|
|
- <!-- <el-table-column label="操作" align="center" fixed="right">
|
|
|
- <template #default="scope">
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="primary"
|
|
|
- @click="openForm('update', scope.row.id, scope.row)"
|
|
|
- v-hasPermi="['pms:iot-rh-daily-report:update']"
|
|
|
- >
|
|
|
- 编辑
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="danger"
|
|
|
- @click="handleDelete(scope.row.id)"
|
|
|
- v-hasPermi="['pms:iot-rh-daily-report:delete']"
|
|
|
- >
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- </template>
|
|
|
- </el-table-column> -->
|
|
|
- </el-table>
|
|
|
- </div>
|
|
|
- <!-- 分页 -->
|
|
|
- <Pagination
|
|
|
- :total="total"
|
|
|
- v-model:page="queryParams.pageNo"
|
|
|
- v-model:limit="queryParams.pageSize"
|
|
|
- @pagination="getList"
|
|
|
- />
|
|
|
- </ContentWrap>
|
|
|
-
|
|
|
- <!-- 表单弹窗:添加/修改 -->
|
|
|
- <IotRhDailyReportForm ref="formRef" @success="getList" :row-data="selectedRowData" />
|
|
|
-
|
|
|
- <UnfilledReportDialog
|
|
|
- ref="unfilledDialogRef"
|
|
|
- :query-params="queryParams"
|
|
|
- @close="handleUnfilledDialogClose"
|
|
|
- />
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
-</template>
|
|
|
-
|
|
|
<script setup lang="ts">
|
|
|
-import { dateFormatter, dateFormatter2, rangeShortcuts } from '@/utils/formatTime'
|
|
|
+import { IotRhDailyReportApi } from '@/api/pms/iotrhdailyreport'
|
|
|
+import { useUserStore } from '@/store/modules/user'
|
|
|
import download from '@/utils/download'
|
|
|
-import { IotRhDailyReportApi, IotRhDailyReportVO } from '@/api/pms/iotrhdailyreport'
|
|
|
-import IotRhDailyReportForm from './IotRhDailyReportForm.vue'
|
|
|
-import UnfilledReportDialog from './UnfilledReportDialog.vue'
|
|
|
-import { DICT_TYPE } from '@/utils/dict'
|
|
|
-import { ref, reactive, onMounted, onUnmounted } from 'vue'
|
|
|
+import { rangeShortcuts } from '@/utils/formatTime'
|
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
|
-import quarterOfYear from 'dayjs/plugin/quarterOfYear'
|
|
|
+import UnfilledReportDialog from './UnfilledReportDialog.vue'
|
|
|
+import CountTo from '@/components/count-to1.vue'
|
|
|
import dayjs from 'dayjs'
|
|
|
+import RhTable from './rh-table.vue'
|
|
|
|
|
|
-import { useUserStore } from '@/store/modules/user'
|
|
|
+defineOptions({ name: 'IotRhDailyReport' })
|
|
|
+
|
|
|
+const route = useRoute()
|
|
|
|
|
|
-dayjs.extend(quarterOfYear)
|
|
|
+const message = useMessage()
|
|
|
|
|
|
-/** 瑞恒日报 列表 */
|
|
|
-defineOptions({ name: 'IotRhDailyReport' })
|
|
|
+const id = useUserStore().getUser.deptId
|
|
|
|
|
|
-const message = useMessage() // 消息弹窗
|
|
|
-const { t } = useI18n() // 国际化
|
|
|
+const deptId = id
|
|
|
|
|
|
-// 添加 selectedRowData 响应式变量
|
|
|
-const selectedRowData = ref<Record<string, any> | null>(null)
|
|
|
+interface Query {
|
|
|
+ deptId?: number
|
|
|
+ contractName?: string
|
|
|
+ taskName?: string
|
|
|
+ createTime?: string[]
|
|
|
+ pageNo: number
|
|
|
+ pageSize: number
|
|
|
+ nonProductFlag?: string
|
|
|
+}
|
|
|
|
|
|
-const loading = ref(true) // 列表的加载中
|
|
|
-const list = ref<IotRhDailyReportVO[]>([]) // 列表的数据
|
|
|
-const total = ref(0) // 列表的总页数
|
|
|
-let queryParams = reactive({
|
|
|
+const initQuery: Query = {
|
|
|
pageNo: 1,
|
|
|
pageSize: 10,
|
|
|
- deptId: useUserStore().getUser.deptId,
|
|
|
- contractName: undefined,
|
|
|
- projectId: undefined,
|
|
|
- taskName: undefined,
|
|
|
- taskId: undefined,
|
|
|
- projectClassification: undefined,
|
|
|
- relocationDays: undefined,
|
|
|
- transitTime: [],
|
|
|
- dailyGasInjection: undefined,
|
|
|
- dailyWaterInjection: undefined,
|
|
|
- dailyPowerUsage: undefined,
|
|
|
- dailyInjectGasTime: [],
|
|
|
- dailyInjectWaterTime: [],
|
|
|
- nonProductionTime: [],
|
|
|
- nptReason: undefined,
|
|
|
- constructionStartDate: [],
|
|
|
- constructionEndDate: [],
|
|
|
- productionStatus: undefined,
|
|
|
- nextPlan: undefined,
|
|
|
- constructionStatus: undefined,
|
|
|
- personnel: undefined,
|
|
|
- totalGasInjection: undefined,
|
|
|
- totalWaterInjection: undefined,
|
|
|
- cumulativeCompletion: undefined,
|
|
|
- extProperty: undefined,
|
|
|
- sort: undefined,
|
|
|
- remark: undefined,
|
|
|
- status: undefined,
|
|
|
- processInstanceId: undefined,
|
|
|
- auditStatus: undefined,
|
|
|
- createTime: [
|
|
|
- ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
|
|
|
+ deptId: route.query.deptId ? Number(route.query.deptId) : id,
|
|
|
+ createTime: route.query.createTime
|
|
|
+ ? (route.query.createTime as string[])
|
|
|
+ : [...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))],
|
|
|
+ nonProductFlag: route.query.nonProductFlag ? (route.query.nonProductFlag as string) : undefined
|
|
|
+}
|
|
|
+
|
|
|
+const query = ref<Query>({ ...initQuery })
|
|
|
+
|
|
|
+const totalWorkKeys: [string, string, string, string, number][] = [
|
|
|
+ ['totalGasInjection', '万方', '累计注气量', 'i-material-symbols:cloud-outline text-sky', 2],
|
|
|
+ [
|
|
|
+ 'totalWaterInjection',
|
|
|
+ '万方',
|
|
|
+ '累计注水量',
|
|
|
+ 'i-material-symbols:water-drop-outline-rounded text-sky',
|
|
|
+ 2
|
|
|
],
|
|
|
- nonProductFlag: 'N'
|
|
|
-})
|
|
|
-const queryFormRef = ref() // 搜索的表单
|
|
|
-const exportLoading = ref(false) // 导出的加载中
|
|
|
-// 添加弹窗引用
|
|
|
-const unfilledDialogRef = ref()
|
|
|
-
|
|
|
-const rootDeptId = ref(useUserStore().getUser.deptId)
|
|
|
-
|
|
|
-// 新增统计相关变量
|
|
|
-const statistics = ref({
|
|
|
- total: '-',
|
|
|
- filled: '-',
|
|
|
- unFilled: '-',
|
|
|
- totalWaterInjection: '-', // 新增累计注水量
|
|
|
- totalGasInjection: '-' // 新增累计注气量
|
|
|
-})
|
|
|
-
|
|
|
-const totalColor = '#00DD99'
|
|
|
-const filledColor = '#0055BB'
|
|
|
-const unFilledColor = '#FF5500'
|
|
|
-
|
|
|
-// 表格引用
|
|
|
-const tableRef = ref()
|
|
|
-// 表格容器引用
|
|
|
-const tableContainerRef = ref()
|
|
|
-
|
|
|
-// 工作量统计相关变量
|
|
|
-const workloadStatistics = ref({
|
|
|
- totalWaterInjection: '-',
|
|
|
- totalGasInjection: '-'
|
|
|
-})
|
|
|
-
|
|
|
-// 列宽度配置
|
|
|
-const columnWidths = ref<
|
|
|
- Record<
|
|
|
- string,
|
|
|
- { label: string; prop: string; width: string; fn?: (row: IotRhDailyReportVO) => string }
|
|
|
- >
|
|
|
->({
|
|
|
- createTime: {
|
|
|
- label: '日期',
|
|
|
- prop: 'createTime',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => dateFormatter2(null, null, row.createTime)
|
|
|
- },
|
|
|
- deptName: {
|
|
|
- label: '施工队伍',
|
|
|
- prop: 'deptName',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- contractName: {
|
|
|
- label: '项目',
|
|
|
- prop: 'contractName',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- taskName: {
|
|
|
- label: '任务',
|
|
|
- prop: 'taskName',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- constructionStatus: {
|
|
|
- label: '施工状态',
|
|
|
- prop: 'constructionStatus',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- relocationDays: {
|
|
|
- label: '搬迁安装天数',
|
|
|
- prop: 'relocationDays',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => relocationDaysFormatter(null, null, row.relocationDays, null)
|
|
|
- },
|
|
|
- designInjection: {
|
|
|
- label: '设计注气量(万方)',
|
|
|
- prop: 'designInjection',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- transitTime: {
|
|
|
- label: '运行时效',
|
|
|
- prop: 'transitTime',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => percentageFormatter(null, null, row.transitTime, null)
|
|
|
- },
|
|
|
- dailyGasInjection: {
|
|
|
- label: '注气量(万方)',
|
|
|
- prop: 'dailyGasInjection',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => gasInjectionFormatter(null, null, row.dailyGasInjection, null)
|
|
|
- },
|
|
|
- dailyWaterInjection: {
|
|
|
- label: '注水量(方)',
|
|
|
- prop: 'dailyWaterInjection',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- dailyInjectGasTime: {
|
|
|
- label: '注气时间(H)',
|
|
|
- prop: 'dailyInjectGasTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- dailyInjectWaterTime: {
|
|
|
- label: '注水时间(H)',
|
|
|
- prop: 'dailyInjectWaterTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- dailyPowerUsage: {
|
|
|
- label: '用电量(kWh)',
|
|
|
- prop: 'dailyPowerUsage',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- dailyOilUsage: {
|
|
|
- label: '油耗(L)',
|
|
|
- prop: 'dailyOilUsage',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- gasElectricityRatio: {
|
|
|
- label: '气电比',
|
|
|
- prop: 'gasElectricityRatio',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- accidentTime: {
|
|
|
- label: '工程质量',
|
|
|
- prop: 'accidentTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- repairTime: {
|
|
|
- label: '设备故障',
|
|
|
- prop: 'repairTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- selfStopTime: {
|
|
|
- label: '设备保养',
|
|
|
- prop: 'selfStopTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- complexityTime: {
|
|
|
- label: '技术受限',
|
|
|
- prop: 'complexityTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- relocationTime: {
|
|
|
- label: '生产配合',
|
|
|
- prop: 'relocationTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- rectificationTime: {
|
|
|
- label: '生产组织',
|
|
|
- prop: 'rectificationTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- waitingStopTime: {
|
|
|
- label: '不可抗力',
|
|
|
- prop: 'waitingStopTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- winterBreakTime: {
|
|
|
- label: '待命',
|
|
|
- prop: 'winterBreakTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- partyaDesign: {
|
|
|
- label: '甲方设计',
|
|
|
- prop: 'partyaDesign',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- partyaPrepare: {
|
|
|
- label: '甲方资源',
|
|
|
- prop: 'partyaPrepare',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- partyaResource: {
|
|
|
- label: '甲方准备',
|
|
|
- prop: 'partyaResource',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- otherNptTime: {
|
|
|
- label: '其它非生产时间',
|
|
|
- prop: 'otherNptTime',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- otherNptReason: {
|
|
|
- label: '其他非生产时间原因',
|
|
|
- prop: 'otherNptReason',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- constructionStartDate: {
|
|
|
- label: '施工开始日期',
|
|
|
- prop: 'constructionStartDate',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => dateFormatter(null, null, row.constructionStartDate)
|
|
|
- },
|
|
|
- constructionEndDate: {
|
|
|
- label: '施工结束日期',
|
|
|
- prop: 'constructionEndDate',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => dateFormatter(null, null, row.constructionEndDate)
|
|
|
- },
|
|
|
- productionStatus: {
|
|
|
- label: '生产动态',
|
|
|
- prop: 'productionStatus',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- totalGasInjection: {
|
|
|
- label: '注气量(万方)',
|
|
|
- prop: 'totalGasInjection',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => gasInjectionFormatter(null, null, row.totalGasInjection, null)
|
|
|
- },
|
|
|
- totalWaterInjection: {
|
|
|
- label: '注水量(方)',
|
|
|
- prop: 'totalWaterInjection',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- yearTotalPower: {
|
|
|
- label: '用电量(万千瓦时)',
|
|
|
- prop: 'yearTotalPower',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- cumulativeCompletion: {
|
|
|
- label: '完工井次',
|
|
|
- prop: 'cumulativeCompletion',
|
|
|
- width: '120px'
|
|
|
- },
|
|
|
- capacity: {
|
|
|
- label: '产能(万方)',
|
|
|
- prop: 'capacity',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => gasInjectionFormatter(null, null, row.capacity, null)
|
|
|
- },
|
|
|
- nonProductionRate: {
|
|
|
- label: '非生产时效',
|
|
|
- prop: 'nonProductionRate',
|
|
|
- width: '120px',
|
|
|
- fn: (row: IotRhDailyReportVO) => nonProductionRateFormatter(row)
|
|
|
- }
|
|
|
+ [
|
|
|
+ 'utilizationRate',
|
|
|
+ '%',
|
|
|
+ '设备利用率',
|
|
|
+ 'i-material-symbols:check-circle-outline-rounded text-emerald',
|
|
|
+ 0
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ 'totalPowerConsumption',
|
|
|
+ 'MWh',
|
|
|
+ '累计用电量',
|
|
|
+ 'i-material-symbols:electric-bolt-outline-rounded text-sky',
|
|
|
+ 2
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ 'totalFuelConsumption',
|
|
|
+ '升',
|
|
|
+ '累计油耗',
|
|
|
+ 'i-material-symbols:directions-car-outline-rounded text-sky',
|
|
|
+ 2
|
|
|
+ ],
|
|
|
+ ['totalCount', '个', '总数', 'i-tabler:report-analytics text-sky', 0],
|
|
|
+ [
|
|
|
+ 'alreadyReported',
|
|
|
+ '个',
|
|
|
+ '已填报',
|
|
|
+ 'i-material-symbols:check-circle-outline-rounded text-emerald',
|
|
|
+ 0
|
|
|
+ ],
|
|
|
+ ['notReported', '个', '未填报', 'i-material-symbols:cancel-outline-rounded text-rose', 0]
|
|
|
+]
|
|
|
+
|
|
|
+const totalWork = ref({
|
|
|
+ totalCount: 0,
|
|
|
+ alreadyReported: 0,
|
|
|
+ notReported: 0,
|
|
|
+ totalFuelConsumption: 0,
|
|
|
+ totalPowerConsumption: 0,
|
|
|
+ totalWaterInjection: 0,
|
|
|
+ totalGasInjection: 0,
|
|
|
+ utilizationRate: 0
|
|
|
})
|
|
|
|
|
|
-const nonProductionRateFormatter = (row: any) => {
|
|
|
- const nonProductionRate = row?.nonProductionRate ?? 0
|
|
|
-
|
|
|
- return (nonProductionRate * 100).toFixed(2) + '%'
|
|
|
-}
|
|
|
-
|
|
|
-// 计算文本宽度
|
|
|
-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 = useDebounceFn(() => {
|
|
|
- if (!tableContainerRef.value?.$el) return
|
|
|
- Object.values(columnWidths.value).forEach(({ fn, prop, label, width }) => {
|
|
|
- width =
|
|
|
- Math.min(
|
|
|
- ...[
|
|
|
- Math.max(
|
|
|
- ...[
|
|
|
- getTextWidth(label),
|
|
|
- ...list.value.map((v) => {
|
|
|
- return getTextWidth(fn ? fn(v) : v[prop])
|
|
|
- })
|
|
|
- ]
|
|
|
- ) +
|
|
|
- (label === '施工状态' || label === '非生产时间原因'
|
|
|
- ? 30
|
|
|
- : label === '气电比'
|
|
|
- ? 40
|
|
|
- : 20),
|
|
|
- 200
|
|
|
- ]
|
|
|
- ) + 'px'
|
|
|
-
|
|
|
- columnWidths.value[prop].width = width
|
|
|
- })
|
|
|
-}, 1000)
|
|
|
-// 计算列宽度
|
|
|
-
|
|
|
-// 格式化设计井身结构文本
|
|
|
-const formatDesignWellStruct = (text: string | null | undefined) => {
|
|
|
- if (!text) return '-'
|
|
|
- // 如果文本长度超过30个字符,显示前30个字符并添加省略号
|
|
|
- return text.length > 30 ? text.substring(0, 30) + '...' : text
|
|
|
-}
|
|
|
-
|
|
|
-// 百分比格式化函数
|
|
|
-const percentageFormatter = (row: any, column: any, cellValue: any, index: number | null) => {
|
|
|
- const capacity = Number(row?.capacity)
|
|
|
- const dailyGasInjection = Number(row?.dailyGasInjection)
|
|
|
+const totalLoading = ref(false)
|
|
|
|
|
|
- if (!capacity || !dailyGasInjection) {
|
|
|
- return '0.00%'
|
|
|
- }
|
|
|
+const getTotal = useDebounceFn(async function () {
|
|
|
+ totalLoading.value = true
|
|
|
|
|
|
- return ((dailyGasInjection / capacity) * 100).toFixed(2) + '%'
|
|
|
-
|
|
|
- // if (cellValue === null || cellValue === undefined) return ''
|
|
|
- // // 将小数转换为百分比,保留两位小数
|
|
|
- // return `${(parseFloat(cellValue) * 100).toFixed(2)}%`
|
|
|
-}
|
|
|
-
|
|
|
-// 添加打开未填报弹窗的方法
|
|
|
-const openUnfilledDialog = () => {
|
|
|
- // 检查是否选择了创建时间
|
|
|
- if (!queryParams.createTime || queryParams.createTime.length === 0) {
|
|
|
- message.warning('请先选择创建时间范围')
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 打开弹窗
|
|
|
- unfilledDialogRef.value.open()
|
|
|
-}
|
|
|
-
|
|
|
-// 弹窗关闭回调
|
|
|
-const handleUnfilledDialogClose = () => {
|
|
|
- // 可以在这里处理弹窗关闭后的逻辑
|
|
|
- console.log('未填报弹窗已关闭')
|
|
|
-}
|
|
|
-
|
|
|
-// 新增获取统计数据的方法
|
|
|
-const getStatistics = async () => {
|
|
|
- // 重置统计数据
|
|
|
- statistics.value = {
|
|
|
- total: '-',
|
|
|
- filled: '-',
|
|
|
- unFilled: '-'
|
|
|
- }
|
|
|
-
|
|
|
- // 如果没有选择时间范围,不调用接口
|
|
|
- if (!queryParams.createTime || queryParams.createTime.length === 0) {
|
|
|
- return
|
|
|
- }
|
|
|
+ const { pageNo, pageSize, ...other } = query.value
|
|
|
|
|
|
try {
|
|
|
- const res = await IotRhDailyReportApi.rhDailyReportStatistics({
|
|
|
- createTime: queryParams.createTime
|
|
|
- })
|
|
|
+ let res1: any[]
|
|
|
+ if (query.value.createTime && query.value.createTime.length === 2) {
|
|
|
+ res1 = await IotRhDailyReportApi.rhDailyReportStatistics({
|
|
|
+ createTime: query.value.createTime,
|
|
|
+ deptId: query.value.deptId
|
|
|
+ })
|
|
|
+
|
|
|
+ totalWork.value.totalCount = res1[0].count
|
|
|
+ totalWork.value.alreadyReported = res1[1].count
|
|
|
+ totalWork.value.notReported = res1[2].count
|
|
|
+ }
|
|
|
|
|
|
- // 处理统计数据
|
|
|
- const statsMap = {}
|
|
|
- res.forEach((item) => {
|
|
|
- statsMap[item.groupName] = item.count
|
|
|
- })
|
|
|
+ const res2 = await IotRhDailyReportApi.totalWorkload(other)
|
|
|
|
|
|
- statistics.value = {
|
|
|
- total: statsMap['总数'] || '-',
|
|
|
- filled: statsMap['已填报'] || '-',
|
|
|
- unFilled: statsMap['未填报'] || '-'
|
|
|
+ totalWork.value = {
|
|
|
+ ...totalWork.value,
|
|
|
+ ...res2,
|
|
|
+ totalPowerConsumption: (res2.totalPowerConsumption || 0) / 1000,
|
|
|
+ totalWaterInjection: (res2.totalWaterInjection || 0) / 10000,
|
|
|
+ totalGasInjection: (res2.totalGasInjection || 0) / 10000,
|
|
|
+ totalFuelConsumption: res2.totalFuelConsumption || 0,
|
|
|
+ utilizationRate: Number(((res2.utilizationRate || 0) * 100).toFixed(2))
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.error('获取统计数据失败', error)
|
|
|
+ } finally {
|
|
|
+ totalLoading.value = false
|
|
|
}
|
|
|
-}
|
|
|
+}, 500)
|
|
|
+
|
|
|
+const list = ref<any[]>([])
|
|
|
+const total = ref(0)
|
|
|
+
|
|
|
+const loading = ref(false)
|
|
|
|
|
|
-/** 查询列表 */
|
|
|
-const getList = async () => {
|
|
|
+const loadList = useDebounceFn(async function () {
|
|
|
loading.value = true
|
|
|
try {
|
|
|
- console.log('22 :>> ', 11)
|
|
|
- const data = await IotRhDailyReportApi.getIotRhDailyReportPage(queryParams)
|
|
|
+ const data = await IotRhDailyReportApi.getIotRhDailyReportPage(query.value)
|
|
|
list.value = data.list
|
|
|
total.value = data.total
|
|
|
-
|
|
|
- // 获取统计数据
|
|
|
- await getStatistics()
|
|
|
-
|
|
|
- // 获取工作量统计数据
|
|
|
- await getWorkloadStatistics()
|
|
|
-
|
|
|
- // 获取数据后计算列宽
|
|
|
- nextTick(() => {
|
|
|
- calculateColumnWidths()
|
|
|
- })
|
|
|
} finally {
|
|
|
loading.value = false
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// 搬迁安装天数格式化函数
|
|
|
-const relocationDaysFormatter = (row: any, column: any, cellValue: any, index: number | null) => {
|
|
|
- if (cellValue === null || cellValue === undefined || cellValue === '') return ''
|
|
|
-
|
|
|
- const value = parseFloat(cellValue)
|
|
|
- // 如果值为负数,显示0,否则显示原值
|
|
|
- return value < 0 ? '0' : String(value)
|
|
|
-}
|
|
|
-
|
|
|
-// 注气量格式化函数(单位转换:方 -> 万方)
|
|
|
-const gasInjectionFormatter = (row: any, column: any, cellValue: any, index: number | null) => {
|
|
|
- if (cellValue === null || cellValue === undefined || cellValue === '') return ''
|
|
|
- // 将方转换为万方,保留两位小数
|
|
|
- const value = parseFloat(cellValue)
|
|
|
- return (value / 10000).toFixed(2)
|
|
|
-}
|
|
|
-
|
|
|
-// 检查三个时间字段之和是否为24
|
|
|
-const checkTimeSumEquals24 = (row: any) => {
|
|
|
- // 获取三个字段的值,转换为数字,如果为空则视为0
|
|
|
- const gasTime = parseFloat(row.dailyInjectGasTime) || 0
|
|
|
- const waterTime = parseFloat(row.dailyInjectWaterTime) || 0
|
|
|
- const nonProdTime = parseFloat(row.nonProductionTime) || 0
|
|
|
-
|
|
|
- // 计算总和
|
|
|
- const sum = gasTime + waterTime + nonProdTime
|
|
|
+})
|
|
|
|
|
|
- // 返回是否等于24(允许一定的浮点数误差)
|
|
|
- return Math.abs(sum - 24) < 0.01 // 使用0.01作为误差范围
|
|
|
+function handleSizeChange(val: number) {
|
|
|
+ query.value.pageSize = val
|
|
|
+ handleQuery()
|
|
|
}
|
|
|
|
|
|
-// 单元格样式函数
|
|
|
-const cellStyle = ({
|
|
|
- row,
|
|
|
- column,
|
|
|
- rowIndex,
|
|
|
- columnIndex
|
|
|
-}: {
|
|
|
- row: any
|
|
|
- column: any
|
|
|
- rowIndex: number
|
|
|
- columnIndex: number
|
|
|
-}) => {
|
|
|
- // 只针对 transitTime 列进行处理
|
|
|
- if (column.property === 'transitTime') {
|
|
|
- // 1. 获取参与计算的字段,逻辑与 formatter 保持一致
|
|
|
- const capacity = Number(row?.capacity)
|
|
|
- const dailyGasInjection = Number(row?.dailyGasInjection)
|
|
|
-
|
|
|
- // 2. 只有当两个值都有效(且 capacity 不为 0)时才进行计算
|
|
|
- // 对应 formatter 中的 if (!capacity || !dailyGasInjection) 返回 '0.00%' 的情况
|
|
|
- if (capacity && dailyGasInjection) {
|
|
|
- const ratio = dailyGasInjection / capacity
|
|
|
-
|
|
|
- // 3. 判断计算结果是否大于 1.2 (即 120%)
|
|
|
- if (ratio > 1.2) {
|
|
|
- return {
|
|
|
- color: 'red',
|
|
|
- fontWeight: 'bold'
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 处理三个时间字段:当日注气时间、当日注水时间、非生产时间
|
|
|
- // const timeFields = ['dailyInjectGasTime', 'dailyInjectWaterTime', 'nonProductionTime']
|
|
|
- // if (timeFields.includes(column.property)) {
|
|
|
- // // 检查三个时间字段之和是否不等于24
|
|
|
- // if (!checkTimeSumEquals24(row)) {
|
|
|
- // return {
|
|
|
- // color: 'orange',
|
|
|
- // fontWeight: 'bold'
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // 默认返回空对象,不应用特殊样式
|
|
|
- return {}
|
|
|
+function handleCurrentChange(val: number) {
|
|
|
+ query.value.pageNo = val
|
|
|
+ loadList()
|
|
|
+ getTotal()
|
|
|
}
|
|
|
|
|
|
-// 获取工作量统计数据的方法
|
|
|
-const getWorkloadStatistics = async () => {
|
|
|
- // 重置工作量统计数据
|
|
|
- statistics.value.totalWaterInjection = '-'
|
|
|
- statistics.value.totalGasInjection = '-'
|
|
|
-
|
|
|
- try {
|
|
|
- const res = await IotRhDailyReportApi.totalWorkload(queryParams)
|
|
|
-
|
|
|
- // 处理工作量统计数据
|
|
|
- if (res) {
|
|
|
- // 累计注水量直接显示,单位:方
|
|
|
- statistics.value.totalWaterInjection = res.totalWaterInjection || '-'
|
|
|
-
|
|
|
- // 累计注气量需要转换:方 -> 万方 (除以10000)
|
|
|
- if (res.totalGasInjection) {
|
|
|
- const gasInjection = parseFloat(res.totalGasInjection)
|
|
|
- statistics.value.totalGasInjection = (gasInjection / 10000).toFixed(2)
|
|
|
- } else {
|
|
|
- statistics.value.totalGasInjection = '-'
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('获取工作量统计数据失败', error)
|
|
|
+function handleQuery(setPage = true) {
|
|
|
+ if (setPage) {
|
|
|
+ query.value.pageNo = 1
|
|
|
}
|
|
|
+ loadList()
|
|
|
+ getTotal()
|
|
|
}
|
|
|
|
|
|
-/** 搜索按钮操作 */
|
|
|
-const handleQuery = () => {
|
|
|
- queryParams.pageNo = 1
|
|
|
- getList()
|
|
|
-}
|
|
|
-
|
|
|
-const route = useRoute()
|
|
|
+function resetQuery() {
|
|
|
+ query.value = { ...initQuery }
|
|
|
|
|
|
-/** 重置按钮操作 */
|
|
|
-const resetQuery = () => {
|
|
|
- queryFormRef.value.resetFields()
|
|
|
- queryParams.deptId = useUserStore().getUser.deptId
|
|
|
- // 重置后需要重新获取统计数据
|
|
|
- getStatistics()
|
|
|
- // 重新获取工作量统计数据
|
|
|
- getWorkloadStatistics()
|
|
|
handleQuery()
|
|
|
}
|
|
|
|
|
|
-/** 添加/修改操作 */
|
|
|
-const formRef = ref()
|
|
|
-const openForm = (type: string, id?: number, row?: any) => {
|
|
|
- // 保存当前行数据
|
|
|
- if (row) {
|
|
|
- selectedRowData.value = {
|
|
|
- deptName: row.deptName,
|
|
|
- contractName: row.contractName,
|
|
|
- taskName: row.taskName,
|
|
|
- relocationDays: row.relocationDays
|
|
|
- }
|
|
|
- } else {
|
|
|
- selectedRowData.value = null
|
|
|
- }
|
|
|
-
|
|
|
- formRef.value.open(type, id)
|
|
|
-}
|
|
|
-
|
|
|
-/** 删除按钮操作 */
|
|
|
-const handleDelete = async (id: number) => {
|
|
|
- try {
|
|
|
- // 删除的二次确认
|
|
|
- await message.delConfirm()
|
|
|
- // 发起删除
|
|
|
- await IotRhDailyReportApi.deleteIotRhDailyReport(id)
|
|
|
- message.success(t('common.delSuccess'))
|
|
|
- // 刷新列表
|
|
|
- await getList()
|
|
|
- } catch {}
|
|
|
-}
|
|
|
-
|
|
|
-// 响应式变量存储选中的部门
|
|
|
-const selectedDept = ref<{ id: number; name: string }>()
|
|
|
-/** 处理部门被点击 */
|
|
|
-const handleDeptNodeClick = async (row) => {
|
|
|
- // 记录选中的部门信息
|
|
|
- selectedDept.value = { id: row.id, name: row.name }
|
|
|
- // queryParams.deptId = row.id
|
|
|
- await getList()
|
|
|
-}
|
|
|
-
|
|
|
-/** 导出按钮操作 */
|
|
|
-const handleExport = async () => {
|
|
|
- try {
|
|
|
- // 导出的二次确认
|
|
|
- await message.exportConfirm()
|
|
|
- // 发起导出
|
|
|
- exportLoading.value = true
|
|
|
- const data = await IotRhDailyReportApi.exportIotRhDailyReport(queryParams)
|
|
|
- download.excel(data, '瑞恒日报.xls')
|
|
|
- } catch {
|
|
|
- } finally {
|
|
|
- exportLoading.value = false
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 声明 ResizeObserver 实例
|
|
|
-let resizeObserver: ResizeObserver | null = null
|
|
|
-
|
|
|
-/** 初始化 **/
|
|
|
-onMounted(() => {
|
|
|
- if (Object.keys(route.query).length > 0) {
|
|
|
- nextTick(() => {
|
|
|
- queryParams.deptId = Number(route.query.deptId) as any
|
|
|
- queryParams.createTime = route.query.createTime as string[]
|
|
|
- queryParams.nonProductFlag = route.query.nonProductFlag as string
|
|
|
- handleQuery()
|
|
|
- })
|
|
|
- } else getList()
|
|
|
- // 创建 ResizeObserver 监听表格容器尺寸变化
|
|
|
- if (tableContainerRef.value?.$el) {
|
|
|
- resizeObserver = new ResizeObserver(() => {
|
|
|
- // 使用防抖避免频繁触发
|
|
|
- clearTimeout((window as any).resizeTimer)
|
|
|
- ;(window as any).resizeTimer = setTimeout(() => {
|
|
|
- calculateColumnWidths()
|
|
|
- }, 100)
|
|
|
- })
|
|
|
- resizeObserver.observe(tableContainerRef.value.$el)
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-onUnmounted(() => {
|
|
|
- // 清除 ResizeObserver
|
|
|
- if (resizeObserver && tableContainerRef.value?.$el) {
|
|
|
- resizeObserver.unobserve(tableContainerRef.value.$el)
|
|
|
- resizeObserver = null
|
|
|
- }
|
|
|
-
|
|
|
- // 清除定时器
|
|
|
- if ((window as any).resizeTimer) {
|
|
|
- clearTimeout((window as any).resizeTimer)
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-// 监听列表数据变化重新计算列宽
|
|
|
watch(
|
|
|
- list,
|
|
|
+ [
|
|
|
+ () => query.value.deptId,
|
|
|
+ () => query.value.contractName,
|
|
|
+ () => query.value.taskName,
|
|
|
+ () => query.value.createTime,
|
|
|
+ () => query.value.nonProductFlag
|
|
|
+ ],
|
|
|
() => {
|
|
|
- nextTick(() => calculateColumnWidths())
|
|
|
+ handleQuery()
|
|
|
},
|
|
|
- { deep: true }
|
|
|
+ { immediate: true }
|
|
|
)
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-/* 表格容器样式,确保水平滚动 */
|
|
|
-.table-container {
|
|
|
- width: 100%;
|
|
|
- overflow-x: auto;
|
|
|
-}
|
|
|
-
|
|
|
-/* 确保表格单元格内容不换行 */
|
|
|
|
|
|
-/* :deep(.el-table .cell) {
|
|
|
- white-space: nowrap;
|
|
|
-} */
|
|
|
+// const selectedRowData = ref<any>(null)
|
|
|
|
|
|
-/* 确保表格列标题不换行 */
|
|
|
+// const formRef = ref()
|
|
|
|
|
|
-/* :deep(.el-table th > .cell) {
|
|
|
- white-space: nowrap;
|
|
|
-} */
|
|
|
+// const openForm = (type: string, id?: number, row?: any) => {
|
|
|
+// if (row) {
|
|
|
+// selectedRowData.value = {
|
|
|
+// deptName: row.deptName,
|
|
|
+// contractName: row.contractName,
|
|
|
+// taskName: row.taskName,
|
|
|
+// relocationDays: row.relocationDays
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// selectedRowData.value = null
|
|
|
+// }
|
|
|
|
|
|
-/* 调整表格最小宽度,确保内容完全显示 */
|
|
|
-:deep(.el-table) {
|
|
|
- min-width: 100%;
|
|
|
-}
|
|
|
-
|
|
|
-/* 强制显示所有内容,防止省略号 */
|
|
|
-
|
|
|
-/* :deep(.el-table td.el-table__cell),
|
|
|
-:deep(.el-table th.el-table__cell) {
|
|
|
- overflow: visible !important;
|
|
|
-} */
|
|
|
-
|
|
|
-/* :deep(.el-table .cell) {
|
|
|
- overflow: visible !important;
|
|
|
- text-overflow: clip !important;
|
|
|
-} */
|
|
|
+// formRef.value.open(type, id)
|
|
|
+// }
|
|
|
|
|
|
-/* :deep(.contract-name-column .cell) {
|
|
|
- overflow: hidden !important;
|
|
|
- text-overflow: ellipsis !important;
|
|
|
- white-space: nowrap !important;
|
|
|
-} */
|
|
|
-
|
|
|
-/* 颜色说明区域样式 */
|
|
|
-.color-legend {
|
|
|
- display: flex;
|
|
|
- padding: 12px 16px;
|
|
|
- background-color: #f8f9fa;
|
|
|
- border-left: 4px solid #e6f7ff;
|
|
|
- border-radius: 4px;
|
|
|
- flex-direction: column;
|
|
|
- gap: 8px;
|
|
|
-}
|
|
|
-
|
|
|
-.legend-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 8px;
|
|
|
- font-size: 14px;
|
|
|
-}
|
|
|
+const exportLoading = ref(false)
|
|
|
|
|
|
-.color-indicator {
|
|
|
- display: inline-block;
|
|
|
- width: 12px;
|
|
|
- height: 12px;
|
|
|
- border-radius: 50%;
|
|
|
-}
|
|
|
+async function handleExport() {
|
|
|
+ try {
|
|
|
+ await message.exportConfirm()
|
|
|
|
|
|
-.color-indicator.red {
|
|
|
- background-color: red;
|
|
|
-}
|
|
|
+ exportLoading.value = true
|
|
|
+ const res = await IotRhDailyReportApi.exportIotRhDailyReport(query.value)
|
|
|
|
|
|
-.color-indicator.orange {
|
|
|
- background-color: orange;
|
|
|
+ download.excel(res, '瑞恒日报.xls')
|
|
|
+ } finally {
|
|
|
+ exportLoading.value = false
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-/* 统计区域未填报链接样式 */
|
|
|
-.unfilled-link {
|
|
|
- color: #f50;
|
|
|
- text-decoration: underline;
|
|
|
- cursor: pointer;
|
|
|
-}
|
|
|
+const unfilledDialogRef = ref()
|
|
|
|
|
|
-.unfilled-link:hover {
|
|
|
- color: #f73;
|
|
|
-}
|
|
|
+const openUnfilledDialog = () => {
|
|
|
+ if (!query.value.createTime || query.value.createTime.length === 0) {
|
|
|
+ message.warning('请先选择创建时间范围')
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
-.unfilled-link.disabled {
|
|
|
- color: #ccc;
|
|
|
- text-decoration: none;
|
|
|
- cursor: not-allowed;
|
|
|
+ // 打开弹窗
|
|
|
+ unfilledDialogRef.value.open()
|
|
|
}
|
|
|
-</style>
|
|
|
+</script>
|
|
|
|
|
|
-<style>
|
|
|
-/* 设计井身结构 tooltip 样式 - 保留换行符 */
|
|
|
-.design-well-struct-tooltip {
|
|
|
- max-width: 500px;
|
|
|
- line-height: 1.5;
|
|
|
- white-space: pre-line;
|
|
|
-}
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ class="grid grid-cols-[15%_1fr] grid-rows-[48px_auto_auto_1fr] gap-x-4 gap-y-3 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]"
|
|
|
+ >
|
|
|
+ <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg row-span-4">
|
|
|
+ <DeptTreeSelect :top-id="157" :deptId="deptId" v-model="query.deptId" :show-title="false" />
|
|
|
+ </div>
|
|
|
+ <el-form
|
|
|
+ size="default"
|
|
|
+ class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-6 gap-8 flex items-center justify-between"
|
|
|
+ >
|
|
|
+ <div class="flex items-center gap-8">
|
|
|
+ <el-form-item label="项目">
|
|
|
+ <el-input
|
|
|
+ v-model="query.contractName"
|
|
|
+ placeholder="请输入项目"
|
|
|
+ clearable
|
|
|
+ @keyup.enter="handleQuery()"
|
|
|
+ class="!w-180px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="任务">
|
|
|
+ <el-input
|
|
|
+ v-model="query.taskName"
|
|
|
+ placeholder="请输入任务"
|
|
|
+ clearable
|
|
|
+ @keyup.enter="handleQuery()"
|
|
|
+ class="!w-180px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="创建时间" prop="createTime">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="query.createTime"
|
|
|
+ value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ type="daterange"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
|
|
+ class="!w-220px"
|
|
|
+ :shortcuts="rangeShortcuts"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="非生产时效" prop="nonProductFlag">
|
|
|
+ <el-switch v-model="query.nonProductFlag" active-value="Y" inactive-value="N" />
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ <el-form-item>
|
|
|
+ <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
|
|
|
+ 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']"
|
|
|
+ >
|
|
|
+ <Icon icon="ep:download" class="mr-5px" /> 导出
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div class="grid grid-cols-8 gap-3">
|
|
|
+ <div
|
|
|
+ v-for="info in totalWorkKeys"
|
|
|
+ :key="info[0]"
|
|
|
+ class="group relative bg-white dark:bg-[#1d1e1f] rounded-lg shadow-sm hover:shadow-md border border-gray-100 dark:border-gray-700 p-2.5 overflow-hidden transition-all duration-300"
|
|
|
+ :class="{
|
|
|
+ 'cursor-pointer hover:border-blue-200 dark:hover:border-blue-800': info[2] === '未填报'
|
|
|
+ }"
|
|
|
+ @click="info[2] === '未填报' ? openUnfilledDialog() : ''"
|
|
|
+ >
|
|
|
+ <div class="relative z-10 flex flex-col h-full justify-center">
|
|
|
+ <span
|
|
|
+ class="text-[11px] text-gray-400 dark:text-gray-500 font-medium tracking-wide mb-0.5"
|
|
|
+ >
|
|
|
+ {{ info[2] }}
|
|
|
+ </span>
|
|
|
+ <div class="flex items-baseline gap-1">
|
|
|
+ <count-to
|
|
|
+ class="text-lg font-bold text-gray-800 dark:text-gray-100 leading-none tracking-tight font-sans"
|
|
|
+ :start-val="0"
|
|
|
+ :end-val="totalWork[info[0]]"
|
|
|
+ :decimals="info[4]"
|
|
|
+ />
|
|
|
+ <span class="text-[10px] text-gray-400 font-normal">{{ info[1] }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
-/* 统计区域样式 */
|
|
|
-.statistics-container {
|
|
|
- display: flex;
|
|
|
- justify-content: space-around;
|
|
|
- padding: 10px 0;
|
|
|
-}
|
|
|
+ <div
|
|
|
+ class="absolute -right-2 -bottom-3 opacity-40 dark:opacity-60 transform rotate-[-10deg] transition-transform duration-500 group-hover:scale-110 group-hover:rotate-0"
|
|
|
+ >
|
|
|
+ <div :class="info[3]" class="text-5xl"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="p-2 bg-white dark:bg-[#1d1e1f] rounded-lg shadow">
|
|
|
+ <el-alert
|
|
|
+ class="h-8!"
|
|
|
+ title="运行时效=当日注气量/产能 超过120%红色预警"
|
|
|
+ type="error"
|
|
|
+ show-icon
|
|
|
+ :closable="false"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <rh-table
|
|
|
+ :list="list"
|
|
|
+ :total="total"
|
|
|
+ :loading="loading"
|
|
|
+ :page-no="query.pageNo"
|
|
|
+ :page-size="query.pageSize"
|
|
|
+ :show-action="false"
|
|
|
+ is-index
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <UnfilledReportDialog ref="unfilledDialogRef" :query-params="query" />
|
|
|
+</template>
|
|
|
|
|
|
-.stat-item {
|
|
|
- min-width: 0; /* 防止内容溢出 */
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 500;
|
|
|
- text-align: center;
|
|
|
- flex: 1;
|
|
|
+<style scoped>
|
|
|
+:deep(.el-form-item) {
|
|
|
+ margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
-/* 确保统计项内容不换行 */
|
|
|
-.stat-item span {
|
|
|
- white-space: nowrap;
|
|
|
+:deep(.zm-table) {
|
|
|
+ .el-table__cell {
|
|
|
+ height: 42px;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|