You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

481 lines
21 KiB

  1. <template>
  2. <div class="mod-config">
  3. <!-- 查询区site 来自登录工厂禁止手改 - rqrq -->
  4. <el-form ref="queryForm" :inline="true" label-position="top" style="margin-top: 1px; margin-left: 0px;">
  5. <el-form-item label="工厂编码">
  6. <el-input v-model="queryData.site" style="width: 100px" disabled></el-input>
  7. </el-form-item>
  8. <el-form-item label="托盘号">
  9. <el-input v-model="queryData.searchPalletId" style="width: 140px" clearable placeholder="请输入托盘号" @keyup.enter.native="getDataList()"></el-input>
  10. </el-form-item>
  11. <el-form-item label="运输任务号">
  12. <el-input v-model="queryData.searchTransportTaskNo" style="width: 160px" clearable placeholder="请输入运输任务号" @keyup.enter.native="getDataList()"></el-input>
  13. </el-form-item>
  14. <el-form-item label="状态">
  15. <el-select v-model="queryData.searchStatus" placeholder="请选择" style="width: 120px" clearable>
  16. <el-option label="全部" value=""></el-option>
  17. <el-option label="移库中" value="移库中"></el-option>
  18. <el-option label="待发料" value="待发料"></el-option>
  19. <el-option label="处理中" value="处理中"></el-option>
  20. <el-option label="已完成" value="已完成"></el-option>
  21. </el-select>
  22. </el-form-item>
  23. <el-form-item label="失败码">
  24. <el-select v-model="queryData.searchErrorCode" placeholder="请选择" style="width: 130px" clearable>
  25. <el-option label="全部" value=""></el-option>
  26. <el-option label="无失败码" value="NONE"></el-option>
  27. <el-option label="移库失败" value="移库失败"></el-option>
  28. <el-option label="发料失败" value="发料失败"></el-option>
  29. <!-- 待核实独立筛选避免现场把结果不确定的标签直接补发 - rqrq -->
  30. <el-option label="发料待核实" value="发料待核实"></el-option>
  31. </el-select>
  32. </el-form-item>
  33. <el-form-item label="创建时间从">
  34. <el-date-picker v-model="queryData.searchStartDate" type="date" value-format="yyyy-MM-dd" style="width: 140px" clearable></el-date-picker>
  35. </el-form-item>
  36. <el-form-item label="创建时间至">
  37. <el-date-picker v-model="queryData.searchEndDate" type="date" value-format="yyyy-MM-dd" style="width: 140px" clearable></el-date-picker>
  38. </el-form-item>
  39. <el-form-item label=" ">
  40. <el-button type="primary" :loading="dataListLoading" :disabled="dataListLoading" @click="getDataList()">查询</el-button>
  41. <el-button :disabled="dataListLoading" @click="resetQuery()">重置</el-button>
  42. </el-form-item>
  43. </el-form>
  44. <el-table
  45. ref="mainTable"
  46. :data="dataList"
  47. :height="height"
  48. border
  49. highlight-current-row
  50. v-loading="dataListLoading"
  51. :row-class-name="tableRowClassName"
  52. style="width: 100%;"
  53. @row-click="handleRowClick">
  54. <el-table-column prop="id" label="任务ID" min-width="80" header-align="center" align="center"></el-table-column>
  55. <el-table-column prop="palletId" label="托盘号" min-width="120" header-align="center" align="center"></el-table-column>
  56. <el-table-column prop="transportTaskNo" label="运输任务号" min-width="140" header-align="center" align="center"></el-table-column>
  57. <el-table-column prop="status" label="状态" min-width="90" header-align="center" align="center">
  58. <template slot-scope="scope">
  59. <el-tag :type="getStatusTagType(scope.row.status, scope.row.errorCode)" size="small">{{ scope.row.status || '-' }}</el-tag>
  60. </template>
  61. </el-table-column>
  62. <el-table-column prop="errorCode" label="失败码" min-width="100" header-align="center" align="center">
  63. <template slot-scope="scope">
  64. <span :style="scope.row.errorCode ? 'color:#F56C6C' : ''">{{ scope.row.errorCode || '-' }}</span>
  65. </template>
  66. </el-table-column>
  67. <el-table-column prop="labelCount" label="标签数" min-width="80" header-align="center" align="center">
  68. <template slot-scope="scope">{{ formatCount(scope.row.labelCount) }}</template>
  69. </el-table-column>
  70. <el-table-column label="成功/失败" min-width="100" header-align="center" align="center">
  71. <template slot-scope="scope">{{ formatCount(scope.row.successCount) }} / {{ formatCount(scope.row.failCount) }}</template>
  72. </el-table-column>
  73. <el-table-column prop="unbindCount" label="已解绑" min-width="80" header-align="center" align="center">
  74. <template slot-scope="scope">{{ formatCount(scope.row.unbindCount) }}</template>
  75. </el-table-column>
  76. <!-- 待核实数量来自后端 U 状态聚合单位张与普通失败分开展示 - rqrq -->
  77. <el-table-column prop="unknownCount" label="待核实" min-width="80" header-align="center" align="center">
  78. <template slot-scope="scope">{{ formatCount(scope.row.unknownCount) }}</template>
  79. </el-table-column>
  80. <el-table-column prop="errorMsg" label="错误说明" min-width="180" header-align="center" align="left" show-overflow-tooltip></el-table-column>
  81. <el-table-column prop="createdTime" label="创建时间" min-width="160" header-align="center" align="center">
  82. <template slot-scope="scope">{{ formatDateTime(scope.row.createdTime) }}</template>
  83. </el-table-column>
  84. <el-table-column prop="processedTime" label="完结时间" min-width="160" header-align="center" align="center">
  85. <template slot-scope="scope">{{ formatDateTime(scope.row.processedTime) }}</template>
  86. </el-table-column>
  87. </el-table>
  88. <el-pagination
  89. ref="pagination"
  90. @size-change="sizeChangeHandle"
  91. @current-change="currentChangeHandle"
  92. :current-page="pageIndex"
  93. :page-sizes="[20, 50, 100, 1000]"
  94. :page-size="pageSize"
  95. :total="totalPage"
  96. layout="total, sizes, prev, pager, next, jumper">
  97. </el-pagination>
  98. <!-- 主表与详情页签平分可用高度未选任务也保留固定页签区域长错误仅在表格提示中展示 - rqrq -->
  99. <div ref="detailPanel" class="detail-panel" :style="{ height: height + 'px' }">
  100. <el-tabs ref="detailTabs" v-model="activeTab" @tab-click="updateTableHeights">
  101. <el-tab-pane label="标签明细" name="label">
  102. <el-table ref="labelTable" :data="labelList" border v-loading="labelListLoading" :height="detailHeight" :empty-text="currentTask.id ? '暂无标签明细' : '请选择一条任务'" style="width: 100%;">
  103. <el-table-column prop="serialNo" label="标签号" min-width="140" header-align="center" align="center"></el-table-column>
  104. <el-table-column prop="partNo" label="物料号" min-width="120" header-align="center" align="center"></el-table-column>
  105. <el-table-column prop="notifyNo" label="申请单号" min-width="140" header-align="center" align="center"></el-table-column>
  106. <!-- 工单三字段取定时建单已保存的标签快照空来源保持空白避免实时关联改变历史任务展示 - rqrq -->
  107. <el-table-column prop="orderNo" label="order_no" min-width="140" header-align="center" align="center"></el-table-column>
  108. <el-table-column prop="releaseNo" label="release_no" min-width="110" header-align="center" align="center"></el-table-column>
  109. <el-table-column prop="sequenceNo" label="sequence_no" min-width="110" header-align="center" align="center"></el-table-column>
  110. <!-- 移库结果在全部队列结束进入下一阶段时保存等待时显示-不根据主任务失败码把所有标签判成失败 - rqrq -->
  111. <el-table-column prop="moveFlag" label="移库" min-width="80" header-align="center" align="center">
  112. <template slot-scope="scope">
  113. <el-tag :type="getIssueFlagTag(scope.row.moveFlag)" size="small">{{ getMoveResultLabel(scope.row.moveFlag) }}</el-tag>
  114. </template>
  115. </el-table-column>
  116. <el-table-column prop="issueFlag" label="发料" min-width="120" header-align="center" align="center">
  117. <template slot-scope="scope">
  118. <!-- U仍保留后台待核实保护页面归为处理中并明确提示禁止现场误当未发料再次发送 - rqrq -->
  119. <el-tooltip :disabled="scope.row.issueFlag !== 'U'" content="发料结果待核实,禁止自动重发" placement="top">
  120. <el-tag :type="getIssueFlagTag(scope.row.issueFlag)" size="small">{{ getIssueFlagLabel(scope.row.issueFlag) }}</el-tag>
  121. </el-tooltip>
  122. </template>
  123. </el-table-column>
  124. <el-table-column prop="unbindFlag" label="解绑" min-width="80" header-align="center" align="center">
  125. <!-- 解绑只展示是/与移库发料结果独立不再显示重复的留盘列 - rqrq -->
  126. <template slot-scope="scope">{{ scope.row.unbindFlag === 'Y' ? '是' : '否' }}</template>
  127. </el-table-column>
  128. <!-- <el-table-column prop="errorMsg" label="失败原因" min-width="180" header-align="center" align="left" show-overflow-tooltip></el-table-column>-->
  129. <el-table-column prop="updatedTime" label="更新时间" min-width="160" header-align="center" align="center">
  130. <template slot-scope="scope">{{ formatDateTime(scope.row.updatedTime) }}</template>
  131. </el-table-column>
  132. </el-table>
  133. </el-tab-pane>
  134. <el-tab-pane label="移库队列" name="move">
  135. <!-- 无关联记录只表示本任务没有队列关联不据此断言 IFS 已完成 - rqrq -->
  136. <el-table ref="moveTable" :data="moveList" border v-loading="moveListLoading" :height="detailHeight" :empty-text="currentTask.id ? '暂无关联移库队列' : '请选择一条任务'" style="width: 100%;">
  137. <!-- 五列均取关联haian_ifs_pallet_move_queue长标签串/JSON/说明悬浮查看移库时间只取队列updated_time - rqrq -->
  138. <el-table-column prop="serialNoStr" label="标签串" min-width="220" header-align="center" align="left" show-overflow-tooltip></el-table-column>
  139. <el-table-column prop="resultFlag" label="结果" min-width="80" header-align="center" align="center">
  140. <template slot-scope="scope">{{ getMoveResultLabel(scope.row.resultFlag) }}</template>
  141. </el-table-column>
  142. <!-- <el-table-column prop="moveGroupJson" label="移库JSON" min-width="300" header-align="center" align="left" show-overflow-tooltip></el-table-column>-->
  143. <el-table-column prop="resultMsg" label="结果说明" min-width="220" header-align="center" align="left" show-overflow-tooltip></el-table-column>
  144. <el-table-column prop="updatedTime" label="移库时间" min-width="160" header-align="center" align="center">
  145. <template slot-scope="scope">{{ formatDateTime(scope.row.updatedTime) }}</template>
  146. </el-table-column>
  147. </el-table>
  148. </el-tab-pane>
  149. </el-tabs>
  150. </div>
  151. </div>
  152. </template>
  153. <script>
  154. import {
  155. getAutoIssueTaskPage,
  156. getAutoIssueTaskLabelList,
  157. getAutoIssueMoveRefList
  158. } from '@/api/haianWarehouse/autoIssueTask.js'
  159. export default {
  160. name: 'autoIssueTask54',
  161. data () {
  162. return {
  163. queryData: {
  164. site: this.$store.state.user.site,
  165. searchPalletId: '',
  166. searchTransportTaskNo: '',
  167. searchStatus: '',
  168. searchErrorCode: '',
  169. searchStartDate: '',
  170. searchEndDate: '',
  171. page: 1,
  172. limit: 20
  173. },
  174. dataList: [],
  175. pageIndex: 1,
  176. pageSize: 20,
  177. totalPage: 0,
  178. dataListLoading: false,
  179. height: 280,
  180. detailHeight: 220,
  181. currentTask: {},
  182. activeTab: 'label',
  183. labelList: [],
  184. labelListLoading: false,
  185. moveList: [],
  186. moveListLoading: false
  187. }
  188. },
  189. mounted () {
  190. // 跟随窗口与查询区换行重算高度;观察查询区避免表格自身高度变化触发循环 - rqrq
  191. window.addEventListener('resize', this.updateTableHeights)
  192. if (window.ResizeObserver) {
  193. this.queryResizeObserver = new window.ResizeObserver(this.updateTableHeights)
  194. this.queryResizeObserver.observe(this.$refs.queryForm.$el)
  195. }
  196. this.updateTableHeights()
  197. },
  198. activated () {
  199. // keep-alive 页面重新显示时恢复真实尺寸,再按当前工厂查询 - rqrq
  200. this.updateTableHeights()
  201. this.queryData.site = this.$store.state.user.site
  202. this.getDataList()
  203. },
  204. beforeDestroy () {
  205. // 释放窗口与尺寸观察监听,避免关闭页签后继续访问已销毁表格 - rqrq
  206. window.removeEventListener('resize', this.updateTableHeights)
  207. if (this.queryResizeObserver) {
  208. this.queryResizeObserver.disconnect()
  209. }
  210. },
  211. methods: {
  212. // 扣除查询区、分页、边距后,主表与下方页签各占一半;详情表扣除页签头,数据在表内滚动 - rqrq
  213. updateTableHeights () {
  214. this.$nextTick(() => {
  215. if (this._isDestroyed || !this.$el.offsetWidth || !this.$refs.mainTable) {
  216. return
  217. }
  218. const pagination = this.$refs.pagination.$el
  219. const paginationStyle = window.getComputedStyle(pagination)
  220. const panelStyle = window.getComputedStyle(this.$refs.detailPanel)
  221. const tabHeader = this.$refs.detailTabs.$el.querySelector('.el-tabs__header')
  222. const headerStyle = window.getComputedStyle(tabHeader)
  223. const number = value => parseFloat(value) || 0
  224. const paginationHeight = pagination.offsetHeight + number(paginationStyle.marginTop) + number(paginationStyle.marginBottom)
  225. const panelSpacing = number(panelStyle.marginTop) + number(panelStyle.marginBottom)
  226. const availableHeight = window.innerHeight - this.$refs.mainTable.$el.getBoundingClientRect().top - paginationHeight - panelSpacing - 20
  227. this.height = Math.max(140, Math.floor(availableHeight / 2))
  228. const panelPadding = number(panelStyle.paddingTop) + number(panelStyle.paddingBottom) + number(panelStyle.borderTopWidth) + number(panelStyle.borderBottomWidth)
  229. const headerHeight = tabHeader.offsetHeight + number(headerStyle.marginTop) + number(headerStyle.marginBottom)
  230. this.detailHeight = Math.max(60, this.height - panelPadding - headerHeight)
  231. // 切换页签后重排当前表格,防止隐藏页签首次显示时列宽或滚动条错位 - rqrq
  232. this.$nextTick(() => {
  233. if (this._isDestroyed) return
  234. this.$refs.mainTable.doLayout()
  235. const detailTable = this.activeTab === 'move' ? this.$refs.moveTable : this.$refs.labelTable
  236. if (detailTable) detailTable.doLayout()
  237. })
  238. })
  239. },
  240. // 查询主表:先写 site 再请求,失败清空列表避免展示过期数据 - rqrq
  241. getDataList () {
  242. if (this.dataListLoading) {
  243. return
  244. }
  245. if (!this.queryData.site) {
  246. this.$alert('缺少site,无法查询', '提示')
  247. return
  248. }
  249. this.dataListLoading = true
  250. this.queryData.page = this.pageIndex
  251. this.queryData.limit = this.pageSize
  252. this.queryData.site = this.$store.state.user.site
  253. getAutoIssueTaskPage(this.queryData).then(({ data }) => {
  254. if (data && data.code === 0) {
  255. this.dataList = (data.page && data.page.list) || []
  256. this.totalPage = (data.page && data.page.totalCount) || 0
  257. } else {
  258. this.dataList = []
  259. this.totalPage = 0
  260. this.$alert((data && data.msg) || '查询失败', '提示')
  261. }
  262. this.clearDetail()
  263. }).catch(() => {
  264. this.dataList = []
  265. this.totalPage = 0
  266. this.clearDetail()
  267. this.$message.error('查询异常')
  268. }).finally(() => {
  269. this.dataListLoading = false
  270. })
  271. },
  272. // 重置筛选后从第一页重查 - rqrq
  273. resetQuery () {
  274. if (this.dataListLoading) {
  275. return
  276. }
  277. this.queryData = {
  278. site: this.$store.state.user.site,
  279. searchPalletId: '',
  280. searchTransportTaskNo: '',
  281. searchStatus: '',
  282. searchErrorCode: '',
  283. searchStartDate: '',
  284. searchEndDate: '',
  285. page: 1,
  286. limit: this.pageSize
  287. }
  288. this.pageIndex = 1
  289. this.getDataList()
  290. },
  291. sizeChangeHandle (val) {
  292. this.pageSize = val
  293. this.pageIndex = 1
  294. this.getDataList()
  295. },
  296. currentChangeHandle (val) {
  297. this.pageIndex = val
  298. this.getDataList()
  299. },
  300. // 点主表行加载标签与移库关联,只刷明细 loading - rqrq
  301. handleRowClick (row) {
  302. if (!row || !row.id) {
  303. return
  304. }
  305. this.currentTask = Object.assign({}, row)
  306. this.activeTab = 'label'
  307. this.loadLabelList()
  308. this.loadMoveList()
  309. },
  310. loadLabelList () {
  311. const taskId = this.currentTask.id
  312. this.labelListLoading = true
  313. getAutoIssueTaskLabelList({
  314. site: this.$store.state.user.site,
  315. searchIssueTaskId: taskId
  316. }).then(({ data }) => {
  317. if (this.currentTask.id !== taskId) {
  318. return
  319. }
  320. if (data && data.code === 0) {
  321. this.labelList = data.rows || []
  322. } else {
  323. this.labelList = []
  324. this.$alert((data && data.msg) || '查询标签明细失败', '提示')
  325. }
  326. }).catch(() => {
  327. if (this.currentTask.id !== taskId) {
  328. return
  329. }
  330. this.labelList = []
  331. this.$message.error('查询标签明细异常')
  332. }).finally(() => {
  333. if (this.currentTask.id === taskId) {
  334. this.labelListLoading = false
  335. }
  336. })
  337. },
  338. loadMoveList () {
  339. const taskId = this.currentTask.id
  340. this.moveListLoading = true
  341. getAutoIssueMoveRefList({
  342. site: this.$store.state.user.site,
  343. searchIssueTaskId: taskId
  344. }).then(({ data }) => {
  345. if (this.currentTask.id !== taskId) {
  346. return
  347. }
  348. if (data && data.code === 0) {
  349. this.moveList = data.rows || []
  350. } else {
  351. this.moveList = []
  352. this.$alert((data && data.msg) || '查询移库关联失败', '提示')
  353. }
  354. }).catch(() => {
  355. if (this.currentTask.id !== taskId) {
  356. return
  357. }
  358. this.moveList = []
  359. this.$message.error('查询移库关联异常')
  360. }).finally(() => {
  361. if (this.currentTask.id === taskId) {
  362. this.moveListLoading = false
  363. }
  364. })
  365. },
  366. clearDetail () {
  367. // 清空选择后旧请求会被任务ID校验忽略,固定详情区的 loading 必须同步复位 - rqrq
  368. this.currentTask = {}
  369. this.labelList = []
  370. this.moveList = []
  371. this.labelListLoading = false
  372. this.moveListLoading = false
  373. },
  374. formatCount (value) {
  375. if (value === null || value === undefined || value === '') {
  376. return 0
  377. }
  378. return value
  379. },
  380. formatDateTime (value) {
  381. if (!value) {
  382. return ''
  383. }
  384. const date = new Date(value)
  385. if (isNaN(date.getTime())) {
  386. return value
  387. }
  388. const pad = num => (num < 10 ? '0' + num : '' + num)
  389. return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate()) +
  390. ' ' + pad(date.getHours()) + ':' + pad(date.getMinutes()) + ':' + pad(date.getSeconds())
  391. },
  392. getStatusTagType (status, errorCode) {
  393. if (errorCode) {
  394. return 'danger'
  395. }
  396. if (status === '已完成') {
  397. return 'success'
  398. }
  399. if (status === '待发料') {
  400. return 'warning'
  401. }
  402. if (status === '处理中') {
  403. return 'info'
  404. }
  405. return ''
  406. },
  407. tableRowClassName ({ row }) {
  408. if (row && row.errorCode) {
  409. return 'error-row'
  410. }
  411. return ''
  412. },
  413. // 发料展示统一四态;P请求已开始、U结果待核实均为处理中,U另有悬浮提示,后台防重语义保留 - rqrq
  414. getIssueFlagLabel (flag) {
  415. if (flag === 'P') {
  416. return '处理中'
  417. }
  418. if (flag === 'U') {
  419. return '处理中'
  420. }
  421. if (flag === 'S') {
  422. return '成功'
  423. }
  424. if (flag === 'F') {
  425. return '失败'
  426. }
  427. return '未发料'
  428. },
  429. // 不确定状态使用警示色,提示先核实 IFS,禁止据此自动补发 - rqrq
  430. getIssueFlagTag (flag) {
  431. if (flag === 'P' || flag === 'U') {
  432. return 'warning'
  433. }
  434. if (flag === 'S') {
  435. return 'success'
  436. }
  437. if (flag === 'F') {
  438. return 'danger'
  439. }
  440. return 'info'
  441. },
  442. // 留盘仅以解绑标记为准,S+N 表示成功后尚未解绑,仍必须显示留盘 - rqrq
  443. isRemainOnPallet (row) {
  444. if (!row) {
  445. return false
  446. }
  447. return row.unbindFlag !== 'Y'
  448. },
  449. getMoveResultLabel (flag) {
  450. if (flag === 'S') {
  451. return '成功'
  452. }
  453. if (flag === 'F') {
  454. return '失败'
  455. }
  456. return flag || '-'
  457. }
  458. }
  459. }
  460. </script>
  461. <style scoped>
  462. .mod-config {
  463. padding: 10px;
  464. }
  465. .detail-panel {
  466. margin-top: 12px;
  467. padding: 10px;
  468. border: 1px solid #ebeef5;
  469. background: #fff;
  470. box-sizing: border-box;
  471. }
  472. /deep/ .el-table .error-row {
  473. background: #fef0f0;
  474. }
  475. </style>