1
0
forked from dyf/APP
Files
APP/pages/100J/audioManager/Recording.vue

1458 lines
37 KiB
Vue
Raw Permalink Normal View History

2026-02-03 18:55:48 +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 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, //已录间的时长
ID: '',
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;
console.log('id:', opt.id); // 输出123
these.Status.ID = opt.id
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) {
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/ttsToOss",
method: 'post',
data: {
deviceId: these.Status.ID,
text: this.formData.txt
}
}).then(res => {
if (res && res.code && res.code === 200) {
succ(res.data);
console.log('这是成功了吗');
uni.navigateBack()
} else {
err(res);
}
}).catch(ex => {
console.error("出现异常", ex);
err(res);
});
})
}
task().then(res => {
try {
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() {
// 文件类型验证
if (!this.AudioData.tempFilePath) {
this.showMsg("请先录制或选择音频文件");
return;
}
// 检查文件扩展名
const validExtensions = ['.mp3', '.wav', '.aac', '.m4a'];
let uploadFilePath = this.AudioData.tempFilePath;
const hasValidExtension = validExtensions.some(ext =>
uploadFilePath.toLowerCase().endsWith(ext)
);
if (!hasValidExtension) {
// 如果没有有效扩展名,添加.mp3扩展名
uploadFilePath = uploadFilePath + '.mp3';
console.log("自动添加.mp3扩展名新路径:", uploadFilePath);
}
console.log("上传文件路径:", uploadFilePath);
plus.io.resolveLocalFileSystemURL(uploadFilePath, (entry) => {
entry.getMetadata((metadata) => {
console.log("文件大小:", metadata.size, "字节");
console.log("文件类型验证通过");
this.doUpload(uploadFilePath);
}, (err) => {
console.error("获取文件元数据失败:", err);
this.doUpload(this.AudioData.tempFilePath);
});
}, (err) => {
console.error("文件不存在或路径错误:", err);
this.doUpload(this.AudioData.tempFilePath);
});
},
// 执行上传操作
doUpload(filePath) {
const key = `${Common.pcmStorageKey}_${this.cEdit.Id}`;
const store = uni.getStorageInfoSync();
if (store.keys.includes(key)) return;
const token = uni.getStorageSync('token');
const clientid = uni.getStorageSync('clientID');
const these = this;
showLoading(this, {
text: "文件上传中"
});
console.log("最终上传文件路径:", filePath);
uni.uploadFile({
url: baseURL + "/app/video/uploadAudioToOss",
filePath: filePath,
name: 'file',
header: {
"Authorization": `Bearer ${token}`,
"clientid": clientid
},
formData: {
deviceId: these.Status.ID
},
success: (res) => {
try {
if (!res.data) {
throw new Error('res.data is empty');
}
const resData = JSON.parse(res.data);
if (resData.code === 200) {
// 合并两个存储操作
Promise.all([
new Promise((resolve, reject) => {
uni.setStorage({
key,
data: resData.data,
success: resolve,
fail: reject
});
}),
new Promise((resolve, reject) => {
let array = uni.getStorageSync(Common.audioStorageKey) ||
[];
array.unshift(these.cEdit);
uni.setStorage({
key: Common.audioStorageKey,
data: array,
success: resolve,
fail: reject
});
})
]).then(() => {
updateLoading(these, {
text: "操作成功"
});
these.AudioData.tempFilePath = "";
these.Status.isRecord = false;
uni.navigateBack();
}).catch(ex => {
updateLoading(these, {
text: `出现异常${JSON.stringify(ex)}`
});
these.timeOutCloseLoad();
});
return;
} else {
console.log('上传失败:', resData.msg);
uni.showToast({
title: resData.msg,
icon: 'none',
duration: 3000
});
these.timeOutCloseLoad();
}
} catch (error) {
uni.showToast({
title: '服务器响应格式错误',
icon: 'none',
duration: 3000
});
these.timeOutCloseLoad();
}
},
fail: (err) => {
console.error('上传文件失败:', err);
uni.showToast({
title: '上传失败,请检查网络',
icon: 'none',
duration: 3000
});
these.timeOutCloseLoad();
},
complete: () => {
console.log('上传操作完成');
}
});
},
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);
// 确保路径有.mp3扩展名
if (path && !path.toLowerCase().endsWith('.mp3')) {
path = path + '.mp3';
console.log("播放路径已添加.mp3扩展名:", 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 = "";
if (path) {
this.createAudioPlayer();
} else {
this.cEdit.time = "";
}
} catch (exx) {
console.error("playInit错误:", exx)
}
}
if (tempFilePath) {
Common.moveFileToDownloads(tempFilePath).then(res => {
console.log("文件移动成功", res);
task(res);
}).catch(ex => {
console.error("文件移动失败了", ex);
task(tempFilePath);
});
} else {
task("");
}
},
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);
}
});
} catch (ex) {
console.error("获取录音管理器错误:", ex);
}
// #endif
}
let startTask = () => {
clearInterval(this.Status.recoderIntval);
this.Status.recoderIntval = null;
// #ifdef APP
try {
AudeoRecoder.start({
duration: 60000,
sampleRate: 44100,
format: 'mp3', // 确保这里是mp3格式
frameSize: 16,
encodeBitRate: 192000,
numberOfChannels: 1
});
} catch (error) {
console.error("开始录音错误:", error);
}
// #endif
this.Status.RecordTime = 0;
// 确保录音文件名包含.mp3扩展名
this.Status.RecordName = Common.DateFormat(new Date(), "yyyyMMddHHmmss") + ".mp3";
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() {
clearInterval(this.Status.recoderIntval);
this.Status.recoderIntval = null;
try {
AudeoRecoder.stop();
} catch (ex) {
console.error("停止录音错误:", ex);
if (!these.Status.pageValid) {
these.AudioData.tempFilePath = "_doc/" + this.Status.RecordName;
}
} 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) {
console.error("删除文件异常:", 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>