修正上传文件名
This commit is contained in:
@@ -401,7 +401,7 @@ export default {
|
||||
this.stopRecordingTicker();
|
||||
const tempFilePath = res.tempFilePath || '';
|
||||
if (ctx && ctx.id) {
|
||||
const name = `service_record_${ctx.id}_${Date.now()}_part${normalizedSegmentNo}.mp3`;
|
||||
const name = this.getAudioUploadFileName({ segmentNo: normalizedSegmentNo });
|
||||
if (!tempFilePath) {
|
||||
this.pushUploadResult(String(ctx.id), {
|
||||
id: `seg_${String(ctx.id)}_${normalizedSegmentNo}_${Date.now()}`,
|
||||
@@ -1035,10 +1035,88 @@ export default {
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
/** 上传音频文件名:租户id_手机号_年月日时分秒(租户id、手机号后各有一个下划线;多段录音段号>1 时末尾再追加 _段号) */
|
||||
getAudioUploadFileName(options = {}) {
|
||||
let tenantId = '';
|
||||
let phone = '';
|
||||
try {
|
||||
tenantId = String(uni.getStorageSync('backend-tenant-id') || '').trim();
|
||||
} catch (e) {}
|
||||
try {
|
||||
const raw = this.currentUserPhone || '';
|
||||
const login = uni.getStorageSync('backend-login-response') || {};
|
||||
const fallback = login.phone || login.userName || '';
|
||||
phone = String(raw || fallback || '').replace(/\D/g, '');
|
||||
} catch (e) {}
|
||||
const d = new Date();
|
||||
const pad = (n) => String(n).padStart(2, '0');
|
||||
const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
||||
const seg = Number(options.segmentNo);
|
||||
const segSuffix = Number.isFinite(seg) && seg > 1 ? `_${seg}` : '';
|
||||
const ext = typeof options.ext === 'string' && options.ext ? options.ext : '.mp3';
|
||||
const dotExt = ext.startsWith('.') ? ext : `.${ext}`;
|
||||
const tenantPrefix = tenantId ? `${tenantId}_` : '';
|
||||
const phonePrefix = phone ? `${phone}_` : '';
|
||||
const base = `${tenantPrefix}${phonePrefix}${ts}${segSuffix}`.replace(/[/\\:*?"<>|]/g, '_') || `upload_${ts}${segSuffix}`;
|
||||
return `${base}${dotExt}`;
|
||||
},
|
||||
/**
|
||||
* 微信小程序等环境下 multipart 的原始文件名来自本地路径最后一段;临时路径常为随机串甚至带异常后缀。
|
||||
* 复制到 USER_DATA_PATH 并使用规范文件名再上传,后端 getOriginalFilename / 落盘名才能与 fileName 参数一致。
|
||||
*/
|
||||
prepareAudioFileForUpload(tempPath, displayFileName) {
|
||||
return new Promise((resolve) => {
|
||||
if (!tempPath || !displayFileName) {
|
||||
resolve({ uploadPath: tempPath, tempCopyPath: null });
|
||||
return;
|
||||
}
|
||||
const baseName = (() => {
|
||||
const seg = String(tempPath).split(/[/\\]/).pop() || '';
|
||||
return seg.split('?')[0] || '';
|
||||
})();
|
||||
const needsRename =
|
||||
baseName !== displayFileName ||
|
||||
baseName.includes('=') ||
|
||||
/\.durationTime=/i.test(baseName);
|
||||
let userDataPath = '';
|
||||
try {
|
||||
userDataPath = (uni.env && uni.env.USER_DATA_PATH) || '';
|
||||
} catch (e) {}
|
||||
if (!userDataPath && typeof wx !== 'undefined' && wx.env) {
|
||||
userDataPath = wx.env.USER_DATA_PATH || '';
|
||||
}
|
||||
if (!needsRename || !userDataPath || typeof uni.getFileSystemManager !== 'function') {
|
||||
resolve({ uploadPath: tempPath, tempCopyPath: null });
|
||||
return;
|
||||
}
|
||||
const destPath = `${String(userDataPath).replace(/\/+$/, '')}/${displayFileName}`;
|
||||
uni.getFileSystemManager().copyFile({
|
||||
srcPath: tempPath,
|
||||
destPath,
|
||||
success: () => resolve({ uploadPath: destPath, tempCopyPath: destPath }),
|
||||
fail: (err) => {
|
||||
console.warn('prepareAudioFileForUpload copyFile failed:', err);
|
||||
resolve({ uploadPath: tempPath, tempCopyPath: null });
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
safeUnlinkAudioCopy(filePath) {
|
||||
if (!filePath || typeof uni.getFileSystemManager !== 'function') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
uni.getFileSystemManager().unlink({ filePath, fail: () => {} });
|
||||
} catch (e) {}
|
||||
},
|
||||
async uploadFileForRecord(item, selectedFile, options = {}) {
|
||||
const recordId = String(item.id);
|
||||
const segmentNo = Number(options.segmentNo) || 1;
|
||||
const durationSeconds = Math.max(0, Number(options.durationSeconds) || 0);
|
||||
const audioDurationMinutesStr = (() => {
|
||||
const m = durationSeconds / 60;
|
||||
return Number.isFinite(m) ? String(Math.round(m * 1e6) / 1e6) : '0';
|
||||
})();
|
||||
const fileSize = Math.max(0, Number(selectedFile?.size) || 0);
|
||||
const resultId = `seg_${recordId}_${segmentNo}_${Date.now()}`;
|
||||
this.pushUploadResult(recordId, {
|
||||
@@ -1051,20 +1129,26 @@ export default {
|
||||
message: '',
|
||||
});
|
||||
this.increaseUploadingCount(recordId);
|
||||
let tempCopyPath = null;
|
||||
try {
|
||||
const targetFileName = this.getAudioUploadFileName({ segmentNo });
|
||||
const prep = await this.prepareAudioFileForUpload(selectedFile.path, targetFileName);
|
||||
const uploadPath = prep.uploadPath;
|
||||
tempCopyPath = prep.tempCopyPath;
|
||||
const maxAttempt = options.retryOnceOnFail ? 2 : 1;
|
||||
let lastErrorMessage = '';
|
||||
for (let attempt = 1; attempt <= maxAttempt; attempt += 1) {
|
||||
const uploadRes = await uni.uploadFile({
|
||||
url: getApiUrl('/api/audio/upload'),
|
||||
filePath: selectedFile.path,
|
||||
filePath: uploadPath,
|
||||
name: 'file',
|
||||
formData: {
|
||||
id: item.id,
|
||||
audioId: item.id,
|
||||
audioDuration: audioDurationMinutesStr,
|
||||
customerId: item.customerId || '',
|
||||
customerName: item.customerName || '',
|
||||
fileName: selectedFile.name || `service_file_${Date.now()}`,
|
||||
fileName: targetFileName,
|
||||
compress: true
|
||||
},
|
||||
header: this.getAuthHeaders(),
|
||||
@@ -1110,6 +1194,7 @@ export default {
|
||||
});
|
||||
return false;
|
||||
} finally {
|
||||
this.safeUnlinkAudioCopy(tempCopyPath);
|
||||
this.decreaseUploadingCount(recordId);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user