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.

379 lines
12 KiB

4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
3 months ago
3 months ago
3 months ago
4 months ago
4 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
4 months ago
4 months ago
3 months ago
4 months ago
4 months ago
4 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
4 months ago
3 months ago
4 months ago
3 months ago
4 months ago
4 months ago
4 months ago
4 months ago
3 months ago
4 months ago
  1. <template>
  2. <div>
  3. <div class="pda-container">
  4. <!-- 头部栏 -->
  5. <div class="header-bar">
  6. <div class="header-left" @click="handleBack">
  7. <i class="el-icon-arrow-left"></i>
  8. <span>Call料</span>
  9. </div>
  10. <div class="header-right" @click="$router.push({ path: '/' })">
  11. 首页
  12. </div>
  13. </div>
  14. <!-- 搜索框 -->
  15. <!-- <div class="search-container">-->
  16. <!-- -->
  17. <!-- </div>-->
  18. <div class="table-body" style="max-height: 500px; overflow-y: auto;">
  19. <div class="main-content form-section">
  20. <!-- 表单区域 -->
  21. <div class="input-group">
  22. <label class="input-label">物料编码</label>
  23. <el-input
  24. v-model="formData.partNo"
  25. placeholder="请输入物料编码"
  26. class="form-input"
  27. clearable
  28. @blur="handlePartNoBlur"
  29. />
  30. </div>
  31. <!-- 栈板编码搜索框 - rqrq -->
  32. <div class="input-group">
  33. <label class="input-label">栈板编码</label>
  34. <el-input
  35. v-model="formData.palletId"
  36. placeholder="请输入栈板编码"
  37. class="form-input"
  38. clearable
  39. />
  40. </div>
  41. <div class="input-group">
  42. <label class="input-label">物料名称</label>
  43. <el-input
  44. v-model="formData.partDesc"
  45. disabled
  46. class="form-input"
  47. />
  48. </div>
  49. <div class="input-group">
  50. <label class="input-label">批号</label>
  51. <el-input
  52. v-model="formData.batchNo"
  53. class="form-input"
  54. clearable
  55. />
  56. </div>
  57. <div class="bottom-actions" style="display: flex; gap: 10px; flex-wrap: nowrap;">
  58. <button class="action-btn secondary" @click="confirmDo" style="flex: 1;">
  59. 查询
  60. </button>
  61. <button class="action-btn secondary" @click="cleanData" style="flex: 1;">
  62. 清空
  63. </button>
  64. <button
  65. class="action-btn secondary"
  66. @click="handleCall"
  67. :disabled="callLoading||selectedPallets.length === 0"
  68. style="flex: 1;"
  69. >
  70. {{ callLoading ? '下达中...' : `下达 (${selectedPallets.length})` }}
  71. </button>
  72. </div>
  73. </div>
  74. <!-- 栈板列表 -->
  75. <div v-if="palletList.length > 0" class="rma-list">
  76. <!-- Call车按钮 - 当有选中栈板时显示 -->
  77. <div class="list-title" style="flex: 0.75">可用栈板列表</div>
  78. <el-form>
  79. <el-row v-for="(pallet, index) in palletList" :key="index" class="rma-row">
  80. <el-col :span="24">
  81. <div class="rma-item" @click="selectPallet(pallet)" :class="{ 'selected': isSelected(pallet) }">
  82. <div class="item-info">
  83. <span class="part-no">栈板号: {{ pallet.palletId }}</span>
  84. <!-- rqrq - 如果有物料编码显示明细否则只显示栈板 -->
  85. <span class="batch-qty" v-if="pallet.partNo">
  86. 物料: {{ pallet.partNo }} | 数量: {{ pallet.qty }}
  87. </span>
  88. <span class="batch-qty" v-if="pallet.partNo && pallet.batchNo">
  89. | 批号: {{ pallet.batchNo }}
  90. </span>
  91. <span class="batch-qty" v-if="pallet.partNo && pallet.wdr">
  92. | WDR: {{ pallet.wdr }}
  93. </span>
  94. <span class="batch-qty" v-if="pallet.partNo && pallet.expiredDate">
  95. | 失效日期: {{ pallet.expiredDate }}
  96. </span>
  97. </div>
  98. <div class="item-status">
  99. <i class="el-icon-check" v-if="isSelected(pallet)"></i>
  100. </div>
  101. </div>
  102. </el-col>
  103. </el-row>
  104. </el-form>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. </template>
  110. <script>
  111. import {
  112. saveTransportTask,
  113. getShopOrderFromIFSWithOrderNo,
  114. getPalletList,
  115. callPalletFromWcs,
  116. callPalletFromWcsNew
  117. } from '../../../api/automatedWarehouse/callOut'
  118. export default {
  119. data() {
  120. return {
  121. scanRma: "",
  122. rmaList: [],
  123. returnList: [], // 退货明细列表
  124. selectedDetail: null, // 当前选择的RMA明细
  125. processType: "inbound", // 固定为入库处理
  126. site:localStorage.getItem('site'),
  127. loading: false, // 查询物料明细的loading状态
  128. lastPartNo: '', // 记录最后查询的物料编码,避免重复查询
  129. formData: {
  130. palletId: '', // 栈板编码 - rqrq
  131. partNo: '',
  132. partDesc: '',
  133. batchNo: '',
  134. rollNo: '',
  135. site:localStorage.getItem('site'),
  136. },
  137. palletList: [], // 栈板列表
  138. selectedPallet: null, // 选中的栈板
  139. selectedPallets: [], // 多选时选中的栈板列表
  140. callLoading: false, // Call车按钮loading状态 - rqrq
  141. };
  142. },
  143. computed: {
  144. },
  145. methods: {
  146. handleBack() {
  147. this.$router.back();
  148. },
  149. // 处理物料编码失去焦点事件
  150. async handlePartNoBlur() {
  151. const partNo = this.formData.partNo;
  152. if (!partNo) {
  153. this.formData.partDesc = '';
  154. return;
  155. }
  156. // 如果物料编码没有变化,不重复查询
  157. // if (this.lastPartNo === partNo) {
  158. // return;
  159. // }
  160. this.loading = true;
  161. getShopOrderFromIFSWithOrderNo({
  162. site: this.formData.site,
  163. partNo: partNo
  164. }).then(({ data }) => {
  165. this.loading = false;
  166. if (data.code === 0) {
  167. let rows=data.rows
  168. if(rows.length>0){
  169. this.formData.partDesc = rows[0].description || '';
  170. }else {
  171. this.formData.partDesc = '';
  172. this.$alert('没有找到该物料编码', '错误', {
  173. confirmButtonText: '确定',
  174. })
  175. }
  176. } else {
  177. // 查询失败或没有数据
  178. this.formData.partDesc = '';
  179. this.$alert(data.msg, '错误', {
  180. confirmButtonText: '确定',
  181. })
  182. }
  183. })
  184. },
  185. // 查询栈板列表 - rqrq 修改校验逻辑:物料编码和栈板码至少填一个
  186. confirmDo() {
  187. // 校验:物料编码和栈板码至少填一个 - rqrq
  188. if((!this.formData.partNo || this.formData.partNo === '') &&
  189. (!this.formData.palletId || this.formData.palletId === '')){
  190. this.$message.error('请输入物料编码或栈板编码');
  191. return;
  192. }
  193. // 构建查询参数 - rqrq
  194. const queryParams = {
  195. site: this.formData.site
  196. };
  197. // 添加栈板码到查询参数 - rqrq
  198. if (this.formData.palletId && this.formData.palletId.trim()) {
  199. queryParams.palletId = this.formData.palletId.trim();
  200. }
  201. // 添加物料编码到查询参数 - rqrq
  202. if (this.formData.partNo && this.formData.partNo.trim()) {
  203. queryParams.partNo = this.formData.partNo.trim();
  204. }
  205. // 如果有批号,添加到查询参数
  206. if (this.formData.batchNo && this.formData.batchNo.trim()) {
  207. queryParams.batchNo = this.formData.batchNo.trim();
  208. }
  209. getPalletList(queryParams).then(({ data }) => {
  210. if (data && data.code === 0) {
  211. this.palletList = data.rows || [];
  212. //如果有些是用batchNo查的 这些字段要一起加进去 呼叫栈板时保存
  213. if (this.palletList.length === 0) {
  214. this.$message.warning('未找到满足条件的栈板');
  215. } else {
  216. this.$message.success(`找到 ${this.palletList.length} 个栈板`);
  217. }
  218. // 清空之前选中的栈板
  219. this.selectedPallet = null;
  220. this.selectedPallets = []; // 清空多选选中的栈板
  221. } else {
  222. this.$message.error(data.msg || '查询失败');
  223. this.palletList = [];
  224. this.selectedPallet = null;
  225. this.selectedPallets = []; // 清空多选选中的栈板
  226. }
  227. }).catch(error => {
  228. console.error('查询栈板列表失败:', error);
  229. this.$message.error('查询失败');
  230. this.palletList = [];
  231. this.selectedPallet = null;
  232. this.selectedPallets = []; // 清空多选选中的栈板
  233. });
  234. },
  235. // 选择栈板 - rqrq 修改逻辑:按栈板ID选择,支持同一栈板多条明细
  236. selectPallet(pallet) {
  237. const palletId = pallet.palletId;
  238. const index = this.selectedPallets.findIndex(item => item.palletId === palletId);
  239. if (index > -1) {
  240. // 如果已选中,取消选择(移除该栈板)- rqrq
  241. this.selectedPallets.splice(index, 1);
  242. this.$message.success('已取消选择栈板');
  243. } else {
  244. // 如果未选中,选择该栈板(只添加一条记录用于Call)- rqrq
  245. this.selectedPallets.push({
  246. site: pallet.site,
  247. palletId: pallet.palletId,
  248. partNo: pallet.partNo || '', // 如果没有物料,传空字符串
  249. qty: pallet.qty || 0,
  250. batchNo: pallet.batchNo || this.formData.batchNo || ''
  251. });
  252. this.$message.success(`已选择栈板: ${palletId}`);
  253. }
  254. },
  255. // 判断栈板是否被选中 - rqrq
  256. isSelected(pallet) {
  257. return this.selectedPallets.some(item => item.palletId === pallet.palletId);
  258. },
  259. // 处理Call按钮点击 - rqrq
  260. handleCall() {
  261. if (this.selectedPallets.length === 0) {
  262. this.$message.error('请至少选择一个栈板');
  263. return;
  264. }
  265. this.$confirm(`确定Call ${this.selectedPallets.length} 个栈板出库?`, '提示', {
  266. confirmButtonText: '确认',
  267. cancelButtonText: '取消',
  268. type: 'warning'
  269. }).then(() => {
  270. // 设置loading状态 - rqrq
  271. this.callLoading = true;
  272. // 调用新的接口 - rqrq
  273. callPalletFromWcsNew(this.selectedPallets).then(({ data }) => {
  274. if (data && data.code === 0) {
  275. const failedCount = data.failedCount || 0;
  276. const successCount = data.successCount || 0;
  277. // 判断是否有失败 - rqrq
  278. if (failedCount === 0) {
  279. // 全部成功 - rqrq
  280. this.$message.success(`成功Call ${successCount} 个栈板出库!`);
  281. this.cleanData();
  282. } else {
  283. // 有失败的栈板 - rqrq
  284. const failedPalletIds = data.failedPalletIds || [];
  285. const failedReasons = data.failedReasons || [];
  286. // 构建失败信息 - rqrq
  287. let errorMsg = `成功:${successCount}个,失败:${failedCount}\n\n失败栈板:\n`;
  288. failedPalletIds.forEach((palletId, index) => {
  289. errorMsg += `${index + 1}. ${palletId}${failedReasons[index] || '未知错误'}\n`;
  290. });
  291. // 显示失败信息弹窗 - rqrq
  292. this.$alert(errorMsg, `Call车结果`, {
  293. confirmButtonText: '确定',
  294. type: 'warning',
  295. callback: () => {
  296. // 点击确定后初始化页面 - rqrq
  297. this.cleanData();
  298. }
  299. });
  300. }
  301. } else {
  302. this.$message.error(data.msg || 'Call车失败');
  303. }
  304. }).catch(error => {
  305. console.error('Call车失败:', error);
  306. this.$message.error('Call车失败');
  307. }).finally(() => {
  308. // 恢复按钮状态 - rqrq
  309. this.callLoading = false;
  310. });
  311. }).catch(() => {
  312. // 用户取消操作 - rqrq
  313. });
  314. },
  315. cleanData(){
  316. // 更安全的清空方式 - rqrq
  317. this.formData = {
  318. palletId: '', // 栈板编码 - rqrq
  319. partNo: '',
  320. partDesc: '',
  321. batchNo: '',
  322. rollNo: '',
  323. site:localStorage.getItem('site'),
  324. };
  325. // 清空栈板列表和选中状态
  326. this.palletList = [];
  327. this.selectedPallet = null;
  328. this.selectedPallets = []; // 清空多选选中的栈板
  329. },
  330. },
  331. mounted() {
  332. }
  333. };
  334. </script>
  335. <style scoped>
  336. /* 按钮禁用状态样式 - rqrq */
  337. .action-btn:disabled {
  338. opacity: 0.6;
  339. cursor: not-allowed;
  340. background-color: #ccc !important;
  341. border-color: #ccc !important;
  342. }
  343. </style>