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.

298 lines
13 KiB

8 months ago
8 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
7 months ago
6 months ago
6 months ago
6 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
6 months ago
7 months ago
8 months ago
6 months ago
8 months ago
6 months ago
7 months ago
8 months ago
6 months ago
8 months ago
7 months ago
6 months ago
6 months ago
6 months ago
8 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
8 months ago
6 months ago
7 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
8 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
8 months ago
6 months ago
8 months ago
6 months ago
8 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
8 months ago
7 months ago
8 months ago
7 months ago
6 months ago
7 months ago
6 months ago
6 months ago
6 months ago
6 months ago
8 months ago
  1. <template>
  2. <div>
  3. <div class="pda-container">
  4. <div class="status-bar">
  5. <div class="goBack" @click="handleBack"><i class="el-icon-arrow-left"></i>上一页</div>
  6. <div class="goBack">采购订单接收</div>
  7. <div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div>
  8. </div>
  9. <div style="overflow-y: auto">
  10. <!-- Step 1: 扫描 -->
  11. <div v-if="processFlag === 1">
  12. <div class="scan-box" style="margin: 2px;">
  13. <el-input clearable v-model="scanCode" placeholder="扫描PO条码或输入PO号"
  14. @keyup.enter.native="searchPoList" ref="scanCodeRef" />
  15. </div>
  16. <div class="item-list" v-if="poList.length > 0" style="margin: 2px;">
  17. <el-form label-position="top" style="margin: 3px;">
  18. <el-row :gutter="5" @click.native="recvLine(poDetail)"
  19. v-for="(poDetail, index) in poList" :key="index" :class="index < poList.length - 1 ? 'bottom-line-row' : ''">
  20. <el-col :span="8">
  21. <el-form-item label="商品编码"><span>{{ poDetail.partNo }}</span></el-form-item>
  22. </el-col>
  23. <el-col :span="8">
  24. <el-form-item label="行号/下达号"><span>{{ poDetail.lineNo }}/{{ poDetail.wdr }}</span></el-form-item>
  25. </el-col>
  26. <el-col :span="8">
  27. <el-form-item label="">
  28. <el-button type="text" class="recvButton" @click="recvLine(poDetail)"
  29. style="margin-top: 10px;margin-left: 20px" size="small">接收</el-button>
  30. </el-form-item>
  31. </el-col>
  32. <el-col :span="24">
  33. <el-form-item label="商品描述"><span>{{ poDetail.description }}</span></el-form-item>
  34. </el-col>
  35. <el-col :span="6">
  36. <el-form-item label="订单数量"><span>{{ poDetail.purchaseQty }}</span></el-form-item>
  37. </el-col>
  38. <el-col :span="6">
  39. <el-form-item label="待收数量"><span>{{ poDetail.qtyToReceive }}</span></el-form-item>
  40. </el-col>
  41. <el-col :span="6">
  42. <el-form-item label="此次接收数量"><span>{{ poDetail.thisRecvQty }}</span></el-form-item>
  43. </el-col>
  44. <el-col :span="6" >
  45. <el-form-item style="margin-left: 20px" label="单位"><span>{{ poDetail.inventoryUOM }}</span></el-form-item>
  46. </el-col>
  47. </el-row>
  48. </el-form>
  49. </div>
  50. </div>
  51. <!-- Step 2: 收货明细 -->
  52. <div v-if="processFlag === 2">
  53. <el-form label-position="top" class="form-section" style="margin: 5px;">
  54. <el-row :gutter="20">
  55. <el-col :span="12"><el-form-item label="PO号码"><el-input v-model="recvItem.orderNo" disabled /></el-form-item></el-col>
  56. <el-col :span="12"><el-form-item label="行号/下达号"><el-input v-model="displayLineWdr" disabled /></el-form-item></el-col>
  57. <el-col :span="12"><el-form-item label="商品编码"><el-input v-model="recvItem.partNo" disabled /></el-form-item></el-col>
  58. <el-col :span="12"><el-form-item label="计量单位"><el-input v-model="recvItem.inventoryUOM" disabled /></el-form-item></el-col>
  59. <el-col :span="24"><el-form-item label="商品名称"><el-input v-model="recvItem.description" disabled /></el-form-item></el-col>
  60. <el-col :span="12"><el-form-item label="订单数量"><el-input v-model="recvItem.purchaseQty" disabled /></el-form-item></el-col>
  61. <el-col :span="12"><el-form-item label="待收数量"><el-input v-model="recvItem.qtyToReceive" disabled /></el-form-item></el-col>
  62. <el-col :span="12">
  63. <el-form-item label="此次接收数量">
  64. <el-input v-model="recvItem.transQty" :disabled="recvItem.needHandlingUnit === 'Y'" />
  65. </el-form-item>
  66. </el-col>
  67. <el-col :span="12">
  68. <el-form-item label=" ">
  69. <el-button type="text" @click.stop="handlingUnitStep" :disabled="recvItem.needHandlingUnit !== 'Y'"
  70. :class="{ 'disabled-button': recvItem.needHandlingUnit !== 'Y' }"
  71. style="font-size: 16px" size="small">包装记录</el-button>
  72. </el-form-item>
  73. </el-col>
  74. <el-col :span="12"><el-form-item label="制造日期"><el-date-picker v-model="recvItem.manufactureDate" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" placeholder="选择制造日期" style="width: 100%" /></el-form-item></el-col>
  75. <el-col :span="12"><el-form-item label="失效日期"><el-date-picker v-model="recvItem.expiringDate" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" placeholder="选择失效日期" style="width: 100%" /></el-form-item></el-col>
  76. <el-col :span="12"><el-form-item label="库位"><el-input v-model="recvItem.locationNo" placeholder="请输入库位" /></el-form-item></el-col>
  77. <el-col :span="12"><el-form-item label="批号"><el-input v-model="recvItem.batchNo" placeholder="请输入批号" /></el-form-item></el-col>
  78. <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>
  79. <el-col :span="8" style="margin-top: 10px"><el-form-item><el-button type="text" style="font-size: 16px;margin-left: 20px" @click="receivePo">保存</el-button></el-form-item></el-col>
  80. <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>
  81. </el-row>
  82. </el-form>
  83. </div>
  84. <!-- Step 3: 包装记录 -->
  85. <div v-if="processFlag === 3">
  86. <el-form label-position="top" class="form-section" style="margin: 5px;">
  87. <el-row :gutter="20">
  88. <el-col :span="12"><el-form-item label="商品编码"><el-input v-model="recvItem.partNo" disabled /></el-form-item></el-col>
  89. <el-col :span="12"><el-form-item label="计量单位"><el-input v-model="recvItem.unit" disabled /></el-form-item></el-col>
  90. <el-col :span="24"><el-form-item label="商品名称"><el-input v-model="recvItem.desc" disabled /></el-form-item></el-col>
  91. <el-col :span="8"><el-form-item label="单包装数量"><el-input v-model="hanlingItem.perQty" /></el-form-item></el-col>
  92. <el-col :span="8"><el-form-item label="包装数"><el-input v-model="hanlingItem.packageQty" /></el-form-item></el-col>
  93. <el-col :span="8" style="margin-top: 24px"><el-form-item>
  94. <el-button type="text" @click="createHandlingUnit" style="font-size: 16px">创建</el-button></el-form-item></el-col>
  95. <el-table :data="handlingUnit" :row-style="{ height: '30px' }" style="width: 94%; margin-left: 10px;" highlight-current-row>
  96. <el-table-column prop="code" label="Unit ID" />
  97. <el-table-column prop="qty" label="数量" width="60" />
  98. <el-table-column label="操作">
  99. <template slot-scope="scope">
  100. <a @click="removeItem(scope.$index)">删除</a>
  101. </template>
  102. </el-table-column>
  103. </el-table>
  104. <el-col :span="24"><el-form-item><span>合计</span><span style="margin-left: 38%">{{ totalQty }}</span></el-form-item></el-col>
  105. <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>
  106. <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>
  107. </el-row>
  108. </el-form>
  109. </div>
  110. </div>
  111. </div>
  112. </div>
  113. </template>
  114. <script>
  115. import { getPoList, receivePo } from "@/api/po/po.js";
  116. export default {
  117. data() {
  118. return {
  119. processFlag: 1,
  120. scanCode: '',
  121. poList: [],
  122. recvItem: {},
  123. handlingUnit: [],
  124. hanlingItem: { code: '', qty: '', perQty: '', packageQty: '' },
  125. site:localStorage.getItem('site')
  126. };
  127. },
  128. computed: {
  129. totalQty() {
  130. const sum = this.handlingUnit.reduce((sum, item) => sum + Number(item.qty), 0);
  131. this.recvItem.transQty = sum;
  132. return sum;
  133. },
  134. huKey() {
  135. return `hu_${this.recvItem.poNumber}_${this.recvItem.lineNo}`;
  136. },
  137. displayLineWdr() {
  138. return `${this.recvItem.lineNo || ''}/${this.recvItem.wdr || ''}`;
  139. }
  140. },
  141. methods: {
  142. handleBack() {
  143. if (this.processFlag === 1) this.$router.back();
  144. else if (this.processFlag === 3) this.processFlag = 2;
  145. else this.processFlag = 1;
  146. },
  147. searchPoList() {
  148. if (!this.scanCode) return this.poList = [];
  149. getPoList({ poNumber: this.scanCode,site: this.site }).then(({ data }) => {
  150. if (data.code === 0) this.poList = data.rows;
  151. });
  152. },
  153. recvLine(row) {
  154. this.recvItem = {
  155. ...row,
  156. poNo: row.poNumber || this.scanCode,
  157. dueinQty: row.qtyToReceive || row.thisRecvQty,
  158. transQty: row.thisRecvQty || 0
  159. };
  160. this.processFlag = 2;
  161. },
  162. handlingUnitStep() {
  163. this.processFlag = 3;
  164. const saved = localStorage.getItem(this.huKey);
  165. this.handlingUnit = saved ? JSON.parse(saved) : [];
  166. },
  167. createHandlingUnit() {
  168. const { perQty, packageQty } = this.hanlingItem;
  169. if (!perQty || !packageQty || isNaN(perQty) || isNaN(packageQty)) {
  170. return this.$message.warning("请填写有效的包装信息");
  171. }
  172. const qty = parseFloat(perQty) * parseInt(packageQty);
  173. const code = 'H' + String(this.handlingUnit.length + 1).padStart(3, '0');
  174. const newItem = { ...this.hanlingItem, qty, code };
  175. this.handlingUnit.push(newItem);
  176. localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit));
  177. },
  178. removeItem(index) {
  179. this.handlingUnit.splice(index, 1);
  180. localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit));
  181. },
  182. receivePo() {
  183. const item = this.recvItem;
  184. if (!item.transQty || !item.locationNo || !item.batchNo) {
  185. return this.$message.error("请填写完整信息");
  186. }
  187. // 构建符合服务端TransDetailDto结构的数据
  188. const receiveData = {
  189. // 基本字段
  190. site: this.site,
  191. partNo: item.partNo,
  192. transQty: item.transQty,
  193. batchNo: item.batchNo,
  194. locationNo: item.locationNo,
  195. itemNo: 1,
  196. // PO相关字段
  197. poNo: item.poNumber || item.poNo,
  198. orderNo: item.orderNo,
  199. lineNo: item.lineNo,
  200. relNo: item.relNo,
  201. receiptNo: item.receiptNo,
  202. // 业务控制字段
  203. needHandlingUnit: item.needHandlingUnit || 'N',
  204. needCheck: item.needCheck || 'N',
  205. warehouseType: item.warehouseType || 'MANUAL',
  206. needPallet: item.needPallet || 'N',
  207. workshopFlag: item.workshopFlag || 'N',
  208. cuttingFlag: item.cuttingFlag || 'N',
  209. // 日期字段
  210. manufactureDate: item.manufactureDate,
  211. // 注意:失效日期由服务端自动计算,不需要传递
  212. // expiredDate: item.expiringDate,
  213. // 处理单元列表
  214. handlingUnitList: item.needHandlingUnit === 'Y' ? this.handlingUnit.map(hu => ({
  215. perQty: hu.qty,
  216. packageQty: 1
  217. })) : []
  218. };
  219. receivePo(receiveData).then(({ data }) => {
  220. if (data.code === 0) {
  221. this.$message.success("操作成功");
  222. localStorage.removeItem(this.huKey);
  223. this.processFlag = 1;
  224. this.scanCode = '';
  225. this.poList = [];
  226. this.recvItem = {};
  227. this.handlingUnit = [];
  228. } else {
  229. this.$message.error(data.msg || '操作失败');
  230. }
  231. }).catch(error => {
  232. console.error('接收失败:', error);
  233. this.$message.error('网络错误,请重试');
  234. });
  235. }
  236. },
  237. mounted() {
  238. this.$nextTick(() => this.$refs.scanCodeRef.focus());
  239. }
  240. };
  241. </script>
  242. <style scoped>
  243. .scan-box input {
  244. width: 100%;
  245. padding: 12px;
  246. font-size: 16px;
  247. }
  248. .item-list {
  249. flex: 1;
  250. overflow-y: auto;
  251. margin: 10px 0;
  252. border: 1px solid rgba(200, 200, 200, 0.8);
  253. }
  254. .item-list span {
  255. color: #000;
  256. font-size: 15px;
  257. }
  258. .bottom-line-row {
  259. border-bottom: 1px solid rgba(200, 200, 200, 0.8);
  260. }
  261. .recvButton {
  262. font-size: 16px;
  263. border-radius: 3px;
  264. color: #17b3a3;
  265. }
  266. .item-list .el-row {
  267. cursor: pointer;
  268. transition: background 0.3s;
  269. }
  270. .item-list .el-row:hover {
  271. background: #f5f7fa;
  272. }
  273. .disabled-button {
  274. color: #ccc !important;
  275. cursor: not-allowed !important;
  276. }
  277. .form-section >>> .el-col {
  278. margin-bottom: 12px;
  279. }
  280. .status-bar {
  281. display: flex;
  282. justify-content: space-between;
  283. align-items: center;
  284. background: #17b3a3;
  285. color: white;
  286. }
  287. </style>