1、具体实现如下图:
2、实现功能:
- 对话框内的当前播放语句随音频播放而自动滑动到顶部位置;
- 亦可前进或后退音频时,对话框定位到音频此时播放语句;
- 可以在播放的时候上下滚动对话框,一定的时间内不操作又再次定位到音频正播放的位置;
- css区分已播放和未播放的语句,暂停播放音频后,自动滑动停止;
3、代码:
HTML
<div class="IM_box">
<div class="IM_header">转写记录</div>
<div class="IM_content" id="IM_content">
<div :key="item.ownId" v-for="item in conversationList">
<div class="left_person" v-if="item.roleType == 2">
<img
src="@/assets/images/touxiang_moren.png"
class="head_potraite"
/>
<div style="width: 100%" :id="item.idSelector">
<p class="time">{{ getTime(item.beginTime) }}</p>
<div
class="text_info"
:style="{
background: item.isPlayed ? '#bab0b0' : '',
color: item.isPlayed ? 'white' : '',
}"
>
{{ item.content }}
</div>
</div>
</div>
<div class="right_person" v-else>
<div class="content" :id="item.idSelector">
<p class="time" style="text-align: right">
{{ getTime(item.beginTime) }}
</p>
<div
class="text_info"
:style="{ background: item.isPlayed ? '#1f62a5' : '' }"
>
{{ item.content }}
</div>
</div>
<img
src="@/assets/images/header_kefu.png"
class="head_potraite"
/>
</div>
</div>
</div></div
>
CSS
.IM_box {
border: 1px solid #eeeeee;
display: flex;
flex-direction: column;
.IM_header {
width: 100%;
height: 58px;
border-bottom: 1px solid #eeeeee;
line-height: 58px;
padding-left: 20px;
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #333333;
box-sizing: border-box;
}
.IM_content {
position: relative;
height: 505px;
overflow-y: scroll;
padding: 33px 17px 0px 17px;
box-sizing: border-box;
&::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
-ms-overflow-style: none; /* IE 10+ */
scrollbar-width: none; /* Firefox */
.time {
margin-bottom: 5px !important;
}
.left_person {
display: flex;
margin-bottom: 20px;
clear: both;
.head_potraite {
margin-right: 12px;
}
.text_info {
background: #f9f9f9;
word-break: break-all;
color: #333333;
border: 1px solid #e8e8e8;
width: max-content;
}
}
.right_person {
display: flex;
width: 100%;
justify-content: flex-end;
margin-bottom: 20px;
float: right;
clear: both;
.content {
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.head_potraite {
margin-left: 12px;
}
.text_info {
background: #409efe;
color: #ffffff;
word-break: break-all;
}
}
.head_potraite {
width: 40px;
height: 40px;
border-radius: 50%;
}
.image_box {
img {
max-width: 200px;
max-height: 320px;
}
}
.file_box {
background: #f9f9f9;
border: 1px solid #e8e8e8;
padding: 10px;
box-sizing: border-box;
max-width: 220px;
border-radius: 6px;
.file_box_inner {
display: flex;
align-items: center;
margin-bottom: 8px;
.iconfont {
font-size: 24px;
margin-right: 5px;
}
.file_name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.text_info {
max-width: 60%;
padding: 14px 13px;
box-sizing: border-box;
border-radius: 6px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
}
}
}
JavaScript
// 监听音频播放
subscribeAudio() {
var audioPlayer = document.getElementById("player");
let _this = this;
let justOne = null;
audioPlayer.addEventListener("timeupdate", function () {
let curTime = Math.floor(this.currentTime); //监听audio时间变化事件,this.currentTime其中一个秒数的会监听到4次
//justOne用来控制一个秒数的只执行一次筛选任务
if (justOne != curTime) {
// console.log(curTime, "当前秒时");
justOne = curTime;
// secStamp是当前对话的秒时,_this.conversationList为对话列表,后台返的数据
let obj = _this.conversationList.filter(
(xtem) => xtem.secStamp == curTime
);
_this.conversationList.forEach((item) => {
if (item.secStamp <= curTime) {
_this.$set(item, "isPlayed", true);
} else {
_this.$set(item, "isPlayed", false);
}
});
// console.log("对象值", obj);
// console.log("数组", _this.conversationList);
if (obj.length > 0) {
obj.forEach((x) => {
_this.slideConversation(x.idSelector);
});
}
}
});
},
// 滑动聊天记录
slideConversation(sessionItemId) {
let node = document.querySelector(`#${sessionItemId}`);
this.IM_content.scroll({ top: node.offsetTop, behavior: "smooth" });
},
this.conversationList数据结构
数据处理
this.conversationList = res.data.itemList
.filter((item) => item.content)
.map((x) => {
return Object.assign(x, {
idSelector: `selector${x.sessionItemId}`,
secStamp: this.msTosec(x.beginTime),
});
});
// 毫秒转秒
msTosec(ms) {
return Math.trunc(ms / 1000);
},