af-mobile-client-vue3 1.6.30 → 1.6.31

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "af-mobile-client-vue3",
3
3
  "type": "module",
4
- "version": "1.6.30",
4
+ "version": "1.6.31",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
@@ -0,0 +1,168 @@
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 { detectEnvironment } from '@af-mobile-client-vue3/utils/environment'
6
+ import { showFailToast, Field as VanField } from 'vant'
7
+ import { 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 / 非 App:原生桥只在 App 可用,其余环境统一走 H5 签名
28
+ const isApp = detectEnvironment().isApp
29
+
30
+ const nativeSignatureRef = ref<InstanceType<typeof SignatureComponent>>()
31
+ const webSignatureImage = ref('')
32
+ const webSignatureData = ref<any>(null)
33
+ const webUploading = ref(false)
34
+
35
+ const serviceName = props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME
36
+
37
+ watch(
38
+ () => props.imageList,
39
+ (list) => {
40
+ if (isApp || !Array.isArray(list) || !list[0]?.url)
41
+ return
42
+ webSignatureImage.value = list[0].url
43
+ },
44
+ { immediate: true, deep: true },
45
+ )
46
+
47
+ async function uploadWebSignature(base64Image: string) {
48
+ const blob = await (await fetch(base64Image)).blob()
49
+ const filename = `signature_${Date.now()}.png`
50
+ const file = new File([blob], filename, { type: blob.type || 'image/png' })
51
+ const formData = new FormData()
52
+ formData.append('avatar', file)
53
+ formData.append('resUploadMode', props.uploadMode)
54
+ formData.append('pathKey', 'Default')
55
+ formData.append('formType', 'image')
56
+ formData.append('useType', 'Default')
57
+ formData.append('resUploadStock', '1')
58
+ formData.append('filename', filename)
59
+ formData.append('filesize', (file.size / 1024 / 1024).toFixed(4))
60
+ formData.append('f_operator', 'server')
61
+
62
+ return upload(formData, serviceName, { 'Content-Type': 'multipart/form-data' })
63
+ }
64
+
65
+ function resetWebSignature() {
66
+ webSignatureImage.value = ''
67
+ webSignatureData.value = null
68
+ }
69
+
70
+ async function handleWebSignatureSave(base64Image: string) {
71
+ if (props.disabled || props.formReadonly || webUploading.value)
72
+ return
73
+
74
+ webUploading.value = true
75
+ try {
76
+ const res: any = await uploadWebSignature(base64Image)
77
+ if (!res?.data?.id) {
78
+ showFailToast('签名上传失败')
79
+ resetWebSignature()
80
+ return
81
+ }
82
+ webSignatureData.value = res.data
83
+ emit('signatureComplete', { status: 'success', data: res.data })
84
+ }
85
+ catch (error) {
86
+ console.error('签名上传失败:', error)
87
+ showFailToast('签名上传失败')
88
+ resetWebSignature()
89
+ }
90
+ finally {
91
+ webUploading.value = false
92
+ }
93
+ }
94
+
95
+ function handleWebSignatureClear() {
96
+ resetWebSignature()
97
+ emit('signatureComplete', { base64: '', status: 'cleared' })
98
+ }
99
+
100
+ defineExpose<SignatureComponentExpose>({
101
+ clearSignature() {
102
+ if (isApp)
103
+ nativeSignatureRef.value?.clearSignature()
104
+ else
105
+ handleWebSignatureClear()
106
+ },
107
+ hasSignature() {
108
+ if (isApp)
109
+ return nativeSignatureRef.value?.hasSignature() ?? false
110
+ return !!webSignatureData.value?.id || !!webSignatureImage.value
111
+ },
112
+ getSignatureData() {
113
+ if (isApp)
114
+ return nativeSignatureRef.value?.getSignatureData() ?? ''
115
+ return webSignatureImage.value.replace(/^data:image\/\w+;base64,/, '')
116
+ },
117
+ previewSignature() {
118
+ nativeSignatureRef.value?.previewSignature()
119
+ },
120
+ getSignatureList() {
121
+ if (isApp)
122
+ return nativeSignatureRef.value?.getSignatureList() ?? []
123
+ if (!webSignatureData.value)
124
+ return []
125
+ return [{
126
+ photo_name: webSignatureData.value.f_filename,
127
+ id: webSignatureData.value.id,
128
+ f_downloadpath: webSignatureData.value.f_downloadpath,
129
+ }]
130
+ },
131
+ })
132
+ </script>
133
+
134
+ <template>
135
+ <!-- App:原生签字板 -->
136
+ <SignatureComponent
137
+ v-if="isApp"
138
+ ref="nativeSignatureRef"
139
+ :label="label"
140
+ :required="required"
141
+ :disabled="disabled"
142
+ :upload-mode="uploadMode"
143
+ :image-list="imageList"
144
+ :form-readonly="formReadonly"
145
+ :is-async-upload="isAsyncUpload"
146
+ @signature-complete="emit('signatureComplete', $event)"
147
+ />
148
+ <!-- 非 App:H5 在线签名(浏览器、微信等) -->
149
+ <VanField
150
+ v-else
151
+ center
152
+ name="signature"
153
+ :label="label"
154
+ :required="required"
155
+ >
156
+ <template #input>
157
+ <XSignature
158
+ v-model="webSignatureImage"
159
+ button-text="点击签字"
160
+ :show-button-after-signed="true"
161
+ :show-sign-button="!formReadonly"
162
+ :show-preview="true"
163
+ @save="handleWebSignatureSave"
164
+ @clear="handleWebSignatureClear"
165
+ />
166
+ </template>
167
+ </VanField>
168
+ </template>
@@ -2,7 +2,7 @@
2
2
  import type { FieldType } from 'vant'
3
3
  import type { Numeric } from 'vant/es/utils'
4
4
  import ImageUploader from '@af-mobile-client-vue3/components/core/ImageUploader/index.vue'
5
- import SignatureComponent from '@af-mobile-client-vue3/components/core/Signature/SignatureComponent.vue'
5
+ import AdaptiveSignatureField from '@af-mobile-client-vue3/components/core/Signature/AdaptiveSignatureField.vue'
6
6
  import XDatePicker from '@af-mobile-client-vue3/components/core/XDatePicker/index.vue'
7
7
  import XGridDropOption from '@af-mobile-client-vue3/components/core/XGridDropOption/index.vue'
8
8
  import XMultiSelect from '@af-mobile-client-vue3/components/core/XMultiSelect/index.vue'
@@ -1275,17 +1275,17 @@ function commChange() {
1275
1275
  />
1276
1276
  </template>
1277
1277
  </VanField>
1278
- <!-- 手机端签字 -->
1279
- <SignatureComponent
1278
+ <!-- 签字:App 原生签字板,微信/浏览器 H5 在线签名 -->
1279
+ <AdaptiveSignatureField
1280
1280
  v-if="attr.type === 'signature' && showItem"
1281
1281
  :label="labelData"
1282
1282
  upload-mode="server"
1283
1283
  :image-list="(modelData as any[])"
1284
- authority="admin"
1285
- :required="attr.rule?.required"
1284
+ :required="attr.rule?.required === 'true'"
1286
1285
  :disabled="attr.disabled"
1287
1286
  :form-readonly="readonly"
1288
1287
  :is-async-upload="isAsyncUpload"
1288
+ :service-name="serviceName"
1289
1289
  @signature-complete="signatureComplete"
1290
1290
  />
1291
1291