ToolsHelper.ets 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. import promptAction from '@ohos.promptAction';
  2. import { BusinessError, deviceInfo } from '@kit.BasicServicesKit';
  3. import { HashMap } from '@kit.ArkTS';
  4. import { DeviceInfo } from '../bean/DeviceInfo';
  5. import { common } from '@kit.AbilityKit';
  6. import { md5_hex } from '../util/md5';
  7. export interface Btn {
  8. text?: string | Resource;
  9. color?: string | Resource;
  10. onClick?: () => void
  11. }
  12. export interface AlertOptions {
  13. title?: string,
  14. msg?: string,
  15. action?: Btn
  16. }
  17. export interface ConfirmOptions {
  18. title?: string
  19. msg?: string
  20. confirm?: Btn
  21. cancel?: Btn
  22. }
  23. export interface ListOptions<T> {
  24. title?: string
  25. cancel?: Btn
  26. values: Array<T>
  27. onSelected: (index: number, value: T) => void
  28. onError?: (msg: string) => void
  29. }
  30. interface ListItem {
  31. content: string
  32. }
  33. @Builder
  34. function customDialogBuilder<T>(option: ListOptions<T>, dialogTag: string) {
  35. Column() {
  36. Text(option.title)
  37. .fontSize(13)
  38. .textAlign(TextAlign.Center)
  39. .width('60%')
  40. .maxLines(2)
  41. .ellipsisMode(EllipsisMode.END)
  42. .textOverflow({
  43. overflow: TextOverflow.Ellipsis
  44. })
  45. .visibility(option.title ? Visibility.Visible : Visibility.None)
  46. List({ space: 20, initialIndex: 0 }) {
  47. ForEach(option.values, (item: T, index: number) => {
  48. ListItem() {
  49. Text(typeof item === "string" ? item : (item as ListItem).content)
  50. .width('100%')
  51. .fontSize(16)
  52. .textAlign(TextAlign.Center)
  53. .onClick(() => {
  54. if (ToolsHelper.mapDialog.get(dialogTag)) {
  55. promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogTag))
  56. ToolsHelper.mapDialog.remove(dialogTag)
  57. }
  58. option.onSelected(index, item)
  59. })
  60. }
  61. }, (item: string) => item)
  62. }
  63. .listDirection(Axis.Vertical) // 排列方向
  64. .scrollBar(BarState.Off)
  65. .friction(0.6)
  66. .divider({
  67. strokeWidth: 1,
  68. color: 0xEEEEEE,
  69. startMargin: 20,
  70. endMargin: 20
  71. }) // 每行之间的分界线
  72. .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring
  73. .width('100%')
  74. .height(option.values.length < 8 ? `${option.values.length / 16 * 100}%` : '50%')
  75. .margin({ top: 20 })
  76. }
  77. .padding({
  78. top: 20,
  79. bottom: 20,
  80. left: 20,
  81. right: 20
  82. })
  83. }
  84. interface ThrottleInterface {
  85. startTime: number; //调用的时间
  86. timeoutNumber: number; //setTimeout的句柄
  87. }
  88. /**
  89. * 常用方法
  90. */
  91. export class ToolsHelper {
  92. /**
  93. * 弹出Toast
  94. * @param msg
  95. */
  96. static log(...args: ESObject[]) {
  97. const k = ToolsHelper.getStackKey()?.split('/')
  98. console.log(`========>${k ? k[k.length-1].split('.')[0] : ''}::`, args, '\n')
  99. }
  100. /**
  101. * 弹出Toast
  102. * @param msg
  103. */
  104. static showMessage(msg: string) {
  105. console.info(msg);
  106. promptAction.showToast({
  107. message: msg,
  108. duration: 1500
  109. });
  110. }
  111. private static oTime: number = 0
  112. /**
  113. * 双击退出
  114. * @param msg
  115. */
  116. static doubleAndExit(event?: () => void) {
  117. const cTime = new Date().getTime()
  118. console.log('=====>', cTime)
  119. console.log('=====>', cTime - ToolsHelper.oTime)
  120. if (cTime - ToolsHelper.oTime > 800) {
  121. ToolsHelper.oTime = cTime
  122. ToolsHelper.showMessage('双击退出')
  123. } else {
  124. if (event) {
  125. event()
  126. } else {
  127. (getContext() as common.UIAbilityContext).terminateSelf()
  128. // getContext().getApplicationContext().killAllProcesses();
  129. }
  130. }
  131. return true
  132. }
  133. /**kio9
  134. * 弹出Alert弹窗
  135. * @param options
  136. */
  137. static showAlertDialog(options: AlertOptions) {
  138. try {
  139. promptAction.showDialog({
  140. alignment: DialogAlignment.Center,
  141. title: options.title,
  142. message: options.msg,
  143. buttons: [{
  144. text: options.action?.text ?? "确定",
  145. color: options.action?.color ?? "#000000",
  146. }]
  147. })
  148. .then(() => {
  149. options.action?.onClick && options.action?.onClick()
  150. })
  151. .catch((err: Error) => {
  152. ToolsHelper.showMessage(err.message)
  153. })
  154. } catch (error) {
  155. let message = (error as BusinessError).message
  156. ToolsHelper.showMessage(message)
  157. }
  158. }
  159. /**
  160. * 弹出Confirm弹窗
  161. * @param options
  162. */
  163. static showConfirmDialog(options: ConfirmOptions) {
  164. try {
  165. promptAction.showDialog({
  166. alignment: 1,
  167. title: options.title,
  168. message: options.msg,
  169. buttons: [{
  170. text: options.confirm?.text ?? "确定",
  171. color: options.confirm?.color ?? "#000000",
  172. }, {
  173. text: options.cancel?.text ?? "取消",
  174. color: options.cancel?.color ?? "#666666",
  175. }]
  176. })
  177. .then((data) => {
  178. if (data.index === 0) {
  179. options.confirm?.onClick && options.confirm.onClick()
  180. } else {
  181. options.cancel?.onClick && options.cancel.onClick()
  182. }
  183. })
  184. .catch((err: Error) => {
  185. ToolsHelper.showMessage(err.message)
  186. })
  187. } catch (error) {
  188. let message = (error as BusinessError).message
  189. ToolsHelper.showMessage(message)
  190. }
  191. }
  192. public static mapDialog = new HashMap<string, number>()
  193. /**
  194. * 弹出List弹窗
  195. * @param options values 如果是非string列表的话,需要存在content字段
  196. */
  197. static showListDialog<T = string>(options: ListOptions<T>, p: object) {
  198. let isSuccess: Array<number> = []
  199. options.values.forEach((item, index) => {
  200. if (typeof item !== 'string') {
  201. if (!(item as ListItem).content) {
  202. isSuccess.push(index)
  203. }
  204. }
  205. })
  206. if (isSuccess.length > 0) {
  207. options.onError && options.onError(`第(${isSuccess.join("、")})个数据中,没有content字段。`)
  208. } else {
  209. const dialogTag = ToolsHelper.getUuid()
  210. promptAction.openCustomDialog({
  211. alignment: 1,
  212. builder: customDialogBuilder.bind(p, options, dialogTag)
  213. }).then((dialogId: number) => {
  214. ToolsHelper.mapDialog.set(dialogTag, dialogId)
  215. })
  216. }
  217. }
  218. /**
  219. * 弹出自定义弹窗
  220. * @param alignment 弹窗在竖直方向上的对齐方式
  221. */
  222. static showCustomDialog(dialogTag: string, b: CustomBuilder, alignment?: DialogAlignment) {
  223. promptAction.openCustomDialog({
  224. alignment: alignment ?? DialogAlignment.Center,
  225. builder: b
  226. }).then((dialogId: number) => {
  227. ToolsHelper.mapDialog.set(dialogTag, dialogId)
  228. }).catch((error: Error) => {
  229. console.log('>>>>>', JSON.stringify(error))
  230. })
  231. }
  232. /**
  233. * 关闭自定义弹窗
  234. * @param dialogTag 开启时的tag
  235. */
  236. static closeCustomDialog(dialogTag: string) {
  237. if (ToolsHelper.mapDialog.get(dialogTag)) {
  238. promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogTag))
  239. ToolsHelper.mapDialog.remove(dialogTag)
  240. }
  241. }
  242. /**
  243. * 获取调用栈第一个类
  244. */
  245. static getStackKey() {
  246. let stack = new Error().stack
  247. if (stack) {
  248. let list = JSON.stringify(stack).split('\\n')
  249. let a = list[list.length-2].split(':')[0].split('(')[1]
  250. return a
  251. }
  252. return undefined
  253. }
  254. private static deviceInfo: DeviceInfo
  255. /**
  256. * 获取设备信息
  257. * @returns {@link DeviceInfo}
  258. */
  259. static getDeviceInfo() {
  260. if (!ToolsHelper.deviceInfo) {
  261. ToolsHelper.deviceInfo = new DeviceInfo()
  262. ToolsHelper.deviceInfo.ODID = deviceInfo.ODID
  263. ToolsHelper.deviceInfo.manufacture = deviceInfo.manufacture
  264. ToolsHelper.deviceInfo.brand = deviceInfo.brand
  265. ToolsHelper.deviceInfo.osFullName = deviceInfo.osFullName
  266. }
  267. return ToolsHelper.deviceInfo
  268. }
  269. /**
  270. * 防抖动函数,调用后会延迟wait时间执行,当在wait时间内再次对同一函数调用,则会取消之前的定时器,重新定时
  271. * @param fun
  272. * @param wait
  273. */
  274. static debounceHold(fun: Function, wait: number = 1500) {
  275. let funcValue1 = ToolsHelper.getUniqueId(fun)
  276. let hash = md5_hex(funcValue1)
  277. if (ToolsHelper.setTimeOutMap.get(hash)) {
  278. clearTimeout(ToolsHelper.setTimeOutMap.get(hash)?.timeoutNumber)
  279. ToolsHelper.setTimeOutMap.delete(hash)
  280. }
  281. // ToolsHelper.checkTimeOutNumber()
  282. let timeoutNumber = setTimeout(() => {
  283. ToolsHelper.setTimeOutMap.get(hash) && clearTimeout(ToolsHelper.setTimeOutMap.get(hash)?.timeoutNumber)
  284. ToolsHelper.setTimeOutMap.delete(hash)
  285. // 执行函数调用
  286. fun()
  287. }, wait)
  288. ToolsHelper.setTimeOutMap.set(hash, {
  289. timeoutNumber: timeoutNumber,
  290. startTime: new Date().getTime(),
  291. })
  292. }
  293. private static setTimeOutMap: Map<string, ThrottleInterface> = new Map()
  294. private static uniqueIdMap = new WeakMap<Function, string>();
  295. public static getUuid() {
  296. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
  297. let r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
  298. return v.toString(16);
  299. });
  300. }
  301. private static getUniqueId(fun: Function): string {
  302. if (!ToolsHelper.uniqueIdMap.has(fun)) {
  303. ToolsHelper.uniqueIdMap.set(fun, ToolsHelper.getUuid());
  304. }
  305. return ToolsHelper.uniqueIdMap.get(fun)!;
  306. }
  307. }