From 248dfd2d60e6e4caa83e1e5c869bdcaf468881cd Mon Sep 17 00:00:00 2001 From: zhonghua1 Date: Fri, 2 Jan 2026 22:27:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=92=AD=E6=94=BE=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=98=BE=E7=A4=BA=E4=B8=8D=E5=AE=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/customer/components/ServiceList.vue | 12 +- pages/customer/customer.vue | 227 ++++++++++++++++++++-- 2 files changed, 226 insertions(+), 13 deletions(-) diff --git a/pages/customer/components/ServiceList.vue b/pages/customer/components/ServiceList.vue index db367a3..22a36c1 100644 --- a/pages/customer/components/ServiceList.vue +++ b/pages/customer/components/ServiceList.vue @@ -32,7 +32,8 @@ class="service-item" v-for="(item, index) in list" :key="index" - :class="{ 'service-item--active': selectedServiceItem && selectedServiceItem.id === item.id }"> + :class="{ 'service-item--active': selectedServiceItem && selectedServiceItem.id === item.id }" + @click="handleItemClick(item)"> {{ item.title }} @@ -167,6 +168,15 @@ action: 'audio', item: item }); + }, + // 处理列表项点击 + handleItemClick(item) { + // 如果菜单正在显示,不触发列表项点击 + if (this.showServiceActionMenu) { + return; + } + // 触发列表项点击事件,打开详情页面 + this.$emit('itemClick', item); } } } diff --git a/pages/customer/customer.vue b/pages/customer/customer.vue index d72f117..fc12fe5 100644 --- a/pages/customer/customer.vue +++ b/pages/customer/customer.vue @@ -68,18 +68,16 @@ - + - - - + + + {{ playingAudioId === (item.id || item.segmentId) ? '暂停' : '播放' }} + {{ formatAudioFileName(item.audioFileOriginalName) }} @@ -829,8 +827,194 @@ }, // 关闭录音列表弹窗 closeAudioList() { + // 关闭弹窗时,如果正在播放,先停止播放 + if (this.playingAudioId) { + this.stopAudioPlay({ id: this.playingAudioId }); + } this.$refs.audioListPopup.close(); }, + // 切换录音播放/暂停 + async toggleAudioPlay(item, index) { + try { + // 获取录音ID(可能是 id 或 segmentId) + const audioId = item.id || item.segmentId; + if (!audioId) { + console.warn('录音项缺少ID:', item); + uni.showToast({ + title: '无法获取录音ID', + icon: 'none' + }); + return; + } + + // 如果点击的是当前正在播放的录音,则暂停 + if (this.playingAudioId === audioId) { + await this.stopAudioPlay(item); + } else { + // 如果其他录音正在播放,先停止 + if (this.playingAudioId) { + await this.stopAudioPlay({ id: this.playingAudioId }); + } + // 开始播放新的录音 + await this.startAudioPlay(item); + } + } catch (error) { + console.error('切换播放状态失败:', error); + uni.showToast({ + title: '操作失败', + icon: 'none' + }); + } + }, + // 开始播放录音 + async startAudioPlay(item) { + try { + // 获取录音ID(可能是 id 或 segmentId) + const audioId = item.id || item.segmentId; + if (!audioId) { + console.warn('录音项缺少ID:', item); + uni.showToast({ + title: '无法获取录音ID', + icon: 'none' + }); + return; + } + + uni.showLoading({ + title: '播放中...' + }); + + // 调用播放接口:/api/audioManagementSegments/play/{id} + const url = getApiUrl(`/api/audioManagementSegments/play/${audioId}`); + + // 获取认证信息 + let tenantId = ''; + let token = ''; + try { + tenantId = uni.getStorageSync('backend-tenant-id') || ''; + token = uni.getStorageSync('backend-token') || ''; + } catch (e) { + console.error('获取认证信息失败:', e); + } + + // 构建请求头 + const headers = { + 'Content-Type': 'application/json' + }; + if (token) { + headers['Authorization'] = `Bearer ${token}`; + } + if (tenantId) { + headers['X-Tenant-Id'] = tenantId; + } + + const res = await uni.request({ + url: url, + method: 'POST', + header: headers, + timeout: 10000 + }); + + uni.hideLoading(); + + if (res.statusCode === 200 && res.data && res.data.success) { + // 设置当前播放的录音ID + this.playingAudioId = audioId; + uni.showToast({ + title: '开始播放', + icon: 'success', + duration: 1000 + }); + } else { + uni.showToast({ + title: res.data?.message || '播放失败', + icon: 'none' + }); + } + } catch (error) { + uni.hideLoading(); + console.error('播放录音失败:', error); + uni.showToast({ + title: `播放失败: ${error.errMsg || error.message || '未知错误'}`, + icon: 'none' + }); + } + }, + // 停止播放录音 + async stopAudioPlay(item) { + try { + // 获取录音ID(可能是 id 或 segmentId) + const audioId = item.id || item.segmentId; + if (!audioId) { + // 如果没有ID,直接清除播放状态 + this.playingAudioId = null; + return; + } + + uni.showLoading({ + title: '停止中...' + }); + + // 调用停止接口:/api/audioManagementSegments/stop/{id} + const url = getApiUrl(`/api/audioManagementSegments/stop/${audioId}`); + + // 获取认证信息 + let tenantId = ''; + let token = ''; + try { + tenantId = uni.getStorageSync('backend-tenant-id') || ''; + token = uni.getStorageSync('backend-token') || ''; + } catch (e) { + console.error('获取认证信息失败:', e); + } + + // 构建请求头 + const headers = { + 'Content-Type': 'application/json' + }; + if (token) { + headers['Authorization'] = `Bearer ${token}`; + } + if (tenantId) { + headers['X-Tenant-Id'] = tenantId; + } + + const res = await uni.request({ + url: url, + method: 'POST', + header: headers, + timeout: 10000 + }); + + uni.hideLoading(); + + if (res.statusCode === 200 && res.data && res.data.success) { + // 清除当前播放的录音ID + this.playingAudioId = null; + uni.showToast({ + title: '已停止', + icon: 'success', + duration: 1000 + }); + } else { + // 即使接口失败,也清除播放状态 + this.playingAudioId = null; + uni.showToast({ + title: res.data?.message || '停止失败', + icon: 'none' + }); + } + } catch (error) { + uni.hideLoading(); + // 即使接口失败,也清除播放状态 + this.playingAudioId = null; + console.error('停止播放失败:', error); + uni.showToast({ + title: `停止失败: ${error.errMsg || error.message || '未知错误'}`, + icon: 'none' + }); + } + }, // 格式化时长(秒转换为时分秒) formatDuration(seconds) { if (!seconds) return '00:00:00'; @@ -2950,6 +3134,7 @@ background-color: #FFFFFF; border-radius: 32rpx 32rpx 0 0; max-height: 90vh; + height: 90vh; display: flex; flex-direction: column; overflow: hidden; @@ -2960,6 +3145,8 @@ padding: 24rpx 32rpx; box-sizing: border-box; background-color: #F5F5F5; + min-height: 0; /* 配合 flex: 1 使用,确保可以滚动 */ + height: 100%; } .audio-list-item { @@ -2977,19 +3164,35 @@ } .audio-play-btn { - width: 48rpx; - height: 48rpx; + min-width: 80rpx; + height: 56rpx; + padding: 0 20rpx; display: flex; align-items: center; justify-content: center; - margin-right: 12rpx; + margin-right: 16rpx; cursor: pointer; - border-radius: 50%; + border-radius: 8rpx; transition: background-color 0.2s; + flex-shrink: 0; + background-color: #F5F5F5; + position: relative; + z-index: 1; } .audio-play-btn:active { - background-color: #F5F5F5; + background-color: #E0E0E0; + } + + .audio-play-text { + font-size: 24rpx; + color: #2A68FF; + font-weight: 500; + line-height: 1; + } + + .audio-play-text--playing { + color: #FF3B30; } .audio-item-name {