r-util-js/packages/uni-app/src/uni-helper.ts

246 lines
6.7 KiB
TypeScript
Raw Normal View History

2026-03-16 17:58:57 +08:00
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. ReturnTypeuni 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 APIAPI单独写重载
* -
*
* @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
}