ToolsHelper.ets 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. export interface Btn {
  7. text?: string | Resource;
  8. color?: string | Resource;
  9. onClick: () => void
  10. }
  11. export interface AlertOptions {
  12. title?: string
  13. msg?: string
  14. action: Btn
  15. }
  16. export interface ConfirmOptions {
  17. title?: string
  18. msg?: string
  19. confirm: Btn
  20. cancel: Btn
  21. }
  22. export interface ListOptions<T> {
  23. title?: string
  24. cancel?: Btn
  25. values: Array<T>
  26. onSelected: (index: number, value: T) => void
  27. onError?: (msg: string) => void
  28. }
  29. interface ListItem {
  30. content: string
  31. }
  32. @Builder
  33. function customDialogBuilder<T>(option: ListOptions<T>, dialogId: number) {
  34. Column() {
  35. Text(option.title)
  36. .fontSize(13)
  37. .textAlign(TextAlign.Center)
  38. .width('60%')
  39. .maxLines(2)
  40. .ellipsisMode(EllipsisMode.END)
  41. .textOverflow({
  42. overflow: TextOverflow.Ellipsis
  43. })
  44. .visibility(option.title ? Visibility.Visible : Visibility.None)
  45. List({ space: 20, initialIndex: 0 }) {
  46. ForEach(option.values, (item: T, index: number) => {
  47. ListItem() {
  48. Text(typeof item === "string" ? item : (item as ListItem).content)
  49. .width('100%')
  50. .fontSize(16)
  51. .textAlign(TextAlign.Center)
  52. .onClick(() => {
  53. if (ToolsHelper.mapDialog.get(dialogId)) {
  54. promptAction.closeCustomDialog(ToolsHelper.mapDialog.get(dialogId))
  55. ToolsHelper.mapDialog.remove(dialogId)
  56. }
  57. option.onSelected(index, item)
  58. })
  59. }
  60. }, (item: string) => item)
  61. }
  62. .listDirection(Axis.Vertical) // 排列方向
  63. .scrollBar(BarState.Off)
  64. .friction(0.6)
  65. .divider({
  66. strokeWidth: 1,
  67. color: 0xEEEEEE,
  68. startMargin: 20,
  69. endMargin: 20
  70. }) // 每行之间的分界线
  71. .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring
  72. .width('100%')
  73. .height(option.values.length < 8 ? `${option.values.length / 16 * 100}%` : '50%')
  74. .margin({ top: 20 })
  75. }
  76. .padding({
  77. top: 20,
  78. bottom: 20,
  79. left: 20,
  80. right: 20
  81. })
  82. }
  83. /**
  84. * 常用方法
  85. */
  86. export class ToolsHelper {
  87. /**
  88. * 弹出Toast
  89. * @param msg
  90. */
  91. static log(...args: ESObject[]) {
  92. const k = ToolsHelper.getStackKey()?.split('/')
  93. console.log(`========>${k?k[k.length-1].split('.')[0]:''}::`, args,'\n')
  94. }
  95. /**
  96. * 弹出Toast
  97. * @param msg
  98. */
  99. static showMessage(msg: string) {
  100. console.info(msg);
  101. promptAction.showToast({
  102. message: msg,
  103. duration: 1500
  104. });
  105. }
  106. private static oTime: number = 0
  107. /**
  108. * 双击退出
  109. * @param msg
  110. */
  111. static doubleAndExit() {
  112. const cTime = new Date().getTime()
  113. console.log('=====>', cTime)
  114. console.log('=====>', cTime - ToolsHelper.oTime)
  115. if (cTime - ToolsHelper.oTime > 800) {
  116. ToolsHelper.oTime = cTime
  117. ToolsHelper.showMessage('双击退出')
  118. } else {
  119. // getContext().getApplicationContext().killAllProcesses();
  120. (getContext() as common.UIAbilityContext).terminateSelf()
  121. }
  122. return true
  123. }
  124. /**kio9
  125. * 弹出Alert弹窗
  126. * @param options
  127. */
  128. static showAlertDialog(options: AlertOptions) {
  129. try {
  130. promptAction.showDialog({
  131. alignment: 1,
  132. title: options.title,
  133. message: options.msg,
  134. buttons: [{
  135. text: options.action.text ?? "确定",
  136. color: options.action.color ?? "#000000",
  137. }]
  138. })
  139. .then(() => {
  140. options.action.onClick()
  141. })
  142. .catch((err: Error) => {
  143. ToolsHelper.showMessage(err.message)
  144. })
  145. } catch (error) {
  146. let message = (error as BusinessError).message
  147. ToolsHelper.showMessage(message)
  148. }
  149. }
  150. /**
  151. * 弹出Confirm弹窗
  152. * @param options
  153. */
  154. static showConfirmDialog(options: ConfirmOptions) {
  155. try {
  156. promptAction.showDialog({
  157. alignment: 1,
  158. title: options.title,
  159. message: options.msg,
  160. buttons: [{
  161. text: options.confirm.text ?? "确定",
  162. color: options.confirm.color ?? "#000000",
  163. }, {
  164. text: options.cancel.text ?? "取消",
  165. color: options.cancel.color ?? "#666666",
  166. }]
  167. })
  168. .then((data) => {
  169. if (data.index === 0) {
  170. options.confirm.onClick()
  171. } else {
  172. options.cancel.onClick()
  173. }
  174. })
  175. .catch((err: Error) => {
  176. ToolsHelper.showMessage(err.message)
  177. })
  178. } catch (error) {
  179. let message = (error as BusinessError).message
  180. ToolsHelper.showMessage(message)
  181. }
  182. }
  183. public static mapDialog = new HashMap<number, number>()
  184. /**
  185. * 弹出List弹窗
  186. * @param options values 如果是非string列表的话,需要存在content字段
  187. */
  188. static showListDialog<T = string>(options: ListOptions<T>, p: object) {
  189. let isSuccess: Array<number> = []
  190. options.values.forEach((item, index) => {
  191. if (typeof item !== 'string') {
  192. if (!(item as ListItem).content) {
  193. isSuccess.push(index)
  194. }
  195. }
  196. })
  197. if (isSuccess.length > 0) {
  198. options.onError && options.onError(`第(${isSuccess.join("、")})个数据中,没有content字段。`)
  199. } else {
  200. const dialogTag = new Date().getTime()
  201. promptAction.openCustomDialog({
  202. alignment: 1,
  203. builder: customDialogBuilder.bind(p, options, dialogTag)
  204. }).then((dialogId: number) => {
  205. ToolsHelper.mapDialog.set(dialogTag, dialogId)
  206. })
  207. }
  208. }
  209. /**
  210. * 弹出自定义弹窗
  211. * @param alignment 弹窗在竖直方向上的对齐方式
  212. */
  213. static showCustomDialog(b: CustomBuilder, alignment?: DialogAlignment) {
  214. const dialogTag = new Date().getTime()
  215. promptAction.openCustomDialog({
  216. alignment: alignment ?? DialogAlignment.Center,
  217. builder: b
  218. }).then((dialogId: number) => {
  219. ToolsHelper.mapDialog.set(dialogTag, dialogId)
  220. }).catch((error: Error) => {
  221. console.log('>>>>>', JSON.stringify(error))
  222. })
  223. }
  224. /**
  225. * 获取调用栈第一个类
  226. */
  227. static getStackKey() {
  228. let stack = new Error().stack
  229. if (stack) {
  230. let list = JSON.stringify(stack).split('\\n')
  231. let a = list[list.length-2].split(':')[0].split('(')[1]
  232. return a
  233. }
  234. return undefined
  235. }
  236. private static deviceInfo: DeviceInfo
  237. /**
  238. * 获取设备信息
  239. * @returns {@link DeviceInfo}
  240. */
  241. static getDeviceInfo() {
  242. if (!ToolsHelper.deviceInfo) {
  243. ToolsHelper.deviceInfo = new DeviceInfo()
  244. ToolsHelper.deviceInfo.ODID = deviceInfo.ODID
  245. ToolsHelper.deviceInfo.manufacture = deviceInfo.manufacture
  246. ToolsHelper.deviceInfo.brand = deviceInfo.brand
  247. ToolsHelper.deviceInfo.osFullName = deviceInfo.osFullName
  248. }
  249. return ToolsHelper.deviceInfo
  250. }
  251. }