From 863f0fe850d93ca4ecb9baddef1f71d9a3df70c2 Mon Sep 17 00:00:00 2001 From: HongxuanG <1359774872@qq.com> Date: Tue, 18 Aug 2026 14:06:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(storegoods):=20=E6=89=A3=E9=87=8D=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=89=AB=E7=A0=81=E6=8F=90=E4=BA=A4=E5=B9=B6=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E7=BB=86=E7=A0=81=E9=87=8D=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- src/common/storeGoodsProcessIn.js | 94 +++++++++++++-- .../storegoods/ProcessInDetailList.vue | 18 ++- .../storegoods/storeGoodsProcessInAdd.vue | 61 +++++++++- .../storegoods/storeGoodsProcessInEdit.vue | 51 +++++++- .../storegoods/storeGoodsProcessInMixin.js | 113 ++++++++++++++++-- .../storegoods/storeGoodsProcessInView.vue | 24 ++++ 6 files changed, 335 insertions(+), 26 deletions(-) diff --git a/src/common/storeGoodsProcessIn.js b/src/common/storeGoodsProcessIn.js index c86aa59..dd7645a 100644 --- a/src/common/storeGoodsProcessIn.js +++ b/src/common/storeGoodsProcessIn.js @@ -31,6 +31,25 @@ export const ARRANGE_TYPE = { /** 入仓类型:加工进仓单 */ export const IN_ORDER_TYPE_PROCESS = 5; +/** 入仓类型:返修进仓 */ +export const IN_ORDER_TYPE_REPAIR = 6; + +export const IN_ORDER_TYPE_MAP = { + [IN_ORDER_TYPE_PROCESS]: '加工进仓单', + [IN_ORDER_TYPE_REPAIR]: '返修进仓', +}; + +export const IN_ORDER_TYPE_OPTIONS = [ + { value: IN_ORDER_TYPE_PROCESS, label: IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_PROCESS] }, + { value: IN_ORDER_TYPE_REPAIR, label: IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_REPAIR] }, +]; + +/** 默认纸筒重量(公斤,表单展示值) */ +export const DEFAULT_PAPER_TUBE_WEIGHT = 1.5; + +/** 默认包装重量(公斤,表单展示值) */ +export const DEFAULT_PACKAGE_WEIGHT = 0.3; + /** 往来单位类型:加工单位 */ export const BUSINESS_UNIT_TYPE_PROCESS = 12; @@ -75,6 +94,11 @@ export function formatWeightKg(value) { return Number(n.toFixed(2)); } +/** 公斤展示值转后端存储(×10000) */ +export function toWeightStorage(value) { + return Math.round(Number(value || 0) * 10000); +} + export function normalizeOrder(order) { if (!order) return null; return { @@ -89,7 +113,11 @@ export function normalizeOrder(order) { sale_system_id: order.sale_system_id || '', sale_system_name: order.sale_system_name || '', in_order_type: order.in_order_type || IN_ORDER_TYPE_PROCESS, - in_order_type_name: order.in_order_type_name || '加工进仓单', + in_order_type_name: order.in_order_type_name + || IN_ORDER_TYPE_MAP[order.in_order_type] + || IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_PROCESS], + paper_tube_weight: formatWeightKg(order.paper_tube_weight), + package_weight: formatWeightKg(order.package_weight), remark: order.remark || '', warehouse_in_time: (order.warehouse_in_time || '').slice(0, 10), creator_name: order.creator_name || '', @@ -109,17 +137,28 @@ export function normalizeFineCode(fc) { const weightRaw = fc.base_unit_weight != null ? fc.base_unit_weight : (fc.settle_weight != null ? fc.settle_weight : fc.weight); + const qrCode = fc.qr_code || fc.long_code || ''; + const barCode = fc.bar_code || fc.digital_code || fc.short_code || ''; return { id: fc.id, volume_number: fc.volume_number != null && fc.volume_number !== '' ? String(fc.volume_number) : '', roll: formatRoll(fc.roll), weight: formatWeightKg(weightRaw), - bar_code: fc.bar_code || '', - qr_code: fc.qr_code || '', + bar_code: barCode, + qr_code: qrCode, + digital_code: fc.digital_code || '', + long_code: fc.long_code || '', + short_code: fc.short_code || '', dye_factory_dyelot_number: fc.dye_factory_dyelot_number || fc.dyelot_number || '', warehouse_bin_name: fc.warehouse_bin_name || '', shelf_no: fc.shelf_no || '', - scan_code: fc.qr_code || fc.bar_code || '', + scan_code: qrCode || barCode || '', + paper_tube_weight: fc.paper_tube_weight != null && fc.paper_tube_weight !== '' + ? formatWeightKg(fc.paper_tube_weight) + : null, + package_weight: fc.package_weight != null && fc.package_weight !== '' + ? formatWeightKg(fc.package_weight) + : null, }; } @@ -213,6 +252,16 @@ export function getEmptyScanDetail() { }; } +/** 刚扫细码的数量(公斤存储值):优先细码 weight */ +function pickScannedFineWeight(res) { + if (!res) return 0; + if (res.weight != null && res.weight !== '') return res.weight; + if (res.base_unit_weight != null && res.base_unit_weight !== '') return res.base_unit_weight; + if (res.settle_weight != null && res.settle_weight !== '') return res.settle_weight; + if (res.actually_weight != null && res.actually_weight !== '') return res.actually_weight; + return res.item_weight; +} + /** 从扫码接口返回构建详情区(匹数÷100,数量÷10000) */ export function buildScanDetailFromScanResponse(res) { if (!res) return getEmptyScanDetail(); @@ -225,16 +274,39 @@ export function buildScanDetailFromScanResponse(res) { order_roll: formatRoll(res.order_roll != null ? res.order_roll : res.total_roll), item_roll: formatRoll(res.item_roll != null ? res.item_roll : res.roll), order_weight: formatWeightKg(res.order_weight != null ? res.order_weight : res.total_weight), - item_weight: formatWeightKg(res.item_weight != null ? res.item_weight : res.weight), + // 本行数量:刚扫这条细码的重量(weight),不是明细行合计 + item_weight: formatWeightKg(pickScannedFineWeight(res)), }; } -/** 构建扫码请求参数 */ -export function buildScanUpdateParams({ id, scanCode, arrangeType, warehouseBinId }) { +/** 校验纸筒/包装重量(扫码时提交) */ +export function validateScanWeights(paperTubeWeight, packageWeight) { + if (paperTubeWeight === '' || paperTubeWeight == null) { + return '请输入纸筒重量'; + } + if (Number.isNaN(Number(paperTubeWeight))) return '纸筒重量格式不正确'; + if (packageWeight === '' || packageWeight == null) { + return '请输入包装重量'; + } + if (Number.isNaN(Number(packageWeight))) return '包装重量格式不正确'; + return ''; +} + +/** 构建扫码请求参数(纸筒/包装重量在扫码时提交,公斤值需 ×10000) */ +export function buildScanUpdateParams({ + id, + scanCode, + arrangeType, + warehouseBinId, + paperTubeWeight, + packageWeight, +}) { const code = (scanCode || '').trim(); const params = { id: Number(id), arrange_type: arrangeType, + paper_tube_weight: toWeightStorage(paperTubeWeight), + package_weight: toWeightStorage(packageWeight), }; if (warehouseBinId) { params.warehouse_bin_id = Number(warehouseBinId); @@ -326,6 +398,14 @@ export function orderToFormFields(order) { process_name: order.process_name, warehouse_id: order.warehouse_id, warehouse_name: order.warehouse_name, + sale_system_id: order.sale_system_id, + sale_system_name: order.sale_system_name, + in_order_type: order.in_order_type || IN_ORDER_TYPE_PROCESS, + in_order_type_name: order.in_order_type_name + || IN_ORDER_TYPE_MAP[order.in_order_type] + || IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_PROCESS], + paper_tube_weight: String(DEFAULT_PAPER_TUBE_WEIGHT), + package_weight: String(DEFAULT_PACKAGE_WEIGHT), remark: order.remark, item_data: order.item_data, }; diff --git a/src/components/storegoods/ProcessInDetailList.vue b/src/components/storegoods/ProcessInDetailList.vue index 107e403..6873253 100644 --- a/src/components/storegoods/ProcessInDetailList.vue +++ b/src/components/storegoods/ProcessInDetailList.vue @@ -89,19 +89,33 @@ const FINE_COLUMNS = [ { label: '缸号', key: 'dye_factory_dyelot_number', width: 140 }, ]; +const TARE_COLUMNS = [ + { label: '纸筒重量', key: 'paper_tube_weight', width: 120 }, + { label: '包装重量', key: 'package_weight', width: 120 }, +]; + export default { props: { list: { type: Array, default: () => [] }, title: { type: String, default: '进仓明细' }, deletable: { type: Boolean, default: false }, + /** 加工/采购进仓:细码行展示扫码时提交的纸筒、包装重量 */ + showTareColumns: { type: Boolean, default: false }, }, computed: { groups() { return buildItemGroups(this.list); }, fineColumns() { - if (!this.deletable) return FINE_COLUMNS; - return [...FINE_COLUMNS, { label: '操作', key: 'action', width: 90 }]; + const cols = [...FINE_COLUMNS]; + if (this.showTareColumns) { + const idx = cols.findIndex((col) => col.key === 'weight'); + cols.splice(idx + 1, 0, ...TARE_COLUMNS); + } + if (this.deletable) { + cols.push({ label: '操作', key: 'action', width: 90 }); + } + return cols; }, fineTableWidth() { const total = this.fineColumns.reduce((sum, col) => sum + (col.width || 100), 0); diff --git a/src/pages/storegoods/storeGoodsProcessInAdd.vue b/src/pages/storegoods/storeGoodsProcessInAdd.vue index 7461f8f..ab36052 100644 --- a/src/pages/storegoods/storeGoodsProcessInAdd.vue +++ b/src/pages/storegoods/storeGoodsProcessInAdd.vue @@ -6,9 +6,12 @@ 进仓单号 - - 进仓类型 - 加工进仓单 + + 进仓类型* + + {{ form.in_order_type_name || '请选择' }} + + 加工单位* @@ -24,6 +27,37 @@ + + + 纸筒重量 + + + + 包装重量 + + + + + 营销体系* + + {{ form.sale_system_name || '请选择' }} + + + 单据备注 @@ -57,6 +91,7 @@ @@ -95,6 +130,13 @@ export default { ProcessInBinBar, }, mixins: [formMixin], + data() { + return { + weightInputStyle: { + fontSize: '36rpx', + }, + }; + }, onLoad() { uni.setNavigationBarTitle({ title: '新增加工进仓单' }); this.pageMode = 'add'; @@ -109,4 +151,17 @@ page { background-color: #F8F8F8; padding-bottom: 260rpx; } +.process-in-weight-row { + gap: 20rpx; +} +.process-in-weight-col { + flex: 1; + display: flex; + align-items: center; + min-width: 0; + + ::v-deep .u-input__input { + font-size: 36rpx !important; + } +} diff --git a/src/pages/storegoods/storeGoodsProcessInEdit.vue b/src/pages/storegoods/storeGoodsProcessInEdit.vue index 3e15513..9614908 100644 --- a/src/pages/storegoods/storeGoodsProcessInEdit.vue +++ b/src/pages/storegoods/storeGoodsProcessInEdit.vue @@ -8,7 +8,7 @@ 进仓类型 - 加工进仓单 + {{ form.in_order_type_name || '加工进仓单' }} 加工单位 @@ -18,6 +18,34 @@ 仓库名称 {{ form.warehouse_name || '-' }} + + + 纸筒重量 + + + + 包装重量 + + + + + 营销体系 + {{ form.sale_system_name || '-' }} + 单据备注 {{ form.remark || '-' }} @@ -51,6 +79,7 @@ @@ -79,6 +108,13 @@ export default { ProcessInBinBar, }, mixins: [formMixin], + data() { + return { + weightInputStyle: { + fontSize: '36rpx', + }, + }; + }, onLoad(e) { uni.setNavigationBarTitle({ title: '编辑加工进仓单' }); this.pageMode = 'edit'; @@ -95,4 +131,17 @@ page { background-color: #F8F8F8; padding-bottom: 260rpx; } +.process-in-weight-row { + gap: 20rpx; +} +.process-in-weight-col { + flex: 1; + display: flex; + align-items: center; + min-width: 0; + + ::v-deep .u-input__input { + font-size: 36rpx !important; + } +} diff --git a/src/pages/storegoods/storeGoodsProcessInMixin.js b/src/pages/storegoods/storeGoodsProcessInMixin.js index 5a8650d..2e33303 100644 --- a/src/pages/storegoods/storeGoodsProcessInMixin.js +++ b/src/pages/storegoods/storeGoodsProcessInMixin.js @@ -1,9 +1,9 @@ /** * 加工进仓单表单 mixin(新增/编辑共用) * - * 1. 先填表头(加工单位 / 仓库 / 备注)提交 add,拿到 id 后可扫码 + * 1. 先填表头(进仓类型 / 加工单位 / 仓库 / 营销体系 / 备注)提交 add,拿到 id 后可扫码 * 2. 先扫仓位(getWarehouseBin:传 qr_code + warehouse_id),校验后扫布匹二维码 - * 3. 扫码走 updateFpmProcessInOrder(arrange_type: 1 录入 / 3 删除,带 warehouse_bin_id) + * 3. 扫码走 updateFpmProcessInOrder(arrange_type: 1 录入 / 3 删除,带 warehouse_bin_id、纸筒/包装重量) * 4. 手机扫码成功展示详情后自动再次调起扫码,形成连续扫 */ import util from '@/common/util'; @@ -15,6 +15,10 @@ import { BUSINESS_UNIT_TYPE_PROCESS, WAREHOUSE_TYPE_FINISHED, IN_ORDER_TYPE_PROCESS, + IN_ORDER_TYPE_MAP, + IN_ORDER_TYPE_OPTIONS, + DEFAULT_PAPER_TUBE_WEIGHT, + DEFAULT_PACKAGE_WEIGHT, normalizeOrder, mapToSelectOptions, canScanAtStatus, @@ -28,6 +32,7 @@ import { buildScanDetailFromScanResponse, buildScanUpdateParams, pickDefaultWarehouse, + validateScanWeights, } from '@/common/storeGoodsProcessIn'; export default { @@ -49,6 +54,8 @@ export default { auditStatus: 0, processUnitOptions: [], warehouseOptions: [], + saleSystemOptions: [], + inOrderTypeOptions: IN_ORDER_TYPE_OPTIONS, dropdownLoading: false, /** 仓位 */ warehouseBinId: 0, @@ -70,6 +77,10 @@ export default { headerEditable() { return this.pageMode === 'add' && !this.headerSaved; }, + /** 纸筒/包装重量随扫码提交,保存前后及可扫编辑态均可改 */ + canEditWeights() { + return this.isEditable && (this.headerEditable || this.canScan); + }, statusActionButtons() { return getFormStatusActionButtons(this.headerSaved, this.orderId, this.auditStatus); }, @@ -243,6 +254,7 @@ export default { loadBaseDropdowns() { if (this.dropdownLoading) return Promise.resolve(); this.dropdownLoading = true; + if (this.headerEditable) this.applyDefaultSaleSystem(); return Promise.all([ this.ensureProcessUnitOptions().catch((e) => { console.error('加载加工单位失败', e); @@ -252,6 +264,10 @@ export default { console.error('加载仓库失败', e); return []; }), + this.ensureSaleSystemOptions().catch((e) => { + console.error('加载营销体系失败', e); + return []; + }), ]).finally(() => { this.dropdownLoading = false; }); @@ -275,6 +291,15 @@ export default { return this.warehouseOptions; }); }, + ensureSaleSystemOptions() { + if (this.saleSystemOptions.length) return Promise.resolve(this.saleSystemOptions); + return this.$u.api.saleSystem.getDropdownList() + .then((res) => { + this.saleSystemOptions = mapToSelectOptions(res); + if (this.headerEditable) this.applyDefaultSaleSystem(); + return this.saleSystemOptions; + }); + }, applyDefaultWarehouse() { const app = getApp(); const picked = pickDefaultWarehouse( @@ -286,13 +311,42 @@ export default { this.form.warehouse_id = picked.value; this.form.warehouse_name = picked.label; }, + applyDefaultSaleSystem() { + if (this.form.sale_system_id) { + if (!this.form.sale_system_name && this.saleSystemOptions.length) { + const found = this.saleSystemOptions.find( + (item) => String(item.value) === String(this.form.sale_system_id), + ); + if (found) this.form.sale_system_name = found.label; + } + return; + } + const app = getApp(); + const gd = app && app.globalData ? app.globalData : {}; + const id = gd.PlanDepartmentID; + if (!id) return; + this.form.sale_system_id = id; + this.form.sale_system_name = gd.PlanDepartmentName || ''; + if (!this.form.sale_system_name && this.saleSystemOptions.length) { + const found = this.saleSystemOptions.find((item) => String(item.value) === String(id)); + if (found) this.form.sale_system_name = found.label; + } + }, getEmptyForm() { + const app = getApp(); + const gd = app && app.globalData ? app.globalData : {}; return { order_no: '', process_unit_id: '', process_name: '', warehouse_id: '', warehouse_name: '', + sale_system_id: gd.PlanDepartmentID || '', + sale_system_name: gd.PlanDepartmentName || '', + in_order_type: IN_ORDER_TYPE_PROCESS, + in_order_type_name: IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_PROCESS], + paper_tube_weight: String(DEFAULT_PAPER_TUBE_WEIGHT), + package_weight: String(DEFAULT_PACKAGE_WEIGHT), remark: '', item_data: [], }; @@ -336,7 +390,9 @@ export default { this.selectList = list; this.selectShow = true; }; - if (type === '加工单位') { + if (type === '进仓类型') { + openPicker(this.inOrderTypeOptions); + } else if (type === '加工单位') { this.ensureProcessUnitOptions() .then(openPicker) .catch((e) => this.showError(e.message || '加载加工单位失败')); @@ -344,33 +400,41 @@ export default { this.ensureWarehouseOptions() .then(openPicker) .catch((e) => this.showError(e.message || '加载仓库失败')); + } else if (type === '营销体系') { + this.ensureSaleSystemOptions() + .then(openPicker) + .catch((e) => this.showError(e.message || '加载营销体系失败')); } }, selectConfirmFun(e) { const item = e[0]; - if (this.selectType === '加工单位') { + if (this.selectType === '进仓类型') { + this.form.in_order_type = item.value; + this.form.in_order_type_name = item.label; + } else if (this.selectType === '加工单位') { this.form.process_unit_id = item.value; this.form.process_name = item.label; } else if (this.selectType === '仓库名称') { this.form.warehouse_id = item.value; this.form.warehouse_name = item.label; + } else if (this.selectType === '营销体系') { + this.form.sale_system_id = item.value; + this.form.sale_system_name = item.label; } }, validateForm() { + if (!this.form.in_order_type) return '请选择进仓类型'; if (!this.form.process_unit_id) return '请选择加工单位'; if (!this.form.warehouse_id) return '请选择仓库名称'; - const app = getApp(); - const saleSystemId = app && app.globalData ? app.globalData.PlanDepartmentID : ''; - if (!saleSystemId) return '缺少营销体系,请重新登录'; + if (!this.form.sale_system_id) return '请选择营销体系'; return ''; }, buildAddParam() { - const app = getApp(); return { - inOrderType: IN_ORDER_TYPE_PROCESS, + inOrderType: Number(this.form.in_order_type), process_unit_id: Number(this.form.process_unit_id), warehouse_id: Number(this.form.warehouse_id), - sale_system_id: Number(app.globalData.PlanDepartmentID), + sale_system_id: Number(this.form.sale_system_id), remark: this.form.remark || '', item_data: [], }; @@ -397,7 +461,7 @@ export default { .then((detail) => { uni.hideLoading(); const order = normalizeOrder(detail); - this.applyOrder(order); + this.applyOrder(order, { keepWeights: true }); this.headerSaved = true; this.clearWarehouseBin(); this.syncCanScanFromStatus(order.audit_status); @@ -409,10 +473,16 @@ export default { this.showError(e.message || '保存失败'); }); }, - applyOrder(order) { + applyOrder(order, options = {}) { if (!order) return; this.auditStatus = order.audit_status; + const paperTubeWeight = this.form.paper_tube_weight; + const packageWeight = this.form.package_weight; Object.assign(this.form, orderToFormFields(order)); + if (options.keepWeights) { + this.form.paper_tube_weight = paperTubeWeight; + this.form.package_weight = packageWeight; + } }, handleScan(options = {}) { const fromPhone = !!options.fromPhone; @@ -444,7 +514,13 @@ export default { }, getFineCodeScanCode(fineCode) { if (!fineCode) return ''; - return fineCode.qr_code || fineCode.scan_code || fineCode.bar_code || ''; + return fineCode.qr_code + || fineCode.long_code + || fineCode.scan_code + || fineCode.digital_code + || fineCode.bar_code + || fineCode.short_code + || ''; }, onDeleteFineCode(fineCode) { if (!this.canScan || !this.orderId) { @@ -468,6 +544,15 @@ export default { doScanUpdate(scanCode, arrangeType, options = {}) { const { fromPhone = false } = options; const isDelete = arrangeType === ARRANGE_TYPE.DEL; + if (!isDelete) { + const weightErr = validateScanWeights(this.form.paper_tube_weight, this.form.package_weight); + if (weightErr) { + this.showError(weightErr); + this.QRBarCode = ''; + this.phoneContinuousScan = false; + return; + } + } uni.showLoading({ title: isDelete ? '删除中...' : '处理中...' }); return this.$u.api.fpmProcessInOrder.scanUpdate(buildScanUpdateParams({ id: this.orderId, @@ -475,6 +560,8 @@ export default { arrangeType, // 删除不强制仓位;录入带当前仓位 warehouseBinId: isDelete ? 0 : this.warehouseBinId, + paperTubeWeight: this.form.paper_tube_weight, + packageWeight: this.form.package_weight, })) .then((scanRes) => { this.scanDetail = buildScanDetailFromScanResponse(scanRes); diff --git a/src/pages/storegoods/storeGoodsProcessInView.vue b/src/pages/storegoods/storeGoodsProcessInView.vue index 0835625..17b69f2 100644 --- a/src/pages/storegoods/storeGoodsProcessInView.vue +++ b/src/pages/storegoods/storeGoodsProcessInView.vue @@ -18,6 +18,20 @@ 仓库名称 {{ order.warehouse_name || '-' }} + + + 纸筒重量 + {{ order.paper_tube_weight != null ? order.paper_tube_weight : '-' }} + + + 包装重量 + {{ order.package_weight != null ? order.package_weight : '-' }} + + + + 营销体系 + {{ order.sale_system_name || '-' }} + 单据备注 {{ order.remark || '-' }} @@ -34,6 +48,7 @@ @@ -126,4 +141,13 @@ page { background-color: #F8F8F8; padding-bottom: 260rpx; } +.process-in-weight-row { + gap: 20rpx; +} +.process-in-weight-col { + flex: 1; + display: flex; + align-items: center; + min-width: 0; +}