时间的3是三秒还没修改格式 问题不大 凑合着看一眼弄了个啥 单纯为了记录 需要的同学得自己找需用用到的地方 我多少写了点注释
wxml部分:
<view class="wrap">
<el-form :inline="true" :model="form">
<view class="white-box" wx:for="{{activityMaterials}}" wx:key="index">
<view class="title-box">
<view class="yellow-fence"></view>
<view class="title-txt-part" wx:if="{{!item.isEdit}}">
<view class="v1">{{item.title}}</view>
<image src="/image/icon_edit.png" class="icon-edit" data-idx="{{index}}" bindtap="titleHandle" />
</view>
<input wx:if="{{item.isEdit}}" type="text" value="" data-idx="{{index}}" class="title-input" placeholder="请输入标题" bindblur="inputBlurHandle" />
<image src="/image/icon_close_black.png" data-idx="{{index}}" class="icon-close-black" bindtap="deleteHandle"></image>
</view>
<view class="textarea-box-wrap">
<view class="voice-box" wx:if="{{item.recordArr.length > 0}}">
<!--这里是录音的显示区域-->
<view class="record-item" wx:for="{{item.recordArr}}" wx:key="txt" wx:for-item="oItem" wx:for-index="oIndex">
<view class="record-list" data-pidx="{{index}}" data-idx="{{oIndex}}" bindtap="playHandle">
<image src="{{oItem.played == true ? '/image/icon_pause.png' : '/image/icon_video.png'}}" class="icon-video" />
<text class="t1">语音</text>
<text class="t2">00:{{oItem.time}}</text>
</view>
<view class="record-txt" wx:if="{{oItem.showTxt}}">{{oItem.txt}}</view>
</view>
<!-- <view class="record-item">
<view class="record-list">
<image src="/image/icon_video.png" class="icon-video" />
<text class="t1">语音</text>
<text class="t2">00:23</text>
</view>
<view class="record-txt">该生聪明伶俐,乐于助人,和同学们相处融洽,尊师重道,就是不学习,感觉没别的啥缺点</view>
</view> -->
</view>
<textarea class="textarea-box" value="{{item.content}}" data-idx="{{index}}" bindblur="textareaBlurHandle" placeholder="请输入内容"></textarea>
<!--这里是中间那个录音按钮-->
<button class="record-btn" data-idx="{{index}}" bindtap="recordHandle">
<image src="/image/icon_record_gray.png" wx:if="{{!item.recordState}}" class="icon-record" />
<image src="/image/icon_record_red.png" wx:else="{{item.recordState}}" class="icon-record" />
</button>
</view>
<view class="material-box">
<button class="upload-box" data-idx="{{index}}" bindtap="uploadFile">
<image src="/image/icon_photo.png" class="icon-photo" />
上传图片、视频
</button>
<block wx:for="{{activityMaterials[index].material}}" wx:for-item="mItem" wx:for-index="mIndex" wx:key="url">
<view class="material-list" wx:if="{{mItem.type == 'img'}}">
<image src="/image/icon_close.png" class="icon-close" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="closeHadle" />
<image src="{{mItem.url}}" data-src="{{mItem.url}}" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="preview" class="material-list-m2" mode="aspectFill"></image>
</view>
<view class="material-list" wx:if="{{mItem.type == 'mp4'}}">
<image src="/image/icon_close.png" class="icon-close" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="closeHadle" />
<video src="{{mItem.url}}" data-src="{{mItem.url}}" class="material-list-m2" mode="aspectFill"></video>
</view>
</block>
</view>
</view>
<view class="add-box" bindtap="addListHandle">
+添加
</view>
<view class="save-btn" bindtap="save">提交</view>
</el-form>
</view>
js部分
const app = getApp()
const util = require('../../utils/util.js');
const api = require('../../config/api.js');
const BASE_URL = app.globalData.BASE_URL
let lock = false
//**************重点 该录音功能亲测如果超过三秒不继续录音会自动结束录音 还得手动关闭录音状态**************
//录音部分-start
const innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
})
const recorderManager = wx.getRecorderManager();
var wxst; //语音websocket
var status = 0; // 音频的状态
var iatResult = [] // 识别结果
const searchoptions = {
duration: 1000 * 60,
sampleRate: 16000,
numberOfChannels: 1,
encodeBitRate: 48000,
format: 'mp3',
frameSize: 6
}
//录音部分-end
Page({
data: {
coursewareId: '',
form: {},
activityMaterials: [],
isFromReport: false,
info: {},
//recordArr: [], recordArr率属于activityMaterials的子集 //音频数组 包含三个字段 url->mp3格式文件 txt:MP3的文字版的文本 time: 录音的时间 played:是否正在播放
parentIndex: null,
//录音部分-start
srcMic: '',
edit_text_max: 200,
remain_length: 200,
edit_text: "",
is_focus: false,
tips: "",
index: -1,
voicePath: "",
//语音
//recordState: false, //录音状态 该字段纳入作为activityMaterials的子级 由activityMaterials统一调配
contentTxt: '', //内容
firstSend: true,
//录音部分-end
},
onLoad(options) {
//console.log(options)
if (options.title) { //自定义顶部导航title
wx.setNavigationBarTitle({
title: options.title
})
}
const userInfo = wx.getStorageSync('userInfo');
this.setData({
userInfo,
coursewareId: options.coursewareId,
isFromReport: options.isFromReport ? true : false,
title: options.title,
info: {
thumb: options.thumb,
title: options.title,
updateTime: options.updateTime
},
activityMaterials: []
})
lock = false
//先调用接口 如果length为零 那么新增一个对象
this.loadData()
this.initRecord()//这个是录音的内容要调用
},
onShow: function () { //这是录音的马蜂窝
var that = this;
recorderManager.onStart(() => {//开始录音时触发
status = 0;
iatResult = []
//console.log('recorder start');
that.data.firstSend = false;
});
recorderManager.onError((res) => {//错误回调
//console.log(res);
});
recorderManager.onStop((res) => {//结束录音时触发
//console.log('recorder stop')
//console.log(res)
let otime = (res.duration/1000).toFixed(0)
status = 2;
var sendsty = '{"data":{"status":2,"audio":"","format":"audio/L16;rate=8000","encoding":"raw"}}'
wxst.send({
data: sendsty
})
wx.uploadFile({
// 模拟https
url: BASE_URL + 'common/uploadMediaToTencent', //需要用HTTPS,同时在微信公众平台后台添加服务器地址
filePath: res.tempFilePath, //上传的文件本地地址
name: 'file',
//附近数据,这里为路径
success: function(result) {
// console.log("--结束录音--")
// console.log(that.data.contentTxt)
// console.log(JSON.parse(result.data).url)
// console.log(otime)
if(that.data.contentTxt){
//recordArr: []//音频数组 包含三个字段 url->mp3格式文件 txt:MP3的文字版的文本 time: 录音的时间 played:是否正在播放
let ourl = JSON.parse(result.data).url
let pidx = that.data.parentIndex
let params = {
url: ourl,
txt: that.data.contentTxt,
time: that.timeHandle(otime),//这个时间是用来显示的
played: false,
showTxt: false,
}
let oarr = that.data.activityMaterials
oarr.forEach((item) => {
item.recordArr = item.recordArr && item.recordArr.length > 0 ? item.recordArr : []
})
oarr[pidx].recordArr.push(params)
that.setData({
activityMaterials: oarr
})
//console.log(that.data.activityMaterials)
}else{
//console.log("木有内容啊")
}
},
fail: function(err) {
//console.log(err)
}
})
});
recorderManager.onFrameRecorded((res) => {//每帧触发
const that = this
const { frameBuffer, isLastFrame } = res
let params = {
'common': {
'app_id': '57198f05'
},
'business': {
'language': 'zh_cn', //⼩语种可在控制台--语⾳听写(流式)--⽅⾔/语种处添加试⽤
'domain': 'iat',
'accent': 'mandarin', //中⽂⽅⾔可在控制台--语⾳听写(流式)--⽅⾔/语种处添加试⽤
'vad_eos': 1000,
'dwa': 'wpgs' //为使该功能⽣效,需到控制台开通动态修正功能(该功能免费)
},
'data': {
'status': 0,
'format': 'audio/L16;rate=16000',
'encoding': 'lame',
'audio': wx.arrayBufferToBase64(frameBuffer)
}
}
// 拼接数据
let status = 0
if (this.data.firstSend) {
this.data.firstSend = false
} else {
if (isLastFrame) {
status = 2
} else {
status = 1
}
}
params.data.status = status
wx.sendSocketMessage({
data: JSON.stringify(params),
success: (data) => {
console.log('send success:' + JSON.stringify(data))
//that.resetRecordState()
},
fail: (err) => {
console.log('send error:' + JSON.stringify(err))
//中断录音的时候
//that.resetRecordState()
},
completed: () => {
if (isLastFrame) {
// wx closeSocket
}
}
})
})
},
timeHandle(time){
if(time < 9){
return '0' + time
}else{
return time
}
},
//重置录音按钮状态
resetRecordState(){
let activityMaterials = this.data.activityMaterials
activityMaterials[this.data.parentIndex].recordState = false
this.setData({
activityMaterials: activityMaterials
})
},
save() {//这里还没改 不重要的文件
if (lock) return
lock = true
//处理过滤activityMaterials数据
let actArr = this.data.activityMaterials.map(function (item) {
let oarr = []
//转换数据格式
oarr[0] = {
content: item.content
}
for (let i in item.material) {
oarr.push({
content: item.material[i].url
})
}
return {
title: item.title,
paragraphs: oarr
}
})
for (let i in actArr) {
//title等于编辑标题就代表没编辑过 paragraphs[0].content的值为空就代表textare没编辑过 paragraphs[1]不存在或者content为空就代表没编辑过
if (actArr[i].title == '编辑标题' && !actArr[i].paragraphs[0].content && (!actArr[i].paragraphs[1] || !actArr[i].paragraphs[1].content)) {
actArr.splice(i, 1)
}
}
if (actArr.length == 0) {
wx.showToast({
title: '请先编辑材料!',
icon: 'none',
duration: 2000
})
lock = false
return
}
util.request(api.activityPreparationSave, {
teacherId: this.data.userInfo.userId,
classId: this.data.userInfo.deptId,
coursewareId: this.data.coursewareId,
activityMaterials: actArr
}, 'POST', 'application/json').then(res => {
if (res.code = 200) {
wx.showToast({
title: '提交成功!',
icon: 'error',
duration: 2000
})
//判断是不是报告那边跳转过来的
if (this.data.isFromReport) {
let oinfo = this.data.info
wx.redirectTo({
url: '../reportdetail/reportdetail?coursewareId=' + this.data.coursewareId + '&title=' + oinfo.title + '&thumb=' + oinfo.thumb + '&updateTime=' + oinfo.updateTime
})
} else {
wx.navigateBack({
delta: 1
});
}
lock = false
} else {
wx.showToast({
title: res.msg,
icon: 'error',
duration: 2000
})
lock = false
}
});
},
loadData() {
util.request(api.activityPreparationList + this.data.userInfo.userId + '&coursewareId=' + this.data.coursewareId + '&classId=' + this.data.userInfo.deptId, '', 'get').then(res => {
if (res.code = 200) {
let odata = res.data
if (odata && odata.length == 0) {
let obj = this.data.activityMaterials
obj.push({
title: '编辑标题',
isEdit: false,
content: '',
material: []
})
this.setData({
activityMaterials: obj
})
} else {
//重组数据
//type 1图片 3视频
let oarr = odata.map(function (item) {
let paragraphs = []
for (let i in item.paragraphs) {
paragraphs.push({
url: item.paragraphs[i].content,
type: item.paragraphs[i].type == '3' ? 'mp4' : item.paragraphs[i].type == '1' ? 'img' : ''
})
}
return {
title: item.title ? item.title : '编辑标题',
isEdit: false,
content: item.content,
material: paragraphs
}
})
//console.log(oarr)
this.setData({
activityMaterials: oarr
})
}
} else {
wx.showToast({
title: res.msg,
icon: 'error',
duration: 2000
})
}
});
},
addListHandle() {
let obj = this.data.activityMaterials
obj.push({
title: '编辑标题',
isEdit: false,
content: '',
material: []
})
this.setData({
activityMaterials: obj
})
},
titleHandle(e) {
let obj = this.data.activityMaterials
let idx = e.currentTarget.dataset.idx
obj[idx].isEdit = true
this.setData({
activityMaterials: obj
})
},
inputBlurHandle(e) {
let oval = e.detail.value
let obj = this.data.activityMaterials
let idx = e.currentTarget.dataset.idx
if (oval) {
obj[idx].title = oval
}
obj[idx].isEdit = false
this.setData({
activityMaterials: obj
})
},
textareaBlurHandle(e) {
let oval = e.detail.value
let obj = this.data.activityMaterials
let idx = e.currentTarget.dataset.idx
if (oval) {
obj[idx].content = oval
}
this.setData({
activityMaterials: obj
})
},
preview(e) {
let currentUrl = e.currentTarget.dataset.src
let pidx = e.currentTarget.dataset.pidx //父级循环的index
const oarr = []
for (let i in this.data.activityMaterials[pidx].material) {
oarr.push(this.data.activityMaterials[pidx].material[i].url)
}
wx.previewImage({
current: currentUrl, // 当前显示图片的http链接
urls: oarr // 需要预览的图片http链接列表
})
},
closeHadle(e) {
//console.log(e)
const that = this
wx.showModal({
title: '',
content: '是否删除素材',
success(res) {
if (res.confirm) {
let obj = that.data.activityMaterials
let pidx = e.currentTarget.dataset.pidx //父级循环的index
let idx = e.currentTarget.dataset.idx //子级循环的index
obj[pidx].material.splice(idx, 1)
that.setData({
activityMaterials: obj
})
} else if (res.cancel) {
//console.log('用户点击取消')
}
}
})
},
//上传图片、视频
uploadFile: function (e) {
const that = this
let obj = this.data.activityMaterials
let pidx = e.currentTarget.dataset.idx
wx.chooseMedia({
count: 9, // 设置为需要上传的文件数量
mediaType: ['image', 'video'],
success: function (res) {
const files = res.tempFiles;
// 遍历选择的文件数组,依次上传每个文件
files.forEach(function (file) {
const tempFilePath = file.tempFilePath;
wx.uploadFile({
url: BASE_URL + 'common/uploadMediaToTencent',
filePath: tempFilePath,
name: 'file',
success: function (res) {
//console.log(res)
let ores = JSON.parse(res.data)
//每个数组里添加一个type值是mp4或者img,在for循环里通过type赋值到mp4或者img里面
let otype = that.getFileExtension(ores.url)
if (otype) {
let params = {
url: ores.url,
type: otype
}
obj[pidx].material.push(params)
}
that.setData({
activityMaterials: obj
})
},
fail: function (res) {
//console.log(res.errMsg);
// 处理上传失败后的逻辑
}
})
});
}
})
},
//用一个方法来判断 返回的文件是mp4 还是图片
getFileExtension(url) {
const dotIndex = url.lastIndexOf('.');
const extension = url.substring(dotIndex + 1);
if (/(jpg|jpeg|png)$/.test(extension.toLowerCase())) {
return 'img'
} else if (/(mp4|avi|mov)$/.test(extension.toLowerCase())) {
return 'mp4'
}
return false
},
deleteHandle(e) {
const that = this
wx.showModal({
title: '',
content: '是否删除',
success(res) {
if (res.confirm) {
let obj = that.data.activityMaterials
let idx = e.currentTarget.dataset.idx //子级循环的index
obj.splice(idx, 1)
that.setData({
activityMaterials: obj
})
} else if (res.cancel) {
//console.log('用户点击取消')
}
}
})
},
//识别语音 -- 初始化 从这里开始是录音的内容 一直到结束
initRecord: function () {
var that = this;
wx.onSocketOpen((res) => {// websocket打开
//console.log('监听到 WebSocket 连接已打开' + res);
})
wx.onSocketError((err) => {//连接失败
//console.log('websocket连接失败', err);
wx.showToast({
title: 'websocket连接失败',
icon: 'none',
duration: 2000,
mask: false
})
})
wx.onSocketMessage((res) => {//接收返回值
var data = JSON.parse(res.data)
//console.log('----------------')
//console.log(data)
if (data.code != 0) {
//console.log("error code " + data.code + ", reason " + data.message)
return
}
let str = ""
if (data.data.status == 2) {//最终识别结果
// data.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
wxst.close();
} else {//中间识别结果
}
iatResult[data.data.result.sn] = data.data.result
if (data.data.result.pgs == 'rpl') {
data.data.result.rg.forEach(i => {
iatResult[i] = null
})
}
iatResult.forEach(i => {
if (i != null) {
i.ws.forEach(j => {
j.cw.forEach(k => {
str += k.w
})
})
}
});
// console.log('这个是中间的语音识别结果')
// console.log(str)
that.setData({
contentTxt: str //这个是中间的语音识别结果
})
if(!this.data.contentTxt){
wx.showToast({
title: '识别失败,请重新录入',
icon: 'none',
duration: 2000,
mask: false
})
return
}
})
wx.onSocketClose((res) => {//WebSocket连接已关闭!
//var that = this;
recorderManager.stop();
// var str = that.data.contentTxt;
// console.log(str);
// str = str.replace(/\s*/g, "");//去除空格
// if (str.substr(str.length - 1, 1) == "。") {//去除句号
// str = str.substr(0, str.length - 1);
// }
// console.log('这个是最后确定的语音识别结果', str)
// that.setData({
// contentTxt: str//这个是最后确定的语音识别结果
// })
//console.log('WebSocket连接已关闭!')
})
},
//录音和停止录音操作
recordHandle(e){
let oactivityMaterials = this.data.activityMaterials
let parentIndex = e.currentTarget.dataset.idx
this.setData({//获取父级的下标 后面录音结束后给对应的模块赋值
parentIndex: parentIndex
})
//改成点击事件
if(!oactivityMaterials[parentIndex].recordState){
wx.showToast({
title: '开始录音',
icon: 'none',
duration: 1000
})
//兄弟节点的录音按钮改成灰色
if(oactivityMaterials.length > 1){
for(let i in oactivityMaterials){
oactivityMaterials[i].recordState = false
}
this.setData({
activityMaterials: oactivityMaterials
})
}
oactivityMaterials[parentIndex].recordState = true
this.setData({
activityMaterials: oactivityMaterials //录音状态
})
wx.getSetting({//查看用户有没有开启语音权限
success(res) {
if (res.authSetting['scope.record']) {
wx.authorize({
scope: 'scope.record',
success() {
var xfurl = "";
wx.request({//请求接口 获取讯飞语音鉴权
url: BASE_URL + 'assistant/url',
method: "get",
header: {
'content-type': 'application/json' // 默认值
},
success: function (res) {
//console.log('鉴权结果start:');
//console.log(res);
if (res.statusCode == "200" && res.data) {
xfurl = res.data;
wxst = wx.connectSocket({ // 开启websocket连接
url: xfurl,
method: 'GET',
success: function (res) {
recorderManager.start(searchoptions);//开始录音
}
});
} else {
wx.showToast({
title: '获取语音鉴权失败',
icon: 'none',
mask: true,
duration: 3000
})
}
},
fail: function () {
wx.showToast({
title: '获取语音鉴权失败',
icon: 'none',
mask: true,
duration: 3000
})
}
})
},
fail() {
wx.showModal({
title: '微信授权',
content: '您当前未开启语音权限,请在右上角设置(···)中开启“录音功能”',
showCancel: false,
success(res) {
if (res.confirm) {
//console.log('用户点击确定')
}
}
})
}
})
} else {
wx.showModal({
title: '微信授权',
content: '您当前未开启语音权限,请在右上角设置(···)中开启“录音功能”',
showCancel: false,
success(res) {
if (res.confirm) {
//console.log('用户点击确定')
}
}
})
}
}
})
}else{
oactivityMaterials[parentIndex].recordState = false
this.setData({
activityMaterials: oactivityMaterials
})
recorderManager.stop();
}
},
//播放操作
playHandle(e){
const that = this
let idx = e.currentTarget.dataset.idx
let pidx = e.currentTarget.dataset.pidx
//recordArr的字段有url/txt/time/played/showTxt
let activityMaterials = this.data.activityMaterials
let orecordArr = activityMaterials[pidx].recordArr[idx]
innerAudioContext.src = orecordArr.url
if(!orecordArr.played){
//查找兄弟节点 把所有的played状态改成false
for(let i in activityMaterials){
for(let j in activityMaterials[i].recordArr){
activityMaterials[i].recordArr[j].played = false
}
}
// if(activityMaterials && activityMaterials.length > 1){
// that.setData({
// activityMaterials: activityMaterials
// })
// }
//播放
orecordArr.played = true
innerAudioContext.play() // 播放
innerAudioContext.onEnded(() => {
//console.log('语音播放结束');
orecordArr.played = false
that.setData({
activityMaterials: activityMaterials
})
});
}else{
//关闭
orecordArr.played = false
innerAudioContext.stop() // 停止
}
this.setData({
activityMaterials: activityMaterials
})
}
})
wxss部分
.wrap{ padding: 22rpx 10rpx 100rpx 10rpx;}
.white-box{ margin-bottom: 22rpx; padding: 22rpx; width: 730rpx; box-sizing: border-box; background: #fff; border-radius: 25rpx;}
.title-box,.title-txt-part{ display: flex; align-items: center;}
.title-box{ position: relative;}
.icon-close-black{ position: absolute; right: 0; display: block; width: 20rpx; height: 21rpx;}
.icon-edit{ margin-left: 10rpx; width: 31rpx; height: 30rpx;}
.yellow-fence{ margin-right: 10rpx; width: 6rpx; height: 30rpx; background: #ffb81c; border-radius: 3rpx;}
.title-txt-part{ font-size: 28rpx; font-weight: bold;}
.title-input{ padding-left: 16rpx; width: 360rpx; height: 60rpx; border:1rpx solid #ddd; border-radius: 10rpx; font-size: 26rpx;}
.material-box{ margin-top: 22rpx; display: flex; justify-content: flex-start; flex-wrap: wrap;}
.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;}
button::after {border: none;}
.icon-photo{ margin-right: 10rpx; display: block; width: 93rpx; height: 85rpx;}
.material-list{ position: relative; margin: 0 25rpx 25rpx 0; width: 310rpx; height: 186rpx;}
.material-list-m2{ width: 100%; height: 100%; border-radius: 22rpx;}
.icon-close{ position: absolute; top: 10rpx; right: 10rpx; z-index: 999; display: block; width: 50rpx; height: 50rpx;}
.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;}
.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;}
.textarea-box-wrap{ margin-top: 22rpx; padding: 22rpx; display: flex; flex-direction: column; justify-content: center; height: 580rpx; background: #f0f0f0; border-radius: 25rpx;}
.textarea-box{ flex:1; height: 100%; box-sizing: border-box; font-size: 25rpx; color: #111;}
.voice-box{ margin-bottom: 20rpx; max-height: 200rpx; overflow-y: scroll; box-sizing: border-box; font-size: 25rpx; color: #111;}
.videoBtn {width: 50%;}
.videoBtn text{color:#fff;}
.videoBtnBg {background: #bdb4b4;}
.startYuyinImage {
position: fixed;
top: 200rpx;
left: 50%;
z-index: 99;
transform: translateX(-50%);
display:flex;justify-content:center;flex-flow: column;
width: 220rpx;
height: 220rpx;
text-align: center;
background: rgba(0, 0, 0, 0.1);
color: #fff;
font-size: 24rpx;
border-radius: 50%;
}
.startYuyinImage cover-image { margin:0 auto; width:80rpx;height: 80rpx;}
.startYuyinImage cover-view { margin-top: 22rpx;}
.musicd {
position: fixed;
z-index: 9999;
top: 10%;
left: 4%;
}
.musicd image {
width: 100rpx;
height: 100rpx;
z-index: 999;
}
.icon-record{ display: block; width: 70rpx; height: 70rpx;}
.record-btn{ margin: 0 auto; padding: 0; width: 70rpx; height: 70rpx; background: transparent; border-radius: 50%;}
button::after{border: none;}
.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;}
.icon-video{ display: block; width: 56rpx; height: 55rpx;}
.record-list .t1{ margin: 0 22rpx;}
.record-txt{ padding:10rpx 10rpx 0 10rpx; font-size: 24rpx; color: #19b2ff;}
.record-item{ margin-bottom: 22rpx;}
.record-item:last-child{ margin-bottom: 0;}
json不用调用什么
页面我也还没写完 单纯的记录一下这个功能