feat(): 改为vite
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
import { ComponentInternalInstance } from "vue";
|
||||
|
||||
/** 扫码 */
|
||||
export async function scanCode() {
|
||||
const res = await new Promise<UniApp.ScanCodeSuccessRes>(
|
||||
(resolve, reject) => {
|
||||
uni.scanCode({
|
||||
success(res) {
|
||||
resolve(res);
|
||||
},
|
||||
fail(res) {
|
||||
reject(res);
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
console.log({ res });
|
||||
return res.result;
|
||||
}
|
||||
|
||||
/** 获取当前页面 */
|
||||
export function getCurrentPage() {
|
||||
const pages = getCurrentPages();
|
||||
return pages[pages.length - 1];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 使用 TypeScript 工具类型实现自动类型推断的 toPromise
|
||||
*
|
||||
* 核心思路:
|
||||
* 1. 使用类似 Parameters<T>[0] 的方式提取函数第一个参数类型
|
||||
* 2. 从参数类型中提取 success 回调的参数类型
|
||||
* 3. 使用条件类型和 infer 关键字实现类型推断
|
||||
* 4. 虽然不能直接用 ReturnType(因为uni API返回void),但可以用类似思路提取回调参数类型
|
||||
*/
|
||||
|
||||
// 方法1:直接使用 Parameters<T> 工具类型
|
||||
// type ExtractFirstParameter<T> = Parameters<T>[0]; // 这样也可以,但需要T是函数类型
|
||||
|
||||
// 方法2:使用条件类型实现(更灵活,等价于 Parameters<T>[0])
|
||||
type ExtractFirstParameter<T> = T extends (arg: infer P, ...args: unknown[]) => unknown ? P : never;
|
||||
|
||||
// 提取 success 回调的参数类型(类似 ReturnType 的思路,但提取回调参数)
|
||||
type ExtractSuccessResult<T> = T extends { success?: (result: infer R) => void } ? R : never;
|
||||
|
||||
// 提取函数参数类型并排除回调函数(用于args参数)
|
||||
type ExtractOptions<T> = T extends (options: infer P) => unknown
|
||||
? Omit<P, "success" | "fail" | "complete">
|
||||
: never;
|
||||
|
||||
// 类型测试示例(编译时验证)
|
||||
// type TestDownloadOptions = ExtractOptions<typeof uni.downloadFile>; // UniNamespace.DownloadFileOption 去除回调
|
||||
// type TestDownloadResult = ExtractSuccessResult<Parameters<typeof uni.downloadFile>[0]>; // UniNamespace.DownloadSuccessData
|
||||
|
||||
/**
|
||||
* 将 uni-app 回调方法转换为 Promise(使用工具类型自动推断)
|
||||
*
|
||||
* 优势:
|
||||
* - 无需手动指定泛型参数
|
||||
* - 完全基于 TypeScript 工具类型实现
|
||||
* - 支持所有 uni-app API,不需要为每个API单独写重载
|
||||
* - 类型安全,有完整的智能提示
|
||||
*
|
||||
* @example
|
||||
* // 自动推断为 Promise<UniNamespace.DownloadSuccessData>
|
||||
* const downloadRes = await toPromise(uni.downloadFile, { url: 'https://example.com/file.jpg' });
|
||||
* console.log(downloadRes.tempFilePath); // ✅ 类型安全,有智能提示
|
||||
*
|
||||
* // 自动推断为 Promise<UniNamespace.ScanCodeSuccessRes>
|
||||
* const scanRes = await toPromise(uni.scanCode, {});
|
||||
* console.log(scanRes.result); // ✅ 类型安全,有智能提示
|
||||
*
|
||||
* // 自动推断为 Promise<UniNamespace.UploadFileSuccessCallbackResult>
|
||||
* const uploadRes = await toPromise(uni.uploadFile, {
|
||||
* url: '/upload',
|
||||
* filePath: 'temp://file.jpg',
|
||||
* name: 'file'
|
||||
* });
|
||||
* console.log(uploadRes.statusCode); // ✅ 类型安全,有智能提示
|
||||
*
|
||||
* // 自动推断为 Promise<UniNamespace.RequestSuccessCallbackResult>
|
||||
* const requestRes = await toPromise(uni.request, { url: '/api/data' });
|
||||
* console.log(requestRes.data); // ✅ 类型安全,有智能提示
|
||||
*/
|
||||
export function toPromise<F extends (options: Record<string, unknown>) => void>(
|
||||
uniFun: F,
|
||||
args?: ExtractOptions<F>,
|
||||
): Promise<ExtractSuccessResult<ExtractFirstParameter<F>>> {
|
||||
type OptionsType = ExtractFirstParameter<F>;
|
||||
type ResultType = ExtractSuccessResult<OptionsType>;
|
||||
|
||||
return new Promise<ResultType>((resolve, reject) => {
|
||||
uniFun({
|
||||
...args,
|
||||
success(res: ResultType) {
|
||||
resolve(res);
|
||||
},
|
||||
fail(err: unknown) {
|
||||
reject(err);
|
||||
},
|
||||
} as OptionsType);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function showToast(
|
||||
title: string,
|
||||
icon: "success" | "loading" | "error" | "none" = "none",
|
||||
options?: UniNamespace.ShowToastOptions,
|
||||
) {
|
||||
uni.showToast({
|
||||
...options,
|
||||
title,
|
||||
icon,
|
||||
duration: options?.duration ?? 1000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过URL生成canvas二维码
|
||||
* @param canvasId
|
||||
* @param url 图片URL
|
||||
* @param x 定位于canvas左边宽度,单位px
|
||||
* @param y 定位于canvas顶部高度,单位px
|
||||
* @param width 二维码宽度,单位px
|
||||
* @param height 二维码高度,单位px
|
||||
* @param thisArg 页面上下文
|
||||
* @returns 图像像素点数据
|
||||
*/
|
||||
export async function getCanvasImageData(
|
||||
canvasId: string,
|
||||
url: string,
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 200,
|
||||
height = 200,
|
||||
thisArg: ComponentInternalInstance,
|
||||
) {
|
||||
const context = uni.createCanvasContext(canvasId, thisArg);
|
||||
|
||||
const imgRes = await toPromise(
|
||||
uni.downloadFile,
|
||||
{
|
||||
url,
|
||||
},
|
||||
);
|
||||
|
||||
console.log(imgRes);
|
||||
context.drawImage(imgRes.tempFilePath, x, y, width, height);
|
||||
await new Promise((resolve) => {
|
||||
context.draw(false, (res) => {
|
||||
console.log(res);
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
const imageData: UniNamespace.CanvasGetImageDataRes =
|
||||
await uni.canvasGetImageData({
|
||||
canvasId: canvasId,
|
||||
x,
|
||||
y,
|
||||
width: width,
|
||||
height: height,
|
||||
});
|
||||
|
||||
return imageData.data;
|
||||
}
|
||||
|
||||
export async function getCanvasImageDataSimplify(
|
||||
canvasId: string,
|
||||
url: string,
|
||||
width = 200,
|
||||
height = 200,
|
||||
thisArg: ComponentInternalInstance,
|
||||
) {
|
||||
return await getCanvasImageData(canvasId, url, 0, 0, width, height, thisArg);
|
||||
}
|
||||
|
||||
export async function getCanvasImageDataTransObj({
|
||||
canvasId,
|
||||
url,
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 200,
|
||||
height = 200,
|
||||
thisArg,
|
||||
}: {
|
||||
canvasId: string;
|
||||
url: string;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
thisArg: ComponentInternalInstance;
|
||||
}) {
|
||||
return await getCanvasImageData(canvasId, url, x, y, width, height, thisArg);
|
||||
}
|
||||
|
||||
export function rpxToPx(rpx: number | string) {
|
||||
if (typeof rpx === "string") {
|
||||
rpx = Number.parseInt(rpx);
|
||||
}
|
||||
const screenWidth = uni.getSystemInfoSync().screenWidth;
|
||||
return (screenWidth * rpx) / 750;
|
||||
}
|
||||
|
||||
export function pxToRpx(px: number | string) {
|
||||
if (typeof px === "string") {
|
||||
px = Number.parseInt(px);
|
||||
}
|
||||
const screenWidth = uni.getSystemInfoSync().screenWidth;
|
||||
return (750 * px) / screenWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出程序
|
||||
*/
|
||||
export function exitApp() {
|
||||
// #ifdef APP-PLUS
|
||||
if (plus.os.name?.toLowerCase() === "android") {
|
||||
plus.runtime.quit();
|
||||
} else {
|
||||
const threadClass = plus.ios.importClass("NSThread");
|
||||
const mainThread = plus.ios.invoke(threadClass, "mainThread");
|
||||
plus.ios.invoke(mainThread, "exit");
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有安卓权限
|
||||
*/
|
||||
export function checkAndroidPermission(permissionList: string[]) {
|
||||
// #ifdef APP-PLUS
|
||||
const ActivityCompat = plus.android.importClass(
|
||||
"androidx.core.app.ActivityCompat",
|
||||
) as Android.ActivityCompat;
|
||||
const activity = plus.android.runtimeMainActivity();
|
||||
|
||||
return permissionList.every((v) => {
|
||||
const p = ActivityCompat.checkSelfPermission(activity, v);
|
||||
return p === 0;
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
Reference in New Issue
Block a user