@uxda/appkit 4.3.13 → 4.3.15

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 (35) hide show
  1. package/COMPONENT_USAGE.md +3 -3
  2. package/dist/appkit.css +12 -105
  3. package/dist/index.js +449 -1060
  4. package/package.json +5 -2
  5. package/src/balance/api/index.ts +1 -1
  6. package/src/balance/components/PromoterCard.vue +0 -1
  7. package/src/notice/api/index.ts +1 -1
  8. package/src/notice/components/NoticeList2.vue +73 -234
  9. package/src/notice/components/useCommonList.ts +0 -1
  10. package/src/payment/api/endpoints.ts +14 -2
  11. package/src/payment/api/index.ts +1 -2
  12. package/src/payment/components/RechargeResult.vue +1 -0
  13. package/src/payment/components/RechargeView.vue +45 -13
  14. package/src/payment/components/TradeView.vue +153 -326
  15. package/src/payment/services/request-payment.ts +0 -2
  16. package/src/payment/types.ts +0 -1
  17. package/src/register/components/SelfRegistration.vue +1 -1
  18. package/src/shared/components/AppVerify.vue +6 -15
  19. package/src/shared/components/OcrBusinessLicense.vue +37 -20
  20. package/src/shared/components/OcrIcon.vue +67 -105
  21. package/src/shared/components/index.ts +1 -3
  22. package/src/shared/composables/index.ts +0 -1
  23. package/src/shared/composables/useDeviceEnv.ts +35 -1
  24. package/src/shared/composables/useUpload.ts +51 -96
  25. package/src/shared/http/Http.ts +0 -1
  26. package/src/shared/tracking/tracking-sdk.ts +1 -0
  27. package/src/shared/weixin/jssdk.ts +0 -1
  28. package/src/user/api/index.ts +1 -1
  29. package/src/user/components/UserAuth.vue +1 -1
  30. package/src/user/components/UserFeedback.vue +0 -1
  31. package/src/user/components/UserInfo.vue +0 -2
  32. package/types/global.d.ts +0 -2
  33. package/src/shared/components/OcrBank.vue +0 -202
  34. package/src/shared/components/OcrInvoice.vue +0 -322
  35. package/src/shared/composables/useCompress.ts +0 -64
@@ -202,7 +202,6 @@ function requestFeedback() {
202
202
 
203
203
  showLoading({
204
204
  title: '反馈中...',
205
- mask: true
206
205
  })
207
206
 
208
207
  const attachment = JSON.parse(
@@ -220,7 +220,6 @@ async function toUpload() {
220
220
  async function updateImage(filePath: string) {
221
221
  showLoading({
222
222
  title: "上传中...",
223
- mask: true
224
223
  });
225
224
  const appkitOptions = useAppKitOptions();
226
225
  const $http = useHttp();
@@ -360,7 +359,6 @@ function toLogout() {
360
359
  title: "提示",
361
360
  content: "确定要退出登录吗?",
362
361
  confirmText: "确定",
363
- confirmColor: '#017fff',
364
362
  success: async (e: any) => {
365
363
  if (e.confirm) {
366
364
  emits("logout");
package/types/global.d.ts CHANGED
@@ -20,5 +20,3 @@ declare namespace NodeJS {
20
20
  declare module '@tarojs/components' {
21
21
  export * from '@tarojs/components/types/index.vue3'
22
22
  }
23
-
24
- declare module '@uxda/nutshell/taro'
@@ -1,202 +0,0 @@
1
- <template>
2
- <div class="ocr-bank" :class="[disabled ? 'disabled' : '']" v-track-click="'银行卡识别-点击'" @click="!customClick ? onUpload() : null">
3
- <slot name="icon">
4
- <ns-icon name="https://cdn.ddjf.com/static/images/beidouxing/ocr-icon.png" />
5
- </slot>
6
- </div>
7
-
8
- <nut-action-sheet v-model:visible="activeSheetVisible" :menu-items="actionSheetMenus" @choose="chooseImages"
9
- cancel-txt="取消" />
10
- </template>
11
-
12
- <script lang="ts" setup>
13
- import Taro, { showToast, showLoading, hideLoading, chooseMedia, chooseMessageFile, uploadFile } from '@tarojs/taro'
14
- import { NsIcon, useNutshell } from '@uxda/nutshell/taro'
15
- import { useAppKitOptions } from '../../Appkit'
16
- import { ref } from 'vue';
17
- import { useHttp } from '../../balance/api'
18
- import { compressImage, getCompressQuality } from '../composables/useUpload'
19
-
20
- const appKitOptions = useAppKitOptions()
21
- const $http = useHttp(),
22
- $n = useNutshell()
23
-
24
- const emits = defineEmits(['complete'])
25
-
26
- type OcrProps = {
27
- disabled?: boolean,
28
- class?: string
29
- uploadUrl?: string
30
- customClick?: boolean
31
- }
32
- type FileType = {
33
- "downloadUrl": string,
34
- "fileId": string,
35
- "fileName": string,
36
- "fileSize": number,
37
- "fileSuffix": string,
38
- "fileType": string,
39
- "originalUrl": string
40
- }
41
-
42
- const props = withDefaults(defineProps<OcrProps>(), {
43
- disabled: false,
44
- class: '',
45
- uploadUrl: '/hkbase/file/uploadFile',
46
- customClick: false
47
- })
48
-
49
- type BankCardType = {
50
- bankCardNumber: string
51
- bankCardType: string
52
- bankName: string
53
- }
54
-
55
- async function onUploadFile(csRes: any) {
56
- try {
57
- let { path, size, tempFilePath } = csRes.tempFiles[0]
58
- const compressImg: any = (await compressImage(path || tempFilePath, getCompressQuality(size))) || {}
59
- const filePath = compressImg.tempFilePath || path
60
-
61
- showLoading({ title: '银行卡识别中..', mask: true })
62
-
63
- const session = appKitOptions.token()
64
- const baseUrl = appKitOptions.baseUrl()
65
- const upRes: any = await uploadFile({
66
- url: baseUrl + props.uploadUrl,
67
- filePath,
68
- name: 'file',
69
- formData: {
70
- objectNo: `min${Date.now()}`,
71
- appCode: appKitOptions.app(),
72
- },
73
- header: {
74
- token: session || '',
75
- },
76
- })
77
-
78
- const res = JSON.parse(upRes.data)
79
- if (res.code === '200') {
80
- await getBankCardInfo(res.result)
81
- } else {
82
- hideLoading()
83
- showToast({
84
- title: res.msg,
85
- icon: 'error',
86
- })
87
- }
88
- } catch (err) {
89
- hideLoading()
90
- console.log(err)
91
- }
92
- }
93
-
94
- // 根据银行卡路径获取银行卡信息
95
- async function getBankCardInfo(file: string | FileType) {
96
- try {
97
- const res: BankCardType = await $http.get('/hkbase/common/bankCard', {
98
- fileUrl: typeof file === 'string' ? file : file.originalUrl,
99
- })
100
- hideLoading()
101
-
102
- if (res && !res.bankCardNumber) {
103
- $n.dialog({
104
- title: '识别失败',
105
- message: `您上传的图片可能不够清晰或与当前功能不符,请重新上传一张清晰、完整的图片。谢谢!`,
106
- okText: '我知道了',
107
- cancelText: '',
108
- })
109
- return
110
- }
111
-
112
- emits('complete', {
113
- ...res,
114
- fileUrl: typeof file === 'string' ? file : file.originalUrl,
115
- fileKey: typeof file === 'string' ? file : file.fileId,
116
- })
117
- } catch (err) {
118
- hideLoading()
119
- }
120
- }
121
-
122
- // 上传图片操作面板
123
- const activeSheetVisible = ref(false)
124
- const actionSheetMenus = [
125
- {
126
- name: '拍摄',
127
- type: 'camera',
128
- },
129
- {
130
- name: '从相册选择',
131
- type: 'album',
132
- },
133
- {
134
- name: '从聊天会话选择',
135
- type: 'message',
136
- },
137
- ]
138
- if (Taro.getEnv() === 'WEB') {
139
- actionSheetMenus.pop()
140
- }
141
-
142
- // 选择图像上传
143
- async function chooseImages(item: any) {
144
- if (['camera', 'album'].includes(item.type)) {
145
- const csRes = await chooseMedia({
146
- count: 1,
147
- sourceType: [item.type], // "camera" | "album"
148
- maxDuration: 60, // 使用duration属性判断是图片还是视频,图片没有该属性
149
- })
150
-
151
- onUploadFile(csRes)
152
- } else {
153
- const csRes = await chooseMessageFile({
154
- count: 1,
155
- type: 'image',
156
- })
157
-
158
- onUploadFile(csRes)
159
- }
160
- }
161
-
162
- async function onUpload() {
163
- if (props.disabled) return
164
-
165
- if (Taro.getEnv() === 'WEB') {
166
- const csRes = await chooseMedia({
167
- count: 1,
168
- sourceType: ['album'], // "camera" | "album"
169
- maxDuration: 60, // 使用duration属性判断是图片还是视频,图片没有该属性
170
- })
171
-
172
- onUploadFile(csRes)
173
- return
174
- }
175
-
176
- activeSheetVisible.value = true
177
- }
178
-
179
- defineExpose({
180
- onUpload
181
- })
182
- </script>
183
-
184
- <style lang="scss">
185
- .ocr-bank {
186
- width: 24px;
187
- height: 24px;
188
- display: inline-flex;
189
- align-items: center;
190
-
191
- .ns-icon {
192
- width: 24px;
193
- height: 24px;
194
- }
195
-
196
- &.disabled {
197
- .ns-icon {
198
- filter: brightness(1.5) grayscale(1);
199
- }
200
- }
201
- }
202
- </style>
@@ -1,322 +0,0 @@
1
- <template>
2
- <div class="ocr-invoice" :class="[disabled ? 'disabled' : '', className]" v-track-click="'发票识别-点击'" @click="!customClick ? onUpload() : null">
3
- <slot name="icon">
4
- <ns-icon name="https://cdn.ddjf.com/static/images/beidouxing/ocr-icon.png"/>
5
- </slot>
6
- </div>
7
-
8
- <nut-action-sheet v-model:visible="activeSheetVisible" :menu-items="actionSheetMenus" @choose="chooseImages"
9
- cancel-txt="取消" />
10
- </template>
11
-
12
- <script lang="ts" setup>
13
- import Taro, { showToast, showLoading, hideLoading, chooseMedia, chooseMessageFile, uploadFile } from '@tarojs/taro'
14
- import { NsIcon, useNutshell } from '@uxda/nutshell/taro'
15
- import { useAppKitOptions } from '../../Appkit'
16
- import { ref } from 'vue';
17
- import { useHttp } from '../../balance/api'
18
- import { compressImage, getCompressQuality } from '../composables/useUpload'
19
-
20
- const appKitOptions = useAppKitOptions()
21
- const $http = useHttp(),
22
- $n = useNutshell()
23
-
24
- const emits = defineEmits(['complete'])
25
-
26
- type OcrProps = {
27
- disabled?: boolean,
28
- side?: 'face' | 'back',
29
- className?: string
30
- customUpload?: Function
31
- uploadUrl?: string
32
- customClick?: boolean
33
- }
34
- type FileType = {
35
- "downloadUrl": string,
36
- "fileId": string,
37
- "fileName": string,
38
- "fileSize": number,
39
- "fileSuffix": string,
40
- "fileType": string,
41
- "originalUrl": string
42
- }
43
-
44
- const props = withDefaults(defineProps<OcrProps>(), {
45
- disabled: false,
46
- side: 'face',
47
- className: '',
48
- uploadUrl: '/hkbase/file/uploadFile',
49
- customClick: false
50
- })
51
-
52
- /**
53
- * 判断文件类型
54
- */
55
- function getFileType(filePath: string, fileName?: string): 'img' | 'pdf' {
56
- const lowerPath = filePath.toLowerCase()
57
- const lowerName = (fileName || '').toLowerCase()
58
-
59
- // 检查文件扩展名
60
- if (lowerPath.endsWith('.pdf') || lowerName.endsWith('.pdf')) {
61
- return 'pdf'
62
- }
63
-
64
- // 检查是否为图片格式
65
- const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
66
- if (imageExtensions.some(ext => lowerPath.endsWith(ext) || lowerName.endsWith(ext))) {
67
- return 'img'
68
- }
69
-
70
- // 默认为图片
71
- return 'img'
72
- }
73
-
74
- async function onUploadFile(csRes: any, fileType?: 'img' | 'pdf') {
75
- try {
76
- let { path, size, tempFilePath, name } = csRes.tempFiles[0]
77
- const originalPath = path || tempFilePath
78
-
79
- // 判断文件类型
80
- const detectedFileType = fileType || getFileType(originalPath, name)
81
-
82
- // 只有图片才进行压缩
83
- let filePath = originalPath
84
- if (detectedFileType === 'img') {
85
- const compressImg: any = (await compressImage(originalPath, getCompressQuality(size))) || {}
86
- filePath = compressImg.tempFilePath || originalPath
87
- }
88
-
89
- if (props.customUpload) {
90
- props.customUpload(filePath, detectedFileType)
91
- return
92
- }
93
-
94
- showLoading({ title: '发票识别中..', mask: true })
95
-
96
- const session = appKitOptions.token()
97
- const baseUrl = appKitOptions.baseUrl()
98
- const upRes: any = await uploadFile({
99
- url: `${baseUrl}${props.uploadUrl}`,
100
- filePath,
101
- name: 'file',
102
- formData: {
103
- objectNo: `min${Date.now()}`,
104
- appCode: appKitOptions.app(),
105
- },
106
- header: {
107
- token: session || '',
108
- },
109
- })
110
-
111
- const res = JSON.parse(upRes.data)
112
- if (res.code === '200') {
113
- await getOcrInfo(res.result, detectedFileType)
114
- } else {
115
- hideLoading()
116
- showToast({
117
- title: res.msg,
118
- icon: 'error',
119
- })
120
- }
121
- } catch (err) {
122
- hideLoading()
123
- console.log(err)
124
- }
125
- }
126
-
127
- // 根据证件路径获取证件信息
128
- async function getOcrInfo(file: string | FileType, fileType: 'img' | 'pdf' = 'img') {
129
- try {
130
- const fileUrl = typeof file === 'string' ? file : file.originalUrl
131
- const res: any = await $http.get('/hkbase/common/vatInvoice', {
132
- fileUrl,
133
- fileType: fileType
134
- })
135
- hideLoading()
136
-
137
- if (!res?.purchaserRegisterNum) {
138
- $n.dialog({
139
- title: '识别失败',
140
- message: `您上传的${fileType === 'pdf' ? '文件' : '图片'}可能不够清晰或与当前功能不符,请重新上传一张清晰、完整的${fileType === 'pdf' ? 'PDF文件' : '图片'}。谢谢!`,
141
- okText: '我知道了',
142
- cancelText: '',
143
- })
144
- return
145
- }
146
-
147
- emits('complete', {
148
- invoiceDate: res?.invoiceDate,
149
- invoiceNum: res?.invoiceNum,
150
- invoiceNumConfirm: res?.invoiceNumConfirm,
151
- invoiceType: res?.invoiceType,
152
- noteDrawer: res?.noteDrawer,
153
- purchaserBank: res?.purchaserBank,
154
- purchaserName: res?.purchaserName,
155
- purchaserRegisterNum: res?.purchaserRegisterNum,
156
- remarks: res?.remarks,
157
- sellerName: res?.sellerName,
158
- sellerRegisterNum: res?.sellerRegisterNum,
159
- serviceType: res?.serviceType,
160
- totalAmount: res?.totalAmount,
161
- totalTax: res?.totalTax,
162
- fileUrl: fileUrl,
163
- fileType: fileType,
164
- fileKey: typeof file === 'string' ? file : file.fileId,
165
- })
166
- } catch (err) {
167
- hideLoading()
168
- }
169
- }
170
-
171
- // 上传图片操作面板
172
- const activeSheetVisible = ref(false)
173
- const actionSheetMenus = [
174
- {
175
- name: '拍摄',
176
- type: 'camera',
177
- },
178
- {
179
- name: '从相册选择',
180
- type: 'album',
181
- },
182
- {
183
- name: '从聊天会话选择',
184
- type: 'message',
185
- },
186
- {
187
- name: '选择文件',
188
- type: 'file',
189
- },
190
- ]
191
- if (Taro.getEnv() === 'WEB') {
192
- // Web 端移除"从聊天会话选择",保留"选择文件"
193
- actionSheetMenus.splice(2, 1)
194
- }
195
-
196
- // 选择图像上传
197
- async function chooseImages(item: any) {
198
- if (['camera', 'album'].includes(item.type)) {
199
- const csRes = await chooseMedia({
200
- count: 1,
201
- sourceType: [item.type], // "camera" | "album"
202
- maxDuration: 60, // 使用duration属性判断是图片还是视频,图片没有该属性
203
- })
204
-
205
- onUploadFile(csRes)
206
- } else if (item.type === 'message') {
207
- const csRes = await chooseMessageFile({
208
- count: 1,
209
- type: 'image',
210
- })
211
-
212
- onUploadFile(csRes)
213
- } else if (item.type === 'file') {
214
- // 选择文件(包括PDF)
215
- const csRes = await chooseMessageFile({
216
- count: 1,
217
- type: 'file',
218
- })
219
-
220
- // 不预先指定类型,让 onUploadFile 根据文件名自动判断
221
- onUploadFile(csRes)
222
- }
223
- }
224
-
225
- /**
226
- * Web 端选择文件(支持图片和PDF)
227
- */
228
- function chooseFileInWeb() {
229
- return new Promise<void>((resolve, reject) => {
230
- const input = document.createElement('input')
231
- input.type = 'file'
232
- input.accept = 'image/*,.pdf'
233
- input.style.display = 'none'
234
-
235
- input.onchange = async (e: any) => {
236
- const file = e.target?.files?.[0]
237
- if (!file) {
238
- document.body.removeChild(input)
239
- resolve()
240
- return
241
- }
242
-
243
- // 根据文件 MIME 类型和扩展名判断文件类型
244
- let fileType: 'img' | 'pdf' = 'img'
245
- if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) {
246
- fileType = 'pdf'
247
- }
248
-
249
- const filePath = URL.createObjectURL(file)
250
-
251
- try {
252
- // 构造类似 chooseMedia 返回的数据结构
253
- const csRes = {
254
- tempFiles: [{
255
- path: filePath,
256
- tempFilePath: filePath,
257
- size: file.size,
258
- name: file.name,
259
- }]
260
- }
261
-
262
- await onUploadFile(csRes, fileType)
263
- resolve()
264
- } catch (error) {
265
- reject(error)
266
- } finally {
267
- document.body.removeChild(input)
268
- // 清理 blob URL
269
- URL.revokeObjectURL(filePath)
270
- }
271
- }
272
-
273
- input.oncancel = () => {
274
- document.body.removeChild(input)
275
- resolve()
276
- }
277
-
278
- document.body.appendChild(input)
279
- input.click()
280
- })
281
- }
282
-
283
- async function onUpload() {
284
- if (props.disabled) return
285
-
286
- if (Taro.getEnv() === 'WEB') {
287
- // Web 端弹出选择:图片或PDF
288
- try {
289
- await chooseFileInWeb()
290
- } catch (err) {
291
- console.error('文件选择失败:', err)
292
- }
293
- return
294
- }
295
-
296
- activeSheetVisible.value = true
297
- }
298
-
299
- defineExpose({
300
- onUpload
301
- })
302
- </script>
303
-
304
- <style lang="scss">
305
- .ocr-invoice {
306
- width: 24px;
307
- height: 24px;
308
- display: inline-flex;
309
- align-items: center;
310
-
311
- .ns-icon {
312
- width: 24px;
313
- height: 24px;
314
- }
315
-
316
- &.disabled {
317
- .ns-icon {
318
- filter: brightness(1.5) grayscale(1);
319
- }
320
- }
321
- }
322
- </style>
@@ -1,64 +0,0 @@
1
- import Taro, { uploadFile } from '@tarojs/taro'
2
- import { Media } from '@uxda/nutshell/taro'
3
- import { useAppKitOptions } from '../../Appkit'
4
-
5
- export type UploadConfig = {
6
- baseUrl: string
7
- name?: string
8
- headers?: Record<string, string>
9
- }
10
-
11
- const mappings: { [x: string]: keyof Media } = {
12
- downloadUrl: 'thrumb',
13
- fileId: 'id',
14
- fileName: 'name',
15
- fileSize: 'size',
16
- fileSuffix: 'ext',
17
- fileType: 'type',
18
- originalUrl: 'url',
19
- }
20
-
21
- const transformFields = (row: any) => {
22
- return Object.fromEntries(Object.entries(row).map(([k, v]) => [mappings[k] || k, v]))
23
- }
24
-
25
- type UploadFunction = (url: string, file: Media) => Promise<Media>
26
-
27
- export const useUpload = (config: UploadConfig) => {
28
- const appkitOptions = useAppKitOptions()
29
-
30
- // 上传文件
31
- const upload: UploadFunction = (url: string, file: Media) => {
32
- return new Promise<Media>((resolve, reject) => {
33
- uploadFile({
34
- url: config.baseUrl + url,
35
- filePath: file.path!,
36
- name: 'file',
37
- formData: {
38
- objectNo: `min${Date.now()}`,
39
- appCode: config.headers?.appcode || appkitOptions.app(),
40
- },
41
- header: {
42
- ...config.headers,
43
- token: appkitOptions.tempToken() || appkitOptions.token(),
44
- },
45
- success: (rsp: any) => {
46
- const { data } = rsp
47
- try {
48
- const response = JSON.parse(data)
49
- console.log('===response', response)
50
- resolve(transformFields(response.result))
51
- } catch (e) {
52
- reject({
53
- message: '文件上传异常',
54
- })
55
- }
56
- },
57
- })
58
- })
59
- }
60
-
61
- return {
62
- upload,
63
- }
64
- }