当前位置:   article > 正文

微信小程序调用讯飞接口实现录音和获取录音音译的文本 前端部分 包含图片、视频的上传功能_微信小程序获取录音文件

微信小程序获取录音文件

时间的3是三秒还没修改格式 问题不大 凑合着看一眼弄了个啥 单纯为了记录 需要的同学得自己找需用用到的地方 我多少写了点注释

wxml部分:

  1. <view class="wrap">
  2. <el-form :inline="true" :model="form">
  3. <view class="white-box" wx:for="{{activityMaterials}}" wx:key="index">
  4. <view class="title-box">
  5. <view class="yellow-fence"></view>
  6. <view class="title-txt-part" wx:if="{{!item.isEdit}}">
  7. <view class="v1">{{item.title}}</view>
  8. <image src="/image/icon_edit.png" class="icon-edit" data-idx="{{index}}" bindtap="titleHandle" />
  9. </view>
  10. <input wx:if="{{item.isEdit}}" type="text" value="" data-idx="{{index}}" class="title-input" placeholder="请输入标题" bindblur="inputBlurHandle" />
  11. <image src="/image/icon_close_black.png" data-idx="{{index}}" class="icon-close-black" bindtap="deleteHandle"></image>
  12. </view>
  13. <view class="textarea-box-wrap">
  14. <view class="voice-box" wx:if="{{item.recordArr.length > 0}}">
  15. <!--这里是录音的显示区域-->
  16. <view class="record-item" wx:for="{{item.recordArr}}" wx:key="txt" wx:for-item="oItem" wx:for-index="oIndex">
  17. <view class="record-list" data-pidx="{{index}}" data-idx="{{oIndex}}" bindtap="playHandle">
  18. <image src="{{oItem.played == true ? '/image/icon_pause.png' : '/image/icon_video.png'}}" class="icon-video" />
  19. <text class="t1">语音</text>
  20. <text class="t2">00:{{oItem.time}}</text>
  21. </view>
  22. <view class="record-txt" wx:if="{{oItem.showTxt}}">{{oItem.txt}}</view>
  23. </view>
  24. <!-- <view class="record-item">
  25. <view class="record-list">
  26. <image src="/image/icon_video.png" class="icon-video" />
  27. <text class="t1">语音</text>
  28. <text class="t2">00:23</text>
  29. </view>
  30. <view class="record-txt">该生聪明伶俐,乐于助人,和同学们相处融洽,尊师重道,就是不学习,感觉没别的啥缺点</view>
  31. </view> -->
  32. </view>
  33. <textarea class="textarea-box" value="{{item.content}}" data-idx="{{index}}" bindblur="textareaBlurHandle" placeholder="请输入内容"></textarea>
  34. <!--这里是中间那个录音按钮-->
  35. <button class="record-btn" data-idx="{{index}}" bindtap="recordHandle">
  36. <image src="/image/icon_record_gray.png" wx:if="{{!item.recordState}}" class="icon-record" />
  37. <image src="/image/icon_record_red.png" wx:else="{{item.recordState}}" class="icon-record" />
  38. </button>
  39. </view>
  40. <view class="material-box">
  41. <button class="upload-box" data-idx="{{index}}" bindtap="uploadFile">
  42. <image src="/image/icon_photo.png" class="icon-photo" />
  43. 上传图片、视频
  44. </button>
  45. <block wx:for="{{activityMaterials[index].material}}" wx:for-item="mItem" wx:for-index="mIndex" wx:key="url">
  46. <view class="material-list" wx:if="{{mItem.type == 'img'}}">
  47. <image src="/image/icon_close.png" class="icon-close" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="closeHadle" />
  48. <image src="{{mItem.url}}" data-src="{{mItem.url}}" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="preview" class="material-list-m2" mode="aspectFill"></image>
  49. </view>
  50. <view class="material-list" wx:if="{{mItem.type == 'mp4'}}">
  51. <image src="/image/icon_close.png" class="icon-close" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="closeHadle" />
  52. <video src="{{mItem.url}}" data-src="{{mItem.url}}" class="material-list-m2" mode="aspectFill"></video>
  53. </view>
  54. </block>
  55. </view>
  56. </view>
  57. <view class="add-box" bindtap="addListHandle">
  58. +添加
  59. </view>
  60. <view class="save-btn" bindtap="save">提交</view>
  61. </el-form>
  62. </view>

 js部分
 

  1. const app = getApp()
  2. const util = require('../../utils/util.js');
  3. const api = require('../../config/api.js');
  4. const BASE_URL = app.globalData.BASE_URL
  5. let lock = false
  6. //**************重点 该录音功能亲测如果超过三秒不继续录音会自动结束录音 还得手动关闭录音状态**************
  7. //录音部分-start
  8. const innerAudioContext = wx.createInnerAudioContext({
  9. useWebAudioImplement: false // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
  10. })
  11. const recorderManager = wx.getRecorderManager();
  12. var wxst; //语音websocket
  13. var status = 0; // 音频的状态
  14. var iatResult = [] // 识别结果
  15. const searchoptions = {
  16. duration: 1000 * 60,
  17. sampleRate: 16000,
  18. numberOfChannels: 1,
  19. encodeBitRate: 48000,
  20. format: 'mp3',
  21. frameSize: 6
  22. }
  23. //录音部分-end
  24. Page({
  25. data: {
  26. coursewareId: '',
  27. form: {},
  28. activityMaterials: [],
  29. isFromReport: false,
  30. info: {},
  31. //recordArr: [], recordArr率属于activityMaterials的子集 //音频数组 包含三个字段 url->mp3格式文件 txt:MP3的文字版的文本 time: 录音的时间 played:是否正在播放
  32. parentIndex: null,
  33. //录音部分-start
  34. srcMic: '',
  35. edit_text_max: 200,
  36. remain_length: 200,
  37. edit_text: "",
  38. is_focus: false,
  39. tips: "",
  40. index: -1,
  41. voicePath: "",
  42. //语音
  43. //recordState: false, //录音状态 该字段纳入作为activityMaterials的子级 由activityMaterials统一调配
  44. contentTxt: '', //内容
  45. firstSend: true,
  46. //录音部分-end
  47. },
  48. onLoad(options) {
  49. //console.log(options)
  50. if (options.title) { //自定义顶部导航title
  51. wx.setNavigationBarTitle({
  52. title: options.title
  53. })
  54. }
  55. const userInfo = wx.getStorageSync('userInfo');
  56. this.setData({
  57. userInfo,
  58. coursewareId: options.coursewareId,
  59. isFromReport: options.isFromReport ? true : false,
  60. title: options.title,
  61. info: {
  62. thumb: options.thumb,
  63. title: options.title,
  64. updateTime: options.updateTime
  65. },
  66. activityMaterials: []
  67. })
  68. lock = false
  69. //先调用接口 如果length为零 那么新增一个对象
  70. this.loadData()
  71. this.initRecord()//这个是录音的内容要调用
  72. },
  73. onShow: function () { //这是录音的马蜂窝
  74. var that = this;
  75. recorderManager.onStart(() => {//开始录音时触发
  76. status = 0;
  77. iatResult = []
  78. //console.log('recorder start');
  79. that.data.firstSend = false;
  80. });
  81. recorderManager.onError((res) => {//错误回调
  82. //console.log(res);
  83. });
  84. recorderManager.onStop((res) => {//结束录音时触发
  85. //console.log('recorder stop')
  86. //console.log(res)
  87. let otime = (res.duration/1000).toFixed(0)
  88. status = 2;
  89. var sendsty = '{"data":{"status":2,"audio":"","format":"audio/L16;rate=8000","encoding":"raw"}}'
  90. wxst.send({
  91. data: sendsty
  92. })
  93. wx.uploadFile({
  94. // 模拟https
  95. url: BASE_URL + 'common/uploadMediaToTencent', //需要用HTTPS,同时在微信公众平台后台添加服务器地址
  96. filePath: res.tempFilePath, //上传的文件本地地址
  97. name: 'file',
  98. //附近数据,这里为路径
  99. success: function(result) {
  100. // console.log("--结束录音--")
  101. // console.log(that.data.contentTxt)
  102. // console.log(JSON.parse(result.data).url)
  103. // console.log(otime)
  104. if(that.data.contentTxt){
  105. //recordArr: []//音频数组 包含三个字段 url->mp3格式文件 txt:MP3的文字版的文本 time: 录音的时间 played:是否正在播放
  106. let ourl = JSON.parse(result.data).url
  107. let pidx = that.data.parentIndex
  108. let params = {
  109. url: ourl,
  110. txt: that.data.contentTxt,
  111. time: that.timeHandle(otime),//这个时间是用来显示的
  112. played: false,
  113. showTxt: false,
  114. }
  115. let oarr = that.data.activityMaterials
  116. oarr.forEach((item) => {
  117. item.recordArr = item.recordArr && item.recordArr.length > 0 ? item.recordArr : []
  118. })
  119. oarr[pidx].recordArr.push(params)
  120. that.setData({
  121. activityMaterials: oarr
  122. })
  123. //console.log(that.data.activityMaterials)
  124. }else{
  125. //console.log("木有内容啊")
  126. }
  127. },
  128. fail: function(err) {
  129. //console.log(err)
  130. }
  131. })
  132. });
  133. recorderManager.onFrameRecorded((res) => {//每帧触发
  134. const that = this
  135. const { frameBuffer, isLastFrame } = res
  136. let params = {
  137. 'common': {
  138. 'app_id': '57198f05'
  139. },
  140. 'business': {
  141. 'language': 'zh_cn', //⼩语种可在控制台--语⾳听写(流式)--⽅⾔/语种处添加试⽤
  142. 'domain': 'iat',
  143. 'accent': 'mandarin', //中⽂⽅⾔可在控制台--语⾳听写(流式)--⽅⾔/语种处添加试⽤
  144. 'vad_eos': 1000,
  145. 'dwa': 'wpgs' //为使该功能⽣效,需到控制台开通动态修正功能(该功能免费)
  146. },
  147. 'data': {
  148. 'status': 0,
  149. 'format': 'audio/L16;rate=16000',
  150. 'encoding': 'lame',
  151. 'audio': wx.arrayBufferToBase64(frameBuffer)
  152. }
  153. }
  154. // 拼接数据
  155. let status = 0
  156. if (this.data.firstSend) {
  157. this.data.firstSend = false
  158. } else {
  159. if (isLastFrame) {
  160. status = 2
  161. } else {
  162. status = 1
  163. }
  164. }
  165. params.data.status = status
  166. wx.sendSocketMessage({
  167. data: JSON.stringify(params),
  168. success: (data) => {
  169. console.log('send success:' + JSON.stringify(data))
  170. //that.resetRecordState()
  171. },
  172. fail: (err) => {
  173. console.log('send error:' + JSON.stringify(err))
  174. //中断录音的时候
  175. //that.resetRecordState()
  176. },
  177. completed: () => {
  178. if (isLastFrame) {
  179. // wx closeSocket
  180. }
  181. }
  182. })
  183. })
  184. },
  185. timeHandle(time){
  186. if(time < 9){
  187. return '0' + time
  188. }else{
  189. return time
  190. }
  191. },
  192. //重置录音按钮状态
  193. resetRecordState(){
  194. let activityMaterials = this.data.activityMaterials
  195. activityMaterials[this.data.parentIndex].recordState = false
  196. this.setData({
  197. activityMaterials: activityMaterials
  198. })
  199. },
  200. save() {//这里还没改 不重要的文件
  201. if (lock) return
  202. lock = true
  203. //处理过滤activityMaterials数据
  204. let actArr = this.data.activityMaterials.map(function (item) {
  205. let oarr = []
  206. //转换数据格式
  207. oarr[0] = {
  208. content: item.content
  209. }
  210. for (let i in item.material) {
  211. oarr.push({
  212. content: item.material[i].url
  213. })
  214. }
  215. return {
  216. title: item.title,
  217. paragraphs: oarr
  218. }
  219. })
  220. for (let i in actArr) {
  221. //title等于编辑标题就代表没编辑过 paragraphs[0].content的值为空就代表textare没编辑过 paragraphs[1]不存在或者content为空就代表没编辑过
  222. if (actArr[i].title == '编辑标题' && !actArr[i].paragraphs[0].content && (!actArr[i].paragraphs[1] || !actArr[i].paragraphs[1].content)) {
  223. actArr.splice(i, 1)
  224. }
  225. }
  226. if (actArr.length == 0) {
  227. wx.showToast({
  228. title: '请先编辑材料!',
  229. icon: 'none',
  230. duration: 2000
  231. })
  232. lock = false
  233. return
  234. }
  235. util.request(api.activityPreparationSave, {
  236. teacherId: this.data.userInfo.userId,
  237. classId: this.data.userInfo.deptId,
  238. coursewareId: this.data.coursewareId,
  239. activityMaterials: actArr
  240. }, 'POST', 'application/json').then(res => {
  241. if (res.code = 200) {
  242. wx.showToast({
  243. title: '提交成功!',
  244. icon: 'error',
  245. duration: 2000
  246. })
  247. //判断是不是报告那边跳转过来的
  248. if (this.data.isFromReport) {
  249. let oinfo = this.data.info
  250. wx.redirectTo({
  251. url: '../reportdetail/reportdetail?coursewareId=' + this.data.coursewareId + '&title=' + oinfo.title + '&thumb=' + oinfo.thumb + '&updateTime=' + oinfo.updateTime
  252. })
  253. } else {
  254. wx.navigateBack({
  255. delta: 1
  256. });
  257. }
  258. lock = false
  259. } else {
  260. wx.showToast({
  261. title: res.msg,
  262. icon: 'error',
  263. duration: 2000
  264. })
  265. lock = false
  266. }
  267. });
  268. },
  269. loadData() {
  270. util.request(api.activityPreparationList + this.data.userInfo.userId + '&coursewareId=' + this.data.coursewareId + '&classId=' + this.data.userInfo.deptId, '', 'get').then(res => {
  271. if (res.code = 200) {
  272. let odata = res.data
  273. if (odata && odata.length == 0) {
  274. let obj = this.data.activityMaterials
  275. obj.push({
  276. title: '编辑标题',
  277. isEdit: false,
  278. content: '',
  279. material: []
  280. })
  281. this.setData({
  282. activityMaterials: obj
  283. })
  284. } else {
  285. //重组数据
  286. //type 1图片 3视频
  287. let oarr = odata.map(function (item) {
  288. let paragraphs = []
  289. for (let i in item.paragraphs) {
  290. paragraphs.push({
  291. url: item.paragraphs[i].content,
  292. type: item.paragraphs[i].type == '3' ? 'mp4' : item.paragraphs[i].type == '1' ? 'img' : ''
  293. })
  294. }
  295. return {
  296. title: item.title ? item.title : '编辑标题',
  297. isEdit: false,
  298. content: item.content,
  299. material: paragraphs
  300. }
  301. })
  302. //console.log(oarr)
  303. this.setData({
  304. activityMaterials: oarr
  305. })
  306. }
  307. } else {
  308. wx.showToast({
  309. title: res.msg,
  310. icon: 'error',
  311. duration: 2000
  312. })
  313. }
  314. });
  315. },
  316. addListHandle() {
  317. let obj = this.data.activityMaterials
  318. obj.push({
  319. title: '编辑标题',
  320. isEdit: false,
  321. content: '',
  322. material: []
  323. })
  324. this.setData({
  325. activityMaterials: obj
  326. })
  327. },
  328. titleHandle(e) {
  329. let obj = this.data.activityMaterials
  330. let idx = e.currentTarget.dataset.idx
  331. obj[idx].isEdit = true
  332. this.setData({
  333. activityMaterials: obj
  334. })
  335. },
  336. inputBlurHandle(e) {
  337. let oval = e.detail.value
  338. let obj = this.data.activityMaterials
  339. let idx = e.currentTarget.dataset.idx
  340. if (oval) {
  341. obj[idx].title = oval
  342. }
  343. obj[idx].isEdit = false
  344. this.setData({
  345. activityMaterials: obj
  346. })
  347. },
  348. textareaBlurHandle(e) {
  349. let oval = e.detail.value
  350. let obj = this.data.activityMaterials
  351. let idx = e.currentTarget.dataset.idx
  352. if (oval) {
  353. obj[idx].content = oval
  354. }
  355. this.setData({
  356. activityMaterials: obj
  357. })
  358. },
  359. preview(e) {
  360. let currentUrl = e.currentTarget.dataset.src
  361. let pidx = e.currentTarget.dataset.pidx //父级循环的index
  362. const oarr = []
  363. for (let i in this.data.activityMaterials[pidx].material) {
  364. oarr.push(this.data.activityMaterials[pidx].material[i].url)
  365. }
  366. wx.previewImage({
  367. current: currentUrl, // 当前显示图片的http链接
  368. urls: oarr // 需要预览的图片http链接列表
  369. })
  370. },
  371. closeHadle(e) {
  372. //console.log(e)
  373. const that = this
  374. wx.showModal({
  375. title: '',
  376. content: '是否删除素材',
  377. success(res) {
  378. if (res.confirm) {
  379. let obj = that.data.activityMaterials
  380. let pidx = e.currentTarget.dataset.pidx //父级循环的index
  381. let idx = e.currentTarget.dataset.idx //子级循环的index
  382. obj[pidx].material.splice(idx, 1)
  383. that.setData({
  384. activityMaterials: obj
  385. })
  386. } else if (res.cancel) {
  387. //console.log('用户点击取消')
  388. }
  389. }
  390. })
  391. },
  392. //上传图片、视频
  393. uploadFile: function (e) {
  394. const that = this
  395. let obj = this.data.activityMaterials
  396. let pidx = e.currentTarget.dataset.idx
  397. wx.chooseMedia({
  398. count: 9, // 设置为需要上传的文件数量
  399. mediaType: ['image', 'video'],
  400. success: function (res) {
  401. const files = res.tempFiles;
  402. // 遍历选择的文件数组,依次上传每个文件
  403. files.forEach(function (file) {
  404. const tempFilePath = file.tempFilePath;
  405. wx.uploadFile({
  406. url: BASE_URL + 'common/uploadMediaToTencent',
  407. filePath: tempFilePath,
  408. name: 'file',
  409. success: function (res) {
  410. //console.log(res)
  411. let ores = JSON.parse(res.data)
  412. //每个数组里添加一个type值是mp4或者img,在for循环里通过type赋值到mp4或者img里面
  413. let otype = that.getFileExtension(ores.url)
  414. if (otype) {
  415. let params = {
  416. url: ores.url,
  417. type: otype
  418. }
  419. obj[pidx].material.push(params)
  420. }
  421. that.setData({
  422. activityMaterials: obj
  423. })
  424. },
  425. fail: function (res) {
  426. //console.log(res.errMsg);
  427. // 处理上传失败后的逻辑
  428. }
  429. })
  430. });
  431. }
  432. })
  433. },
  434. //用一个方法来判断 返回的文件是mp4 还是图片
  435. getFileExtension(url) {
  436. const dotIndex = url.lastIndexOf('.');
  437. const extension = url.substring(dotIndex + 1);
  438. if (/(jpg|jpeg|png)$/.test(extension.toLowerCase())) {
  439. return 'img'
  440. } else if (/(mp4|avi|mov)$/.test(extension.toLowerCase())) {
  441. return 'mp4'
  442. }
  443. return false
  444. },
  445. deleteHandle(e) {
  446. const that = this
  447. wx.showModal({
  448. title: '',
  449. content: '是否删除',
  450. success(res) {
  451. if (res.confirm) {
  452. let obj = that.data.activityMaterials
  453. let idx = e.currentTarget.dataset.idx //子级循环的index
  454. obj.splice(idx, 1)
  455. that.setData({
  456. activityMaterials: obj
  457. })
  458. } else if (res.cancel) {
  459. //console.log('用户点击取消')
  460. }
  461. }
  462. })
  463. },
  464. //识别语音 -- 初始化 从这里开始是录音的内容 一直到结束
  465. initRecord: function () {
  466. var that = this;
  467. wx.onSocketOpen((res) => {// websocket打开
  468. //console.log('监听到 WebSocket 连接已打开' + res);
  469. })
  470. wx.onSocketError((err) => {//连接失败
  471. //console.log('websocket连接失败', err);
  472. wx.showToast({
  473. title: 'websocket连接失败',
  474. icon: 'none',
  475. duration: 2000,
  476. mask: false
  477. })
  478. })
  479. wx.onSocketMessage((res) => {//接收返回值
  480. var data = JSON.parse(res.data)
  481. //console.log('----------------')
  482. //console.log(data)
  483. if (data.code != 0) {
  484. //console.log("error code " + data.code + ", reason " + data.message)
  485. return
  486. }
  487. let str = ""
  488. if (data.data.status == 2) {//最终识别结果
  489. // data.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
  490. wxst.close();
  491. } else {//中间识别结果
  492. }
  493. iatResult[data.data.result.sn] = data.data.result
  494. if (data.data.result.pgs == 'rpl') {
  495. data.data.result.rg.forEach(i => {
  496. iatResult[i] = null
  497. })
  498. }
  499. iatResult.forEach(i => {
  500. if (i != null) {
  501. i.ws.forEach(j => {
  502. j.cw.forEach(k => {
  503. str += k.w
  504. })
  505. })
  506. }
  507. });
  508. // console.log('这个是中间的语音识别结果')
  509. // console.log(str)
  510. that.setData({
  511. contentTxt: str //这个是中间的语音识别结果
  512. })
  513. if(!this.data.contentTxt){
  514. wx.showToast({
  515. title: '识别失败,请重新录入',
  516. icon: 'none',
  517. duration: 2000,
  518. mask: false
  519. })
  520. return
  521. }
  522. })
  523. wx.onSocketClose((res) => {//WebSocket连接已关闭!
  524. //var that = this;
  525. recorderManager.stop();
  526. // var str = that.data.contentTxt;
  527. // console.log(str);
  528. // str = str.replace(/\s*/g, "");//去除空格
  529. // if (str.substr(str.length - 1, 1) == "。") {//去除句号
  530. // str = str.substr(0, str.length - 1);
  531. // }
  532. // console.log('这个是最后确定的语音识别结果', str)
  533. // that.setData({
  534. // contentTxt: str//这个是最后确定的语音识别结果
  535. // })
  536. //console.log('WebSocket连接已关闭!')
  537. })
  538. },
  539. //录音和停止录音操作
  540. recordHandle(e){
  541. let oactivityMaterials = this.data.activityMaterials
  542. let parentIndex = e.currentTarget.dataset.idx
  543. this.setData({//获取父级的下标 后面录音结束后给对应的模块赋值
  544. parentIndex: parentIndex
  545. })
  546. //改成点击事件
  547. if(!oactivityMaterials[parentIndex].recordState){
  548. wx.showToast({
  549. title: '开始录音',
  550. icon: 'none',
  551. duration: 1000
  552. })
  553. //兄弟节点的录音按钮改成灰色
  554. if(oactivityMaterials.length > 1){
  555. for(let i in oactivityMaterials){
  556. oactivityMaterials[i].recordState = false
  557. }
  558. this.setData({
  559. activityMaterials: oactivityMaterials
  560. })
  561. }
  562. oactivityMaterials[parentIndex].recordState = true
  563. this.setData({
  564. activityMaterials: oactivityMaterials //录音状态
  565. })
  566. wx.getSetting({//查看用户有没有开启语音权限
  567. success(res) {
  568. if (res.authSetting['scope.record']) {
  569. wx.authorize({
  570. scope: 'scope.record',
  571. success() {
  572. var xfurl = "";
  573. wx.request({//请求接口 获取讯飞语音鉴权
  574. url: BASE_URL + 'assistant/url',
  575. method: "get",
  576. header: {
  577. 'content-type': 'application/json' // 默认值
  578. },
  579. success: function (res) {
  580. //console.log('鉴权结果start:');
  581. //console.log(res);
  582. if (res.statusCode == "200" && res.data) {
  583. xfurl = res.data;
  584. wxst = wx.connectSocket({ // 开启websocket连接
  585. url: xfurl,
  586. method: 'GET',
  587. success: function (res) {
  588. recorderManager.start(searchoptions);//开始录音
  589. }
  590. });
  591. } else {
  592. wx.showToast({
  593. title: '获取语音鉴权失败',
  594. icon: 'none',
  595. mask: true,
  596. duration: 3000
  597. })
  598. }
  599. },
  600. fail: function () {
  601. wx.showToast({
  602. title: '获取语音鉴权失败',
  603. icon: 'none',
  604. mask: true,
  605. duration: 3000
  606. })
  607. }
  608. })
  609. },
  610. fail() {
  611. wx.showModal({
  612. title: '微信授权',
  613. content: '您当前未开启语音权限,请在右上角设置(···)中开启“录音功能”',
  614. showCancel: false,
  615. success(res) {
  616. if (res.confirm) {
  617. //console.log('用户点击确定')
  618. }
  619. }
  620. })
  621. }
  622. })
  623. } else {
  624. wx.showModal({
  625. title: '微信授权',
  626. content: '您当前未开启语音权限,请在右上角设置(···)中开启“录音功能”',
  627. showCancel: false,
  628. success(res) {
  629. if (res.confirm) {
  630. //console.log('用户点击确定')
  631. }
  632. }
  633. })
  634. }
  635. }
  636. })
  637. }else{
  638. oactivityMaterials[parentIndex].recordState = false
  639. this.setData({
  640. activityMaterials: oactivityMaterials
  641. })
  642. recorderManager.stop();
  643. }
  644. },
  645. //播放操作
  646. playHandle(e){
  647. const that = this
  648. let idx = e.currentTarget.dataset.idx
  649. let pidx = e.currentTarget.dataset.pidx
  650. //recordArr的字段有url/txt/time/played/showTxt
  651. let activityMaterials = this.data.activityMaterials
  652. let orecordArr = activityMaterials[pidx].recordArr[idx]
  653. innerAudioContext.src = orecordArr.url
  654. if(!orecordArr.played){
  655. //查找兄弟节点 把所有的played状态改成false
  656. for(let i in activityMaterials){
  657. for(let j in activityMaterials[i].recordArr){
  658. activityMaterials[i].recordArr[j].played = false
  659. }
  660. }
  661. // if(activityMaterials && activityMaterials.length > 1){
  662. // that.setData({
  663. // activityMaterials: activityMaterials
  664. // })
  665. // }
  666. //播放
  667. orecordArr.played = true
  668. innerAudioContext.play() // 播放
  669. innerAudioContext.onEnded(() => {
  670. //console.log('语音播放结束');
  671. orecordArr.played = false
  672. that.setData({
  673. activityMaterials: activityMaterials
  674. })
  675. });
  676. }else{
  677. //关闭
  678. orecordArr.played = false
  679. innerAudioContext.stop() // 停止
  680. }
  681. this.setData({
  682. activityMaterials: activityMaterials
  683. })
  684. }
  685. })

wxss部分

  1. .wrap{ padding: 22rpx 10rpx 100rpx 10rpx;}
  2. .white-box{ margin-bottom: 22rpx; padding: 22rpx; width: 730rpx; box-sizing: border-box; background: #fff; border-radius: 25rpx;}
  3. .title-box,.title-txt-part{ display: flex; align-items: center;}
  4. .title-box{ position: relative;}
  5. .icon-close-black{ position: absolute; right: 0; display: block; width: 20rpx; height: 21rpx;}
  6. .icon-edit{ margin-left: 10rpx; width: 31rpx; height: 30rpx;}
  7. .yellow-fence{ margin-right: 10rpx; width: 6rpx; height: 30rpx; background: #ffb81c; border-radius: 3rpx;}
  8. .title-txt-part{ font-size: 28rpx; font-weight: bold;}
  9. .title-input{ padding-left: 16rpx; width: 360rpx; height: 60rpx; border:1rpx solid #ddd; border-radius: 10rpx; font-size: 26rpx;}
  10. .material-box{ margin-top: 22rpx; display: flex; justify-content: flex-start; flex-wrap: wrap;}
  11. .upload-box{ margin: 0 25rpx 25rpx 0; padding: 0; display: flex; justify-content: center; align-items: center; width: 310rpx; height: 186rpx; background: #f0f0f0; font-size: 25rpx; color: #111; border: 0; border-radius: 22rpx;}
  12. button::after {border: none;}
  13. .icon-photo{ margin-right: 10rpx; display: block; width: 93rpx; height: 85rpx;}
  14. .material-list{ position: relative; margin: 0 25rpx 25rpx 0; width: 310rpx; height: 186rpx;}
  15. .material-list-m2{ width: 100%; height: 100%; border-radius: 22rpx;}
  16. .icon-close{ position: absolute; top: 10rpx; right: 10rpx; z-index: 999; display: block; width: 50rpx; height: 50rpx;}
  17. .add-box{ margin: 22rpx auto 0 auto; width: 270rpx; text-align: center; line-height: 60rpx; font-size: 35rpx; color: #ffb81c; font-weight: bold; border-bottom: 3rpx solid #ffb81c;}
  18. .save-btn{ margin: 100rpx auto 0 auto; width: 330rpx; height: 84rpx; text-align: center; line-height: 84rpx; background: #ffb81c; font-size: 30rpx; color: #111; font-weight: bold; border-radius: 42rpx;}
  19. .textarea-box-wrap{ margin-top: 22rpx; padding: 22rpx; display: flex; flex-direction: column; justify-content: center; height: 580rpx; background: #f0f0f0; border-radius: 25rpx;}
  20. .textarea-box{ flex:1; height: 100%; box-sizing: border-box; font-size: 25rpx; color: #111;}
  21. .voice-box{ margin-bottom: 20rpx; max-height: 200rpx; overflow-y: scroll; box-sizing: border-box; font-size: 25rpx; color: #111;}
  22. .videoBtn {width: 50%;}
  23. .videoBtn text{color:#fff;}
  24. .videoBtnBg {background: #bdb4b4;}
  25. .startYuyinImage {
  26. position: fixed;
  27. top: 200rpx;
  28. left: 50%;
  29. z-index: 99;
  30. transform: translateX(-50%);
  31. display:flex;justify-content:center;flex-flow: column;
  32. width: 220rpx;
  33. height: 220rpx;
  34. text-align: center;
  35. background: rgba(0, 0, 0, 0.1);
  36. color: #fff;
  37. font-size: 24rpx;
  38. border-radius: 50%;
  39. }
  40. .startYuyinImage cover-image { margin:0 auto; width:80rpx;height: 80rpx;}
  41. .startYuyinImage cover-view { margin-top: 22rpx;}
  42. .musicd {
  43. position: fixed;
  44. z-index: 9999;
  45. top: 10%;
  46. left: 4%;
  47. }
  48. .musicd image {
  49. width: 100rpx;
  50. height: 100rpx;
  51. z-index: 999;
  52. }
  53. .icon-record{ display: block; width: 70rpx; height: 70rpx;}
  54. .record-btn{ margin: 0 auto; padding: 0; width: 70rpx; height: 70rpx; background: transparent; border-radius: 50%;}
  55. button::after{border: none;}
  56. .record-list{ padding-left: 18rpx; display: flex; align-items: center; box-sizing: border-box; width: 640rpx; height: 74rpx; background: #fff; color: #19b2ff; border-radius: 18rpx;}
  57. .icon-video{ display: block; width: 56rpx; height: 55rpx;}
  58. .record-list .t1{ margin: 0 22rpx;}
  59. .record-txt{ padding:10rpx 10rpx 0 10rpx; font-size: 24rpx; color: #19b2ff;}
  60. .record-item{ margin-bottom: 22rpx;}
  61. .record-item:last-child{ margin-bottom: 0;}

json不用调用什么

页面我也还没写完 单纯的记录一下这个功能

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/77592
推荐阅读
相关标签
  

闽ICP备14008679号