diff --git a/src/common/storeFabricBusinessOut.js b/src/common/storeFabricBusinessOut.js index 7998ab0..4b23c2b 100644 --- a/src/common/storeFabricBusinessOut.js +++ b/src/common/storeFabricBusinessOut.js @@ -61,6 +61,12 @@ export const STATUS_ACTION_CONFIG = { unapprove: { status: AUDIT_STATUS.PENDING, msg: '确认消审该单据?', apiKey: 'statusWait' }, }; +/** 审核 / 作废成功后播放的语音文案 */ +export const STATUS_ACTION_VOICE = { + approve: '审核成功', + void: '作废成功', +}; + // 出仓类型:当前后端仅提供「坯布其他出货单」一种类型的接口 export const BILL_TYPES = [ { value: 'other', label: '坯布其他出货单' }, @@ -147,17 +153,7 @@ export function normalizeOrder(order) { }; } -/** 扫码详情区表格列 */ -export const SCAN_DETAIL_TABLE_COLUMNS = [ - { label: '坯布编号', key: 'grey_fabric_code', width: 140 }, - { label: '坯布名称', key: 'grey_fabric_name', width: 140 }, - { label: '纱批', key: 'yarn_batch', width: 120 }, - { label: '机号', key: 'machine_number', width: 100 }, - { label: '条数', key: 'roll', width: 80 }, - { label: '重量', key: 'weight', width: 100 }, -]; - -/** 扫码详情区汇总维度(勾选后参与表格分组;带 lock 的维度会随扫码请求传给后端) */ +/** 扫码详情区汇总维度(勾选后随扫码请求把对应 lock 字段传给后端) */ export const SCAN_GROUP_OPTIONS = [ { key: 'produce_order_no', label: '合同' }, { key: 'grey_fabric_code', label: '布编' }, @@ -300,56 +296,6 @@ export function buildScanDetailFromContext(context, order) { }; } -function aggregateScanTableRows(rows, keys) { - const map = new Map(); - rows.forEach((row) => { - const groupId = keys.map((k) => row[k] || '').join('|'); - const existing = map.get(groupId); - if (!existing) { - map.set(groupId, { ...row, roll: 0, raw_weight: 0 }); - } - const agg = map.get(groupId); - agg.roll = Number((agg.roll + Number(row.roll || 0)).toFixed(2)); - agg.raw_weight = Number(agg.raw_weight || 0) + Number(row.raw_weight || 0); - }); - return Array.from(map.values()).map((row) => ({ - ...row, - weight: formatWeightKg(row.raw_weight), - })); -} - -/** 构建扫码详情区汇总表格数据 */ -export function buildScanDetailTableRows(itemData, groupKeys = []) { - const rows = []; - (itemData || []).forEach((item) => { - (item.fine_codes || []).forEach((fc) => { - rows.push({ - customer_name: item.customer_name || '', - produce_order_no: item.produce_order_no || item.contract_no || '', - grey_fabric_code: item.grey_fabric_code || '', - grey_fabric_name: item.grey_fabric_name || '', - yarn_batch: item.yarn_batch || '', - machine_number: item.machine_number || '', - volume_number: fc.roll_no || fc.fabric_piece_code || '', - grey_fabric_level_name: item.grey_fabric_level_name || '', - roll: fc.roll || 0, - raw_weight: fc.raw_weight != null ? fc.raw_weight : 0, - }); - }); - }); - if (!rows.length) return []; - const keys = (groupKeys || []).filter(Boolean); - if (!keys.length) { - return aggregateScanTableRows(rows, ['grey_fabric_code', 'grey_fabric_name', 'yarn_batch', 'machine_number']); - } - return aggregateScanTableRows(rows, keys); -} - -export function getScanDetailTableWidth(columns) { - const total = (columns || []).reduce((sum, col) => sum + (col.width || 120), 0); - return `${total}rpx`; -} - export function normalizeItem(item) { const machineStockRaw = item.machine_stock_roll ?? item.machine_stock ?? item.machine_inventory_roll; return { diff --git a/src/common/util.js b/src/common/util.js index f245774..579ee8f 100644 --- a/src/common/util.js +++ b/src/common/util.js @@ -366,6 +366,56 @@ function playErrorAudio() { errorAudio.play(); } +// 坯布出仓等业务的固定中文提示语音 +const SPEAK_AUDIO = { + '扫码出仓成功': '/static/audio/scan_out_ok.mp3', + '删除成功': '/static/audio/delete_ok.mp3', + '提交成功': '/static/audio/submit_ok.mp3', + '审核成功': '/static/audio/audit_ok.mp3', + '作废成功': '/static/audio/void_ok.mp3', +}; + +const speakAudioMap = {}; + +function stopOtherSpeak(exceptText) { + Object.keys(speakAudioMap).forEach((key) => { + if (key === exceptText || !speakAudioMap[key]) return; + try { + speakAudioMap[key].stop(); + } catch (e) {} + }); + if (successAudio) { + try { + successAudio.stop(); + } catch (e) {} + } +} + +function playSpeak(text) { + const src = SPEAK_AUDIO[text]; + if (!src) return; + stopOtherSpeak(text); + const prev = speakAudioMap[text]; + if (prev) { + try { + prev.stop(); + prev.destroy(); + } catch (e) {} + speakAudioMap[text] = undefined; + } + const audio = uni.createInnerAudioContext(); + audio.autoplay = true; + audio.src = src; + audio.onError((res) => { + console.log('语音播放失败', text, res && res.errMsg); + try { + audio.destroy(); + } catch (e) {} + if (speakAudioMap[text] === audio) speakAudioMap[text] = undefined; + }); + speakAudioMap[text] = audio; +} + export default { get apiurl() { @@ -378,4 +428,5 @@ export default { parGetData, playSuccessAudio, playErrorAudio, + playSpeak, }; diff --git a/src/components/storefabric/FabricOutDetailList.vue b/src/components/storefabric/FabricOutDetailList.vue index a4f5529..ac1fe5e 100644 --- a/src/components/storefabric/FabricOutDetailList.vue +++ b/src/components/storefabric/FabricOutDetailList.vue @@ -1,6 +1,6 @@ diff --git a/src/pages/storefabric/storeFabricBusinessOutAdd.vue b/src/pages/storefabric/storeFabricBusinessOutAdd.vue index 2033118..f4a5b83 100644 --- a/src/pages/storefabric/storeFabricBusinessOutAdd.vue +++ b/src/pages/storefabric/storeFabricBusinessOutAdd.vue @@ -89,7 +89,6 @@ diff --git a/src/pages/storefabric/storeFabricBusinessOutEdit.vue b/src/pages/storefabric/storeFabricBusinessOutEdit.vue index dc1ffbc..e3c1f0e 100644 --- a/src/pages/storefabric/storeFabricBusinessOutEdit.vue +++ b/src/pages/storefabric/storeFabricBusinessOutEdit.vue @@ -43,7 +43,6 @@ diff --git a/src/pages/storefabric/storeFabricBusinessOutMixin.js b/src/pages/storefabric/storeFabricBusinessOutMixin.js index 90a3ce8..d380848 100644 --- a/src/pages/storefabric/storeFabricBusinessOutMixin.js +++ b/src/pages/storefabric/storeFabricBusinessOutMixin.js @@ -22,6 +22,7 @@ import { getFormStatusActionButtons, orderToFormFields, confirmOrderStatusAction, + STATUS_ACTION_VOICE, DRAFT_AUDIT_STATUS, DRAFT_AUDIT_STATUS_NAME, getEmptyScanDetail, @@ -242,7 +243,7 @@ export default { this.applyOrder(order); this.headerSaved = true; this.syncCanScanFromStatus(order.audit_status); - this.showSuccess('保存成功,可以扫码'); + this.showSuccess('保存成功,可以扫码', '提交成功'); this.registerOrderScanBroadcast(); }) .catch((e) => { @@ -330,10 +331,10 @@ export default { 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.BillDataMessage = scanType === 2 ? '删除成功' : '扫码出仓成功'; this.QRBarCode = ''; - if (scanType === 2) this.showSuccess('删除成功'); - else util.playSuccessAudio(); + if (scanType === 2) this.showSuccess('删除成功', '删除成功'); + else util.playSpeak('扫码出仓成功'); }) .catch((e) => { uni.hideLoading(); @@ -377,7 +378,8 @@ export default { if (!order) return; this.applyOrder(order); this.syncCanScanFromStatus(order.audit_status); - this.showSuccess('操作成功'); + const voice = STATUS_ACTION_VOICE[action] || ''; + this.showSuccess(voice || '操作成功', voice); }), }); }, @@ -385,8 +387,9 @@ export default { util.playErrorAudio(); uni.showModal({ title: '提示', content: message, showCancel: false }); }, - showSuccess(message) { - util.playSuccessAudio(); + showSuccess(message, speakText) { + if (speakText) util.playSpeak(speakText); + else util.playSuccessAudio(); uni.showToast({ title: message, icon: 'success' }); }, getBillTypeName() { diff --git a/src/pages/storefabric/storeFabricBusinessOutPage.scss b/src/pages/storefabric/storeFabricBusinessOutPage.scss index 2071f27..7b50b23 100644 --- a/src/pages/storefabric/storeFabricBusinessOutPage.scss +++ b/src/pages/storefabric/storeFabricBusinessOutPage.scss @@ -125,34 +125,6 @@ color: #333; word-break: break-all; } -.fabric-out-scanDetailTableScroll { - width: 100%; -} -.fabric-out-scanDetailTable { - min-width: 100%; -} -.fabric-out-scanDetailTableRow { - display: flex; - border-bottom: 1rpx solid #f0f0f0; -} -.fabric-out-scanDetailTableHead { - background: #f5f5f5; - font-weight: bold; -} -.fabric-out-scanDetailTableCell { - padding: 14rpx 8rpx; - font-size: 32rpx; - color: #333; - text-align: center; - box-sizing: border-box; - word-break: break-all; -} -.fabric-out-scanDetailEmpty { - padding: 24rpx; - text-align: center; - font-size: 36rpx; - color: #999; -} .fabric-out-submitView { width: 100%; padding: 16rpx 26rpx 26rpx; diff --git a/src/pages/storefabric/storeFabricBusinessOutView.vue b/src/pages/storefabric/storeFabricBusinessOutView.vue index 8e913bd..a437859 100644 --- a/src/pages/storefabric/storeFabricBusinessOutView.vue +++ b/src/pages/storefabric/storeFabricBusinessOutView.vue @@ -53,6 +53,7 @@ import { getViewStatusActionButtons, confirmOrderStatusAction, formatDisplayTime, + STATUS_ACTION_VOICE, } from '@/common/storeFabricBusinessOut'; export default { @@ -123,8 +124,10 @@ export default { uni.hideLoading(); const order = normalizeOrder(res); if (order) this.order = order; - util.playSuccessAudio(); - uni.showToast({ title: '操作成功', icon: 'success' }); + const voice = STATUS_ACTION_VOICE[action] || ''; + if (voice) util.playSpeak(voice); + else util.playSuccessAudio(); + uni.showToast({ title: voice || '操作成功', icon: 'success' }); }), }); }, diff --git a/src/static/audio/audit_ok.mp3 b/src/static/audio/audit_ok.mp3 new file mode 100644 index 0000000..126d1bc Binary files /dev/null and b/src/static/audio/audit_ok.mp3 differ diff --git a/src/static/audio/delete_ok.mp3 b/src/static/audio/delete_ok.mp3 new file mode 100644 index 0000000..21ac1c8 Binary files /dev/null and b/src/static/audio/delete_ok.mp3 differ diff --git a/src/static/audio/scan_out_ok.mp3 b/src/static/audio/scan_out_ok.mp3 new file mode 100644 index 0000000..a4a9abb Binary files /dev/null and b/src/static/audio/scan_out_ok.mp3 differ diff --git a/src/static/audio/submit_ok.mp3 b/src/static/audio/submit_ok.mp3 new file mode 100644 index 0000000..0446ead Binary files /dev/null and b/src/static/audio/submit_ok.mp3 differ diff --git a/src/static/audio/void_ok.mp3 b/src/static/audio/void_ok.mp3 new file mode 100644 index 0000000..42eef6f Binary files /dev/null and b/src/static/audio/void_ok.mp3 differ