Files
ys-app/src/utils/common.js

458 lines
15 KiB
JavaScript
Raw Normal View History

2025-08-15 11:16:08 +08:00
import { showAlert } from '@/utils/message.js'
2025-08-14 20:26:26 +08:00
2026-01-13 10:49:01 +08:00
// 验证是否有网络
export const isNetwork=()=>{
return new Promise((resolve, reject) => {
uni.getNetworkType({
success: function (res) {
resolve(res.networkType)
},fail:function(err){
reject(err)
}
});
});
}
// 打开网络设置
export const openNetworkSettings = () => {
// 根据不同平台打开网络设置
// #ifdef APP-PLUS
// App端
const platform = uni.getSystemInfoSync().platform;
if (platform === 'ios') {
// iOS打开设置页面
plus.runtime.openURL('App-Prefs:root')
} else if (platform === 'android') {
// Android打开网络设置
// 方式1使用原生API
const main = plus.android.runtimeMainActivity()
const Intent = plus.android.importClass('android.content.Intent')
const Settings = plus.android.importClass('android.provider.Settings')
const intent = new Intent(Settings.ACTION_WIFI_SETTINGS)
main.startActivity(intent)
// 方式2使用scheme某些设备可能不支持
// plus.runtime.openURL('android.settings.WIFI_SETTINGS')
}
// #endif
// #ifdef H5
// H5端无法直接跳转系统设置只能提示
uni.showToast({
title: '请手动打开网络设置',
icon: 'none'
})
// #endif
// #ifdef MP-WEIXIN
// 微信小程序无法跳转系统设置,可以引导用户检查网络
uni.showModal({
title: '提示',
content: '请检查手机网络或WiFi连接',
showCancel: false
})
// #endif
}
2025-08-13 18:15:04 +08:00
// 递归算法
2025-08-14 20:26:26 +08:00
export const initTree = (arr, parentId = '0', id) => {
2025-08-13 18:15:04 +08:00
const tree = [];
arr.filter(item => item.parentId === parentId).forEach(item => {
2025-08-14 20:26:26 +08:00
const children = initTree(arr, item[id]);
if (children.length > 0) {
item.children = children;
}
tree.push(item);
2025-08-13 18:15:04 +08:00
});
return tree;
2025-08-14 20:26:26 +08:00
}
2025-08-15 11:16:08 +08:00
2025-08-14 20:26:26 +08:00
// 安卓异步调用
2025-08-15 11:16:08 +08:00
export const requestAndroidPermissionAsync = (systemInfo, permissions) => {
2025-08-14 20:26:26 +08:00
return new Promise((resolve, reject) => {
// if (uni.getSystemInfoSync().platform !== 'android') {
// resolve({ granted: true, nonSystem: true })
// return
// }
2025-08-15 11:16:08 +08:00
plus.android.requestPermissions(permissions, (result) => {
showAlert("result=>" + JSON.stringify(result))
2025-08-14 20:26:26 +08:00
// const granted = Object.values(result.granted).every(Boolean);
let granted = false;
2025-08-15 11:16:08 +08:00
if (systemInfo.osVersion < 13) {
granted = result.granted.length == 2
} else if (systemInfo.osVersion == 13) {
granted = result.granted.length == 3
} else {
granted = result.granted.length == 1
2025-08-14 20:26:26 +08:00
}
resolve({ ...result, granted })
2025-08-15 11:16:08 +08:00
}, (error) => {
2025-08-14 20:26:26 +08:00
reject(error)
})
})
}
// 安卓同步调用
export const requestAndroidPermission = (systemInfo) => {
let granted = false;
const Manifest = plus.android.importClass("android.Manifest");
2025-08-15 11:16:08 +08:00
const MainActivity = plus.android.runtimeMainActivity();
if (systemInfo.osVersion < 13) { // 安卓系统版本
let permissionStatus = MainActivity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
2025-08-14 20:26:26 +08:00
let perStatus = 0;
if (permissionStatus === 0) {
perStatus++;
2025-08-15 11:16:08 +08:00
}
2025-08-14 20:26:26 +08:00
permissionStatus = MainActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionStatus === 0) {
perStatus++;
2025-08-15 11:16:08 +08:00
}
if (perStatus == 2) {
granted = true
} else {
granted = false //"当前文件保存权限被关闭,请到设置中开启才能继续后续操作"
2025-08-15 10:13:39 +08:00
goPermission();//调用授权方法去授权
2025-08-14 20:26:26 +08:00
}
2025-08-15 11:16:08 +08:00
} else if (systemInfo.osVersion == 13) {
let permissionStatus = MainActivity.checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES);
2025-08-14 20:26:26 +08:00
let perStatus = 0;
if (permissionStatus === 0) {
perStatus++;
2025-08-15 11:16:08 +08:00
}
2025-08-14 20:26:26 +08:00
permissionStatus = MainActivity.checkSelfPermission(Manifest.permission.READ_MEDIA_VIDEO);
if (permissionStatus === 0) {
perStatus++;
}
permissionStatus = MainActivity.checkSelfPermission(Manifest.permission.READ_MEDIA_AUDIO);
if (permissionStatus === 0) {
perStatus++;
}
2025-08-15 11:16:08 +08:00
if (perStatus == 3) {
granted = true
} else {
granted = false //"当前文件保存权限被关闭,请到设置中开启才能继续后续操作"
2025-08-15 10:13:39 +08:00
goPermission();//调用授权方法去授权
2025-08-14 20:26:26 +08:00
}
2025-08-15 11:16:08 +08:00
} else {
let permissionStatus = MainActivity.checkSelfPermission(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED);
2025-08-14 20:26:26 +08:00
let perStatus = 0;
2025-08-15 11:16:08 +08:00
if (permissionStatus === 0) {
2025-08-14 20:26:26 +08:00
perStatus++;
}
2025-08-15 11:16:08 +08:00
if (perStatus == 1) {
granted = true
} else {
granted = false //"当前文件保存权限被关闭,请到设置中开启才能继续后续操作"
2025-08-15 10:13:39 +08:00
goPermission();//调用授权方法去授权
2025-08-14 20:26:26 +08:00
}
}
2025-08-15 11:16:08 +08:00
2025-08-14 20:26:26 +08:00
return granted
2025-08-15 11:16:08 +08:00
2025-08-14 20:26:26 +08:00
}
2025-08-15 10:13:39 +08:00
// 弹窗跳授权页面
2025-08-15 11:16:08 +08:00
const goPermission = () => {
2025-08-15 10:13:39 +08:00
uni.showModal({
title: '提示',
content: "请进行设备授权",
2025-08-15 11:16:08 +08:00
cancelText: '去授权',
confirmText: '已授权',
2025-08-15 10:13:39 +08:00
success: function (res) {
if (res.confirm) {
uni.reLaunch({
url: '/pages/loading/loading',
});
} else if (res.cancel) {
jumpAuthPermission();
}
}
})
}
2025-08-18 15:50:40 +08:00
// 跳转授权按钮
const jumpAuthPermission=()=>{
2025-08-14 20:26:26 +08:00
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass('android.content.Intent');
var Uri = plus.android.importClass('android.net.Uri');
var pkg = main.getPackageName();
2025-08-18 15:50:40 +08:00
var intent = new Intent('android.settings.APPLICATION_DETAILS_SETTINGS');
intent.setData(Uri.parse('package:' + pkg));
main.startActivity(intent);
setTimeout(()=>{
uni.reLaunch({
url: '/pages/loading/loading',
});
},500)
}
// 跳转授权
const jumpAuthPermission2 = () => {
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass('android.content.Intent');
let Uri = plus.android.importClass('android.net.Uri');
let Build = plus.android.importClass('android.os.Build');
let Settings = plus.android.importClass('android.provider.Settings');
let PackageManager = plus.android.importClass('android.content.pm.PackageManager');
let pkg = main.getPackageName();
2025-08-18 11:32:35 +08:00
2025-08-18 15:50:40 +08:00
let intent = new Intent();
2025-08-18 11:32:35 +08:00
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
2025-08-18 15:50:40 +08:00
showAlert(Build.VERSION.SDK_INT)
2025-08-18 11:32:35 +08:00
// 尝试直接跳转到存储权限设置Android 13+ 支持)
if (Build.VERSION.SDK_INT >= 33) {
// Android 13+ 尝试直接打开存储权限页面
intent.setAction(Settings.ACTION_MANAGE_APP_PERMISSIONS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, pkg);
// 指定权限类型为存储需要Android 13+支持)
intent.putExtra(Settings.EXTRA_PERMISSION_NAME, "android.permission.READ_EXTERNAL_STORAGE");
}
// Android 11-12 尝试直接跳转到权限列表
else if (Build.VERSION.SDK_INT >= 30) {
intent.setAction(Settings.ACTION_MANAGE_APP_PERMISSIONS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, pkg);
2025-08-18 15:50:40 +08:00
2025-08-18 11:32:35 +08:00
}
// Android 6.0-10 跳转到应用详情页(用户需手动点击权限)
else if (Build.VERSION.SDK_INT >= 23) {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
2025-08-18 15:50:40 +08:00
let uri = Uri.fromParts("package", pkg, null);
2025-08-18 11:32:35 +08:00
intent.setData(uri);
}
// 低版本系统
else {
intent.setAction(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
}
2025-08-18 15:50:40 +08:00
showAlert("main=>"+main)
showAlert("intent=>"+intent)
2025-08-18 11:32:35 +08:00
main.startActivity(intent);
setTimeout(() => {
uni.reLaunch({
url: '/pages/loading/loading',
});
}, 1000)
} catch (e) {
2025-08-18 15:50:40 +08:00
showAlert(e)
2025-08-18 11:32:35 +08:00
// 异常情况下降级处理
console.error("跳转存储权限页面失败,使用备用方案", e);
2025-08-18 15:50:40 +08:00
let fallbackIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
2025-08-18 11:32:35 +08:00
fallbackIntent.setData(Uri.parse('package:' + pkg));
fallbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
main.startActivity(fallbackIntent);
setTimeout(() => {
uni.reLaunch({
url: '/pages/loading/loading',
});
}, 1000)
}
2025-08-14 20:26:26 +08:00
}
2025-11-20 17:45:41 +08:00
// 判断文件是图片还是视频
export const getFileType = (filePathOrName) => {
// 从路径或文件名中提取扩展名
let suffix = '';
try {
suffix = filePathOrName.split('.').pop().toLowerCase();
} catch (err) {
return 'unknown';
}
// 定义常见的图片和视频扩展名
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
const videoExtensions = ['mp4', 'mov', 'avi', 'm4v', '3gp', 'mpeg', 'mkv', 'wmv'];
if (imageExtensions.includes(suffix)) {
return 'image';
} else if (videoExtensions.includes(suffix)) {
return 'video';
} else {
return 'other';
}
2025-11-27 18:18:19 +08:00
}
// 计算图片的新尺寸
const calculateNewSize = (originalWidth, originalHeight)=>{
const MAX_SIZE = 1920;
let newWidth = originalWidth;
let newHeight = originalHeight;
// 如果宽或高超过最大尺寸,进行等比缩放
if (originalWidth > MAX_SIZE || originalHeight > MAX_SIZE) {
if (originalWidth > originalHeight) {
// 宽图
newWidth = MAX_SIZE;
newHeight = Math.round((originalHeight * MAX_SIZE) / originalWidth);
} else {
// 高图或方图
newHeight = MAX_SIZE;
newWidth = Math.round((originalWidth * MAX_SIZE) / originalHeight);
}
}
// console.log('调整后尺寸:', newWidth, 'x', newHeight);
return {
width: newWidth,
height: newHeight
};
}
// 图片压缩处理tempFilePaths
export const compressImageUni = (file) => {
return new Promise((resolve, reject) => {
try {
console.log("compressImageUni=>file=>",file)
uni.getImageInfo({
src: file,
success: function (image) {
const newSize = calculateNewSize(image.width, image.height);
console.log("调整后的尺寸=>",newSize)
uni.compressImage({
src: file,
compressedWidth:newSize.width,
compressedHeight:newSize.height,
quality: 100, // 压缩质量 (0-100)
success: (res) => {
// console.log('压缩成功,临时路径:', res.tempFilePath);
resolve(res.tempFilePath)
},
fail: (err) => {
console.log('压缩失败:', err);
reject(err)
}
});
}
});
} catch (error) {
console.log('压缩失败:', error);
}
})
2025-12-19 16:54:02 +08:00
}
// H5 获取视频第一帧
const getFirstFrameInH5 = (videoPath) => {
return new Promise((resolve, reject) => {
const video = document.createElement('video')
video.src = videoPath
video.crossOrigin = 'anonymous'
video.addEventListener('loadeddata', () => {
video.currentTime = 0.1
})
video.addEventListener('seeked', () => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
const dataUrl = canvas.toDataURL('image/jpeg', 0.8)
resolve(dataUrl)
})
video.addEventListener('error', reject)
})
}
// App平台获取第一帧Android/iOS
const getFirstFrameInApp = (videoPath) => {
return new Promise((resolve, reject) => {
// 方法1使用原生VideoPlayer推荐
// #ifdef APP-PLUS
try {
const videoPlayer = plus.video.createVideoPlayer('firstFramePlayer', {
src: videoPath,
autoplay: false,
controls: false,
showLoading: false,
showProgress: false
})
// 监听视频准备完成
videoPlayer.addEventListener('loadeddata', () => {
// 截图
videoPlayer.snapshot({
format: 'jpg',
quality: 80
}, (res) => {
// res.target 是图片临时路径
console.log('截图成功:', res)
resolve(res.target)
// 销毁播放器
videoPlayer.close()
}, (error) => {
console.error('截图失败:', error)
reject(error)
videoPlayer.close()
})
}, false)
videoPlayer.addEventListener('error', (error) => {
console.error('视频加载失败:', error)
reject(error)
videoPlayer.close()
})
} catch (error) {
console.error('创建VideoPlayer失败:', error)
// 方法2备用方案使用HTML5 video如果原生方法失败
// showAppVideo.value = true
// showAppCanvas.value = true
// // 等待DOM更新后获取元素
// setTimeout(() => {
// const video = document.getElementById('appVideo')
// const canvas = document.getElementById('appCanvas')
// const ctx = canvas.getContext('2d')
// video.onloadedmetadata = () => {
// canvas.width = video.videoWidth
// canvas.height = video.videoHeight
// video.onseeked = () => {
// ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
// const dataUrl = canvas.toDataURL('image/jpeg', 0.8)
// // 清理
// showAppVideo.value = false
// showAppCanvas.value = false
// resolve(dataUrl)
// }
// video.currentTime = 0.1
// }
// video.onerror = reject
// }, 100)
}
// #endif
})
}
// 获取视频第一帧(跨平台处理)
export const getVideoFirstFrame = (videoPath) => {
return new Promise((resolve, reject) => {
// #ifdef H5
// H5平台使用canvas
getFirstFrameInH5(videoPath).then(resolve).catch(reject)
// #endif
// #ifdef APP-PLUS
// App平台使用plus.video
getFirstFrameInApp(videoPath).then(resolve).catch(reject)
// #endif
})
2025-11-27 18:18:19 +08:00
}