@uxda/appkit 4.2.24 → 4.2.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/.eslintrc.mjs +7 -7
  2. package/README.md +187 -187
  3. package/babel.config.js +12 -12
  4. package/dist/appkit.css +3 -3
  5. package/dist/index.js +13 -13
  6. package/package.json +79 -79
  7. package/project.config.json +15 -15
  8. package/project.tt.json +13 -13
  9. package/rollup.config.mjs +67 -67
  10. package/src/Appkit.ts +66 -66
  11. package/src/balance/api/endpoints.ts +133 -133
  12. package/src/balance/api/index.ts +106 -106
  13. package/src/balance/components/AccountView.vue +760 -760
  14. package/src/balance/components/BalanceCard.vue +215 -215
  15. package/src/balance/components/BalanceReminder.vue +85 -85
  16. package/src/balance/components/ConsumptionFilter.vue +218 -218
  17. package/src/balance/components/ConsumptionRules.vue +68 -68
  18. package/src/balance/components/DateFilter.vue +250 -250
  19. package/src/balance/components/DateRange.vue +80 -80
  20. package/src/balance/components/ListFilter.vue +62 -62
  21. package/src/balance/components/ListFilterPicker.vue +191 -191
  22. package/src/balance/components/PromoterCard.vue +237 -237
  23. package/src/balance/components/SecondBalance.vue +71 -71
  24. package/src/balance/components/Tip.vue +45 -45
  25. package/src/balance/components/index.ts +8 -8
  26. package/src/balance/types.ts +97 -97
  27. package/src/components/bt-cropper/index.vue +730 -774
  28. package/src/components/bt-cropper/utils/calcCropper.js +42 -42
  29. package/src/components/bt-cropper/utils/calcImagePosition.js +23 -23
  30. package/src/components/bt-cropper/utils/calcImageSize.js +37 -37
  31. package/src/components/bt-cropper/utils/calcPointDistance.js +12 -12
  32. package/src/components/bt-cropper/utils/calcRightAndBottom.js +7 -7
  33. package/src/components/bt-cropper/utils/ratio.js +3 -3
  34. package/src/components/bt-cropper/utils/tools.js +25 -25
  35. package/src/components/dd-area/index.vue +225 -225
  36. package/src/components/dd-icon/doc.md +21 -21
  37. package/src/components/dd-icon/index.vue +23 -23
  38. package/src/components/dd-notice-bar/index.vue +78 -78
  39. package/src/components/dd-search/doc.md +34 -34
  40. package/src/components/dd-search/index.vue +168 -168
  41. package/src/components/dd-selector/index.vue +124 -124
  42. package/src/components/dd-skeleton/doc.md +19 -19
  43. package/src/components/dd-skeleton/index.vue +36 -36
  44. package/src/global.ts +6 -6
  45. package/src/index.ts +89 -89
  46. package/src/main.scss +1 -1
  47. package/src/notice/api/endpoints.ts +17 -17
  48. package/src/notice/api/index.ts +106 -106
  49. package/src/notice/components/NoticeBanner.vue +243 -243
  50. package/src/notice/components/NoticeEntry.vue +99 -99
  51. package/src/notice/components/NoticeList.vue +315 -315
  52. package/src/notice/components/NoticePopup.vue +162 -162
  53. package/src/notice/components/index.ts +5 -5
  54. package/src/notice/components/useCommonList.ts +86 -86
  55. package/src/notice/components/useNotice.ts +35 -35
  56. package/src/notice/index.ts +1 -1
  57. package/src/notice/types.ts +25 -25
  58. package/src/payment/api/config.ts +7 -7
  59. package/src/payment/api/endpoints.ts +103 -103
  60. package/src/payment/api/index.ts +100 -100
  61. package/src/payment/components/AmountPicker.vue +90 -90
  62. package/src/payment/components/RechargeResult.vue +69 -69
  63. package/src/payment/components/RechargeView.vue +155 -155
  64. package/src/payment/components/RightsPicker.vue +105 -105
  65. package/src/payment/components/TradeView.vue +317 -317
  66. package/src/payment/components/UserAgreement.vue +234 -234
  67. package/src/payment/components/index.ts +22 -22
  68. package/src/payment/index.ts +5 -5
  69. package/src/payment/services/index.ts +16 -16
  70. package/src/payment/services/invoke-recharge.ts +25 -25
  71. package/src/payment/services/request-payment.ts +58 -58
  72. package/src/payment/types.ts +28 -28
  73. package/src/register/components/SelfRegistration.vue +233 -233
  74. package/src/register/components/index.ts +2 -2
  75. package/src/shared/components/AppDrawer.vue +54 -54
  76. package/src/shared/components/AppVerify.vue +128 -128
  77. package/src/shared/components/DeviceVersion.vue +63 -68
  78. package/src/shared/components/EmptyView.vue +33 -33
  79. package/src/shared/components/OcrBusinessLicense.vue +130 -130
  80. package/src/shared/components/OcrIcon.vue +202 -202
  81. package/src/shared/components/PageHeader.vue +84 -84
  82. package/src/shared/components/index.ts +8 -8
  83. package/src/shared/composables/index.ts +8 -8
  84. package/src/shared/composables/useAmount.ts +46 -46
  85. package/src/shared/composables/useCountdown.ts +46 -46
  86. package/src/shared/composables/useCrypto.ts +76 -76
  87. package/src/shared/composables/useDragBox.ts +97 -97
  88. package/src/shared/composables/useEncode.ts +43 -43
  89. package/src/shared/composables/useLogger.ts +124 -124
  90. package/src/shared/composables/useSafeArea.ts +46 -46
  91. package/src/shared/composables/useTabbar.ts +24 -24
  92. package/src/shared/composables/useUpload.ts +54 -54
  93. package/src/shared/composables/useValidator.ts +32 -32
  94. package/src/shared/http/Http.ts +136 -136
  95. package/src/shared/http/index.ts +1 -1
  96. package/src/shared/http/types.ts +157 -157
  97. package/src/shared/index.ts +3 -3
  98. package/src/shared/weixin/payment.ts +38 -38
  99. package/src/styles/vars.scss +3 -3
  100. package/src/user/api/endpoints.ts +17 -17
  101. package/src/user/api/index.ts +111 -111
  102. package/src/user/components/LoginSetting.vue +114 -114
  103. package/src/user/components/UserAuth.vue +257 -257
  104. package/src/user/components/UserBinding.vue +307 -307
  105. package/src/user/components/UserBindingSuccess.vue +80 -80
  106. package/src/user/components/UserEntry.vue +133 -133
  107. package/src/user/components/UserFeedback.vue +431 -431
  108. package/src/user/components/UserFeedbackEntry.vue +175 -192
  109. package/src/user/components/UserHeadCrop.vue +65 -65
  110. package/src/user/components/UserInfo.vue +826 -826
  111. package/src/user/components/UserResourceEmpty.vue +75 -75
  112. package/src/user/components/index.ts +23 -23
  113. package/src/user/index.ts +1 -1
  114. package/tsconfig.json +30 -30
  115. package/types/global.d.ts +21 -21
  116. package/types/vue.d.ts +10 -10
@@ -1,85 +1,85 @@
1
- <template>
2
- <div :class="[
3
- 'page-header',
4
- `color-mode-${colorMode}`
5
- ]" :style="cssVars">
6
- <h1 class="page-title" v-if="title">{{ title }}</h1>
7
- <view class="back-button" @click="onBackButtonClick"></view>
8
- <slot></slot>
9
- </div>
10
- </template>
11
-
12
- <script lang="ts" setup>
13
- import { useSafeArea } from '../composables'
14
-
15
-
16
- const safeArea = useSafeArea()
17
-
18
- const cssVars = {
19
- '--top': `${safeArea.status}px`,
20
- '--height': `${safeArea.nav}px`
21
- }
22
-
23
- export type PageHeaderColorMode = 'light' | 'dark'
24
-
25
- export interface PageHeaderProps {
26
- title?: string,
27
- colorMode?: PageHeaderColorMode
28
- }
29
-
30
- const emit = defineEmits<{
31
- (event: 'close'): void
32
- }>()
33
-
34
- withDefaults(
35
- defineProps<PageHeaderProps>(), {
36
- title: '',
37
- colorMode: 'light'
38
- }
39
- )
40
-
41
- const onBackButtonClick = () => {
42
- emit('close')
43
- }
44
- </script>
45
-
46
- <style lang="scss">
47
- .page-header {
48
- display: flex;
49
- position: relative;
50
- align-items: center;
51
- padding-top: var(--top);
52
- min-height: var(--height);
53
-
54
- .page-title {
55
- position: absolute;
56
- font-size: 18px;
57
- height: var(--height);
58
- line-height: var(--height);
59
- top: var(--top);
60
- width: 100%;
61
- text-align: center;
62
- margin: 0;
63
- }
64
-
65
- .back-button {
66
- position: absolute;
67
- top: var(--top);
68
- left: 10px;
69
- width: var(--height);
70
- height: var(--height);
71
- background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIiIGhlaWdodD0iNDIiIHZpZXdCb3g9IjAgMCA0MiA0MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggb3BhY2l0eT0iMC4wMSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjk5OTg3OCA0MUw0MC45OTk5IDQxTDQwLjk5OTkgMUwwLjk5OTg3OCAxTDAuOTk5ODc4IDQxWiIgZmlsbD0iI0Q4RDhEOCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMi45OTMzIDE4Ljk0NzdDMTEuODYzMyAyMC4wMTQ1IDExLjgxMiAyMS43OTU0IDEyLjg3ODggMjIuOTI1NUwyNy45MTA1IDM3LjEzNDVDMjguNjkyNSAzNy44NzM0IDI5LjkyNTUgMzcuODM4NCAzMC42NjQ0IDM3LjA1NjRDMzEuMzY4MSAzNi4zMTE2IDMxLjM2OTkgMzUuMTU3OSAzMC42OTI5IDM0LjQxMTRMMTYuNTAxMiAyMC45OTM5TDMwLjU4NTcgNy42OTc4NUMzMS4zMzA4IDYuOTk0NDkgMzEuMjk4MiA1LjcyNzk1IDMwLjY2NDkgNC45NDQwMkMyOS45NjE2IDQuMTk4OTUgMjguODA5OCA0LjEzMTI5IDI4LjAyNTkgNC43NjQ1MkwxMi45OTMzIDE4Ljk0NzdaIiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPC9zdmc+Cg==");
72
- background-size: 50%;
73
- background-repeat: no-repeat;
74
- background-position: center center;
75
- }
76
-
77
- &.color-mode-dark {
78
- color: var(--text-color-dark-mode, #fff);
79
-
80
- .back-button {
81
- background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIiIGhlaWdodD0iNDIiIHZpZXdCb3g9IjAgMCA0MiA0MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggb3BhY2l0eT0iMC4wMSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjk5OTg0NyA0MUw0MC45OTk4IDQxTDQwLjk5OTggMUwwLjk5OTg0NyAxTDAuOTk5ODQ3IDQxWiIgZmlsbD0iI0Q4RDhEOCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMi45OTM0IDE4Ljk0NzVDMTEuODYzNCAyMC4wMTQzIDExLjgxMjEgMjEuNzk1MiAxMi44Nzg5IDIyLjkyNTJMMjcuOTEwNiAzNy4xMzQzQzI4LjY5MjcgMzcuODczMSAyOS45MjU2IDM3LjgzODIgMzAuNjY0NSAzNy4wNTYyQzMxLjM2ODIgMzYuMzExNCAzMS4zNyAzNS4xNTc2IDMwLjY5MyAzNC40MTExTDE2LjUwMTMgMjAuOTkzNkwzMC41ODU4IDcuNjk3NjFDMzEuMzMwOSA2Ljk5NDI0IDMxLjI5ODMgNS43Mjc3MSAzMC42NjUxIDQuOTQzNzdDMjkuOTYxNyA0LjE5ODcxIDI4LjgwOTkgNC4xMzEwNCAyOC4wMjYgNC43NjQyN0wxMi45OTM0IDE4Ljk0NzVaIiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPC9zdmc+Cg==");
82
- }
83
- }
84
- }
1
+ <template>
2
+ <div :class="[
3
+ 'page-header',
4
+ `color-mode-${colorMode}`
5
+ ]" :style="cssVars">
6
+ <h1 class="page-title" v-if="title">{{ title }}</h1>
7
+ <view class="back-button" @click="onBackButtonClick"></view>
8
+ <slot></slot>
9
+ </div>
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import { useSafeArea } from '../composables'
14
+
15
+
16
+ const safeArea = useSafeArea()
17
+
18
+ const cssVars = {
19
+ '--top': `${safeArea.status}px`,
20
+ '--height': `${safeArea.nav}px`
21
+ }
22
+
23
+ export type PageHeaderColorMode = 'light' | 'dark'
24
+
25
+ export interface PageHeaderProps {
26
+ title?: string,
27
+ colorMode?: PageHeaderColorMode
28
+ }
29
+
30
+ const emit = defineEmits<{
31
+ (event: 'close'): void
32
+ }>()
33
+
34
+ withDefaults(
35
+ defineProps<PageHeaderProps>(), {
36
+ title: '',
37
+ colorMode: 'light'
38
+ }
39
+ )
40
+
41
+ const onBackButtonClick = () => {
42
+ emit('close')
43
+ }
44
+ </script>
45
+
46
+ <style lang="scss">
47
+ .page-header {
48
+ display: flex;
49
+ position: relative;
50
+ align-items: center;
51
+ padding-top: var(--top);
52
+ min-height: var(--height);
53
+
54
+ .page-title {
55
+ position: absolute;
56
+ font-size: 18px;
57
+ height: var(--height);
58
+ line-height: var(--height);
59
+ top: var(--top);
60
+ width: 100%;
61
+ text-align: center;
62
+ margin: 0;
63
+ }
64
+
65
+ .back-button {
66
+ position: absolute;
67
+ top: var(--top);
68
+ left: 10px;
69
+ width: var(--height);
70
+ height: var(--height);
71
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIiIGhlaWdodD0iNDIiIHZpZXdCb3g9IjAgMCA0MiA0MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggb3BhY2l0eT0iMC4wMSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjk5OTg3OCA0MUw0MC45OTk5IDQxTDQwLjk5OTkgMUwwLjk5OTg3OCAxTDAuOTk5ODc4IDQxWiIgZmlsbD0iI0Q4RDhEOCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMi45OTMzIDE4Ljk0NzdDMTEuODYzMyAyMC4wMTQ1IDExLjgxMiAyMS43OTU0IDEyLjg3ODggMjIuOTI1NUwyNy45MTA1IDM3LjEzNDVDMjguNjkyNSAzNy44NzM0IDI5LjkyNTUgMzcuODM4NCAzMC42NjQ0IDM3LjA1NjRDMzEuMzY4MSAzNi4zMTE2IDMxLjM2OTkgMzUuMTU3OSAzMC42OTI5IDM0LjQxMTRMMTYuNTAxMiAyMC45OTM5TDMwLjU4NTcgNy42OTc4NUMzMS4zMzA4IDYuOTk0NDkgMzEuMjk4MiA1LjcyNzk1IDMwLjY2NDkgNC45NDQwMkMyOS45NjE2IDQuMTk4OTUgMjguODA5OCA0LjEzMTI5IDI4LjAyNTkgNC43NjQ1MkwxMi45OTMzIDE4Ljk0NzdaIiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPC9zdmc+Cg==");
72
+ background-size: 50%;
73
+ background-repeat: no-repeat;
74
+ background-position: center center;
75
+ }
76
+
77
+ &.color-mode-dark {
78
+ color: var(--text-color-dark-mode, #fff);
79
+
80
+ .back-button {
81
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIiIGhlaWdodD0iNDIiIHZpZXdCb3g9IjAgMCA0MiA0MiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggb3BhY2l0eT0iMC4wMSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjk5OTg0NyA0MUw0MC45OTk4IDQxTDQwLjk5OTggMUwwLjk5OTg0NyAxTDAuOTk5ODQ3IDQxWiIgZmlsbD0iI0Q4RDhEOCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMi45OTM0IDE4Ljk0NzVDMTEuODYzNCAyMC4wMTQzIDExLjgxMjEgMjEuNzk1MiAxMi44Nzg5IDIyLjkyNTJMMjcuOTEwNiAzNy4xMzQzQzI4LjY5MjcgMzcuODczMSAyOS45MjU2IDM3LjgzODIgMzAuNjY0NSAzNy4wNTYyQzMxLjM2ODIgMzYuMzExNCAzMS4zNyAzNS4xNTc2IDMwLjY5MyAzNC40MTExTDE2LjUwMTMgMjAuOTkzNkwzMC41ODU4IDcuNjk3NjFDMzEuMzMwOSA2Ljk5NDI0IDMxLjI5ODMgNS43Mjc3MSAzMC42NjUxIDQuOTQzNzdDMjkuOTYxNyA0LjE5ODcxIDI4LjgwOTkgNC4xMzEwNCAyOC4wMjYgNC43NjQyN0wxMi45OTM0IDE4Ljk0NzVaIiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMDEiLz4KPC9zdmc+Cg==");
82
+ }
83
+ }
84
+ }
85
85
  </style>
@@ -1,8 +1,8 @@
1
- import AppDrawer from './AppDrawer.vue'
2
- import PageHeader from './PageHeader.vue'
3
- import AppVerify from './AppVerify.vue'
4
- import DeviceVersion from './DeviceVersion.vue'
5
- import OcrIcon from './OcrIcon.vue'
6
- import OcrBusinessLicense from './OcrBusinessLicense.vue'
7
-
8
- export { AppDrawer, PageHeader, DeviceVersion, AppVerify, OcrIcon, OcrBusinessLicense }
1
+ import AppDrawer from './AppDrawer.vue'
2
+ import PageHeader from './PageHeader.vue'
3
+ import AppVerify from './AppVerify.vue'
4
+ import DeviceVersion from './DeviceVersion.vue'
5
+ import OcrIcon from './OcrIcon.vue'
6
+ import OcrBusinessLicense from './OcrBusinessLicense.vue'
7
+
8
+ export { AppDrawer, PageHeader, DeviceVersion, AppVerify, OcrIcon, OcrBusinessLicense }
@@ -1,8 +1,8 @@
1
- export * from './useSafeArea'
2
- export * from './useTabbar'
3
- export * from './useCountdown'
4
- export * from './useValidator'
5
- export * from './useEncode'
6
- export * from './useUpload'
7
- export * from './useCrypto'
8
- export * from './useLogger'
1
+ export * from './useSafeArea'
2
+ export * from './useTabbar'
3
+ export * from './useCountdown'
4
+ export * from './useValidator'
5
+ export * from './useEncode'
6
+ export * from './useUpload'
7
+ export * from './useCrypto'
8
+ export * from './useLogger'
@@ -1,46 +1,46 @@
1
- /**
2
- * 金额通用方法
3
- */
4
-
5
- export function useAmount() {
6
- /**
7
- * 限制数字小数位
8
- */
9
- function limitDecimal(value, precision = 1) {
10
- if (!value) return value
11
-
12
- value = String(value)
13
-
14
- // 限制最多precision位小数
15
- if (value.includes('.')) {
16
- value = value.slice(0, value.indexOf('.') + (precision + 1))
17
- }
18
-
19
- // 移除非数字字符
20
- value = value.replace(/[^0-9.]/g, '')
21
-
22
- // 防止出现多个小数点
23
- value = value.replace(/\.{2,}/g, '.')
24
-
25
- return value
26
- }
27
-
28
- /**
29
- * 格式化金额
30
- */
31
- function formatAmount(value: string | number, digits = 2) {
32
- if (!value) {
33
- return '0'
34
- }
35
-
36
- return value.toLocaleString('en-US', {
37
- minimumFractionDigits: 0,
38
- maximumFractionDigits: digits,
39
- })
40
- }
41
-
42
- return {
43
- limitDecimal,
44
- formatAmount,
45
- }
46
- }
1
+ /**
2
+ * 金额通用方法
3
+ */
4
+
5
+ export function useAmount() {
6
+ /**
7
+ * 限制数字小数位
8
+ */
9
+ function limitDecimal(value, precision = 1) {
10
+ if (!value) return value
11
+
12
+ value = String(value)
13
+
14
+ // 限制最多precision位小数
15
+ if (value.includes('.')) {
16
+ value = value.slice(0, value.indexOf('.') + (precision + 1))
17
+ }
18
+
19
+ // 移除非数字字符
20
+ value = value.replace(/[^0-9.]/g, '')
21
+
22
+ // 防止出现多个小数点
23
+ value = value.replace(/\.{2,}/g, '.')
24
+
25
+ return value
26
+ }
27
+
28
+ /**
29
+ * 格式化金额
30
+ */
31
+ function formatAmount(value: string | number, digits = 2) {
32
+ if (!value) {
33
+ return '0'
34
+ }
35
+
36
+ return value.toLocaleString('en-US', {
37
+ minimumFractionDigits: 0,
38
+ maximumFractionDigits: digits,
39
+ })
40
+ }
41
+
42
+ return {
43
+ limitDecimal,
44
+ formatAmount,
45
+ }
46
+ }
@@ -1,46 +1,46 @@
1
- /**
2
- * @description: 倒计时
3
- * @param {number} time
4
- * @return {*}
5
- */
6
- import { ref, onUnmounted, computed } from 'vue'
7
-
8
- export function useCountdown() {
9
- let timer: any = null
10
- const countdown = ref(60)
11
- const countdownActive = computed(() => countdown.value > 0 && countdown.value < 60)
12
-
13
- const startCountdown = () => {
14
- countdown.value = 60
15
- timer = setInterval(() => {
16
- countdown.value--
17
- if (countdown.value <= 0) {
18
- stopCountdown()
19
- }
20
- }, 1000)
21
- }
22
-
23
- const stopCountdown = () => {
24
- clearInterval(timer)
25
- countdown.value = 60 // 重置倒计时
26
- }
27
-
28
- onUnmounted(() => {
29
- // stopCountdown() // 组件卸载时确保清除定时器
30
- })
31
-
32
- const countdownText = computed(() => {
33
- if (countdown.value === 60) {
34
- return '获取验证码'
35
- } else {
36
- return `重新发送(${countdown.value}s)`
37
- }
38
- })
39
-
40
- return {
41
- countdownActive,
42
- countdownText,
43
- startCountdown,
44
- stopCountdown,
45
- }
46
- }
1
+ /**
2
+ * @description: 倒计时
3
+ * @param {number} time
4
+ * @return {*}
5
+ */
6
+ import { ref, onUnmounted, computed } from 'vue'
7
+
8
+ export function useCountdown() {
9
+ let timer: any = null
10
+ const countdown = ref(60)
11
+ const countdownActive = computed(() => countdown.value > 0 && countdown.value < 60)
12
+
13
+ const startCountdown = () => {
14
+ countdown.value = 60
15
+ timer = setInterval(() => {
16
+ countdown.value--
17
+ if (countdown.value <= 0) {
18
+ stopCountdown()
19
+ }
20
+ }, 1000)
21
+ }
22
+
23
+ const stopCountdown = () => {
24
+ clearInterval(timer)
25
+ countdown.value = 60 // 重置倒计时
26
+ }
27
+
28
+ onUnmounted(() => {
29
+ // stopCountdown() // 组件卸载时确保清除定时器
30
+ })
31
+
32
+ const countdownText = computed(() => {
33
+ if (countdown.value === 60) {
34
+ return '获取验证码'
35
+ } else {
36
+ return `重新发送(${countdown.value}s)`
37
+ }
38
+ })
39
+
40
+ return {
41
+ countdownActive,
42
+ countdownText,
43
+ startCountdown,
44
+ stopCountdown,
45
+ }
46
+ }
@@ -1,77 +1,77 @@
1
- // 解析脱敏姓名、手机号码等
2
-
3
- export type CryptoConfig = {
4
- maskField: string,
5
- secretField: string,
6
- }
7
-
8
- export const defaultCryptoConfig: CryptoConfig = {
9
- maskField: 'mask',
10
- secretField: 'secretKey'
11
- }
12
-
13
- export type DecodeResult<T extends string> = {
14
- [key in T | `${T}Secret`]: string
15
- }
16
-
17
- export type DefaultDecodeResult = DecodeResult<'masked'>
18
-
19
- export type DecodeFunction = (encoded: string, key: string) => DecodeResult<`${key}`>
20
-
21
- /**
22
- * 解析以及解密脱敏数据
23
- * @param config
24
- * @returns
25
- */
26
- export function useCrypto (config?: CryptoConfig) {
27
-
28
- const conf = config || defaultCryptoConfig
29
-
30
- const parse: DecodeFunction = (data: string, key?: string) => {
31
- let k = key || 'masked'
32
- let result: Record<string, any> = {}
33
- try {
34
- result = JSON.parse(data)
35
- result = {
36
- [k]: result.mask,
37
- // 字段后加$表示用于解密的 secret
38
- [`${k}$`]: result.secretKey
39
- }
40
- } catch (e) {}
41
- return result
42
- }
43
-
44
- /**
45
- * 批量解析数组内的数据
46
- * @param list
47
- * @param field
48
- * @returns
49
- */
50
- const resolve = (list: any[], field?: string | string[]) => {
51
- if (list.length === 0) return []
52
- const [first] = list,
53
- f = field
54
- ? Array.isArray(field) ? field : [field]
55
- // 自动探测需要解密的字段
56
- // '{"secretKey":"","mask":""}' 形式
57
- : Object.entries(first)
58
- .filter(([_, v]) => /^\{.*\}$/.test(v as string))
59
- .map(([k]) => k)
60
- return list
61
- .map(item => {
62
- let result = { ...item }
63
- f.forEach(r => {
64
- result = {
65
- ...result,
66
- ...parse(item[r], r)
67
- }
68
- })
69
- return result
70
- })
71
- }
72
-
73
- return {
74
- parse,
75
- resolve,
76
- }
1
+ // 解析脱敏姓名、手机号码等
2
+
3
+ export type CryptoConfig = {
4
+ maskField: string,
5
+ secretField: string,
6
+ }
7
+
8
+ export const defaultCryptoConfig: CryptoConfig = {
9
+ maskField: 'mask',
10
+ secretField: 'secretKey'
11
+ }
12
+
13
+ export type DecodeResult<T extends string> = {
14
+ [key in T | `${T}Secret`]: string
15
+ }
16
+
17
+ export type DefaultDecodeResult = DecodeResult<'masked'>
18
+
19
+ export type DecodeFunction = (encoded: string, key: string) => DecodeResult<`${key}`>
20
+
21
+ /**
22
+ * 解析以及解密脱敏数据
23
+ * @param config
24
+ * @returns
25
+ */
26
+ export function useCrypto (config?: CryptoConfig) {
27
+
28
+ const conf = config || defaultCryptoConfig
29
+
30
+ const parse: DecodeFunction = (data: string, key?: string) => {
31
+ let k = key || 'masked'
32
+ let result: Record<string, any> = {}
33
+ try {
34
+ result = JSON.parse(data)
35
+ result = {
36
+ [k]: result.mask,
37
+ // 字段后加$表示用于解密的 secret
38
+ [`${k}$`]: result.secretKey
39
+ }
40
+ } catch (e) {}
41
+ return result
42
+ }
43
+
44
+ /**
45
+ * 批量解析数组内的数据
46
+ * @param list
47
+ * @param field
48
+ * @returns
49
+ */
50
+ const resolve = (list: any[], field?: string | string[]) => {
51
+ if (list.length === 0) return []
52
+ const [first] = list,
53
+ f = field
54
+ ? Array.isArray(field) ? field : [field]
55
+ // 自动探测需要解密的字段
56
+ // '{"secretKey":"","mask":""}' 形式
57
+ : Object.entries(first)
58
+ .filter(([_, v]) => /^\{.*\}$/.test(v as string))
59
+ .map(([k]) => k)
60
+ return list
61
+ .map(item => {
62
+ let result = { ...item }
63
+ f.forEach(r => {
64
+ result = {
65
+ ...result,
66
+ ...parse(item[r], r)
67
+ }
68
+ })
69
+ return result
70
+ })
71
+ }
72
+
73
+ return {
74
+ parse,
75
+ resolve,
76
+ }
77
77
  }