af-mobile-client-vue3 1.6.41 → 1.6.42
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.
- package/.env +1 -1
- package/package.json +1 -1
- package/src/components/core/ImageUploader/index.vue +4 -0
- package/src/components/core/Signature/AdaptiveSignatureField.vue +172 -172
- package/src/components/data/AttachmentListItem/index.vue +174 -174
- package/src/components/data/OtherCharge/OtherChargeGroupModal.vue +542 -542
- package/src/utils/nativeFilePicker.ts +89 -89
- package/src/views/SafeInspection/SecurityCertificate/index.vue +20 -0
- package/src/views/SafeInspection/SecurityCertificate/photoAiRecognition/components/PhotoCaptureCard.vue +42 -2
- package/src/views/SafeInspection/SecurityFormItem/CameraView/index.vue +4 -0
package/.env
CHANGED
|
@@ -5,7 +5,7 @@ VITE_APP_OUT_DIR=dist_af-library-mobile-web
|
|
|
5
5
|
VITE_APP_VCONSOLE=false
|
|
6
6
|
# 自定义参数
|
|
7
7
|
VITE_APP_WEB_CONFIG_KEY=admin.webconfig
|
|
8
|
-
VITE_APP_SYSTEM_NAME=af-
|
|
8
|
+
VITE_APP_SYSTEM_NAME=af-safecheck
|
|
9
9
|
# 最低兼容性 V4(最新产品)V3(V3产品) OA(公司OA)
|
|
10
10
|
VITE_APP_COMPATIBLE=V4
|
|
11
11
|
VITE_RSA_PRIVATE_KEY=MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIRrmftLDHCQqREEJ132Onu+W3vmFbdF7QD751SrcDDGDTfzuz1zBuElvkHhuDBb7KZkXrCIe+MhvX2IvxcLObl3faX+evYlnfj2HRbF0hIpQLuIq22tL06ZcV5w7wqLxUZRpFElIFm8gZTkUvfKXVuHw89e4daDVhU5hK3GHNGTAgMBAAECgYABiINrFaE1E8pkBYx1JJA5yuhL73aUktfd2TeCU00vFg6kyrWCI85Sa2RKu/6CJNZWeOFgdubEUv7a22tRrNIZb3yUMaqtTwSso78mspIOJqjWXTkTH9WPElfTcdpdIse/lgZtPz6egxkuhadSvwrM9Y6NgusiW/5+x95Ct08iOQJBAN5aK+7uISURvGQj2EaRtgGEd8+d4oHl+BYvvTeG3qSgUikHQW3j0sp4gXPw2kxw6sjVgLFOc4FB6LGqwzOTzokCQQCYdYG8ty3Uo/ebUlNzeJFxHXjy/KvBSytAUzAXkRu3nZrkEaPQsi3dgOkZgk+F1fMDzfQ4EbDIU6xvqOoZXHg7AkATCW9XfoXR8anKfRMoP5Nwn9HOMbtR2cmaxK2TknV/bMZ8AsYETYwfj5+tuIJIJybC2RyykX/sIiN1CqS5xr7ZAkArj19rMRdaKyMi8MnBM1Cy9g3Jt2HHj5ejAGG8SgyWUOShh1y70z0BjcSMMkxQXAncK2s83ekZw7aADM4eQupjAkARRgTwwMOnn3IoKmQusKhZk0uxilZ4Zc2LH6Z4GiWnvteM0W8Zw4Z1lJUcjgQq3dGqL2RdmzeQZ+HgPIOXrZVK
|
package/package.json
CHANGED
|
@@ -302,6 +302,9 @@ function triggerCamera() {
|
|
|
302
302
|
rePhotoCheck(result.data)
|
|
303
303
|
}
|
|
304
304
|
else if (result.status === 'error') {
|
|
305
|
+
if (result.message && result.message.startsWith('图片质量检测失败')) {
|
|
306
|
+
parentData?.onPhotoQualityFailed?.()
|
|
307
|
+
}
|
|
305
308
|
const env = detectEnvironment()
|
|
306
309
|
// App 环境下弹窗提示错误
|
|
307
310
|
if (env.isApp) {
|
|
@@ -345,6 +348,7 @@ function rePhotoCheck(photoData: any) {
|
|
|
345
348
|
if (result && result.status === 'success') {
|
|
346
349
|
const checkRePhotoResult = result.data
|
|
347
350
|
if (checkRePhotoResult.is_rephoto === true || checkRePhotoResult.is_rephoto === 'true') {
|
|
351
|
+
parentData?.onPhotoRephotodetected?.()
|
|
348
352
|
console.warn(`检测到当前图片属于翻拍照片\n请上传合法图片!`)
|
|
349
353
|
showFailToast({
|
|
350
354
|
message: `当前图片属于翻拍照片\n请上传合法图片!`,
|
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { SignatureComponentExpose, SignatureComponentProps } from './signature'
|
|
3
|
-
import XSignature from '@af-mobile-client-vue3/components/data/XSignature/index.vue'
|
|
4
|
-
import { upload } from '@af-mobile-client-vue3/services/api/common'
|
|
5
|
-
import { isNativeApp } from '@af-mobile-client-vue3/utils/environment'
|
|
6
|
-
import { showFailToast, Field as VanField } from 'vant'
|
|
7
|
-
import { onMounted, ref, watch } from 'vue'
|
|
8
|
-
import SignatureComponent from './SignatureComponent.vue'
|
|
9
|
-
|
|
10
|
-
const props = withDefaults(defineProps<SignatureComponentProps & {
|
|
11
|
-
serviceName?: string
|
|
12
|
-
}>(), {
|
|
13
|
-
label: '用户签字',
|
|
14
|
-
required: false,
|
|
15
|
-
disabled: false,
|
|
16
|
-
uploadMode: 'server',
|
|
17
|
-
imageList: null,
|
|
18
|
-
formReadonly: false,
|
|
19
|
-
isAsyncUpload: false,
|
|
20
|
-
serviceName: undefined,
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
const emit = defineEmits<{
|
|
24
|
-
signatureComplete: [data: any]
|
|
25
|
-
}>()
|
|
26
|
-
|
|
27
|
-
// App / Flutter 壳走原生签字板;浏览器、微信等走 H5 签名
|
|
28
|
-
const isApp = ref(isNativeApp())
|
|
29
|
-
onMounted(() => {
|
|
30
|
-
// 部分 WebView 桥接注入略晚于首屏,挂载后再判一次
|
|
31
|
-
isApp.value = isNativeApp()
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
const nativeSignatureRef = ref<InstanceType<typeof SignatureComponent>>()
|
|
35
|
-
const webSignatureImage = ref('')
|
|
36
|
-
const webSignatureData = ref<any>(null)
|
|
37
|
-
const webUploading = ref(false)
|
|
38
|
-
|
|
39
|
-
const serviceName = props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME
|
|
40
|
-
|
|
41
|
-
watch(
|
|
42
|
-
() => props.imageList,
|
|
43
|
-
(list) => {
|
|
44
|
-
if (isApp.value || !Array.isArray(list) || !list[0]?.url)
|
|
45
|
-
return
|
|
46
|
-
webSignatureImage.value = list[0].url
|
|
47
|
-
},
|
|
48
|
-
{ immediate: true, deep: true },
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
async function uploadWebSignature(base64Image: string) {
|
|
52
|
-
const blob = await (await fetch(base64Image)).blob()
|
|
53
|
-
const filename = `signature_${Date.now()}.png`
|
|
54
|
-
const file = new File([blob], filename, { type: blob.type || 'image/png' })
|
|
55
|
-
const formData = new FormData()
|
|
56
|
-
formData.append('avatar', file)
|
|
57
|
-
formData.append('resUploadMode', props.uploadMode)
|
|
58
|
-
formData.append('pathKey', 'Default')
|
|
59
|
-
formData.append('formType', 'image')
|
|
60
|
-
formData.append('useType', 'Default')
|
|
61
|
-
formData.append('resUploadStock', '1')
|
|
62
|
-
formData.append('filename', filename)
|
|
63
|
-
formData.append('filesize', (file.size / 1024 / 1024).toFixed(4))
|
|
64
|
-
formData.append('f_operator', 'server')
|
|
65
|
-
|
|
66
|
-
return upload(formData, serviceName, { 'Content-Type': 'multipart/form-data' })
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function resetWebSignature() {
|
|
70
|
-
webSignatureImage.value = ''
|
|
71
|
-
webSignatureData.value = null
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function handleWebSignatureSave(base64Image: string) {
|
|
75
|
-
if (props.disabled || props.formReadonly || webUploading.value)
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
webUploading.value = true
|
|
79
|
-
try {
|
|
80
|
-
const res: any = await uploadWebSignature(base64Image)
|
|
81
|
-
if (!res?.data?.id) {
|
|
82
|
-
showFailToast('签名上传失败')
|
|
83
|
-
resetWebSignature()
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
webSignatureData.value = res.data
|
|
87
|
-
emit('signatureComplete', { status: 'success', data: res.data })
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
console.error('签名上传失败:', error)
|
|
91
|
-
showFailToast('签名上传失败')
|
|
92
|
-
resetWebSignature()
|
|
93
|
-
}
|
|
94
|
-
finally {
|
|
95
|
-
webUploading.value = false
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function handleWebSignatureClear() {
|
|
100
|
-
resetWebSignature()
|
|
101
|
-
emit('signatureComplete', { base64: '', status: 'cleared' })
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
defineExpose<SignatureComponentExpose>({
|
|
105
|
-
clearSignature() {
|
|
106
|
-
if (isApp.value)
|
|
107
|
-
nativeSignatureRef.value?.clearSignature()
|
|
108
|
-
else
|
|
109
|
-
handleWebSignatureClear()
|
|
110
|
-
},
|
|
111
|
-
hasSignature() {
|
|
112
|
-
if (isApp.value)
|
|
113
|
-
return nativeSignatureRef.value?.hasSignature() ?? false
|
|
114
|
-
return !!webSignatureData.value?.id || !!webSignatureImage.value
|
|
115
|
-
},
|
|
116
|
-
getSignatureData() {
|
|
117
|
-
if (isApp.value)
|
|
118
|
-
return nativeSignatureRef.value?.getSignatureData() ?? ''
|
|
119
|
-
return webSignatureImage.value.replace(/^data:image\/\w+;base64,/, '')
|
|
120
|
-
},
|
|
121
|
-
previewSignature() {
|
|
122
|
-
nativeSignatureRef.value?.previewSignature()
|
|
123
|
-
},
|
|
124
|
-
getSignatureList() {
|
|
125
|
-
if (isApp.value)
|
|
126
|
-
return nativeSignatureRef.value?.getSignatureList() ?? []
|
|
127
|
-
if (!webSignatureData.value)
|
|
128
|
-
return []
|
|
129
|
-
return [{
|
|
130
|
-
photo_name: webSignatureData.value.f_filename,
|
|
131
|
-
id: webSignatureData.value.id,
|
|
132
|
-
f_downloadpath: webSignatureData.value.f_downloadpath,
|
|
133
|
-
}]
|
|
134
|
-
},
|
|
135
|
-
})
|
|
136
|
-
</script>
|
|
137
|
-
|
|
138
|
-
<template>
|
|
139
|
-
<!-- App:原生签字板 -->
|
|
140
|
-
<SignatureComponent
|
|
141
|
-
v-if="isApp"
|
|
142
|
-
ref="nativeSignatureRef"
|
|
143
|
-
:label="label"
|
|
144
|
-
:required="required"
|
|
145
|
-
:disabled="disabled"
|
|
146
|
-
:upload-mode="uploadMode"
|
|
147
|
-
:image-list="imageList"
|
|
148
|
-
:form-readonly="formReadonly"
|
|
149
|
-
:is-async-upload="isAsyncUpload"
|
|
150
|
-
@signature-complete="emit('signatureComplete', $event)"
|
|
151
|
-
/>
|
|
152
|
-
<!-- 非 App:H5 在线签名(浏览器、微信等) -->
|
|
153
|
-
<VanField
|
|
154
|
-
v-else
|
|
155
|
-
center
|
|
156
|
-
name="signature"
|
|
157
|
-
:label="label"
|
|
158
|
-
:required="required"
|
|
159
|
-
>
|
|
160
|
-
<template #input>
|
|
161
|
-
<XSignature
|
|
162
|
-
v-model="webSignatureImage"
|
|
163
|
-
button-text="点击签字"
|
|
164
|
-
:show-button-after-signed="true"
|
|
165
|
-
:show-sign-button="!formReadonly"
|
|
166
|
-
:show-preview="true"
|
|
167
|
-
@save="handleWebSignatureSave"
|
|
168
|
-
@clear="handleWebSignatureClear"
|
|
169
|
-
/>
|
|
170
|
-
</template>
|
|
171
|
-
</VanField>
|
|
172
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { SignatureComponentExpose, SignatureComponentProps } from './signature'
|
|
3
|
+
import XSignature from '@af-mobile-client-vue3/components/data/XSignature/index.vue'
|
|
4
|
+
import { upload } from '@af-mobile-client-vue3/services/api/common'
|
|
5
|
+
import { isNativeApp } from '@af-mobile-client-vue3/utils/environment'
|
|
6
|
+
import { showFailToast, Field as VanField } from 'vant'
|
|
7
|
+
import { onMounted, ref, watch } from 'vue'
|
|
8
|
+
import SignatureComponent from './SignatureComponent.vue'
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<SignatureComponentProps & {
|
|
11
|
+
serviceName?: string
|
|
12
|
+
}>(), {
|
|
13
|
+
label: '用户签字',
|
|
14
|
+
required: false,
|
|
15
|
+
disabled: false,
|
|
16
|
+
uploadMode: 'server',
|
|
17
|
+
imageList: null,
|
|
18
|
+
formReadonly: false,
|
|
19
|
+
isAsyncUpload: false,
|
|
20
|
+
serviceName: undefined,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const emit = defineEmits<{
|
|
24
|
+
signatureComplete: [data: any]
|
|
25
|
+
}>()
|
|
26
|
+
|
|
27
|
+
// App / Flutter 壳走原生签字板;浏览器、微信等走 H5 签名
|
|
28
|
+
const isApp = ref(isNativeApp())
|
|
29
|
+
onMounted(() => {
|
|
30
|
+
// 部分 WebView 桥接注入略晚于首屏,挂载后再判一次
|
|
31
|
+
isApp.value = isNativeApp()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const nativeSignatureRef = ref<InstanceType<typeof SignatureComponent>>()
|
|
35
|
+
const webSignatureImage = ref('')
|
|
36
|
+
const webSignatureData = ref<any>(null)
|
|
37
|
+
const webUploading = ref(false)
|
|
38
|
+
|
|
39
|
+
const serviceName = props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME
|
|
40
|
+
|
|
41
|
+
watch(
|
|
42
|
+
() => props.imageList,
|
|
43
|
+
(list) => {
|
|
44
|
+
if (isApp.value || !Array.isArray(list) || !list[0]?.url)
|
|
45
|
+
return
|
|
46
|
+
webSignatureImage.value = list[0].url
|
|
47
|
+
},
|
|
48
|
+
{ immediate: true, deep: true },
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
async function uploadWebSignature(base64Image: string) {
|
|
52
|
+
const blob = await (await fetch(base64Image)).blob()
|
|
53
|
+
const filename = `signature_${Date.now()}.png`
|
|
54
|
+
const file = new File([blob], filename, { type: blob.type || 'image/png' })
|
|
55
|
+
const formData = new FormData()
|
|
56
|
+
formData.append('avatar', file)
|
|
57
|
+
formData.append('resUploadMode', props.uploadMode)
|
|
58
|
+
formData.append('pathKey', 'Default')
|
|
59
|
+
formData.append('formType', 'image')
|
|
60
|
+
formData.append('useType', 'Default')
|
|
61
|
+
formData.append('resUploadStock', '1')
|
|
62
|
+
formData.append('filename', filename)
|
|
63
|
+
formData.append('filesize', (file.size / 1024 / 1024).toFixed(4))
|
|
64
|
+
formData.append('f_operator', 'server')
|
|
65
|
+
|
|
66
|
+
return upload(formData, serviceName, { 'Content-Type': 'multipart/form-data' })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function resetWebSignature() {
|
|
70
|
+
webSignatureImage.value = ''
|
|
71
|
+
webSignatureData.value = null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function handleWebSignatureSave(base64Image: string) {
|
|
75
|
+
if (props.disabled || props.formReadonly || webUploading.value)
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
webUploading.value = true
|
|
79
|
+
try {
|
|
80
|
+
const res: any = await uploadWebSignature(base64Image)
|
|
81
|
+
if (!res?.data?.id) {
|
|
82
|
+
showFailToast('签名上传失败')
|
|
83
|
+
resetWebSignature()
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
webSignatureData.value = res.data
|
|
87
|
+
emit('signatureComplete', { status: 'success', data: res.data })
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error('签名上传失败:', error)
|
|
91
|
+
showFailToast('签名上传失败')
|
|
92
|
+
resetWebSignature()
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
webUploading.value = false
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function handleWebSignatureClear() {
|
|
100
|
+
resetWebSignature()
|
|
101
|
+
emit('signatureComplete', { base64: '', status: 'cleared' })
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
defineExpose<SignatureComponentExpose>({
|
|
105
|
+
clearSignature() {
|
|
106
|
+
if (isApp.value)
|
|
107
|
+
nativeSignatureRef.value?.clearSignature()
|
|
108
|
+
else
|
|
109
|
+
handleWebSignatureClear()
|
|
110
|
+
},
|
|
111
|
+
hasSignature() {
|
|
112
|
+
if (isApp.value)
|
|
113
|
+
return nativeSignatureRef.value?.hasSignature() ?? false
|
|
114
|
+
return !!webSignatureData.value?.id || !!webSignatureImage.value
|
|
115
|
+
},
|
|
116
|
+
getSignatureData() {
|
|
117
|
+
if (isApp.value)
|
|
118
|
+
return nativeSignatureRef.value?.getSignatureData() ?? ''
|
|
119
|
+
return webSignatureImage.value.replace(/^data:image\/\w+;base64,/, '')
|
|
120
|
+
},
|
|
121
|
+
previewSignature() {
|
|
122
|
+
nativeSignatureRef.value?.previewSignature()
|
|
123
|
+
},
|
|
124
|
+
getSignatureList() {
|
|
125
|
+
if (isApp.value)
|
|
126
|
+
return nativeSignatureRef.value?.getSignatureList() ?? []
|
|
127
|
+
if (!webSignatureData.value)
|
|
128
|
+
return []
|
|
129
|
+
return [{
|
|
130
|
+
photo_name: webSignatureData.value.f_filename,
|
|
131
|
+
id: webSignatureData.value.id,
|
|
132
|
+
f_downloadpath: webSignatureData.value.f_downloadpath,
|
|
133
|
+
}]
|
|
134
|
+
},
|
|
135
|
+
})
|
|
136
|
+
</script>
|
|
137
|
+
|
|
138
|
+
<template>
|
|
139
|
+
<!-- App:原生签字板 -->
|
|
140
|
+
<SignatureComponent
|
|
141
|
+
v-if="isApp"
|
|
142
|
+
ref="nativeSignatureRef"
|
|
143
|
+
:label="label"
|
|
144
|
+
:required="required"
|
|
145
|
+
:disabled="disabled"
|
|
146
|
+
:upload-mode="uploadMode"
|
|
147
|
+
:image-list="imageList"
|
|
148
|
+
:form-readonly="formReadonly"
|
|
149
|
+
:is-async-upload="isAsyncUpload"
|
|
150
|
+
@signature-complete="emit('signatureComplete', $event)"
|
|
151
|
+
/>
|
|
152
|
+
<!-- 非 App:H5 在线签名(浏览器、微信等) -->
|
|
153
|
+
<VanField
|
|
154
|
+
v-else
|
|
155
|
+
center
|
|
156
|
+
name="signature"
|
|
157
|
+
:label="label"
|
|
158
|
+
:required="required"
|
|
159
|
+
>
|
|
160
|
+
<template #input>
|
|
161
|
+
<XSignature
|
|
162
|
+
v-model="webSignatureImage"
|
|
163
|
+
button-text="点击签字"
|
|
164
|
+
:show-button-after-signed="true"
|
|
165
|
+
:show-sign-button="!formReadonly"
|
|
166
|
+
:show-preview="true"
|
|
167
|
+
@save="handleWebSignatureSave"
|
|
168
|
+
@clear="handleWebSignatureClear"
|
|
169
|
+
/>
|
|
170
|
+
</template>
|
|
171
|
+
</VanField>
|
|
172
|
+
</template>
|