fill.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. <script lang="ts" setup>
  2. import { IotRhDailyReportApi } from '@/api/pms/iotrhdailyreport'
  3. import { rangeShortcuts } from '@/utils/formatTime'
  4. import { useDebounceFn } from '@vueuse/core'
  5. import dayjs from 'dayjs'
  6. import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
  7. import { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'
  8. import { FormInstance, FormRules } from 'element-plus'
  9. import Form from '@/components/Form/src/Form.vue'
  10. import { useUserStore } from '@/store/modules/user'
  11. interface List {
  12. createTime: number // 日期
  13. deptName: string // 施工队伍
  14. contractName: string // 项目
  15. taskName: string // 任务
  16. id: number
  17. deptId: number
  18. projectId: number
  19. taskId: number
  20. relocationDays: number // 搬迁安装天数
  21. designInjection: string // 设计注气量(万方)
  22. transitTime: number // 运行时效
  23. dailyGasInjection: number // 注气量(万方)
  24. dailyWaterInjection: number // 注水量(方)
  25. dailyInjectGasTime: number // 注气时间(H)
  26. dailyInjectWaterTime: number // 注水时间(H)
  27. dailyPowerUsage: number // 日耗电量(度)
  28. dailyOilUsage: number // 日耗油量(升)
  29. nonProductionTime: number // 非生产时间(小时)
  30. nptReason: string // 非生产时间原因
  31. constructionStartDate: number // 施工开始日期
  32. constructionEndDate: number // 施工结束日期
  33. productionStatus: string // 生产动态
  34. constructionStatus: string // 施工状态
  35. totalGasInjection: number // 注气量(万方)
  36. totalWaterInjection: number // 注水量(方)
  37. cumulativeCompletion: number // 完工井次
  38. capacity: number // 产能(万方)
  39. remark: string // 备注
  40. auditStatus: number // 审核状态
  41. status: number // 状态
  42. opinion: string // 审核意见
  43. }
  44. interface Column {
  45. prop?: keyof List
  46. label: string
  47. 'min-width'?: string
  48. isTag?: boolean
  49. fixed?: 'left' | 'right'
  50. formatter?: (row: List) => any
  51. children?: Column[]
  52. dictType?: string
  53. }
  54. const columns = ref<Column[]>([
  55. {
  56. label: '日期',
  57. prop: 'createTime',
  58. 'min-width': '120px',
  59. fixed: 'left',
  60. formatter: (row: List) => dayjs(row.createTime).format('YYYY-MM-DD')
  61. },
  62. {
  63. label: '施工队伍',
  64. prop: 'deptName',
  65. fixed: 'left',
  66. 'min-width': '120px'
  67. },
  68. {
  69. label: '任务',
  70. prop: 'taskName',
  71. fixed: 'left',
  72. 'min-width': '120px'
  73. },
  74. {
  75. label: '施工状态',
  76. prop: 'constructionStatus',
  77. fixed: 'left',
  78. 'min-width': '120px',
  79. isTag: true,
  80. dictType: DICT_TYPE.PMS_PROJECT_TASK_SCHEDULE
  81. },
  82. {
  83. label: '审批状态',
  84. prop: 'auditStatus',
  85. 'min-width': '120px',
  86. isTag: true,
  87. formatter: (row: List) => {
  88. switch (row.auditStatus) {
  89. case 0:
  90. return '待提交'
  91. case 10:
  92. return '待审批'
  93. case 20:
  94. return '审批通过'
  95. case 30:
  96. return '审批拒绝'
  97. default:
  98. return ''
  99. }
  100. }
  101. },
  102. {
  103. label: '搬迁安装天数',
  104. prop: 'relocationDays',
  105. 'min-width': '120px',
  106. formatter: (row: List) => (row.relocationDays < 0 ? '0' : String(row.relocationDays))
  107. },
  108. {
  109. label: '设计注气量(万方)',
  110. prop: 'designInjection',
  111. 'min-width': '120px',
  112. formatter: (row: List) => row.designInjection || '0'
  113. },
  114. {
  115. label: '运行时效',
  116. prop: 'transitTime',
  117. 'min-width': '120px',
  118. formatter: (row: List) => (row.transitTime * 100).toFixed(2) + '%'
  119. },
  120. {
  121. label: '当日',
  122. children: [
  123. {
  124. label: '注气量(万方)',
  125. prop: 'dailyGasInjection',
  126. 'min-width': '120px',
  127. formatter: (row: List) => (row.dailyGasInjection / 10000).toFixed(2)
  128. },
  129. {
  130. label: '注水量(方)',
  131. prop: 'dailyWaterInjection',
  132. 'min-width': '120px'
  133. },
  134. {
  135. label: '注气时间(H)',
  136. prop: 'dailyInjectGasTime',
  137. 'min-width': '120px'
  138. },
  139. {
  140. label: '注水时间(H)',
  141. prop: 'dailyInjectWaterTime',
  142. 'min-width': '120px'
  143. },
  144. {
  145. label: '用电量(kWh)',
  146. prop: 'dailyPowerUsage',
  147. 'min-width': '120px'
  148. },
  149. {
  150. label: '油耗(L)',
  151. prop: 'dailyOilUsage',
  152. 'min-width': '120px'
  153. }
  154. ]
  155. },
  156. {
  157. label: '非生产时间(H)',
  158. prop: 'nonProductionTime',
  159. 'min-width': '120px'
  160. },
  161. {
  162. label: '非生产时间原因',
  163. prop: 'nptReason',
  164. 'min-width': '120px',
  165. isTag: true,
  166. dictType: DICT_TYPE.PMS_PROJECT_NPT_REASON
  167. },
  168. // {
  169. // label: '施工开始日期',
  170. // prop: 'constructionStartDate',
  171. // 'min-width': '120px',
  172. // formatter: (row: List) => dayjs(row.constructionStartDate).format('YYYY-MM-DD HH:mm:ss')
  173. // },
  174. // {
  175. // label: '施工结束日期',
  176. // prop: 'constructionEndDate',
  177. // 'min-width': '120px',
  178. // formatter: (row: List) => dayjs(row.constructionEndDate).format('YYYY-MM-DD HH:mm:ss')
  179. // },
  180. {
  181. label: '生产动态',
  182. prop: 'productionStatus',
  183. 'min-width': '120px'
  184. },
  185. {
  186. label: '项目',
  187. prop: 'contractName',
  188. 'min-width': '120px'
  189. },
  190. {
  191. label: '累计',
  192. children: [
  193. {
  194. label: '注气量(万方)',
  195. prop: 'totalGasInjection',
  196. 'min-width': '120px',
  197. formatter: (row: List) => (row.totalGasInjection / 10000).toFixed(2)
  198. },
  199. {
  200. label: '注水量(方)',
  201. prop: 'totalWaterInjection',
  202. 'min-width': '120px'
  203. },
  204. {
  205. label: '完工井次',
  206. prop: 'cumulativeCompletion',
  207. 'min-width': '120px'
  208. }
  209. ]
  210. },
  211. {
  212. label: '产能(万方)',
  213. prop: 'capacity',
  214. 'min-width': '120px',
  215. formatter: (row: List) => (row.capacity / 10000).toFixed(2)
  216. }
  217. ])
  218. const getTextWidth = (text: string, fontSize = 12) => {
  219. const span = document.createElement('span')
  220. span.style.visibility = 'hidden'
  221. span.style.position = 'absolute'
  222. span.style.whiteSpace = 'nowrap'
  223. span.style.fontSize = `${fontSize}px`
  224. span.style.fontFamily = 'PingFang SC'
  225. span.innerText = text
  226. document.body.appendChild(span)
  227. const width = span.offsetWidth
  228. document.body.removeChild(span)
  229. return width
  230. }
  231. const calculateColumnWidths = (colums: Column[]) => {
  232. for (const col of colums) {
  233. let { formatter, prop, label, 'min-width': minWidth, isTag, children } = col
  234. if (children && children.length > 0) {
  235. calculateColumnWidths(children)
  236. continue
  237. }
  238. minWidth =
  239. Math.min(
  240. ...[
  241. Math.max(
  242. ...[
  243. getTextWidth(label),
  244. ...list.value.map((v) => {
  245. return getTextWidth(formatter ? formatter(v) : v[prop!])
  246. })
  247. ]
  248. ) + (isTag ? 40 : 20),
  249. 200
  250. ]
  251. ) + 'px'
  252. col['min-width'] = minWidth
  253. }
  254. }
  255. function checkTimeSumEquals24(row: List) {
  256. // 获取三个字段的值,转换为数字,如果为空则视为0
  257. const gasTime = row.dailyInjectGasTime || 0
  258. const waterTime = row.dailyInjectWaterTime || 0
  259. const nonProdTime = row.nonProductionTime || 0
  260. // 计算总和
  261. const sum = gasTime + waterTime + nonProdTime
  262. // 返回是否等于24(允许一定的浮点数误差)
  263. return Math.abs(sum - 24) < 0.01 // 使用0.01作为误差范围
  264. }
  265. function cellStyle(data: {
  266. row: List
  267. column: TableColumnCtx<List>
  268. rowIndex: number
  269. columnIndex: number
  270. }) {
  271. const { row, column } = data
  272. if (column.property === 'transitTime') {
  273. const originalValue = row.transitTime ?? 0
  274. if (originalValue > 1.2)
  275. return {
  276. color: 'red',
  277. fontWeight: 'bold'
  278. }
  279. }
  280. const timeFields = ['dailyInjectGasTime', 'dailyInjectWaterTime', 'nonProductionTime']
  281. if (timeFields.includes(column.property)) {
  282. if (!checkTimeSumEquals24(row)) {
  283. return {
  284. color: 'orange',
  285. fontWeight: 'bold'
  286. }
  287. }
  288. }
  289. // 默认返回空对象,不应用特殊样式
  290. return {}
  291. }
  292. const id = useUserStore().getUser.deptId ?? 157
  293. const deptId = id
  294. interface Query {
  295. pageNo: number
  296. pageSize: number
  297. deptId: number
  298. contractName?: string
  299. taskName?: string
  300. createTime: string[]
  301. }
  302. const query = ref<Query>({
  303. pageNo: 1,
  304. pageSize: 10,
  305. deptId: id,
  306. createTime: [
  307. ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
  308. ]
  309. })
  310. function handleSizeChange(val: number) {
  311. query.value.pageSize = val
  312. handleQuery()
  313. }
  314. function handleCurrentChange(val: number) {
  315. query.value.pageNo = val
  316. loadList()
  317. }
  318. const loading = ref(false)
  319. const list = ref<List[]>([])
  320. const total = ref(0)
  321. const loadList = useDebounceFn(async function () {
  322. loading.value = true
  323. try {
  324. const data = await IotRhDailyReportApi.getIotRhDailyReportPage(query.value)
  325. list.value = data.list
  326. total.value = data.total
  327. nextTick(() => {
  328. calculateColumnWidths(columns.value)
  329. })
  330. } finally {
  331. loading.value = false
  332. }
  333. }, 500)
  334. function handleQuery(setPage = true) {
  335. if (setPage) {
  336. query.value.pageNo = 1
  337. }
  338. loadList()
  339. }
  340. function resetQuery() {
  341. query.value = {
  342. pageNo: 1,
  343. pageSize: 10,
  344. deptId: 157,
  345. contractName: '',
  346. taskName: '',
  347. createTime: [
  348. ...rangeShortcuts[2].value().map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
  349. ]
  350. }
  351. handleQuery()
  352. }
  353. watch(
  354. [
  355. () => query.value.createTime,
  356. () => query.value.deptId,
  357. () => query.value.taskName,
  358. () => query.value.contractName
  359. ],
  360. () => {
  361. handleQuery()
  362. },
  363. { immediate: true }
  364. )
  365. const FORM_KEYS = [
  366. 'id',
  367. 'deptId',
  368. 'projectId',
  369. 'taskId',
  370. 'deptName',
  371. 'contractName',
  372. 'taskName',
  373. 'dailyGasInjection',
  374. 'dailyWaterInjection',
  375. 'dailyInjectGasTime',
  376. 'dailyInjectWaterTime',
  377. 'nonProductionTime',
  378. 'nptReason',
  379. 'productionStatus',
  380. 'remark',
  381. 'relocationDays',
  382. 'capacity',
  383. 'createTime',
  384. 'opinion'
  385. ] as const
  386. type FormKey = (typeof FORM_KEYS)[number]
  387. type Form = Partial<Pick<List, FormKey>>
  388. const dialogVisible = ref(false)
  389. const formRef = ref<FormInstance>()
  390. const formLoading = ref(false)
  391. const message = useMessage()
  392. const initFormData = (): Form => ({
  393. dailyGasInjection: 0,
  394. dailyWaterInjection: 0,
  395. dailyInjectGasTime: 0,
  396. dailyInjectWaterTime: 0,
  397. nonProductionTime: 0,
  398. relocationDays: 0,
  399. capacity: 0
  400. })
  401. const form = ref<Form>(initFormData())
  402. async function loadDetail(id: number) {
  403. try {
  404. const res = await IotRhDailyReportApi.getIotRhDailyReport(id)
  405. FORM_KEYS.forEach((key) => {
  406. form.value[key] = res[key] ?? form.value[key]
  407. })
  408. form.value.id = id
  409. if (res.status !== 0) {
  410. formType.value = 'readonly'
  411. }
  412. if (!form.value.capacity) {
  413. message.error('请维护增压机产能')
  414. }
  415. } finally {
  416. }
  417. }
  418. const formType = ref<'edit' | 'readonly'>('edit')
  419. function handleOpenForm(id: number, type: 'edit' | 'readonly') {
  420. form.value = initFormData()
  421. formRef.value?.resetFields()
  422. formType.value = type
  423. dialogVisible.value = true
  424. loadDetail(id).then(() => {
  425. formRef.value?.validate()
  426. })
  427. }
  428. const route = useRoute()
  429. onMounted(() => {
  430. if (Object.keys(route.query).length > 0) {
  431. handleOpenForm(Number(route.query.id), 'edit')
  432. }
  433. })
  434. const transitTime = computed(() => {
  435. const cap = form.value.capacity
  436. const gas = form.value.dailyGasInjection ?? 0
  437. if (!cap) return { original: 0, value: '0%' }
  438. const original = gas / cap
  439. return { original, value: (original * 100).toFixed(2) + '%' }
  440. })
  441. const sumTimes = () => {
  442. const { dailyInjectGasTime = 0, dailyInjectWaterTime = 0, nonProductionTime = 0 } = form.value
  443. return parseFloat((dailyInjectGasTime + dailyInjectWaterTime + nonProductionTime).toFixed(2))
  444. }
  445. const validateTotalTime = (_rule: any, _value: any, callback: any) => {
  446. const total = sumTimes()
  447. if (total !== 24) {
  448. callback(new Error(`当前合计 ${total} 小时,三项时间之和必须等于 24`))
  449. } else {
  450. callback()
  451. }
  452. }
  453. const validateNptReason = (_rule: any, value: any, callback: any) => {
  454. if ((form.value.nonProductionTime || 0) > 0 && !value) {
  455. callback(new Error('非生产时间大于 0 时,必须选择原因'))
  456. } else {
  457. callback()
  458. }
  459. }
  460. const timeRuleItem = [
  461. { required: true, message: '请输入时间', trigger: 'blur' },
  462. { validator: validateTotalTime, trigger: 'blur' }
  463. ]
  464. const rules = reactive<FormRules>({
  465. dailyGasInjection: [{ required: true, message: '请输入当日注气量', trigger: ['change', 'blur'] }],
  466. dailyWaterInjection: [
  467. { required: true, message: '请输入当日注水量', trigger: ['change', 'blur'] }
  468. ],
  469. productionStatus: [{ required: true, message: '请输入生产动态', trigger: ['change', 'blur'] }],
  470. // 复用规则
  471. dailyInjectGasTime: timeRuleItem,
  472. dailyInjectWaterTime: timeRuleItem,
  473. nonProductionTime: timeRuleItem,
  474. nptReason: [{ validator: validateNptReason, trigger: ['change', 'blur'] }]
  475. })
  476. watch(
  477. [
  478. () => form.value.dailyInjectGasTime,
  479. () => form.value.dailyInjectWaterTime,
  480. () => form.value.nonProductionTime
  481. ],
  482. () => {
  483. nextTick(() => {
  484. formRef.value?.validateField('nptReason')
  485. if (sumTimes() === 24) {
  486. formRef.value?.clearValidate([
  487. 'dailyInjectGasTime',
  488. 'dailyInjectWaterTime',
  489. 'nonProductionTime'
  490. ])
  491. }
  492. })
  493. }
  494. )
  495. const { t } = useI18n()
  496. const submitForm = async () => {
  497. if (!formRef.value) return
  498. try {
  499. await formRef.value.validate()
  500. formLoading.value = true
  501. const { createTime, ...other } = form.value
  502. const data = { ...other, fillOrderCreateTime: createTime } as any
  503. await IotRhDailyReportApi.createIotRhDailyReport(data)
  504. message.success(t('common.updateSuccess'))
  505. dialogVisible.value = false
  506. loadList()
  507. } catch (error) {
  508. console.warn('表单校验未通过或提交出错')
  509. } finally {
  510. formLoading.value = false
  511. }
  512. }
  513. </script>
  514. <template>
  515. <div class="grid grid-cols-[15%_1fr] gap-4 h-full">
  516. <div class="p-4 bg-white dark:bg-[#1d1e1f] shadow rounded-lg h-full">
  517. <DeptTreeSelect :top-id="157" :deptId="deptId" v-model="query.deptId" />
  518. </div>
  519. <div class="grid grid-rows-[62px_1fr] h-full gap-4">
  520. <el-form
  521. size="default"
  522. class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center justify-between"
  523. >
  524. <div class="flex items-center gap-8">
  525. <el-form-item label="项目">
  526. <el-input
  527. v-model="query.contractName"
  528. placeholder="请输入项目"
  529. clearable
  530. @keyup.enter="handleQuery()"
  531. class="!w-240px"
  532. />
  533. </el-form-item>
  534. <el-form-item label="任务">
  535. <el-input
  536. v-model="query.taskName"
  537. placeholder="请输入任务"
  538. clearable
  539. @keyup.enter="handleQuery()"
  540. class="!w-240px"
  541. />
  542. </el-form-item>
  543. <el-form-item label="创建时间">
  544. <el-date-picker
  545. v-model="query.createTime"
  546. value-format="YYYY-MM-DD HH:mm:ss"
  547. type="daterange"
  548. start-placeholder="开始日期"
  549. end-placeholder="结束日期"
  550. :shortcuts="rangeShortcuts"
  551. class="!w-220px"
  552. />
  553. </el-form-item>
  554. </div>
  555. <el-form-item>
  556. <el-button type="primary" @click="handleQuery()">
  557. <Icon icon="ep:search" class="mr-5px" /> 搜索
  558. </el-button>
  559. <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
  560. </el-form-item>
  561. </el-form>
  562. <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-4 flex flex-col">
  563. <div class="flex-1 relative">
  564. <el-auto-resizer class="absolute">
  565. <template #default="{ width, height }">
  566. <el-table
  567. :data="list"
  568. v-loading="loading"
  569. stripe
  570. class="absolute"
  571. :max-height="height"
  572. show-overflow-tooltip
  573. :width="width"
  574. :cell-style="cellStyle"
  575. border
  576. >
  577. <DailyTableColumn :columns="columns" />
  578. <el-table-column label="操作" width="120px" align="center" fixed="right">
  579. <template #default="{ row }">
  580. <el-button
  581. link
  582. type="success"
  583. @click="handleOpenForm(row.id, 'readonly')"
  584. v-hasPermi="['pms:iot-rh-daily-report:query']"
  585. >
  586. 查看
  587. </el-button>
  588. <el-button
  589. v-show="row.status === 0"
  590. link
  591. type="primary"
  592. @click="handleOpenForm(row.id, 'edit')"
  593. v-hasPermi="['pms:iot-rh-daily-report:create']"
  594. >
  595. 编辑
  596. </el-button>
  597. </template>
  598. </el-table-column>
  599. </el-table>
  600. </template>
  601. </el-auto-resizer>
  602. </div>
  603. <div class="h-10 mt-4 flex items-center justify-end">
  604. <el-pagination
  605. size="default"
  606. v-show="total > 0"
  607. v-model:current-page="query.pageNo"
  608. v-model:page-size="query.pageSize"
  609. :background="true"
  610. :page-sizes="[10, 20, 30, 50, 100]"
  611. :total="total"
  612. layout="total, sizes, prev, pager, next, jumper"
  613. @size-change="handleSizeChange"
  614. @current-change="handleCurrentChange"
  615. />
  616. </div>
  617. </div>
  618. </div>
  619. </div>
  620. <Dialog title="编辑" v-model="dialogVisible">
  621. <el-form
  622. ref="formRef"
  623. label-position="top"
  624. size="default"
  625. :rules="rules"
  626. :model="form"
  627. v-loading="formLoading"
  628. require-asterisk-position="right"
  629. :disabled="formType === 'readonly'"
  630. >
  631. <div class="flex flex-col gap-3 text-sm">
  632. <div
  633. class="rounded-md border border-blue-100 bg-blue-50/80 p-3 dark:border-blue-900/30 dark:bg-blue-900/10"
  634. >
  635. <div class="flex flex-col gap-2.5">
  636. <div class="flex items-center justify-between">
  637. <div class="text-gray-600 dark:text-gray-400">
  638. <span class="font-bold text-gray-800 dark:text-gray-200">运行时效:</span>
  639. 当日注气量 / 产能
  640. </div>
  641. <span
  642. class="inline-flex items-center rounded border border-red-200 bg-red-100 px-2 py-0.5 text-xs font-medium text-red-600 dark:bg-red-900/20 dark:border-red-800 dark:text-red-400"
  643. >
  644. >120% 红色预警
  645. </span>
  646. </div>
  647. <div class="flex items-center justify-between">
  648. <div class="text-gray-600 dark:text-gray-400">
  649. <span class="font-bold text-gray-800 dark:text-gray-200">时间平衡:</span>
  650. 注气 + 注水 + 非生产 = 24H
  651. </div>
  652. <span
  653. class="inline-flex items-center rounded border border-orange-200 bg-orange-100 px-2 py-0.5 text-xs font-medium text-orange-600 dark:bg-orange-900/20 dark:border-orange-800 dark:text-orange-400"
  654. >
  655. ≠24H 橙色预警
  656. </span>
  657. </div>
  658. </div>
  659. </div>
  660. <div
  661. v-if="form.opinion"
  662. class="flex gap-3 rounded-md border border-yellow-200 bg-yellow-50 p-3 dark:border-yellow-800 dark:bg-yellow-900/10"
  663. >
  664. <Icon
  665. icon="ep:warning-filled"
  666. class="mt-0.5 shrink-0 text-base text-yellow-600 dark:text-yellow-500"
  667. />
  668. <div class="flex flex-col">
  669. <h4 class="mb-1 font-bold text-yellow-800 dark:text-yellow-500"> 审核意见 </h4>
  670. <p class="leading-relaxed text-gray-600 dark:text-gray-400">
  671. {{ form.opinion }}
  672. </p>
  673. </div>
  674. </div>
  675. </div>
  676. <div class="grid grid-cols-2 gap-4 mt-5">
  677. <el-form-item label="施工队伍" prop="deptName">
  678. <el-input v-model="form.deptName" placeholder="" disabled />
  679. </el-form-item>
  680. <el-form-item label="项目" prop="contractName">
  681. <el-input v-model="form.contractName" placeholder="" disabled />
  682. </el-form-item>
  683. <el-form-item label="任务" prop="taskName">
  684. <el-input v-model="form.taskName" placeholder="" disabled />
  685. </el-form-item>
  686. <el-form-item label="搬迁安装天数(D)" prop="relocationDays">
  687. <el-input v-model="form.relocationDays" placeholder="" disabled />
  688. </el-form-item>
  689. <el-form-item label="运行时效" prop="transitTime">
  690. <el-input
  691. :model-value="transitTime.value"
  692. placeholder="运行时效"
  693. disabled
  694. :class="{ 'warning-input': transitTime.original > 1.2 }"
  695. id="transitTimeInput"
  696. />
  697. </el-form-item>
  698. <el-form-item label="当日注气量(方)" prop="dailyGasInjection">
  699. <el-input-number
  700. class="w-full!"
  701. :min="0"
  702. v-model="form.dailyGasInjection"
  703. placeholder="请输入当日注气量(方)"
  704. />
  705. </el-form-item>
  706. <el-form-item label="当日注水量(方)" prop="dailyWaterInjection">
  707. <el-input-number
  708. class="w-full!"
  709. :min="0"
  710. v-model="form.dailyWaterInjection"
  711. placeholder="请输入当日注水量(方)"
  712. />
  713. </el-form-item>
  714. <el-form-item label="当日注气时间(H)" prop="dailyInjectGasTime">
  715. <el-input-number
  716. class="w-full!"
  717. :min="0"
  718. v-model="form.dailyInjectGasTime"
  719. placeholder="请输入当日注气时间(H)"
  720. />
  721. </el-form-item>
  722. <el-form-item label="当日注水时间(H)" prop="dailyInjectWaterTime">
  723. <el-input-number
  724. class="w-full!"
  725. :min="0"
  726. v-model="form.dailyInjectWaterTime"
  727. placeholder="当日注水时间(H)"
  728. />
  729. </el-form-item>
  730. <el-form-item label="非生产时间(H)" prop="nonProductionTime">
  731. <el-input-number
  732. class="w-full!"
  733. :min="0"
  734. v-model="form.nonProductionTime"
  735. placeholder="非生产时间(H)"
  736. />
  737. </el-form-item>
  738. <el-form-item label="非生产时间原因" prop="nptReason">
  739. <el-select v-model="form.nptReason" placeholder="请选择" clearable>
  740. <el-option
  741. v-for="(dict, index) of getStrDictOptions(DICT_TYPE.PMS_PROJECT_NPT_REASON)"
  742. :key="index"
  743. :label="dict.label"
  744. :value="dict.value"
  745. />
  746. </el-select>
  747. </el-form-item>
  748. </div>
  749. <div class="grid grid-cols-1 gap-4 mt-5">
  750. <el-form-item label="生产动态" prop="productionStatus">
  751. <el-input
  752. v-model="form.productionStatus"
  753. placeholder="请输入生产动态"
  754. type="textarea"
  755. autosize
  756. :max-length="1000"
  757. />
  758. </el-form-item>
  759. <el-form-item label="备注" prop="remark">
  760. <el-input
  761. v-model="form.remark"
  762. placeholder="请输入备注"
  763. :max-length="1000"
  764. type="textarea"
  765. autosize
  766. />
  767. </el-form-item>
  768. </div>
  769. </el-form>
  770. <template #footer>
  771. <el-button size="default" @click="submitForm" type="primary" :disabled="formLoading">
  772. 确 定
  773. </el-button>
  774. <el-button size="default" @click="dialogVisible = false">取 消</el-button>
  775. </template>
  776. </Dialog>
  777. </template>
  778. <style scoped>
  779. :deep(.el-form-item) {
  780. margin-bottom: 0;
  781. }
  782. :deep(.el-table) {
  783. border-top-right-radius: 8px;
  784. border-top-left-radius: 8px;
  785. .el-table__cell {
  786. height: 40px;
  787. }
  788. .el-table__header-wrapper {
  789. .el-table__cell {
  790. background: var(--el-fill-color-light);
  791. }
  792. }
  793. }
  794. :deep(.warning-input) {
  795. .el-input__inner {
  796. color: red !important;
  797. -webkit-text-fill-color: red !important;
  798. }
  799. }
  800. :deep(.el-input-number) {
  801. width: 100%;
  802. }
  803. :deep(.el-input-number__decrease) {
  804. display: none !important;
  805. }
  806. :deep(.el-input-number__increase) {
  807. display: none !important;
  808. }
  809. </style>