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.

404 lines
9.8 KiB

1 month ago
​
​
​
​
​
​
1 month ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
1 month ago
​
​
​
​
1 month ago
​
​
1 month ago
​
​
​
​
​
​
​
​
​
​
1 month ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
1 month ago
​
1 month ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
1 month ago
​
1 month ago
​
1 month ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <template>
  2. <div>
  3. <div class="pda-container">
  4. <div class="header-bar">
  5. <div class="header-left" :class="{ 'header-action-disabled': pageBusy }" @click="handleBack">
  6. <i class="el-icon-arrow-left"></i>
  7. <!-- WMS标签状态统一展示为预定,reserve字段和Y/N判断保持原有业务含义 - rqrq -->
  8. <span>取消预定</span>
  9. </div>
  10. <div class="header-right" :class="{ 'header-action-disabled': pageBusy }" @click="goHome">
  11. 首页
  12. </div>
  13. </div>
  14. <div class="table-body" style="max-height: 500px; overflow-y: auto;">
  15. <div class="main-content form-section">
  16. <div class="input-group">
  17. <label class="input-label">标签编码</label>
  18. <el-input
  19. v-model="labelCode"
  20. placeholder="请扫描标签编码"
  21. class="form-input"
  22. clearable
  23. inputmode="none"
  24. autocomplete="off"
  25. autocorrect="off"
  26. spellcheck="false"
  27. @keyup.enter.native="handleLabelScan"
  28. ref="labelInput"
  29. />
  30. </div>
  31. <div v-if="labelInfo" class="info-section">
  32. <div class="info-title">
  33. <i class="el-icon-document"></i>
  34. <span>标签信息</span>
  35. </div>
  36. <div class="info-row">
  37. <span class="info-label">标签编码:</span>
  38. <span class="info-value">{{ labelInfo.unitId || '-' }}</span>
  39. </div>
  40. <div class="info-row">
  41. <span class="info-label">工厂编码:</span>
  42. <span class="info-value">{{ labelInfo.site || '-' }}</span>
  43. </div>
  44. <div class="info-row">
  45. <span class="info-label">物料编码:</span>
  46. <span class="info-value">{{ labelInfo.partNo || '-' }}</span>
  47. </div>
  48. <div class="info-row">
  49. <span class="info-label">数量:</span>
  50. <span class="info-value">{{ labelInfo.qty || '0' }}</span>
  51. </div>
  52. <div class="info-row">
  53. <span class="info-label">批次号:</span>
  54. <span class="info-value">{{ labelInfo.batchNo || '-' }}</span>
  55. </div>
  56. <div class="info-row">
  57. <span class="info-label">仓库:</span>
  58. <span class="info-value">{{ labelInfo.warehouseId || '-' }}</span>
  59. </div>
  60. <div class="info-row">
  61. <span class="info-label">库位:</span>
  62. <span class="info-value">{{ labelInfo.locationId || '-' }}</span>
  63. </div>
  64. <div class="info-row">
  65. <span class="info-label">WDR:</span>
  66. <span class="info-value">{{ labelInfo.wdr || '-' }}</span>
  67. </div>
  68. <div class="info-row">
  69. <span class="info-label">是否被WMS预定:</span>
  70. <span class="info-value" :style="{ color: labelInfo.reserveFlag === 'Y' ? '#F56C6C' : '#67C23A' }">
  71. {{ labelInfo.reserveFlag === 'Y' ? '是' : '否' }}
  72. </span>
  73. </div>
  74. <div class="info-row" v-if="labelInfo.reserveOrderRef1">
  75. <span class="info-label">预定申请单号:</span>
  76. <span class="info-value">{{ labelInfo.reserveOrderRef1 || '-' }}</span>
  77. </div>
  78. <div class="info-row" v-if="labelInfo.reserveOrderRef3">
  79. <span class="info-label">预定订单号:</span>
  80. <span class="info-value">{{ labelInfo.reserveOrderRef3 || '-' }}</span>
  81. </div>
  82. </div>
  83. <div v-if="labelInfo" class="bottom-actions">
  84. <button class="action-btn secondary" @click="clearData" :disabled="pageBusy">清空</button>
  85. <button
  86. class="action-btn primary"
  87. @click="handleCancelReserve"
  88. :disabled="cancelReserveLoading || labelInfo.reserveFlag !== 'Y'"
  89. >
  90. {{ cancelReserveLoading ? '取消中...' : '取消预定' }}
  91. </button>
  92. </div>
  93. </div>
  94. </div>
  95. </div>
  96. </div>
  97. </template>
  98. <script>
  99. import { queryLabelInfo, cancelReserve } from '@/api/haianAutoWarehouse/wmsCancelReserve'
  100. export default {
  101. name: 'HaianWmsCancelReserve',
  102. data() {
  103. return {
  104. site: this.$store.state.user.site,
  105. labelCode: '',
  106. labelInfo: null,
  107. loading: false,
  108. cancelReserveLoading: false
  109. }
  110. },
  111. computed: {
  112. pageBusy() {
  113. return this.loading || this.cancelReserveLoading
  114. }
  115. },
  116. methods: {
  117. handleBack() {
  118. if (this.pageBusy) {
  119. return
  120. }
  121. this.resetPage(false)
  122. this.$router.back()
  123. },
  124. goHome() {
  125. if (this.pageBusy) {
  126. return
  127. }
  128. this.resetPage(false)
  129. this.$router.push({ path: '/' })
  130. },
  131. // 统一状态清理:避免页面缓存导致上一单标签信息残留 - rqrq
  132. resetPage(needFocus = true) {
  133. this.site = this.$store.state.user.site
  134. this.labelCode = ''
  135. this.labelInfo = null
  136. this.loading = false
  137. this.cancelReserveLoading = false
  138. if (needFocus) {
  139. this.focusLabelInput()
  140. }
  141. },
  142. handleLabelScan() {
  143. if (!this.labelCode || !this.labelCode.trim()) {
  144. this.$message.error('请扫描有效的标签编码')
  145. return
  146. }
  147. this.loading = true
  148. queryLabelInfo({
  149. site: this.site,
  150. serialNo: this.labelCode.trim()
  151. }).then(({ data }) => {
  152. if (data && data.code === 0) {
  153. this.labelInfo = data.data
  154. this.$message.success('查询成功')
  155. } else {
  156. this.$message.error((data && data.msg) || '标签不存在')
  157. this.labelCode = ''
  158. this.labelInfo = null
  159. this.focusLabelInput()
  160. }
  161. }).catch(() => {
  162. this.$message.error('查询异常')
  163. this.labelCode = ''
  164. this.labelInfo = null
  165. this.focusLabelInput()
  166. }).finally(() => {
  167. this.loading = false
  168. })
  169. },
  170. handleCancelReserve() {
  171. if (!this.labelInfo || this.labelInfo.reserveFlag !== 'Y') {
  172. this.$message.warning('当前标签未被预定')
  173. return
  174. }
  175. this.$confirm('确定要取消该标签的WMS预定吗?', '提示', {
  176. confirmButtonText: '确定',
  177. cancelButtonText: '取消',
  178. type: 'warning'
  179. }).then(() => {
  180. this.doCancelReserve()
  181. }).catch(() => {
  182. // 用户取消 - rqrq
  183. })
  184. },
  185. doCancelReserve() {
  186. this.cancelReserveLoading = true
  187. cancelReserve({
  188. site: this.site,
  189. serialNo: this.labelInfo.unitId
  190. }).then(({ data }) => {
  191. if (data && data.code === 0) {
  192. this.$message.success('取消预定成功')
  193. this.clearData()
  194. } else {
  195. this.$message.error((data && data.msg) || '取消预定失败')
  196. }
  197. }).catch(() => {
  198. this.$message.error('取消预定异常')
  199. }).finally(() => {
  200. this.cancelReserveLoading = false
  201. })
  202. },
  203. clearData() {
  204. this.labelCode = ''
  205. this.labelInfo = null
  206. this.focusLabelInput()
  207. },
  208. focusLabelInput() {
  209. this.$nextTick(() => {
  210. if (this.$refs.labelInput) {
  211. this.$refs.labelInput.focus()
  212. }
  213. })
  214. }
  215. },
  216. mounted() {
  217. this.resetPage(true)
  218. },
  219. activated() {
  220. this.resetPage(true)
  221. },
  222. beforeRouteLeave(to, from, next) {
  223. this.resetPage(false)
  224. next()
  225. }
  226. }
  227. </script>
  228. <style scoped>
  229. .header-action-disabled {
  230. opacity: 0.5;
  231. pointer-events: none;
  232. }
  233. .pda-container {
  234. width: 100vw;
  235. height: 120vh;
  236. display: flex;
  237. flex-direction: column;
  238. background: #f5f5f5;
  239. font-family: 'Arial', sans-serif;
  240. }
  241. .header-bar {
  242. display: flex;
  243. justify-content: space-between;
  244. align-items: center;
  245. padding: 8px 16px;
  246. background: #17B3A3;
  247. color: white;
  248. height: 40px;
  249. min-height: 40px;
  250. max-height: 40px;
  251. }
  252. .header-left {
  253. display: flex;
  254. align-items: center;
  255. cursor: pointer;
  256. }
  257. .header-left i {
  258. margin-right: 8px;
  259. font-size: 18px;
  260. }
  261. .header-left span {
  262. font-size: 16px;
  263. font-weight: 500;
  264. }
  265. .header-right {
  266. cursor: pointer;
  267. font-size: 14px;
  268. padding: 4px 8px;
  269. border-radius: 4px;
  270. }
  271. .table-body {
  272. flex: 1;
  273. overflow-y: auto;
  274. }
  275. .main-content {
  276. padding: 16px;
  277. }
  278. .input-label {
  279. display: block;
  280. margin-bottom: 8px;
  281. font-size: 14px;
  282. font-weight: 500;
  283. color: #333;
  284. }
  285. .form-input {
  286. width: 100%;
  287. height: 44px;
  288. }
  289. .info-section {
  290. background: white;
  291. border-radius: 8px;
  292. padding: 16px;
  293. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  294. }
  295. .info-title {
  296. display: flex;
  297. align-items: center;
  298. font-size: 16px;
  299. font-weight: bold;
  300. color: #17B3A3;
  301. margin-bottom: 16px;
  302. padding-bottom: 12px;
  303. border-bottom: 2px solid #17B3A3;
  304. }
  305. .info-title i {
  306. margin-right: 8px;
  307. font-size: 18px;
  308. }
  309. .info-row {
  310. display: flex;
  311. justify-content: space-between;
  312. align-items: flex-start;
  313. padding: 10px 0;
  314. border-bottom: 1px solid #f0f0f0;
  315. }
  316. .info-row:last-child {
  317. border-bottom: none;
  318. }
  319. .info-label {
  320. font-size: 14px;
  321. color: #666;
  322. min-width: 90px;
  323. flex-shrink: 0;
  324. }
  325. .info-value {
  326. font-size: 14px;
  327. font-weight: 500;
  328. color: #333;
  329. flex: 1;
  330. text-align: right;
  331. word-break: break-all;
  332. }
  333. .bottom-actions {
  334. display: flex;
  335. gap: 12px;
  336. padding-top: 16px;
  337. }
  338. .action-btn {
  339. flex: 1;
  340. padding: 12px 24px;
  341. border: none;
  342. border-radius: 6px;
  343. font-size: 16px;
  344. font-weight: 500;
  345. cursor: pointer;
  346. transition: all 0.2s;
  347. min-height: 44px;
  348. }
  349. .action-btn.primary {
  350. background: #17B3A3;
  351. color: white;
  352. }
  353. .action-btn.primary:hover {
  354. background: #15a394;
  355. }
  356. .action-btn.primary:disabled {
  357. background: #ccc;
  358. cursor: not-allowed;
  359. opacity: 0.6;
  360. }
  361. .action-btn.secondary {
  362. background: #f5f5f5;
  363. color: #333;
  364. border: 1px solid #ddd;
  365. }
  366. .action-btn.secondary:hover {
  367. background: #e8e8e8;
  368. }
  369. .action-btn:disabled {
  370. opacity: 0.6;
  371. cursor: not-allowed;
  372. }
  373. </style>