菜大王uniapp开发
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

218 lines
6.6 KiB

// import { isAsync } from "./isPending";
import useStore from "@/store";
const _promiseThrottleMap = {};
/**
* 节流函数
* @description 本函数接收一个Promise,当Promise在pending状态中,会自动阻止下次继续触发,在finally后释放。
* 同时允许传入一个时限,如果达到时限Promise还未finally,会执行onTime回调
* @param {string|number} promise_id 节流ID,同ID的内部节流,不同ID的互不干扰
* @param {number} time x毫秒后触发onTime,如果在此之前Promise已经finally,则不执行onTime
* @param {Function} promiseFunction 要节流的Promise函数,该函数应该返回一个Promise
* @param {Function} onTime 事件
* @returns {Promise} 节流后的Promise
*/
export function promiseThrottle(promise_id, time = 500, promiseFunction, onTime) {
if (_promiseThrottleMap[promise_id] === true)
return Promise.reject(new Error("请求正在进行中"));
let timeout;
if (typeof time == "number" && onTime)
timeout = setTimeout(onTime, time);
_promiseThrottleMap[promise_id] = true;
return promiseFunction().finally(() => {
_promiseThrottleMap[promise_id] = false;
clearTimeout(timeout);
});
}
export function sleep(timeout = 3000) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
/**
* @typedef {object} safeHeight
* @property {number} status - 状态栏高度
* @property {number} menu - 小程序胶囊高度
* @property {number} screen - 屏幕高度
* @property {number} content - 内容高度(屏幕高度 - 安全区域底部高度)
* @property {number} bottom - 安全区域底部高度
* @property {number} statusMenu - 状态栏高度 + 小程序胶囊高度
* @property {number} tabbar - tabbar高度
*/
/**
* @returns {safeHeight} - safeHeight
*/
export function useHeight() {
const safeHeight = {};
const info = uni.getWindowInfo();
const store = useStore();
safeHeight.status = info.statusBarHeight || 0;
// #ifdef APP
uni.hideTabBar();
// #endif
// #ifdef MP-WEIXIN
const menuButton = uni.getMenuButtonBoundingClientRect();
// menuHeight.value = menuButton.height;
safeHeight.menu = menuButton.height; // 小程序胶囊高度
safeHeight.status = menuButton.top; // 小程序胶囊距离手机顶部的高度
// #endif
// #ifdef APP-PlUS
safeHeight.status = info.statusBarHeight || 45; // 手机状态栏高度
// #endif
safeHeight.screen = info.screenHeight; // 屏幕高度
safeHeight.menu = safeHeight.menu || 0; // 小程序胶囊高度
safeHeight.bottom = info.safeAreaInsets.bottom || 0; // 手机屏幕底部安全高度
safeHeight.statusMenu = safeHeight.status + safeHeight.menu; // 手机状态栏+小程序胶囊的高度
safeHeight.tabbar = store.tabbarBottomHeight || 0; // tabbar高度
safeHeight.content = info.screenHeight
// - info.safeAreaInsets.bottom
// - store.tabbarBottomHeight
- safeHeight.bottom
- safeHeight.status - (safeHeight.menu || 40); // 减去手机状态栏 + 小程序胶囊 + tabbar + 底部安全高度
return safeHeight;
}
/**
* 获取元素矩形信息
* @param {*} selector 选择器
*/
export function useRect(selector, proxy) {
return new Promise((resolve) => {
const query = uni.createSelectorQuery();
if (proxy)
query.in(proxy);
query.select(selector).boundingClientRect((rect) => {
resolve(rect);
}).exec();
});
}
/**
* 通过类或者id 获取元素高度
* @deprecated
* @param {string} idOrClass
* @returns {Promise{number}} 元素高度
*/
export function getHeight(idOrClass) {
return new Promise((resolve) => {
const query = uni.createSelectorQuery();
query.select(idOrClass).boundingClientRect((data) => {
if ("height" in data) {
resolve(data.height);
}
}).exec();
});
}
/**
* 返回上一页或首页
*/
export function gotoBack() {
// uni.navigateBack();
// 获取当前页面栈信息
const pages = getCurrentPages();
// 页面栈长度为1时,说明当前是首页或无法返回,直接跳转到首页
if (pages.length <= 1) {
uni.switchTab({
url: "/pages/home/home", // 替换为你的首页路径
});
}
else {
// 页面栈长度大于1时,执行返回操作
uni.navigateBack({
delta: 1, // 返回的页面数
});
}
}
/**
* toast配置
* @typedef {object} toastConfig
* @property {string} title - toast标题
* @property {string} icon - toast图标,默认none
* @property {boolean} returnBoolean - 是否返回布尔值,默认返回布尔值
*/
/**
* 校验器
* @example
* const validators = [
* () => !email && "请输入邮箱", // && if true: return msge
* ];
* validates(validators);
* @param {Array<Function>|Function} validators 校验函数数组,每个函数返回校验错误信息或空字符串
* @param {toastConfig} toastConfig 校验失败时的toast配置
* @returns {string|boolean} 校验错误信息或空字符串
*/
export function validates(validators, toastConfig = { icon: "none", returnBoolean: true }) {
const validatorsFlat = Array.isArray(validators) ? validators : [validators];
// const hasAsync = validatorsFlat.some(item => isAsync(item));
// if (!hasAsync) {
// 同步校验:顺序执行,遇到第一条错误立即返回
for (const validator of validatorsFlat) {
const msg = validator();
if (msg) {
if (toastConfig.returnBoolean) {
uni.showToast({
...toastConfig,
title: msg,
});
}
return toastConfig.returnBoolean ? false : msg;
}
}
return toastConfig.returnBoolean ? true : "";
// }
// else {
// // 异步校验:顺序执行,遇到第一条错误立即返回
// return (async () => {
// for (const validator of validatorsFlat) {
// const msg = await validator();
// if (msg) {
// console.log(msg, "校验失败");
// return toastConfig.returnBoolean ? false : msg;
// }
// }
// return toastConfig.returnBoolean ? true : "";
// })();
// }
}
/**
* 增加字体缩放比例
* @param {number} incScale 缩放增量,默认0.1
*/
export function increaseFontScale(incScale = 0.1) {
const store = useStore();
store.fontScale += incScale;
uni.setStorageSync("fontScale", store.fontScale);
// validates(() => true && `${store.fontScale} 倍数`);
}
/**
* 获取指定路由的页面实例
* @param {string} route 页面路由
* @returns {object|undefined} 页面实例或undefined
*/
export function getPage(route) {
const pages = getCurrentPages();
const page = pages.find(page => page.route == route);
return page;
}