Files
APP/pages/common/audioManager/Recording.vue

1557 lines
37 KiB
Vue
Raw Normal View History

2025-11-07 12:16:10 +08:00
<template>
<view class="maincontent contentBg">
<!-- 文字转语音 -->
<view v-if="Status.pageType==='Txt'">
<view>
<view class="importTxt fright" @click="importDoc">导入文档</view>
<view class="clear"></view>
</view>
<view class="text-content">
<view class="uni-textarea">
<textarea class="textarea" v-model="formData.txt" placeholder-class="placehoderClass"
placeholder="请输入要转换的文本" :auto-height="true" maxlength="100" cursor-color="#BBE600" />
</view>
<view class="line"></view>
<view class="footBtn">
<view class="fright convert" @click.stop="txtToAudio()">转换</view>
<view class="fright audioSett" @click.stop="formData.txt=''">清空</view>
<view class="clear"></view>
</view>
</view>
</view>
<!-- 获取到的语音信息 -->
<view class="cEdit" :class="{'displayNone':(!AudioData.tempFilePath && Status.pageType!=='Txt')|| (AudioData.hexLength===0 && Status.pageType==='Txt')}">
<view class="audioRemark">
<view>
<view>
<input type="text" class="txtName" v-model="cEdit.name" placeholder="音频名称"
placeholder-class="placehoderClass" />
</view>
<view>
<text>{{cEdit.createTime}}</text>
<text>{{getFormatSeconds(cEdit.time,true)}}</text>
</view>
</view>
<view class="btnSave" v-if="Status.pageType!=='Txt'" @click.stop="uploadLuYin">保存</view>
</view>
<view class="slide" v-if="Status.pageType!=='Txt'">
<view class="circle" :style="{'left':PlayProgress}"></view>
<view class="line"></view>
<view class="fleft">
{{getFormatSeconds(cEdit.currTime)}}
</view>
<view class="fright">
{{getFormatSeconds(cEdit.time)}}
</view>
<view class="clear"></view>
</view>
<view class="control" v-if="Status.pageType!=='Txt'">
<view class="playControl">
<view class="seek" @click.stop="seek(-10)">
<image class="img" src="/static/images/common/prev.png" mode="aspectFit"></image>
</view>
<view class="play" @click="playToggle()">
<image class="img"
:class="{'displayNone':Status.playState!=='ready' && Status.playState!=='pause'}"
src="/static/images/common/play.png" mode="aspectFit"></image>
<image class="img" :class="{'displayNone':!Status.playState || Status.playState!=='play'}"
src="/static/images/common/pause.png" mode="aspectFit"></image>
</view>
<view class="seek" @click.stop="seek(10)">
<image class="img" src="/static/images/common/next.png" mode="aspectFit"></image>
</view>
</view>
<view class="drop" v-if="Status.pageType!=='Txt'" @click.stop="drop()">
<uni-icons type="trash" size="30" color="#e03434"></uni-icons>
</view>
</view>
</view>
<view class="txtBtns" v-if="Status.pageType==='Txt'"
:class="{'displayNone':AudioData.hexLength===0}">
<view class="btnSave fright" @click.stop="SaveTTS()">保存</view>
<view class="audioSett fright" @click.stop="CancelTTS">取消</view>
<view class="clear"></view>
</view>
<!-- 录音的提示 -->
<view v-if="Status.pageType==='Record'">
<view class="tips" :class="{'displayNone':Status.isRecord || AudioData.tempFilePath}">
点击下方红色录制按钮开始录音吐字清晰语句流畅
</view>
</view>
<!-- 录音选择文件操作 -->
<view class="footer" v-if="Status.pageType!=='Txt'">
<view class="opt">
<view class="recording" :class="{'displayNone':Status.pageType!=='Record'}">
<view class="recordTitle">语音录制{{Status.RecordName}}</view>
<view class="recordName" :class="{'visibilityHidden':!formatSecondsToDHMS}">{{formatSecondsToDHMS?formatSecondsToDHMS:"00:00"}}</view>
</view>
<view class="btnRecord center" @click.stop="toggleRecord()"
:class="{'displayNone':Status.pageType!=='Record'}">
<view class="start" :class="{'active':Status.isRecord}"></view>
</view>
<view class="btnRemark" :class="{'displayNone':Status.pageType!=='Record'}">
{{Status.isRecord?'录制中':'录制'}}
</view>
<view class="btnCheckFile center" @click.stop="checkFile()"
:class="{'displayNone':Status.pageType!=='File'}">
<view class="polygon center">
<uni-icons type="plusempty" size="45" color="#ffffff99"></uni-icons>
</view>
</view>
</view>
</view>
<!-- 自定义弹出层 -->
<MessagePopup :visible="Status.Pop.showPop" :type="Status.Pop.popType" :bgColor="Status.Pop.bgColor"
:borderColor="Status.Pop.borderColor" :textColor="Status.Pop.textColor"
:buttonBgColor="Status.Pop.buttonBgColor" :buttonTextColor="Status.Pop.buttonTextColor"
:iconUrl="Status.Pop.iconUrl" :message="Status.Pop.message" :buttonText="Status.Pop.buttonText"
@buttonClick="HidePop" :visiblePrompt="Status.Pop.visiblePrompt" :promptTitle="Status.Pop.promptTitle"
v-model="Status.Pop.modelValue" @closePop="closePop" :buttonCancelText="Status.Pop.buttonCancelText"
:showCancel="Status.Pop.showCancel" @cancelPop="closePop" :showSlot="Status.Pop.showSlot">
<view class="popup-prompt">
<input type="text" class="popup-prompt-input" placeholder="请输入名称" v-model="cEdit.name" />
</view>
</MessagePopup>
<global-loading ref="loading" />
<xe-upload ref="XeUpload" :options="uploadOptions" @callback="handleUploadCallback"></xe-upload>
</view>
</template>
<script>
var eventChannel = null;
var these = null;
var innerAudioContext = null;
var AudeoRecoder = null;
var audioTime = null;
var hexs = null;
import BleTool from '@/utils/BleHelper.js';
import request, {
baseURL
} from '@/utils/request';
import {
showLoading,
hideLoading,
updateLoading
} from '@/utils/loading.js';
import Common from '@/utils/Common.js';
export default {
data() {
return {
Status: {
playState: '', //播放状态
pageType: '', //页面类型,用于区分录音、选择文件、文字转语音
pageValid: false, //页面状态,是否已销毁
recoderIntval: null, //录音的定时器
isRecord: false, //是否正在录音
RecordTime: null, //已录间的时长
Pop: { //弹出框的配置
showPop: false, //是否显示弹窗
popType: 'custom',
bgColor: '#383934bd',
borderColor: '#BBE600',
textColor: '#ffffffde',
buttonBgColor: '#BBE600',
buttonTextColor: '#232323DE',
iconUrl: '',
message: '您确定要这样做吗?',
buttonText: '确定',
clickEvt: '',
visiblePrompt: false,
promptTitle: '设备名称',
modelValue: '',
visibleClose: false,
okCallback: null,
buttonCancelText: '',
showCancel: false,
showSlot: false
},
},
cEdit: {
Id: "", //编号
name: "", //名称
createTime: "", //创建时间
localPath: "", //本地地址
webPath: "", //网络地址
statu: "", //状态,是否公开
isApply: "", //是否使用中
time: "", //音频总长度
currTime: '', //当前播放进度
type:''
},
AudioData: {
tempFilePath: '',
hexLength:0
},
uploadOptions: {
},
formData: {
txt: '只要你能吃苦,就有吃不完的苦'
}
}
},
computed: {
formatSecondsToDHMS() {
let seconds = this.Status.RecordTime;
return this.getFormatSeconds(seconds);
},
PlayProgress() {
return this.cEdit.currTime / (this.cEdit.time === 0 ? 1 : this.cEdit.time) * 100 + '%';
}
},
onLoad(opt) {
eventChannel = this.getOpenerEventChannel();
these = this;
this.Status.pageType = opt.pageType;
let title = ""
if (opt.pageType === 'Record') {
title = "录制语音";
} else if (opt.pageType === 'Txt') {
title = '文字转语音';
} else {
title = "文件上传";
}
uni.setNavigationBarTitle({
title: title
});
},
onUnload() {
this.destoryAudioPlayer();
clearInterval(audioTime);
eventChannel.emit('RecordOver', {
data: '从音频页面返回,刷新数据'
});
},
onBackPress(e) {
debugger;
if (this.Status.isRecord) { //如果正在录音,提示是否放弃
this.showMsg("正在录音,是否放弃?", false, true, () => {
these.Status.pageValid = true;
these.stopLuYin();
uni.navigateBack();
});
return true;
} else {
if (this.AudioData.tempFilePath) {
this.showMsg("录音没有保存是否放弃?", false, true, () => {
these.Status.pageValid = true;
this.dropTmpFile();
this.AudioData.tempFilePath = "";
AudeoRecoder = null;
uni.navigateBack();
});
return true;
}
}
},
methods: {
CancelTTS(){
this.cEdit.name='';
this.cEdit.Id="";
this.cEdit.createTime="";
this.cEdit.currTime="";
this.cEdit.isApply="";
this.cEdit.localPath="";
this.cEdit.statu="";
this.cEdit.time="";
this.cEdit.webPath="";
this.AudioData.hexLength=0;
this.cEdit.type=this.Status.pageType;
hexs=[];
},
SaveTTS() {
if (!this.cEdit.name) {
this.showMsg("请输入语音名称");
return;
}
this.cEdit.localPath = "";
this.cEdit.Id = Common.guid();
this.cEdit.createTime = Common.DateFormat(new Date(), "yyyy年MM月dd日");
this.cEdit.isApply = false;
this.cEdit.statu = false;
this.cEdit.type=this.Status.pageType;
this.cEdit.webPath = "";
let pro1 = new Promise((resolve, reject) => {
uni.setStorage({
key: Common.pcmStorageKey + "_" + this
.cEdit.Id,
data: hexs,
success() {
resolve();
},
fail(ex) {
reject(ex)
}
});
});
let pro2 = new Promise((resolve, reject) => {
let array = uni.getStorageSync(Common
.audioStorageKey);
if (!array) {
array = [this.cEdit];
} else {
array.unshift(this.cEdit);
}
uni.setStorage({
key: Common.audioStorageKey,
data: array,
success() {
resolve();
},
fail(ex) {
reject(ex)
}
});
});
Promise.allSettled([pro1, pro2]).then(res => {
if (res[0].status == 'fulfilled' && res[1]
.status == 'fulfilled') {
updateLoading(these, {
text: "操作成功"
});
this.AudioData.tempFilePath = "";
this.Status.isRecord = false;
uni.navigateBack();
return;
} else {
updateLoading(these, {
text: "操作没有成功"
});
}
this.timeOutCloseLoad();
}).catch(ex => {
updateLoading(these, {
text: "出现异常" + JSON.stringify(ex)
});
this.timeOutCloseLoad();
});
},
importDoc() {
this.checkFile();
},
txtToAudio() {
let msg = "";
if (!this.formData.txt) {
msg = '请输入语音内容';
}
if (this.formData.txt.length > 100) {
msg = "内容限制在100字以内";
}
if (msg) {
this.showMsg(msg);
return;
}
hexs = [];
this.AudioData.hexLength=0;
showLoading(this, {
text: '正在生成语音'
});
let closeWaiting = () => {
setTimeout(() => {
hideLoading(this);
}, 2000)
}
let task = () => {
return new Promise((succ, err) => {
request({
url: "/app/video/audioTTS",
method: 'GET',
data: {
text: this.formData.txt
}
}).then(res => {
if (res && res.code && res.code === 200) {
succ(res.data);
} else {
err(res);
}
}).catch(ex => {
console.error("出现异常", ex);
err(res);
});
})
}
task().then(res => {
try {
debugger;
console.log("文本转语音成功", res);
hexs = res;
this.AudioData.hexLength =hexs.length;
this.AudioData.tempFilePath = "";
this.cEdit.localPath = "";
this.cEdit.time="";
this.playInit("");
updateLoading(this, {
text: '文本转语音成功'
});
} catch (error) {
console.error("出现错误,", error)
}
}).catch(ex => {
console.error("出现异常", ex);
updateLoading(this, {
text: '生成失败'
});
}).finally(closeWaiting);
},
timeOutCloseLoad() {
setTimeout(() => {
hideLoading(these);
}, 1200);
},
uploadLuYin() {
let key = Common.pcmStorageKey + "_" + this.cEdit.Id;
var store = uni.getStorageInfoSync();
var f = store.keys.includes(key);
if (f) {
return;
}
const token = uni.getStorageSync('token');
const clientid = uni.getStorageSync('clientID');
showLoading(this, {
text: "文件上传中"
});
console.log("token=", {
token: token,
clientid: clientid
});
setTimeout(() => {
uni.uploadFile({
url: baseURL + "/app/video/audio",
filePath: this.AudioData.tempFilePath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data",
"Authorization": 'Bearer ' + token,
"clientid": clientid
},
timeout: 1200000,
fail: (ex) => {
updateLoading(these, {
text: "未知的原因上传失败"
});
this.timeOutCloseLoad();
},
success: (res) => {
// console.log("服务器响应=", res);
if (res && res.data) {
try {
res.data = JSON.parse(res.data);
if (res.data.code == 200) {
let pro1 = new Promise((resolve, reject) => {
uni.setStorage({
key: Common.pcmStorageKey + "_" + this
.cEdit.Id,
data: res.data.data,
success() {
resolve();
},
fail(ex) {
reject(ex)
}
});
});
let pro2 = new Promise((resolve, reject) => {
let array = uni.getStorageSync(Common
.audioStorageKey);
if (!array) {
array = [this.cEdit];
} else {
array.unshift(this.cEdit);
}
uni.setStorage({
key: Common.audioStorageKey,
data: array,
success() {
resolve();
},
fail(ex) {
reject(ex)
}
});
});
Promise.allSettled([pro1, pro2]).then(res => {
if (res[0].status == 'fulfilled' && res[1]
.status == 'fulfilled') {
updateLoading(these, {
text: "操作成功"
});
this.AudioData.tempFilePath = "";
this.Status.isRecord = false;
uni.navigateBack();
return;
} else {
updateLoading(these, {
text: "操作没有成功"
});
}
this.timeOutCloseLoad();
}).catch(ex => {
updateLoading(these, {
text: "出现异常" + JSON.stringify(ex)
});
this.timeOutCloseLoad();
});
return;
}
} catch (error) {
console.error("出现异常,", error);
}
}
updateLoading(these, {
text: "未知的异常上传失败"
});
this.timeOutCloseLoad();
},
complete() {
}
});
}, 10);
},
drop() {
this.showMsg("您确定删除该音频吗?", false, true, () => {
these.dropTmpFile();
this.cEdit = {
Id: "", //编号
name: "", //名称
createTime: "", //创建时间
localPath: "", //本地地址
webPath: "", //网络地址
statu: "", //状态,是否公开
isApply: "", //是否使用中
time: "", //音频总长度
currTime: '' //当前播放进度
};
this.Status.playState = "";
})
},
seek(intval) { //快进快退
let tmp = this.cEdit.currTime + intval;
console.log("tmp=" + tmp)
if (tmp < 0) {
this.cEdit.currTime = 0;
innerAudioContext.seekTo(0);
innerAudioContext.play();
} else if (tmp > this.cEdit.time) {
this.cEdit.currTime = this.cEdit.time;
innerAudioContext.seekTo(this.cEdit.time);
innerAudioContext.stop();
clearInterval(audioTime);
} else {
this.cEdit.currTime = tmp;
innerAudioContext.seekTo(tmp);
}
},
playToggle() {
if (this.Status.playState === '') {
this.showMsg("音频未就绪");
return;
}
if (innerAudioContext) {
if (this.Status.playState == 'play') {
innerAudioContext.pause();
} else {
innerAudioContext.play();
}
} else {
this.showMsg("播放器未就绪");
}
},
getFormatSeconds(seconds, Ms) {
if (!seconds) {
return "";
}
let totalSeconds = Math.floor(seconds);
let days = Math.floor(totalSeconds / 86400); // 1天=86400秒
let remainingSeconds = totalSeconds % 86400;
let hours = Math.floor(remainingSeconds / 3600);
let minutes = Math.floor((remainingSeconds % 3600) / 60);
let secs = remainingSeconds % 60;
// 补零处理
let paddedDays = String(days).padStart(2, '0');
let paddedHours = String(hours).padStart(2, '0');
let paddedMinutes = String(minutes).padStart(2, '0');
let paddedSecs = String(secs).padStart(2, '0');
if (Ms) {
return `${paddedMinutes}${paddedSecs}`;
}
return `${paddedMinutes}:${paddedSecs}`;
},
createAudioPlayer() {
try {
console.log("准备创建播放器");
if (innerAudioContext) {
this.destoryAudioPlayer();
clearInterval(audioTime);
this.cEdit.currTime = 0;
}
innerAudioContext = plus.audio.createPlayer({
src: this.cEdit.localPath,
autoplay: false,
backgroundControl: false,
});
console.log('播放器创建成功');
innerAudioContext.addEventListener('canplay', () => {
console.log("准备就绪,可以播放了");
this.Status.playState = 'ready';
this.cEdit.time = innerAudioContext.getDuration();
this.cEdit.time =Math.ceil(this.cEdit.time);
console.log("音频长度:", this.cEdit.time);
});
console.log("canplay事件注册成功")
//开始播放
innerAudioContext.addEventListener("play", (res) => {
if (this.Status.playState === 'ready') {
this.cEdit.currTime = 0;
}
this.Status.playState = 'play';
audioTime = setInterval(() => {
this.cEdit.currTime += 1;
}, 1000);
console.log("播放中", res);
});
console.log("play事件注册成功")
//播放结束
innerAudioContext.addEventListener("ended", (res) => {
clearInterval(audioTime);
this.cEdit.currTime = 0;
this.Status.playState = 'ready';
console.log("播放结束", res);
});
console.log("ended事件注册成功")
//暂停播放
innerAudioContext.addEventListener("pause", (res) => {
clearInterval(audioTime);
audioTime = null;
this.Status.playState = 'pause';
console.log("暂停了", res);
});
console.log("pause事件注册成功")
innerAudioContext.addEventListener("seeked", (res) => {
console.log("seek完成了", res);
})
console.log("seeked事件注册成功")
innerAudioContext.addEventListener('error',ex=>{
console.log("出错了",ex)
});
console.log("error事件注册成功");
this.Status.playState = 'ready';
} catch (ex) {
console.error("出现错误", ex);
}
},
destoryAudioPlayer() { //销毁播放器
if (innerAudioContext) {
innerAudioContext.close();
console.log("播放器已销毁");
}
},
handleUploadCallback(res) {
console.log("选择文件:", res);
if (res && res.data) {
if (this.Status.pageType === 'File') { //文件上传
if (res.data[0].type.indexOf('audio') > -1) {
this.cEdit.name = res.data[0].name;
this.playInit(res.data[0].tempFilePath);
} else {
this.showMsg("只能选择音频文件");
}
return;
}
if (this.Status.pageType === 'Txt') { //文字转语音
let file = res.data[0];
let path = file.tempFilePath;
let type = file.type;
if (type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
this.parseWord(path); //docx
return;
}
if (type === 'text/plain') {
this.parseTxt(path); //txt
return;
}
if (type == "application/msword") { //doc
this.showPop({
showPop: true, //是否显示弹窗
popType: 'custom',
bgColor: '#383934bd',
borderColor: '#BBE600',
textColor: '#ffffffde',
buttonBgColor: '#BBE600',
buttonTextColor: '#232323DE',
iconUrl: '',
message: '打开文档后请手动复制文本内容',
buttonText: '打开',
clickEvt: '',
visiblePrompt: false,
promptTitle: '',
modelValue: '',
visibleClose: false,
okCallback: () => {
this.parseDoc(path);
},
showSlot: false,
buttonCancelText: '取消',
showCancel: true,
});
return;
}
this.showMsg("只能选择.txt、.docx、.doc文档");
return;
}
} else {
console.log("未选择任何文件");
}
},
parseTxt(txtPath) { //读取txt文件
showLoading(this, {
text: "文档读取中"
});
let promise = new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(
txtPath,
(entry) => {
// 2. 获取文件对象
console.log("111111");
entry.file(
(file) => {
console.log("22222")
try {
let reader = new plus.io.FileReader();
reader.onloadend = function(e) {
// Get data
console.log("读取成功:", e.target.result);
resolve(e.target.result);
};
reader.onerror = function(ex) {
console.error("err=", ex)
reject("reader.onerror");
}
reader.readAsText(file);
} catch (err) {
console.error("err=", err);
reject(err.message)
}
},
(err) => {
console.error('获取文件对象失败:', err);
reject('获取文件对象失败')
}
);
},
(err) => {
console.error('解析文件路径失败:', err);
reject('解析文件路径失败')
}
);
});
promise.then(txt => {
this.formData.txt = txt;
updateLoading(this, {
text: '读取成功'
});
}).catch(ex => {
updateLoading(this, {
text: '无法读取文档'
});
}).finally(() => {
setTimeout(() => {
hideLoading(these);
}, 500)
})
},
parseDoc(filePath) {
uni.openDocument({
filePath: filePath,
fail(err) {
these.showMsg("无法打开文档");
}
});
},
parseWord(filePath) { //读取word文件
const token = uni.getStorageSync('token');
const clientid = uni.getStorageSync('clientID');
showLoading(this, {
text: "文档读取中"
});
let promise = new Promise((resolve, reject) => {
uni.uploadFile({
url: baseURL + "/app/video/extract",
filePath: filePath,
name: 'file',
header: {
"Method": "POST",
"Content-Type": "multipart/form-data",
"Authorization": 'Bearer ' + token,
"clientid": clientid
},
timeout: 600000,
fail: (ex) => {
reject('文件无法读取,请手动复制文本内容');
},
success: (res) => {
if (res.statusCode === 200) {
res = JSON.parse(res.data);
console.log("服务器响应=", res);
if (res && res.data) {
these.formData.txt = res.data;
updateLoading(this, {
text: '读取成功'
});
resolve();
return;
}
}
reject('文件无法读取,请手动复制文本内容');
},
complete() {
setTimeout(() => {
hideLoading(these);
}, 500);
}
});
});
promise.then(res => {}).catch(ex => {
updateLoading(these, {
text: ex
});
uni.openDocument({
filePath: filePath,
fail(err) {
console.error("无法打开文件", err);
}
});
});
},
checkFile() {
this.$refs.XeUpload.upload('file');
},
toggleRecord() {
if (this.Status.recoderIntval) {
this.stopLuYin();
} else {
this.startLuYin();
}
},
playInit(tempFilePath) {
let task = (path) => {
try {
console.log("path=", path);
this.AudioData.tempFilePath = path;
this.cEdit.localPath = path;
this.cEdit.Id = Common.guid();
this.cEdit.createTime = Common.DateFormat(new Date(), "yyyy年MM月dd日");
this.cEdit.isApply = false;
this.cEdit.statu = false;
this.cEdit.type=this.Status.pageType;
this.cEdit.webPath = "";
console.log("aaaaaaaaaaaaaaaaaaa");
if(path){
this.createAudioPlayer();
}
else{
this.cEdit.time="";
}
} catch (exx) {
console.error("exx=", exx)
}
}
//将文件移动到downloads目录因为doc目录会丢失
Common.moveFileToDownloads(tempFilePath).then(res => {
console.log("文件移动成功", res);
task(res);
}).catch(ex => {
console.error("文件移动失败了", ex);
task(tempFilePath);
});
},
startLuYin() {
this.destoryAudioPlayer();
if (!AudeoRecoder) {
// #ifdef APP
try {
AudeoRecoder = uni.getRecorderManager();
AudeoRecoder.onStop(function(res) {
try {
console.log('录音停止:' + JSON.stringify(res));
these.AudioData = res;
these.cEdit.time = these.Status.RecordTime;
these.cEdit.name = "语音录制" + these.Status.RecordName;
if (these.Status.pageValid) {
these.dropTmpFile();
these.Status.pageValid = false;
AudeoRecoder = null;
} else {
these.playInit(these.AudioData.tempFilePath);
}
} catch (ex) {
console.error("ex=", ex);
}
});
} catch (ex) {
}
// #endif
}
let startTask = () => {
clearInterval(this.Status.recoderIntval);
this.Status.recoderIntval = null;
// #ifdef APP
try {
AudeoRecoder.start({
duration: 60000,
sampleRate: 44100,
format: 'wav',
frameSize: 16
});
} catch (error) {
//TODO handle the exception
}
// #endif
this.Status.RecordTime = 0;
this.Status.RecordName = Common.DateFormat(new Date(), "yyyyMMddHHmmss");
this.AudioData.tempFilePath = "";
this.Status.recoderIntval = setInterval(() => {
this.Status.RecordTime += 1;
if (this.Status.RecordTime >= 60) {
this.toggleRecord();
}
}, 1000);
this.Status.isRecord = !this.Status.isRecord;
}
if (this.AudioData.tempFilePath) {
this.showMsg("当前录音未保存,您要放弃该录音吗?", false, true, () => {
these.dropTmpFile();
startTask();
})
} else {
startTask()
}
},
stopLuYin() {
debugger;
clearInterval(this.Status.recoderIntval);
this.Status.recoderIntval = null;
try {
AudeoRecoder.stop();
} catch (ex) {
if (!these.Status.pageValid) {
these.AudioData.tempFilePath = "_doc/" + this.Status.RecordName + ".mp3"
}
} finally {
this.Status.isRecord = !this.Status.isRecord;
}
},
dropTmpFile() {
//删除丢弃的文件
// #ifdef APP
if (!these.AudioData.tempFilePath) {
return;
}
try {
plus.io.resolveLocalFileSystemURL(these.AudioData.tempFilePath, (entry) => {
// 确认是文件类型
if (entry.isFile) {
entry.remove(
() => {
console.log('文件删除成功');
// 删除成功后的逻辑
these.AudioData.tempFilePath = "";
},
(err) => {
console.error('文件删除失败:', err.message);
}
);
} else {
console.error('路径指向的不是文件');
}
}, (err) => {
console.error('路径解析失败:', err.message);
});
} catch (error) {
}
// #endif
},
closePop: function() {
this.Status.Pop.showPop = false;
if (this.Status.Pop.cancelCallback) {
this.Status.Pop.cancelCallback();
}
},
HidePop: function() {
this.Status.Pop.showPop = false;
if (this.Status.Pop.okCallback) {
this.Status.Pop.okCallback();
}
},
showPop: function(option) {
hideLoading(this);
let def = {
showPop: true, //是否显示弹窗
popType: 'custom',
bgColor: '#383934bd',
borderColor: '#BBE600',
textColor: '#ffffffde',
buttonBgColor: '#BBE600',
buttonTextColor: '#232323DE',
iconUrl: '',
message: '',
buttonText: '确定',
clickEvt: '',
visiblePrompt: false,
promptTitle: '',
modelValue: '',
visibleClose: false,
okCallback: null,
showSlot: false,
buttonCancelText: '',
showCancel: false,
}
let keys = Object.keys(def);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
if (key in option) {
continue;
}
this.Status.Pop[key] = def[key];
}
if (option) {
keys = Object.keys(option);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
this.Status.Pop[key] = option[key];
}
}
if (!option.borderColor) {
option.borderColor = '#BBE600';
option.buttonBgColor = '#BBE600';
}
these.Status.Pop.showPop = true;
},
showMsg(msg, isSucc, showCancel, okCallback) {
if (showCancel === undefined) {
showCancel = false;
}
if (okCallback === undefined) {
okCallback = null;
}
let icoUrl = '/static/images/6155/DeviceDetail/uploadErr.png';
let borderColor = "#e034344d";
let buttonBgColor = "#E03434";
if (isSucc) {
icoUrl = '/static/images/common/success.png';
borderColor = "#BBE600";
buttonBgColor = "#BBE600";
}
this.showPop({
message: msg,
iconUrl: icoUrl,
borderColor: borderColor,
buttonBgColor: buttonBgColor,
buttonText: '确定',
okCallback: okCallback,
showCancel: showCancel,
});
}
}
}
</script>
<style>
.footer .opt {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: center;
align-items: center;
justify-content: flex-start;
}
.footer .recordTitle {
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
line-height: 40rpx;
letter-spacing: 0.14rpx;
text-align: center;
}
.footer .recordName {
color: rgba(255, 255, 255, 0.6);
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
line-height: 34rpx;
letter-spacing: 0.14px;
text-align: center;
margin-bottom: 40rpx;
}
.footer .btnRecord .start {
background: rgba(224, 52, 52, 1);
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
.footer .btnRecord .start.active {
border-radius: 8rpx;
background: rgba(224, 52, 52, 1);
width: 40rpx;
height: 40rpx;
}
.footer .btnRecord {
width: 110rpx;
height: 110rpx;
box-sizing: border-box;
border: 4rpx solid rgba(255, 255, 255, 0.6);
border-radius: 50%;
}
.footer .btnRemark {
color: rgba(255, 255, 255, 0.6);
margin-top: 20rpx;
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
line-height: 40rpx;
letter-spacing: 0.14px;
text-align: center;
}
.footer {
padding-top: 60rpx;
padding-bottom: 60rpx;
width: 100%;
height: auto;
position: fixed;
z-index: 99;
left: 0rpx;
bottom: 0rpx;
border-radius: 16rpx 16rpx 0px 0px;
background: rgba(26, 26, 26, 1);
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: flex-start;
}
.popup-prompt {
width: 100%;
margin-top: 40rpx;
}
.popup-prompt-input {
width: 100%;
height: 80rpx;
line-height: 80rpx;
border: 1rpx solid #BBE60096;
border-radius: 10rpx;
padding: 0 20rpx;
margin-bottom: 30rpx;
font-size: 26rpx;
box-sizing: border-box;
text-align: left;
}
.tips {
color: rgba(255, 255, 255, 0.6);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
line-height: 40rpx;
letter-spacing: 0.14rpx;
text-align: left;
}
.polygon {
width: 300rpx;
height: 150rpx;
background-color: #3A3A3A;
border-radius: 10rpx;
color: rgba(255, 255, 255, 0.6);
;
}
.cEdit {
width: 100%;
height: auto;
border-radius: 8px;
background: rgba(26, 26, 26, 1);
box-sizing: border-box;
padding: 40rpx 30rpx
}
.btnSave {
width: 130rpx;
height: 55rpx;
line-height: 55rpx;
text-align: center;
color: rgba(23, 23, 23, 1);
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
letter-spacing: 12rpx;
background-color: #BBE600;
border-radius: 180rpx;
}
.txtName {
color: rgba(174, 214, 0, 1);
border-bottom: 1rpx solid rgba(174, 214, 0, 1);
font-family: PingFang SC;
font-size: 32rpx;
font-weight: 400;
line-height: 44rpx;
letter-spacing: 0.14px;
text-align: left;
margin-bottom: 10rpx;
}
.audioRemark {
display: flex;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: space-between;
}
.slide {
padding-top: 60rpx;
width: 100%;
position: relative;
}
.slide .line {
width: 100%;
height: 4rpx;
border-radius: 12rpx;
background: rgba(106, 106, 106, 1);
}
.slide .circle {
position: absolute;
margin-top: -4rpx;
width: 12rpx;
height: 12rpx;
background: rgba(234, 234, 234, 1);
border-radius: 50%;
}
.control {
width: 100%;
padding: 40rpx;
position: relative;
}
.control .playControl {
width: 100%;
position: absolute;
left: 0rpx;
bottom: 0rpx;
z-index: 1;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: center;
}
.control .drop {
position: absolute;
z-index: 2;
bottom: 0rpx;
right: 0rpx;
}
.playControl .seek .img {
width: 32rpx;
height: 32rpx;
}
.playControl .play .img {
width: 38rpx;
height: 44rpx;
margin: 0rpx 80rpx;
}
.input {
border-bottom: 1rpx solid #FFFFFF;
}
.placehoderClass {
color: rgba(255, 255, 255, 0.6);
font-family: PingFang SC;
font-size: 32rpx;
font-weight: 400;
line-height: 44rpx;
letter-spacing: 0.14px;
}
.text-content {
border-radius: 16rpx;
background: rgba(26, 26, 26, 1);
width: 100%;
height: auto;
box-sizing: border-box;
padding: 20rpx;
margin-bottom: 20rpx;
}
.importTxt {
color: rgba(174, 214, 0, 1);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
height: 60rpx;
line-height: 60rpx;
letter-spacing: 0.14px;
}
.textarea {
min-height: 300rpx;
width: 100%;
box-sizing: border-box;
}
.line {
width: 100%;
height: 0rpx;
border-bottom: 1rpx solid rgba(255, 255, 255, 0.36);
margin-bottom: 20rpx;
}
.footBtn {
width: 100%;
}
.footBtn .convert {
/* 组合 99 */
width: 130rpx;
height: 55rpx;
line-height: 55rpx;
border-radius: 180px;
color: #232323;
background-color: #AED600;
text-align: center;
font-family: PingFang SC;
font-size: 24rpx;
font-weight: 400;
letter-spacing: 12rpx;
}
.footBtn .audioSett,
.audioSett{
margin-right: 50rpx;
color: #FFFFFFDE;
color: rgba(255, 255, 255, 0.87);
font-family: PingFang SC;
font-size: 28rpx;
font-weight: 400;
line-height: 55rpx;
letter-spacing: 0px;
text-align: center;
}
.txtBtns{
box-sizing: border-box;
width: 100%;
padding:20rpx;
}
</style>