|
|
|
|
|
export function formatDate(date, fmt) {
|
|
|
|
|
|
const o = {
|
|
|
|
|
|
'M+': date.getMonth() + 1, // 月份
|
|
|
|
|
|
'd+': date.getDate(), // 日
|
|
|
|
|
|
'h+': date.getHours(), // 小时
|
|
|
|
|
|
'm+': date.getMinutes(), // 分
|
|
|
|
|
|
's+': date.getSeconds(), // 秒
|
|
|
|
|
|
S: date.getMilliseconds() // 毫秒
|
|
|
|
|
|
};
|
|
|
|
|
|
if (/(y+)/.test(fmt)) {
|
|
|
|
|
|
// eslint-disable-next-line no-param-reassign
|
|
|
|
|
|
fmt = fmt.replace(RegExp.$1, `${date.getFullYear()}`.substr(4 - RegExp.$1.length));
|
|
|
|
|
|
}
|
|
|
|
|
|
for (const k in o) {
|
|
|
|
|
|
if (new RegExp(`(${k})`).test(fmt)) {
|
|
|
|
|
|
// eslint-disable-next-line no-param-reassign
|
|
|
|
|
|
fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return fmt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function copyText(text) {
|
|
|
|
|
|
uni.setClipboardData({
|
|
|
|
|
|
data: text,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '复制成功',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '复制失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const removeFile = (filePath) => {
|
|
|
|
|
|
|
|
|
|
|
|
plus.io.resolveLocalFileSystemURL(
|
|
|
|
|
|
filePath,
|
|
|
|
|
|
(entry) => {
|
|
|
|
|
|
entry.remove(
|
|
|
|
|
|
() => console.log("删除成功"), // 成功回调
|
|
|
|
|
|
(error) => console.log(`删除失败:${error.message}`) // 失败回调
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
(error) => console.log(`文件不存在:${error.message}`)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const base64ToFile = (base64Strs, fileName, callback) => {
|
|
|
|
|
|
let index = base64Strs.indexOf(',');
|
|
|
|
|
|
let base64Str = base64Strs.slice(index + 1, base64Strs.length);
|
|
|
|
|
|
|
|
|
|
|
|
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) {
|
|
|
|
|
|
fs.root.getFile(fileName, {
|
|
|
|
|
|
create: true
|
|
|
|
|
|
}, function(entry) {
|
|
|
|
|
|
let fullPath = entry.fullPath;
|
|
|
|
|
|
let platform = uni.getSystemInfoSync().platform;
|
|
|
|
|
|
if (platform == 'android') {
|
|
|
|
|
|
let Base64 = plus.android.importClass("android.util.Base64");
|
|
|
|
|
|
let FileOutputStream = plus.android.importClass("java.io.FileOutputStream");
|
|
|
|
|
|
try {
|
|
|
|
|
|
let out = new FileOutputStream(fullPath);
|
|
|
|
|
|
let bytes = Base64.decode(base64Str, Base64.DEFAULT);
|
|
|
|
|
|
out.write(bytes);
|
|
|
|
|
|
out.close();
|
|
|
|
|
|
callback && callback(entry.toLocalURL());
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.log(e.message);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (platform == 'ios') {
|
|
|
|
|
|
let NSData = plus.ios.importClass('NSData');
|
|
|
|
|
|
let nsData = new NSData();
|
|
|
|
|
|
nsData = nsData.initWithBase64EncodedStringoptions(base64Str, 0);
|
|
|
|
|
|
if (nsData) {
|
|
|
|
|
|
nsData.plusCallMethod({
|
|
|
|
|
|
writeToFile: fullPath,
|
|
|
|
|
|
atomically: true
|
|
|
|
|
|
});
|
|
|
|
|
|
plus.ios.deleteObject(nsData);
|
|
|
|
|
|
}
|
|
|
|
|
|
callback && callback(entry.toLocalURL());
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function textToSpeech(text, options = {}) {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
const {
|
|
|
|
|
|
token = '24.1c8cc30b5f7be445723b6d4b19a36152.2592000.1765094496.282335-120706844',
|
|
|
|
|
|
tex = text,
|
|
|
|
|
|
cuid = 'uni-app-demo',
|
|
|
|
|
|
ctp = 1,
|
|
|
|
|
|
lan = 'zh',
|
|
|
|
|
|
spd = 5,
|
|
|
|
|
|
pit = 5,
|
|
|
|
|
|
vol = 5,
|
|
|
|
|
|
per = 0
|
|
|
|
|
|
} = options
|
|
|
|
|
|
|
|
|
|
|
|
const url = 'https://tsn.baidu.com/text2audio'
|
|
|
|
|
|
const params = {
|
|
|
|
|
|
tex: encodeURIComponent(tex),
|
|
|
|
|
|
cuid,
|
|
|
|
|
|
ctp,
|
|
|
|
|
|
lan,
|
|
|
|
|
|
spd,
|
|
|
|
|
|
pit,
|
|
|
|
|
|
vol,
|
|
|
|
|
|
per,
|
|
|
|
|
|
tok: token
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构建查询字符串
|
|
|
|
|
|
const queryString = Object.keys(params).map(key => {
|
|
|
|
|
|
return `${key}=${params[key]}`
|
|
|
|
|
|
}).join('&')
|
|
|
|
|
|
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: `${url}?${queryString}`,
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
responseType: 'arraybuffer',
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
// 检查响应状态
|
|
|
|
|
|
if (res.statusCode === 200) {
|
|
|
|
|
|
// 检查是否是音频数据(MP3格式通常以特定字节开头)
|
|
|
|
|
|
if (res.data && res.data.byteLength > 0) {
|
|
|
|
|
|
// 检查是否是JSON错误响应(百度API错误时返回JSON)
|
|
|
|
|
|
try {
|
|
|
|
|
|
const textDecoder = new TextDecoder('utf-8')
|
|
|
|
|
|
const text = textDecoder.decode(new Uint8Array(res.data.slice(0, 100)))
|
|
|
|
|
|
if (text.startsWith('{') || text.startsWith('[')) {
|
|
|
|
|
|
// 是JSON响应,说明是错误
|
|
|
|
|
|
const errorData = JSON.parse(text)
|
|
|
|
|
|
console.error('TTS API Error:', errorData)
|
|
|
|
|
|
reject(new Error(errorData.err_msg || 'TTS请求失败'))
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
// 不是JSON,应该是音频数据
|
|
|
|
|
|
}
|
|
|
|
|
|
resolve(res.data)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reject(new Error('返回数据为空'))
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reject(new Error(`请求失败,状态码: ${res.statusCode}`))
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('TTS Request Error:', err)
|
|
|
|
|
|
reject(new Error(err.errMsg || '网络请求失败'))
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|