index.vue 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. <template>
  2. <el-row :gutter="20">
  3. <el-col :span="4" :xs="24">
  4. <ContentWrap class="h-1/1">
  5. <DeptTree2 :deptId="rootDeptId" @node-click="handleDeptNodeClick" />
  6. </ContentWrap>
  7. </el-col>
  8. <el-col :span="20" :xs="24">
  9. <ContentWrap>
  10. <!-- 搜索工作栏 -->
  11. <el-form
  12. class="-mb-15px"
  13. :model="queryParams"
  14. ref="queryFormRef"
  15. :inline="true"
  16. label-width="68px"
  17. >
  18. <el-form-item label="项目" prop="contractName">
  19. <el-input
  20. v-model="queryParams.contractName"
  21. placeholder="请输入项目"
  22. clearable
  23. @keyup.enter="handleQuery"
  24. class="!w-240px"
  25. />
  26. </el-form-item>
  27. <el-form-item label="任务" prop="taskName">
  28. <el-input
  29. v-model="queryParams.taskName"
  30. placeholder="请输入任务"
  31. clearable
  32. @keyup.enter="handleQuery"
  33. class="!w-240px"
  34. />
  35. </el-form-item>
  36. <el-form-item label="创建时间" prop="createTime">
  37. <el-date-picker
  38. v-model="queryParams.createTime"
  39. value-format="YYYY-MM-DD HH:mm:ss"
  40. type="daterange"
  41. start-placeholder="开始日期"
  42. end-placeholder="结束日期"
  43. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  44. class="!w-220px"
  45. :shortcuts="rangeShortcuts"
  46. />
  47. </el-form-item>
  48. <el-form-item>
  49. <el-button @click="handleQuery"
  50. ><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button
  51. >
  52. <el-button @click="resetQuery"
  53. ><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button
  54. >
  55. <el-button
  56. type="primary"
  57. plain
  58. @click="openForm('create')"
  59. v-hasPermi="['pms:iot-ry-daily-report:create']"
  60. >
  61. <Icon icon="ep:plus" class="mr-5px" /> 新增
  62. </el-button>
  63. <el-button
  64. type="success"
  65. plain
  66. @click="handleExport"
  67. :loading="exportLoading"
  68. v-hasPermi="['pms:iot-ry-daily-report:export']"
  69. >
  70. <Icon icon="ep:download" class="mr-5px" /> 导出
  71. </el-button>
  72. </el-form-item>
  73. </el-form>
  74. </ContentWrap>
  75. <ContentWrap class="mb-15px">
  76. <div class="color-legend">
  77. <div class="legend-item">
  78. <span class="color-indicator red"></span>
  79. <span>当日油耗大于15吨&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;红色预警</span>
  80. </div>
  81. <div class="legend-item">
  82. <span class="color-indicator orange"></span>
  83. <span
  84. >进尺工作时间+其它生产时间+非生产时间=24H&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;否则橙色预警</span
  85. >
  86. </div>
  87. </div>
  88. </ContentWrap>
  89. <!-- 列表 -->
  90. <ContentWrap ref="tableContainerRef">
  91. <div class="table-container">
  92. <el-table
  93. ref="tableRef"
  94. v-loading="loading"
  95. :data="list"
  96. :stripe="true"
  97. :style="{ width: '100%' }"
  98. max-height="600"
  99. :cell-style="cellStyle"
  100. show-overflow-tooltip
  101. border
  102. >
  103. <el-table-column :label="t('iotDevice.serial')" width="56px" align="center">
  104. <template #default="scope">
  105. {{ scope.$index + 1 }}
  106. </template>
  107. </el-table-column>
  108. <el-table-column
  109. label="日期"
  110. align="center"
  111. prop="createTime"
  112. :formatter="dateFormatter2"
  113. :min-width="columnWidths.createTime.width"
  114. resizable
  115. />
  116. <el-table-column
  117. label="施工队伍"
  118. align="center"
  119. prop="deptName"
  120. :min-width="columnWidths.deptName.width"
  121. resizable
  122. />
  123. <el-table-column
  124. label="项目"
  125. align="center"
  126. prop="contractName"
  127. :min-width="columnWidths.contractName.width"
  128. resizable
  129. />
  130. <el-table-column
  131. label="任务"
  132. align="center"
  133. prop="taskName"
  134. :min-width="columnWidths.taskName.width"
  135. resizable
  136. />
  137. <el-table-column
  138. label="设备型号"
  139. align="center"
  140. prop="equipmentType"
  141. :min-width="columnWidths.equipmentType.width"
  142. resizable
  143. />
  144. <el-table-column
  145. :label="t('project.status')"
  146. align="center"
  147. prop="rigStatus"
  148. :min-width="columnWidths.rigStatus.width"
  149. resizable
  150. >
  151. <template #default="scope">
  152. <dict-tag
  153. :type="DICT_TYPE.PMS_PROJECT_TASK_RY_SCHEDULE"
  154. :value="scope.row.rigStatus"
  155. />
  156. </template>
  157. </el-table-column>
  158. <el-table-column
  159. label="上井次完井时间"
  160. align="center"
  161. prop="latestWellDoneTime"
  162. :min-width="columnWidths.latestWellDoneTime.width"
  163. :formatter="dateFormatter2"
  164. resizable
  165. />
  166. <el-table-column align="center" label="井深(m)">
  167. <el-table-column
  168. label="设计"
  169. align="center"
  170. prop="designWellDepth"
  171. :min-width="columnWidths.designWellDepth.width"
  172. resizable
  173. />
  174. <el-table-column
  175. label="当前"
  176. align="center"
  177. prop="currentDepth"
  178. :min-width="columnWidths.currentDepth.width"
  179. resizable
  180. />
  181. </el-table-column>
  182. <el-table-column align="center" label="进尺(m)">
  183. <el-table-column
  184. label="日"
  185. align="center"
  186. prop="dailyFootage"
  187. :min-width="columnWidths.dailyFootage.width"
  188. resizable
  189. />
  190. <el-table-column
  191. label="月"
  192. align="center"
  193. prop="monthlyFootage"
  194. :min-width="columnWidths.monthlyFootage.width"
  195. resizable
  196. />
  197. <el-table-column
  198. label="年累计"
  199. align="center"
  200. prop="annualFootage"
  201. :min-width="columnWidths.annualFootage.width"
  202. resizable
  203. />
  204. </el-table-column>
  205. <el-table-column
  206. label="总施工井数"
  207. align="center"
  208. prop="totalConstructionWells"
  209. :min-width="columnWidths.totalConstructionWells.width"
  210. resizable
  211. />
  212. <el-table-column
  213. label="完工井数"
  214. align="center"
  215. prop="completedWells"
  216. :min-width="columnWidths.completedWells.width"
  217. resizable
  218. />
  219. <el-table-column align="center" label="泥浆性能">
  220. <el-table-column
  221. label="密度(g/cm³)"
  222. align="center"
  223. prop="mudDensity"
  224. :min-width="columnWidths.mudDensity.width"
  225. resizable
  226. />
  227. <el-table-column
  228. label="粘度(S)"
  229. align="center"
  230. prop="mudViscosity"
  231. :min-width="columnWidths.mudViscosity.width"
  232. resizable
  233. />
  234. </el-table-column>
  235. <el-table-column align="center" label="当日">
  236. <el-table-column
  237. label="用电量(kWh)"
  238. align="center"
  239. prop="dailyPowerUsage"
  240. :min-width="columnWidths.dailyPowerUsage.width"
  241. resizable
  242. />
  243. <el-table-column
  244. label="油耗(吨)"
  245. align="center"
  246. prop="dailyFuel"
  247. :min-width="columnWidths.dailyFuel.width"
  248. resizable
  249. >
  250. <template #default="scope">
  251. <span :class="{ 'fuel-warning': shouldShowFuelWarning(scope.row) }">
  252. {{ scope.row.dailyFuel }}
  253. </span>
  254. </template>
  255. </el-table-column>
  256. </el-table-column>
  257. <el-table-column
  258. label="施工开始日期"
  259. align="center"
  260. prop="constructionStartDate"
  261. :formatter="dateFormatter"
  262. :min-width="columnWidths.constructionStartDate.width"
  263. resizable
  264. />
  265. <el-table-column
  266. label="施工结束日期"
  267. align="center"
  268. prop="constructionEndDate"
  269. :formatter="dateFormatter"
  270. :min-width="columnWidths.constructionEndDate.width"
  271. resizable
  272. />
  273. <el-table-column
  274. label="水平段长度(m)"
  275. align="center"
  276. prop="lateralLength"
  277. :min-width="columnWidths.lateralLength.width"
  278. resizable
  279. />
  280. <el-table-column
  281. label="井斜(°)"
  282. align="center"
  283. prop="wellInclination"
  284. :min-width="columnWidths.wellInclination.width"
  285. resizable
  286. />
  287. <el-table-column
  288. label="方位(°)"
  289. align="center"
  290. prop="azimuth"
  291. :min-width="columnWidths.azimuth.width"
  292. resizable
  293. />
  294. <el-table-column
  295. label="设计井身结构"
  296. align="center"
  297. prop="designWellStruct"
  298. :min-width="columnWidths.designWellStruct.width"
  299. resizable
  300. />
  301. <el-table-column
  302. label="生产动态"
  303. align="center"
  304. prop="productionStatus"
  305. :width="columnWidths.productionStatus.width"
  306. />
  307. <el-table-column
  308. label="进尺工作时间(H)"
  309. align="center"
  310. prop="drillingWorkingTime"
  311. :min-width="columnWidths.drillingWorkingTime.width"
  312. resizable
  313. />
  314. <el-table-column
  315. label="其它生产时间(H)"
  316. align="center"
  317. prop="otherProductionTime"
  318. :min-width="columnWidths.otherProductionTime.width"
  319. resizable
  320. />
  321. <el-table-column label="非生产时间" align="center">
  322. <el-table-column
  323. label="事故(H)"
  324. align="center"
  325. prop="accidentTime"
  326. :min-width="columnWidths.accidentTime.width"
  327. resizable
  328. />
  329. <el-table-column
  330. label="修理(H)"
  331. align="center"
  332. prop="repairTime"
  333. :min-width="columnWidths.repairTime.width"
  334. resizable
  335. />
  336. <el-table-column
  337. label="自停(H)"
  338. align="center"
  339. prop="selfStopTime"
  340. :min-width="columnWidths.selfStopTime.width"
  341. resizable
  342. />
  343. <el-table-column
  344. label="复杂(H)"
  345. align="center"
  346. prop="complexityTime"
  347. :min-width="columnWidths.complexityTime.width"
  348. resizable
  349. />
  350. <el-table-column
  351. label="搬迁(H)"
  352. align="center"
  353. prop="relocationTime"
  354. :min-width="columnWidths.relocationTime.width"
  355. resizable
  356. />
  357. <el-table-column
  358. label="整改(H)"
  359. align="center"
  360. prop="rectificationTime"
  361. :min-width="columnWidths.rectificationTime.width"
  362. resizable
  363. />
  364. <el-table-column
  365. label="等停(H)"
  366. align="center"
  367. prop="waitingStopTime"
  368. :min-width="columnWidths.waitingStopTime.width"
  369. resizable
  370. />
  371. <el-table-column
  372. label="冬休(H)"
  373. align="center"
  374. prop="winterBreakTime"
  375. :min-width="columnWidths.winterBreakTime.width"
  376. resizable
  377. />
  378. </el-table-column>
  379. <el-table-column label="操作" align="center" fixed="right">
  380. <template #default="scope">
  381. <el-button
  382. link
  383. type="primary"
  384. @click="openForm('update', scope.row.id, scope.row)"
  385. v-hasPermi="['pms:iot-ry-daily-report:update']"
  386. >
  387. 编辑
  388. </el-button>
  389. <el-button
  390. link
  391. type="danger"
  392. @click="handleDelete(scope.row.id)"
  393. v-hasPermi="['pms:iot-ry-daily-report:delete']"
  394. >
  395. 删除
  396. </el-button>
  397. </template>
  398. </el-table-column>
  399. </el-table>
  400. </div>
  401. <!-- 分页 -->
  402. <Pagination
  403. :total="total"
  404. v-model:page="queryParams.pageNo"
  405. v-model:limit="queryParams.pageSize"
  406. @pagination="getList"
  407. />
  408. </ContentWrap>
  409. <!-- 表单弹窗:添加/修改 -->
  410. <IotRyDailyReportForm ref="formRef" @success="getList" :row-data="selectedRowData" />
  411. </el-col>
  412. </el-row>
  413. </template>
  414. <script setup lang="ts">
  415. import { dateFormatter, dateFormatter2, rangeShortcuts } from '@/utils/formatTime'
  416. import download from '@/utils/download'
  417. import { IotRyDailyReportApi, IotRyDailyReportVO } from '@/api/pms/iotrydailyreport'
  418. import IotRyDailyReportForm from './IotRyDailyReportForm.vue'
  419. import { DICT_TYPE } from '@/utils/dict'
  420. import { ref, reactive, onMounted, nextTick, watch, onUnmounted } from 'vue'
  421. import DeptTree2 from '@/views/pms/iotrhdailyreport/DeptTree2.vue'
  422. import dayjs from 'dayjs'
  423. import quarterOfYear from 'dayjs/plugin/quarterOfYear'
  424. import { useDebounceFn } from '@vueuse/core'
  425. dayjs.extend(quarterOfYear)
  426. /** 瑞鹰日报 列表 */
  427. defineOptions({ name: 'IotRyDailyReport' })
  428. const message = useMessage() // 消息弹窗
  429. const { t } = useI18n() // 国际化
  430. // 添加 selectedRowData 响应式变量
  431. const selectedRowData = ref<Record<string, any> | null>(null)
  432. const rootDeptId = ref(158)
  433. const loading = ref(true) // 列表的加载中
  434. const list = ref<IotRyDailyReportVO[]>([]) // 列表的数据
  435. const total = ref(0) // 列表的总页数
  436. let queryParams = reactive({
  437. pageNo: 1,
  438. pageSize: 10,
  439. deptId: undefined,
  440. contractName: undefined,
  441. projectId: undefined,
  442. taskName: undefined,
  443. taskId: undefined,
  444. projectClassification: '1',
  445. relocationDays: undefined,
  446. latestWellDoneTime: [],
  447. currentDepth: undefined,
  448. dailyFootage: undefined,
  449. monthlyFootage: undefined,
  450. annualFootage: undefined,
  451. dailyPowerUsage: undefined,
  452. monthlyPowerUsage: undefined,
  453. dailyFuel: undefined,
  454. monthlyFuel: undefined,
  455. nonProductionTime: [],
  456. nptReason: undefined,
  457. constructionStartDate: [],
  458. constructionEndDate: [],
  459. productionStatus: undefined,
  460. nextPlan: undefined,
  461. rigStatus: undefined,
  462. personnel: undefined,
  463. mudDensity: undefined,
  464. mudViscosity: undefined,
  465. lateralLength: undefined,
  466. wellInclination: undefined,
  467. azimuth: undefined,
  468. extProperty: undefined,
  469. sort: undefined,
  470. remark: undefined,
  471. status: undefined,
  472. processInstanceId: undefined,
  473. auditStatus: undefined,
  474. createTime: [
  475. ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
  476. ]
  477. })
  478. const queryFormRef = ref() // 搜索的表单
  479. const exportLoading = ref(false) // 导出的加载中
  480. // 表格引用
  481. const tableRef = ref()
  482. // 表格容器引用
  483. const tableContainerRef = ref()
  484. const columnWidths = ref<
  485. Record<
  486. string,
  487. { label: string; prop: string; width: string; fn?: (row: IotRyDailyReportVO) => string }
  488. >
  489. >({
  490. createTime: {
  491. label: '日期',
  492. prop: 'createTime',
  493. width: '120px',
  494. fn: (row: IotRyDailyReportVO) => dateFormatter2(null, null, row.createTime)
  495. },
  496. deptName: {
  497. label: '施工队伍',
  498. prop: 'deptName',
  499. width: '120px'
  500. },
  501. contractName: {
  502. label: '项目',
  503. prop: 'contractName',
  504. width: '120px'
  505. },
  506. taskName: {
  507. label: '任务',
  508. prop: 'taskName',
  509. width: '120px'
  510. },
  511. equipmentType: {
  512. label: '设备型号',
  513. prop: 'equipmentType',
  514. width: '120px'
  515. },
  516. rigStatus: {
  517. label: '施工状态',
  518. prop: 'rigStatus',
  519. width: '120px'
  520. },
  521. latestWellDoneTime: {
  522. label: '上井次完井时间',
  523. prop: 'latestWellDoneTime',
  524. width: '120px',
  525. fn: (row: IotRyDailyReportVO) => dateFormatter2(null, null, row.latestWellDoneTime)
  526. },
  527. designWellDepth: {
  528. label: '设计',
  529. prop: 'designWellDepth',
  530. width: '120px'
  531. },
  532. currentDepth: {
  533. label: '当前',
  534. prop: 'currentDepth',
  535. width: '120px'
  536. },
  537. dailyFootage: {
  538. label: '日',
  539. prop: 'dailyFootage',
  540. width: '120px'
  541. },
  542. monthlyFootage: {
  543. label: '月',
  544. prop: 'monthlyFootage',
  545. width: '120px'
  546. },
  547. annualFootage: {
  548. label: '年累计',
  549. prop: 'annualFootage',
  550. width: '120px'
  551. },
  552. totalConstructionWells: {
  553. label: '总施工井数',
  554. prop: 'totalConstructionWells',
  555. width: '120px'
  556. },
  557. completedWells: {
  558. label: '完工井数',
  559. prop: 'completedWells',
  560. width: '120px'
  561. },
  562. mudDensity: {
  563. label: '密度(g/cm³)',
  564. prop: 'mudDensity',
  565. width: '120px'
  566. },
  567. mudViscosity: {
  568. label: '粘度(S)',
  569. prop: 'mudViscosity',
  570. width: '120px'
  571. },
  572. dailyPowerUsage: {
  573. label: '用电量(kWh)',
  574. prop: 'dailyPowerUsage',
  575. width: '120px'
  576. },
  577. dailyFuel: {
  578. label: '油耗(吨)',
  579. prop: 'dailyFuel',
  580. width: '120px'
  581. },
  582. constructionStartDate: {
  583. label: '施工开始日期',
  584. prop: 'constructionStartDate',
  585. width: '120px',
  586. fn: (row: IotRyDailyReportVO) => dateFormatter(null, null, row.constructionStartDate)
  587. },
  588. constructionEndDate: {
  589. label: '施工结束日期',
  590. prop: 'constructionEndDate',
  591. width: '120px',
  592. fn: (row: IotRyDailyReportVO) => dateFormatter(null, null, row.constructionEndDate)
  593. },
  594. lateralLength: {
  595. label: '水平段长度(m)',
  596. prop: 'lateralLength',
  597. width: '120px'
  598. },
  599. wellInclination: {
  600. label: '井斜(°)',
  601. prop: 'wellInclination',
  602. width: '120px'
  603. },
  604. azimuth: {
  605. label: '方位(°)',
  606. prop: 'azimuth',
  607. width: '120px'
  608. },
  609. designWellStruct: {
  610. label: '设计井身结构',
  611. prop: 'designWellStruct',
  612. width: '120px'
  613. },
  614. productionStatus: {
  615. label: '生产动态',
  616. prop: 'productionStatus',
  617. width: '120px'
  618. },
  619. drillingWorkingTime: {
  620. label: '进尺工作时间(H)',
  621. prop: 'drillingWorkingTime',
  622. width: '120px'
  623. },
  624. otherProductionTime: {
  625. label: '其它生产时间(H)',
  626. prop: 'otherProductionTime',
  627. width: '120px'
  628. },
  629. accidentTime: {
  630. label: '事故(H)',
  631. prop: 'accidentTime',
  632. width: '120px'
  633. },
  634. repairTime: {
  635. label: '修理(H)',
  636. prop: 'repairTime',
  637. width: '120px'
  638. },
  639. selfStopTime: {
  640. label: '修理(H)',
  641. prop: 'selfStopTime',
  642. width: '120px'
  643. },
  644. complexityTime: {
  645. label: '复杂(H)',
  646. prop: 'selfStopTime',
  647. width: '120px'
  648. },
  649. relocationTime: {
  650. label: '搬迁(H)',
  651. prop: 'relocationTime',
  652. width: '120px'
  653. },
  654. rectificationTime: {
  655. label: '整改(H)',
  656. prop: 'rectificationTime',
  657. width: '120px'
  658. },
  659. waitingStopTime: {
  660. label: '等停(H)',
  661. prop: 'waitingStopTime',
  662. width: '120px'
  663. },
  664. winterBreakTime: {
  665. label: '冬休(H)',
  666. prop: 'winterBreakTime',
  667. width: '120px'
  668. }
  669. })
  670. // 计算文本宽度
  671. const getTextWidth = (text: string, fontSize = 12) => {
  672. const span = document.createElement('span')
  673. span.style.visibility = 'hidden'
  674. span.style.position = 'absolute'
  675. span.style.whiteSpace = 'nowrap'
  676. span.style.fontSize = `${fontSize}px`
  677. span.style.fontFamily = 'PingFang SC'
  678. span.innerText = text
  679. document.body.appendChild(span)
  680. const width = span.offsetWidth
  681. document.body.removeChild(span)
  682. return width
  683. }
  684. const calculateColumnWidths = useDebounceFn(() => {
  685. if (!tableContainerRef.value?.$el) return
  686. Object.values(columnWidths.value).forEach(({ fn, prop, label, width }) => {
  687. width =
  688. Math.min(
  689. ...[
  690. Math.max(
  691. ...[
  692. getTextWidth(label),
  693. ...list.value.map((v) => {
  694. return getTextWidth(fn ? fn(v) : v[prop])
  695. })
  696. ]
  697. ) + (label === '施工状态' ? 30 : 20),
  698. 200
  699. ]
  700. ) + 'px'
  701. columnWidths.value[prop].width = width
  702. })
  703. }, 1000)
  704. // 检查10个时间字段之和是否为24H
  705. const checkTimeSumEquals24 = (row: any) => {
  706. // 获取三个字段的值,转换为数字,如果为空则视为0
  707. const drillingWorkingTime = parseFloat(row.drillingWorkingTime) || 0
  708. const otherProductionTime = parseFloat(row.otherProductionTime) || 0
  709. const accidentTime = parseFloat(row.accidentTime) || 0
  710. const repairTime = parseFloat(row.repairTime) || 0
  711. const selfStopTime = parseFloat(row.selfStopTime) || 0
  712. const complexityTime = parseFloat(row.complexityTime) || 0
  713. const relocationTime = parseFloat(row.relocationTime) || 0
  714. const rectificationTime = parseFloat(row.rectificationTime) || 0
  715. const waitingStopTime = parseFloat(row.waitingStopTime) || 0
  716. const winterBreakTime = parseFloat(row.winterBreakTime) || 0
  717. // 计算总和
  718. const sum =
  719. drillingWorkingTime +
  720. otherProductionTime +
  721. accidentTime +
  722. repairTime +
  723. selfStopTime +
  724. complexityTime +
  725. relocationTime +
  726. rectificationTime +
  727. waitingStopTime +
  728. winterBreakTime
  729. // 返回是否等于24(允许一定的浮点数误差)
  730. return Math.abs(sum - 24) < 0.01 // 使用0.01作为误差范围
  731. }
  732. // 单元格样式函数
  733. const cellStyle = ({
  734. row,
  735. column,
  736. rowIndex,
  737. columnIndex
  738. }: {
  739. row: any
  740. column: any
  741. rowIndex: number
  742. columnIndex: number
  743. }) => {
  744. // 处理当日油耗预警
  745. if (column.property === 'dailyFuel') {
  746. if (shouldShowFuelWarning(row)) {
  747. return {
  748. color: 'red',
  749. fontWeight: 'bold',
  750. backgroundColor: '#fff5f5' // 可选:添加背景色突出显示
  751. }
  752. }
  753. }
  754. // 处理三个时间字段:当日注气时间、当日注水时间、非生产时间
  755. const timeFields = [
  756. 'drillingWorkingTime',
  757. 'otherProductionTime',
  758. 'accidentTime',
  759. 'repairTime',
  760. 'selfStopTime',
  761. 'complexityTime',
  762. 'relocationTime',
  763. 'rectificationTime',
  764. 'waitingStopTime',
  765. 'winterBreakTime'
  766. ]
  767. if (timeFields.includes(column.property)) {
  768. // 检查10个时间字段之和是否不等于24
  769. if (!checkTimeSumEquals24(row)) {
  770. return {
  771. color: 'orange',
  772. fontWeight: 'bold'
  773. }
  774. }
  775. }
  776. // 默认返回空对象,不应用特殊样式
  777. return {}
  778. }
  779. // 可伸缩列配置
  780. /** 查询列表 */
  781. const getList = async () => {
  782. loading.value = true
  783. try {
  784. const data = await IotRyDailyReportApi.getIotRyDailyReportPage(queryParams)
  785. list.value = data.list
  786. total.value = data.total
  787. // 获取数据后计算列宽
  788. nextTick(() => {
  789. calculateColumnWidths()
  790. })
  791. } finally {
  792. loading.value = false
  793. }
  794. }
  795. // 在 cellStyle 函数附近添加油耗预警判断函数
  796. const shouldShowFuelWarning = (row: any): boolean => {
  797. const dailyFuel = parseFloat(row.dailyFuel)
  798. return !isNaN(dailyFuel) && dailyFuel > 15
  799. }
  800. // 计算列宽度
  801. /** 搜索按钮操作 */
  802. const handleQuery = () => {
  803. queryParams.pageNo = 1
  804. getList()
  805. }
  806. /** 重置按钮操作 */
  807. const resetQuery = () => {
  808. queryFormRef.value.resetFields()
  809. handleQuery()
  810. }
  811. /** 添加/修改操作 */
  812. const formRef = ref()
  813. const openForm = (type: string, id?: number, row?: any) => {
  814. // 保存当前行数据
  815. if (row) {
  816. selectedRowData.value = {
  817. deptName: row.deptName,
  818. contractName: row.contractName,
  819. taskName: row.taskName,
  820. designWellDepth: row.designWellDepth,
  821. designWellStruct: row.designWellStruct,
  822. totalConstructionWells: row.totalConstructionWells,
  823. completedWells: row.completedWells
  824. }
  825. } else {
  826. selectedRowData.value = null
  827. }
  828. formRef.value.open(type, id)
  829. }
  830. /** 删除按钮操作 */
  831. const handleDelete = async (id: number) => {
  832. try {
  833. // 删除的二次确认
  834. await message.delConfirm()
  835. // 发起删除
  836. await IotRyDailyReportApi.deleteIotRyDailyReport(id)
  837. message.success(t('common.delSuccess'))
  838. // 刷新列表
  839. await getList()
  840. } catch {}
  841. }
  842. // 响应式变量存储选中的部门
  843. const selectedDept = ref<{ id: number; name: string }>()
  844. /** 处理部门被点击 */
  845. const handleDeptNodeClick = async (row) => {
  846. // 记录选中的部门信息
  847. selectedDept.value = { id: row.id, name: row.name }
  848. queryParams.deptId = row.id
  849. await getList()
  850. }
  851. /** 导出按钮操作 */
  852. const handleExport = async () => {
  853. try {
  854. // 导出的二次确认
  855. await message.exportConfirm()
  856. // 发起导出
  857. exportLoading.value = true
  858. const data = await IotRyDailyReportApi.exportIotRyDailyReport(queryParams)
  859. download.excel(data, '瑞鹰日报.xls')
  860. } catch {
  861. } finally {
  862. exportLoading.value = false
  863. }
  864. }
  865. // 声明 ResizeObserver 实例
  866. let resizeObserver: ResizeObserver | null = null
  867. const route = useRoute()
  868. /** 初始化 **/
  869. onMounted(() => {
  870. if (Object.keys(route.query).length > 0) {
  871. queryParams = {
  872. ...queryParams,
  873. ...route.query,
  874. deptId: Number(route.query.deptId) as any
  875. }
  876. handleQuery()
  877. } else getList()
  878. // 创建 ResizeObserver 监听表格容器尺寸变化
  879. if (tableContainerRef.value?.$el) {
  880. resizeObserver = new ResizeObserver(() => {
  881. // 使用防抖避免频繁触发
  882. clearTimeout((window as any).resizeTimer)
  883. ;(window as any).resizeTimer = setTimeout(() => {
  884. calculateColumnWidths()
  885. }, 100)
  886. })
  887. resizeObserver.observe(tableContainerRef.value.$el)
  888. }
  889. })
  890. onUnmounted(() => {
  891. // 清除 ResizeObserver
  892. if (resizeObserver && tableContainerRef.value?.$el) {
  893. resizeObserver.unobserve(tableContainerRef.value.$el)
  894. resizeObserver = null
  895. }
  896. // 清除定时器
  897. if ((window as any).resizeTimer) {
  898. clearTimeout((window as any).resizeTimer)
  899. }
  900. })
  901. // 监听列表数据变化重新计算列宽
  902. watch(
  903. list,
  904. () => {
  905. nextTick(calculateColumnWidths)
  906. },
  907. { deep: true }
  908. )
  909. </script>
  910. <style scoped>
  911. /* 表格容器样式,确保水平滚动 */
  912. .table-container {
  913. width: 100%;
  914. overflow-x: auto;
  915. }
  916. /* 确保表格单元格内容不换行 */
  917. /* :deep(.el-table .cell) {
  918. white-space: nowrap;
  919. } */
  920. /* 确保表格列标题不换行 */
  921. /* :deep(.el-table th > .cell) {
  922. white-space: nowrap;
  923. } */
  924. /* 调整表格最小宽度,确保内容完全显示 */
  925. :deep(.el-table) {
  926. min-width: 100%;
  927. }
  928. /* 强制显示所有内容,防止省略号 */
  929. /* :deep(.el-table td.el-table__cell),
  930. :deep(.el-table th.el-table__cell) {
  931. overflow: visible !important;
  932. } */
  933. /* :deep(.el-table .cell) {
  934. overflow: visible !important;
  935. text-overflow: clip !important;
  936. } */
  937. /* 设计井身结构文本样式 - 多行显示并添加省略号 */
  938. .design-well-struct-text {
  939. display: -webkit-box;
  940. max-height: 3em; /* 两行文本的高度 */
  941. overflow: hidden;
  942. line-height: 1.5;
  943. text-overflow: ellipsis;
  944. -webkit-box-orient: vertical;
  945. -webkit-line-clamp: 2;
  946. }
  947. /* 确保设计井身结构列不参与自动调整 */
  948. :deep(.el-table__header-wrapper .el-table__cell.fixed-width),
  949. :deep(.el-table__body-wrapper .el-table__cell.fixed-width) {
  950. flex-shrink: 0;
  951. flex-grow: 0;
  952. }
  953. /* 颜色说明区域样式 */
  954. .color-legend {
  955. display: flex;
  956. padding: 12px 16px;
  957. background-color: #f8f9fa;
  958. border-left: 4px solid #e6f7ff;
  959. border-radius: 4px;
  960. flex-direction: column;
  961. gap: 8px;
  962. }
  963. .legend-item {
  964. display: flex;
  965. align-items: center;
  966. gap: 8px;
  967. font-size: 14px;
  968. }
  969. .color-indicator {
  970. display: inline-block;
  971. width: 12px;
  972. height: 12px;
  973. border-radius: 50%;
  974. }
  975. .color-indicator.red {
  976. background-color: red;
  977. }
  978. .color-indicator.orange {
  979. background-color: orange;
  980. }
  981. </style>
  982. <style>
  983. /* 设计井身结构 tooltip 样式 - 保留换行符 */
  984. .design-well-struct-tooltip {
  985. max-width: 500px;
  986. line-height: 1.5;
  987. white-space: pre-line;
  988. }
  989. .color-indicator.red {
  990. background-color: red;
  991. }
  992. /* 当日油耗预警样式 */
  993. .fuel-warning {
  994. color: red !important;
  995. font-weight: bold;
  996. animation: pulse 1.5s infinite;
  997. }
  998. /* 确保表格中的预警样式不被覆盖 */
  999. :deep(.el-table .cell .fuel-warning) {
  1000. color: red !important;
  1001. font-weight: bold !important;
  1002. }
  1003. </style>