@uxda/appkit 1.2.72 → 1.2.75

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 (39) hide show
  1. package/dist/appkit.css +1862 -1559
  2. package/dist/assets/asset-BnRbHhKf +88 -0
  3. package/dist/index.js +3041 -558
  4. package/package.json +2 -1
  5. package/src/balance/api/endpoints.ts +44 -44
  6. package/src/balance/types.ts +42 -42
  7. package/src/components/bt-cropper/index.vue +774 -0
  8. package/src/components/bt-cropper/utils/calcCropper.js +42 -0
  9. package/src/components/bt-cropper/utils/calcImagePosition.js +23 -0
  10. package/src/components/bt-cropper/utils/calcImageSize.js +37 -0
  11. package/src/components/bt-cropper/utils/calcPointDistance.js +12 -0
  12. package/src/components/bt-cropper/utils/calcRightAndBottom.js +7 -0
  13. package/src/components/bt-cropper/utils/ratio.js +3 -0
  14. package/src/components/bt-cropper/utils/tools.js +25 -0
  15. package/src/components/dd-search/index.vue +3 -3
  16. package/src/index.ts +1 -0
  17. package/src/notice/components/NoticeBanner.vue +1 -1
  18. package/src/notice/components/NoticeList.vue +4 -4
  19. package/src/notice/components/index.ts +1 -2
  20. package/src/shared/components/DeviceVersion.vue +3 -2
  21. package/src/shared/composables/index.ts +3 -0
  22. package/src/shared/composables/useCountdown.ts +46 -0
  23. package/src/shared/composables/useDragBox.ts +88 -0
  24. package/src/shared/composables/useEncode.ts +43 -0
  25. package/src/shared/composables/useValidator.ts +31 -0
  26. package/src/shared/http/Http.ts +4 -3
  27. package/src/user/api/endpoints.ts +17 -0
  28. package/src/user/api/index.ts +86 -0
  29. package/src/{notice → user}/components/LoginSetting.vue +1 -0
  30. package/src/user/components/UserBinding.vue +300 -0
  31. package/src/user/components/UserBindingSuccess.vue +80 -0
  32. package/src/user/components/UserEntry.vue +129 -0
  33. package/src/user/components/UserFeedback.vue +410 -0
  34. package/src/user/components/UserFeedbackEntry.vue +137 -0
  35. package/src/user/components/UserHeadCrop.vue +65 -0
  36. package/src/user/components/UserInfo.vue +612 -0
  37. package/src/user/components/UserResourceEmpty.vue +74 -0
  38. package/src/user/components/index.ts +21 -0
  39. package/src/user/index.ts +1 -0
@@ -0,0 +1,42 @@
1
+ import ratio from './ratio'
2
+ import calcRightAndBottom from './calcRightAndBottom'
3
+ const defaultImagePosition = {
4
+ left: 0,
5
+ top: 0,
6
+ width: 9,
7
+ height: 16
8
+ }
9
+ const defaultTarget = {
10
+ width: 2,
11
+ height: 1
12
+ }
13
+ /**
14
+ * 计算初始的裁剪框位置
15
+ * @param {*} imagePosition
16
+ * @param {*} target
17
+ */
18
+ export default function (imagePosition = defaultImagePosition, target = defaultTarget) {
19
+ const cropperPosition = {
20
+ left: 0,
21
+ right: 0,
22
+ top: 0,
23
+ bottom: 0,
24
+ width: 0,
25
+ height: 0
26
+ }
27
+ const targetRatio = ratio(target.width, target.height)
28
+ const imageRatio = ratio(imagePosition.width, imagePosition.height)
29
+ if (targetRatio > imageRatio) {
30
+ cropperPosition.width = imagePosition.width
31
+ cropperPosition.height = cropperPosition.width / targetRatio
32
+ cropperPosition.left = imagePosition.left
33
+ cropperPosition.top = (imagePosition.height - cropperPosition.height) / 2 + imagePosition.top
34
+ } else {
35
+ cropperPosition.height = imagePosition.height
36
+ cropperPosition.width =
37
+ targetRatio === 0 ? imagePosition.width : cropperPosition.height * targetRatio
38
+ cropperPosition.left = (imagePosition.width - cropperPosition.width) / 2 + imagePosition.left
39
+ cropperPosition.top = imagePosition.top
40
+ }
41
+ return calcRightAndBottom(cropperPosition)
42
+ }
@@ -0,0 +1,23 @@
1
+ import calcRightAndBottom from './calcRightAndBottom'
2
+ const defaultPosition = {
3
+ left: 0,
4
+ top: 0,
5
+ width: 0,
6
+ height: 0
7
+ }
8
+ const defaultTransfrom = {
9
+ imgTranslateX: 0,
10
+ imgTranslateY: 0,
11
+ imgScale: 1
12
+ }
13
+ // 先默认变换原点在中间
14
+ export default function (imagePosition = defaultPosition, transfrom = defaultTransfrom) {
15
+ const width = imagePosition.width * transfrom.imgScale
16
+ const height = imagePosition.height * transfrom.imgScale
17
+ return calcRightAndBottom({
18
+ left: imagePosition.left + transfrom.imgTranslateX - (width - imagePosition.width) / 2,
19
+ top: imagePosition.top + transfrom.imgTranslateY - (height - imagePosition.height) / 2,
20
+ width,
21
+ height
22
+ })
23
+ }
@@ -0,0 +1,37 @@
1
+ import ratio from './ratio.js'
2
+ export default async function (
3
+ imageInfo,
4
+ container = {
5
+ width: 9,
6
+ height: 16
7
+ }
8
+ ) {
9
+ const defaultcontainer = {
10
+ width: 9,
11
+ height: 16
12
+ }
13
+ if (!container) {
14
+ container = defaultcontainer
15
+ }
16
+ const containerRatio = ratio(container.width, container.height)
17
+ const imageRatio = ratio(imageInfo.width, imageInfo.height)
18
+ if (containerRatio > imageRatio) {
19
+ const width = container.height * imageRatio
20
+ const height = container.height
21
+ return {
22
+ width,
23
+ height,
24
+ left: (container.width - width) / 2,
25
+ top: 0
26
+ }
27
+ } else {
28
+ const width = container.width
29
+ const height = container.width / imageRatio
30
+ return {
31
+ width,
32
+ height,
33
+ left: 0,
34
+ top: (container.height - height) / 2
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 计算两点之间距离
3
+ * @param {*} point1
4
+ * @param {*} point2
5
+ */
6
+ export default function (point1 = [0, 0], point2 = [0, 0]) {
7
+ const X1 = point1[0],
8
+ X2 = point2[0],
9
+ Y1 = point1[1],
10
+ Y2 = point2[1]
11
+ return Math.sqrt(Math.pow(X1 - X2, 2) + Math.pow(Y1 - Y2, 2))
12
+ }
@@ -0,0 +1,7 @@
1
+ export default function (position) {
2
+ return {
3
+ ...position,
4
+ right: position.left + position.width,
5
+ bottom: position.top + position.height
6
+ }
7
+ }
@@ -0,0 +1,3 @@
1
+ export default function (width = 2, height = 1) {
2
+ return width / height
3
+ }
@@ -0,0 +1,25 @@
1
+ export function getTouchPoints(touchs) {
2
+ return Array.from(touchs).map((ev) => {
3
+ return [ev.clientX, ev.clientY]
4
+ })
5
+ }
6
+ export function debounce(fn, wait = 200) {
7
+ var timer = null
8
+ console.log('debounce')
9
+ return function () {
10
+ if (timer !== null) {
11
+ clearTimeout(timer)
12
+ }
13
+ timer = setTimeout(fn, wait)
14
+ }
15
+ }
16
+
17
+ /**
18
+ * @description 睡眠
19
+ * @param {number} time 等待时间毫秒数
20
+ */
21
+ export function sleep(time = 200) {
22
+ return new Promise((resolve) => {
23
+ setTimeout(resolve, time)
24
+ })
25
+ }
@@ -119,7 +119,7 @@ const isFoucs = ref(props.focus)
119
119
  }
120
120
  &.focus {
121
121
  .dd-search__form {
122
- border-color: #017fff;
122
+ border-color: var(--app-primary-color, #017fff);
123
123
  }
124
124
  }
125
125
  &__placeholder {
@@ -143,7 +143,7 @@ const isFoucs = ref(props.focus)
143
143
  width: 100%;
144
144
  box-sizing: border-box;
145
145
  padding: 0 10px;
146
- caret-color: #017fff;
146
+ caret-color: var(--app-primary-color, #017fff);
147
147
  }
148
148
  &__prefix,
149
149
  &__suffix {
@@ -155,7 +155,7 @@ const isFoucs = ref(props.focus)
155
155
  line-height: 33px;
156
156
  padding: 0 10px;
157
157
  font-size: 16px;
158
- color: #017fff;
158
+ color: var(--app-primary-color, #017fff);
159
159
  }
160
160
  &.disabled &__suffix {
161
161
  display: none;
package/src/index.ts CHANGED
@@ -85,4 +85,5 @@ export * from './balance'
85
85
  export * from './shared'
86
86
  export * from './register'
87
87
  export * from './notice'
88
+ export * from './user'
88
89
  export { type AppKitOptions }
@@ -236,7 +236,7 @@ const emits = defineEmits(['detail', 'close', 'view', 'popup'])
236
236
  text-align: left;
237
237
  }
238
238
  &-btn {
239
- color: #017fff;
239
+ color: var(--app-primary-color, #017fff);
240
240
  padding-left: 6px;
241
241
  }
242
242
  }
@@ -31,7 +31,7 @@
31
31
  <div>
32
32
  <div class="time">{{ formatMinutes(item.receiveTime) }}</div>
33
33
  <div
34
- v-if="showTitle"
34
+ v-if="app !== 'loankit' || (app === 'loankit' && item.title !== item.context)"
35
35
  class="text tit"
36
36
  style="display: flex; align-items: center"
37
37
  :class="{ gray: item.isRead == '1' }"
@@ -85,14 +85,12 @@ const props = withDefaults(
85
85
  app: string
86
86
  userId: string
87
87
  showApp?: boolean
88
- showTitle?: boolean
89
88
  checkBeforeRead?: Function
90
89
  }>(),
91
90
  {
92
91
  app: '',
93
92
  userId: '',
94
93
  showApp: false,
95
- showTitle: true,
96
94
  }
97
95
  )
98
96
 
@@ -134,6 +132,8 @@ function formatMinutes(time: number) {
134
132
  const diffInMinutes = end.diff(start, 'minute')
135
133
  if (diffInMinutes < 60 && diffInMinutes > 0) {
136
134
  return `${diffInMinutes}分钟前`
135
+ } else if (diffInMinutes === 0) {
136
+ return `刚刚`
137
137
  }
138
138
 
139
139
  return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
@@ -289,7 +289,7 @@ const emits = defineEmits(['view'])
289
289
  }
290
290
  &-file {
291
291
  font-size: 10px;
292
- color: #017fff;
292
+ color: var(--app-primary-color, #017fff);
293
293
  opacity: 0.5;
294
294
  }
295
295
  .cue-text {
@@ -1,6 +1,5 @@
1
1
  import NoticeBanner from './NoticeBanner.vue'
2
- import LoginSetting from './LoginSetting.vue'
3
2
  import NoticeEntry from './NoticeEntry.vue'
4
3
  import NoticeList from './NoticeList.vue'
5
4
 
6
- export { NoticeBanner, LoginSetting, NoticeEntry, NoticeList }
5
+ export { NoticeBanner, NoticeEntry, NoticeList }
@@ -14,6 +14,7 @@ import DdNoticeBar from '../../components/dd-notice-bar/index.vue'
14
14
  import { useSafeArea } from '../composables'
15
15
  import Taro from '@tarojs/taro'
16
16
  import { useHttp } from '../../balance/api'
17
+ import debounce from 'lodash/debounce'
17
18
 
18
19
  const showAlert = ref(false)
19
20
  const safeArea = useSafeArea()
@@ -24,7 +25,7 @@ const topStype = computed(() => {
24
25
 
25
26
  const recommendVersions = ref()
26
27
  // 获取系统配置 - 小程序推荐版本
27
- async function getPropertieByCode() {
28
+ const getPropertieByCode = debounce(async () => {
28
29
  if (recommendVersions.value) return
29
30
 
30
31
  const $http = useHttp()
@@ -35,7 +36,7 @@ async function getPropertieByCode() {
35
36
  .then((res: any) => {
36
37
  recommendVersions.value = JSON.parse(res.value || '{}')
37
38
  })
38
- }
39
+ }, 100)
39
40
 
40
41
  onMounted(async () => {
41
42
  await getPropertieByCode()
@@ -1,2 +1,5 @@
1
1
  export * from './useSafeArea'
2
2
  export * from './useTabbar'
3
+ export * from './useCountdown'
4
+ export * from './useValidator'
5
+ export * from './useEncode'
@@ -0,0 +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
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * 元素拖拽功能
3
+ */
4
+ import Taro from '@tarojs/taro'
5
+ import { reactive } from 'vue'
6
+
7
+ export function useDragBox() {
8
+ const dragData = reactive({
9
+ left: 0, // 浮动按钮的左边距
10
+ top: 0, // 浮动按钮的上边距
11
+ width: 0, // 浮动按钮的宽度
12
+ height: 0, // 浮动按钮的高度
13
+ startX: 0, // 手指触摸起始点的横坐标
14
+ startY: 0, // 手指触摸起始点的纵坐标
15
+ screenWidth: 0, // 屏幕宽度
16
+ screenHeight: 0, // 屏幕高度
17
+ isDrag: false, // 是否开始拖拽
18
+ oldLeft: 0,
19
+ })
20
+
21
+ // 初始化元素拖拽模型
22
+ function initDragData(data: any) {
23
+ // 获取屏幕宽度和高度
24
+ const res = Taro.getSystemInfoSync()
25
+ dragData.screenWidth = res.windowWidth
26
+ dragData.screenHeight = res.windowHeight
27
+ if (!data) data = {}
28
+
29
+ const scale = dragData.screenWidth / 375
30
+ dragData.width = data.width * scale || 0
31
+ dragData.height = data.height * scale || 0
32
+ dragData.left = data.left * scale || 0
33
+ dragData.top = data.top * scale || 0
34
+ dragData.oldLeft = data.left * scale || 0
35
+ }
36
+
37
+ // 触屏开始
38
+ function onDragStart(event: any) {
39
+ dragData.startX = event.touches[0].clientX
40
+ dragData.startY = event.touches[0].clientY
41
+ dragData.isDrag = true
42
+ }
43
+
44
+ // 触屏移动
45
+ function onDragMove(event: any) {
46
+ const moveX = event.touches[0].clientX - dragData.startX
47
+ const moveY = event.touches[0].clientY - dragData.startY
48
+
49
+ let left = dragData.left + moveX
50
+ let top = dragData.top + moveY
51
+
52
+ // 防止浮动按钮移出屏幕
53
+ if (left < 0) {
54
+ left = 0
55
+ } else if (left > dragData.screenWidth - dragData.width) {
56
+ left = dragData.screenWidth - dragData.width
57
+ }
58
+
59
+ if (top < 0) {
60
+ top = 0
61
+ } else if (top > dragData.screenHeight - dragData.height) {
62
+ top = dragData.screenHeight - dragData.height
63
+ }
64
+
65
+ dragData.left = left
66
+ dragData.top = top
67
+
68
+ dragData.startX = event.touches[0].clientX
69
+ dragData.startY = event.touches[0].clientY
70
+
71
+ // 阻止页面滚动
72
+ event.preventDefault()
73
+ }
74
+
75
+ // 触屏结束
76
+ function onDragEnd() {
77
+ dragData.isDrag = false
78
+ dragData.left = dragData.oldLeft
79
+ }
80
+
81
+ return {
82
+ dragData,
83
+ initDragData,
84
+ onDragStart,
85
+ onDragMove,
86
+ onDragEnd,
87
+ }
88
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @description: 脱敏相关方法
3
+ */
4
+
5
+ export function useEncode() {
6
+ // 姓名脱敏
7
+ function encodeName(name: string) {
8
+ name = name.trim()
9
+ if (name.length > 2) {
10
+ return name[0].padEnd(name.length - 1, '*') + (name[name.length - 1] || '')
11
+ }
12
+ if (name.length == 0) {
13
+ return ''
14
+ } else {
15
+ return name[0].padEnd(name.length, '*')
16
+ }
17
+ }
18
+
19
+ // 证件脱敏
20
+ function encodeCard(card: string) {
21
+ if (card.length === 18) {
22
+ return card.replace(/(\d{6})\d{8}(\d{3}.)/g, '$1********$2')
23
+ } else {
24
+ return card
25
+ }
26
+ }
27
+
28
+ // 手机脱敏
29
+ function encodePhone(phone: string) {
30
+ phone = String(phone)
31
+ if (phone.length === 11) {
32
+ return phone.replace(/(1\d{2})\d{4}(\d{4})/g, '$1****$2')
33
+ } else {
34
+ return phone
35
+ }
36
+ }
37
+
38
+ return {
39
+ encodeName,
40
+ encodeCard,
41
+ encodePhone,
42
+ }
43
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 通用表单校验器
3
+ */
4
+ import { isMobilePhone, isIdentityCard } from 'validator'
5
+
6
+ export function useValidator() {
7
+ // 身份证号码校验
8
+ function certNoValidator(value: unknown) {
9
+ if (!value) {
10
+ return '请输入身份证号'
11
+ } else if (!isIdentityCard(value, 'zh-CN')) {
12
+ return '请输入正确的身份证号码'
13
+ }
14
+ return false
15
+ }
16
+
17
+ // 电话号码校验
18
+ function phoneValidator(value: unknown) {
19
+ if (!value) {
20
+ return '请输入手机号码'
21
+ } else if (!isMobilePhone(value, 'zh-CN')) {
22
+ return '请输入正确的手机号'
23
+ }
24
+ return false
25
+ }
26
+
27
+ return {
28
+ certNoValidator,
29
+ phoneValidator,
30
+ }
31
+ }
@@ -66,9 +66,10 @@ const request: HttpInstance['request'] = <T>(config: HttpRequestConfig) => {
66
66
  // 前端要求分页
67
67
  // 在 endpoints transform 之前格式化分页数据
68
68
  // 并拼装回原 raw 数据
69
- const paging = (config.data as RequestData).page
70
- ? (clientConfig.paging as Paging).transform(raw.data)
71
- : void 0
69
+ const paging =
70
+ config.data && config.data.page
71
+ ? (clientConfig.paging as Paging).transform(raw.data)
72
+ : void 0
72
73
  resolve(
73
74
  paging
74
75
  ? ({
@@ -0,0 +1,17 @@
1
+ import { HttpEndpoints } from '../../shared/http'
2
+
3
+ const endpointsList: HttpEndpoints = {}
4
+
5
+ const endpoints = Object.fromEntries(
6
+ Object.entries(endpointsList).map(([name, def]) => [name, def.path])
7
+ )
8
+
9
+ const translates = Object.fromEntries(
10
+ Object.entries(endpointsList).map(([, def]) => [def.path, def.translate])
11
+ )
12
+
13
+ const transforms = Object.fromEntries(
14
+ Object.entries(endpointsList).map(([, def]) => [def.path, def.transform])
15
+ )
16
+
17
+ export { endpoints, translates, transforms }
@@ -0,0 +1,86 @@
1
+ import Taro from '@tarojs/taro'
2
+ import { HttpRequestConfig, PagingData, PagingParams, ResponseRaw, createHttp } from '../../shared'
3
+ import { translates, transforms } from './endpoints'
4
+ import { useAppKitOptions } from '../../Appkit'
5
+
6
+ /**
7
+ * 小程序端 Http
8
+ * 使用 Taro.request 实现
9
+ */
10
+ const vendor = {
11
+ async request<T>(config: HttpRequestConfig) {
12
+ return new Promise<ResponseRaw<T>>((resolve, reject) => {
13
+ Taro.request({
14
+ url: config.url,
15
+ method: config.method,
16
+ header: config.headers,
17
+ data: config.data,
18
+ })
19
+ .then(({ data }) => {
20
+ resolve({
21
+ status: +data.code,
22
+ message: data.msg,
23
+ data: data.result as T,
24
+ })
25
+ })
26
+ .catch((e: any) => {
27
+ reject(e)
28
+ })
29
+ })
30
+ },
31
+ }
32
+
33
+ function useHttp() {
34
+ const appkitOptions = useAppKitOptions()
35
+ const headers = {
36
+ Token: appkitOptions.tempToken() || appkitOptions.token(),
37
+ Appcode: appkitOptions.app(),
38
+ cookie: `tid=${appkitOptions.tenant()}`,
39
+ gray: appkitOptions.gray ? appkitOptions.gray() : '0',
40
+ }
41
+ /**
42
+ * 传入配置获取 Http instanse
43
+ */
44
+ const $http = createHttp({
45
+ vendor,
46
+ baseUrl: appkitOptions.baseUrl(),
47
+ headers,
48
+ interceptors: [
49
+ (raw) => {
50
+ if (raw.status == 401) {
51
+ appkitOptions[401]()
52
+ return true
53
+ }
54
+ return false
55
+ },
56
+ (raw) => {
57
+ if (raw.status > 500 && raw.status != 51015 && raw.status != 51014) {
58
+ Taro.showToast({
59
+ title: raw.message,
60
+ icon: 'none',
61
+ })
62
+ return true
63
+ }
64
+ return false
65
+ },
66
+ ],
67
+ paging: {
68
+ translate: (params: PagingParams) => ({
69
+ pageNum: params.page,
70
+ pageSize: params.pageSize,
71
+ }),
72
+ transform(data: any): PagingData {
73
+ return {
74
+ totalPages: data.pages,
75
+ }
76
+ },
77
+ },
78
+ translates,
79
+ transforms,
80
+ })
81
+ return $http
82
+ }
83
+
84
+ export { useHttp }
85
+
86
+ export * from './endpoints'
@@ -107,6 +107,7 @@ const emits = defineEmits(['show'])
107
107
  color: #353535;
108
108
  opacity: 0.4;
109
109
  font-size: 12px;
110
+ padding: 0 30px;
110
111
  }
111
112
  }
112
113
  </style>