af-mobile-client-vue3 1.5.88 → 1.5.90

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.5.88",
4
+ "version": "1.5.90",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
@@ -121,11 +121,11 @@ const filteredRecordEntries = computed(() => {
121
121
  if (!user.value?.f_meter_type)
122
122
  return []
123
123
 
124
- return props?.recordEntries || props?.recordEntries?.length === 0
125
- ? allRecords.value.filter(entry =>
124
+ return props?.recordEntries && props?.recordEntries?.length > 0
125
+ ? props.recordEntries.filter(entry =>
126
126
  entry.forMeterTypes.includes(user.value!.f_meter_type),
127
127
  )
128
- : props.recordEntries.filter(entry =>
128
+ : allRecords.value.filter(entry =>
129
129
  entry.forMeterTypes.includes(user.value!.f_meter_type),
130
130
  )
131
131
  })
@@ -6,10 +6,10 @@ import type {
6
6
  DeviceTypeAction,
7
7
  } from './types/device'
8
8
 
9
- import SecurityFormItem from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/index.vue'
10
9
  import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
11
10
  import { getConfigByName } from '@af-mobile-client-vue3/services/api/common'
12
11
  import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
12
+ import SecurityFormItem from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/index.vue'
13
13
  import {
14
14
  showConfirmDialog,
15
15
  showToast,
@@ -2,14 +2,14 @@
2
2
  import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
3
3
  import { getPhotosFromAny } from '@af-mobile-client-vue3/utils/PhotoClean'
4
4
  import {
5
+ showConfirmDialog,
6
+ showToast,
5
7
  Button as VanButton,
6
8
  Cell as VanCell,
7
9
  CellGroup as VanCellGroup,
8
10
  Empty as VanEmpty,
9
11
  Icon as VanIcon,
10
12
  List as VanList,
11
- showConfirmDialog,
12
- showToast,
13
13
  } from 'vant'
14
14
  import { defineEmits, defineExpose, defineProps, inject, onMounted, ref, watch } from 'vue'
15
15
 
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
3
3
  import { runLogic } from '@af-mobile-client-vue3/services/api/common'
4
- import { Popup as VanPopup, showToast } from 'vant'
4
+ import { showToast, Popup as VanPopup } from 'vant'
5
5
  import { defineEmits, defineExpose, ref } from 'vue'
6
6
 
7
7
  const emit = defineEmits(['signSuccess'])
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
14
14
  import { Icon } from '@iconify/vue'
15
- import { Button as VanButton, Icon as VanIcon, showFailToast } from 'vant'
15
+ import { showFailToast, Button as VanButton, Icon as VanIcon } from 'vant'
16
16
  import { inject } from 'vue'
17
17
 
18
18
  /**
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import ImageUploader from '@af-mobile-client-vue3/components/core/ImageUploader/index.vue'
3
- import { Button as VanButton, Cell as VanCell, CellGroup as VanCellGroup, Empty as VanEmpty, Field as VanField } from 'vant'
3
+ import { Button as VanButton, Cell as VanCell, Empty as VanEmpty, Field as VanField } from 'vant'
4
4
  import { computed } from 'vue'
5
5
 
6
6
  interface StepItem {
@@ -10,7 +10,7 @@
10
10
  * - 支持点击切换到指定步骤
11
11
  * ========================================
12
12
  */
13
- import { Progress, Tab as VanTab, Tabs as VanTabs } from 'vant'
13
+ import { Progress } from 'vant'
14
14
 
15
15
  /**
16
16
  * 步骤项接口
@@ -12,9 +12,9 @@
12
12
  */
13
13
  import { getConfigByName, runLogic } from '@af-mobile-client-vue3/services/api/common'
14
14
  import { Icon } from '@iconify/vue'
15
- import { showFailToast } from 'vant'
15
+ import { showFailToast, Loading as VanLoading, Tab as VanTab, Tabs as VanTabs } from 'vant'
16
16
  import { computed, onMounted, ref } from 'vue'
17
- import { Loading as VanLoading, Tab as VanTab, Tabs as VanTabs } from 'vant'
17
+
18
18
  import PhotoCaptureCard from './components/PhotoCaptureCard.vue'
19
19
  import PhotoRecognitionInfo from './components/PhotoRecognitionInfo.vue'
20
20
  import PhotoStepHeader from './components/PhotoStepHeader.vue'
@@ -0,0 +1,285 @@
1
+ <script setup lang="ts">
2
+ import type { SignatureCompleteData, SignatureComponentExpose, SignatureComponentProps } from './signature'
3
+ import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
4
+ import {
5
+ showImagePreview,
6
+ showToast,
7
+ Button as VanButton,
8
+ Field as VanField,
9
+ Icon as VanIcon,
10
+ Image as VanImage,
11
+ } from 'vant'
12
+ import { computed, defineEmits, defineProps, inject, ref } from 'vue'
13
+
14
+ const props = withDefaults(defineProps<SignatureComponentProps>(), {
15
+ label: '用户签字',
16
+ required: false,
17
+ disabled: false,
18
+ uploadMode: 'server',
19
+ imageList: Array<any>,
20
+ formReadonly: false,
21
+ })
22
+
23
+ const emit = defineEmits<{
24
+ signatureComplete: [data: SignatureCompleteData]
25
+ }>()
26
+
27
+ const signatureImage = ref<string>('')
28
+ const rawBase64Data = ref<string>('') // 保存原始base64数据
29
+ const hasSignature = ref(false)
30
+ const parentData: any = inject('provideParent')
31
+ const imageList = ref<Array<any>>(props.imageList ?? [])
32
+ const signatureFormData: any = inject('getSignatureData')
33
+ const isRequired = computed(() => {
34
+ const isSignature = signatureFormData?.getSignatureData()
35
+ return !(isSignature?.f_signature && isSignature?.f_signature !== '现场签字')
36
+ })
37
+
38
+ // 处理签字后的上传
39
+ function getImageMimeType(fileName: string): string {
40
+ const ext = fileName.split('.').pop()?.toLowerCase()
41
+ if (ext === 'jpg' || ext === 'jpeg')
42
+ return 'image/jpeg'
43
+ if (ext === 'png')
44
+ return 'image/png'
45
+ if (ext === 'gif')
46
+ return 'image/gif'
47
+ return 'image/png' // 默认
48
+ }
49
+
50
+ function handleSignature() {
51
+ if (props.disabled)
52
+ return
53
+ if (!isRequired.value) {
54
+ showToast('只有现场签字才需要签字')
55
+ return
56
+ }
57
+
58
+ mobileUtil.execute({
59
+ funcName: 'showSignaturePad',
60
+ param: {},
61
+ callbackFunc: (result: any) => {
62
+ console.log('签字结果:', result)
63
+ if (result.status === 'success') {
64
+ const mimeType = getImageMimeType(result.data.filePath)
65
+ // 保存原始base64数据
66
+ rawBase64Data.value = result.data.base64
67
+ // 添加base64图片前缀用于显示
68
+ signatureImage.value = `data:${mimeType};base64,${result.data.base64}`
69
+ hasSignature.value = true
70
+ const tempFile = {
71
+ uid: Date.now() + Math.random().toString(36).substr(2, 5),
72
+ name: result.data.filePath.split('/').pop(),
73
+ status: 'uploading',
74
+ message: '上传中...',
75
+ url: `data:${mimeType};base64,${result.data.base64}`,
76
+ isImage: true,
77
+ type: mimeType,
78
+ }
79
+ if (imageList.value) {
80
+ imageList.value = [tempFile]
81
+ }
82
+
83
+ const param = {
84
+ resUploadMode: props.uploadMode,
85
+ pathKey: 'Default',
86
+ formType: 'image',
87
+ useType: 'Default',
88
+ resUploadStock: '1',
89
+ filename: tempFile.name,
90
+ // 暂无size
91
+ // filesize: photoData.size,
92
+ f_operator: 'server',
93
+ imgPath: result.data.filePath,
94
+ urlPath: `/api/${import.meta.env.VITE_APP_SYSTEM_NAME}/resource/upload`,
95
+ commonId: parentData.commonId.value ?? '',
96
+ }
97
+
98
+ // 添加上传队列
99
+ mobileUtil.execute({
100
+ funcName: 'queueUpload',
101
+ param,
102
+ callbackFunc: (res: any) => {
103
+ console.warn('上传结果', res)
104
+ // 成功
105
+ if (res.data && res.data.enqueued) {
106
+ const index = imageList.value.findIndex(item => item.uid === tempFile.uid)
107
+ if (index !== -1) {
108
+ delete imageList.value[index].message
109
+ imageList.value[index].status = 'done'
110
+ imageList.value[index].photo_name = tempFile.name
111
+ imageList.value[index].type = mimeType
112
+ }
113
+ else {
114
+ if (index !== -1) {
115
+ imageList.value[index].status = 'failed'
116
+ imageList.value[index].message = '上传失败'
117
+ }
118
+ }
119
+ }
120
+ },
121
+ })
122
+ emit('signatureComplete', {
123
+ base64: result.data.base64,
124
+ status: result.data.status,
125
+ })
126
+ }
127
+ },
128
+ })
129
+ }
130
+
131
+ function clearSignature() {
132
+ signatureImage.value = ''
133
+ rawBase64Data.value = ''
134
+ hasSignature.value = false
135
+ imageList.value = []
136
+ emit('signatureComplete', {
137
+ base64: '',
138
+ status: 'cleared',
139
+ })
140
+ }
141
+
142
+ // 预览签字照片
143
+ function previewSignature() {
144
+ if (imageList.value) {
145
+ showImagePreview(imageList.value.map(item => item.url))
146
+ }
147
+ }
148
+
149
+ // 暴露方法供父组件调用
150
+ defineExpose<SignatureComponentExpose>({
151
+ clearSignature,
152
+ hasSignature: () => hasSignature.value,
153
+ getSignatureData: () => rawBase64Data.value, // 返回原始base64数据
154
+ previewSignature,
155
+ getSignatureList: () => imageList.value.map(item => item.photo_name),
156
+ })
157
+ </script>
158
+
159
+ <template>
160
+ <VanField
161
+ center
162
+ name="signature"
163
+ :label="label"
164
+ :required="required"
165
+ >
166
+ <template #input>
167
+ <div class="signature-container">
168
+ <!-- 签字照片预览 -->
169
+ <div v-if="imageList.length > 0 || hasSignature" class="signature-preview">
170
+ <VanImage
171
+ v-for="(item, index) in imageList"
172
+ :key="`${item}_${index}`"
173
+ :src="item.url"
174
+ alt="签字照片"
175
+ class="signature-image"
176
+ fit="contain"
177
+ :show-loading="true"
178
+ :show-error="true"
179
+ loading-icon="photo-o"
180
+ error-icon="warning-o"
181
+ @click="previewSignature"
182
+ />
183
+ </div>
184
+
185
+ <!-- 按钮行 -->
186
+ <div class="button-row">
187
+ <!-- 签字按钮 -->
188
+ <VanButton
189
+ v-if="!props.formReadonly"
190
+ :disabled="disabled"
191
+ type="default"
192
+ size="small"
193
+ class="signature-btn dashed-btn"
194
+ @click="handleSignature"
195
+ >
196
+ <VanIcon :name="hasSignature ? 'edit' : 'edit'" class="btn-icon" />
197
+ {{ imageList.length > 0 || hasSignature ? '重签' : '点击签字' }}
198
+ </VanButton>
199
+
200
+ <!-- 清除按钮 -->
201
+ <VanButton
202
+ v-if="(imageList.length > 0 || hasSignature) && !props.formReadonly"
203
+ type="default"
204
+ size="small"
205
+ class="dashed-btn clear-btn"
206
+ @click="clearSignature"
207
+ >
208
+ <VanIcon name="delete" class="btn-icon" />
209
+ 清除
210
+ </VanButton>
211
+ </div>
212
+ </div>
213
+ </template>
214
+ </VanField>
215
+ </template>
216
+
217
+ <style scoped lang="less">
218
+ .signature-container {
219
+ display: flex;
220
+ flex-direction: column;
221
+ gap: 12px;
222
+ width: 100%;
223
+ }
224
+
225
+ .signature-preview {
226
+ position: relative;
227
+ display: flex;
228
+ flex-direction: column;
229
+ align-items: center;
230
+ gap: 8px;
231
+
232
+ .signature-image {
233
+ max-width: 200px;
234
+ max-height: 120px;
235
+ border: 1px solid #e8e8e8;
236
+ border-radius: 4px;
237
+ cursor: pointer;
238
+ transition: all 0.2s ease;
239
+ }
240
+ }
241
+
242
+ // 按钮行样式
243
+ .button-row {
244
+ display: flex;
245
+ gap: 12px;
246
+ align-items: center;
247
+ justify-content: space-between;
248
+ }
249
+
250
+ .signature-btn {
251
+ flex-shrink: 0;
252
+ margin-right: auto;
253
+ }
254
+
255
+ // 虚线按钮样式
256
+ .dashed-btn {
257
+ border: 1px dashed #1989fa !important;
258
+ background-color: transparent !important;
259
+ color: #1989fa !important;
260
+ border-radius: 4px !important;
261
+
262
+ &:hover {
263
+ border-color: #0570d9 !important;
264
+ color: #0570d9 !important;
265
+ }
266
+
267
+ &:active {
268
+ border-color: #0366d6 !important;
269
+ color: #0366d6 !important;
270
+ background-color: rgba(25, 137, 250, 0.1) !important;
271
+ }
272
+
273
+ &:disabled {
274
+ border-color: #c8c9cc !important;
275
+ color: #c8c9cc !important;
276
+ background-color: transparent !important;
277
+ }
278
+ }
279
+
280
+ // 按钮图标样式
281
+ .btn-icon {
282
+ margin-right: 4px;
283
+ font-size: 14px;
284
+ }
285
+ </style>
@@ -1,12 +1,13 @@
1
1
  <script setup lang="ts">
2
- import type { SignatureCompleteData, SignatureComponentExpose } from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/SignatureComponent/signature'
2
+ import type { SignatureCompleteData, SignatureComponentExpose } from './SignatureComponent/signature'
3
3
  import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
4
4
  import { runLogic } from '@af-mobile-client-vue3/services/api/common'
5
5
  import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
6
6
  import { getPhotosFromAny } from '@af-mobile-client-vue3/utils/PhotoClean'
7
+ import contractSign from '@af-mobile-client-vue3/views/SafeInspection/SecurityCertificate/contractSign/index.vue'
7
8
  import { Icon as VanIcon } from 'vant'
8
9
  import { defineExpose, inject, onBeforeMount, provide, ref, watch } from 'vue'
9
- import contractSign from '@af-mobile-client-vue3/views/SafeInspection/SecurityCertificate/contractSign/index.vue'
10
+ import SignatureComponent from './SignatureComponent/SignatureComponent.vue'
10
11
 
11
12
  // 定义组件属性
12
13
  interface Props {
@@ -3,11 +3,11 @@ import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
3
3
  import { getConfigByName, runLogic } from '@af-mobile-client-vue3/services/api/common'
4
4
  import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
5
5
  import {
6
+ showToast,
6
7
  ActionSheet as VanActionSheet,
7
8
  Button as VanButton,
8
9
  CellGroup as VanCellGroup,
9
10
  Field as VanField,
10
- showToast,
11
11
  } from 'vant'
12
12
  import { defineEmits, defineExpose, defineProps, onBeforeMount, ref, watch } from 'vue'
13
13
 
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import CameraView from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/CameraView/index.vue'
3
- import XMultiSelect from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/XMultiSelect/index.vue'
4
2
  import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
5
3
  import XSignature from '@af-mobile-client-vue3/components/data/XSignature/index.vue'
6
4
  import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
5
+ import CameraView from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/CameraView/index.vue'
6
+ import XMultiSelect from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/XMultiSelect/index.vue'
7
7
  import dayjs from 'dayjs/esm/index'
8
8
  import { debounce } from 'lodash-es'
9
9
  import {
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import CameraView from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/CameraView/index.vue'
3
- import SecurityFormItem from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/FormItem.vue'
4
2
  import XDatePicker from '@af-mobile-client-vue3/components/core/XDatePicker/index.vue'
5
3
  import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
6
4
  import { getConfigByName } from '@af-mobile-client-vue3/services/api/common'
5
+ import CameraView from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/CameraView/index.vue'
6
+ import SecurityFormItem from '@af-mobile-client-vue3/views/SafeInspection/SecurityFormItem/FormItem.vue'
7
7
  import moment from 'moment'
8
8
  import { Field as VanField } from 'vant'
9
9
  import { defineEmits, defineProps, inject, onBeforeMount, ref } from 'vue'