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.

662 lines
25 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <template>
  2. <div>
  3. <div class="pda-container" v-loading.fullscreen.lock="fullscreenLoading"
  4. element-loading-background="rgba(255, 255, 255, 0.3)"
  5. element-loading-spinner="el-icon-loading"
  6. :element-loading-text="loadingText">
  7. <div class="status-bar">
  8. <div class="goBack" @click="handleBack"><i class="el-icon-arrow-left"></i>上一页</div>
  9. <div class="goBack">生产入库</div>
  10. <div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div>
  11. </div>
  12. <div style="overflow-y: auto">
  13. <!-- Step 1: 扫描工单号 -->
  14. <div v-if="processFlag === 1">
  15. <div class="scan-box" style="margin: 2px;">
  16. <el-input clearable v-model="scanCode" placeholder="扫描或输入工单号"
  17. inputmode="none"
  18. autocomplete="off"
  19. autocorrect="off"
  20. spellcheck="false"
  21. @keyup.enter.native="searchShopOrder" ref="scanCodeRef" />
  22. </div>
  23. <div class="item-list" v-if="shopOrderList.length > 0" style="margin: 2px;">
  24. <el-form label-position="top" style="margin: 3px;">
  25. <el-row :gutter="5"
  26. v-for="(orderDetail, index) in shopOrderList" :key="index" :class="index < shopOrderList.length - 1 ? 'bottom-line-row' : ''">
  27. <el-col :span="8">
  28. <el-form-item label="料号"><span>{{ orderDetail.partNo }}</span></el-form-item>
  29. </el-col>
  30. <el-col :span="8">
  31. <el-form-item label="行号/下达号"><span>{{ orderDetail.releaseNo }}/{{ orderDetail.sequenceNo }}</span></el-form-item>
  32. </el-col>
  33. <el-col :span="8">
  34. <el-form-item label="">
  35. <el-button type="text" class="recvButton" @click="selectShopOrder(orderDetail)"
  36. style="margin-top: 10px;margin-left: 20px" size="small">入库</el-button>
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="24">
  40. <el-form-item label="物料描述"><span>{{ orderDetail.partDesc }}</span></el-form-item>
  41. </el-col>
  42. <el-col :span="6" :class="{ mt10: getTextWidth(orderDetail.partDesc) > 34 }">
  43. <el-form-item label="订单数量"><span>{{ orderDetail.lotSize }}</span></el-form-item>
  44. </el-col>
  45. <el-col :span="6" :class="{ mt10: getTextWidth(orderDetail.partDesc) > 34 }">
  46. <el-form-item label="已完成数"><span>{{ orderDetail.qtyComplete }}</span></el-form-item>
  47. </el-col>
  48. <el-col :span="6" :class="{ mt10: getTextWidth(orderDetail.partDesc) > 34 }">
  49. <el-form-item label="状态">
  50. <el-tag :type="orderDetail.objstate === 'Started' ? 'success' : 'warning'" size="mini">
  51. {{ orderDetail.objstate }}
  52. </el-tag>
  53. </el-form-item>
  54. </el-col>
  55. <el-col :span="6" :class="{ mt10: getTextWidth(orderDetail.partDesc) > 34 }">
  56. <el-form-item style="margin-left: 20px" label="单位"><span>{{ orderDetail.uom }}</span></el-form-item>
  57. </el-col>
  58. </el-row>
  59. </el-form>
  60. </div>
  61. </div>
  62. <!-- Step 2: 入库明细 -->
  63. <div v-if="processFlag === 2">
  64. <el-form label-position="top" class="form-section" style="margin: 5px;">
  65. <el-row :gutter="20">
  66. <el-col :span="12"><el-form-item label="工单号"><el-input v-model="inboundItem.orderNo" disabled /></el-form-item></el-col>
  67. <el-col :span="12"><el-form-item label="下达号/序列号"><el-input v-model="displayReleaseSeq" disabled /></el-form-item></el-col>
  68. <el-col :span="12"><el-form-item label="料号"><el-input v-model="inboundItem.partNo" disabled /></el-form-item></el-col>
  69. <el-col :span="12"><el-form-item label="计量单位"><el-input v-model="inboundItem.uom" disabled /></el-form-item></el-col>
  70. <el-col :span="24"><el-form-item label="物料描述"><el-input v-model="inboundItem.partDesc" disabled /></el-form-item></el-col>
  71. <el-col :span="12"><el-form-item label="订单数量"><el-input v-model="inboundItem.lotSize" disabled /></el-form-item></el-col>
  72. <el-col :span="12"><el-form-item label="已完成数"><el-input v-model="inboundItem.qtyComplete" disabled /></el-form-item></el-col>
  73. <el-col :span="12">
  74. <el-form-item label="此次入库数量">
  75. <el-input v-model="inboundItem.transQty" type="number" @blur="checkQuantity" />
  76. </el-form-item>
  77. </el-col>
  78. <el-col :span="12">
  79. <el-form-item label=" ">
  80. <el-button type="text" @click.stop="handlingUnitStep"
  81. style="font-size: 16px;margin-top: -5px" size="small">包装记录</el-button>
  82. </el-form-item>
  83. </el-col>
  84. <el-col :span="12"><el-form-item label="库位">
  85. <el-input v-model="inboundItem.locationNo" placeholder="请输入库位" />
  86. </el-form-item></el-col>
  87. <el-col :span="12"><el-form-item label="批号">
  88. <el-input v-model="inboundItem.batchNo" placeholder="请输入批号" />
  89. </el-form-item></el-col>
  90. <el-col :span="12"><el-form-item label="WDR">
  91. <el-input v-model="inboundItem.wdr" placeholder="请输入WDR" />
  92. </el-form-item></el-col>
  93. <!-- 勾选框 -->
  94. <el-col :span="12" style="margin-top: 24px">
  95. <el-form-item>
  96. <el-checkbox v-model="inboundItem.ifsAutoReport">Auto Report of Operation</el-checkbox>
  97. </el-form-item>
  98. </el-col>
  99. <el-col :span="24" style="margin-top: 5px">
  100. <el-form-item>
  101. <el-checkbox v-model="inboundItem.ifsSimplifiedMaterial">Simplified Material Check</el-checkbox>
  102. </el-form-item>
  103. </el-col>
  104. </el-row>
  105. <el-row :gutter="20">
  106. <el-col :span="8" style="margin-top: 10px"><el-form-item><el-button type="text" style="font-size: 16px;margin-left: 30px" @click="processFlag = 1">回退</el-button></el-form-item></el-col>
  107. <el-col :span="8" style="margin-top: 10px"><el-form-item><el-button type="text" style="font-size: 16px;margin-left: 20px" @click="confirmInbound">确认</el-button></el-form-item></el-col>
  108. <el-col :span="8" style="margin-top: 10px"><el-form-item><el-button type="text" style="font-size: 16px;margin-left: 10px" @click="$router.push('/')">退出</el-button></el-form-item></el-col>
  109. </el-row>
  110. </el-form>
  111. </div>
  112. <!-- Step 3: 包装记录 -->
  113. <div v-if="processFlag === 3">
  114. <el-form label-position="top" class="form-section" style="margin: 5px;">
  115. <el-row :gutter="20">
  116. <el-col :span="12"><el-form-item label="料号"><el-input v-model="inboundItem.partNo" disabled /></el-form-item></el-col>
  117. <el-col :span="12"><el-form-item label="未完成数量"><el-input v-model="inboundItem.unCompleteQty" disabled /></el-form-item></el-col>
  118. <el-col :span="24"><el-form-item label="物料描述"><el-input v-model="inboundItem.partDesc" disabled /></el-form-item></el-col>
  119. <!-- 自动计算开关 -->
  120. <el-col :span="24" style="margin-bottom: 10px;">
  121. <el-form-item>
  122. <el-switch
  123. v-model="autoCalculate"
  124. active-text="自动计算模式"
  125. inactive-text="手动输入模式"
  126. active-color="#17B3A3"
  127. style="display: block;"
  128. >
  129. </el-switch>
  130. <span v-if="autoCalculate" style="font-size: 13px; color: #17B3A3; margin-top: 5px; display: block; font-weight: bold;">
  131. 💡 输入单包装数量后按回车键或点击确定按钮
  132. </span>
  133. <span v-else style="font-size: 12px; color: #999; margin-top: 5px; display: block;">
  134. 手动输入单包装数量和包装数然后点击"创建"按钮
  135. </span>
  136. </el-form-item>
  137. </el-col>
  138. <el-col :span="8" style="margin-top: 5px"><el-form-item label="单包装数量">
  139. <el-input
  140. v-model="hanlingItem.perQty"
  141. type="number"
  142. :placeholder="autoCalculate ? '输入完按回车或失去焦点' : '请输入单包装数量'"
  143. @blur="autoCalculate && autoCreateHandlingUnits()"
  144. @keyup.enter.native="autoCalculate && autoCreateHandlingUnits()"
  145. />
  146. </el-form-item></el-col>
  147. <el-col :span="8" style="margin-top: 5px" v-if="!autoCalculate"><el-form-item label="包装数">
  148. <el-input v-model="hanlingItem.packageQty" type="number" placeholder="请输入包装数" />
  149. </el-form-item></el-col>
  150. <el-col :span="8" v-if="!autoCalculate" style="margin-top: 16px"><el-form-item>
  151. <el-button type="text" @click="createHandlingUnit" style="font-size: 16px">创建</el-button></el-form-item></el-col>
  152. <el-col :span="8" v-else style="margin-top: 16px"><el-form-item>
  153. <el-button type="text" style="font-size: 16px">确定</el-button></el-form-item></el-col>
  154. <el-table :data="handlingUnit" :row-style="{ height: '30px' }" style="width: 94%; margin-left: 10px;" highlight-current-row>
  155. <el-table-column prop="code" label="序号" />
  156. <el-table-column prop="packageQty" label="包装数" width="80" />
  157. <el-table-column prop="perQty" label="单包装数量" width="100" />
  158. <el-table-column label="操作" v-if="!autoCalculate">
  159. <template slot-scope="scope">
  160. <a @click="removeItem(scope.$index)">删除</a>
  161. </template>
  162. </el-table-column>
  163. </el-table>
  164. <el-col :span="24" v-if="autoCalculate && handlingUnit.length > 0" style="margin-top: 10px;">
  165. <span style="font-size: 12px; color: #999;">
  166. 💡 如需修改请重新输入单包装数量
  167. </span>
  168. </el-col>
  169. <el-col :span="24"><el-form-item><span>合计</span><span style="margin-left: 38%">{{ totalQty }}</span></el-form-item></el-col>
  170. <el-col :span="12"><el-form-item><el-button type="text" @click="processFlag = 2" style="font-size: 18px;margin-left: 60px">回退</el-button></el-form-item></el-col>
  171. <el-col :span="12"><el-form-item><el-button type="text" @click="processFlag = 2" style="font-size: 18px;">确定</el-button></el-form-item></el-col>
  172. </el-row>
  173. </el-form>
  174. </div>
  175. </div>
  176. </div>
  177. </div>
  178. </template>
  179. <script>
  180. import { getShopOrderFromIfs, getNextSequenceNo, submitShopOrderInbound, validateMaterialIssued, printLabel } from "@/api/production/production-inbound.js";
  181. export default {
  182. data() {
  183. return {
  184. processFlag: 1,
  185. scanCode: '',
  186. shopOrderList: [],
  187. inboundItem: {},
  188. handlingUnit: [],
  189. hanlingItem: { code: '', qty: '', perQty: '', packageQty: '' },
  190. site: localStorage.getItem('site'),
  191. warehouseId: localStorage.getItem('selectedWarehouse'),
  192. fullscreenLoading: false,
  193. loadingText: '加载中...',
  194. autoCalculate: false
  195. };
  196. },
  197. computed: {
  198. totalQty() {
  199. const sum = this.handlingUnit.reduce((sum, item) => sum + Number(item.qty), 0);
  200. this.inboundItem.transQty = sum;
  201. return sum;
  202. },
  203. huKey() {
  204. return `hu_shop_${this.inboundItem.orderNo}_${this.inboundItem.releaseNo}`;
  205. },
  206. displayReleaseSeq() {
  207. return `${this.inboundItem.releaseNo || ''}/${this.inboundItem.sequenceNo || ''}`;
  208. }
  209. },
  210. watch: {
  211. autoCalculate(newVal, oldVal) {
  212. this.hanlingItem.perQty = '';
  213. this.hanlingItem.packageQty = '';
  214. this.handlingUnit = [];
  215. localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit));
  216. if (newVal) {
  217. this.$message.success('已切换到自动创建HU模式');
  218. } else {
  219. this.$message.success('已切换到手动输入模式');
  220. }
  221. }
  222. },
  223. methods: {
  224. // 计算"显示宽度"
  225. getTextWidth(text) {
  226. if (!text) return 0
  227. let len = 0
  228. for (let char of text) {
  229. if (/[\u4e00-\u9fa5\u3000-\u303F\uFF00-\uFFEF]/.test(char)) {
  230. len += 2
  231. } else {
  232. len += 1
  233. }
  234. }
  235. return len
  236. },
  237. handleBack() {
  238. if (this.processFlag === 1) this.$router.back();
  239. else if (this.processFlag === 3) this.processFlag = 2;
  240. else this.processFlag = 1;
  241. },
  242. // 搜索工单
  243. searchShopOrder() {
  244. if (!this.scanCode) return this.shopOrderList = [];
  245. this.loadingText = '搜索中...';
  246. this.fullscreenLoading = true;
  247. // 解析工单号:支持 "3038851" 或 "3038851-1-2" 格式
  248. let orderNo = this.scanCode.trim();
  249. let releaseNo = "*";
  250. let sequenceNo = "*";
  251. // 如果包含"-",则按照 orderNo-releaseNo-sequenceNo 格式解析
  252. const parts = orderNo.split('-');
  253. if (parts.length >= 2) {
  254. orderNo = parts[0];
  255. releaseNo = parts[1];
  256. if (parts.length >= 3) {
  257. sequenceNo = parts[2];
  258. }
  259. }
  260. const requestData = {
  261. ifsDBName: "IFST",
  262. domainUserID: "CCL_WMS",
  263. ifsSiteID: this.site,
  264. ifsOrderNo: orderNo,
  265. ifsReleaseNo: releaseNo,
  266. ifsSequenceNo: sequenceNo
  267. };
  268. console.log('工单查询参数:', requestData);
  269. getShopOrderFromIfs(requestData).then(({ data }) => {
  270. if (data.code === 0) {
  271. this.shopOrderList = data.data || []
  272. if (this.shopOrderList.length === 0) {
  273. this.$message.warning('未找到匹配的工单');
  274. }
  275. } else {
  276. this.$message.error(data.msg || '查询失败');
  277. this.shopOrderList = []
  278. }
  279. this.$nextTick(() => {
  280. if (this.$refs.scanCodeRef) {
  281. this.$refs.scanCodeRef.blur();
  282. }
  283. });
  284. }).catch(error => {
  285. console.error('搜索失败:', error);
  286. this.$message.error('搜索失败,请重试');
  287. this.shopOrderList = []
  288. }).finally(() => {
  289. this.fullscreenLoading = false;
  290. });
  291. },
  292. // 选择工单
  293. async selectShopOrder(row) {
  294. // 校验状态
  295. if (row.objstate !== 'Started') {
  296. return this.$message.warning(`工单状态为 ${row.objstate},只有Started状态才能入库`);
  297. }
  298. this.fullscreenLoading = true;
  299. this.loadingText = '检查物料发料状态...';
  300. try {
  301. // 1. 检查物料是否已发料
  302. const validateResult = await validateMaterialIssued({
  303. site: this.site,
  304. orderNo: row.orderNo,
  305. releaseNo: row.releaseNo || '*',
  306. sequenceNo: row.sequenceNo || '*'
  307. });
  308. if (validateResult.data.code !== 0) {
  309. this.$alert(validateResult.data.msg || '物料发料检查失败', '操作提示', {
  310. confirmButtonText: '确定',
  311. type: 'warning'
  312. });
  313. return;
  314. }
  315. this.loadingText = '加载中...';
  316. // 2. 获取下一个序列号
  317. let nextSequence = 1;
  318. try {
  319. const { data } = await getNextSequenceNo({
  320. orderNo: row.orderNo,
  321. releaseNo: row.releaseNo || '*',
  322. sequenceNo: row.sequenceNo || '*'
  323. });
  324. if (data.code === 0) {
  325. nextSequence = data.data;
  326. }
  327. } catch (error) {
  328. console.error('获取序列号失败:', error);
  329. }
  330. this.inboundItem = {
  331. ...row,
  332. transQty: '',
  333. unCompleteQty: parseFloat(row.lotSize) - parseFloat(row.qtyComplete),
  334. sequenceNoNew: nextSequence,
  335. batchNo: `${row.orderNo}-${row.releaseNo}-${row.sequenceNo}-${nextSequence}`,
  336. locationNo: '',
  337. serialNo: '*',
  338. wdr: '*',
  339. engChgLevel: '1',
  340. ifsAutoReport: false, // Auto Report of Operation
  341. ifsSimplifiedMaterial: true // Simplified Material Check默认选中
  342. };
  343. this.processFlag = 2;
  344. } catch (error) {
  345. console.error('操作失败:', error);
  346. this.$message.error(error.message || '操作失败');
  347. } finally {
  348. this.fullscreenLoading = false;
  349. }
  350. },
  351. // 检查数量
  352. checkQuantity() {
  353. const transQty = parseFloat(this.inboundItem.transQty) || 0;
  354. const qtyComplete = parseFloat(this.inboundItem.qtyComplete) || 0;
  355. const lotSize = parseFloat(this.inboundItem.lotSize) || 0;
  356. if (qtyComplete + transQty > lotSize) {
  357. this.$confirm(
  358. `当前已完成数量(${qtyComplete}) + 本次入库数量(${transQty}) = ${qtyComplete + transQty},超过订单数量(${lotSize}),是否继续?`,
  359. '数量超出提示',
  360. {
  361. confirmButtonText: '继续',
  362. cancelButtonText: '取消',
  363. type: 'warning'
  364. }
  365. ).catch(() => {
  366. this.inboundItem.transQty = '';
  367. });
  368. }
  369. },
  370. handlingUnitStep() {
  371. this.processFlag = 3;
  372. this.autoCalculate = false; // 默认使用自动计算模式
  373. const saved = localStorage.getItem(this.huKey);
  374. this.handlingUnit = saved ? JSON.parse(saved) : [];
  375. },
  376. /**
  377. * 自动创建HU列表自动模式
  378. */
  379. autoCreateHandlingUnits() {
  380. const perQty = this.hanlingItem.perQty;
  381. if (!perQty || isNaN(perQty) || parseFloat(perQty) <= 0) {
  382. this.$message.warning('请输入有效的单包装数量');
  383. return;
  384. }
  385. const qtyToReceive = parseFloat(this.inboundItem.transQty) || 0;
  386. if (qtyToReceive <= 0) {
  387. this.$message.warning('入库数量为0,无法创建HU');
  388. this.hanlingItem.perQty = '';
  389. return;
  390. }
  391. const perQtyValue = parseFloat(perQty);
  392. const packageQty = Math.floor(qtyToReceive / perQtyValue);
  393. const remainder = qtyToReceive - (packageQty * perQtyValue);
  394. this.handlingUnit = [];
  395. if (packageQty > 0) {
  396. for (let i = 1; i <= packageQty; i++) {
  397. const qty = perQtyValue;
  398. const code = String(i);
  399. this.handlingUnit.push({
  400. code: code,
  401. perQty: perQtyValue,
  402. packageQty: 1,
  403. qty: qty
  404. });
  405. }
  406. }
  407. if (remainder > 0) {
  408. const code = String(this.handlingUnit.length + 1);
  409. this.handlingUnit.push({
  410. code: code,
  411. perQty: remainder,
  412. packageQty: 1,
  413. qty: remainder
  414. });
  415. }
  416. localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit));
  417. this.hanlingItem.perQty = '';
  418. this.hanlingItem.packageQty = '';
  419. this.$message.success(`自动创建了${this.handlingUnit.length}个HU,合计数量:${qtyToReceive}`);
  420. },
  421. /**
  422. * 手动创建HU手动模式
  423. */
  424. createHandlingUnit() {
  425. const { perQty, packageQty } = this.hanlingItem;
  426. if (!perQty || !packageQty || isNaN(perQty) || isNaN(packageQty)) {
  427. return this.$message.warning("请填写有效的包装信息");
  428. }
  429. const qty = parseFloat(perQty) * parseInt(packageQty);
  430. const code = String(this.handlingUnit.length + 1);
  431. const newItem = { ...this.hanlingItem, qty, code };
  432. this.handlingUnit.push(newItem);
  433. localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit));
  434. this.hanlingItem.perQty = '';
  435. this.hanlingItem.packageQty = '';
  436. },
  437. removeItem(index) {
  438. this.handlingUnit.splice(index, 1);
  439. localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit));
  440. },
  441. clearAllHandlingUnitCache() {
  442. this.hanlingItem = { code: '', qty: '', perQty: '', packageQty: '' };
  443. const keys = Object.keys(localStorage);
  444. keys.forEach(key => {
  445. if (key.startsWith('hu_shop_')) {
  446. localStorage.removeItem(key);
  447. }
  448. });
  449. },
  450. // 确认入库
  451. async confirmInbound() {
  452. if (this.fullscreenLoading) return;
  453. const item = this.inboundItem;
  454. if (!item.transQty || !item.locationNo || !item.batchNo) {
  455. return this.$message.error("请填写完整信息");
  456. }
  457. // 检查数量是否超出
  458. const transQty = parseFloat(item.transQty) || 0;
  459. const qtyComplete = parseFloat(item.qtyComplete) || 0;
  460. const lotSize = parseFloat(item.lotSize) || 0;
  461. if (qtyComplete + transQty > lotSize) {
  462. try {
  463. await this.$confirm(
  464. `当前已完成数量(${qtyComplete}) + 本次入库数量(${transQty}) = ${qtyComplete + transQty},超过订单数量(${lotSize}),是否继续?`,
  465. '数量超出提示',
  466. {
  467. confirmButtonText: '继续',
  468. cancelButtonText: '取消',
  469. type: 'warning'
  470. }
  471. );
  472. } catch (error) {
  473. // 用户取消
  474. return;
  475. }
  476. }
  477. this.loadingText = '提交中...';
  478. this.fullscreenLoading = true;
  479. // 构建提交数据
  480. const submitData = {
  481. // 基本字段
  482. site: this.site,
  483. warehouseId: this.warehouseId,
  484. orderNo: item.orderNo,
  485. releaseNo: item.releaseNo,
  486. sequenceNo: item.sequenceNo,
  487. partNo: item.partNo,
  488. partDesc: item.partDesc,
  489. transQty: item.transQty,
  490. batchNo: item.batchNo,
  491. locationNo: item.locationNo,
  492. serialNo: item.serialNo || '*',
  493. engChgLevel: item.engChgLevel || '1',
  494. uom: item.uom,
  495. lotSize: item.lotSize,
  496. qtyComplete: item.qtyComplete,
  497. // IFS参数
  498. ifsAutoReport: item.ifsAutoReport ? 'Yes' : 'No',
  499. ifsSimplifiedMaterial: item.ifsSimplifiedMaterial ? 'Yes' : 'No',
  500. ifsAutoClose:item.closeCodeDb==='Y'?'TRUE':'FALSE',
  501. // 处理单元列表
  502. handlingUnitList: this.handlingUnit.map(hu => ({
  503. perQty: hu.perQty,
  504. packageQty: hu.packageQty
  505. }))
  506. };
  507. submitShopOrderInbound(submitData).then(({ data }) => {
  508. if (data.code === 0) {
  509. this.$message.success("入库成功");
  510. this.clearAllHandlingUnitCache();
  511. this.printViaServer(data.data);
  512. this.processFlag = 1;
  513. this.scanCode = '';
  514. this.shopOrderList = [];
  515. this.inboundItem = {};
  516. this.handlingUnit = [];
  517. } else {
  518. this.$message.error(data.msg || '入库失败');
  519. }
  520. }).catch(error => {
  521. console.error('入库失败:', error);
  522. this.$message.error('网络错误,请重试');
  523. }).finally(() => {
  524. this.fullscreenLoading = false;
  525. });
  526. },
  527. /**
  528. * 通过服务器打印
  529. */
  530. async printViaServer(transNo) {
  531. this.$emit('print-start')
  532. try {
  533. const printRequest = {
  534. userId: localStorage.getItem('userName'),
  535. username: localStorage.getItem('userName'),
  536. site: localStorage.getItem('site'),
  537. transNo: transNo,
  538. labelType: "库存成品标签"
  539. }
  540. const { data } = await printLabel(printRequest)
  541. if (data.code === 200) {
  542. this.$message.success(`打印任务已发送!`)
  543. }
  544. } catch (error) {
  545. console.error('服务器打印失败:', error)
  546. this.$message.error(`打印失败: ${error.message || error}`)
  547. }
  548. },
  549. },
  550. mounted() {
  551. this.$nextTick(() => this.$refs.scanCodeRef.focus());
  552. },
  553. };
  554. </script>
  555. <style scoped>
  556. .mt10 {
  557. margin-top: 10px;
  558. }
  559. .scan-box input {
  560. width: 100%;
  561. padding: 12px;
  562. font-size: 16px;
  563. }
  564. .item-list {
  565. flex: 1;
  566. overflow-y: auto;
  567. margin: 10px 0;
  568. border: 1px solid rgba(200, 200, 200, 0.8);
  569. }
  570. .item-list span {
  571. color: #000;
  572. font-size: 15px;
  573. }
  574. .bottom-line-row {
  575. border-bottom: 1px solid rgba(200, 200, 200, 0.8);
  576. }
  577. .recvButton {
  578. font-size: 16px;
  579. border-radius: 3px;
  580. color: #17b3a3;
  581. }
  582. .item-list .el-row {
  583. cursor: pointer;
  584. transition: background 0.3s;
  585. }
  586. .item-list .el-row:hover {
  587. background: #f5f7fa;
  588. }
  589. .disabled-button {
  590. color: #ccc !important;
  591. cursor: not-allowed !important;
  592. }
  593. .form-section >>> .el-col {
  594. margin-bottom: 2px;
  595. }
  596. .status-bar {
  597. display: flex;
  598. justify-content: space-between;
  599. align-items: center;
  600. background: #17b3a3;
  601. color: white;
  602. }
  603. /* 自定义loading样式 */
  604. .pda-container >>> .el-loading-mask {
  605. background-color: rgba(255, 255, 255, 0.3) !important;
  606. }
  607. .pda-container >>> .el-loading-spinner {
  608. margin-top: -25px;
  609. }
  610. .pda-container >>> .el-loading-spinner .circular {
  611. width: 35px;
  612. height: 35px;
  613. }
  614. .pda-container >>> .el-loading-text {
  615. color: #17b3a3 !important;
  616. font-size: 14px;
  617. font-weight: 500;
  618. margin-top: 10px;
  619. }
  620. </style>