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.

468 lines
12 KiB

3 months ago
  1. <template>
  2. <div>
  3. <div class="pda-container">
  4. <!-- 头部栏 - rqrq -->
  5. <div class="header-bar">
  6. <div class="header-left" @click="handleBack">
  7. <i class="el-icon-arrow-left"></i>
  8. <span>取消WCS组盘任务</span>
  9. </div>
  10. <div class="header-right" @click="$router.push({ path: '/' })">
  11. 首页
  12. </div>
  13. </div>
  14. <div class="table-body" style="max-height: 600px; overflow-y: auto;">
  15. <div class="main-content form-section">
  16. <!-- 栈板扫描 - rqrq -->
  17. <div class="input-group">
  18. <label class="input-label">栈板编码</label>
  19. <el-input
  20. v-model="palletCode"
  21. placeholder="请扫描栈板编码"
  22. class="form-input"
  23. clearable
  24. @keyup.enter.native="handlePalletScan"
  25. inputmode="none"
  26. autocomplete="off"
  27. autocorrect="off"
  28. spellcheck="false"
  29. ref="palletInput"
  30. />
  31. </div>
  32. <!-- 栈板信息显示扫描栈板后显示- rqrq -->
  33. <div v-if="palletScanned" class="pallet-info-section">
  34. <div class="info-row">
  35. <label class="info-label">是否被调用:</label>
  36. <span class="info-value" :style="{color: palletInfo.callingFlag === 'Y' ? '#F56C6C' : '#67C23A'}">
  37. {{ palletInfo.callingFlag === 'Y' ? '是' : '否' }}
  38. </span>
  39. </div>
  40. <!-- 是否发送组盘任务 - rqrq -->
  41. <div class="info-row">
  42. <label class="info-label">是否已组盘:</label>
  43. <span class="info-value" :style="{color: hasSentWcsTask ? '#F56C6C' : '#67C23A'}">
  44. {{ hasSentWcsTask ? '是' : '否' }}
  45. </span>
  46. </div>
  47. <!-- 浏览明细按钮 - rqrq -->
  48. <div class="button-row">
  49. <button class="action-btn primary" @click="showDetailModal" style="width: 100%;">
  50. 浏览明细 ({{ detailList.length }})
  51. </button>
  52. </div>
  53. <!-- 取消组盘按钮只有发送了组盘任务才显示- rqrq -->
  54. <div v-if="showCancelButton" class="button-row">
  55. <button
  56. class="action-btn primary"
  57. @click="handleCancelWcsPallet"
  58. :disabled="cancelLoading"
  59. style="width: 100%;">
  60. {{ cancelLoading ? '取消中...' : '取消组盘' }}
  61. </button>
  62. </div>
  63. <!-- 移出全部物料按钮只有未发送组盘任务且未被调用且有明细才显示- rqrq -->
  64. <div v-if="showRemoveAllButton" class="button-row">
  65. <button
  66. class="action-btn warning"
  67. @click="handleRemoveAllMaterials"
  68. :disabled="removeAllLoading"
  69. style="width: 100%;">
  70. {{ removeAllLoading ? '移出中...' : '移出全部物料' }}
  71. </button>
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. <!-- 浏览明细弹窗 - rqrq -->
  78. <el-dialog
  79. :title="'栈板明细 (共'+detailList.length+'条)'"
  80. :visible.sync="detailModalVisible"
  81. width="90%"
  82. :close-on-click-modal="false"
  83. :show-close="false"
  84. :modal="true"
  85. :modal-append-to-body="true"
  86. :append-to-body="true"
  87. >
  88. <div class="table-body" style="max-height: 400px; overflow-y: auto;">
  89. <div class="detail-table">
  90. <div class="table-header">
  91. <div class="col-position">位置</div>
  92. <div class="col-layer">层数</div>
  93. <div class="col-serial">标签号</div>
  94. </div>
  95. <div
  96. v-for="(detail, index) in detailList"
  97. :key="index"
  98. class="table-row"
  99. >
  100. <div class="col-position">{{ detail.position }}</div>
  101. <div class="col-layer">{{ detail.layer }}</div>
  102. <div class="col-serial">{{ detail.serialNo }}</div>
  103. </div>
  104. <!-- 暂无数据提示 -->
  105. <div v-if="detailList.length === 0" class="table-row empty-row">
  106. <div class="empty-hint">暂无栈板明细数据</div>
  107. </div>
  108. </div>
  109. </div>
  110. <div slot="footer" class="dialog-footer">
  111. <button class="action-btn secondary" @click="detailModalVisible=false">关闭</button>
  112. </div>
  113. </el-dialog>
  114. </div>
  115. </template>
  116. <script>
  117. import {
  118. getPalletDetails
  119. } from '../../../api/automatedWarehouse/palletPacking'
  120. import {
  121. checkPalletWcsStatus,
  122. cancelWcsPallet,
  123. removeAllPalletDetails
  124. } from '../../../api/automatedWarehouse/cancelWcsPallet'
  125. export default {
  126. data() {
  127. return {
  128. site: localStorage.getItem('site'),
  129. // 栈板信息 - rqrq
  130. palletCode: '',
  131. palletScanned: false,
  132. palletInfo: {
  133. callingFlag: '',
  134. canOperate: '',
  135. isEmpty: ''
  136. },
  137. // 按钮显示控制 - rqrq
  138. hasSentWcsTask: false,
  139. showCancelButton: false,
  140. showRemoveAllButton: false,
  141. // 栈板明细 - rqrq
  142. detailList: [],
  143. detailModalVisible: false,
  144. // 加载状态 - rqrq
  145. cancelLoading: false,
  146. removeAllLoading: false
  147. };
  148. },
  149. methods: {
  150. // 返回上一页 - rqrq
  151. handleBack() {
  152. this.$router.back();
  153. },
  154. // 扫描栈板 - rqrq
  155. handlePalletScan() {
  156. if (!this.palletCode.trim()) {
  157. this.$message.error('请输入栈板编码');
  158. return;
  159. }
  160. checkPalletWcsStatus({
  161. site: this.site,
  162. palletId: this.palletCode
  163. }).then(({ data }) => {
  164. if (data.code === 0) {
  165. // 后端返回正确的6位栈板码,赋值给输入框 - rqrq
  166. this.palletCode = data.row.palletId;
  167. // 保存栈板信息 - rqrq
  168. this.palletInfo = data.row;
  169. this.palletScanned = true;
  170. // 解析按钮显示逻辑 - rqrq
  171. // canOperate字段存储showCancelButton(是否显示取消组盘按钮)- rqrq
  172. this.showCancelButton = data.row.canOperate === 'Y';
  173. // isEmpty字段存储showRemoveAllButton(是否显示移出全部物料按钮)- rqrq
  174. this.showRemoveAllButton = data.row.isEmpty === 'Y';
  175. // 计算hasSentWcsTask(是否发送组盘任务)用于显示 - rqrq
  176. this.hasSentWcsTask = this.showCancelButton;
  177. // 加载栈板明细 - rqrq
  178. this.loadPalletDetails();
  179. } else {
  180. this.$alert(data.msg || '栈板不存在', '错误', {
  181. confirmButtonText: '确定',
  182. callback: () => {
  183. this.palletCode = '';
  184. this.$nextTick(() => {
  185. if (this.$refs.palletInput) {
  186. this.$refs.palletInput.focus();
  187. }
  188. });
  189. }
  190. });
  191. }
  192. }).catch(error => {
  193. console.error('查询栈板失败:', error);
  194. this.$alert(error.message || '查询栈板失败', '错误', {
  195. confirmButtonText: '确定',
  196. callback: () => {
  197. this.palletCode = '';
  198. this.$nextTick(() => {
  199. if (this.$refs.palletInput) {
  200. this.$refs.palletInput.focus();
  201. }
  202. });
  203. }
  204. });
  205. });
  206. },
  207. // 加载栈板明细 - rqrq
  208. loadPalletDetails() {
  209. getPalletDetails({
  210. site: this.site,
  211. palletId: this.palletCode,
  212. position: '',
  213. layer: ''
  214. }).then(({ data }) => {
  215. if (data.code === 0) {
  216. this.detailList = data.details || [];
  217. } else {
  218. this.detailList = [];
  219. }
  220. }).catch(error => {
  221. console.error('获取栈板明细失败:', error);
  222. this.detailList = [];
  223. });
  224. },
  225. // 显示明细弹窗 - rqrq
  226. showDetailModal() {
  227. this.detailModalVisible = true;
  228. },
  229. // 取消组盘 - rqrq
  230. handleCancelWcsPallet() {
  231. this.$confirm('确定要取消组盘吗?取消后需要重新组盘才能推送到WCS。', '确认操作', {
  232. confirmButtonText: '确定',
  233. cancelButtonText: '取消',
  234. type: 'warning'
  235. }).then(() => {
  236. this.cancelLoading = true;
  237. cancelWcsPallet({
  238. site: this.site,
  239. palletId: this.palletCode
  240. }).then(({ data }) => {
  241. if (data && data.code === 0) {
  242. this.$message.success('取消组盘成功');
  243. // 重新扫描刷新信息 - rqrq
  244. this.handlePalletScan();
  245. } else {
  246. this.$alert(data.msg || '取消组盘失败', '错误');
  247. }
  248. }).catch(error => {
  249. console.error('取消组盘失败:', error);
  250. this.$message.error(error.message || '取消组盘失败');
  251. }).finally(() => {
  252. this.cancelLoading = false;
  253. });
  254. }).catch(() => {
  255. // 用户取消操作
  256. });
  257. },
  258. // 移出全部物料 - rqrq
  259. handleRemoveAllMaterials() {
  260. this.$confirm('确定要移出栈板上的全部物料吗?此操作不可恢复!', '确认操作', {
  261. confirmButtonText: '确定',
  262. cancelButtonText: '取消',
  263. type: 'warning'
  264. }).then(() => {
  265. this.removeAllLoading = true;
  266. removeAllPalletDetails({
  267. site: this.site,
  268. palletId: this.palletCode
  269. }).then(({ data }) => {
  270. if (data && data.code === 0) {
  271. this.$message.success('移出全部物料成功');
  272. // 重新扫描刷新信息 - rqrq
  273. this.handlePalletScan();
  274. } else {
  275. this.$alert(data.msg || '移出全部物料失败', '错误');
  276. }
  277. }).catch(error => {
  278. console.error('移出全部物料失败:', error);
  279. this.$message.error(error.message || '移出全部物料失败');
  280. }).finally(() => {
  281. this.removeAllLoading = false;
  282. });
  283. }).catch(() => {
  284. // 用户取消操作
  285. });
  286. }
  287. },
  288. mounted() {
  289. this.$nextTick(() => {
  290. if (this.$refs.palletInput) {
  291. this.$refs.palletInput.focus();
  292. }
  293. });
  294. }
  295. };
  296. </script>
  297. <style scoped>
  298. /* 栈板信息区域 - rqrq */
  299. .pallet-info-section {
  300. margin-top: 16px;
  301. padding: 12px;
  302. background: #f5f7fa;
  303. border-radius: 6px;
  304. }
  305. .info-row {
  306. display: flex;
  307. align-items: center;
  308. padding: 8px 0;
  309. border-bottom: 1px solid #e4e7ed;
  310. }
  311. .info-row:last-child {
  312. border-bottom: none;
  313. }
  314. .info-label {
  315. font-weight: bold;
  316. color: #606266;
  317. width: 140px;
  318. flex-shrink: 0;
  319. }
  320. .info-value {
  321. color: #303133;
  322. font-size: 14px;
  323. font-weight: bold;
  324. }
  325. .button-row {
  326. margin-top: 12px;
  327. }
  328. /* 警告按钮 - rqrq */
  329. .action-btn.warning {
  330. background-color: #E6A23C;
  331. color: white;
  332. border: none;
  333. padding: 10px 20px;
  334. border-radius: 4px;
  335. cursor: pointer;
  336. font-size: 14px;
  337. }
  338. .action-btn.warning:hover {
  339. background-color: #d99525;
  340. }
  341. .action-btn.warning:disabled {
  342. background-color: #f5dab1;
  343. cursor: not-allowed;
  344. }
  345. /* 表格样式 - rqrq */
  346. .detail-table {
  347. background: white;
  348. border-radius: 6px;
  349. overflow: hidden;
  350. border: 1px solid #e0e0e0;
  351. }
  352. .table-header,
  353. .table-row {
  354. display: flex;
  355. align-items: center;
  356. padding: 8px;
  357. border-bottom: 1px solid #e0e0e0;
  358. }
  359. .table-header {
  360. background: #f5f5f5;
  361. font-weight: bold;
  362. font-size: 14px;
  363. }
  364. .table-row {
  365. font-size: 13px;
  366. }
  367. .table-row:last-child {
  368. border-bottom: none;
  369. }
  370. .col-position {
  371. flex: 1;
  372. text-align: center;
  373. }
  374. .col-layer {
  375. flex: 1;
  376. text-align: center;
  377. }
  378. .col-serial {
  379. flex: 4;
  380. text-align: center;
  381. word-break: break-all;
  382. }
  383. /* 空数据提示 - rqrq */
  384. .empty-hint {
  385. text-align: center;
  386. color: #999;
  387. padding: 20px;
  388. background: white;
  389. border-radius: 6px;
  390. }
  391. /* 空数据行样式 - rqrq */
  392. .empty-row {
  393. justify-content: center;
  394. align-items: center;
  395. padding: 20px;
  396. border-bottom: none;
  397. }
  398. .empty-row .empty-hint {
  399. text-align: center;
  400. color: #999;
  401. width: 100%;
  402. }
  403. .dialog-footer {
  404. display: flex;
  405. gap: 8px;
  406. text-align: center;
  407. }
  408. /* 修复模态框层级问题 - rqrq */
  409. ::v-deep .el-dialog__wrapper {
  410. z-index: 2000 !important;
  411. }
  412. ::v-deep .el-overlay {
  413. z-index: 2000 !important;
  414. }
  415. </style>