From 87afece84fea3ce47aafdeae5b615e7698e6f04b Mon Sep 17 00:00:00 2001 From: "zhonghua.li" Date: Sat, 18 Apr 2026 23:17:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E6=AE=B5=E5=8E=8B=E7=BC=A9=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../serviceListFurniture.vue | 324 ++++++++++++++---- .../serviceListFurniture.js | 2 +- .../serviceListFurniture.wxml | 2 +- .../serviceListFurniture.wxss | 2 +- 4 files changed, 251 insertions(+), 79 deletions(-) diff --git a/pages-subpackage/furniture_reception/serviceListFurniture.vue b/pages-subpackage/furniture_reception/serviceListFurniture.vue index 16cfd31..cfd3cd1 100644 --- a/pages-subpackage/furniture_reception/serviceListFurniture.vue +++ b/pages-subpackage/furniture_reception/serviceListFurniture.vue @@ -127,7 +127,7 @@ 补录客户 - {{ isUploading(item.id) ? '上传中' : '上传录音' }} + 上传录音 结束服务 @@ -137,6 +137,18 @@ 已录音:{{ formatRecordingElapsed(recordingElapsedSeconds) }} 当前大小:{{ formatRecordingSize(recordingEstimatedSizeBytes) }} + + + + 第{{ segment.segmentNo }}段({{ segment.durationText || '--:--' }} / {{ segment.sizeText || '--' }}):{{ segment.statusText }} + + {{ segment.message }} + + {{ emptyListHint }} @@ -276,7 +288,17 @@ export default { recordingElapsedSeconds: 0, recordingEstimatedSizeBytes: 0, recordingTicker: null, - keepScreenOnEnabled: false + keepScreenOnEnabled: false, + // 上传前压缩策略:从录音源头降低采样率/码率,减少上传文件体积 + recordingSampleRate: 16000, + recordingEncodeBitRate: 32000, + recordingSegmentDurationMs: 5 * 60 * 1000, + recordingManualStopRequested: false, + recordingCurrentSegmentNo: 0, + recordingCurrentSegmentStartAt: 0, + recordingCurrentSegmentElapsedSeconds: 0, + uploadingCountMap: {}, + uploadResultMap: {} } }, mounted() { @@ -305,27 +327,71 @@ export default { return; } this.recorderManager = uni.getRecorderManager(); - // 用户点击「停止」后由系统回调此处,再将临时录音文件上传到 /api/audio/upload + // 录音每段停止后回调:静默上传,若非手动停止则继续下一段 this.recorderManager.onStop((res) => { const ctx = this.recordingContext; + const recordId = this.recordingServiceId; + const currentSegmentNo = this.recordingCurrentSegmentNo; + const currentSegmentElapsedSeconds = this.recordingCurrentSegmentElapsedSeconds || this.recordingElapsedSeconds || 0; + const shouldContinue = + !!recordId && + !!ctx && + !!ctx.id && + !this.recordingManualStopRequested; + const normalizedSegmentNo = currentSegmentNo > 0 ? currentSegmentNo : 1; + this.stopRecordingTicker(); + const tempFilePath = res.tempFilePath || ''; + if (ctx && ctx.id) { + const name = `service_record_${ctx.id}_${Date.now()}_part${normalizedSegmentNo}.mp3`; + if (!tempFilePath) { + this.pushUploadResult(String(ctx.id), { + id: `seg_${String(ctx.id)}_${normalizedSegmentNo}_${Date.now()}`, + segmentNo: normalizedSegmentNo, + durationText: this.formatRecordingElapsed(currentSegmentElapsedSeconds), + sizeText: '--', + status: 'failed', + statusText: '上传失败', + message: '未获取到录音文件(已重试1次)', + }); + } else { + this.uploadFileForRecord( + ctx, + { + path: tempFilePath, + name, + size: Number(res.fileSize) || 0, + }, + { + silent: true, + segmentNo: normalizedSegmentNo, + durationSeconds: currentSegmentElapsedSeconds, + retryOnceOnFail: true, + } + ); + } + } + if (shouldContinue) { + this.setKeepScreenOn(true); + setTimeout(() => { + this.startNewSegmentRecording(); + }, 80); + return; + } this.recordingServiceId = null; this.recordingContext = null; - this.stopRecordingTicker(); + this.recordingManualStopRequested = false; + this.recordingCurrentSegmentNo = 0; + this.recordingCurrentSegmentStartAt = 0; + this.recordingCurrentSegmentElapsedSeconds = 0; this.setKeepScreenOn(false); - const tempFilePath = res.tempFilePath || ''; - if (!ctx || !ctx.id) { - return; - } - if (!tempFilePath) { - uni.showToast({ title: '未获取到录音文件', icon: 'none' }); - return; - } - const name = `service_record_${ctx.id}_${Date.now()}.mp3`; - this.uploadFileForRecord(ctx, { path: tempFilePath, name }); }); this.recorderManager.onError(() => { this.recordingServiceId = null; this.recordingContext = null; + this.recordingManualStopRequested = false; + this.recordingCurrentSegmentNo = 0; + this.recordingCurrentSegmentStartAt = 0; + this.recordingCurrentSegmentElapsedSeconds = 0; this.stopRecordingTicker(); this.setKeepScreenOn(false); uni.showToast({ title: '录音出错', icon: 'none' }); @@ -349,10 +415,10 @@ export default { this.stopRecordingTicker(); this.recordingElapsedSeconds = 0; this.recordingEstimatedSizeBytes = 0; - // 96kbps(encodeBitRate)约等于每秒 12000 字节 - const bytesPerSecond = 96000 / 8; + const bytesPerSecond = (Number(this.recordingEncodeBitRate) || 32000) / 8; this.recordingTicker = setInterval(() => { this.recordingElapsedSeconds += 1; + this.recordingCurrentSegmentElapsedSeconds = this.recordingElapsedSeconds; this.recordingEstimatedSizeBytes = Math.floor(this.recordingElapsedSeconds * bytesPerSecond); }, 1000); }, @@ -361,9 +427,38 @@ export default { clearInterval(this.recordingTicker); } this.recordingTicker = null; + this.recordingCurrentSegmentElapsedSeconds = this.recordingElapsedSeconds; this.recordingElapsedSeconds = 0; this.recordingEstimatedSizeBytes = 0; }, + startNewSegmentRecording() { + if (!this.recorderManager || !this.recordingServiceId || !this.recordingContext?.id) { + return; + } + this.recordingCurrentSegmentNo += 1; + this.recordingCurrentSegmentStartAt = Date.now(); + this.recordingCurrentSegmentElapsedSeconds = 0; + try { + this.recorderManager.start({ + duration: this.recordingSegmentDurationMs, + sampleRate: this.recordingSampleRate, + numberOfChannels: 1, + encodeBitRate: this.recordingEncodeBitRate, + format: 'mp3' + }); + this.startRecordingTicker(); + } catch (e) { + this.recordingServiceId = null; + this.recordingContext = null; + this.recordingManualStopRequested = false; + this.recordingCurrentSegmentNo = 0; + this.recordingCurrentSegmentStartAt = 0; + this.recordingCurrentSegmentElapsedSeconds = 0; + this.stopRecordingTicker(); + this.setKeepScreenOn(false); + uni.showToast({ title: '无法开始录音', icon: 'none' }); + } + }, formatRecordingElapsed(seconds) { const safeSeconds = Math.max(0, Number(seconds) || 0); const minutes = String(Math.floor(safeSeconds / 60)).padStart(2, '0'); @@ -409,25 +504,15 @@ export default { uni.showToast({ title: '正在上传,请稍候', icon: 'none' }); return; } + this.recordingManualStopRequested = false; + this.recordingCurrentSegmentNo = 0; + this.recordingCurrentSegmentStartAt = 0; + this.recordingCurrentSegmentElapsedSeconds = 0; + this.setUploadResultList(String(item.id), []); this.recordingContext = { ...item }; this.recordingServiceId = String(item.id); - try { - this.recorderManager.start({ - duration: 600000, - sampleRate: 44100, - numberOfChannels: 1, - encodeBitRate: 96000, - format: 'mp3' - }); - this.setKeepScreenOn(true); - this.startRecordingTicker(); - } catch (e) { - this.recordingServiceId = null; - this.recordingContext = null; - this.stopRecordingTicker(); - this.setKeepScreenOn(false); - uni.showToast({ title: '无法开始录音', icon: 'none' }); - } + this.setKeepScreenOn(true); + this.startNewSegmentRecording(); }, /** 结束录音;onStop 回调中会调用 uploadFileForRecord 上传至后端 */ stopPhoneRecordAndUpload(item) { @@ -437,8 +522,7 @@ export default { if (String(item.id) !== this.recordingServiceId) { return; } - this.stopRecordingTicker(); - this.setKeepScreenOn(false); + this.recordingManualStopRequested = true; this.recorderManager.stop(); }, /** @@ -698,7 +782,41 @@ export default { }, isUploading(recordId) { if (!recordId) return false; - return this.uploadingIds.includes(String(recordId)); + return Number(this.uploadingCountMap[String(recordId)] || 0) > 0; + }, + increaseUploadingCount(recordId) { + const key = String(recordId); + const next = Number(this.uploadingCountMap[key] || 0) + 1; + this.uploadingCountMap = { ...this.uploadingCountMap, [key]: next }; + }, + decreaseUploadingCount(recordId) { + const key = String(recordId); + const current = Number(this.uploadingCountMap[key] || 0); + const next = Math.max(0, current - 1); + this.uploadingCountMap = { ...this.uploadingCountMap, [key]: next }; + }, + getUploadResultList(recordId) { + const key = String(recordId || ''); + const list = this.uploadResultMap[key]; + return Array.isArray(list) ? list : []; + }, + setUploadResultList(recordId, list) { + const key = String(recordId || ''); + this.uploadResultMap = { ...this.uploadResultMap, [key]: Array.isArray(list) ? list : [] }; + }, + pushUploadResult(recordId, segment) { + const list = this.getUploadResultList(recordId); + this.setUploadResultList(recordId, [...list, segment]); + }, + updateUploadResult(recordId, segmentResultId, patch = {}) { + const list = this.getUploadResultList(recordId); + const nextList = list.map((it) => { + if (it.id !== segmentResultId) { + return it; + } + return { ...it, ...patch }; + }); + this.setUploadResultList(recordId, nextList); }, /** 仅允许扩展名为 .mp3 的文件(不区分大小写) */ isMp3UploadFile(selected) { @@ -823,55 +941,82 @@ export default { } return headers; }, - async uploadFileForRecord(item, selectedFile) { + async uploadFileForRecord(item, selectedFile, options = {}) { const recordId = String(item.id); - this.uploadingIds = [...this.uploadingIds, recordId]; + const segmentNo = Number(options.segmentNo) || 1; + const durationSeconds = Math.max(0, Number(options.durationSeconds) || 0); + const fileSize = Math.max(0, Number(selectedFile?.size) || 0); + const resultId = `seg_${recordId}_${segmentNo}_${Date.now()}`; + this.pushUploadResult(recordId, { + id: resultId, + segmentNo, + durationText: this.formatRecordingElapsed(durationSeconds), + sizeText: this.formatRecordingSize(fileSize), + status: 'uploading', + statusText: '上传中', + message: '', + }); + this.increaseUploadingCount(recordId); try { - uni.showLoading({ - title: '上传中...' - }); - const uploadRes = await uni.uploadFile({ - url: getApiUrl('/api/audio/upload'), - filePath: selectedFile.path, - name: 'file', - formData: { - id: item.id, - audioId: item.id, - customerId: item.customerId || '', - customerName: item.customerName || '', - fileName: selectedFile.name || `service_file_${Date.now()}` - }, - header: this.getAuthHeaders(), - timeout: 60000 - }); - let result = {}; - try { - result = typeof uploadRes?.data === 'string' ? JSON.parse(uploadRes.data) : (uploadRes?.data || {}); - } catch (e) { - result = uploadRes?.data || {}; - } - if (uploadRes?.statusCode === 200 && result?.success !== false) { - uni.showToast({ - title: '上传成功', - icon: 'success' + 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, + name: 'file', + formData: { + id: item.id, + audioId: item.id, + customerId: item.customerId || '', + customerName: item.customerName || '', + fileName: selectedFile.name || `service_file_${Date.now()}`, + compress: true + }, + header: this.getAuthHeaders(), + timeout: 60000 }); - this.serviceStatusPage.current = 1; - this.fetchServiceStatusList({ force: true }); - return; + let result = {}; + try { + result = typeof uploadRes?.data === 'string' ? JSON.parse(uploadRes.data) : (uploadRes?.data || {}); + } catch (e) { + result = uploadRes?.data || {}; + } + if (uploadRes?.statusCode === 200 && result?.success !== false) { + this.updateUploadResult(recordId, resultId, { + status: 'success', + statusText: '上传成功', + message: attempt > 1 ? `第${attempt}次尝试成功` : '', + }); + this.serviceStatusPage.current = 1; + this.fetchServiceStatusList({ force: true }); + return true; + } + lastErrorMessage = result?.message || `上传失败(HTTP ${uploadRes?.statusCode || '--'})`; + if (attempt < maxAttempt) { + this.updateUploadResult(recordId, resultId, { + status: 'retrying', + statusText: '重试中', + message: `${lastErrorMessage},正在重试`, + }); + } } - uni.showToast({ - title: result?.message || '上传失败', - icon: 'none' + this.updateUploadResult(recordId, resultId, { + status: 'failed', + statusText: '上传失败', + message: `${lastErrorMessage || '未知错误'}(已重试1次)`, }); + return false; } catch (error) { console.error('上传文件失败:', error); - uni.showToast({ - title: error?.errMsg || error?.message || '上传失败', - icon: 'none' + this.updateUploadResult(recordId, resultId, { + status: 'failed', + statusText: '上传失败', + message: `${error?.errMsg || error?.message || '未知错误'}(已重试1次)`, }); + return false; } finally { - uni.hideLoading(); - this.uploadingIds = this.uploadingIds.filter(id => id !== recordId); + this.decreaseUploadingCount(recordId); } }, async finishService(item) { @@ -1530,6 +1675,33 @@ export default { font-size: 24rpx; color: #FF3B30; } + + .upload-result-list { + margin-top: 12rpx; + padding: 12rpx 16rpx; + background-color: #F8FAFF; + border-radius: 10rpx; + border: 1px solid #E7EEFF; + display: flex; + flex-direction: column; + gap: 8rpx; + } + + .upload-result-item { + display: flex; + flex-direction: column; + gap: 4rpx; + } + + .upload-result-item__main { + font-size: 24rpx; + color: #374151; + } + + .upload-result-item__sub { + font-size: 22rpx; + color: #6B7280; + } /* 补录弹窗样式 */ .supplement-dialog-mask { diff --git a/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.js b/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.js index 2d299bd..9aaf029 100644 --- a/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.js +++ b/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.js @@ -1 +1 @@ -"use strict";const e=require("../../common/vendor.js"),t=require("../../common/config.js"),i=require("../../common/store.js");function r(...e){for(const t of e){if(null==t)continue;const e=String(t).trim();if(e)return e}return""}const o={props:{recordStateLabel:{type:String,default:"服务中"},emptyListHint:{type:String,default:"暂无服务中记录"},showReceptionEntryShortcut:{type:Boolean,default:!1},showRecordStateIndicator:{type:Boolean,default:!0}},data:()=>({serviceStatusLoading:!1,serviceStatusTotal:0,serviceStatusPage:{current:1,size:10},serviceStatusQuery:{salesName:"",customerName:"",salesPhone:""},isAdmin:!1,currentUserPhone:"",serviceStatusList:[],showSupplementModal:!1,currentSupplementItem:null,uploadingIds:[],supplementForm:{customerName:"",contact:"",recordingName:"",remarks:""},recorderSupported:!1,recorderManager:null,recordingServiceId:null,recordingContext:null,recordingElapsedSeconds:0,recordingEstimatedSizeBytes:0,recordingTicker:null,keepScreenOnEnabled:!1}),mounted(){this.checkUserRole(),this.loadCurrentUserPhone(),this.initServiceRecorder(),this.fetchServiceStatusList()},beforeUnmount(){if(this.stopRecordingTicker(),this.setKeepScreenOn(!1),this.recorderManager&&this.recordingServiceId)try{this.recorderManager.stop()}catch(e){}},methods:{initServiceRecorder(){this.recorderSupported="function"==typeof e.index.getRecorderManager,this.recorderSupported&&(this.recorderManager=e.index.getRecorderManager(),this.recorderManager.onStop((t=>{const i=this.recordingContext;this.recordingServiceId=null,this.recordingContext=null,this.stopRecordingTicker(),this.setKeepScreenOn(!1);const r=t.tempFilePath||"";if(!i||!i.id)return;if(!r)return void e.index.showToast({title:"未获取到录音文件",icon:"none"});const o=`service_record_${i.id}_${Date.now()}.mp3`;this.uploadFileForRecord(i,{path:r,name:o})})),this.recorderManager.onError((()=>{this.recordingServiceId=null,this.recordingContext=null,this.stopRecordingTicker(),this.setKeepScreenOn(!1),e.index.showToast({title:"录音出错",icon:"none"})})))},setKeepScreenOn(t){"function"==typeof e.index.setKeepScreenOn&&e.index.setKeepScreenOn({keepScreenOn:!!t,success:()=>{this.keepScreenOnEnabled=!!t},fail:()=>{this.keepScreenOnEnabled=!1}})},startRecordingTicker(){this.stopRecordingTicker(),this.recordingElapsedSeconds=0,this.recordingEstimatedSizeBytes=0;this.recordingTicker=setInterval((()=>{this.recordingElapsedSeconds+=1,this.recordingEstimatedSizeBytes=Math.floor(12e3*this.recordingElapsedSeconds)}),1e3)},stopRecordingTicker(){this.recordingTicker&&clearInterval(this.recordingTicker),this.recordingTicker=null,this.recordingElapsedSeconds=0,this.recordingEstimatedSizeBytes=0},formatRecordingElapsed(e){const t=Math.max(0,Number(e)||0);return`${String(Math.floor(t/60)).padStart(2,"0")}:${String(t%60).padStart(2,"0")}`},formatRecordingSize(e){const t=Math.max(0,Number(e)||0);return t<1024?`${t} B`:t<1048576?`${(t/1024).toFixed(1)} KB`:`${(t/1048576).toFixed(2)} MB`},isRecordingItem(e){return!(!e||!this.recordingServiceId)&&String(e)===this.recordingServiceId},startPhoneRecord(t){if(this.recorderSupported&&this.recorderManager)if(t&&t.id)if(this.recordingServiceId)e.index.showToast({title:"请先停止当前录音",icon:"none"});else if(this.isUploading(t.id))e.index.showToast({title:"正在上传,请稍候",icon:"none"});else{this.recordingContext={...t},this.recordingServiceId=String(t.id);try{this.recorderManager.start({duration:6e5,sampleRate:44100,numberOfChannels:1,encodeBitRate:96e3,format:"mp3"}),this.setKeepScreenOn(!0),this.startRecordingTicker()}catch(i){this.recordingServiceId=null,this.recordingContext=null,this.stopRecordingTicker(),this.setKeepScreenOn(!1),e.index.showToast({title:"无法开始录音",icon:"none"})}}else e.index.showToast({title:"无法获取服务记录ID",icon:"none"});else e.index.showToast({title:"当前环境不支持录音,请使用微信小程序或 App",icon:"none"})},stopPhoneRecordAndUpload(e){this.recorderManager&&(null==e?void 0:e.id)&&String(e.id)===this.recordingServiceId&&(this.stopRecordingTicker(),this.setKeepScreenOn(!1),this.recorderManager.stop())},checkUserRole(){try{const t=e=>"string"==typeof e?e.split(",").map((e=>e.trim().toLowerCase())).filter(Boolean):[],i=e.index.getStorageSync("backend-role-name")||"",r=(e.index.getStorageSync("backend-login-response")||{}).roleName||"",o=[...t(i),...t(r)];this.isAdmin=o.some((e=>e.includes("admin"))),console.log("用户角色检查:",{storedRole:i,respRole:r,roles:o,isAdmin:this.isAdmin})}catch(t){console.error("检查用户角色失败:",t),this.isAdmin=!1}},loadCurrentUserPhone(){try{const t=e.index.getStorageSync("backend-login-response")||{};t.phone?this.currentUserPhone=t.phone:t.userName?this.currentUserPhone=t.userName:this.currentUserPhone=""}catch(t){console.error("加载当前用户手机号或登录账户失败:",t),this.currentUserPhone=""}},onServiceStatusSearch(){this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})},onServiceStatusRefresh(){this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})},goReceptionEntry(){e.index.navigateTo({url:"/pages-subpackage/furniture_reception/furniture_reception_entry?tab=reception",fail:()=>{e.index.showToast({title:"跳转接待失败",icon:"none"})}})},onServiceStatusReachBottom(){this.serviceStatusLoading||this.serviceStatusList.length>=this.serviceStatusTotal||(this.serviceStatusPage.current+=1,this.fetchServiceStatusList())},async fetchServiceStatusList({force:i=!1}={}){var r,o,s,n,a,c,d;if(!this.serviceStatusLoading||i){this.serviceStatusLoading=!0;try{const u={current:this.serviceStatusPage.current,size:this.serviceStatusPage.size,serviceStatus:"服务中"},h=null==(o=null==(r=this.serviceStatusQuery)?void 0:r.salesName)?void 0:o.trim(),m=null==(n=null==(s=this.serviceStatusQuery)?void 0:s.customerName)?void 0:n.trim();if(h&&(u.salesName=h),m&&(u.customerName=m),this.isAdmin){const e=null==(c=null==(a=this.serviceStatusQuery)?void 0:a.salesPhone)?void 0:c.trim();e&&(u.salesPhone=e)}else this.currentUserPhone&&(u.salesPhone=this.currentUserPhone);u.serviceStatus="服务中";const p=Object.keys(u).filter((e=>null!==u[e]&&void 0!==u[e]&&""!==u[e])).map((e=>`${encodeURIComponent(e)}=${encodeURIComponent(u[e])}`)).join("&");console.log("服务状态查询参数:",JSON.stringify(u)),console.log("查询字符串:",p);const g=t.getApiUrl("/api/audioManagement/list"),S=p?`${g}?${p}`:g;let v="",f="";try{v=e.index.getStorageSync("backend-tenant-id")||"",f=e.index.getStorageSync("backend-token")||""}catch(l){console.error("获取认证信息失败:",l)}const y={"Content-Type":"application/json"};f&&(y.Authorization=`Bearer ${f}`),v&&(y["X-Tenant-Id"]=v);const x=await e.index.request({url:S,method:"POST",data:{},header:y,timeout:3e4});if(200===x.statusCode&&x.data&&x.data.success){const e=Array.isArray(x.data.data)?x.data.data:[];if(0===e.length)return this.serviceStatusList=[],void(this.serviceStatusTotal=0);const t=e.map((e=>this.buildServiceStatusItem(e))).filter((e=>null!==e));1===this.serviceStatusPage.current||i?this.serviceStatusList=[...t]:this.serviceStatusList=[...this.serviceStatusList,...t],this.serviceStatusTotal=Number(x.data.total)||0}else this.serviceStatusList=[],this.serviceStatusTotal=0,e.index.showToast({title:(null==(d=x.data)?void 0:d.message)||"获取服务中列表失败",icon:"none"})}catch(u){console.error("获取服务中列表失败:",u);let t="获取服务状态失败,请稍后重试";u.errMsg&&(u.errMsg.includes("timeout")?t="请求超时,请检查网络连接后重试":u.errMsg.includes("fail")&&(t="网络请求失败,请检查网络连接")),e.index.showToast({title:t,icon:"none",duration:3e3})}finally{this.serviceStatusLoading=!1}}},buildServiceStatusItem(e={}){if(!e||"object"!=typeof e)return null;const t=this.formatDateTime(e.createTime),i=[];e.recordingName&&i.push({text:`录音:${e.recordingName}`,color:"blue"}),e.intentionLevel&&i.push({text:`意向:${e.intentionLevel}`,color:"orange"}),e.projectName&&i.push({text:`项目:${e.projectName}`,color:"blue"});const o=r(e.recordingName)||(r(e.customerName)?`${String(e.customerName).trim()}的接待记录`:"")||"";return{id:e.id||"",staffName:e.salesName||"未分配销售",status:e.syncStatus||"服务中",customerName:e.customerName||"",customerPhone:e.customerPhone||"",customerId:e.customerId||"",recordingName:e.recordingName||"",title:o,remarks:e.remarks||"",tags:i,durationText:t?`开始时间:${t}`:"暂无开始时间"}},formatDateTime(e){if(!e)return"";const t=new Date(e);if(Number.isNaN(t.getTime()))return"";return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}:${String(t.getSeconds()).padStart(2,"0")}`},viewServiceDetail(e){console.log("查看服务详情",e)},isUploading(e){return!!e&&this.uploadingIds.includes(String(e))},isMp3UploadFile(e){if(!e||!e.path)return!1;const t=e=>{if(!e||"string"!=typeof e)return"";return(e.split("/").pop()||e.split("\\").pop()||e).trim()},i=[t(e.name),t(e.path)].filter(Boolean);for(const r of i)if(r.toLowerCase().endsWith(".mp3"))return!0;return!1},async chooseAndUploadFile(t){if(!t||!t.id)return void e.index.showToast({title:"无法获取服务记录ID",icon:"none"});if(this.isUploading(t.id))return;const i=await this.selectUploadFile();i&&i.path&&await this.uploadFileForRecord(t,i)},selectUploadFile(){return new Promise((t=>{const i=i=>{const r=(e=>{const t=Array.isArray(null==e?void 0:e.tempFiles)?e.tempFiles:[];if(!t.length)return null;const i=t[0]||{},r=i.path||i.tempFilePath||i.url||"",o=i.name||r.split("/").pop()||`service_file_${Date.now()}`;return r?{path:r,name:o}:null})(i);return r?this.isMp3UploadFile(r)?void t(r):(e.index.showToast({title:"仅支持上传 MP3 文件",icon:"none"}),void t(null)):(e.index.showToast({title:"未选择有效文件",icon:"none"}),void t(null))},r=i=>{((null==i?void 0:i.errMsg)||"").includes("cancel")||(console.error("选择文件失败:",i),e.index.showToast({title:"选择文件失败",icon:"none"})),t(null)};"function"!=typeof e.index.chooseMessageFile?"function"!=typeof e.index.chooseFile?e.index.chooseImage({count:1,success:i,fail:r}):e.index.chooseFile({count:1,extension:[".mp3"],success:i,fail:r}):e.index.chooseMessageFile({count:1,type:"file",success:i,fail:r})}))},getAuthHeaders(){let t="",i="";try{t=e.index.getStorageSync("backend-tenant-id")||"",i=e.index.getStorageSync("backend-token")||""}catch(o){console.error("获取认证信息失败:",o)}const r={};return i&&(r.Authorization=`Bearer ${i}`),t&&(r["X-Tenant-Id"]=t),r},async uploadFileForRecord(i,r){const o=String(i.id);this.uploadingIds=[...this.uploadingIds,o];try{e.index.showLoading({title:"上传中..."});const n=await e.index.uploadFile({url:t.getApiUrl("/api/audio/upload"),filePath:r.path,name:"file",formData:{id:i.id,audioId:i.id,customerId:i.customerId||"",customerName:i.customerName||"",fileName:r.name||`service_file_${Date.now()}`},header:this.getAuthHeaders(),timeout:6e4});let a={};try{a="string"==typeof(null==n?void 0:n.data)?JSON.parse(n.data):(null==n?void 0:n.data)||{}}catch(s){a=(null==n?void 0:n.data)||{}}if(200===(null==n?void 0:n.statusCode)&&!1!==(null==a?void 0:a.success))return e.index.showToast({title:"上传成功",icon:"success"}),this.serviceStatusPage.current=1,void this.fetchServiceStatusList({force:!0});e.index.showToast({title:(null==a?void 0:a.message)||"上传失败",icon:"none"})}catch(n){console.error("上传文件失败:",n),e.index.showToast({title:(null==n?void 0:n.errMsg)||(null==n?void 0:n.message)||"上传失败",icon:"none"})}finally{e.index.hideLoading(),this.uploadingIds=this.uploadingIds.filter((e=>e!==o))}},async finishService(i){i&&i.id?e.index.showModal({title:"确认结束",content:"确定要结束这条服务记录吗?",success:async r=>{var o,s;if(r.confirm)try{e.index.showLoading({title:"结束中..."});const r=t.getApiUrl("/api/audioManagement/finishServiceById");let a="",c="";try{a=e.index.getStorageSync("backend-tenant-id")||"",c=e.index.getStorageSync("backend-token")||""}catch(n){console.error("获取认证信息失败:",n)}const d={"Content-Type":"application/json"};c&&(d.Authorization=`Bearer ${c}`),a&&(d["X-Tenant-Id"]=a);const l={id:i.id},u=await e.index.request({url:r,method:"POST",data:l,header:d,timeout:3e4});if(e.index.hideLoading(),200===u.statusCode&&u.data&&u.data.success){const t=((null==(o=u.data)?void 0:o.message)||"结束服务成功").replace(/[A-Za-z]+/g,"").split(/\n/).map((e=>e.trim())).filter(Boolean).join("\n")||"结束服务成功";e.index.showToast({title:t,icon:"success"}),this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})}else e.index.showToast({title:(null==(s=u.data)?void 0:s.message)||"结束服务失败",icon:"none"})}catch(a){e.index.hideLoading(),console.error("结束服务失败:",a);let t="结束服务失败,请重试";a.errMsg&&(a.errMsg.includes("timeout")?t="请求超时,请检查网络连接后重试":a.errMsg.includes("fail")&&(t="网络请求失败,请检查网络连接")),e.index.showToast({title:t,icon:"none",duration:3e3})}}}):e.index.showToast({title:"无法获取服务记录ID",icon:"none"})},showSupplementDialog(e){this.currentSupplementItem=e,this.supplementForm={customerName:e.customerName||"",contact:e.customerPhone||"",recordingName:e.recordingName||"",remarks:e.remarks||""},this.showSupplementModal=!0},closeSupplementDialog(){this.showSupplementModal=!1,this.currentSupplementItem=null,this.supplementForm={customerName:"",contact:"",recordingName:"",remarks:""}},async saveSupplement(){var o,s,n,a,c;const d=null==(o=this.supplementForm.contact)?void 0:o.trim();if(!d||this.isValidPhoneNumber(d))if(this.currentSupplementItem&&this.currentSupplementItem.id)try{e.index.showLoading({title:"保存中..."});let o="",u="";try{o=e.index.getStorageSync("backend-tenant-id")||"",u=e.index.getStorageSync("backend-token")||""}catch(l){console.error("获取认证信息失败:",l)}const h={"Content-Type":"application/json"};u&&(h.Authorization=`Bearer ${u}`),o&&(h["X-Tenant-Id"]=o);let m={};try{m=e.index.getStorageSync("backend-login-response")||{}}catch(l){console.error("读取登录信息失败:",l)}const p=i.store.userInfo||{},g=r(m.phone,m.userName,p.username),S=r(m.realName,m.name,m.nickName,p.nickname,m.userName,p.username),v={id:this.currentSupplementItem.id,customerId:this.currentSupplementItem.customerId||"",customerName:(null==(s=this.supplementForm.customerName)?void 0:s.trim())||"",customerPhone:d||"",recordingName:(null==(n=this.supplementForm.recordingName)?void 0:n.trim())||"",remarks:(null==(a=this.supplementForm.remarks)?void 0:a.trim())||"",salesPhone:g,salesName:S},f=await e.index.request({url:t.getApiUrl("/api/audioManagement/updateForCustomerInfo"),method:"PUT",data:v,header:h,timeout:3e4});e.index.hideLoading(),200===f.statusCode&&f.data&&f.data.success?(e.index.showToast({title:"补录成功",icon:"success"}),this.closeSupplementDialog(),this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})):e.index.showToast({title:(null==(c=f.data)?void 0:c.message)||"补录失败",icon:"none"})}catch(u){e.index.hideLoading(),console.error("补录失败:",u);let t="补录失败,请重试";u.errMsg&&(u.errMsg.includes("timeout")?t="请求超时,请检查网络连接后重试":u.errMsg.includes("fail")&&(t="网络请求失败,请检查网络连接")),e.index.showToast({title:t,icon:"none",duration:3e3})}else e.index.showToast({title:"无法获取服务记录ID",icon:"none"});else e.index.showToast({title:"请输入有效的客户电话",icon:"none"})},isValidPhoneNumber(e){const t=null==e?void 0:e.trim();return!!t&&/^1[3-9]\d{9}$/.test(t)}}};if(!Array){e.resolveComponent("uni-icons")()}Math;const s=e._export_sfc(o,[["render",function(t,i,r,o,s,n){return e.e({a:e.t(s.serviceStatusTotal),b:e.o(((...e)=>n.onServiceStatusSearch&&n.onServiceStatusSearch(...e)),"1e"),c:s.serviceStatusQuery.salesName,d:e.o((e=>s.serviceStatusQuery.salesName=e.detail.value),"5b"),e:e.o(((...e)=>n.onServiceStatusSearch&&n.onServiceStatusSearch(...e)),"4f"),f:s.serviceStatusQuery.customerName,g:e.o((e=>s.serviceStatusQuery.customerName=e.detail.value),"ff"),h:s.isAdmin},s.isAdmin?{i:e.o(((...e)=>n.onServiceStatusSearch&&n.onServiceStatusSearch(...e)),"91"),j:s.serviceStatusQuery.salesPhone,k:e.o((e=>s.serviceStatusQuery.salesPhone=e.detail.value),"86")}:{},{l:r.showReceptionEntryShortcut},r.showReceptionEntryShortcut?{m:e.p({type:"home",size:"18",color:"#2A68FF"}),n:e.o(((...e)=>n.goReceptionEntry&&n.goReceptionEntry(...e)),"5d")}:{},{o:e.p({type:"refresh",size:"18",color:"#2A68FF"}),p:e.o(((...e)=>n.onServiceStatusRefresh&&n.onServiceStatusRefresh(...e)),"84"),q:e.f(s.serviceStatusList,((t,i,r)=>e.e({a:e.t(t.staffName?t.staffName.charAt(0):"未"),b:e.t(t.staffName||"未分配销售"),c:"5d9b5d15-2-"+r,d:t.title},t.title?{e:e.t(t.title)}:{},{f:e.t(t.customerName||"未知客户"),g:t.customerPhone},t.customerPhone?{h:e.t(t.customerPhone)}:{},{i:e.f(t.tags,((t,i,r)=>({a:e.t(t.text),b:e.n("tag-"+t.color),c:i}))),j:t.alert},t.alert?e.e({k:e.t(t.alert.title),l:"risk"===t.alert.type},"risk"===t.alert.type?{m:e.t(t.alert.message)}:{n:e.f(t.alert.messages,((t,i,r)=>({a:e.t(t),b:i})))},{o:e.n("risk"===t.alert.type?"alert-risk-text":"alert-reminder-text"),p:e.n("risk"===t.alert.type?"alert-risk-box":"alert-reminder-box")}):{},{q:e.t(t.durationText),r:!n.isRecordingItem(t.id)},n.isRecordingItem(t.id)?{t:e.o((e=>n.stopPhoneRecordAndUpload(t)),t.id||i)}:{s:e.o((e=>n.startPhoneRecord(t)),t.id||i)},{v:e.o((e=>n.showSupplementDialog(t)),t.id||i),w:e.t(n.isUploading(t.id)?"上传中":"上传录音"),x:e.o((e=>n.chooseAndUploadFile(t)),t.id||i),y:e.o((e=>n.finishService(t)),t.id||i),z:n.isRecordingItem(t.id)},n.isRecordingItem(t.id)?{A:e.t(n.formatRecordingElapsed(s.recordingElapsedSeconds)),B:e.t(n.formatRecordingSize(s.recordingEstimatedSizeBytes))}:{},{C:t.id||i,D:e.o((e=>n.viewServiceDetail(t)),t.id||i)}))),r:e.p({type:"bars",size:"16",color:"#007AFF"}),s:e.t(r.recordStateLabel),t:!s.serviceStatusLoading&&!s.serviceStatusList.length},s.serviceStatusLoading||s.serviceStatusList.length?{}:{v:e.t(r.emptyListHint)},{w:s.serviceStatusLoading&&s.serviceStatusList.length},(s.serviceStatusLoading&&s.serviceStatusList.length,{}),{x:e.o(((...e)=>n.onServiceStatusReachBottom&&n.onServiceStatusReachBottom(...e)),"d2"),y:s.showSupplementModal},s.showSupplementModal?{z:e.p({type:"close",size:"20",color:"#999"}),A:e.o(((...e)=>n.closeSupplementDialog&&n.closeSupplementDialog(...e)),"06"),B:s.supplementForm.customerName,C:e.o((e=>s.supplementForm.customerName=e.detail.value),"fa"),D:s.supplementForm.contact,E:e.o((e=>s.supplementForm.contact=e.detail.value),"51"),F:s.supplementForm.recordingName,G:e.o((e=>s.supplementForm.recordingName=e.detail.value),"4d"),H:s.supplementForm.remarks,I:e.o((e=>s.supplementForm.remarks=e.detail.value),"fe"),J:e.o(((...e)=>n.closeSupplementDialog&&n.closeSupplementDialog(...e)),"73"),K:e.o(((...e)=>n.saveSupplement&&n.saveSupplement(...e)),"5c"),L:e.o((()=>{}),"83"),M:e.o(((...e)=>n.closeSupplementDialog&&n.closeSupplementDialog(...e)),"22")}:{})}],["__scopeId","data-v-5d9b5d15"]]);wx.createComponent(s); +"use strict";const e=require("../../common/vendor.js"),t=require("../../common/config.js"),r=require("../../common/store.js");function i(...e){for(const t of e){if(null==t)continue;const e=String(t).trim();if(e)return e}return""}const s={props:{recordStateLabel:{type:String,default:"服务中"},emptyListHint:{type:String,default:"暂无服务中记录"},showReceptionEntryShortcut:{type:Boolean,default:!1},showRecordStateIndicator:{type:Boolean,default:!0}},data:()=>({serviceStatusLoading:!1,serviceStatusTotal:0,serviceStatusPage:{current:1,size:10},serviceStatusQuery:{salesName:"",customerName:"",salesPhone:""},isAdmin:!1,currentUserPhone:"",serviceStatusList:[],showSupplementModal:!1,currentSupplementItem:null,uploadingIds:[],supplementForm:{customerName:"",contact:"",recordingName:"",remarks:""},recorderSupported:!1,recorderManager:null,recordingServiceId:null,recordingContext:null,recordingElapsedSeconds:0,recordingEstimatedSizeBytes:0,recordingTicker:null,keepScreenOnEnabled:!1,recordingSampleRate:16e3,recordingEncodeBitRate:32e3,recordingSegmentDurationMs:3e5,recordingManualStopRequested:!1,recordingCurrentSegmentNo:0,recordingCurrentSegmentStartAt:0,recordingCurrentSegmentElapsedSeconds:0,uploadingCountMap:{},uploadResultMap:{}}),mounted(){this.checkUserRole(),this.loadCurrentUserPhone(),this.initServiceRecorder(),this.fetchServiceStatusList()},beforeUnmount(){if(this.stopRecordingTicker(),this.setKeepScreenOn(!1),this.recorderManager&&this.recordingServiceId)try{this.recorderManager.stop()}catch(e){}},methods:{initServiceRecorder(){this.recorderSupported="function"==typeof e.index.getRecorderManager,this.recorderSupported&&(this.recorderManager=e.index.getRecorderManager(),this.recorderManager.onStop((e=>{const t=this.recordingContext,r=this.recordingServiceId,i=this.recordingCurrentSegmentNo,s=this.recordingCurrentSegmentElapsedSeconds||this.recordingElapsedSeconds||0,n=!(!r||!t||!t.id||this.recordingManualStopRequested),o=i>0?i:1;this.stopRecordingTicker();const a=e.tempFilePath||"";if(t&&t.id){const r=`service_record_${t.id}_${Date.now()}_part${o}.mp3`;a?this.uploadFileForRecord(t,{path:a,name:r,size:Number(e.fileSize)||0},{silent:!0,segmentNo:o,durationSeconds:s,retryOnceOnFail:!0}):this.pushUploadResult(String(t.id),{id:`seg_${String(t.id)}_${o}_${Date.now()}`,segmentNo:o,durationText:this.formatRecordingElapsed(s),sizeText:"--",status:"failed",statusText:"上传失败",message:"未获取到录音文件(已重试1次)"})}if(n)return this.setKeepScreenOn(!0),void setTimeout((()=>{this.startNewSegmentRecording()}),80);this.recordingServiceId=null,this.recordingContext=null,this.recordingManualStopRequested=!1,this.recordingCurrentSegmentNo=0,this.recordingCurrentSegmentStartAt=0,this.recordingCurrentSegmentElapsedSeconds=0,this.setKeepScreenOn(!1)})),this.recorderManager.onError((()=>{this.recordingServiceId=null,this.recordingContext=null,this.recordingManualStopRequested=!1,this.recordingCurrentSegmentNo=0,this.recordingCurrentSegmentStartAt=0,this.recordingCurrentSegmentElapsedSeconds=0,this.stopRecordingTicker(),this.setKeepScreenOn(!1),e.index.showToast({title:"录音出错",icon:"none"})})))},setKeepScreenOn(t){"function"==typeof e.index.setKeepScreenOn&&e.index.setKeepScreenOn({keepScreenOn:!!t,success:()=>{this.keepScreenOnEnabled=!!t},fail:()=>{this.keepScreenOnEnabled=!1}})},startRecordingTicker(){this.stopRecordingTicker(),this.recordingElapsedSeconds=0,this.recordingEstimatedSizeBytes=0;const e=(Number(this.recordingEncodeBitRate)||32e3)/8;this.recordingTicker=setInterval((()=>{this.recordingElapsedSeconds+=1,this.recordingCurrentSegmentElapsedSeconds=this.recordingElapsedSeconds,this.recordingEstimatedSizeBytes=Math.floor(this.recordingElapsedSeconds*e)}),1e3)},stopRecordingTicker(){this.recordingTicker&&clearInterval(this.recordingTicker),this.recordingTicker=null,this.recordingCurrentSegmentElapsedSeconds=this.recordingElapsedSeconds,this.recordingElapsedSeconds=0,this.recordingEstimatedSizeBytes=0},startNewSegmentRecording(){var t;if(this.recorderManager&&this.recordingServiceId&&(null==(t=this.recordingContext)?void 0:t.id)){this.recordingCurrentSegmentNo+=1,this.recordingCurrentSegmentStartAt=Date.now(),this.recordingCurrentSegmentElapsedSeconds=0;try{this.recorderManager.start({duration:this.recordingSegmentDurationMs,sampleRate:this.recordingSampleRate,numberOfChannels:1,encodeBitRate:this.recordingEncodeBitRate,format:"mp3"}),this.startRecordingTicker()}catch(r){this.recordingServiceId=null,this.recordingContext=null,this.recordingManualStopRequested=!1,this.recordingCurrentSegmentNo=0,this.recordingCurrentSegmentStartAt=0,this.recordingCurrentSegmentElapsedSeconds=0,this.stopRecordingTicker(),this.setKeepScreenOn(!1),e.index.showToast({title:"无法开始录音",icon:"none"})}}},formatRecordingElapsed(e){const t=Math.max(0,Number(e)||0);return`${String(Math.floor(t/60)).padStart(2,"0")}:${String(t%60).padStart(2,"0")}`},formatRecordingSize(e){const t=Math.max(0,Number(e)||0);return t<1024?`${t} B`:t<1048576?`${(t/1024).toFixed(1)} KB`:`${(t/1048576).toFixed(2)} MB`},isRecordingItem(e){return!(!e||!this.recordingServiceId)&&String(e)===this.recordingServiceId},startPhoneRecord(t){this.recorderSupported&&this.recorderManager?t&&t.id?this.recordingServiceId?e.index.showToast({title:"请先停止当前录音",icon:"none"}):this.isUploading(t.id)?e.index.showToast({title:"正在上传,请稍候",icon:"none"}):(this.recordingManualStopRequested=!1,this.recordingCurrentSegmentNo=0,this.recordingCurrentSegmentStartAt=0,this.recordingCurrentSegmentElapsedSeconds=0,this.setUploadResultList(String(t.id),[]),this.recordingContext={...t},this.recordingServiceId=String(t.id),this.setKeepScreenOn(!0),this.startNewSegmentRecording()):e.index.showToast({title:"无法获取服务记录ID",icon:"none"}):e.index.showToast({title:"当前环境不支持录音,请使用微信小程序或 App",icon:"none"})},stopPhoneRecordAndUpload(e){this.recorderManager&&(null==e?void 0:e.id)&&String(e.id)===this.recordingServiceId&&(this.recordingManualStopRequested=!0,this.recorderManager.stop())},checkUserRole(){try{const t=e=>"string"==typeof e?e.split(",").map((e=>e.trim().toLowerCase())).filter(Boolean):[],r=e.index.getStorageSync("backend-role-name")||"",i=(e.index.getStorageSync("backend-login-response")||{}).roleName||"",s=[...t(r),...t(i)];this.isAdmin=s.some((e=>e.includes("admin"))),console.log("用户角色检查:",{storedRole:r,respRole:i,roles:s,isAdmin:this.isAdmin})}catch(t){console.error("检查用户角色失败:",t),this.isAdmin=!1}},loadCurrentUserPhone(){try{const t=e.index.getStorageSync("backend-login-response")||{};t.phone?this.currentUserPhone=t.phone:t.userName?this.currentUserPhone=t.userName:this.currentUserPhone=""}catch(t){console.error("加载当前用户手机号或登录账户失败:",t),this.currentUserPhone=""}},onServiceStatusSearch(){this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})},onServiceStatusRefresh(){this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})},goReceptionEntry(){e.index.navigateTo({url:"/pages-subpackage/furniture_reception/furniture_reception_entry?tab=reception",fail:()=>{e.index.showToast({title:"跳转接待失败",icon:"none"})}})},onServiceStatusReachBottom(){this.serviceStatusLoading||this.serviceStatusList.length>=this.serviceStatusTotal||(this.serviceStatusPage.current+=1,this.fetchServiceStatusList())},async fetchServiceStatusList({force:r=!1}={}){var i,s,n,o,a,c,d;if(!this.serviceStatusLoading||r){this.serviceStatusLoading=!0;try{const u={current:this.serviceStatusPage.current,size:this.serviceStatusPage.size,serviceStatus:"服务中"},h=null==(s=null==(i=this.serviceStatusQuery)?void 0:i.salesName)?void 0:s.trim(),g=null==(o=null==(n=this.serviceStatusQuery)?void 0:n.customerName)?void 0:o.trim();if(h&&(u.salesName=h),g&&(u.customerName=g),this.isAdmin){const e=null==(c=null==(a=this.serviceStatusQuery)?void 0:a.salesPhone)?void 0:c.trim();e&&(u.salesPhone=e)}else this.currentUserPhone&&(u.salesPhone=this.currentUserPhone);u.serviceStatus="服务中";const m=Object.keys(u).filter((e=>null!==u[e]&&void 0!==u[e]&&""!==u[e])).map((e=>`${encodeURIComponent(e)}=${encodeURIComponent(u[e])}`)).join("&");console.log("服务状态查询参数:",JSON.stringify(u)),console.log("查询字符串:",m);const p=t.getApiUrl("/api/audioManagement/list"),S=m?`${p}?${m}`:p;let v="",f="";try{v=e.index.getStorageSync("backend-tenant-id")||"",f=e.index.getStorageSync("backend-token")||""}catch(l){console.error("获取认证信息失败:",l)}const y={"Content-Type":"application/json"};f&&(y.Authorization=`Bearer ${f}`),v&&(y["X-Tenant-Id"]=v);const x=await e.index.request({url:S,method:"POST",data:{},header:y,timeout:3e4});if(200===x.statusCode&&x.data&&x.data.success){const e=Array.isArray(x.data.data)?x.data.data:[];if(0===e.length)return this.serviceStatusList=[],void(this.serviceStatusTotal=0);const t=e.map((e=>this.buildServiceStatusItem(e))).filter((e=>null!==e));1===this.serviceStatusPage.current||r?this.serviceStatusList=[...t]:this.serviceStatusList=[...this.serviceStatusList,...t],this.serviceStatusTotal=Number(x.data.total)||0}else this.serviceStatusList=[],this.serviceStatusTotal=0,e.index.showToast({title:(null==(d=x.data)?void 0:d.message)||"获取服务中列表失败",icon:"none"})}catch(u){console.error("获取服务中列表失败:",u);let t="获取服务状态失败,请稍后重试";u.errMsg&&(u.errMsg.includes("timeout")?t="请求超时,请检查网络连接后重试":u.errMsg.includes("fail")&&(t="网络请求失败,请检查网络连接")),e.index.showToast({title:t,icon:"none",duration:3e3})}finally{this.serviceStatusLoading=!1}}},buildServiceStatusItem(e={}){if(!e||"object"!=typeof e)return null;const t=this.formatDateTime(e.createTime),r=[];e.recordingName&&r.push({text:`录音:${e.recordingName}`,color:"blue"}),e.intentionLevel&&r.push({text:`意向:${e.intentionLevel}`,color:"orange"}),e.projectName&&r.push({text:`项目:${e.projectName}`,color:"blue"});const s=i(e.recordingName)||(i(e.customerName)?`${String(e.customerName).trim()}的接待记录`:"")||"";return{id:e.id||"",staffName:e.salesName||"未分配销售",status:e.syncStatus||"服务中",customerName:e.customerName||"",customerPhone:e.customerPhone||"",customerId:e.customerId||"",recordingName:e.recordingName||"",title:s,remarks:e.remarks||"",tags:r,durationText:t?`开始时间:${t}`:"暂无开始时间"}},formatDateTime(e){if(!e)return"";const t=new Date(e);if(Number.isNaN(t.getTime()))return"";return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}:${String(t.getSeconds()).padStart(2,"0")}`},viewServiceDetail(e){console.log("查看服务详情",e)},isUploading(e){return!!e&&Number(this.uploadingCountMap[String(e)]||0)>0},increaseUploadingCount(e){const t=String(e),r=Number(this.uploadingCountMap[t]||0)+1;this.uploadingCountMap={...this.uploadingCountMap,[t]:r}},decreaseUploadingCount(e){const t=String(e),r=Number(this.uploadingCountMap[t]||0),i=Math.max(0,r-1);this.uploadingCountMap={...this.uploadingCountMap,[t]:i}},getUploadResultList(e){const t=String(e||""),r=this.uploadResultMap[t];return Array.isArray(r)?r:[]},setUploadResultList(e,t){const r=String(e||"");this.uploadResultMap={...this.uploadResultMap,[r]:Array.isArray(t)?t:[]}},pushUploadResult(e,t){const r=this.getUploadResultList(e);this.setUploadResultList(e,[...r,t])},updateUploadResult(e,t,r={}){const i=this.getUploadResultList(e).map((e=>e.id!==t?e:{...e,...r}));this.setUploadResultList(e,i)},isMp3UploadFile(e){if(!e||!e.path)return!1;const t=e=>{if(!e||"string"!=typeof e)return"";return(e.split("/").pop()||e.split("\\").pop()||e).trim()},r=[t(e.name),t(e.path)].filter(Boolean);for(const i of r)if(i.toLowerCase().endsWith(".mp3"))return!0;return!1},async chooseAndUploadFile(t){if(!t||!t.id)return void e.index.showToast({title:"无法获取服务记录ID",icon:"none"});if(this.isUploading(t.id))return;const r=await this.selectUploadFile();r&&r.path&&await this.uploadFileForRecord(t,r)},selectUploadFile(){return new Promise((t=>{const r=r=>{const i=(e=>{const t=Array.isArray(null==e?void 0:e.tempFiles)?e.tempFiles:[];if(!t.length)return null;const r=t[0]||{},i=r.path||r.tempFilePath||r.url||"",s=r.name||i.split("/").pop()||`service_file_${Date.now()}`;return i?{path:i,name:s}:null})(r);return i?this.isMp3UploadFile(i)?void t(i):(e.index.showToast({title:"仅支持上传 MP3 文件",icon:"none"}),void t(null)):(e.index.showToast({title:"未选择有效文件",icon:"none"}),void t(null))},i=r=>{((null==r?void 0:r.errMsg)||"").includes("cancel")||(console.error("选择文件失败:",r),e.index.showToast({title:"选择文件失败",icon:"none"})),t(null)};"function"!=typeof e.index.chooseMessageFile?"function"!=typeof e.index.chooseFile?e.index.chooseImage({count:1,success:r,fail:i}):e.index.chooseFile({count:1,extension:[".mp3"],success:r,fail:i}):e.index.chooseMessageFile({count:1,type:"file",success:r,fail:i})}))},getAuthHeaders(){let t="",r="";try{t=e.index.getStorageSync("backend-tenant-id")||"",r=e.index.getStorageSync("backend-token")||""}catch(s){console.error("获取认证信息失败:",s)}const i={};return r&&(i.Authorization=`Bearer ${r}`),t&&(i["X-Tenant-Id"]=t),i},async uploadFileForRecord(r,i,s={}){const n=String(r.id),o=Number(s.segmentNo)||1,a=Math.max(0,Number(s.durationSeconds)||0),c=Math.max(0,Number(null==i?void 0:i.size)||0),d=`seg_${n}_${o}_${Date.now()}`;this.pushUploadResult(n,{id:d,segmentNo:o,durationText:this.formatRecordingElapsed(a),sizeText:this.formatRecordingSize(c),status:"uploading",statusText:"上传中",message:""}),this.increaseUploadingCount(n);try{const o=s.retryOnceOnFail?2:1;let a="";for(let s=1;s<=o;s+=1){const c=await e.index.uploadFile({url:t.getApiUrl("/api/audio/upload"),filePath:i.path,name:"file",formData:{id:r.id,audioId:r.id,customerId:r.customerId||"",customerName:r.customerName||"",fileName:i.name||`service_file_${Date.now()}`,compress:!0},header:this.getAuthHeaders(),timeout:6e4});let u={};try{u="string"==typeof(null==c?void 0:c.data)?JSON.parse(c.data):(null==c?void 0:c.data)||{}}catch(l){u=(null==c?void 0:c.data)||{}}if(200===(null==c?void 0:c.statusCode)&&!1!==(null==u?void 0:u.success))return this.updateUploadResult(n,d,{status:"success",statusText:"上传成功",message:s>1?`第${s}次尝试成功`:""}),this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0}),!0;a=(null==u?void 0:u.message)||`上传失败(HTTP ${(null==c?void 0:c.statusCode)||"--"})`,s{var s,n;if(i.confirm)try{e.index.showLoading({title:"结束中..."});const i=t.getApiUrl("/api/audioManagement/finishServiceById");let a="",c="";try{a=e.index.getStorageSync("backend-tenant-id")||"",c=e.index.getStorageSync("backend-token")||""}catch(o){console.error("获取认证信息失败:",o)}const d={"Content-Type":"application/json"};c&&(d.Authorization=`Bearer ${c}`),a&&(d["X-Tenant-Id"]=a);const l={id:r.id},u=await e.index.request({url:i,method:"POST",data:l,header:d,timeout:3e4});if(e.index.hideLoading(),200===u.statusCode&&u.data&&u.data.success){const t=((null==(s=u.data)?void 0:s.message)||"结束服务成功").replace(/[A-Za-z]+/g,"").split(/\n/).map((e=>e.trim())).filter(Boolean).join("\n")||"结束服务成功";e.index.showToast({title:t,icon:"success"}),this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})}else e.index.showToast({title:(null==(n=u.data)?void 0:n.message)||"结束服务失败",icon:"none"})}catch(a){e.index.hideLoading(),console.error("结束服务失败:",a);let t="结束服务失败,请重试";a.errMsg&&(a.errMsg.includes("timeout")?t="请求超时,请检查网络连接后重试":a.errMsg.includes("fail")&&(t="网络请求失败,请检查网络连接")),e.index.showToast({title:t,icon:"none",duration:3e3})}}}):e.index.showToast({title:"无法获取服务记录ID",icon:"none"})},showSupplementDialog(e){this.currentSupplementItem=e,this.supplementForm={customerName:e.customerName||"",contact:e.customerPhone||"",recordingName:e.recordingName||"",remarks:e.remarks||""},this.showSupplementModal=!0},closeSupplementDialog(){this.showSupplementModal=!1,this.currentSupplementItem=null,this.supplementForm={customerName:"",contact:"",recordingName:"",remarks:""}},async saveSupplement(){var s,n,o,a,c;const d=null==(s=this.supplementForm.contact)?void 0:s.trim();if(!d||this.isValidPhoneNumber(d))if(this.currentSupplementItem&&this.currentSupplementItem.id)try{e.index.showLoading({title:"保存中..."});let s="",u="";try{s=e.index.getStorageSync("backend-tenant-id")||"",u=e.index.getStorageSync("backend-token")||""}catch(l){console.error("获取认证信息失败:",l)}const h={"Content-Type":"application/json"};u&&(h.Authorization=`Bearer ${u}`),s&&(h["X-Tenant-Id"]=s);let g={};try{g=e.index.getStorageSync("backend-login-response")||{}}catch(l){console.error("读取登录信息失败:",l)}const m=r.store.userInfo||{},p=i(g.phone,g.userName,m.username),S=i(g.realName,g.name,g.nickName,m.nickname,g.userName,m.username),v={id:this.currentSupplementItem.id,customerId:this.currentSupplementItem.customerId||"",customerName:(null==(n=this.supplementForm.customerName)?void 0:n.trim())||"",customerPhone:d||"",recordingName:(null==(o=this.supplementForm.recordingName)?void 0:o.trim())||"",remarks:(null==(a=this.supplementForm.remarks)?void 0:a.trim())||"",salesPhone:p,salesName:S},f=await e.index.request({url:t.getApiUrl("/api/audioManagement/updateForCustomerInfo"),method:"PUT",data:v,header:h,timeout:3e4});e.index.hideLoading(),200===f.statusCode&&f.data&&f.data.success?(e.index.showToast({title:"补录成功",icon:"success"}),this.closeSupplementDialog(),this.serviceStatusPage.current=1,this.fetchServiceStatusList({force:!0})):e.index.showToast({title:(null==(c=f.data)?void 0:c.message)||"补录失败",icon:"none"})}catch(u){e.index.hideLoading(),console.error("补录失败:",u);let t="补录失败,请重试";u.errMsg&&(u.errMsg.includes("timeout")?t="请求超时,请检查网络连接后重试":u.errMsg.includes("fail")&&(t="网络请求失败,请检查网络连接")),e.index.showToast({title:t,icon:"none",duration:3e3})}else e.index.showToast({title:"无法获取服务记录ID",icon:"none"});else e.index.showToast({title:"请输入有效的客户电话",icon:"none"})},isValidPhoneNumber(e){const t=null==e?void 0:e.trim();return!!t&&/^1[3-9]\d{9}$/.test(t)}}};if(!Array){e.resolveComponent("uni-icons")()}Math;const n=e._export_sfc(s,[["render",function(t,r,i,s,n,o){return e.e({a:e.t(n.serviceStatusTotal),b:e.o(((...e)=>o.onServiceStatusSearch&&o.onServiceStatusSearch(...e)),"1e"),c:n.serviceStatusQuery.salesName,d:e.o((e=>n.serviceStatusQuery.salesName=e.detail.value),"5b"),e:e.o(((...e)=>o.onServiceStatusSearch&&o.onServiceStatusSearch(...e)),"4f"),f:n.serviceStatusQuery.customerName,g:e.o((e=>n.serviceStatusQuery.customerName=e.detail.value),"ff"),h:n.isAdmin},n.isAdmin?{i:e.o(((...e)=>o.onServiceStatusSearch&&o.onServiceStatusSearch(...e)),"91"),j:n.serviceStatusQuery.salesPhone,k:e.o((e=>n.serviceStatusQuery.salesPhone=e.detail.value),"86")}:{},{l:i.showReceptionEntryShortcut},i.showReceptionEntryShortcut?{m:e.p({type:"home",size:"18",color:"#2A68FF"}),n:e.o(((...e)=>o.goReceptionEntry&&o.goReceptionEntry(...e)),"5d")}:{},{o:e.p({type:"refresh",size:"18",color:"#2A68FF"}),p:e.o(((...e)=>o.onServiceStatusRefresh&&o.onServiceStatusRefresh(...e)),"84"),q:e.f(n.serviceStatusList,((t,r,i)=>e.e({a:e.t(t.staffName?t.staffName.charAt(0):"未"),b:e.t(t.staffName||"未分配销售"),c:"8e98b19a-2-"+i,d:t.title},t.title?{e:e.t(t.title)}:{},{f:e.t(t.customerName||"未知客户"),g:t.customerPhone},t.customerPhone?{h:e.t(t.customerPhone)}:{},{i:e.f(t.tags,((t,r,i)=>({a:e.t(t.text),b:e.n("tag-"+t.color),c:r}))),j:t.alert},t.alert?e.e({k:e.t(t.alert.title),l:"risk"===t.alert.type},"risk"===t.alert.type?{m:e.t(t.alert.message)}:{n:e.f(t.alert.messages,((t,r,i)=>({a:e.t(t),b:r})))},{o:e.n("risk"===t.alert.type?"alert-risk-text":"alert-reminder-text"),p:e.n("risk"===t.alert.type?"alert-risk-box":"alert-reminder-box")}):{},{q:e.t(t.durationText),r:!o.isRecordingItem(t.id)},o.isRecordingItem(t.id)?{t:e.o((e=>o.stopPhoneRecordAndUpload(t)),t.id||r)}:{s:e.o((e=>o.startPhoneRecord(t)),t.id||r)},{v:e.o((e=>o.showSupplementDialog(t)),t.id||r),w:e.o((e=>o.chooseAndUploadFile(t)),t.id||r),x:e.o((e=>o.finishService(t)),t.id||r),y:o.isRecordingItem(t.id)},o.isRecordingItem(t.id)?{z:e.t(o.formatRecordingElapsed(n.recordingElapsedSeconds)),A:e.t(o.formatRecordingSize(n.recordingEstimatedSizeBytes))}:{},{B:o.getUploadResultList(t.id).length},o.getUploadResultList(t.id).length?{C:e.f(o.getUploadResultList(t.id),((t,r,i)=>e.e({a:e.t(t.segmentNo),b:e.t(t.durationText||"--:--"),c:e.t(t.sizeText||"--"),d:e.t(t.statusText),e:t.message},t.message?{f:e.t(t.message)}:{},{g:t.id})))}:{},{D:t.id||r,E:e.o((e=>o.viewServiceDetail(t)),t.id||r)}))),r:e.p({type:"bars",size:"16",color:"#007AFF"}),s:e.t(i.recordStateLabel),t:!n.serviceStatusLoading&&!n.serviceStatusList.length},n.serviceStatusLoading||n.serviceStatusList.length?{}:{v:e.t(i.emptyListHint)},{w:n.serviceStatusLoading&&n.serviceStatusList.length},(n.serviceStatusLoading&&n.serviceStatusList.length,{}),{x:e.o(((...e)=>o.onServiceStatusReachBottom&&o.onServiceStatusReachBottom(...e)),"d2"),y:n.showSupplementModal},n.showSupplementModal?{z:e.p({type:"close",size:"20",color:"#999"}),A:e.o(((...e)=>o.closeSupplementDialog&&o.closeSupplementDialog(...e)),"8e"),B:n.supplementForm.customerName,C:e.o((e=>n.supplementForm.customerName=e.detail.value),"72"),D:n.supplementForm.contact,E:e.o((e=>n.supplementForm.contact=e.detail.value),"04"),F:n.supplementForm.recordingName,G:e.o((e=>n.supplementForm.recordingName=e.detail.value),"7b"),H:n.supplementForm.remarks,I:e.o((e=>n.supplementForm.remarks=e.detail.value),"36"),J:e.o(((...e)=>o.closeSupplementDialog&&o.closeSupplementDialog(...e)),"c5"),K:e.o(((...e)=>o.saveSupplement&&o.saveSupplement(...e)),"13"),L:e.o((()=>{}),"b8"),M:e.o(((...e)=>o.closeSupplementDialog&&o.closeSupplementDialog(...e)),"7c")}:{})}],["__scopeId","data-v-8e98b19a"]]);wx.createComponent(n); diff --git a/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxml b/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxml index 4e9c5e7..a44db48 100644 --- a/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxml +++ b/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxml @@ -1 +1 @@ -共{{a}}条接待刷新{{item.a}}{{item.b}}{{s}}{{item.e}}客户:{{item.f}}电话:{{item.h}}{{tag.a}}{{item.k}}{{item.m}}{{msg.a}}{{item.q}}录音停止录音补录客户{{item.w}}结束服务已录音:{{item.A}}当前大小:{{item.B}}{{v}}正在加载更多...补录信息客户姓名客户电话录音名客户详细地址