jeecgBootUniapp/src/utils/index.ts
2025-05-29 18:25:16 +08:00

448 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { pages, subPackages, tabBar } from '@/pages.json'
import { isMpWeixin } from './platform'
import { useAppStore } from '@/store'
const getLastPage = () => {
// getCurrentPages() 至少有1个元素所以不再额外判断
// const lastPage = getCurrentPages().at(-1)
// 上面那个在低版本安卓中打包回报错所以改用下面这个【虽然我加了src/interceptions/prototype.ts但依然报错】
const pages = getCurrentPages()
return pages[pages.length - 1]
}
/** 判断当前页面是否是tabbar页 */
export const getIsTabbar = () => {
if (!tabBar) {
return false
}
if (!tabBar.list.length) {
// 通常有tabBar的话list不能有空且至少有2个元素这里其实不用处理
return false
}
const lastPage = getLastPage()
const currPath = lastPage.route
return !!tabBar.list.find((e) => e.pagePath === currPath)
}
/**
* 获取当前页面路由的 path 路径和 redirectPath 路径
* path 如 /pages/login/index
* redirectPath 如 /pages/demo/base/route-interceptor
*/
export const currRoute = () => {
const lastPage = getLastPage()
const currRoute = (lastPage as any).$page
// 经过多端测试,只有 fullPath 靠谱,其他都不靠谱
const { fullPath } = currRoute as { fullPath : string }
// eg: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor (小程序)
// eg: /pages/login/index?redirect=%2Fpages%2Froute-interceptor%2Findex%3Fname%3Dfeige%26age%3D30(h5)
return getUrlObj(fullPath)
}
const ensureDecodeURIComponent = (url : string) => {
if (url.startsWith('%')) {
return ensureDecodeURIComponent(decodeURIComponent(url))
}
return url
}
/**
* 解析 url 得到 path 和 query
* 比如输入url: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor
* 输出: {path: /pages/login/index, query: {redirect: /pages/demo/base/route-interceptor}}
*/
export const getUrlObj = (url : string) => {
const [path, queryStr] = url.split('?')
if (!queryStr) {
return {
path,
query: {},
}
}
const query : Record<string, string> = {}
queryStr.split('&').forEach((item) => {
const [key, value] = item.split('=')
query[key] = ensureDecodeURIComponent(value) // 这里需要统一 decodeURIComponent 一下可以兼容h5和微信y
})
return { path, query }
}
/**
* 得到所有的需要登录的pages包括主包和分包的
* 这里设计得通用一点可以传递key作为判断依据默认是 needLogin, 与 route-block 配对使用
* 如果没有传 key则表示所有的pages如果传递了 key, 则表示通过 key 过滤
*/
export const getAllPages = (key = 'needLogin') => {
// 这里处理主包
const mainPages = [
...pages
.filter((page) => !key || page[key])
.map((page) => ({
...page,
path: `/${page.path}`,
})),
]
// 这里处理分包
const subPages : any[] = []
subPackages.forEach((subPageObj) => {
const { root } = subPageObj
subPageObj.pages
.filter((page) => !key || page[key])
.forEach((page : { path : string } & Record<string, any>) => {
subPages.push({
...page,
path: `/${root}/${page.path}`,
})
})
})
const result = [...mainPages, ...subPages]
return result
}
/**
* 得到所有的需要登录的pages包括主包和分包的
* 只得到 path 数组
*/
export const getNeedLoginPages = () : string[] => getAllPages('needLogin').map((page) => page.path)
/**
* 得到所有的需要登录的pages包括主包和分包的
* 只得到 path 数组
*/
export const needLoginPages : string[] = getAllPages('needLogin').map((page) => page.path)
/**
* 根据微信小程序当前环境判断应该获取的BaseUrl
*/
export const getEnvBaseUrl = () => {
// 请求基准地址
let baseUrl = import.meta.env.VITE_SERVER_BASEURL
// 微信小程序端环境区分
if (isMpWeixin) {
const {
miniProgram: { envVersion },
} = uni.getAccountInfoSync()
switch (envVersion) {
case 'develop':
baseUrl = import.meta.env.VITE_SERVER_BASEURL__WEIXIN_DEVELOP || baseUrl
break
case 'trial':
baseUrl = import.meta.env.VITE_SERVER_BASEURL__WEIXIN_TRIAL || baseUrl
break
case 'release':
baseUrl = import.meta.env.VITE_SERVER_BASEURL__WEIXIN_RELEASE || baseUrl
break
}
}
return baseUrl
}
/**
* 根据微信小程序当前环境判断应该获取的UPLOAD_BASEURL
*/
export const getEnvBaseUploadUrl = () => {
// 请求基准地址
let baseUploadUrl = import.meta.env.VITE_UPLOAD_BASEURL
// 微信小程序端环境区分
if (isMpWeixin) {
const {
miniProgram: { envVersion },
} = uni.getAccountInfoSync()
switch (envVersion) {
case 'develop':
baseUploadUrl = import.meta.env.VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP || baseUploadUrl
break
case 'trial':
baseUploadUrl = import.meta.env.VITE_UPLOAD_BASEURL__WEIXIN_TRIAL || baseUploadUrl
break
case 'release':
baseUploadUrl = import.meta.env.VITE_UPLOAD_BASEURL__WEIXIN_RELEASE || baseUploadUrl
break
}
}
return baseUploadUrl
}
/**
* 时间格式化
* @param value
* @param fmt
* @returns {*}
*/
export function formatDate(value, fmt) {
var regPos = /^\d+(\.\d+)?$/;
if (regPos.test(value)) {
//如果是数字
let getDate = new Date(value);
let o = {
'M+': getDate.getMonth() + 1,
'd+': getDate.getDate(),
'h+': getDate.getHours(),
'H+': getDate.getHours(),
'm+': getDate.getMinutes(),
's+': getDate.getSeconds(),
'q+': Math.floor((getDate.getMonth() + 3) / 3),
'S': getDate.getMilliseconds()
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (getDate.getFullYear() + '').substr(4 - RegExp.$1.length))
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
}
}
return fmt;
} else {
//TODO
if (value && value.length > 0) {
value = value.trim();
return value.substr(0, fmt.length);
}
return value
}
}
/**
* 判断是否有新版本
* @param version 接口返回的版本号
* @param isWgt 是否是热资源更新 默认不是
*/
export const hasNewVersion = (version, isWgt = false) => {
// #ifdef APP_PLUS
return new Promise((resolve) => {
const transfer = (str) => {
const parts = str.split('.').map(part => part.padStart(4, '0'))
return parts.join('')
}
if (isWgt) {
plus.runtime.getProperty(plus.runtime.appid, (widgetInfo) => {
const currentVersion = widgetInfo.version
resolve(+transfer(version) > +transfer(currentVersion))
})
} else {
const currentVersion = plus.runtime.version
resolve(+transfer(version) > +transfer(currentVersion))
}
})
// #endif
}
export function onClickUpdate(updateType : string, url) {
// #ifdef APP-PLUS
if (updateType != 'wgt') plus.runtime.openURL(url.apkUrl)
else downloadApp(url.wgtUrl)
// #endif
}
function downloadApp(url : string) {
var dtask = plus.downloader.createDownload(url, {
filename: `_downloads/wgt-${Date.now()}.wgt` //利用保存路径,实现下载文件的重命名
}, function (d, status) {
//d为下载的文件对象
if (status == 200) {
//下载成功,d.filename是文件在保存在本地的相对路径使用下面的API可转为平台绝对路径
var fileSaveUrl = plus.io.convertLocalFileSystemURL(d.filename);
installApp(fileSaveUrl)
} else {
//下载失败
plus.downloader.clear(); //清除下载任务
uni.showToast({
title: 'App下载失败',
icon: 'error'
})
}
})
let prg = 0
let showLoading = plus.nativeUI.showWaiting('正在下載')
dtask.start()
dtask.addEventListener('statechanged', (task) => {
// 给下载任务设置一个监听 并根据状态 做操作
switch (task.state) {
case 1:
showLoading.setTitle("正在下载")
break
case 2:
showLoading.setTitle("已连接到服务器")
break
case 3: {
const downloaded = +task.downloadedSize; // 转为数字
const total = +task.totalSize; // 转为数字
prg = total > 0 ? Math.floor((downloaded / total) * 100) : 0;
showLoading.setTitle(`正在下载 ${prg}%`);
break;
}
case 4:
plus.nativeUI.closeWaiting()
//下载完成
break
}
})
}
function installApp(tempFilePath : string) {
// #ifdef APP-PLUS
plus.runtime.install(
tempFilePath, {
force: true
},
() => {
uni.showModal({
title: '更新',
content: '更新成功,请点击确认后重启',
showCancel: false,
success(res) {
if (res.confirm) {
plus.runtime.restart()
}
}
})
},
() =>
uni.showToast({
title: '安装失败!',
icon: 'error'
})
)
// #endif
}
/**
* 定位
*/
export const getLocation = () => {
const store = useAppStore()
// 先尝试获取位置,失败时再回退
uni.getLocation({
type: 'wgs84',
success: function (position) {
// 成功获取位置后请求地理编码
uni.request({
url: 'http://api.tianditu.gov.cn/geocoder',
method: 'GET',
data: {
postStr: JSON.stringify({
lon: position.longitude,
lat: position.latitude,
ver: 1
}),
type: 'geocode',
tk: '30fe0f0c1b2320e112bde797f3ddaff4'
},
success: function (res : any) {
let data = res.data;
if (data.status == 0) {
const obj = data.result.addressComponent
store.setPosition(obj.city ? obj.city : obj.province) //市
store.setLocation(obj.city ? obj.province + obj.city + obj.county : obj.province + obj.county) //省市区
getWeather(position.latitude, position.longitude)
} else {
handleDefaultLocation()
}
},
fail: function (err) {
// uni.showToast({
// title: '位置解析失败',
// icon: 'error'
// })
handleDefaultLocation()
}
});
},
fail: function (err) {
// 根据不同错误码处理
// if (err.errCode === 2 || err.errCode === 12) {
// // 2: 位置服务不可用, 12: 定位权限未开启
// uni.showToast({
// title: '请开启定位服务',
// icon: 'error'
// })
// } else {
// uni.showToast({
// title: '定位获取失败',
// icon: 'error'
// })
// }
handleDefaultLocation()
}
});
}
const getWeather = (lat : number, lon : number) => {
let params = {
lat: lat,
lon: lon
}
weatherRequest(params)
}
// 处理默认位置和天气
function handleDefaultLocation() {
useAppStore().setPosition('濮阳市')
weatherRequest({
q: '濮阳市'
})
}
function weatherRequest(params : { lat ?: number; lon ?: number; q ?: string }) {
const store = useAppStore()
uni.request({
url: 'http://api.openweathermap.org/data/2.5/weather',
method: 'GET',
data: {
...params,
appid: '600a60694b0e453dfbaafa862f1d1482',
lang: 'zh_cn'
},
success: function (res : any) {
if (res.data && res.data.main && res.data.weather) {
store.setTemperature(
Math.round(res.data.main.temp - 273.15)
)
store.setWeather(
res.data.weather[0].icon
)
} else {
// uni.showToast({
// title: '天气数据格式错误',
// icon: 'error'
// })
}
},
// fail: function () {
// uni.showToast({
// title: '天气获取失败',
// icon: 'error'
// })
// }
});
}
export const imgUrl = (url : string) => {
return getEnvBaseUrl() + '/sys/common/static/' + `/${url}`
}
/**
* 获取文件服务访问路径
* @param avatar
* @param subStr
* @returns {*}
*/
export function getFileAccessHttpUrl(avatar, subStr) {
if (!subStr) subStr = 'http'
if (avatar && avatar.startsWith(subStr)) {
return avatar;
} else {
if (avatar && avatar.length > 0 && avatar.indexOf('[') == -1) {
return getEnvBaseUrl() + "/sys/common/static/" + avatar;
}
}
}