HarmonyOSBaseLibs/src/main/ets/utils/ToolsHelper.ets

409 行
12 KiB
Plaintext

2024-05-07 17:41:21 +08:00
import promptAction from '@ohos.promptAction';
2024-10-12 18:45:02 +08:00
import { BusinessError, deviceInfo } from '@kit.BasicServicesKit';
2024-10-14 16:02:55 +08:00
import { HashMap } from '@kit.ArkTS';
2024-10-12 18:45:02 +08:00
import { DeviceInfo } from '../bean/DeviceInfo';
2024-10-15 17:39:02 +08:00
import { common } from '@kit.AbilityKit';
2024-10-20 17:59:30 +08:00
import { md5_hex } from '../util/md5';
import { LogHelper } from '../../../../Index';
2024-05-07 17:41:21 +08:00
export interface Btn {
text?: string | Resource;
color?: string | Resource;
2024-10-20 17:59:30 +08:00
onClick?: () => void
2024-05-07 17:41:21 +08:00
}
export interface AlertOptions {
2024-10-21 19:54:10 +08:00
title?: string,
msg?: string,
2024-10-20 18:25:55 +08:00
action?: Btn
2024-05-07 17:41:21 +08:00
}
export interface ConfirmOptions {
title?: string
msg?: string
2024-10-20 17:59:30 +08:00
confirm?: Btn
cancel?: Btn
2024-05-07 17:41:21 +08:00
}
export interface ListOptions<T> {
title?: string
cancel?: Btn
autoCancel?: boolean
index?: number
alignment?: DialogAlignment
2024-05-07 17:41:21 +08:00
values: Array<T>
onSelected: (index: number, value: T) => void
onError?: (msg: string) => void
}
interface ListItem {
content: string
}
@Builder
2024-10-22 12:00:46 +08:00
function customDialogBuilder<T>(option: ListOptions<T>, dialogTag: string) {
2024-05-07 17:41:21 +08:00
Column() {
Text(option.title)
.fontSize(16)
.fontColor('#00BE87')
2024-05-07 17:41:21 +08:00
.textAlign(TextAlign.Center)
.width('100%')
.height(60)
.backgroundColor('#F0FFFA')
.borderRadius({
topLeft: 10,
topRight: 10
2024-05-07 17:41:21 +08:00
})
.visibility(option.title ? Visibility.Visible : Visibility.None)
Column() {
List() {
ForEach(option.values, (item: T, index: number) => {
ListItem() {
Row() {
Text(typeof item === "string" ? item : (item as ListItem).content)
.fontSize(option.index === index ? 16 : 14)
.fontWeight(option.index === index ? FontWeight.Bold : FontWeight.Normal)
.maxLines(1)
.width('70%')
.ellipsisMode(EllipsisMode.CENTER)
.textOverflow({
overflow: TextOverflow.Ellipsis
})
.textAlign(TextAlign.Center)
.align(Alignment.Center)
.fontColor('#11102C')
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
.height(60)
2024-05-07 17:41:21 +08:00
.width('100%')
.onClick(() => {
2024-10-21 19:54:10 +08:00
if (ToolsHelper.mapDialog.get(dialogTag)) {
promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogTag))
ToolsHelper.mapDialog.remove(dialogTag)
2024-05-07 17:41:21 +08:00
}
option.onSelected(index, item)
})
}
}, (item: T) => typeof item === "string" ? item : (item as ListItem).content)
}
.listDirection(Axis.Vertical) // 排列方向
.scrollBar(BarState.Off)
.friction(0.6)
.divider({
strokeWidth: 1,
color: '#F6F6F6',
}) // 每行之间的分界线
.edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring
.width('100%')
.height(option.values === undefined ? '20%' : option.values.length < 5 ? option.values.length * 60 : 300)
if (option.cancel) {
Column() {
Text(option.cancel.text ?? '取消')
.fontSize(16)
.fontColor(option.cancel.color ?? '#777777')
.textAlign(TextAlign.Center)
.width(325)
.height(44)
.backgroundColor('white')
.borderRadius(22)
.borderWidth(1)
.borderColor('#D7D7D7')
2024-05-07 17:41:21 +08:00
}
.onClick(() => {
if (ToolsHelper.mapDialog.get(dialogTag)) {
promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogTag))
ToolsHelper.mapDialog.remove(dialogTag)
}
option.cancel?.onClick && option.cancel.onClick()
})
.height(71)
.width('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
}
}.justifyContent(FlexAlign.End)
}.justifyContent(FlexAlign.Start)
2024-05-07 17:41:21 +08:00
}
2024-10-20 17:59:30 +08:00
interface ThrottleInterface {
startTime: number; //调用的时间
timeoutNumber: number; //setTimeout的句柄
}
2024-05-07 17:41:21 +08:00
/**
* 常用方法
*/
export class ToolsHelper {
private constructor() {
}
2024-10-14 16:02:55 +08:00
/**
* 弹出Toast
* @param msg
*/
static log(...args: ESObject[]) {
const k = ToolsHelper.getStackKey()?.split('/')
LogHelper.info(`${k ? k[k.length-1].split('.')[0] : ''}::\n`, ...args)
2024-10-14 16:02:55 +08:00
}
2024-05-07 17:41:21 +08:00
/**
* 弹出Toast
* @param msg
*/
static showMessage(msg: string) {
console.info(msg);
promptAction.showToast({
message: msg,
duration: 1500
});
}
2024-10-15 17:39:02 +08:00
2024-10-18 18:38:49 +08:00
private static oTime: number = 0
2024-10-15 17:39:02 +08:00
/**
* 双击退出
* @param msg
*/
2024-10-18 18:38:49 +08:00
static doubleAndExit(event?: () => void) {
2024-10-15 17:39:02 +08:00
const cTime = new Date().getTime()
console.log('=====>', cTime)
console.log('=====>', cTime - ToolsHelper.oTime)
if (cTime - ToolsHelper.oTime > 800) {
ToolsHelper.oTime = cTime
ToolsHelper.showMessage('双击退出')
} else {
2024-10-18 10:01:31 +08:00
if (event) {
event()
2024-10-18 18:38:49 +08:00
} else {
2024-10-18 10:01:31 +08:00
(getContext() as common.UIAbilityContext).terminateSelf()
// getContext().getApplicationContext().killAllProcesses();
}
2024-10-15 17:39:02 +08:00
}
return true
}
2024-05-07 17:41:21 +08:00
/**kio9
* 弹出Alert弹窗
* @param options
*/
2024-10-21 19:54:10 +08:00
static showAlertDialog(options: AlertOptions) {
2024-05-07 17:41:21 +08:00
try {
promptAction.showDialog({
2024-10-21 19:54:10 +08:00
alignment: DialogAlignment.Center,
title: options.title,
message: options.msg,
2024-05-07 17:41:21 +08:00
buttons: [{
2024-10-21 19:54:10 +08:00
text: options.action?.text ?? "确定",
color: options.action?.color ?? "#000000",
2024-05-07 17:41:21 +08:00
}]
})
.then(() => {
2024-10-21 19:54:10 +08:00
options.action?.onClick && options.action?.onClick()
2024-05-07 17:41:21 +08:00
})
.catch((err: Error) => {
ToolsHelper.showMessage(err.message)
})
} catch (error) {
let message = (error as BusinessError).message
ToolsHelper.showMessage(message)
}
}
/**
* 弹出Confirm弹窗
* @param options
*/
static showConfirmDialog(options: ConfirmOptions): Promise<void> {
return new Promise((reject) => {
try {
promptAction.showDialog({
alignment: 1,
title: options.title,
message: options.msg,
buttons: [{
text: options.cancel?.text ?? "取消",
color: options.cancel?.color ?? "#666666",
}, {
text: options.confirm?.text ?? "确定",
color: options.confirm?.color ?? "#000000",
},]
2024-05-07 17:41:21 +08:00
})
.then((data) => {
if (data.index === 0) {
options.cancel?.onClick && options.cancel.onClick()
} else {
options.confirm?.onClick && options.confirm.onClick()
}
})
.catch((err: Error) => {
ToolsHelper.showMessage(err.message)
})
} catch (error) {
reject()
let message = (error as BusinessError).message
ToolsHelper.showMessage(message)
}
})
2024-05-07 17:41:21 +08:00
}
2024-10-21 19:54:10 +08:00
public static mapDialog = new HashMap<string, number>()
2024-05-07 17:41:21 +08:00
/**
* 弹出List弹窗
* @param options values 如果是非string列表的话,需要存在content字段
* @param p 调用页面,直接this 即可
2024-05-07 17:41:21 +08:00
*/
static showListDialog<T = string>(options: ListOptions<T>, p: object) {
let isSuccess: Array<number> = []
options.values.forEach((item, index) => {
if (typeof item !== 'string') {
if (!(item as ListItem).content) {
isSuccess.push(index)
}
}
})
if (isSuccess.length > 0) {
options.onError && options.onError(`第(${isSuccess.join("、")})个数据中,没有content字段。`)
} else {
2024-10-21 19:54:10 +08:00
const dialogTag = ToolsHelper.getUuid()
2024-05-07 17:41:21 +08:00
promptAction.openCustomDialog({
cornerRadius: 0,
autoCancel: options.autoCancel ?? false,
width: '100%',
// height: options.values === undefined ? '20%' :
// options.values?.length < 8 ? `${options.values?.length / 16 * 100+10}%` : '50%',
alignment: options.alignment ?? DialogAlignment.Bottom,
builder: customDialogBuilder.bind(p, options, dialogTag),
backgroundColor: 'white'
2024-05-07 17:41:21 +08:00
}).then((dialogId: number) => {
ToolsHelper.mapDialog.set(dialogTag, dialogId)
})
}
}
/**
* 弹出自定义弹窗
* @param alignment 弹窗在竖直方向上的对齐方式
*/
2024-10-21 19:54:10 +08:00
static showCustomDialog(dialogTag: string, b: CustomBuilder, alignment?: DialogAlignment) {
2024-05-07 17:41:21 +08:00
promptAction.openCustomDialog({
alignment: alignment ?? DialogAlignment.Center,
builder: b,
cornerRadius: 3,
width: '100%',
2024-05-07 17:41:21 +08:00
}).then((dialogId: number) => {
ToolsHelper.mapDialog.set(dialogTag, dialogId)
}).catch((error: Error) => {
console.log('>>>>>', JSON.stringify(error))
})
}
2024-10-10 20:01:58 +08:00
2024-10-21 19:54:10 +08:00
/**
* 关闭自定义弹窗
* @param dialogTag 开启时的tag
*/
static closeCustomDialog(dialogTag: string) {
if (ToolsHelper.mapDialog.get(dialogTag)) {
promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogTag))
ToolsHelper.mapDialog.remove(dialogTag)
}
}
static encryptStringToNumber(str: string): number {
let result = 0;
for (let i = 0; i < str.length; i++) {
result = result * 256 + str.charCodeAt(i);
}
return result;
}
static decryptNumberToString(num: number): string {
let result = '';
while (num > 0) {
result = String.fromCharCode(num & 255) + result;
num >>>= 8;
}
return result.replace(/[\s\0]+$/, ''); // 移除结尾的空白字符
}
2024-10-10 20:01:58 +08:00
/**
* 获取调用栈第一个类
*/
static getStackKey() {
let stack = new Error().stack
if (stack) {
let list = JSON.stringify(stack).split('\\n')
let a = list[list.length-2].split(':')[0].split('(')[1]
return a
}
return undefined
}
2024-10-12 18:45:02 +08:00
private static deviceInfo: DeviceInfo
2024-10-14 16:02:55 +08:00
/**
* 获取设备信息
* @returns {@link DeviceInfo}
*/
2024-10-12 18:45:02 +08:00
static getDeviceInfo() {
if (!ToolsHelper.deviceInfo) {
ToolsHelper.deviceInfo = new DeviceInfo()
ToolsHelper.deviceInfo.ODID = deviceInfo.ODID
ToolsHelper.deviceInfo.manufacture = deviceInfo.manufacture
ToolsHelper.deviceInfo.brand = deviceInfo.brand
ToolsHelper.deviceInfo.osFullName = deviceInfo.osFullName
}
return ToolsHelper.deviceInfo
}
2024-10-20 17:59:30 +08:00
/**
* 防抖动函数,调用后会延迟wait时间执行,当在wait时间内再次对同一函数调用,则会取消之前的定时器,重新定时
* @param fun
* @param wait
*/
static debounceHold(fun: Function, wait: number = 1500) {
let funcValue1 = ToolsHelper.getUniqueId(fun)
let hash = md5_hex(funcValue1)
if (ToolsHelper.setTimeOutMap.get(hash)) {
clearTimeout(ToolsHelper.setTimeOutMap.get(hash)?.timeoutNumber)
ToolsHelper.setTimeOutMap.delete(hash)
}
// ToolsHelper.checkTimeOutNumber()
let timeoutNumber = setTimeout(() => {
ToolsHelper.setTimeOutMap.get(hash) && clearTimeout(ToolsHelper.setTimeOutMap.get(hash)?.timeoutNumber)
ToolsHelper.setTimeOutMap.delete(hash)
// 执行函数调用
fun()
}, wait)
ToolsHelper.setTimeOutMap.set(hash, {
timeoutNumber: timeoutNumber,
startTime: new Date().getTime(),
})
}
private static setTimeOutMap: Map<string, ThrottleInterface> = new Map()
private static uniqueIdMap = new WeakMap<Function, string>();
public static getUuid() {
2024-10-20 17:59:30 +08:00
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
let r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
private static getUniqueId(fun: Function): string {
// ToolsHelper.log(ToolsHelper.getStackKey())
2024-10-20 17:59:30 +08:00
if (!ToolsHelper.uniqueIdMap.has(fun)) {
ToolsHelper.uniqueIdMap.set(fun, ToolsHelper.getUuid());
}
return ToolsHelper.uniqueIdMap.get(fun)!;
}
2024-05-07 17:41:21 +08:00
}