-移除 AppAbility 中的冗余导入 - 调整 MiniAppManager 中的导入顺序 - 重构 GlobalContext 类,使用单个 UIContext 实例替代数组- 优化 SafeView 组件,移除不必要的生命周期方法 -改进 ToolsHelper.showMessage 方法,支持在不同上下文中显示提示信息- 调整 CertDown 页面的逻辑,优化证书下载流程
671 行
21 KiB
Plaintext
671 行
21 KiB
Plaintext
import promptAction from '@ohos.promptAction';
|
||
import { BusinessError, deviceInfo } from '@kit.BasicServicesKit';
|
||
import { buffer, HashMap, util } from '@kit.ArkTS';
|
||
import { DeviceInfo } from '../bean/DeviceInfo';
|
||
import { common } from '@kit.AbilityKit';
|
||
import { md5_hex } from '../util/md5';
|
||
import { GlobalContext, LogHelper } from '../../../../Index';
|
||
import { ComponentContent } from '@kit.ArkUI';
|
||
|
||
export class AlertBean {
|
||
options: ConfirmOptions
|
||
dialogTag: string
|
||
|
||
constructor(options: ConfirmOptions, dialogTag: string) {
|
||
this.options = options
|
||
this.dialogTag = dialogTag
|
||
}
|
||
}
|
||
|
||
export interface Btn {
|
||
text?: string | Resource;
|
||
color?: string | Resource;
|
||
bgColor?: string | Resource;
|
||
onClick?: () => void
|
||
}
|
||
|
||
export interface AlertOptions {
|
||
title?: string,
|
||
msg?: string,
|
||
action?: Btn
|
||
}
|
||
|
||
export interface ConfirmOptions {
|
||
title?: string
|
||
msg?: string
|
||
confirm?: Btn
|
||
cancel?: Btn
|
||
autoCancel?: boolean
|
||
}
|
||
|
||
export interface ListOptions<T> {
|
||
title?: string
|
||
cancel?: Btn
|
||
autoCancel?: boolean
|
||
index?: number
|
||
alignment?: DialogAlignment
|
||
values: Array<T>
|
||
onSelected: (index: number, value: T) => void
|
||
onError?: (msg: string) => void
|
||
}
|
||
|
||
interface ListItem {
|
||
content: string
|
||
}
|
||
|
||
@Builder
|
||
function customDialogBuilder<T>(option: ListOptions<T>, dialogTag: string) {
|
||
|
||
Column() {
|
||
Text(option.title)
|
||
.fontSize(16)
|
||
.fontColor('#00BE87')
|
||
.textAlign(TextAlign.Center)
|
||
.width('100%')
|
||
.height(60)
|
||
.backgroundColor('#F0FFFA')
|
||
.borderRadius({
|
||
topLeft: 10,
|
||
topRight: 10
|
||
})
|
||
.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)
|
||
.width('100%')
|
||
.onClick(() => {
|
||
if (ToolsHelper.mapDialog.get(dialogTag)) {
|
||
promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogTag))
|
||
ToolsHelper.mapDialog.remove(dialogTag)
|
||
}
|
||
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')
|
||
}
|
||
.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)
|
||
}
|
||
|
||
@Builder
|
||
function alertDialogBuilder(options: AlertBean) {
|
||
|
||
Column() {
|
||
Row() {
|
||
Image($r('app.media.dialog_confirm_close'))
|
||
.width(17)
|
||
.height(17)
|
||
.visibility(options.options.cancel ? Visibility.Hidden : Visibility.None)
|
||
Text(options.options.title ? !options.options.msg ? '提示' : options.options.title : '提示')
|
||
.fontSize(16)
|
||
.fontColor($r('sys.color.black'))
|
||
.textAlign(TextAlign.Center)
|
||
.layoutWeight(1)
|
||
.height('100%')
|
||
.fontWeight(FontWeight.Bold)
|
||
.maxLines(1)
|
||
.padding({
|
||
left: 20,
|
||
right: 20
|
||
})
|
||
.ellipsisMode(EllipsisMode.CENTER)
|
||
.textOverflow({
|
||
overflow: TextOverflow.Ellipsis
|
||
})
|
||
Image($r('app.media.dialog_confirm_close'))
|
||
.width(17)
|
||
.height(17)
|
||
.visibility(options.options.cancel ? Visibility.Visible : Visibility.None)
|
||
.onClick(() => {
|
||
options.options.cancel?.onClick && options.options.cancel.onClick()
|
||
ToolsHelper.closeAlertDialog(options.dialogTag)
|
||
})
|
||
|
||
}
|
||
.width('100%')
|
||
.height(60)
|
||
.justifyContent(FlexAlign.SpaceBetween)
|
||
.alignItems(VerticalAlign.Top)
|
||
.padding(9)
|
||
|
||
Scroll() {
|
||
Text(options.options.msg ?? options.options.title)
|
||
.fontSize(14)
|
||
.fontWeight(FontWeight.Medium)
|
||
.fontColor($r('sys.color.black'))
|
||
.textAlign(TextAlign.Center)
|
||
.lineHeight(20)
|
||
.padding({
|
||
left: 19,
|
||
right: 19
|
||
})
|
||
.width('100%')
|
||
}.scrollable(ScrollDirection.Vertical)
|
||
.constraintSize({
|
||
maxHeight: 220
|
||
})
|
||
|
||
Text(options.options.confirm?.text ?? '确定')
|
||
.fontSize(14)
|
||
.fontWeight(FontWeight.Medium)
|
||
.fontColor($r('sys.color.white'))
|
||
.textAlign(TextAlign.Center)
|
||
.margin({
|
||
top: 40,
|
||
bottom: 40,
|
||
left: 18,
|
||
right: 18
|
||
})
|
||
.width(215)
|
||
.backgroundColor('#0E84FA')
|
||
.borderRadius(5)
|
||
.height(34)
|
||
.onClick(() => {
|
||
options.options.confirm?.onClick && options.options.confirm.onClick()
|
||
ToolsHelper.closeAlertDialog(options.dialogTag)
|
||
})
|
||
}
|
||
.width('66%')
|
||
.borderRadius(5)
|
||
.justifyContent(FlexAlign.Start)
|
||
.constraintSize({
|
||
minHeight: 194
|
||
})
|
||
.linearGradient({
|
||
// 0点方向顺时针旋转为正向角度,线性渐变起始角度的默认值为180°
|
||
colors: [
|
||
[0xE6F6FA, 0], // 颜色断点1的颜色和比重,对应组件在180°方向上的起始位置
|
||
[0xffffff, 1.0],// 颜色断点2的颜色和比重,对应组件在180°方向上的终点位置
|
||
]
|
||
})
|
||
}
|
||
|
||
interface ThrottleInterface {
|
||
startTime: number; //调用的时间
|
||
timeoutNumber: number; //setTimeout的句柄
|
||
}
|
||
|
||
|
||
/**
|
||
* 常用方法
|
||
*/
|
||
export class ToolsHelper {
|
||
private constructor() {
|
||
}
|
||
|
||
/**
|
||
* 弹出Toast
|
||
* @param msg
|
||
*/
|
||
static log(...args: ESObject[]) {
|
||
const k = ToolsHelper.getStackKey()?.split('/')
|
||
LogHelper.info(`${k ? k[k.length-1].split('.')[0] : ''}::\n`, ...args)
|
||
}
|
||
|
||
/**
|
||
* 弹出Toast
|
||
* @param msg
|
||
*/
|
||
static showMessage(msg: string) {
|
||
|
||
const pa = GlobalContext.getUiContext()?.getPromptAction()
|
||
if (pa) {
|
||
pa.showToast({
|
||
message: msg,
|
||
duration: 1500
|
||
});
|
||
} else {
|
||
promptAction.showToast({
|
||
message: msg,
|
||
duration: 1500
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
private static oTime: number = 0
|
||
|
||
/**
|
||
* 双击退出
|
||
* @param msg
|
||
*/
|
||
static doubleAndExit(event?: () => void) {
|
||
const cTime = new Date().getTime()
|
||
console.log('=====>', cTime)
|
||
console.log('=====>', cTime - ToolsHelper.oTime)
|
||
if (cTime - ToolsHelper.oTime > 800) {
|
||
ToolsHelper.oTime = cTime
|
||
ToolsHelper.showMessage('双击退出')
|
||
} else {
|
||
if (event) {
|
||
event()
|
||
} else {
|
||
(getContext() as common.UIAbilityContext).terminateSelf()
|
||
// getContext().getApplicationContext().killAllProcesses();
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
static closeAlertDialog(dialogTag: string) {
|
||
if (ToolsHelper.mapAlertDialog.get(dialogTag)) {
|
||
try {
|
||
GlobalContext.getUiContext()?.getPromptAction().closeCustomDialog(ToolsHelper.mapAlertDialog.get(dialogTag))
|
||
} catch (err) {
|
||
}
|
||
ToolsHelper.mapAlertDialog.remove(dialogTag)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 弹出Alert弹窗
|
||
* 第二个参数可以自定义布局,自定义布局接收的参数为AlertBean
|
||
* @Builder
|
||
* function alertDialogBuilder(options: AlertBean) {}
|
||
*
|
||
* @param options
|
||
* @param builder wrapBuilder(alertDialogBuilder)
|
||
*/
|
||
static showAlertDialog(options: AlertOptions, builder?: WrappedBuilder<[Object]>) {
|
||
const dialogTag = ToolsHelper.getUuid()
|
||
const ui = GlobalContext.getUiContext()
|
||
if (ui) {
|
||
const c = new ComponentContent(ui, builder ?? wrapBuilder(alertDialogBuilder),
|
||
new AlertBean({ title: options.title, msg: options.msg, confirm: options.action }, dialogTag))
|
||
ui.getPromptAction().openCustomDialog(c, {
|
||
autoCancel: false
|
||
}).then(() => {
|
||
ToolsHelper.mapAlertDialog.set(dialogTag, c)
|
||
}).catch(() => {
|
||
ToolsHelper.showCommonAlert(options)
|
||
})
|
||
} else {
|
||
ToolsHelper.showCommonAlert(options)
|
||
}
|
||
}
|
||
|
||
private static showCommonAlert(options: AlertOptions) {
|
||
try {
|
||
promptAction.showDialog({
|
||
alignment: DialogAlignment.Center,
|
||
title: options.title,
|
||
message: options.msg,
|
||
buttons: [{
|
||
text: options.action?.text ?? "确定",
|
||
color: options.action?.color ?? "#000000",
|
||
}]
|
||
})
|
||
.then(() => {
|
||
options.action?.onClick && options.action?.onClick()
|
||
})
|
||
.catch((err: Error) => {
|
||
if (err.message === 'cancel') {
|
||
} else {
|
||
ToolsHelper.showMessage(err.message)
|
||
}
|
||
})
|
||
} catch (error) {
|
||
let message = (error as BusinessError).message
|
||
ToolsHelper.showMessage(message)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 弹出Confirm弹窗
|
||
* 第二个参数可以自定义布局,自定义布局接收的参数为AlertBean
|
||
* @Builder
|
||
* function alertDialogBuilder(options: AlertBean) {}
|
||
*
|
||
* @param options
|
||
* @param builder wrapBuilder(alertDialogBuilder)
|
||
*/
|
||
static showConfirmDialog(options: ConfirmOptions, builder?: WrappedBuilder<[Object]>) {
|
||
|
||
const dialogTag = ToolsHelper.getUuid()
|
||
const ui = GlobalContext.getUiContext()
|
||
if (ui) {
|
||
const c = new ComponentContent(ui, builder ?? wrapBuilder(alertDialogBuilder),
|
||
new AlertBean({
|
||
title: options.title,
|
||
msg: options.msg,
|
||
cancel: options.cancel ?? {},
|
||
confirm: options.confirm
|
||
}, dialogTag))
|
||
ui.getPromptAction().openCustomDialog(c, {
|
||
autoCancel: options.autoCancel
|
||
}).then(() => {
|
||
ToolsHelper.mapAlertDialog.set(dialogTag, c)
|
||
}).catch(() => {
|
||
ToolsHelper.showCommonConfirm(options)
|
||
})
|
||
} else {
|
||
ToolsHelper.showCommonConfirm(options)
|
||
}
|
||
|
||
}
|
||
|
||
static showCommonConfirm(options: ConfirmOptions) {
|
||
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",
|
||
},]
|
||
})
|
||
.then((data) => {
|
||
if (data.index === 0) {
|
||
options.cancel?.onClick && options.cancel.onClick()
|
||
} else {
|
||
options.confirm?.onClick && options.confirm.onClick()
|
||
}
|
||
})
|
||
.catch((err: Error) => {
|
||
if (err.message === 'cancel') {
|
||
options.cancel?.onClick && options.cancel.onClick()
|
||
} else {
|
||
ToolsHelper.showMessage(err.message)
|
||
}
|
||
})
|
||
} catch (error) {
|
||
let message = (error as BusinessError).message
|
||
ToolsHelper.showMessage(message)
|
||
}
|
||
}
|
||
|
||
public static mapDialog = new HashMap<string, number>()
|
||
public static mapAlertDialog = new HashMap<string, ComponentContent<Object>>()
|
||
|
||
/**
|
||
* 弹出List弹窗
|
||
* @param options values 如果是非string列表的话,需要存在content字段
|
||
* @param p 调用页面,直接this 即可
|
||
*/
|
||
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 {
|
||
const dialogTag = ToolsHelper.getUuid()
|
||
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'
|
||
}).then((dialogId: number) => {
|
||
ToolsHelper.mapDialog.set(dialogTag, dialogId)
|
||
})
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 弹出自定义弹窗
|
||
* @param alignment 弹窗在竖直方向上的对齐方式
|
||
*/
|
||
static showCustomDialog(dialogTag: string, b: CustomBuilder, alignment?: DialogAlignment) {
|
||
promptAction.openCustomDialog({
|
||
alignment: alignment ?? DialogAlignment.Center,
|
||
builder: b,
|
||
cornerRadius: 3,
|
||
width: '100%',
|
||
}).then((dialogId: number) => {
|
||
ToolsHelper.mapDialog.set(dialogTag, dialogId)
|
||
}).catch((error: Error) => {
|
||
console.log('>>>>>', JSON.stringify(error))
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 关闭自定义弹窗
|
||
* @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]+$/, ''); // 移除结尾的空白字符
|
||
}
|
||
|
||
/**
|
||
* 获取调用栈第一个类
|
||
*/
|
||
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
|
||
}
|
||
|
||
private static deviceInfo: DeviceInfo
|
||
|
||
/**
|
||
* 获取设备信息
|
||
* @returns {@link DeviceInfo}
|
||
*/
|
||
static getDeviceInfo() {
|
||
if (!ToolsHelper.deviceInfo) {
|
||
ToolsHelper.deviceInfo = new DeviceInfo()
|
||
ToolsHelper.deviceInfo.ODID = deviceInfo.ODID
|
||
ToolsHelper.deviceInfo.manufacture = deviceInfo.manufacture
|
||
ToolsHelper.deviceInfo.productModel = deviceInfo.productModel
|
||
ToolsHelper.deviceInfo.brand = deviceInfo.brand
|
||
ToolsHelper.deviceInfo.osFullName = deviceInfo.osFullName
|
||
ToolsHelper.logInfo()
|
||
}
|
||
return ToolsHelper.deviceInfo
|
||
}
|
||
|
||
private static logInfo() {
|
||
// ToolsHelper.log('deviceType-----', deviceInfo.deviceType)
|
||
// ToolsHelper.log('manufacture-----', deviceInfo.manufacture)
|
||
// ToolsHelper.log('brand-----', deviceInfo.brand)
|
||
// ToolsHelper.log('marketName-----', deviceInfo.marketName)
|
||
// ToolsHelper.log('productSeries-----', deviceInfo.productSeries)
|
||
// ToolsHelper.log('productModel-----', deviceInfo.productModel)
|
||
// ToolsHelper.log('softwareModel-----', deviceInfo.softwareModel)
|
||
// ToolsHelper.log('hardwareModel-----', deviceInfo.hardwareModel)
|
||
// ToolsHelper.log('hardwareProfile-----', deviceInfo.hardwareProfile)
|
||
// ToolsHelper.log('serial-----', deviceInfo.serial)
|
||
// ToolsHelper.log('bootloaderVersion-----', deviceInfo.bootloaderVersion)
|
||
// ToolsHelper.log('abiList-----', deviceInfo.abiList)
|
||
// ToolsHelper.log('securityPatchTag-----', deviceInfo.securityPatchTag)
|
||
// ToolsHelper.log('displayVersion-----', deviceInfo.displayVersion)
|
||
// ToolsHelper.log('incrementalVersion-----', deviceInfo.incrementalVersion)
|
||
// ToolsHelper.log('osReleaseType-----', deviceInfo.osReleaseType)
|
||
// ToolsHelper.log('osFullName-----', deviceInfo.osFullName)
|
||
// ToolsHelper.log('majorVersion-----', deviceInfo.majorVersion)
|
||
// ToolsHelper.log('seniorVersion-----', deviceInfo.seniorVersion)
|
||
// ToolsHelper.log('featureVersion-----', deviceInfo.featureVersion)
|
||
// ToolsHelper.log('buildVersion-----', deviceInfo.buildVersion)
|
||
// ToolsHelper.log('sdkApiVersion-----', deviceInfo.sdkApiVersion)
|
||
// ToolsHelper.log('firstApiVersion-----', deviceInfo.firstApiVersion)
|
||
// ToolsHelper.log('versionId-----', deviceInfo.versionId)
|
||
// ToolsHelper.log('buildType-----', deviceInfo.buildType)
|
||
// ToolsHelper.log('buildUser-----', deviceInfo.buildUser)
|
||
// ToolsHelper.log('buildHost-----', deviceInfo.buildHost)
|
||
// ToolsHelper.log('buildTime-----', deviceInfo.buildTime)
|
||
// ToolsHelper.log('buildRootHash-----', deviceInfo.buildRootHash)
|
||
// ToolsHelper.log('distributionOSName-----', deviceInfo.distributionOSName)
|
||
// ToolsHelper.log('distributionOSVersion-----', deviceInfo.distributionOSVersion)
|
||
// ToolsHelper.log('distributionOSApiVersion-----', deviceInfo.distributionOSApiVersion)
|
||
// ToolsHelper.log('distributionOSApiName-----', deviceInfo.distributionOSApiName)
|
||
// ToolsHelper.log('distributionOSReleaseType-----', deviceInfo.distributionOSReleaseType)
|
||
}
|
||
|
||
/**
|
||
* 防抖动函数,调用后会延迟wait时间执行,当在wait时间内再次对同一函数调用,则会取消之前的定时器,重新定时
|
||
* @param fun
|
||
* @param wait
|
||
*/
|
||
static throttleHold(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(),
|
||
})
|
||
|
||
}
|
||
|
||
/**
|
||
* 防抖函数(调用会立即触发,在wait时间内不再触发)
|
||
* @param fun
|
||
* @param wait
|
||
*/
|
||
static debounceHold(fun: Function, wait: number = 1500) {
|
||
let funcValue1 = ToolsHelper.getUniqueId(fun)
|
||
let hash = md5_hex(funcValue1)
|
||
const func = ToolsHelper.setTimeOutMap.get(hash)
|
||
if (func) {
|
||
if (func.startTime + func.timeoutNumber <= new Date().getTime()) {
|
||
ToolsHelper.setTimeOutMap.delete(hash)
|
||
} else {
|
||
return
|
||
}
|
||
}
|
||
ToolsHelper.setTimeOutMap.set(hash, {
|
||
timeoutNumber: wait,
|
||
startTime: new Date().getTime(),
|
||
})
|
||
// 执行函数调用
|
||
fun()
|
||
// 拦截在wait期间的函数再次调用,在超时后,将限制解除
|
||
setTimeout(() => {
|
||
ToolsHelper.setTimeOutMap.get(hash) && clearTimeout(ToolsHelper.setTimeOutMap.get(hash)?.timeoutNumber)
|
||
ToolsHelper.setTimeOutMap.delete(hash)
|
||
}, wait)
|
||
}
|
||
|
||
static toString(arrayBuffer: ArrayBuffer) {
|
||
let decoder = util.TextDecoder.create('utf-8');
|
||
return decoder.decodeToString(new Uint8Array(arrayBuffer))
|
||
}
|
||
|
||
static stringToArrayBuffer(str: string): ArrayBuffer {
|
||
let buf = buffer.from(str, 'utf-8'); // 使用 UTF-8 编码
|
||
return buf.buffer;
|
||
}
|
||
|
||
private static setTimeOutMap: Map<string, ThrottleInterface> = new Map()
|
||
private static uniqueIdMap = new WeakMap<Function, string>();
|
||
|
||
public static getUuid() {
|
||
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())
|
||
if (!ToolsHelper.uniqueIdMap.has(fun)) {
|
||
ToolsHelper.uniqueIdMap.set(fun, ToolsHelper.getUuid());
|
||
}
|
||
return ToolsHelper.uniqueIdMap.get(fun)!;
|
||
}
|
||
}
|
||
|