feat: 坯布出仓增加操作语音并精简扫码明细
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user