af-mobile-client-vue3 1.6.39 → 1.6.41
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/package.json +1 -1
- package/src/components/core/ImageUploader/index.vue +90 -13
- 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 -0
- package/src/views/SafeInspection/SecurityCertificate/userInfo/index.vue +8 -2
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { NativePickedFile } from '@af-mobile-client-vue3/utils/nativeFilePicker'
|
|
2
3
|
// import cameraIcon from '@af-mobile-client-vue3/assets/img/component/camera.png'
|
|
3
4
|
import { deleteFile, upload } from '@af-mobile-client-vue3/services/api/common'
|
|
4
5
|
import { detectEnvironment } from '@af-mobile-client-vue3/utils/environment'
|
|
5
6
|
import { buildInputAccept, getFileTypeMeta, getUploadFormType, isImageFileName } from '@af-mobile-client-vue3/utils/fileType'
|
|
6
7
|
import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
|
|
8
|
+
import {
|
|
9
|
+
openNativeFilePicker,
|
|
10
|
+
triggerBrowserFileInput,
|
|
11
|
+
} from '@af-mobile-client-vue3/utils/nativeFilePicker'
|
|
7
12
|
import { toDataUrl } from '@af-mobile-client-vue3/utils/resourceUrl'
|
|
8
13
|
import { formatNow } from '@af-mobile-client-vue3/utils/timeUtil'
|
|
9
14
|
import {
|
|
@@ -48,17 +53,11 @@ const documentInputRef = ref<HTMLInputElement | undefined>()
|
|
|
48
53
|
const documentAccept = computed(() => buildInputAccept(props.attr?.accept))
|
|
49
54
|
|
|
50
55
|
function openImageFilePicker() {
|
|
51
|
-
|
|
52
|
-
imageInputRef.value.value = ''
|
|
53
|
-
imageInputRef.value.click()
|
|
54
|
-
}
|
|
56
|
+
triggerBrowserFileInput(imageInputRef.value)
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
function openDocumentFilePicker() {
|
|
58
|
-
|
|
59
|
-
documentInputRef.value.value = ''
|
|
60
|
-
documentInputRef.value.click()
|
|
61
|
-
}
|
|
60
|
+
triggerBrowserFileInput(documentInputRef.value)
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
function emitUpdatesAfterChange() {
|
|
@@ -215,6 +214,69 @@ function handleBrowserDocumentFiles(files: FileList | null) {
|
|
|
215
214
|
}
|
|
216
215
|
}
|
|
217
216
|
|
|
217
|
+
function handleNativeDocumentUpload(fileData: NativePickedFile) {
|
|
218
|
+
const filePath = fileData.filePath || fileData.path || ''
|
|
219
|
+
const fileName = fileData.name || filePath.split('/').pop() || 'file'
|
|
220
|
+
const tempFile = createTempUploadingItem(fileName, '', false)
|
|
221
|
+
|
|
222
|
+
const param = {
|
|
223
|
+
resUploadMode: props.uploadMode,
|
|
224
|
+
pathKey: 'Default',
|
|
225
|
+
formType: 'file' as const,
|
|
226
|
+
useType: props.attr?.useType || 'Default',
|
|
227
|
+
resUploadStock: '1',
|
|
228
|
+
filename: fileName,
|
|
229
|
+
filesize: fileData.size,
|
|
230
|
+
f_operator: 'server',
|
|
231
|
+
imgPath: filePath,
|
|
232
|
+
urlPath: `/api/${props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME}/resource/upload`,
|
|
233
|
+
commonId: parentData?.commonId?.value ?? '',
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
mobileUtil.execute({
|
|
237
|
+
funcName: 'uploadResource',
|
|
238
|
+
param,
|
|
239
|
+
callbackFunc: (result: any) => {
|
|
240
|
+
const index = imageList.value.findIndex(item => item.uid === tempFile.uid)
|
|
241
|
+
if (result.status === 'success') {
|
|
242
|
+
if (index !== -1) {
|
|
243
|
+
imageList.value[index].uid = result.data.id
|
|
244
|
+
imageList.value[index].id = result.data.id
|
|
245
|
+
imageList.value[index].f_downloadpath = result.data.f_downloadpath
|
|
246
|
+
imageList.value[index].photo_name = result.data.f_filename
|
|
247
|
+
imageList.value[index].isDocument = true
|
|
248
|
+
imageList.value[index].isImage = true
|
|
249
|
+
imageList.value[index].url = DOC_TILE_PLACEHOLDER
|
|
250
|
+
delete imageList.value[index].message
|
|
251
|
+
imageList.value[index].status = 'done'
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else if (index !== -1) {
|
|
255
|
+
imageList.value[index].status = 'failed'
|
|
256
|
+
imageList.value[index].message = '上传失败'
|
|
257
|
+
}
|
|
258
|
+
emitUpdatesAfterChange()
|
|
259
|
+
},
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function triggerDocumentPicker() {
|
|
264
|
+
const startedNative = openNativeFilePicker({
|
|
265
|
+
accept: documentAccept.value,
|
|
266
|
+
multiple: true,
|
|
267
|
+
onSuccess: files => files.forEach(handleNativeDocumentUpload),
|
|
268
|
+
onError: (msg) => {
|
|
269
|
+
if (msg)
|
|
270
|
+
showFailToast(msg)
|
|
271
|
+
},
|
|
272
|
+
})
|
|
273
|
+
if (startedNative)
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
// 与「相册中选择」一致:ActionSheet 点击后立即调起系统文件选择器
|
|
277
|
+
openDocumentFilePicker()
|
|
278
|
+
}
|
|
279
|
+
|
|
218
280
|
// 触发拍照
|
|
219
281
|
function triggerCamera() {
|
|
220
282
|
mobileUtil.execute({
|
|
@@ -512,6 +574,11 @@ function handleUploadAreaClick() {
|
|
|
512
574
|
}
|
|
513
575
|
|
|
514
576
|
function handleActionSelect(option: any) {
|
|
577
|
+
if (option.key === 'document') {
|
|
578
|
+
triggerDocumentPicker()
|
|
579
|
+
showActionSheet.value = false
|
|
580
|
+
return
|
|
581
|
+
}
|
|
515
582
|
showActionSheet.value = false
|
|
516
583
|
if (option.key === 'camera') {
|
|
517
584
|
triggerCamera()
|
|
@@ -532,9 +599,6 @@ function handleActionSelect(option: any) {
|
|
|
532
599
|
},
|
|
533
600
|
})
|
|
534
601
|
}
|
|
535
|
-
else if (option.key === 'document') {
|
|
536
|
-
openDocumentFilePicker()
|
|
537
|
-
}
|
|
538
602
|
}
|
|
539
603
|
|
|
540
604
|
function getUploadStatus() {
|
|
@@ -565,7 +629,7 @@ defineExpose({
|
|
|
565
629
|
type="file"
|
|
566
630
|
multiple
|
|
567
631
|
accept="image/*"
|
|
568
|
-
|
|
632
|
+
class="hidden-file-input"
|
|
569
633
|
@change="(e:any) => handleBrowserImageFiles(e.target.files)"
|
|
570
634
|
>
|
|
571
635
|
<!-- 通用文件选择(PDF / Word 等) -->
|
|
@@ -574,7 +638,7 @@ defineExpose({
|
|
|
574
638
|
type="file"
|
|
575
639
|
multiple
|
|
576
640
|
:accept="documentAccept"
|
|
577
|
-
|
|
641
|
+
class="hidden-file-input"
|
|
578
642
|
@change="(e:any) => handleBrowserDocumentFiles(e.target.files)"
|
|
579
643
|
>
|
|
580
644
|
<van-uploader
|
|
@@ -630,6 +694,19 @@ defineExpose({
|
|
|
630
694
|
// 该属性会影响表单布局
|
|
631
695
|
// gap: 16px;
|
|
632
696
|
}
|
|
697
|
+
|
|
698
|
+
/* WebView 内 display:none 会导致 file input 无法被程序化触发,改用视觉隐藏 */
|
|
699
|
+
.hidden-file-input {
|
|
700
|
+
position: fixed;
|
|
701
|
+
top: 0;
|
|
702
|
+
left: 0;
|
|
703
|
+
width: 1px;
|
|
704
|
+
height: 1px;
|
|
705
|
+
opacity: 0;
|
|
706
|
+
overflow: hidden;
|
|
707
|
+
pointer-events: none;
|
|
708
|
+
z-index: -1;
|
|
709
|
+
}
|
|
633
710
|
/* 让自定义上传按钮可点击:关闭 Vant 覆盖在上方的透明 input 的事件捕获 */
|
|
634
711
|
:deep(.custom-trigger-uploader .van-uploader__input) {
|
|
635
712
|
pointer-events: none;
|
|
@@ -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>
|