全栈小学生 3fe60374bc up
2025-04-19 10:41:41 +08:00

717 lines
21 KiB
TypeScript
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 { getTabbarPages } from './pages'
import useDiyStore from '@/app/stores/diy'
import useMemberStore from '@/stores/member'
import useSystemStore from '@/stores/system'
import useConfigStore from '@/stores/config'
import { getNeedLoginPages } from '@/utils/pages'
/**
* 跳转页面
*/
export const redirect = (redirect: any) => {
// 装修模式禁止跳转
if (useDiyStore().mode == 'decorate') return
let { url, mode, param, success, fail, complete } = redirect
let originalUrl = url; // 原始地址
let newLogin = false; // 是否需要登录
// 如果未开启普通账号登录注册,则不展示登录注册页面,如果只开启了账号密码登录,就不需要跳转到登录中间页了,直接进入普通账号密码登录页面
if (!getToken() && getNeedLoginPages().indexOf(url) != -1) {
const config = useConfigStore()
const systemStore = useSystemStore()
// #ifdef MP-WEIXIN
if (config.login.is_username && !config.login.is_mobile && !config.login.is_auth_register) {
url = '/app/pages/auth/login'
param = { type: 'username' }
mode = 'redirectTo'
newLogin = true
} else if (systemStore.initStatus == 'finish' && !config.login.is_username && !config.login.is_mobile && !config.login.is_auth_register) {
uni.showToast({ title: '商家未开启登录注册', icon: 'none' })
return;
} else {
url = '/app/pages/auth/index'
mode = 'redirectTo'
newLogin = true
}
// #endif
// #ifdef H5
if (isWeixinBrowser()) {
// 微信浏览器
if (config.login.is_username && !config.login.is_mobile && !config.login.is_auth_register) {
url = '/app/pages/auth/login'
param = { type: 'username' }
mode = 'redirectTo'
newLogin = true
} else if (systemStore.initStatus == 'finish' && !config.login.is_username && !config.login.is_mobile && !config.login.is_auth_register) {
uni.showToast({ title: '商家未开启登录注册', icon: 'none' })
return;
} else {
url = '/app/pages/auth/index'
mode = 'redirectTo'
newLogin = true
}
} else {
// 普通浏览器
if (config.login.is_username && !config.login.is_mobile) {
url = '/app/pages/auth/login'
param = { type: 'username' }
mode = 'redirectTo'
newLogin = true
} else if (systemStore.initStatus == 'finish' && !config.login.is_username && !config.login.is_mobile) {
uni.showToast({ title: '商家未开启登录注册', icon: 'none' })
return;
} else {
url = '/app/pages/auth/index'
mode = 'redirectTo'
newLogin = true
}
}
// #endif
}
mode = mode || 'navigateTo'
const tabBar = getTabbarPages()
tabBar.includes(url) && (mode = 'switchTab')
mode != 'switchTab' && param && Object.keys(param).length && (url += uni.$u.queryParams(param))
if (newLogin) {
uni.setStorage({ key: 'loginBack', data: { url: originalUrl } });
}
switch (mode) {
case 'switchTab':
uni.switchTab({
url,
success: () => {
success && success()
},
fail: () => {
fail && fail()
},
complete: () => {
complete && complete()
}
})
break;
case 'navigateTo':
uni.navigateTo({
url,
success: () => {
success && success()
},
fail: () => {
fail && fail()
},
complete: () => {
complete && complete()
}
})
break;
case 'reLaunch':
uni.reLaunch({
url,
success: () => {
success && success()
},
fail: () => {
fail && fail()
},
complete: () => {
complete && complete()
}
})
break;
case 'redirectTo':
uni.redirectTo({
url,
success: () => {
success && success()
},
fail: () => {
fail && fail()
},
complete: () => {
complete && complete()
}
})
break;
}
}
/**
* 自定义跳转链接
* @param {Object} link
*/
export const diyRedirect = (link: any) => {
const diyStore = useDiyStore();
// 装修模式禁止跳转
if (diyStore.mode == 'decorate') return;
if (link == null || Object.keys(link).length == 1) return;
// 外部链接
if (link.url && (link.url.indexOf('https') != -1 || link.url.indexOf('http') != -1)) {
// #ifdef H5
window.location.href = link.url;
// #endif
// #ifdef MP
redirect({
url: '/app/pages/webview/index',
param: { src: encodeURIComponent(link.url) }
});
// #endif
} else if (link.appid) {
// 跳转其他小程序
// #ifdef MP
uni.navigateToMiniProgram({
appId: link.appid,
path: link.page
})
// #endif
} else if (link.name == 'DIY_MAKE_PHONE_CALL' && link.mobile) {
// 拨打电话
uni.makePhoneCall({
phoneNumber: link.mobile,
success: (res) => {
},
fail: (res) => {
}
});
} else {
redirect({ url: link.url });
}
}
/**
* 获取当前路由
*/
export const currRoute = () => {
const pages = getCurrentPages()
const route = pages[pages.length - 1]
return route ? route.route : ''
}
// 获取分享路由
export const currShareRoute = () => {
const pages: any = getCurrentPages()
if (pages.length == 0) {
return {
path: '/',
params: {}
}
}
let currentRoute = pages[pages.length - 1].route //获取当前页面路由
// #ifdef H5
let currentParam: any = pages[pages.length - 1].$page.options; //获取路由参数
// #endif
// #ifdef MP
let currentParam: any = pages[pages.length - 1].options || {}; //获取路由参数
// #endif
// 拼接参数
let params: any = {};
for (let key in currentParam) {
params[key] = currentParam[key]
}
let currentPath = '/' + currentRoute;
return {
path: currentPath,
params
}
}
/**
* 获取token
* @returns
*/
export function getToken(): null | string {
return useMemberStore().token
}
/**
* 设置token
* @param token
* @returns
*/
export function setToken(token: string): void {
uni.setStorageSync(import.meta.env.VITE_REQUEST_STORAGE_TOKEN_KEY, token)
}
/**
* 移除token
* @returns
*/
export function removeToken(): void {
uni.removeStorageSync(import.meta.env.VITE_REQUEST_STORAGE_TOKEN_KEY)
}
/**
* 将url 解构为 { path: ***, query: {} }
*/
export function urlDeconstruction(url: string) {
const query: any = {}
const [path, param] = url.split('?')
param && param.split('&').forEach((str: string) => {
let [name, value] = str.split('=')
query[name] = value
})
return { path, query }
}
/**
* 判断是否是url
* @param str
* @returns
*/
export function isUrl(str: string): boolean {
return str && (str.indexOf('http://') != -1 || str.indexOf('https://') != -1) || false
}
/**
* 图片输出
* @param path
* @returns
*/
export function img(path: string): string {
// #ifdef H5
let imgDomain = import.meta.env.VITE_IMG_DOMAIN || location.origin
// #endif
// #ifndef H5
let imgDomain = import.meta.env.VITE_IMG_DOMAIN
// #endif
if (typeof path == 'string' && path.startsWith('/')) path = path.replace(/^\//, '')
if (typeof imgDomain == 'string' && imgDomain.endsWith('/')) imgDomain = imgDomain.slice(0, -1)
return isUrl(path) ? path : `${imgDomain}/${path}`
}
/**
* 手机号隐藏
*/
export function mobileHide(mobile: string) {
return mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
/**
* 判断是否是微信浏览器
*/
export function isWeixinBrowser(): boolean {
// #ifndef H5
return false
// #endif
let ua = navigator.userAgent.toLowerCase()
return /micromessenger/.test(ua) ? true : false
}
/**
* 获取应用场景值
*/
export function getAppChannel(): string {
// #ifdef APP-PLUS
return 'app'
// #endif
// #ifdef MP-WEIXIN
return 'weapp'
// #endif
// #ifdef H5
return isWeixinBrowser() ? 'wechat' : 'h5'
// #endif
}
/**
* 金额格式化
*/
export function moneyFormat(money: string): string {
return isNaN(parseFloat(money)) ? money : parseFloat(money).toFixed(2)
}
/**
* 手机号隐藏
*/
export function mobileConceal(mobile: string): string {
return mobile.substring(0, 3) + "****" + mobile.substr(mobile.length - 4);
}
/**
* 获取站点id
*/
export function getSiteId(siteId: number | string) {
// #ifdef H5
const match = location.href.match(/\/wap\/(\d*)\//);
match && (siteId = match[1])
// #endif
// #ifdef MP-WEIXIN
if (uni.getExtConfigSync) {
const extConfig = uni.getExtConfigSync()
extConfig.site_id && (siteId = extConfig.site_id)
}
// #endif
return siteId
}
/**
* 时间戳转日期格式
* @param timeStamp
* @param type
*/
export function timeStampTurnTime(timeStamp: any, type = "") {
if (timeStamp != undefined && timeStamp != "" && timeStamp > 0) {
var date = new Date();
date.setTime(timeStamp * 1000);
var y = date.getFullYear();
var m: any = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var d: any = date.getDate();
d = d < 10 ? ('0' + d) : d;
var h: any = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute: any = date.getMinutes();
var second: any = date.getSeconds();
minute = minute < 10 ? ('0' + minute) : minute;
second = second < 10 ? ('0' + second) : second;
if (type) {
if (type == 'yearMonthDay') {
return y + '年' + m + '月' + d + '日';
}
return y + '-' + m + '-' + d;
} else {
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
}
} else {
return "";
}
}
/**
* 日期格式转时间戳
* @param {Object} date
*/
export function timeTurnTimeStamp(dateStr: string) {
let timestamp;
let date;
// 尝试解析 'YYYY年M月D日'
try {
let dateStr1 = dateStr.replace('年', '-').replace('月', '-').replace('日', '');
date = new Date(dateStr1);
timestamp = date.getTime();
} catch (e) {
// 尝试解析 'YYYY-MM-DD'
try {
date = new Date(dateStr);
timestamp = date.getTime();
} catch (e) {
// 尝试解析 'YYYY/MM/DD'
try {
date = new Date(dateStr.replace(/\//g, "-"));
timestamp = date.getTime();
} catch (e) {
// 尝试解析 'YYYY年M月D日 HH时mm分'
try {
let dateStr1 = dateStr.replace('年', '-').replace('月', '-').replace('日', ' ').replace('时', ':').replace('分', '');
date = new Date(dateStr1);
timestamp = date.getTime();
} catch (e) {
// 尝试解析 'YYYY-MM-DD HH:mm'
try {
date = new Date(dateStr);
timestamp = date.getTime();
} catch (e) {
// 尝试解析 'YYYY/MM/DD HH:mm'
try {
date = new Date(dateStr.replace(/\//g, "-"));
timestamp = date.getTime();
} catch (e) {
// 如果所有格式都失败返回null
console.error("无法解析日期字符串:", dateStr);
return null;
}
}
}
}
}
}
return (timestamp / 1000);
}
/**
* 复制
* @param {Object} value
* @param {Object} callback
*/
export function copy(value: any, callback: any) {
// #ifdef H5
var oInput = document.createElement('input'); //创建一个隐藏input重要
oInput.value = value; //赋值
oInput.setAttribute("readonly", "readonly");
document.body.appendChild(oInput);
oInput.select(); // 选择对象
document.execCommand("Copy"); // 执行浏览器复制命令
oInput.className = 'oInput';
oInput.style.display = 'none';
uni.hideKeyboard();
uni.showToast({
title: '复制成功',
icon: 'none'
});
typeof callback == 'function' && callback();
// #endif
// #ifdef MP || APP-PLUS
uni.setClipboardData({
data: value,
success: () => {
typeof callback == 'function' && callback();
},
fail: (res) => {
// 在隐私协议中没有声明chooseLocation:fail api作用域
if (res.errMsg && res.errno) {
if (res.errno == 104) {
let msg = '用户未授权隐私权限,设置剪贴板数据失败';
uni.showToast({ title: msg, icon: 'none' })
} else if (res.errno == 112) {
let msg = '隐私协议中未声明,设置剪贴板数据失败';
uni.showToast({ title: msg, icon: 'none' })
} else {
uni.showToast({ title: res.errMsg, icon: 'none' })
}
}
}
});
// #endif
}
/**
* 处理onLoad传递的参数
* @param option
*/
export function handleOnloadParams(option: any) {
let params: any = {};
// 处理小程序扫码进入的场景值参数
if (option.scene) {
var sceneParams = decodeURIComponent(option.scene).split('&');
if (sceneParams.length) {
sceneParams.forEach(item => {
let arr = item.split('-');
params[arr[0]] = arr[1];
if (arr[0] == 'mid') {
uni.setStorageSync('pid', arr[1])
}
});
}
} else {
params = option;
}
return params;
}
/**
* @description 深度克隆
* @param {object} obj 需要深度克隆的对象
* @returns {*} 克隆后的对象或者原值(不是对象)
*/
export function deepClone(obj: any) {
// 对常见的“非”值,直接返回原来值
if ([null, undefined, NaN, false].includes(obj)) return obj
if (typeof obj !== 'object' && typeof obj !== 'function') {
// 原始类型直接返回
return obj
}
const o = isArray(obj) ? [] : {}
for (const i in obj) {
if (obj.hasOwnProperty(i)) {
o[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
}
}
return o
}
/**
* 防抖函数
* @param fn
* @param delay
* @returns
*/
export function debounce(fn: (args?: any) => any, delay: number = 300) {
let timer: null | number = null
return function (...args) {
if (timer != null) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn.call(this, ...args)
}, delay);
}
}
const isArray = (value: any) => {
if (typeof Array.isArray === 'function') {
return Array.isArray(value)
}
return Object.prototype.toString.call(value) === '[object Array]'
}
// px转rpx
export function pxToRpx(px: any) {
const screenWidth = uni.getSystemInfoSync().screenWidth;
return (750 * Number.parseInt(px)) / screenWidth;
}
// 返回上一页
export function goback(data: any) {
let { url, mode, param, title } = data
uni.showToast({
title: title,
icon: 'none'
});
setTimeout(() => {
if (getCurrentPages().length > 1) {
uni.navigateBack({
delta: 1
});
} else {
redirect({
url: url,
param: param || {},
mode: mode || 'redirectTo'
});
}
}, 600);
}
// 获取微信OpenId、微信公众号OpenId
export function getWinxinOpenId() {
const memberStore = useMemberStore();
const memberInfo = memberStore.info;
let obj = {
weapp: '',
wechat: ''
}
if (memberInfo) {
obj.weapp = memberInfo.weapp_openid;
obj.wechat = memberInfo.wx_openid;
}
return obj;
}
// 获取有效期
export function getValidTime(minutes: any = 1) {
var date = new Date();
date.setSeconds(60 * minutes);
let validTime: any = parseInt(date.getTime() / 1000); // 定位信息 5分钟内有效过期后将重新获取定位信息
return validTime;
}
/**
* 检测当前访问的是系统app还是插件
* 设置插件的底部导航
* 设置插件应用的主色调
* @param path
*/
export function setThemeColor (path: string) {
let pathArr = path.split('/')
let index = !pathArr[0] ? 1 : 0;
let route = pathArr[index] == 'addon' ? pathArr[(index+1)] : 'app';
// 设置底部导航
const configStore = useConfigStore()
if (configStore.addon != route) {
configStore.addon = route;
}
// 设置插件应用的主色调,排除系统
const theme_color_list = uni.getStorageSync('theme_color_list');
const current_theme_color = uni.getStorageSync('current_theme_color');
let currTheme = {};
if (route != 'app') {
try {
currTheme = theme_color_list[route];
if(currTheme && currTheme.theme){
configStore.themeColor = themeColorToHex(currTheme.theme)
uni.setStorageSync('current_theme_color', JSON.stringify(themeColorToHex(currTheme.theme)));
}else if( !currTheme && current_theme_color){
configStore.themeColor = ''
}else{
currTheme = theme_color_list.app || Object.values(theme_color_list)[0];
configStore.themeColor = themeColorToHex(currTheme.theme)
uni.setStorageSync('current_theme_color', JSON.stringify(themeColorToHex(currTheme.theme)));
}
} catch (e) {
// 设置插件应用的主色调发生错误,若不存在则使用最后有效的主色调
if(!current_theme_color && theme_color_list && theme_color_list.length>0){
currTheme = theme_color_list.app || Object.values(theme_color_list)[0];
configStore.themeColor = themeColorToHex(currTheme.theme)
uni.setStorageSync('current_theme_color', JSON.stringify(themeColorToHex(currTheme.theme)));
}else{
configStore.themeColor = '';
}
}
}else if (!current_theme_color && theme_color_list && theme_color_list.length>0) {
currTheme = theme_color_list.app || Object.values(theme_color_list)[0]
configStore.themeColor = themeColorToHex(currTheme.theme)
uni.setStorageSync("current_theme_color", JSON.stringify(themeColorToHex(currTheme.theme)))
}
}
export function themeColorToHex (param: any) {
const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
const rgbaRegex = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(,\s*\d*\.?\d+)?\)$/
for(let key in param){
if (rgbaRegex.test(param[key])) {
const values = param[key].replace('rgba(', '').replace(')', '').split(',');
// 提取 r, g, b, a 值,并将它们转换为合适的类型
const r = parseInt(values[0].trim(), 10); // Red 分量
const g = parseInt(values[1].trim(), 10); // Green 分量
const b = parseInt(values[2].trim(), 10); // Blue 分量
const a = parseFloat(values[3].trim()); // Alpha 分量
param[key] = rgbaToHex(r,g,b,a)
}
}
return param
}
// rgba转十六进制颜色
export function rgbaToHex (r, g, b, a) {
// 计算混合后的RGB值假设背景是白色 (255, 255, 255)
let rBlend = Math.round((1 - a) * 255 + a * r)
let gBlend = Math.round((1 - a) * 255 + a * g)
let bBlend = Math.round((1 - a) * 255 + a * b)
// 将RGB值转换为十六进制
let componentToHex = function (c) {
let hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
let hex = "#" + componentToHex(rBlend) + componentToHex(gBlend) + componentToHex(bBlend)
return hex.toUpperCase()
}