- 发布:2021-11-18 16:31
- 更新:2021-11-19 18:14
- 阅读:381
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: win 10 2004
HBuilderX类型: 正式
HBuilderX版本号: 3.2.12
手机系统: 全部
手机厂商: 苹果
页面类型: vue
vue版本: vue2
打包方式: 云端
项目创建方式: HBuilderX
测试过的手机:
示例代码:
<template>
<view class="voiceIntroduction_box">
<view class="voice_icon">
<!-- 进度条 -->
<view :class="{'cmd_progress':true,'progress_active':process}">
<!-- 录制进度条 -->
<u-circle-progress :percent="process" :inactive-color="originalColor" :active-color="processColor"
width="452" border-width="10" :duration="duration"></u-circle-progress>
</view>
<view class="voice_icon_inside">
<view class="voice_mic">
<image src="../static/image/mic.png" mode=""></image>
</view>
<view class="voice_time">
00:{{recorded.time}}
</view>
</view>
</view>
<view class="voice_btn">
<view v-show="recorded.show" @click.stop="handleRecord()" class="voice_again btn">
<image src="../static/image/again.png" mode="">
<text>重新录制</text>
</image>
</view>
<view @click.stop="handleClick()" class="voice_play btn">
<image :src="recorded.src" mode="">
<text>{{recorded.text}}</text>
</image>
</view>
<view v-show="recorded.show" @click.stop="uploadMp3Action()" class="voice_detertime btn">
<image src='../static/image/determine.png' mode="">
<text>确定</text>
</image>
</view>
</view>
{{process}}
<view class="person">
<textarea v-model="personal" placeholder="个人简介(自动保存)" placeholder-style="color:#999999" />
<image src="../../static/image/edit2.png" mode=""></image>
</view>
</view>
</template>
<script>
import permision from '@/js_sdk/wa-permission/permission.js'
const recorderManager = uni.getRecorderManager()
const innerAudioContext = uni.createInnerAudioContext()
innerAudioContext.autoplay = true
export default {
data() {
return {
recorded: {
show: false,
text: '点击录音',
time: '00',
src: '../static/image/play(1).png',
},
timer1: null,
timer2: null,
timer3: null,
timer4: null,
process: 0, //录制进度
processColor: '#6FECE4', //进度条颜色
originalColor: '#ffffff', //进度条底色
// innerbgColor: '#111',
time: null,
maxTime: 10000, //最大时间
duration: 10000, //进度条走一周需要的时间
voicePath: '', //录音文件路径
voiceStatus: 0, //录音状态
}
},
onLoad() {
if (this.$store.getters.getData.voice) {
this.voicePath = this.$store.getters.getData.voice
innerAudioContext.src = this.voicePath
innerAudioContext.onCanplay((res) => {
this.recorded.time = '0' + Math.floor(innerAudioContext.duration)
this.time = this.recorded.time
console.log(innerAudioContext);
console.log(2);
innerAudioContext.offCanplay(rej => {
console.log(1111);
})
})
this.finishRecord()
}
// console.log(this.time);
recorderManager.onStop((res) => {
this.voicePath = res.tempFilePath
})
},
computed: {
personal: {
get: function() {
return this.$store.getters.getData.personal_profile
},
set: function(data) {
this.$HTTP('/api/technician_index/edit_user_info', {
type: 8,
personal_profile: data
}, 'POST', true).then(res => {
console.log(res);
})
}
}
},
methods: {
handleClick() {
function judgeIosPermissionRecord() {
var result = false;
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
var permissionStatus = avaudio.recordPermission();
if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
uni.showModal({
title: '提示',
content: '录音权限已被禁用,是否前往开启?',
success: function(res) {
if (res.confirm) {
permision.gotoAppPermissionSetting()
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
} else {
result = true;
voFun()
console.log("麦克风权限已经开启");
}
plus.ios.deleteObject(avaudiosession);
return result;
}
permision.requestAndroidPermission('android.permission.RECORD_AUDIO').then(resolve => {
// console.log(JSON.stringify(resolve))
if (resolve == -1) {
uni.showModal({
title: '提示',
content: '录音权限已被禁用,是否前往开启?',
success: function(res) {
if (res.confirm) {
permision.gotoAppPermissionSetting()
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
} else if (resolve == 1) {
voFun()
}
}).catch(reject => {
console.log(JSON.stringify(reject))
})
let voFun = () => {
// console.log(this.voiceStatus);
// 开始录音
if (this.voiceStatus == 0) {
this.startRecord()
// 结束录音
} else if (this.voiceStatus == 1) {
this.finishRecord()
console.log(1);
// 试听录音
} else if (this.voiceStatus == 2) { //点击了试听录音
this.audition()
// 暂停/结束 试听
} else if (this.voiceStatus == 3) {
this.pauseAudition()
}
}
if (uni.getSystemInfoSync().brand == 'Apple') {
judgeIosPermissionRecord()
}
},
// 未录制状态
unRecord() {
this.voiceStatus = 0
innerAudioContext.stop()
this.voicePath = ''
innerAudioContext.src = this.voicePath
this.recorded.show = false
this.recorded.text = '点击录音'
this.recorded.time = '00'
this.time = null
this.recorded.src = '../static/image/play(1).png'
this.process = 0
},
// 开始录制状态
startRecord() {
this.voiceStatus = 1 //正在录制
this.recorded.src = '../static/image/finish.png'
console.log(1);
recorderManager.start(this.maxTime)
let v_time = 0
this.timer1 = setInterval(() => {
v_time++
if (v_time <= 9) {
this.recorded.time = '0' + v_time
} else {
this.recorded.time = v_time
}
this.time = v_time
}, 1000)
this.timer2 = setInterval(() => {
this.process += 1000 / this.maxTime
// console.log(this.process);
// 最大值为maxTime
if (this.process >= 100) {
this.process = 100
recorderManager.stop()
this.recorded.src = '../static/image/play.png'
this.recorded.show = true
clearInterval(this.timer2)
clearInterval(this.timer1)
this.recorded.text = '点击试听'
}
}, 10)
this.recorded.show = false
this.recorded.text = '点击结束录音'
},
// 结束录制状态
finishRecord() {
recorderManager.stop()
this.voiceStatus = 2 //点击了结束录音,此时可以试听
this.recorded.src = '../static/image/play.png'
this.recorded.show = true
this.time = this.recorded.time
clearInterval(this.timer2)
clearInterval(this.timer1)
this.recorded.text = '点击试听'
},
// 试听状态
audition() {
this.voiceStatus = 3
this.duration = this.time
this.process = 0
if (this.voicePath) {
innerAudioContext.src = this.voicePath
innerAudioContext.play()
}
this.recorded.src = '../static/image/pause.png'
// time?time:time= this.recorded.time;
this.recorded.time = '00'
this.recorded.text = '播放中'
let v_time = 0
let fn = () => {
// console.log(this.timer3);
if (v_time <= 9) {
this.recorded.time = '0' + v_time
} else {
this.recorded.time = v_time
}
if (v_time >= this.time) {
this.process = 100
this.recorded.src = '../static/image/play.png'
this.voiceStatus = 2
clearInterval(this.timer3)
this.recorded.text = '点击试听'
}
// console.log(this.process);
v_time++
return fn
}
this.timer3 = setInterval(fn(), 1000)
this.$nextTick(() => {
this.timer4 = setInterval(() => {
this.process += 1 / this.time
if (this.process >= 100) {
this.process = 100
clearInterval(this.timer4)
}
}, 10)
})
},
//暂停试听状态
pauseAudition() {
this.voiceStatus = 2 //暂停/结束 试听
innerAudioContext.pause()
if (this.voicePath) {
innerAudioContext.src = ''
innerAudioContext.src = this.voicePath
innerAudioContext.pause()
}
this.recorded.src = '../static/image/play.png'
this.recorded.text = '点击试听'
this.recorded.time = this.time
// console.log(this.recorded.time);
clearInterval(this.timer1)
clearInterval(this.timer2)
clearInterval(this.timer3)
this.process = 100
},
// 重新录制
handleRecord() {
this.unRecord()
clearInterval(this.timer1)
clearInterval(this.timer2)
},
uploadMp3Action() {
const tempFilePaths = this.voicePath;
uni.uploadFile({
url: this.$baseUrl + '/api/common/voice_upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths,
name: 'voiceurl',
header: {
'Api-Token': uni.getStorageSync('user_token')
},
success: (res) => {
uni.showLoading({
title: '上传中'
})
console.log(JSON.parse(res.data).data.voice_url);
this.$HTTP('/api/technician_index/edit_user_info', {
type: 3,
voice: JSON.parse(res.data).data.voice_url
}, "POST", true).then(res => {
uni.hideLoading()
if (res.data.code === 1000) {
uni.showToast({
title: '上传成功',
icon: 'success',
duration: 1000
})
setTimeout(() => {
uni.navigateBack({
delta: 1
})
}, 1000)
} else {
uni.showToast({
title: '上传失败',
icon: 'error',
duration: 1000
})
}
})
}
});
},
},
}
</script>
<style lang="less" scoped>
.voiceIntroduction_box {
text-align: center;
padding-top: 90rpx;
.voice_icon {
position: relative;
margin: auto;
width: 440rpx;
height: 440rpx;
background: #ffffff;
border-radius: 50%;
border: 2rpx solid rgba(111, 236, 228, 0.31);
margin-bottom: 145rpx;
.cmd_progress {
display: flex;
justify-content: center;
position: relative;
top: -6rpx;
left: 0rpx;
opacity: 0;
}
.progress_active {
opacity: 1;
transition: 10ms;
}
.voice_icon_inside {
position: absolute;
top: 30rpx;
left: 30rpx;
width: 380rpx;
height: 380rpx;
background: #FFFFFF;
box-shadow: 0px 0px 20px rgba(111, 236, 228, 0.31);
border-radius: 50%;
opacity: 1;
.voice_mic {
margin-top: 115rpx;
image {
width: 100rpx;
height: 120rpx;
opacity: 1;
}
}
.voice_time {
margin: 30rpx;
font-size: 36rpx;
font-weight: 400;
line-height: 50rpx;
color: #666666;
opacity: 1;
}
}
}
.voice_btn {
display: flex;
justify-content: center;
.btn {
// margin-right: 85rpx;
margin-top: 10rpx;
image {
width: 140rpx;
height: 140rpx;
display: inline-block;
}
text {
display: block;
margin-top: 30rpx;
font-size: 26rpx;
font-weight: 400;
line-height: 37rpx;
color: #CECECE;
opacity: 1;
}
}
.voice_detertime {
margin-right: 0;
}
.voice_play {
margin-top: 0;
margin-left: 85rpx;
margin-right: 85rpx;
image {
width: 160rpx;
height: 160rpx;
}
}
}
.person {
margin-top: 159rpx;
margin-left: 30rpx;
padding: 33rpx;
box-sizing: border-box;
text-align: left;
width: 690rpx;
height: 300rpx;
background: rgba(111, 236, 228, 0.12);
border-radius: 14rpx;
position: relative;
textarea {
width: 100%;
height: 100%;
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 400;
color: #000000;
opacity: 1;
}
image {
position: absolute;
width: 37.5rpx;
height: 37.5rpx;
right: 39rpx;
bottom: 30rpx;
}
}
}
</style>
<template>
<view class="voiceIntroduction_box">
<view class="voice_icon">
<!-- 进度条 -->
<view :class="{'cmd_progress':true,'progress_active':process}">
<!-- 录制进度条 -->
<u-circle-progress :percent="process" :inactive-color="originalColor" :active-color="processColor"
width="452" border-width="10" :duration="duration"></u-circle-progress>
</view>
<view class="voice_icon_inside">
<view class="voice_mic">
<image src="../static/image/mic.png" mode=""></image>
</view>
<view class="voice_time">
00:{{recorded.time}}
</view>
</view>
</view>
<view class="voice_btn">
<view v-show="recorded.show" @click.stop="handleRecord()" class="voice_again btn">
<image src="../static/image/again.png" mode="">
<text>重新录制</text>
</image>
</view>
<view @click.stop="handleClick()" class="voice_play btn">
<image :src="recorded.src" mode="">
<text>{{recorded.text}}</text>
</image>
</view>
<view v-show="recorded.show" @click.stop="uploadMp3Action()" class="voice_detertime btn">
<image src='../static/image/determine.png' mode="">
<text>确定</text>
</image>
</view>
</view>
{{process}}
<view class="person">
<textarea v-model="personal" placeholder="个人简介(自动保存)" placeholder-style="color:#999999" />
<image src="../../static/image/edit2.png" mode=""></image>
</view>
</view>
</template>
<script>
import permision from '@/js_sdk/wa-permission/permission.js'
const recorderManager = uni.getRecorderManager()
const innerAudioContext = uni.createInnerAudioContext()
innerAudioContext.autoplay = true
export default {
data() {
return {
recorded: {
show: false,
text: '点击录音',
time: '00',
src: '../static/image/play(1).png',
},
timer1: null,
timer2: null,
timer3: null,
timer4: null,
process: 0, //录制进度
processColor: '#6FECE4', //进度条颜色
originalColor: '#ffffff', //进度条底色
// innerbgColor: '#111',
time: null,
maxTime: 10000, //最大时间
duration: 10000, //进度条走一周需要的时间
voicePath: '', //录音文件路径
voiceStatus: 0, //录音状态
}
},
onLoad() {
if (this.$store.getters.getData.voice) {
this.voicePath = this.$store.getters.getData.voice
innerAudioContext.src = this.voicePath
innerAudioContext.onCanplay((res) => {
this.recorded.time = '0' + Math.floor(innerAudioContext.duration)
this.time = this.recorded.time
console.log(innerAudioContext);
console.log(2);
innerAudioContext.offCanplay(rej => {
console.log(1111);
})
})
this.finishRecord()
}
// console.log(this.time);
recorderManager.onStop((res) => {
this.voicePath = res.tempFilePath
})
},
computed: {
personal: {
get: function() {
return this.$store.getters.getData.personal_profile
},
set: function(data) {
this.$HTTP('/api/technician_index/edit_user_info', {
type: 8,
personal_profile: data
}, 'POST', true).then(res => {
console.log(res);
})
}
}
},
methods: {
handleClick() {
function judgeIosPermissionRecord() {
var result = false;
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
var permissionStatus = avaudio.recordPermission();
if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
uni.showModal({
title: '提示',
content: '录音权限已被禁用,是否前往开启?',
success: function(res) {
if (res.confirm) {
permision.gotoAppPermissionSetting()
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
} else {
result = true;
voFun()
console.log("麦克风权限已经开启");
}
plus.ios.deleteObject(avaudiosession);
return result;
}
permision.requestAndroidPermission('android.permission.RECORD_AUDIO').then(resolve => {
// console.log(JSON.stringify(resolve))
if (resolve == -1) {
uni.showModal({
title: '提示',
content: '录音权限已被禁用,是否前往开启?',
success: function(res) {
if (res.confirm) {
permision.gotoAppPermissionSetting()
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
} else if (resolve == 1) {
voFun()
}
}).catch(reject => {
console.log(JSON.stringify(reject))
})
let voFun = () => {
// console.log(this.voiceStatus);
// 开始录音
if (this.voiceStatus == 0) {
this.startRecord()
// 结束录音
} else if (this.voiceStatus == 1) {
this.finishRecord()
console.log(1);
// 试听录音
} else if (this.voiceStatus == 2) { //点击了试听录音
this.audition()
// 暂停/结束 试听
} else if (this.voiceStatus == 3) {
this.pauseAudition()
}
}
if (uni.getSystemInfoSync().brand == 'Apple') {
judgeIosPermissionRecord()
}
},
// 未录制状态
unRecord() {
this.voiceStatus = 0
innerAudioContext.stop()
this.voicePath = ''
innerAudioContext.src = this.voicePath
this.recorded.show = false
this.recorded.text = '点击录音'
this.recorded.time = '00'
this.time = null
this.recorded.src = '../static/image/play(1).png'
this.process = 0
},
// 开始录制状态
startRecord() {
this.voiceStatus = 1 //正在录制
this.recorded.src = '../static/image/finish.png'
console.log(1);
recorderManager.start(this.maxTime)
let v_time = 0
this.timer1 = setInterval(() => {
v_time++
if (v_time <= 9) {
this.recorded.time = '0' + v_time
} else {
this.recorded.time = v_time
}
this.time = v_time
}, 1000)
this.timer2 = setInterval(() => {
this.process += 1000 / this.maxTime
// console.log(this.process);
// 最大值为maxTime
if (this.process >= 100) {
this.process = 100
recorderManager.stop()
this.recorded.src = '../static/image/play.png'
this.recorded.show = true
clearInterval(this.timer2)
clearInterval(this.timer1)
this.recorded.text = '点击试听'
}
}, 10)
this.recorded.show = false
this.recorded.text = '点击结束录音'
},
// 结束录制状态
finishRecord() {
recorderManager.stop()
this.voiceStatus = 2 //点击了结束录音,此时可以试听
this.recorded.src = '../static/image/play.png'
this.recorded.show = true
this.time = this.recorded.time
clearInterval(this.timer2)
clearInterval(this.timer1)
this.recorded.text = '点击试听'
},
// 试听状态
audition() {
this.voiceStatus = 3
this.duration = this.time
this.process = 0
if (this.voicePath) {
innerAudioContext.src = this.voicePath
innerAudioContext.play()
}
this.recorded.src = '../static/image/pause.png'
// time?time:time= this.recorded.time;
this.recorded.time = '00'
this.recorded.text = '播放中'
let v_time = 0
let fn = () => {
// console.log(this.timer3);
if (v_time <= 9) {
this.recorded.time = '0' + v_time
} else {
this.recorded.time = v_time
}
if (v_time >= this.time) {
this.process = 100
this.recorded.src = '../static/image/play.png'
this.voiceStatus = 2
clearInterval(this.timer3)
this.recorded.text = '点击试听'
}
// console.log(this.process);
v_time++
return fn
}
this.timer3 = setInterval(fn(), 1000)
this.$nextTick(() => {
this.timer4 = setInterval(() => {
this.process += 1 / this.time
if (this.process >= 100) {
this.process = 100
clearInterval(this.timer4)
}
}, 10)
})
},
//暂停试听状态
pauseAudition() {
this.voiceStatus = 2 //暂停/结束 试听
innerAudioContext.pause()
if (this.voicePath) {
innerAudioContext.src = ''
innerAudioContext.src = this.voicePath
innerAudioContext.pause()
}
this.recorded.src = '../static/image/play.png'
this.recorded.text = '点击试听'
this.recorded.time = this.time
// console.log(this.recorded.time);
clearInterval(this.timer1)
clearInterval(this.timer2)
clearInterval(this.timer3)
this.process = 100
},
// 重新录制
handleRecord() {
this.unRecord()
clearInterval(this.timer1)
clearInterval(this.timer2)
},
uploadMp3Action() {
const tempFilePaths = this.voicePath;
uni.uploadFile({
url: this.$baseUrl + '/api/common/voice_upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths,
name: 'voiceurl',
header: {
'Api-Token': uni.getStorageSync('user_token')
},
success: (res) => {
uni.showLoading({
title: '上传中'
})
console.log(JSON.parse(res.data).data.voice_url);
this.$HTTP('/api/technician_index/edit_user_info', {
type: 3,
voice: JSON.parse(res.data).data.voice_url
}, "POST", true).then(res => {
uni.hideLoading()
if (res.data.code === 1000) {
uni.showToast({
title: '上传成功',
icon: 'success',
duration: 1000
})
setTimeout(() => {
uni.navigateBack({
delta: 1
})
}, 1000)
} else {
uni.showToast({
title: '上传失败',
icon: 'error',
duration: 1000
})
}
})
}
});
},
},
}
</script>
<style lang="less" scoped>
.voiceIntroduction_box {
text-align: center;
padding-top: 90rpx;
.voice_icon {
position: relative;
margin: auto;
width: 440rpx;
height: 440rpx;
background: #ffffff;
border-radius: 50%;
border: 2rpx solid rgba(111, 236, 228, 0.31);
margin-bottom: 145rpx;
.cmd_progress {
display: flex;
justify-content: center;
position: relative;
top: -6rpx;
left: 0rpx;
opacity: 0;
}
.progress_active {
opacity: 1;
transition: 10ms;
}
.voice_icon_inside {
position: absolute;
top: 30rpx;
left: 30rpx;
width: 380rpx;
height: 380rpx;
background: #FFFFFF;
box-shadow: 0px 0px 20px rgba(111, 236, 228, 0.31);
border-radius: 50%;
opacity: 1;
.voice_mic {
margin-top: 115rpx;
image {
width: 100rpx;
height: 120rpx;
opacity: 1;
}
}
.voice_time {
margin: 30rpx;
font-size: 36rpx;
font-weight: 400;
line-height: 50rpx;
color: #666666;
opacity: 1;
}
}
}
.voice_btn {
display: flex;
justify-content: center;
.btn {
// margin-right: 85rpx;
margin-top: 10rpx;
image {
width: 140rpx;
height: 140rpx;
display: inline-block;
}
text {
display: block;
margin-top: 30rpx;
font-size: 26rpx;
font-weight: 400;
line-height: 37rpx;
color: #CECECE;
opacity: 1;
}
}
.voice_detertime {
margin-right: 0;
}
.voice_play {
margin-top: 0;
margin-left: 85rpx;
margin-right: 85rpx;
image {
width: 160rpx;
height: 160rpx;
}
}
}
.person {
margin-top: 159rpx;
margin-left: 30rpx;
padding: 33rpx;
box-sizing: border-box;
text-align: left;
width: 690rpx;
height: 300rpx;
background: rgba(111, 236, 228, 0.12);
border-radius: 14rpx;
position: relative;
textarea {
width: 100%;
height: 100%;
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 400;
color: #000000;
opacity: 1;
}
image {
position: absolute;
width: 37.5rpx;
height: 37.5rpx;
right: 39rpx;
bottom: 30rpx;
}
}
}
</style>
操作步骤:
直接运行即可
直接运行即可
预期结果:
取消监听oncanplay
取消监听oncanplay
实际结果:
无法取消监听oncanplay
无法取消监听oncanplay
bug描述:
音频组件控制中,offCanplay不能取消监听onCanplay
陈大雷Q (作者)
文档也没注明,害得我调试很久
2021-11-22 10:55
DCloud_uni-ad_HDX
回复 陈大雷Q: 已更新文档
2021-12-03 10:53