index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. <template>
  2. <zj-page-container>
  3. <zj-page-fill class="neibuview">
  4. <zj-form-container style="margin-bottom:40px">
  5. <!-- 完工明细 -->
  6. <zj-form-module v-if="!look" title="完工明细">
  7. <zj-table ref="tableEl" :isDrop="true" :columns="completionDetailColumns" :tableData="completionDetailData"
  8. :tableAttributes="{
  9. border: true
  10. }"></zj-table>
  11. <div class="fr">
  12. <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageNum"
  13. :page-sizes="[10, 20, 30, 50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper"
  14. :total="listTotal"></el-pagination>
  15. </div>
  16. </zj-form-module>
  17. <!-- 内外机条码信息 -->
  18. <zj-form-module v-if="look" title="内外机条码信息" class="header_right_btn">
  19. <div slot="header" class="btn">
  20. <el-button v-if="orderDetailFiles.length" type="primary" size="mini" @click="imgVisible = true"> 预览图片
  21. </el-button>
  22. </div>
  23. <zj-table ref="tableEl" :isDrop="true" :columns="barcodeColumns" :tableData="barcodeData" :tableAttributes="{
  24. border: true
  25. }"></zj-table>
  26. </zj-form-module>
  27. <!-- 图片采集信息 -->
  28. <zj-form-module v-if="look" title="图片采集信息">
  29. <div class="imgCJ">
  30. <div v-for="(v, i) in orderDetailFiles" :key="i">
  31. <el-image v-if="checkFileType(v.filePath) !== 'mp4'" style="width: 210px; height: 280px"
  32. :src="$imageUrl + v.filePath" :preview-src-list="[$imageUrl + v.filePath]">
  33. <div slot="error" style="height: 100%; display: flex; justify-content: center; align-items: center">
  34. <i>暂无图片</i>
  35. </div>
  36. </el-image>
  37. <video v-else width="210" height="280" controls>
  38. <source :src="$imageUrl + v.filePath" />
  39. </video>
  40. <div class="imgTitle">
  41. {{ v.fileName }}
  42. </div>
  43. </div>
  44. </div>
  45. </zj-form-module>
  46. <!-- 其他信息 -->
  47. <zj-form-module v-if="look" title="其他信息" label-width="120px" :formData="formData" :formItems="otherFormItems"
  48. :column="1">
  49. </zj-form-module>
  50. </zj-form-container>
  51. <div v-if="look" class="fixBtnStyle">
  52. <el-button size="mini" type="info" @click="look = false">关闭</el-button>
  53. <el-button v-if="isCancel && $restrict('discardCollectionData')" size="mini" @click="handlerCancelData"
  54. type="primary">作废采集数据</el-button>
  55. </div>
  56. <el-dialog title="图片预览" :visible.sync="imgVisible" :close-on-click-modal="false" :modal-append-to-body="false"
  57. width="50%" top="8vh" @close="imgVisible = false">
  58. <div>
  59. <div class="box">
  60. <div style="min-height: 200px;" class="flex" v-for="(v, i) in orderDetailFiles" :key="i">
  61. <el-image v-if="checkFileType(v.filePath) !== 'mp4'" style="width: 720px; height: auto"
  62. :src="$imageUrl + v.filePath" :preview-src-list="[$imageUrl + v.filePath]">
  63. <div slot="error"
  64. style="width: 720px;height: auto; display: flex; justify-content: center; align-items: center">
  65. <i>暂无图片</i>
  66. </div>
  67. </el-image>
  68. <video v-else width="720" height="960" controls>
  69. <source :src="$imageUrl + v.filePath" />
  70. </video>
  71. <div class="imgTitle" style=" flex: 0 0 200px; margin-right: 20px; color: #f00">
  72. {{ v.fileName }}
  73. <div style=" margin-top: 20px;">
  74. <span v-if="v.fileType == 1">内机条码: {{ v.code }}</span>
  75. <span v-if="v.fileType == 3">外机机条码: {{ v.code }}</span>
  76. </div>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. </el-dialog>
  82. </zj-page-fill>
  83. </zj-page-container>
  84. </template>
  85. <script>
  86. //完工明细--------------------------------------------
  87. // import otherMixin from '../createWorker/mixin/otherMixin'
  88. // import {
  89. // orderInstallOverList,
  90. // orderInstallOverDetail,
  91. // orderRepairOverDetail,
  92. // orderCancelInstallGatherDetail
  93. // } from '@/api/detailModule'
  94. export default {
  95. // mixins: [otherMixin],
  96. props: {},
  97. filters: {
  98. imgTitleChange(value) {
  99. let data = [
  100. {
  101. type: 1,
  102. title: '内机'
  103. },
  104. {
  105. type: 2,
  106. title: '上墙图片'
  107. },
  108. {
  109. type: 3,
  110. title: '外机'
  111. },
  112. {
  113. type: 4,
  114. title: '内机其他'
  115. },
  116. {
  117. type: 5,
  118. title: '外机其他'
  119. },
  120. {
  121. type: 6,
  122. title: '旧机内机整机图片'
  123. },
  124. {
  125. type: 7,
  126. title: '旧机外机整机图片'
  127. },
  128. {
  129. type: 8,
  130. title: '定位确认书'
  131. },
  132. {
  133. type: 9,
  134. title: '室外机固定图'
  135. },
  136. {
  137. type: 10,
  138. title: '冷凝水管软接图'
  139. },
  140. {
  141. type: 11,
  142. title: '外机电源接线图'
  143. },
  144. {
  145. type: 12,
  146. title: '外机出管处封堵图'
  147. },
  148. {
  149. type: 13,
  150. title: '室内机安装图'
  151. },
  152. {
  153. type: 14,
  154. title: '冷凝水管通气孔图'
  155. },
  156. {
  157. type: 15,
  158. title: '室内机走管图'
  159. },
  160. {
  161. type: 16,
  162. title: '抽真空保压图片'
  163. },
  164. {
  165. type: 17,
  166. title: '电子清单'
  167. },
  168. {
  169. type: 18,
  170. title: '安装完成图片'
  171. },
  172. {
  173. type: 19,
  174. title: '验收报告'
  175. },
  176. {
  177. type: 20,
  178. title: '故障位置图'
  179. }
  180. ]
  181. for (const key in data) {
  182. if (data[key].type == value) {
  183. return data[key].title
  184. }
  185. }
  186. }
  187. },
  188. data() {
  189. return {
  190. look: false,
  191. barcodeData: [],
  192. formData: {
  193. bracket: '',
  194. pipe: '',
  195. swithFlag: '',
  196. highAltitude: '',
  197. hole: ''
  198. },
  199. formRules: {},
  200. pageSize: 15,
  201. pageNum: 1,
  202. listTotal: 0,
  203. completionDetailData: [],
  204. orderDetailFiles: [],
  205. orderType: '',
  206. orderId: '',
  207. orderDetailId: '', //工单采集明细id
  208. isCancel: false,
  209. dispatchStatus: '',
  210. imgVisible: false,
  211. status: null
  212. }
  213. },
  214. computed: {
  215. completionDetailColumns() {
  216. return [
  217. {
  218. columnAttributes: {
  219. width: 130,
  220. fixed: 'left',
  221. align: 'center',
  222. label: '操作',
  223. prop: 'teamWorkerName'
  224. },
  225. render: (h, { row, column, $index }) => {
  226. return (
  227. <div style="">
  228. <el-button
  229. size="mini"
  230. type="text"
  231. onClick={async () => {
  232. this.look = true
  233. this.isCancel = row.status != 2 && this.dispatchStatus !== 'YBWG' ? true : false
  234. this.getListDetail(row.id, this.orderType)
  235. }}
  236. >
  237. 查看
  238. </el-button>
  239. {row.status == 1 ? (
  240. <el-button size="mini" type="text" onClick={async () => { }}>
  241. 结算单
  242. </el-button>
  243. ) : null}
  244. {row.status == 1 && this.$restrict('discardCollectionData') ? (
  245. <el-popconfirm
  246. style="margin-left:10px"
  247. onConfirm={async () => {
  248. this.orderDetailId = row.id
  249. this.handlerCancel()
  250. }}
  251. title="是否确定需要作废该项内容?"
  252. >
  253. <el-button slot="reference" size="mini" type="text">
  254. 作废
  255. </el-button>
  256. </el-popconfirm>
  257. ) : null}
  258. </div>
  259. )
  260. }
  261. },
  262. {
  263. columnAttributes: {
  264. label: '结算状态',
  265. prop: 'isSettle'
  266. },
  267. render: (h, { row, column, $index }) => {
  268. return <div style="padding-left:6px">{row.isSettle == 'NO' ? '否' : '是'}</div>
  269. }
  270. },
  271. {
  272. columnAttributes: {
  273. label: '转结标签',
  274. prop: ''
  275. }
  276. },
  277. {
  278. columnAttributes: {
  279. label: '产品信息',
  280. prop: 'productName',
  281. width: 130
  282. }
  283. },
  284. {
  285. columnAttributes: {
  286. label: '内机条码',
  287. prop: 'insideCode',
  288. width: 130
  289. }
  290. },
  291. {
  292. columnAttributes: {
  293. label: '外机条码',
  294. prop: 'outCode',
  295. width: 130
  296. }
  297. },
  298. {
  299. columnAttributes: {
  300. label: '操作内容',
  301. prop: 'type'
  302. },
  303. render: (h, { row, column, $index }) => {
  304. return (
  305. <div style="padding-left:6px">
  306. {row.type == 'ALL'
  307. ? '一体机'
  308. : row.type == 'INSIDE'
  309. ? '内机'
  310. : row.type == 'OUT'
  311. ? '外机'
  312. : row.type == 'INSIDE_OUT'
  313. ? '一内一外'
  314. : ''}
  315. </div>
  316. )
  317. }
  318. },
  319. {
  320. columnAttributes: {
  321. label: '采集人',
  322. prop: 'operatorName'
  323. }
  324. },
  325. {
  326. columnAttributes: {
  327. label: '大小工',
  328. prop: '',
  329. width: 180
  330. },
  331. render: (h, { row, column, $index }) => {
  332. return (
  333. <div style="padding-left:6px">
  334. {row.mainWorkerName}{row.assistWorkerName ? ',' : ''}{row.assistWorkerName}
  335. </div>
  336. )
  337. }
  338. },
  339. {
  340. columnAttributes: {
  341. label: '状态',
  342. prop: 'status'
  343. },
  344. render: (h, { row, column, $index }) => {
  345. return (
  346. <div style="padding-left:6px">
  347. {row.status == 0
  348. ? '未采集'
  349. : row.status == 1
  350. ? '已采集'
  351. : row.status == 2
  352. ? '作废'
  353. : row.status == 3
  354. ? '临时保存'
  355. : ''}
  356. </div>
  357. )
  358. }
  359. },
  360. {
  361. columnAttributes: {
  362. label: '采集时间',
  363. prop: 'firstTime'
  364. }
  365. },
  366. {
  367. columnAttributes: {
  368. label: '采集来源',
  369. prop: 'detailSource'
  370. },
  371. render: (h, { row, column, $index }) => {
  372. return (
  373. <div style="padding-left:6px">
  374. {row.detailSource == 0 ? '总部' : row.detailSource == 2 ? '家盛茂' : '广佛'}
  375. </div>
  376. )
  377. }
  378. },
  379. {
  380. columnAttributes: {
  381. label: '提交采集时地址',
  382. width: 130,
  383. prop: 'latLngAddress'
  384. }
  385. },
  386. {
  387. columnAttributes: {
  388. label: '最后采集图片时(总部结算-GPS定位地址)',
  389. width: 260,
  390. prop: 'gpsAddress'
  391. }
  392. }
  393. ]
  394. },
  395. barcodeColumns() {
  396. return [
  397. {
  398. columnAttributes: {
  399. label: '序号',
  400. prop: ''
  401. },
  402. render: (h, { row, column, index }) => {
  403. return <div style="padding-left:6px">{index + 1}</div>
  404. }
  405. },
  406. {
  407. columnAttributes: {
  408. label: '条码',
  409. prop: ''
  410. },
  411. render: (h, { row, column, $index }) => {
  412. return (
  413. <div style="padding-left:6px">
  414. {row.type == 1 ? '内机条码' : row.type == 2 ? '外机条码' : ''} {row.code}
  415. </div>
  416. )
  417. }
  418. },
  419. // {
  420. // columnAttributes: {
  421. // label: '外机条码',
  422. // prop: 'brandName'
  423. // }
  424. // },
  425. {
  426. columnAttributes: {
  427. label: '开机密码',
  428. prop: 'insidePassword'
  429. }
  430. },
  431. ...(() => {
  432. return [3, 4].includes(this.status) ? [{
  433. columnAttributes: {
  434. label: '图片',
  435. prop: ''
  436. },
  437. render: (h, { row, column, $index }) => {
  438. return (
  439. <div style="padding-left:6px">
  440. <el-image
  441. style="width: 210px; height: 280px"
  442. src={row.path ? this.$imageUrl + row.path : ''}
  443. preview-src-list={row.path ? [this.$imageUrl + row.path] : []}
  444. >
  445. <div slot="error" style="height: 100%; display: flex; justify-content: center; align-items: center">
  446. <i>暂无图片</i>
  447. </div>
  448. </el-image>
  449. </div>
  450. )
  451. }
  452. }] : []
  453. })()
  454. ]
  455. },
  456. otherFormItems() {
  457. return [
  458. {
  459. name: 'el-input',
  460. md: 6,
  461. options: [],
  462. attributes: { disabled: false },
  463. formItemAttributes: { label: '支架', prop: 'bracket' }
  464. },
  465. {
  466. name: 'el-input',
  467. md: 6,
  468. options: [],
  469. attributes: { disabled: false },
  470. formItemAttributes: { label: '加长管', prop: 'pipe' }
  471. },
  472. {
  473. name: 'el-input',
  474. md: 6,
  475. options: [],
  476. attributes: { disabled: false },
  477. formItemAttributes: { label: '空气开关', prop: 'swithFlag' }
  478. },
  479. {
  480. name: 'el-input',
  481. md: 6,
  482. options: [],
  483. attributes: { disabled: false },
  484. formItemAttributes: { label: '高空作业', prop: 'highAltitude' }
  485. },
  486. {
  487. name: 'el-input',
  488. md: 6,
  489. options: [],
  490. attributes: { disabled: false },
  491. formItemAttributes: { label: '一次性成型墙孔', prop: 'hole' }
  492. },
  493. {
  494. name: 'el-input',
  495. md: 24,
  496. options: [],
  497. attributes: { disabled: false, type: 'textarea' },
  498. formItemAttributes: { label: '备注', prop: 'remark' }
  499. }
  500. ]
  501. }
  502. },
  503. methods: {
  504. // 检查文件类型
  505. checkFileType(url) {
  506. return url.substring(url.lastIndexOf('.') + 1)
  507. },
  508. //作废采集数据
  509. handlerCancelData() {
  510. this.$confirm('此操作将作废已采集数据, 是否继续?', '提示', {
  511. confirmButtonText: '是',
  512. cancelButtonText: '否',
  513. type: 'warning',
  514. closeOnClickModal: false,
  515. closeOnPressEscape: false,
  516. showClose: false
  517. }).then(() => {
  518. this.handlerCancel()
  519. }).catch(() => {
  520. });
  521. },
  522. async handlerCancel() {
  523. let params = {
  524. orderBaseId: this.orderId,
  525. orderDetailId: this.orderDetailId
  526. }
  527. await orderCancelInstallGatherDetail(params)
  528. this.$message.success('作废采集成功')
  529. this.look = false
  530. this.isCancel = false
  531. this.getDetail(this.orderId, this.orderType)
  532. },
  533. handleSizeChange(val) {
  534. this.pageSize = val
  535. this.pageNum = 1
  536. this.getDetail(this.orderId, this.orderType)
  537. },
  538. handleCurrentChange(val) {
  539. this.pageNum = val
  540. this.getDetail(this.orderId, this.orderType)
  541. },
  542. //完工详情
  543. async getListDetail(id, orderType) {
  544. if (orderType == 'INSTALL' || orderType === 'RECOVERY') {
  545. this.orderDetailId = id //工单采集明细id
  546. let { data } = await orderInstallOverDetail({ id })
  547. const neiji = []
  548. const waiji = []
  549. const neijiqit = []
  550. const waijiqit = []
  551. const caiji = []
  552. const qit = []
  553. const tshjazqrs = []
  554. for (let index = 0; index < data.orderDetailFiles.length; index++) {
  555. const el = data.orderDetailFiles[index]
  556. if (el.fileType == 1) {
  557. el.code = data.orderInstallDetailCodes.find(k => k.type == 1)?.code
  558. neiji.push(el)
  559. }
  560. if (el.fileType == 3) {
  561. el.code = data.orderInstallDetailCodes.find(k => k.type == 2)?.code
  562. waiji.push(el)
  563. }
  564. if (el.fileType == 4) {
  565. neijiqit.push(el)
  566. }
  567. if (el.fileType == 5) {
  568. waijiqit.push(el)
  569. }
  570. if (![1, 3, 4, 5, 21, 44].includes(el.fileType)) {
  571. caiji.push(el)
  572. }
  573. if (el.fileType == 21) {
  574. qit.push(el)
  575. }
  576. if (el.fileType == 44) {
  577. tshjazqrs.push(el)
  578. }
  579. }
  580. this.orderDetailFiles = [...neiji, ...waiji, ...neijiqit, ...waijiqit, ...caiji, ...qit, ...tshjazqrs]
  581. data.orderInstallDetailCodes.forEach(v => {
  582. v.insidePassword = data.insidePassword
  583. })
  584. this.barcodeData = data.orderInstallDetailCodes
  585. this.formData = {
  586. bracket: data.bracket,
  587. pipe: data.pipe,
  588. swithFlag: data.swithFlag,
  589. highAltitude: data.highAltitude,
  590. hole: data.hole,
  591. remark: data.remark
  592. }
  593. }
  594. if (orderType == 'REPAIR') {
  595. let { data } = await orderRepairOverDetail({ id })
  596. }
  597. },
  598. //完工明细
  599. async getDetail(orderBaseId, type) {
  600. let params = {
  601. orderBaseId,
  602. pageSize: this.pageSize,
  603. pageNum: this.pageNum
  604. }
  605. if (type == 'INSTALL' || type === 'RECOVERY') {
  606. let { data } = await orderInstallOverList(params)
  607. this.completionDetailData = data.records
  608. this.listTotal = data.total
  609. }
  610. },
  611. init(id, params, status) {
  612. this.orderType = params.orderType
  613. this.dispatchStatus = params.dispatchStatus
  614. this.orderId = id
  615. this.status = status
  616. this.getDetail(this.orderId, this.orderType)
  617. }
  618. }
  619. }
  620. </script>
  621. <style lang="scss" scoped>
  622. .neibuview {
  623. box-sizing: border-box;
  624. padding-left: 16px;
  625. ::v-deep .zj-page-fill-scroll {
  626. box-sizing: border-box;
  627. padding-right: 16px;
  628. &>div:nth-child(1) {
  629. margin-top: 20px;
  630. }
  631. }
  632. }
  633. .fixBtnStyle {
  634. position: fixed;
  635. bottom: 0;
  636. z-index: 2000;
  637. padding: 10px 0 30px;
  638. width: calc(100vw - 120px);
  639. background-color: #fff
  640. }
  641. ::v-deep .header_right_btn {
  642. .el-card__header {
  643. div[class='zj-page-container zj-page-container-row'] {
  644. align-items: center;
  645. }
  646. }
  647. }
  648. .btn {
  649. float: right;
  650. }
  651. .flex {
  652. display: flex;
  653. flex-direction: row-reverse;
  654. align-items: center;
  655. justify-content: flex-end;
  656. margin-left: 40px;
  657. padding-bottom: 30px;
  658. }
  659. .box {
  660. height: calc(100vh - 84px);
  661. padding-bottom: 84px;
  662. overflow-y: auto
  663. }
  664. ::v-deep .el-dialog__wrapper {
  665. position: absolute;
  666. top: 0;
  667. left: 0;
  668. }
  669. ::v-deep .el-dialog {
  670. margin: 0 auto !important;
  671. width: 100% !important;
  672. height: 100% !important;
  673. overflow: hidden;
  674. }
  675. .imgCJ {
  676. display: flex;
  677. justify-content: flex-start;
  678. flex-wrap: wrap;
  679. >div {
  680. flex: 0 calc((100% - 210px)/6);
  681. margin-right: 23px;
  682. }
  683. .imgTitle {
  684. font-size: 14px;
  685. margin: 10px 0 20px;
  686. }
  687. }
  688. </style>