音频转文本
This commit is contained in:
@@ -83,7 +83,15 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="audio-item-info">
|
<view class="audio-item-info">
|
||||||
<text class="audio-item-text" v-if="item.recordingText">{{ truncateText(item.recordingText, 30) }}</text>
|
<text class="audio-item-text" v-if="item.recordingText">{{ truncateText(item.recordingText, 30) }}</text>
|
||||||
<text class="audio-item-text audio-item-text--empty" v-else>暂无录音文本</text>
|
<view class="audio-item-transcribe" v-else>
|
||||||
|
<view
|
||||||
|
class="transcribe-btn"
|
||||||
|
:class="{ 'transcribe-btn--loading': transcribingIds.includes(item.id || item.segmentId) }"
|
||||||
|
@click.stop="transcribeAudio(item, index)">
|
||||||
|
<text v-if="!transcribingIds.includes(item.id || item.segmentId)">转文本</text>
|
||||||
|
<text v-else>处理中...</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="audio-item-meta">
|
<view class="audio-item-meta">
|
||||||
<text class="audio-meta-item" v-if="item.endTime">{{ formatDateTime(item.endTime) }}</text>
|
<text class="audio-meta-item" v-if="item.endTime">{{ formatDateTime(item.endTime) }}</text>
|
||||||
@@ -466,6 +474,7 @@
|
|||||||
currentAudioUrl: null, // 当前音频URL(用于清理Blob URL)
|
currentAudioUrl: null, // 当前音频URL(用于清理Blob URL)
|
||||||
showTextModal: false, // 是否显示文本内容弹框
|
showTextModal: false, // 是否显示文本内容弹框
|
||||||
currentRecordingText: '', // 当前显示的录音文本内容
|
currentRecordingText: '', // 当前显示的录音文本内容
|
||||||
|
transcribingIds: [], // 正在转文本的录音ID列表
|
||||||
customerList: [
|
customerList: [
|
||||||
{
|
{
|
||||||
name: '李女士',
|
name: '李女士',
|
||||||
@@ -1048,6 +1057,106 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 转文本
|
||||||
|
async transcribeAudio(item, index) {
|
||||||
|
try {
|
||||||
|
// 获取录音ID(可能是 id 或 segmentId)
|
||||||
|
const audioId = item.id || item.segmentId;
|
||||||
|
if (!audioId) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '无法获取录音ID',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果正在转文本,则不再处理
|
||||||
|
if (this.transcribingIds.includes(audioId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到转文本列表
|
||||||
|
this.transcribingIds.push(audioId);
|
||||||
|
|
||||||
|
// 调用转文本接口:/api/audioManagementSegments/transcribe/{id}
|
||||||
|
const url = getApiUrl(`/api/audioManagementSegments/transcribe/${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: 30000 // 转文本可能需要较长时间
|
||||||
|
});
|
||||||
|
|
||||||
|
// 从转文本列表中移除
|
||||||
|
const idIndex = this.transcribingIds.indexOf(audioId);
|
||||||
|
if (idIndex > -1) {
|
||||||
|
this.transcribingIds.splice(idIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.statusCode === 200 && res.data && res.data.success) {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.message || '转文本请求已提交',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果返回了更新后的数据,更新列表中的该项
|
||||||
|
if (res.data.data) {
|
||||||
|
// 更新列表中的该项
|
||||||
|
this.$set(this.audioSegmentsList, index, {
|
||||||
|
...item,
|
||||||
|
...res.data.data
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 如果没有返回数据,可以刷新整个列表
|
||||||
|
// 或者等待用户手动刷新
|
||||||
|
// 这里先不自动刷新,因为转文本是后台处理
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data?.message || '转文本请求失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 从转文本列表中移除
|
||||||
|
const audioId = item.id || item.segmentId;
|
||||||
|
const idIndex = this.transcribingIds.indexOf(audioId);
|
||||||
|
if (idIndex > -1) {
|
||||||
|
this.transcribingIds.splice(idIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('转文本失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: `转文本失败: ${error.errMsg || error.message || '未知错误'}`,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
// 格式化时长(秒转换为时分秒)
|
// 格式化时长(秒转换为时分秒)
|
||||||
formatDuration(seconds) {
|
formatDuration(seconds) {
|
||||||
if (!seconds) return '00:00:00';
|
if (!seconds) return '00:00:00';
|
||||||
@@ -3254,6 +3363,38 @@
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audio-item-transcribe {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcribe-btn {
|
||||||
|
padding: 12rpx 24rpx;
|
||||||
|
background-color: #007AFF;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s, opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcribe-btn:active {
|
||||||
|
background-color: #0056CC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcribe-btn--loading {
|
||||||
|
opacity: 0.6;
|
||||||
|
background-color: #999;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcribe-btn text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.audio-item-meta {
|
.audio-item-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user