index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. <template>
  2. <el-row :gutter="20">
  3. <DeptTree @node-click="handleDeptNodeClick" v-model:collapsed="isLeftContentCollapsed" />
  4. <el-col :xs="24" :span="isLeftContentCollapsed ? 24 : 20">
  5. <ContentWrap>
  6. <!-- 搜索工作栏 -->
  7. <el-form
  8. class="-mb-15px"
  9. :model="queryParams"
  10. ref="queryFormRef"
  11. :inline="true"
  12. label-width="68px"
  13. >
  14. <el-form-item
  15. :label="t('maintain.faultCode')"
  16. prop="failureCode"
  17. style="margin-left: 25px"
  18. >
  19. <el-input
  20. v-model="queryParams.failureCode"
  21. :placeholder="t('maintain.codeHolder')"
  22. clearable
  23. @keyup.enter="handleQuery"
  24. class="!w-200px"
  25. />
  26. </el-form-item>
  27. <el-form-item :label="t('maintain.faultName')" label-width="70px" prop="failureName">
  28. <el-input
  29. v-model="queryParams.failureName"
  30. :placeholder="t('maintain.nameHolder')"
  31. clearable
  32. @keyup.enter="handleQuery"
  33. class="!w-200px"
  34. />
  35. </el-form-item>
  36. <el-form-item label="执行时间" label-width="70px" prop="executeDate">
  37. <el-date-picker
  38. size="small"
  39. v-model="queryParams.executeDate"
  40. value-format="YYYY-MM-DD HH:mm:ss"
  41. type="daterange"
  42. start-placeholder="开始日期"
  43. end-placeholder="结束日期"
  44. class="!w-220px"
  45. :clearable="true"
  46. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  47. />
  48. </el-form-item>
  49. <el-form-item label="创建时间" label-width="70px" prop="createTime">
  50. <el-date-picker
  51. size="small"
  52. v-model="queryParams.createTime"
  53. value-format="YYYY-MM-DD HH:mm:ss"
  54. type="daterange"
  55. start-placeholder="开始日期"
  56. end-placeholder="结束日期"
  57. class="!w-220px"
  58. :clearable="true"
  59. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  60. />
  61. </el-form-item>
  62. <el-form-item :label="t('maintain.status')" label-width="40px" prop="status">
  63. <el-select
  64. v-model="queryParams.status"
  65. :placeholder="t('maintain.status')"
  66. clearable
  67. class="!w-200px"
  68. >
  69. <el-option
  70. v-for="dict in getStrDictOptions(DICT_TYPE.PMS_MAIN_STATUS)"
  71. :key="dict.value"
  72. :label="dict.label"
  73. :value="dict.value"
  74. />
  75. </el-select>
  76. </el-form-item>
  77. <el-form-item :label="t('maintain.shutDown')" v-show="ifShow" prop="ifStop">
  78. <el-select
  79. v-model="queryParams.ifStop"
  80. :placeholder="t('maintain.shutDown')"
  81. clearable
  82. class="!w-200px"
  83. >
  84. <el-option
  85. v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  86. :key="dict.value"
  87. :label="dict.label"
  88. :value="dict.value"
  89. />
  90. </el-select>
  91. </el-form-item>
  92. <el-form-item
  93. :label="t('maintain.failureTime')"
  94. v-show="ifShow"
  95. prop="failureTime"
  96. style="margin-left: 25px"
  97. >
  98. <el-date-picker
  99. v-model="queryParams.failureTime"
  100. value-format="YYYY-MM-DD HH:mm:ss"
  101. type="daterange"
  102. start-placeholder="开始日期"
  103. end-placeholder="结束日期"
  104. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  105. class="!w-220px"
  106. />
  107. </el-form-item>
  108. <el-form-item :label="t('maintain.solve')" v-show="ifShow" prop="ifDeal">
  109. <el-select
  110. v-model="queryParams.ifDeal"
  111. :placeholder="t('maintain.solve')"
  112. clearable
  113. class="!w-200px"
  114. >
  115. <el-option
  116. v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  117. :key="dict.value"
  118. :label="dict.label"
  119. :value="dict.value"
  120. />
  121. </el-select>
  122. </el-form-item>
  123. <el-form-item :label="t('maintain.assist')" v-show="ifShow" prop="needHelp">
  124. <el-select
  125. v-model="queryParams.needHelp"
  126. :placeholder="t('maintain.assist')"
  127. clearable
  128. class="!w-200px"
  129. >
  130. <el-option
  131. v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  132. :key="dict.value"
  133. :label="dict.label"
  134. :value="dict.value"
  135. />
  136. </el-select>
  137. </el-form-item>
  138. <el-form-item>
  139. <el-button v-if="!ifShow" @click="moreQuery(true)" type="warning"
  140. ><Icon icon="ep:search" class="mr-5px" /> {{ t('maintain.moreSearch') }}</el-button
  141. >
  142. <el-button v-if="ifShow" @click="moreQuery(false)" type="danger"
  143. ><Icon icon="ep:search" class="mr-5px" /> {{ t('maintain.closeSearch') }}</el-button
  144. >
  145. <el-button @click="handleQuery"
  146. ><Icon icon="ep:search" class="mr-5px" /> {{ t('maintain.search') }}</el-button
  147. >
  148. <el-button @click="resetQuery"
  149. ><Icon icon="ep:refresh" class="mr-5px" /> {{ t('maintain.reset') }}</el-button
  150. >
  151. <el-button
  152. type="primary"
  153. plain
  154. @click="openForm('create')"
  155. v-hasPermi="['rq:iot-maintain:create']"
  156. >
  157. <Icon icon="ep:plus" class="mr-5px" /> {{ t('maintain.added') }}
  158. </el-button>
  159. <el-button type="success" plain @click="handleExport" :loading="exportLoading">
  160. <Icon icon="ep:download" class="mr-5px" /> 导出
  161. </el-button>
  162. </el-form-item>
  163. </el-form>
  164. </ContentWrap>
  165. <!-- 列表 -->
  166. <ContentWrap>
  167. <el-table
  168. v-loading="loading"
  169. :data="list"
  170. :stripe="true"
  171. :show-overflow-tooltip="true"
  172. height="calc(85vh - 175px)"
  173. >
  174. <el-table-column :label="t('maintain.serial')" min-width="70" align="center">
  175. <template #default="scope">
  176. {{ scope.$index + 1 }}
  177. </template>
  178. </el-table-column>
  179. <el-table-column
  180. :label="t('iotDevice.code')"
  181. align="center"
  182. prop="deviceCode"
  183. width="180"
  184. />
  185. <el-table-column
  186. :label="t('maintain.deviceName')"
  187. align="center"
  188. prop="deviceName"
  189. width="280"
  190. />
  191. <el-table-column
  192. :label="t('maintain.status')"
  193. align="center"
  194. prop="status"
  195. min-width="95"
  196. >
  197. <template #default="scope">
  198. <dict-tag :type="DICT_TYPE.PMS_MAIN_STATUS" :value="scope.row.status" />
  199. </template>
  200. </el-table-column>
  201. <el-table-column
  202. :label="t('maintain.source')"
  203. align="center"
  204. prop="maintainType"
  205. min-width="135"
  206. />
  207. <el-table-column
  208. :label="t('iotMaintain.repairType')"
  209. align="center"
  210. prop="type"
  211. min-width="135"
  212. >
  213. <template #default="scope">
  214. <dict-tag :type="DICT_TYPE.PMS_MAIN_TYPE" :value="scope.row.type" />
  215. </template>
  216. </el-table-column>
  217. <el-table-column
  218. :label="t('maintain.shutDown')"
  219. align="center"
  220. prop="ifStop"
  221. min-width="135"
  222. >
  223. <template #default="scope">
  224. <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.ifStop" />
  225. </template>
  226. </el-table-column>
  227. <el-table-column
  228. label="执行时间"
  229. align="center"
  230. prop="executeDate"
  231. :formatter="dateFormatter"
  232. min-width="180px"
  233. />
  234. <el-table-column
  235. :label="t('iotMaintain.oaFlowNo')"
  236. align="center"
  237. prop="oaFlowNo"
  238. min-width="250"
  239. />
  240. <el-table-column
  241. :label="t('maintain.dept')"
  242. align="center"
  243. prop="deptName"
  244. min-width="135"
  245. />
  246. <el-table-column
  247. :label="t('inspect.createName')"
  248. align="center"
  249. prop="createName"
  250. min-width="130"
  251. />
  252. <el-table-column
  253. label="创建时间"
  254. align="center"
  255. prop="createTime"
  256. :formatter="dateFormatter"
  257. width="180px"
  258. />
  259. <el-table-column
  260. :label="t('maintain.operation')"
  261. align="center"
  262. min-width="170"
  263. fixed="right"
  264. >
  265. <template #default="scope">
  266. <el-button link type="primary" @click="detail(scope.row.id)">
  267. {{ t('maintain.view') }}
  268. </el-button>
  269. <el-button
  270. link
  271. v-if="
  272. scope.row.status === 'tx' &&
  273. (scope.row.auditStatus === 20 || scope.row.auditStatus === null)
  274. "
  275. type="danger"
  276. @click="
  277. openForm('update', scope.row.id, scope.row.maintainPerson, scope.row.company)
  278. "
  279. >
  280. {{ t('maintain.fill') }}
  281. </el-button>
  282. <el-button
  283. link
  284. v-if="scope.row.status === 'personnel' && userid === scope.row.maintainPerson"
  285. type="danger"
  286. @click="openDialog(scope.row.id)"
  287. >
  288. {{ t('maintain.maintainWay') }}
  289. </el-button>
  290. <el-button
  291. v-if="scope.row.status !== 'personnel'"
  292. link
  293. type="warning"
  294. @click="openRecord(scope.row.id)"
  295. >
  296. {{ t('maintain.record') }}
  297. </el-button>
  298. </template>
  299. </el-table-column>
  300. </el-table>
  301. <el-dialog
  302. v-model="dialogVisible"
  303. title="维修方式"
  304. :width="600"
  305. :before-close="handleClose"
  306. append-to-body
  307. :close-on-click-modal="false"
  308. >
  309. <el-form ref="methodFormRef" :model="form" :rules="rules" label-width="70px">
  310. <el-form-item label="维修方式" prop="maintainMethod">
  311. <el-select v-model="form.maintainMethod" placeholder="请选择维修方式">
  312. <el-option
  313. v-for="dict in getStrDictOptions(DICT_TYPE.PMS_MAINTAIN_METHOD)"
  314. :key="dict.label"
  315. :label="dict.label"
  316. :value="dict.value"
  317. />
  318. </el-select>
  319. </el-form-item>
  320. <el-form-item label="备注说明" prop="methodDescription">
  321. <el-input
  322. type="textarea"
  323. v-model="form.methodDescription"
  324. placeholder="请输入备注说明"
  325. :rows="4"
  326. resize="none"
  327. />
  328. </el-form-item>
  329. </el-form>
  330. <template #footer>
  331. <el-button @click="handleCancel">取消</el-button>
  332. <el-button type="primary" @click="handleConfirm">确定</el-button>
  333. </template>
  334. </el-dialog>
  335. <!-- 分页 -->
  336. <Pagination
  337. :total="total"
  338. v-model:page="queryParams.pageNo"
  339. v-model:limit="queryParams.pageSize"
  340. @pagination="getList"
  341. />
  342. </ContentWrap>
  343. </el-col>
  344. </el-row>
  345. <!-- 表单弹窗:添加/修改 -->
  346. </template>
  347. <script setup lang="ts">
  348. import { dateFormatter } from '@/utils/formatTime'
  349. import download from '@/utils/download'
  350. import { IotMaintainApi, IotMaintainVO } from '@/api/pms/maintain'
  351. import DeptTree from '@/views/system/user/DeptTree2.vue'
  352. import { DICT_TYPE, getBoolDictOptions, getStrDictOptions } from '@/utils/dict'
  353. import { useUserStore } from '@/store/modules/user'
  354. /** 维修工单 列表 */
  355. defineOptions({ name: 'IotMaintain' })
  356. const message = useMessage() // 消息弹窗
  357. const { t } = useI18n() // 国际化
  358. const { push } = useRouter() // 路由跳转
  359. const ifShow = ref(false)
  360. const loading = ref(true) // 列表的加载中
  361. const list = ref<IotMaintainVO[]>([]) // 列表的数据
  362. const total = ref(0) // 列表的总页数
  363. const dialogVisible = ref(false)
  364. let isLeftContentCollapsed = ref(false)
  365. const queryParams = reactive({
  366. pageNo: 1,
  367. pageSize: 10,
  368. failureCode: undefined,
  369. failureName: undefined,
  370. deviceId: undefined,
  371. status: undefined,
  372. ifStop: undefined,
  373. failureTime: [],
  374. failureInfluence: undefined,
  375. failureSystem: undefined,
  376. description: undefined,
  377. pic: undefined,
  378. solution: undefined,
  379. maintainStartTime: [],
  380. maintainEndTime: [],
  381. remark: undefined,
  382. createTime: [],
  383. deviceName: undefined,
  384. processInstanceId: undefined,
  385. auditStatus: undefined,
  386. deptId: undefined,
  387. executeDate: []
  388. })
  389. const queryFormRef = ref() // 搜索的表单
  390. const exportLoading = ref(false) // 导出的加载中
  391. const moreQuery = (show) => {
  392. ifShow.value = show
  393. }
  394. // 表单验证规则
  395. const rules = {
  396. methodDescription: [{ required: true, message: '请输入备注说明', trigger: 'blur' }],
  397. maintainMethod: [{ required: true, message: '请选择维修方式', trigger: 'blur' }]
  398. }
  399. // 确定按钮处理
  400. const handleConfirm = async () => {
  401. // 表单验证
  402. try {
  403. debugger
  404. await methodFormRef.value.validate()
  405. // 验证通过,调用接口
  406. await IotMaintainApi.maintainMethod(form)
  407. ElMessage.success('操作成功')
  408. dialogVisible.value = false
  409. resetForm()
  410. } catch (error) {
  411. return
  412. }
  413. }
  414. // 取消按钮处理
  415. const handleCancel = () => {
  416. dialogVisible.value = false
  417. resetForm()
  418. }
  419. const methodFormRef = ref(null)
  420. const form = reactive({
  421. id: undefined,
  422. maintainMethod: '',
  423. methodDescription: ''
  424. })
  425. // 关闭对话框前的回调
  426. const handleClose = () => {
  427. resetForm()
  428. }
  429. // 重置表单
  430. const resetForm = () => {
  431. methodFormRef.value?.resetFields()
  432. }
  433. // 打开对话框
  434. const openDialog = (id: number) => {
  435. dialogVisible.value = true
  436. form.id = id
  437. form.maintainMethod = ''
  438. form.methodDescription = ''
  439. }
  440. const openRecord = async (id?: number) => {
  441. await push({ name: 'MaintainRecord', params: { id } })
  442. }
  443. const openForm = async (type: string, id?: number, person: any, company) => {
  444. if (company === 'rh' && person === userid.value) {
  445. message.error('维修人员无法填写工单')
  446. return
  447. }
  448. //修改
  449. if (typeof id === 'number') {
  450. await push({ name: 'MaintainAdd', params: { id } })
  451. return
  452. }
  453. // 新增
  454. await push({ name: 'MaintainAdd', params: {} })
  455. }
  456. const detail = (id?: number) => {
  457. push({ name: 'MaintainDetail', params: { id } })
  458. }
  459. /** 查询列表 */
  460. const getList = async () => {
  461. loading.value = true
  462. try {
  463. const data = await IotMaintainApi.getIotMaintainPage(queryParams)
  464. list.value = data.list
  465. total.value = data.total
  466. } finally {
  467. loading.value = false
  468. }
  469. }
  470. /** 处理部门被点击 */
  471. const handleDeptNodeClick = async (row) => {
  472. queryParams.deptId = row.id
  473. await getList()
  474. }
  475. /** 搜索按钮操作 */
  476. const handleQuery = () => {
  477. queryParams.pageNo = 1
  478. getList()
  479. }
  480. /** 重置按钮操作 */
  481. const resetQuery = () => {
  482. queryFormRef.value.resetFields()
  483. handleQuery()
  484. }
  485. /** 删除按钮操作 */
  486. const handleDelete = async (id: number) => {
  487. try {
  488. // 删除的二次确认
  489. await message.delConfirm()
  490. // 发起删除
  491. await IotMaintainApi.deleteIotMaintain(id)
  492. message.success(t('common.delSuccess'))
  493. // 刷新列表
  494. await getList()
  495. } catch {}
  496. }
  497. /** 导出按钮操作 */
  498. const handleExport = async () => {
  499. try {
  500. // 导出的二次确认
  501. await message.exportConfirm()
  502. // 发起导出
  503. exportLoading.value = true
  504. const data = await IotMaintainApi.exportIotMaintain(queryParams)
  505. download.excel(data, '维修工单.xls')
  506. } catch {
  507. } finally {
  508. exportLoading.value = false
  509. }
  510. }
  511. const userid = ref()
  512. /** 初始化 **/
  513. onMounted(() => {
  514. getList()
  515. userid.value = useUserStore().getUser.id
  516. })
  517. </script>
  518. <style lang="scss" scoped>
  519. ::v-deep .el-table__header-wrapper {
  520. position: sticky !important;
  521. width: 100%;
  522. top: 0px;
  523. z-index: 2000;
  524. }
  525. </style>