| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- <!--
- 作者:GuoZhiBo
- 时间:2020-05-19
- 描述:录音和播放语音插件
- -->
- <template>
- <div>
- <div v-if="isReadonly == 'false'" style="margin-bottom: 10px">
- <button
- type="button"
- class="btn btn-info"
- @mousedown.prevent="mouseStart"
- >
- <span class="glyphicon glyphicon-volume-up" aria-hidden="true" />
- {{ tiptext }}
- </button>
- </div>
- <template v-if="srcArray.length > 0">
- <div
- v-for="(item, index) in srcArray"
- :key="index"
- style="margin-bottom: 10px; display: inline-flex; align-items: center"
- >
- <AuthAudio :audio-src="getUrl(item)" :token="token" />
- <button
- v-if="isReadonly == 'false'"
- type="button"
- class="btn btn-link"
- style="flex: 1"
- @click="deleteAudioSrc(index)"
- >
- <span class="glyphicon glyphicon-remove" aria-hidden="true" /> 删除
- </button>
- <div class="clearfix" />
- </div>
- </template>
- </div>
- </template>
- <script type="text/javascript">
- var Common = require('../common/Common.js');
- import recording from './recorder.js';
- var AuthAudio = require('./AuthAudio.vue').default;
- export default {
- name: 'MRecorder',
- components: {
- AuthAudio,
- },
- // props: ['className', 'srcArray', 'token', 'isReadonly'],
- props: {
- className: {
- type: String,
- default: null,
- },
- srcArray: {
- type: Array,
- default() {
- return [];
- },
- },
- token: {
- type: String,
- default: null,
- },
- isReadonly: {
- type: Boolean,
- },
- },
- data() {
- return {
- src: null,
- mcounter: 0, // 累积时间
- recording: false, // 标记是否在录音
- intervaltimerid: '', // 间隔时间定时器编号
- tiptext: '按住说话', // 提示文字
- mediaRecorder: null, // 录音笔
- mediaConstraints: {
- audio: true,
- },
- isTouchEnd: false, //是否移动结束事件
- num: 60, // 按住说话时间
- recorder: null,
- interval: '',
- audioFileList: [], // 上传语音列表
- startTime: '', // 语音开始时间
- endTime: '', // 语音结束
- flag: true,
- };
- },
- unmounted: function () {
- if (this.recorder) {
- this.recorder.stop();
- this.clearTimer();
- }
- },
- methods: {
- getUrl: function (item) {
- var _self = this;
- var url =
- Common.getApiURL('file/audioDownload') +
- '?className=' +
- _self.className +
- '&fileName=' +
- item;
- return url;
- },
- /**
- * 清除定时器
- */
- clearTimer: function () {
- if (this.interval) {
- this.num = 60;
- clearInterval(this.interval);
- }
- },
- /**
- * 长按说话
- */
- mouseStart: function () {
- var _self = this;
- this.clearTimer();
- this.startTime = new Date().getTime();
- recording.get(rec => {
- // 当首次按下时,要获取浏览器的麦克风权限,所以这时要做一个判断处理
- if (rec) {
- if (this.flag) {
- this.recorder = rec;
- this.interval = setInterval(() => {
- this.mcounter = this.mcounter + 1;
- this.tiptext = '录音中 ' + this.mcounter + 's';
- if (this.num <= 0) {
- rec.stop();
- this.num = 60;
- this.clearTimer();
- } else {
- this.num--;
- this.time = '松开结束(' + this.num + '秒)';
- rec.start();
- }
- }, 1000);
- this.flag = false;
- } else {
- this.flag = true;
- this.clearTimer();
- this.endTime = new Date().getTime();
- this.recorder.stop();
- rec.stop();
- // 重置说话时间
- this.tiptext = '按住说话';
- if (this.mcounter > 0) {
- this.num = 60;
- // 获取语音二进制文件
- let blob = this.recorder.getBlob();
- this.audioUpload(blob);
- this.mcounter = 0;
- }
- }
- }
- });
- },
- /**
- * 松开时上传语音
- */
- mouseEnd: function () {
- var _self = this;
- this.clearTimer();
- this.endTime = new Date().getTime();
- if (this.recorder) {
- this.recorder.stop();
- this.num = 60;
- // 重置说话时间
- this.tiptext = '按住说话';
- // 获取语音二进制文件
- let blob = this.recorder.getBlob();
- this.audioUpload(blob);
- }
- },
- /**
- * 删除语音
- * @param {Object} index
- */
- deleteAudioSrc: function (index) {
- var _self = this;
- _self.$emit('deleteAudioSrc', index);
- },
- /**
- * 长按
- */
- longTap: function () {
- var _self = this;
- _self.mouseStart();
- console.log('开始录音');
- },
- /**
- * 移动
- */
- touchMove: function () {
- var _self = this;
- console.log('取消录音');
- _self.isTouchEnd = true;
- _self.mouseEnd();
- },
- /**
- * 结束
- */
- touchEnd: function () {
- var _self = this;
- console.log('结束录音');
- _self.mouseEnd();
- },
- /**
- * 上传语音
- * @param {Object} blob
- */
- audioUpload: function (blob) {
- var fileName;
- var _self = this;
- if (_self.isTouchEnd == false) {
- // 将获取的二进制对象转为二进制文件流
- let file = new File([blob], 'test.mp3', {
- type: 'audio/mp3',
- lastModified: Date.now(),
- });
- // create FormData
- var formData = new FormData();
- formData.append('fileName', file.name);
- formData.append('files', file);
- formData.append('className', _self.className);
- $.ajax({
- url: Common.getApiURL('file/audioUpload'),
- type: 'post',
- beforeSend: function (request) {
- Common.addTokenToRequest(request);
- },
- data: formData,
- contentType: false,
- processData: false,
- success: function (data) {
- if (data != 'error') {
- fileName = data.substring(data.indexOf(':') + 1);
- const url = URL.createObjectURL(blob);
- _self.$emit('handleStop', {
- url: url,
- mblob: blob,
- fileName: fileName,
- });
- }
- },
- error: function (XMLHttpRequest, textStatus, errorThrown) {
- Common.processException(XMLHttpRequest, textStatus, errorThrown);
- },
- });
- console.log('录音成功:' + fileName);
- } else {
- console.log('取消录音');
- }
- _self.isTouchEnd = false;
- },
- },
- };
- </script>
- <style scoped>
- .wrapper {
- text-align: center;
- }
- .mrecorder {
- width: 40px;
- height: 40px;
- font-size: 40px;
- }
- .anirecorder {
- position: relative;
- animation: mymove 5s infinite;
- -webkit-animation: mymove 5s infinite;
- animation-direction: alternate;
- animation-timing-function: ease-in-out;
- /*safari & chrome*/
- -webkit-animation-direction: alternate;
- -webkit-transition-timing-function: ease-in-out;
- }
- @keyframes mymove {
- 0% {
- transform: scale(1);
- /*开始为原始大小*/
- }
- 25% {
- transform: scale(1.1);
- /*放大1.1倍*/
- }
- 50% {
- transform: scale(0.9);
- }
- 75% {
- transform: scale(1.1);
- }
- }
- @-webkit-keyframes mymove
- /*Safari and Chrome*/ {
- 0% {
- transform: scale(1);
- /*开始为原始大小*/
- }
- 25% {
- transform: scale(1.1);
- /*放大1.1倍*/
- }
- 50% {
- transform: scale(0.9);
- }
- 75% {
- transform: scale(1.1);
- }
- }
- </style>
|