| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- <template>
- <view class="custom-recorder">
- <view class="record-file-list" v-if="list.length">
- <view class="record-file-list-item" v-for="(item, index) in list" :key="index">
- <view class="close-btn" @tap="handleDel(item)"></view>
- <view class="play-icon" v-if="playStatus==='stop'">
- <image style="width: 100%; height: 100%;" src="/static/images/components/recorder/play.svg"
- mode="scaleToFill"></image>
- </view>
- <view class="play-icon" v-else>
- <image style="width: 100%; height: 100%;" src="/static/images/components/recorder/stop.svg"
- mode="scaleToFill"></image>
- </view>
- <view class="item-info">
- <view class="top-name">
- {{item.name}}
- </view>
- <view class="bottom-content">
- <view class="base-info" v-if="playStatus==='stop'">
- <view class="icon">
- <image style="width: 100%; height: 100%;"
- src="/static/images/components/recorder/voice-short.svg" mode="scaleToFill"></image>
- </view>
- <view class="duration">
- 音频时长:{{ item.duration }}
- </view>
- </view>
- <view class="progress" v-else>
- <uv-slider v-model="slider.value" block-size="12" block-color="#FF7300"
- backgroundColor="#ffb97f" activeColor="#ff7300" :min="slider.min" :max="slider.max"
- :step="slider.step" disabled>
- </uv-slider>
- <view class="duration">
- {{ item.duration }}
- </view>
- </view>
- </view>
- </view>
- </view>
- </view>
- <uni-popup ref="popup" type="bottom" class="pop-up-box">
- <view class="pop-up-content">
- <view class="content-header">
- 音频录音
- </view>
- <view class="content-body">
- <view class="content-body-duration">
- {{duration}}
- </view>
- <view class="icon">
- <image style="width: 100%; height: 100%;" src="/static/images/components/recorder/voice.svg"
- mode="scaleToFill"></image>
- </view>
- <view class="btn">
- <button style="height: 68rpx;line-height: 68rpx;border-radius: 1998rpx;" type="primary"
- @longpress="handleStart" @touchcancel="handleStop"
- @touchend="handleStop">{{btnText[recordStatus]}}</button>
- </view>
- </view>
- </view>
- </uni-popup>
- <custom-modal ref="modalRef"></custom-modal>
- </view>
- </template>
- <script>
- import moment from 'moment';
- import CustomModal from '../Modal/CustomModal.vue';
- // #ifdef APP-PLUS
- const recorder = plus.audio.getRecorder();
- const player = plus.audio.createPlayer({
- autoplay: false
- });
- // #endif
- export default {
- components: {
- CustomModal
- },
- data() {
- return {
- list: [],
- duration: "00:00:00",
- recordStatus: "stop",
- btnText: {
- stop: "按住说话",
- start: "说完了"
- },
- voicePath: '',
- playStatus: 'stop',
- slider: {
- value: 0,
- min: 0,
- max: 100,
- step: 1
- },
- }
- },
- onLoad() {},
- beforeDestroy() {
- player.destroy(); // 释放音频资源
- },
- methods: {
- startRecord() {
- console.log('开始录音');
- // #ifdef APP-PLUS
- console.log('走的app')
- recorder.record({
- format: 'amr',
- filename: "_doc/hlt_app/录音文件"
- },
- async (path) => {
- console.log('录制成功')
- // 此处就要上传这个文件
- uni.showLoading({
- title: '上传中...'
- })
- setTimeout(() => {
- uni.hideLoading()
- // 上传成功后,生成一条记录
- this.voicePath = path
- console.log(this.voicePath)
- plus.io.getAudioInfo({
- filePath: path,
- success: ({
- duration
- }) => {
- console.log('时长', duration)
- list.push({
- path,
- duration
- })
- }
- })
- }, 1500)
- },
- (err) => {
- uni.$msg(err)
- }
- )
- // #endif
- },
- // 结束录音
- endRecord() {
- console.log('录音结束');
- // recorder.stop();
- this.list.push({
- name: moment().format('YYYY-MM-DD HH:mm:ss'),
- path: "../",
- duration: this.duration
- })
- },
- // 播放
- playVoice() {
- console.log('播放录音');
- if (this.voicePath) {
- // #ifdef APP-PLUS
- player.setStyles({
- src: this.voicePath
- });
- // #endif
- player.play()
- }
- },
- // 打开底部弹窗,用于开始录音
- handleOpenRecord() {
- this.$refs.popup.open()
- },
- // 按住说话事件
- // 开始录音, 并计时
- handleStart() {
- this.startRecord()
- this.recordStatus = 'start'
- this.timer && clearInterval(this.timer)
- // 计时器内部处理经过时长并显示在面板
- let timeStart = 0
- this.timer = setInterval(() => {
- timeStart += 1000
- let sec = this.timeFormat(moment.duration(timeStart).asSeconds() % 60)
- let min = this.timeFormat(moment.duration(timeStart).asMinutes() % 60)
- let hour = this.timeFormat(moment.duration(timeStart).asHours())
- this.duration = `${hour}:${min}:${sec}`
- }, 1000)
- },
- timeFormat(time) {
- if (0 <= time && time < 1) {
- return '00'
- }
- if (time >= 1 && time < 10) {
- return '0' + Math.floor(time)
- } else {
- return Math.floor(time)
- }
- },
- // 松开事件
- // 结束录音
- handleStop() {
- this.endRecord()
- this.recordStatus = 'stop'
- this.resetRecord()
- },
- resetRecord() {
- this.duration = "00:00:00"
- this.timer && clearInterval(this.timer)
- },
- // 删除录音
- handleDel(record) {
- this.$refs.modalRef.showModal({
- title: "确定删除该录音?",
- onOk: () => {
- this.list.forEach((item, index) => {
- if (item.name === record.name) {
- this.list.splice(index, 1)
- }
- })
- }
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .custom-recorder {
- width: 100%;
- .record-file-list {
- padding: 20rpx 0;
- &-item {
- margin-bottom: 20rpx;
- border-radius: 12rpx;
- background: $uni-bg-color-grey;
- padding: 10rpx 20rpx;
- display: flex;
- align-items: center;
- position: relative;
- &::after {
- content: '';
- position: absolute;
- top: 0;
- right: 0;
- width: 68rpx;
- height: 68rpx;
- background: url('../../static/images/components/recorder/close-bg.svg') no-repeat;
- background-size: 100% 100%;
- }
- .close-btn {
- position: absolute;
- top: 12rpx;
- right: 10rpx;
- width: 20rpx;
- height: 20rpx;
- background: url('../../static/images/components/recorder/close.svg') no-repeat;
- background-size: 100% 100%;
- z-index: 999;
- }
- .play-icon {
- margin-right: 28rpx;
- width: 60rpx;
- height: 60rpx;
- }
- &:last-child {
- margin-bottom: 0;
- }
- .item-info {
- .top-name {
- font-family: Source Han Sans;
- font-size: 32rpx;
- color: $uni-text-color;
- }
- .bottom-content {
- margin-top: 10rpx;
- .base-info {
- display: flex;
- align-items: center;
- .icon {
- margin-right: 10rpx;
- width: 60rpx;
- height: 30rpx;
- }
- .duration {
- font-family: Source Han Sans;
- font-size: 28rpx;
- color: $uni-text-color-grey;
- }
- }
- }
- }
- }
- }
- .pop-up-box {
- .pop-up-content {
- border-top-left-radius: 20rpx;
- border-top-right-radius: 20rpx;
- .content-header {
- background-color: #fff;
- border-top-left-radius: 20rpx;
- border-top-right-radius: 20rpx;
- height: 100rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-family: Source Han Sans;
- font-size: 32rpx;
- font-weight: 500;
- font-feature-settings: "kern" on;
- color: $uni-text-color;
- }
- .content-body {
- background: #EFF0F5;
- height: 400rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- &-duration {
- font-family: Source Han Sans;
- font-size: 70rpx;
- color: $uni-text-color;
- }
- .icon {
- margin-top: 30rpx;
- width: 384rpx;
- height: 40rpx;
- }
- .btn {
- margin-top: 42rpx;
- }
- }
- }
- }
- }
- </style>
|