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.e}}客户:{{item.f}}电话:{{item.h}}{{tag.a}}{{item.m}}{{msg.a}}{{item.q}}录音停止录音补录客户{{item.w}}结束服务已录音:{{item.A}}当前大小:{{item.B}}{{v}}正在加载更多...客户姓名客户电话录音名客户详细地址
\ No newline at end of file
+共{{a}}条接待刷新{{item.e}}客户:{{item.f}}电话:{{item.h}}{{tag.a}}{{item.m}}{{msg.a}}{{item.q}}录音停止录音补录客户上传录音结束服务已录音:{{item.z}}当前大小:{{item.A}} 第{{segment.a}}段({{segment.b}} / {{segment.c}}):{{segment.d}}{{segment.f}}{{v}}正在加载更多...客户姓名客户电话录音名客户详细地址
\ No newline at end of file
diff --git a/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxss b/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxss
index 060f2ee..9515e87 100644
--- a/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxss
+++ b/unpackage/dist/build/mp-weixin/pages-subpackage/furniture_reception/serviceListFurniture.wxss
@@ -1 +1 @@
-.service-list-container.data-v-5d9b5d15{height:100%;width:100%;display:flex;flex-direction:column;background-color:#f5f5f5;padding:0 16rpx;box-sizing:border-box}.service-status-toolbar.data-v-5d9b5d15{display:flex;flex-wrap:nowrap;align-items:center;gap:8rpx;padding:12rpx 8rpx;margin-bottom:24rpx;background-color:#f8f8fa;border-radius:8rpx;border:1px solid #EFEFF2;overflow-x:auto;min-height:64rpx;box-sizing:border-box;flex-shrink:0}.service-list.data-v-5d9b5d15{flex:1;background-color:transparent;box-sizing:border-box;overflow-y:auto}.toolbar-total.data-v-5d9b5d15{font-size:24rpx;color:#666;white-space:nowrap;flex-shrink:0;margin-right:8rpx;line-height:1.2;padding:0 4rpx}.toolbar-input.data-v-5d9b5d15{flex:1;min-width:120rpx;max-width:200rpx;height:56rpx;line-height:56rpx;background-color:#f5f6fa;border-radius:8rpx;padding:0 12rpx;font-size:24rpx;border:1px solid transparent;box-sizing:border-box;flex-shrink:1}.toolbar-actions.data-v-5d9b5d15{display:flex;align-items:center;margin-left:auto;flex-shrink:0;gap:8rpx}.toolbar-btn.data-v-5d9b5d15{padding:0 12rpx;height:56rpx;min-width:56rpx;color:#2a68ff;display:flex;align-items:center;justify-content:center;gap:4rpx;font-size:24rpx;font-weight:400;line-height:1;box-sizing:border-box}.service-card.data-v-5d9b5d15{width:100%;box-sizing:border-box;background-color:#fff;border-radius:16rpx;padding:32rpx;margin-bottom:24rpx;box-shadow:0 2rpx 8rpx rgba(0,0,0,.04);overflow:visible;position:relative}.card-header.data-v-5d9b5d15{display:flex;justify-content:space-between;align-items:center;margin-bottom:20rpx;width:100%;box-sizing:border-box;padding:0;margin:0}.service-title.data-v-5d9b5d15{margin-top:16rpx;margin-bottom:8rpx}.service-title__text.data-v-5d9b5d15{font-size:28rpx;font-weight:600;color:#111827;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.staff-info.data-v-5d9b5d15{display:flex;align-items:center;flex:1;min-width:0;margin:0;padding:0}.staff-avatar.data-v-5d9b5d15{width:64rpx;height:64rpx;background-color:#2196f3;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-right:16rpx;margin-left:0;margin-top:0;margin-bottom:0;flex-shrink:0}.avatar-text.data-v-5d9b5d15{font-size:32rpx;color:#fff;font-weight:500}.staff-name.data-v-5d9b5d15{font-size:32rpx;font-weight:500;color:#333}.service-status-indicator.data-v-5d9b5d15{display:inline-flex;align-items:center;gap:6rpx;flex-shrink:0}.service-status-indicator__text.data-v-5d9b5d15{font-size:26rpx;color:#007aff;white-space:nowrap}.service-actions-row.data-v-5d9b5d15{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:12rpx;margin-top:18rpx}.service-action-btn.data-v-5d9b5d15{padding:8rpx 18rpx;border-radius:10rpx;font-size:24rpx;line-height:1.2;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;background-color:#f8faff}.service-action-btn--record.data-v-5d9b5d15{color:#007aff;border-color:rgba(0,122,255,.22)}.service-action-btn--recording.data-v-5d9b5d15{color:#ff3b30;border-color:rgba(255,59,48,.25)}.service-action-btn--supplement.data-v-5d9b5d15{color:#10b981;border-color:rgba(16,185,129,.25)}.service-action-btn--upload.data-v-5d9b5d15{color:#7c3aed;border-color:rgba(124,58,237,.25)}.service-action-btn--finish.data-v-5d9b5d15{color:#ef4444;border-color:rgba(239,68,68,.28);background-color:#fff7f7}.customer-tags.data-v-5d9b5d15{display:flex;flex-wrap:wrap;margin-bottom:20rpx;gap:12rpx;box-sizing:border-box;margin-left:0;margin-right:0;padding:0;width:100%;max-width:100%}.customer-info.data-v-5d9b5d15{margin-bottom:16rpx;display:flex;flex-direction:column;gap:8rpx;box-sizing:border-box;margin-left:0;margin-right:0;padding:0;width:100%;max-width:100%}.customer-name.data-v-5d9b5d15,.customer-phone.data-v-5d9b5d15{font-size:28rpx;color:#555}.tag-item.data-v-5d9b5d15{padding:8rpx 16rpx;border-radius:8rpx;box-sizing:border-box;word-wrap:break-word;word-break:break-all;display:inline-block;max-width:100%}.tag-blue.data-v-5d9b5d15{background-color:#e3f2fd}.tag-blue text.data-v-5d9b5d15{font-size:24rpx;color:#1976d2}.tag-orange.data-v-5d9b5d15{background-color:#fff3e0}.tag-orange text.data-v-5d9b5d15{font-size:24rpx;color:#f57c00}.ai-alert.data-v-5d9b5d15{border-radius:8rpx;padding:20rpx;margin-bottom:20rpx}.alert-risk-box.data-v-5d9b5d15{background-color:#fff5f5}.alert-reminder-box.data-v-5d9b5d15{background-color:#f5f5f5}.alert-header.data-v-5d9b5d15{display:flex;align-items:center;margin-bottom:12rpx}.alert-icon.data-v-5d9b5d15{margin-right:8rpx}.icon-circle.data-v-5d9b5d15{width:24rpx;height:24rpx;border:2rpx solid #333;border-radius:50%;position:relative}.icon-circle.data-v-5d9b5d15:after{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:8rpx;height:8rpx;background-color:#333;border-radius:50%}.alert-title.data-v-5d9b5d15{font-size:28rpx;font-weight:500;color:#333}.alert-content.data-v-5d9b5d15{font-size:26rpx;line-height:1.6}.alert-risk-text.data-v-5d9b5d15{color:#ff5722}.alert-reminder-text.data-v-5d9b5d15{color:#666}.alert-list.data-v-5d9b5d15{display:flex;flex-direction:column;gap:8rpx}.alert-item.data-v-5d9b5d15{display:flex;align-items:flex-start}.alert-item.data-v-5d9b5d15:before{content:"\2022";margin-right:8rpx;color:#666}.alert-item text.data-v-5d9b5d15{font-size:26rpx;color:#666;line-height:1.6}.service-duration.data-v-5d9b5d15{padding-top:16rpx;border-top:1px solid #F0F0F0}.service-duration text.data-v-5d9b5d15{font-size:26rpx;color:#999}.service-status-empty.data-v-5d9b5d15,.service-status-loading-more.data-v-5d9b5d15{padding:48rpx 0;text-align:center;color:#999;font-size:28rpx}.recording-realtime.data-v-5d9b5d15{margin-top:12rpx;display:flex;align-items:center;gap:20rpx}.recording-realtime text.data-v-5d9b5d15{font-size:24rpx;color:#ff3b30}.supplement-dialog-mask.data-v-5d9b5d15{position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:1000}.supplement-dialog.data-v-5d9b5d15{width:640rpx;max-height:80vh;background-color:#fff;border-radius:24rpx;overflow:hidden;display:flex;flex-direction:column}.supplement-dialog__header.data-v-5d9b5d15{display:flex;align-items:center;justify-content:space-between;padding:32rpx 32rpx 24rpx;border-bottom:1px solid #F0F0F0}.supplement-dialog__title.data-v-5d9b5d15{font-size:32rpx;font-weight:500;color:#333}.supplement-dialog__close.data-v-5d9b5d15{width:48rpx;height:48rpx;display:flex;align-items:center;justify-content:center}.supplement-dialog__body.data-v-5d9b5d15{flex:1;padding:32rpx;overflow-y:auto}.supplement-form-item.data-v-5d9b5d15{margin-bottom:32rpx}.supplement-form-item.data-v-5d9b5d15:last-child{margin-bottom:0}.supplement-form-item__label.data-v-5d9b5d15{display:block;font-size:28rpx;color:#333;font-weight:500;margin-bottom:16rpx}.supplement-form-item__input.data-v-5d9b5d15{width:100%;height:88rpx;background-color:#f9fafb;border-radius:12rpx;padding:0 24rpx;font-size:28rpx;color:#333;box-sizing:border-box}.supplement-form-item__textarea.data-v-5d9b5d15{width:100%;min-height:160rpx;background-color:#f9fafb;border-radius:12rpx;padding:24rpx;font-size:28rpx;color:#333;box-sizing:border-box;line-height:1.6}.supplement-dialog__footer.data-v-5d9b5d15{display:flex;gap:24rpx;padding:24rpx 32rpx 32rpx;border-top:1px solid #F0F0F0}.supplement-dialog__btn.data-v-5d9b5d15{flex:1;height:88rpx;border-radius:12rpx;display:flex;align-items:center;justify-content:center;font-size:32rpx;font-weight:500}.supplement-dialog__btn--cancel.data-v-5d9b5d15{background-color:#f3f4f6;color:#6b7280}.supplement-dialog__btn--save.data-v-5d9b5d15{background-color:#4c8dff;color:#fff}.supplement-dialog__btn.data-v-5d9b5d15:active{opacity:.7}
+.service-list-container.data-v-8e98b19a{height:100%;width:100%;display:flex;flex-direction:column;background-color:#f5f5f5;padding:0 16rpx;box-sizing:border-box}.service-status-toolbar.data-v-8e98b19a{display:flex;flex-wrap:nowrap;align-items:center;gap:8rpx;padding:12rpx 8rpx;margin-bottom:24rpx;background-color:#f8f8fa;border-radius:8rpx;border:1px solid #EFEFF2;overflow-x:auto;min-height:64rpx;box-sizing:border-box;flex-shrink:0}.service-list.data-v-8e98b19a{flex:1;background-color:transparent;box-sizing:border-box;overflow-y:auto}.toolbar-total.data-v-8e98b19a{font-size:24rpx;color:#666;white-space:nowrap;flex-shrink:0;margin-right:8rpx;line-height:1.2;padding:0 4rpx}.toolbar-input.data-v-8e98b19a{flex:1;min-width:120rpx;max-width:200rpx;height:56rpx;line-height:56rpx;background-color:#f5f6fa;border-radius:8rpx;padding:0 12rpx;font-size:24rpx;border:1px solid transparent;box-sizing:border-box;flex-shrink:1}.toolbar-actions.data-v-8e98b19a{display:flex;align-items:center;margin-left:auto;flex-shrink:0;gap:8rpx}.toolbar-btn.data-v-8e98b19a{padding:0 12rpx;height:56rpx;min-width:56rpx;color:#2a68ff;display:flex;align-items:center;justify-content:center;gap:4rpx;font-size:24rpx;font-weight:400;line-height:1;box-sizing:border-box}.service-card.data-v-8e98b19a{width:100%;box-sizing:border-box;background-color:#fff;border-radius:16rpx;padding:32rpx;margin-bottom:24rpx;box-shadow:0 2rpx 8rpx rgba(0,0,0,.04);overflow:visible;position:relative}.card-header.data-v-8e98b19a{display:flex;justify-content:space-between;align-items:center;margin-bottom:20rpx;width:100%;box-sizing:border-box;padding:0;margin:0}.service-title.data-v-8e98b19a{margin-top:16rpx;margin-bottom:8rpx}.service-title__text.data-v-8e98b19a{font-size:28rpx;font-weight:600;color:#111827;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.staff-info.data-v-8e98b19a{display:flex;align-items:center;flex:1;min-width:0;margin:0;padding:0}.staff-avatar.data-v-8e98b19a{width:64rpx;height:64rpx;background-color:#2196f3;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-right:16rpx;margin-left:0;margin-top:0;margin-bottom:0;flex-shrink:0}.avatar-text.data-v-8e98b19a{font-size:32rpx;color:#fff;font-weight:500}.staff-name.data-v-8e98b19a{font-size:32rpx;font-weight:500;color:#333}.service-status-indicator.data-v-8e98b19a{display:inline-flex;align-items:center;gap:6rpx;flex-shrink:0}.service-status-indicator__text.data-v-8e98b19a{font-size:26rpx;color:#007aff;white-space:nowrap}.service-actions-row.data-v-8e98b19a{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:12rpx;margin-top:18rpx}.service-action-btn.data-v-8e98b19a{padding:8rpx 18rpx;border-radius:10rpx;font-size:24rpx;line-height:1.2;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;background-color:#f8faff}.service-action-btn--record.data-v-8e98b19a{color:#007aff;border-color:rgba(0,122,255,.22)}.service-action-btn--recording.data-v-8e98b19a{color:#ff3b30;border-color:rgba(255,59,48,.25)}.service-action-btn--supplement.data-v-8e98b19a{color:#10b981;border-color:rgba(16,185,129,.25)}.service-action-btn--upload.data-v-8e98b19a{color:#7c3aed;border-color:rgba(124,58,237,.25)}.service-action-btn--finish.data-v-8e98b19a{color:#ef4444;border-color:rgba(239,68,68,.28);background-color:#fff7f7}.customer-tags.data-v-8e98b19a{display:flex;flex-wrap:wrap;margin-bottom:20rpx;gap:12rpx;box-sizing:border-box;margin-left:0;margin-right:0;padding:0;width:100%;max-width:100%}.customer-info.data-v-8e98b19a{margin-bottom:16rpx;display:flex;flex-direction:column;gap:8rpx;box-sizing:border-box;margin-left:0;margin-right:0;padding:0;width:100%;max-width:100%}.customer-name.data-v-8e98b19a,.customer-phone.data-v-8e98b19a{font-size:28rpx;color:#555}.tag-item.data-v-8e98b19a{padding:8rpx 16rpx;border-radius:8rpx;box-sizing:border-box;word-wrap:break-word;word-break:break-all;display:inline-block;max-width:100%}.tag-blue.data-v-8e98b19a{background-color:#e3f2fd}.tag-blue text.data-v-8e98b19a{font-size:24rpx;color:#1976d2}.tag-orange.data-v-8e98b19a{background-color:#fff3e0}.tag-orange text.data-v-8e98b19a{font-size:24rpx;color:#f57c00}.ai-alert.data-v-8e98b19a{border-radius:8rpx;padding:20rpx;margin-bottom:20rpx}.alert-risk-box.data-v-8e98b19a{background-color:#fff5f5}.alert-reminder-box.data-v-8e98b19a{background-color:#f5f5f5}.alert-header.data-v-8e98b19a{display:flex;align-items:center;margin-bottom:12rpx}.alert-icon.data-v-8e98b19a{margin-right:8rpx}.icon-circle.data-v-8e98b19a{width:24rpx;height:24rpx;border:2rpx solid #333;border-radius:50%;position:relative}.icon-circle.data-v-8e98b19a:after{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:8rpx;height:8rpx;background-color:#333;border-radius:50%}.alert-title.data-v-8e98b19a{font-size:28rpx;font-weight:500;color:#333}.alert-content.data-v-8e98b19a{font-size:26rpx;line-height:1.6}.alert-risk-text.data-v-8e98b19a{color:#ff5722}.alert-reminder-text.data-v-8e98b19a{color:#666}.alert-list.data-v-8e98b19a{display:flex;flex-direction:column;gap:8rpx}.alert-item.data-v-8e98b19a{display:flex;align-items:flex-start}.alert-item.data-v-8e98b19a:before{content:"\2022";margin-right:8rpx;color:#666}.alert-item text.data-v-8e98b19a{font-size:26rpx;color:#666;line-height:1.6}.service-duration.data-v-8e98b19a{padding-top:16rpx;border-top:1px solid #F0F0F0}.service-duration text.data-v-8e98b19a{font-size:26rpx;color:#999}.service-status-empty.data-v-8e98b19a,.service-status-loading-more.data-v-8e98b19a{padding:48rpx 0;text-align:center;color:#999;font-size:28rpx}.recording-realtime.data-v-8e98b19a{margin-top:12rpx;display:flex;align-items:center;gap:20rpx}.recording-realtime text.data-v-8e98b19a{font-size:24rpx;color:#ff3b30}.upload-result-list.data-v-8e98b19a{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.data-v-8e98b19a{display:flex;flex-direction:column;gap:4rpx}.upload-result-item__main.data-v-8e98b19a{font-size:24rpx;color:#374151}.upload-result-item__sub.data-v-8e98b19a{font-size:22rpx;color:#6b7280}.supplement-dialog-mask.data-v-8e98b19a{position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:1000}.supplement-dialog.data-v-8e98b19a{width:640rpx;max-height:80vh;background-color:#fff;border-radius:24rpx;overflow:hidden;display:flex;flex-direction:column}.supplement-dialog__header.data-v-8e98b19a{display:flex;align-items:center;justify-content:space-between;padding:32rpx 32rpx 24rpx;border-bottom:1px solid #F0F0F0}.supplement-dialog__title.data-v-8e98b19a{font-size:32rpx;font-weight:500;color:#333}.supplement-dialog__close.data-v-8e98b19a{width:48rpx;height:48rpx;display:flex;align-items:center;justify-content:center}.supplement-dialog__body.data-v-8e98b19a{flex:1;padding:32rpx;overflow-y:auto}.supplement-form-item.data-v-8e98b19a{margin-bottom:32rpx}.supplement-form-item.data-v-8e98b19a:last-child{margin-bottom:0}.supplement-form-item__label.data-v-8e98b19a{display:block;font-size:28rpx;color:#333;font-weight:500;margin-bottom:16rpx}.supplement-form-item__input.data-v-8e98b19a{width:100%;height:88rpx;background-color:#f9fafb;border-radius:12rpx;padding:0 24rpx;font-size:28rpx;color:#333;box-sizing:border-box}.supplement-form-item__textarea.data-v-8e98b19a{width:100%;min-height:160rpx;background-color:#f9fafb;border-radius:12rpx;padding:24rpx;font-size:28rpx;color:#333;box-sizing:border-box;line-height:1.6}.supplement-dialog__footer.data-v-8e98b19a{display:flex;gap:24rpx;padding:24rpx 32rpx 32rpx;border-top:1px solid #F0F0F0}.supplement-dialog__btn.data-v-8e98b19a{flex:1;height:88rpx;border-radius:12rpx;display:flex;align-items:center;justify-content:center;font-size:32rpx;font-weight:500}.supplement-dialog__btn--cancel.data-v-8e98b19a{background-color:#f3f4f6;color:#6b7280}.supplement-dialog__btn--save.data-v-8e98b19a{background-color:#4c8dff;color:#fff}.supplement-dialog__btn.data-v-8e98b19a:active{opacity:.7}