Skip to content
Merged

Dev #56

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [1.12.0](https://github.com/TencentCloudBase/cloudbase-agent-ui/compare/v1.11.0...v1.12.0) (2025-05-06)


### Features

* 增加倍速控制 ([99690d9](https://github.com/TencentCloudBase/cloudbase-agent-ui/commit/99690d97673423ba99e28b772962e300ce450dea))


### Bug Fixes

* fix doc ([72c6a53](https://github.com/TencentCloudBase/cloudbase-agent-ui/commit/72c6a53d226cf6426da4569be21d4bc77bba0827))

## [1.11.0](https://github.com/TencentCloudBase/cloudbase-agent-ui/compare/v1.10.1...v1.11.0) (2025-04-27)


Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 50 additions & 9 deletions apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ Component({
frameSize: 50,
},
voiceRecognizing: false,
speedList: [2, 1.5, 1.25, 1, 0.75],
},
attached: async function () {
const chatMode = this.data.chatMode;
Expand Down Expand Up @@ -1912,15 +1913,20 @@ Component({
if (audioContext.recordId === botRecordId) {
// 是则直接播放
audioContext.playStatus = 2;
audioContext.showSpeedList = false;
// audioContext.currentSpeed = 1.25;
this.setData({
audioContext: audioContext,
});
audioContext.context.playbackRate = audioContext.currentSpeed;
audioContext.context.play();
} else {
// 需销毁当前的 audioContext TODO:, 先测试复用content, 直接更换src
audioContext.context.stop(); // 旧的停止
audioContext.recordId = botRecordId;
audioContext.playStatus = 1;
audioContext.showSpeedList = false;
audioContext.currentSpeed = 1.25;
this.setData({
audioContext: {
...audioContext,
Expand All @@ -1930,6 +1936,7 @@ Component({
if (audioUrl) {
audioContext.context.src = audioUrl;
audioContext.context.seek(0); // 播放进度拉回到0
audioContext.context.playbackRate = audioContext.currentSpeed;
audioContext.context.play();
this.setData({
audioContext: {
Expand All @@ -1952,11 +1959,20 @@ Component({
const audioContext = {
recordId: botRecordId,
playStatus: 1,
showSpeedList: false,
currentSpeed: 1.25,
};
const innerAudioContent = wx.createInnerAudioContext({
const innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false, // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
});
innerAudioContent.onEnded(() => {
try {
await wx.setInnerAudioOption({
obeyMuteSwitch: false, // 是否遵循系统静音开关,默认遵循
});
} catch (e) {
console.log("不遵循静音模式控制", e);
}
innerAudioContext.onEnded(() => {
// 音频自然播放至结束触发
this.setData({
audioContext: {
Expand All @@ -1965,13 +1981,14 @@ Component({
},
});
});
audioContext.context = innerAudioContent;
audioContext.context = innerAudioContext;
this.setData({
audioContext: audioContext,
});
const audioUrl = await this.fetchAudioUrlByContent(botRecordId, content);
if (audioUrl) {
audioContext.context.src = audioUrl;
audioContext.context.playbackRate = audioContext.currentSpeed; // 播放速率,范围 0.5~2.0,默认 1.0
audioContext.context.play();
this.setData({
audioContext: {
Expand Down Expand Up @@ -2006,14 +2023,38 @@ Component({
console.log("暂停异常");
}
},
toggleSpeedList(e) {
this.setData({
audioContext: {
...this.data.audioContext,
showSpeedList: !this.data.audioContext.showSpeedList,
},
});
},
chooseSpeed(e) {
const speed = e.currentTarget.dataset.speed;
console.log("choose speed", speed);
const audioContext = this.data.audioContext;
audioContext.showSpeedList = !this.data.audioContext.showSpeedList;
audioContext.currentSpeed = Number(speed);
audioContext.context.pause();
audioContext.context.playbackRate = audioContext.currentSpeed;
audioContext.context.play();
this.setData({
audioContext: {
...this.data.audioContext,
...audioContext,
},
});
},
// 触摸开始
handleTouchStart(e) {
if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
return
return;
}
console.log("touchstart e", e);
const { clientY } = e.touches[0];
Expand All @@ -2033,12 +2074,12 @@ Component({
},
// 触摸移动
handleTouchMove(e) {
if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
return
return;
}
console.log("touchMove");
if (!this.data.longPressTriggered) return;
Expand All @@ -2061,12 +2102,12 @@ Component({
},
// 触摸结束
handleTouchEnd(e) {
if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
return
return;
}
console.log("touchEnd e", e);
clearTimeout(this.data.longPressTimer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,33 @@
<markdownPreview markdown="{{item.content||''}}"></markdownPreview>
<!-- 下面的按钮 -->
<view style="display: flex; gap: 10px;justify-content: flex;" wx:if="{{!item.hiddenBtnGround}}">
<image wx:if="{{item.error}}" mode="widthFix" bind:tap="showErrorMsg" src='./imgs/error-circle.svg' style="width: 36rpx; height: 36rpx;" data-content="{{item.error}}" data-reqid="{{item.reqId}}"/>
<image mode="widthFix" bind:tap="copyChatRecord" src='./imgs/copy.svg' style="width: 36rpx; height: 36rpx;" data-content="{{item.content}}" />
<image wx:if="{{item.error}}" mode="widthFix" bind:tap="showErrorMsg" src='./imgs/error-circle.svg' class="tool_btn" data-content="{{item.error}}" data-reqid="{{item.reqId}}"/>
<image mode="widthFix" bind:tap="copyChatRecord" src='./imgs/copy.svg' class="tool_btn" data-content="{{item.content}}" />
<block wx:if="{{!item.error}}">
<button class="share_btn" open-type="share">
<image mode="widthFix" src='./imgs/share.svg' style="width: 36rpx; height: 36rpx;vertical-align: top;" bind:tap="share" />
<image mode="widthFix" src='./imgs/share.svg' class="tool_btn" style="vertical-align: top;" bind:tap="share" />
</button>
<block wx:if="{{chatMode=== 'bot'}}">
<image mode="widthFix" bind:tap="openFeedback" data-feedbackType="upvote" data-feedbackRecordId="{{item.record_id}}" src='./imgs/thumb-up.svg' style="width: 36rpx; height: 36rpx;" />
<image mode="widthFix" bind:tap="openFeedback" data-feedbackType="downvote" data-feedbackRecordId="{{item.record_id}}" src='./imgs/thumb-down.svg' style="width: 36rpx; height: 36rpx;" />
<image wx:if="{{audioContext.recordId !== item.record_id || audioContext.playStatus === 0}}" mode="widthFix" bind:tap="handlePlayAudio" data-content="{{item.content}}" data-recordId="{{item.record_id}}" src='./imgs/play.svg' style="width: 36rpx; height: 36rpx;" />
<image wx:elif="{{audioContext.playStatus === 1}}" mode="widthFix" src='./imgs/loading.svg' style="width: 36rpx; height: 36rpx;" />
<image wx:else mode="widthFix" bind:tap="handlePauseAudio" data-recordId="{{item.record_id}}" src='./imgs/pause.svg' style="width: 36rpx; height: 36rpx;" />
<image mode="widthFix" bind:tap="openFeedback" data-feedbackType="upvote" data-feedbackRecordId="{{item.record_id}}" src='./imgs/thumb-up.svg' class="tool_btn" />
<image mode="widthFix" bind:tap="openFeedback" data-feedbackType="downvote" data-feedbackRecordId="{{item.record_id}}" src='./imgs/thumb-down.svg' class="tool_btn" />
<image wx:if="{{audioContext.recordId !== item.record_id || audioContext.playStatus === 0}}" mode="widthFix" bind:tap="handlePlayAudio" data-content="{{item.content}}" data-recordId="{{item.record_id}}" src='./imgs/sound.svg' class="tool_btn" />
<image wx:elif="{{audioContext.playStatus === 1}}" mode="widthFix" src='./imgs/loading.svg' class="tool_btn" />
<view wx:else class="playing_btn">
<image style="width: 36rpx;height: 36rpx;" mode="widthFix" bind:tap="handlePauseAudio" data-recordId="{{item.record_id}}" src='./imgs/pause.svg' />
<image style="width: 30rpx;height: 30rpx" src="./imgs/playing.svg" mode="widthFix"/>
<!-- 倍速切换按钮 -->
<view class="speed-switch" bindtap="toggleSpeedList" data-recordId="{{item.record_id}}">

<text class="speed-label">{{audioContext.currentSpeed || '1'}}</text>X
</view>
<!-- 倍速弹窗 -->
<view wx:if="{{audioContext.showSpeedList && audioContext.recordId === item.record_id}}" class="speed-popup">
<view wx:for="{{speedList}}" wx:key="item" class="speed-option" bindtap="chooseSpeed" data-speed="{{item}}" data-recordId="{{item.record_id}}">
<text>{{item}}X</text>
<image wx:if="{{audioContext.currentSpeed === item}}" src="./imgs/check.svg" style="width: 24rpx;height: 24rpx;margin-left:8rpx;" />
</view>
</view>
</view>
</block>
</block>
</view>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@
.share_btn {
background-color: #fff;
margin: 0px !important;
padding: 0px !important;
width: 36rpx !important;
height: 36rpx;
padding: 0rpx !important;
width: 64rpx !important;
height: 64rpx;
}

.avatar {
Expand Down Expand Up @@ -671,4 +671,65 @@
background-color: rgb(249, 251, 255);
filter: brightness(95%);
transition: filter 0.4s;
}

.tool_btn {
width: 36rpx;
height: 36rpx;
padding: 10rpx;
border: 1rpx solid #cfcdcd;
border-radius: 14rpx;
/* box-sizing: content-box; */
}

.playing_btn {
height: 36rpx;
padding: 10rpx;
border: 1rpx solid #cfcdcd;
border-radius: 14rpx;
display: flex;
align-items: center;
gap: 10rpx;
position: relative;
}

.speed-switch {
display: flex;
align-items: center;
margin-left: 0rpx;
padding: 4rpx 12rpx;
border-radius: 20rpx;
/* background: #f5f5f7; */
font-size: 26rpx;
color: #222;
cursor: pointer;
}

.speed-label {
margin-left: 6rpx;
}

.speed-popup {
position: absolute;
bottom: 48rpx;
right: 0;
background: #fff;
border-radius: 12rpx;
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
z-index: 99;
padding: 8rpx 0;
min-width: 80rpx;
}

.speed-option {
padding: 16rpx 32rpx;
font-size: 28rpx;
color: #222;
display: flex;
align-items: center;
justify-content: flex-start;
}

.speed-option:active {
background: #f0f0f0;
}
1 change: 1 addition & 0 deletions components/agent-ui/imgs/playing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions components/agent-ui/imgs/sound.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading