/** * 坯布出仓单(其他出货单)表单 mixin(新增/编辑共用) * * 业务说明: * 1. 后端当前仅提供「坯布其他出货单」一种类型的接口,故出仓类型固定为 other, * 表头保留接收单位(business_unit) / 出货日期 / 备注 等字段。 * 2. 用户先填写表头并「提交保存」(addGfmOtherDeliveryOrder),拿到出仓单 id 后即可扫码; * 扫码新增/删除细码走 updateGfmOtherDeliveryOrder;勾选锁定维度时附带 *_lock 字段,操作后用返回的最新详情刷新。 * 3. 后端没有「修改表头」接口,保存成功或编辑进入后表头变为只读,仅可扫码维护细码。 */ import util from '@/common/util'; import scanMixin from '@/common/scanMixin.js'; import { AUDIT_STATUS_MAP, BILL_TYPES, normalizeOrder, mapToSelectOptions, getFineCodeScanCode, canScanAtStatus, isLockedOrderStatus, getFormStatusActionButtons, orderToFormFields, confirmOrderStatusAction, DRAFT_AUDIT_STATUS, DRAFT_AUDIT_STATUS_NAME, getEmptyScanDetail, findScanContext, buildScanDetailFromContext, buildScanDetailFromOrderResponse, buildScanUpdateParams, getOrderDisplayWeight, getFineCodeDisplayWeight, } from '@/common/storeFabricBusinessOut'; export default { mixins: [scanMixin], data() { return { pageMode: 'add', orderId: 0, form: this.getEmptyForm(), headerSaved: false, selectShow: false, selectList: [], selectType: '', canScan: false, QRBarCode: '', BarCodeDelStatus: false, BillDataMessage: '', currentScanItem: null, fabricInfoShow: false, fineCodeShow: false, currentFabricInfo: {}, currentFineCodes: [], currentGroupKey: '', scanDetail: getEmptyScanDetail(), scanGroupKeys: [], lastScanCode: '', billTypeName: (BILL_TYPES[0] || {}).label || '坯布其他出货单', auditStatus: 0, businessUnitOptions: [], dropdownLoading: false, }; }, computed: { isReadonly() { return this.pageMode === 'view'; }, isEditable() { return this.pageMode === 'add' || this.pageMode === 'edit'; }, // 表头是否可编辑:仅新增且未保存时可编辑(后端无修改表头接口) headerEditable() { return this.pageMode === 'add' && !this.headerSaved; }, dateLabel() { return '出货日期'; }, /** 表头保存后,待审核/已驳回状态下显示审核、作废 */ statusActionButtons() { return getFormStatusActionButtons(this.headerSaved, this.orderId, this.auditStatus); }, displayAuditStatus() { if (this.pageMode === 'add' && !this.headerSaved) return DRAFT_AUDIT_STATUS; return this.auditStatus; }, displayAuditStatusName() { if (this.pageMode === 'add' && !this.headerSaved) return DRAFT_AUDIT_STATUS_NAME; return AUDIT_STATUS_MAP[this.auditStatus] || ''; }, }, onShow() { this.isPageActive = true; // #ifdef APP-PLUS if (this.canScan && this.isEditable) { this.registerScanBroadcast((scanResult) => { this.QRBarCode = scanResult.trim().replace(/[\r\n]/g, ''); this.$nextTick(() => this.handleScan()); }); } // #endif }, onHide() { this.isPageActive = false; // #ifdef APP-PLUS this.unregisterScanBroadcast(); // #endif }, onUnload() { this.isPageActive = false; // #ifdef APP-PLUS this.unregisterScanBroadcast(); // #endif }, methods: { registerOrderScanBroadcast() { // #ifdef APP-PLUS this.registerScanBroadcast((scanResult) => { this.QRBarCode = scanResult.trim().replace(/[\r\n]/g, ''); this.$nextTick(() => this.handleScan()); }); // #endif }, syncCanScanFromStatus(status) { const nextCanScan = this.isEditable && canScanAtStatus(status); if (this.canScan && !nextCanScan) { // #ifdef APP-PLUS this.unregisterScanBroadcast(); // #endif } this.canScan = nextCanScan; }, loadBaseDropdowns() { if (this.dropdownLoading) return Promise.resolve(); if (this.businessUnitOptions.length) { return Promise.resolve(); } this.dropdownLoading = true; return this.ensureBusinessUnitOptions().finally(() => { this.dropdownLoading = false; }); }, ensureBusinessUnitOptions() { if (this.businessUnitOptions.length) return Promise.resolve(this.businessUnitOptions); return this.$u.api.businessUnit.list({}) .then((res) => { this.businessUnitOptions = mapToSelectOptions(res); return this.businessUnitOptions; }); }, getEmptyForm() { return { order_no: '', business_unit_id: '', business_unit_name: '', delivery_time: this.$u.timeFormat(new Date(), 'yyyy-mm-dd'), remark: '', item_data: [], }; }, loadOrder(id, options = {}) { const { rejectIfLocked = false } = options; return this.$u.api.gfmOtherDeliveryOrder.detail({ id }) .then((res) => { const order = normalizeOrder(res); if (!order) { this.showError('单据不存在'); return null; } if (rejectIfLocked && isLockedOrderStatus(order.audit_status)) { this.showError('当前状态不可编辑'); setTimeout(() => uni.navigateBack(), 1500); return null; } this.orderId = order.id; this.auditStatus = order.audit_status; this.headerSaved = true; this.form = orderToFormFields(order); this.refreshScanDetailTotals(order); this.syncCanScanFromStatus(order.audit_status); if (this.canScan) this.registerOrderScanBroadcast(); return order; }) .catch((e) => { this.showError(e.message || '加载单据失败'); return null; }); }, pickerSelectFun(type) { if (!this.headerEditable) return; this.selectType = type; const openPicker = (list) => { if (!list.length) { this.showError('暂无可选数据'); return; } this.selectList = list; this.selectShow = true; }; if (type === '接收单位') { this.ensureBusinessUnitOptions() .then(openPicker) .catch((e) => this.showError(e.message || '加载单位列表失败')); } }, selectConfirmFun(e) { const item = e[0]; if (this.selectType === '接收单位') { this.form.business_unit_id = item.value; this.form.business_unit_name = item.label; } }, bindDateChange(e) { this.form.delivery_time = e.detail.value; }, validateForm() { if (!this.form.business_unit_id) return '请选择接收单位'; if (!this.form.delivery_time) return '请选择出货日期'; return ''; }, buildAddParam() { return { business_unit_id: Number(this.form.business_unit_id), delivery_time: this.form.delivery_time, remark: this.form.remark || '', }; }, submitSave() { if (this.headerSaved) { this.showError('表头已保存,请直接扫码维护细码'); return; } const err = this.validateForm(); if (err) { this.showError(err); return; } uni.showLoading({ title: '保存中...' }); this.$u.api.gfmOtherDeliveryOrder.add(this.buildAddParam()) .then((res) => { this.orderId = (res && res.id) || 0; if (!this.orderId) { throw new Error('保存失败,未返回单据ID'); } return this.$u.api.gfmOtherDeliveryOrder.detail({ id: this.orderId }); }) .then((detail) => { uni.hideLoading(); const order = normalizeOrder(detail); this.applyOrder(order); this.headerSaved = true; this.syncCanScanFromStatus(order.audit_status); this.showSuccess('保存成功,可以扫码'); this.registerOrderScanBroadcast(); }) .catch((e) => { uni.hideLoading(); this.showError(e.message || '保存失败'); }); }, applyOrder(order) { if (!order) return; this.auditStatus = order.audit_status; Object.assign(this.form, orderToFormFields(order)); this.refreshScanDetailTotals(order); }, refreshScanDetailTotals(order) { this.scanDetail = { ...this.scanDetail, total_roll: order.total_roll ?? 0, total_weight: getOrderDisplayWeight(order), }; }, applyScanDetail(scanCode, order, scanType) { const fromResponse = buildScanDetailFromOrderResponse(order); if (fromResponse) { const context = findScanContext(order.item_data, scanCode); if (context) { fromResponse.weight = getFineCodeDisplayWeight(context.fineCode); } this.scanDetail = fromResponse; if (scanType !== 2) this.lastScanCode = scanCode; else if (this.lastScanCode === scanCode) this.lastScanCode = ''; return; } const context = findScanContext(order.item_data, scanCode); if (context) { this.scanDetail = buildScanDetailFromContext(context, order); this.lastScanCode = scanCode; return; } if (scanType === 2 && this.lastScanCode === scanCode) { this.scanDetail = { ...getEmptyScanDetail(), total_roll: order.total_roll ?? 0, total_weight: getOrderDisplayWeight(order), }; this.lastScanCode = ''; return; } this.refreshScanDetailTotals(order); }, handleScan() { const code = (this.QRBarCode || '').trim(); if (!this.canScan || !this.orderId) { this.showError('请先提交保存后再扫码'); this.QRBarCode = ''; return; } if (!code) { this.QRBarCode = ''; return; } const scanType = this.BarCodeDelStatus ? 2 : 1; this.doScanUpdate(code, scanType); }, BarCodeDelChange(e) { this.BarCodeDelStatus = (e.detail.value || []).length > 0; }, /** 扫码新增/删除细码,统一走 scanUpdate 接口 */ doScanUpdate(scanCode, scanType, options = {}) { const { refreshFineCodes = false } = options; uni.showLoading({ title: scanType === 2 ? '删除中...' : '处理中...' }); return this.$u.api.gfmOtherDeliveryOrder.scanUpdate(buildScanUpdateParams({ id: this.orderId, scanCode, scanType, groupKeys: this.scanGroupKeys, detail: this.scanDetail, })) .then((detail) => { uni.hideLoading(); const order = normalizeOrder(detail); this.form.item_data = order.item_data; this.auditStatus = order.audit_status; this.applyScanDetail(scanCode, order, scanType); if (refreshFineCodes) { const row = order.item_data.find((i) => (i.group_key || String(i.id)) === this.currentGroupKey); this.currentFineCodes = row ? [...row.fine_codes] : []; } this.BillDataMessage = scanType === 2 ? '删除成功' : '扫描成功'; this.QRBarCode = ''; if (scanType === 2) this.showSuccess('删除成功'); else util.playSuccessAudio(); }) .catch((e) => { uni.hideLoading(); this.showError(e.message || (scanType === 2 ? '删除失败' : '扫码失败')); this.QRBarCode = ''; }); }, openFabricInfo(row) { this.currentFabricInfo = { ...row }; this.fabricInfoShow = true; }, openFineCode(row) { this.currentGroupKey = row.group_key || String(row.id); this.currentFineCodes = [...(row.fine_codes || [])]; this.fineCodeShow = true; }, onDeleteFineCode(fineCode) { if (this.isReadonly || !this.canScan) return; const scanCode = getFineCodeScanCode(fineCode); if (!scanCode) { this.showError('该细码缺少条码,无法删除'); return; } uni.showModal({ title: '提示', content: `确认删除细码 ${scanCode}?`, success: (res) => { if (!res.confirm) return; this.doScanUpdate(scanCode, 2, { refreshFineCodes: true }); }, }); }, handleStatusAction(action) { confirmOrderStatusAction(this, { orderId: this.orderId, action, onSuccess: () => this.$u.api.gfmOtherDeliveryOrder.detail({ id: this.orderId }) .then((detail) => { uni.hideLoading(); const order = normalizeOrder(detail); if (!order) return; this.applyOrder(order); this.syncCanScanFromStatus(order.audit_status); this.showSuccess('操作成功'); }), }); }, showError(message) { util.playErrorAudio(); uni.showModal({ title: '提示', content: message, showCancel: false }); }, showSuccess(message) { util.playSuccessAudio(); uni.showToast({ title: message, icon: 'success' }); }, getBillTypeName() { return this.billTypeName; }, }, };