af-mobile-client-vue3 1.0.54

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 (156) hide show
  1. package/.editorconfig +38 -0
  2. package/.env +7 -0
  3. package/.env.development +4 -0
  4. package/.env.envoiceShow +7 -0
  5. package/.env.production +7 -0
  6. package/.husky/commit-msg +1 -0
  7. package/.husky/pre-commit +1 -0
  8. package/.vscode/extensions.json +7 -0
  9. package/.vscode/settings.json +61 -0
  10. package/LICENSE +21 -0
  11. package/README.md +181 -0
  12. package/af-example-mobile-vue-web.iml +9 -0
  13. package/build/vite/index.ts +91 -0
  14. package/build/vite/vconsole.ts +44 -0
  15. package/eslint.config.js +7 -0
  16. package/index.html +17 -0
  17. package/mock/data.ts +20 -0
  18. package/mock/index.ts +5 -0
  19. package/mock/modules/prose.mock.ts +16 -0
  20. package/mock/modules/user.mock.ts +152 -0
  21. package/netlify.toml +12 -0
  22. package/package.json +107 -0
  23. package/public/favicon-dark.svg +4 -0
  24. package/public/favicon.ico +0 -0
  25. package/public/favicon.svg +4 -0
  26. package/public/pwa-192x192.png +0 -0
  27. package/public/pwa-512x512.png +0 -0
  28. package/public/safari-pinned-tab.svg +32 -0
  29. package/scripts/verifyCommit.js +19 -0
  30. package/src/App.vue +43 -0
  31. package/src/api/mock/index.ts +30 -0
  32. package/src/api/user/index.ts +40 -0
  33. package/src/assets/common/default-user-profile.png +0 -0
  34. package/src/assets/img/apps/apply-web.png +0 -0
  35. package/src/assets/img/apps/example-web.png +0 -0
  36. package/src/assets/img/apps/iot-web.png +0 -0
  37. package/src/assets/img/apps/linepatrol-web.png +0 -0
  38. package/src/assets/img/apps/monitor-web.png +0 -0
  39. package/src/assets/img/apps/oa-web.png +0 -0
  40. package/src/assets/img/apps/revenue-web.png +0 -0
  41. package/src/assets/img/apps/safe-check-web.png +0 -0
  42. package/src/assets/img/component/logo.png +0 -0
  43. package/src/assets/img/home/banner1.png +0 -0
  44. package/src/assets/img/home/banner2.png +0 -0
  45. package/src/assets/img/home/banner3.png +0 -0
  46. package/src/assets/img/home/banner4.png +0 -0
  47. package/src/assets/img/home/notice/icon.png +0 -0
  48. package/src/assets/img/user/login/background-shadow-1.svg +20 -0
  49. package/src/assets/img/user/login/logo-background.svg +20 -0
  50. package/src/assets/img/user/login/logo.png +0 -0
  51. package/src/assets/img/user/my/exit-login.png +0 -0
  52. package/src/assets/img/user/my/setting-arrow.png +0 -0
  53. package/src/assets/img/user/my/setting.png +0 -0
  54. package/src/bootstrap.ts +32 -0
  55. package/src/components/core/App/MicroAppView.vue +59 -0
  56. package/src/components/core/BeautifulLoading/index.vue +47 -0
  57. package/src/components/core/NavBar/index.vue +12 -0
  58. package/src/components/core/SvgIcon/index.vue +61 -0
  59. package/src/components/core/Tabbar/index.vue +38 -0
  60. package/src/components/core/Uploader/index.vue +104 -0
  61. package/src/components/core/XMultiSelect/index.vue +196 -0
  62. package/src/components/core/XSelect/index.vue +130 -0
  63. package/src/components/data/XBadge/index.vue +85 -0
  64. package/src/components/data/XCellDetail/index.vue +106 -0
  65. package/src/components/data/XCellList/index.vue +358 -0
  66. package/src/components/data/XCellListFilter/index.vue +392 -0
  67. package/src/components/data/XForm/index.vue +127 -0
  68. package/src/components/data/XFormItem/index.vue +472 -0
  69. package/src/components/data/XReportForm/XReportFormJsonRender.vue +220 -0
  70. package/src/components/data/XReportForm/index.vue +1058 -0
  71. package/src/components/layout/NormalDataLayout/index.vue +70 -0
  72. package/src/components/layout/TabBarLayout/index.vue +40 -0
  73. package/src/components.d.ts +53 -0
  74. package/src/enums/requestEnum.ts +25 -0
  75. package/src/env.d.ts +16 -0
  76. package/src/font-style/PingFangSC-Regular.woff2 +0 -0
  77. package/src/font-style/font.css +4 -0
  78. package/src/hooks/useCommon.ts +9 -0
  79. package/src/hooks/useLogin.ts +97 -0
  80. package/src/icons/svg/bird.svg +1 -0
  81. package/src/icons/svg/check-in.svg +33 -0
  82. package/src/icons/svg/dark.svg +5 -0
  83. package/src/icons/svg/github.svg +5 -0
  84. package/src/icons/svg/light.svg +5 -0
  85. package/src/icons/svg/link.svg +5 -0
  86. package/src/icons/svg/loadError.svg +1 -0
  87. package/src/icons/svg/notFound.svg +1 -0
  88. package/src/icons/svgo.yml +22 -0
  89. package/src/layout/PageLayout.vue +51 -0
  90. package/src/layout/SingleLayout.vue +35 -0
  91. package/src/locales/en-US.json +25 -0
  92. package/src/locales/zh-CN.json +25 -0
  93. package/src/main.ts +48 -0
  94. package/src/plugins/AppData.ts +38 -0
  95. package/src/plugins/GetLoginInfoService.ts +10 -0
  96. package/src/plugins/index.ts +11 -0
  97. package/src/router/README.md +8 -0
  98. package/src/router/guards.ts +60 -0
  99. package/src/router/index.ts +60 -0
  100. package/src/router/invoiceRoutes.ts +33 -0
  101. package/src/router/routes.ts +84 -0
  102. package/src/services/api/Login.ts +6 -0
  103. package/src/services/api/common.ts +98 -0
  104. package/src/services/api/index.ts +7 -0
  105. package/src/services/api/manage.ts +8 -0
  106. package/src/services/restTools.ts +37 -0
  107. package/src/settings.ts +1 -0
  108. package/src/stores/index.ts +7 -0
  109. package/src/stores/modules/cachedView.ts +31 -0
  110. package/src/stores/modules/counter.ts +19 -0
  111. package/src/stores/modules/routeTransitionName.ts +26 -0
  112. package/src/stores/modules/setting.ts +28 -0
  113. package/src/stores/modules/user.ts +180 -0
  114. package/src/stores/mutation-type.ts +7 -0
  115. package/src/styles/app.less +67 -0
  116. package/src/styles/login.less +81 -0
  117. package/src/typing.ts +3 -0
  118. package/src/utils/Storage.ts +124 -0
  119. package/src/utils/authority-utils.ts +87 -0
  120. package/src/utils/common.ts +41 -0
  121. package/src/utils/crypto.ts +39 -0
  122. package/src/utils/dataUtil.ts +42 -0
  123. package/src/utils/dictUtil.ts +51 -0
  124. package/src/utils/http/index.ts +158 -0
  125. package/src/utils/i18n.ts +41 -0
  126. package/src/utils/indexedDB.ts +180 -0
  127. package/src/utils/local-storage.ts +9 -0
  128. package/src/utils/mobileUtil.ts +26 -0
  129. package/src/utils/progress.ts +19 -0
  130. package/src/utils/routerUtil.ts +271 -0
  131. package/src/utils/set-page-title.ts +7 -0
  132. package/src/utils/validate.ts +6 -0
  133. package/src/views/chat/index.vue +153 -0
  134. package/src/views/common/LoadError.vue +64 -0
  135. package/src/views/common/NotFound.vue +68 -0
  136. package/src/views/component/EvaluateRecordView/index.vue +40 -0
  137. package/src/views/component/XCellDetailView/index.vue +216 -0
  138. package/src/views/component/XCellListView/index.vue +36 -0
  139. package/src/views/component/XFormView/index.vue +478 -0
  140. package/src/views/component/XReportFormIframeView/index.vue +45 -0
  141. package/src/views/component/XReportFormView/index.vue +295 -0
  142. package/src/views/component/index.vue +111 -0
  143. package/src/views/component/menu.vue +117 -0
  144. package/src/views/component/notice.vue +46 -0
  145. package/src/views/component/topNav.vue +36 -0
  146. package/src/views/invoiceShow/index.vue +62 -0
  147. package/src/views/user/login/ForgetPasswordForm.vue +93 -0
  148. package/src/views/user/login/LoginForm.vue +145 -0
  149. package/src/views/user/login/LoginTitle.vue +68 -0
  150. package/src/views/user/login/LoginWave.vue +109 -0
  151. package/src/views/user/login/index.vue +22 -0
  152. package/src/views/user/my/index.vue +230 -0
  153. package/src/vue-router.d.ts +9 -0
  154. package/tsconfig.json +43 -0
  155. package/uno.config.ts +32 -0
  156. package/vite.config.ts +110 -0
@@ -0,0 +1,472 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ Field as VanField,
4
+ Picker as VanPicker,
5
+ Popup as VanPopup,
6
+ Radio as VanRadio,
7
+ RadioGroup as VanRadioGroup,
8
+ Rate as VanRate,
9
+ Slider as VanSlider,
10
+ Stepper as VanStepper,
11
+ Switch as VanSwitch,
12
+ TimePicker as VanTimePicker,
13
+ DatePicker as VanDatePicker,
14
+ Area as VanArea,
15
+ Calendar as VanCalendar,
16
+ Checkbox as VanCheckbox,
17
+ CheckboxGroup as vanCheckboxGroup,
18
+ } from 'vant'
19
+ import {reactive,ref,watch,onBeforeMount} from 'vue'
20
+ import { areaList } from '@vant/area-data'
21
+ import {runLogic} from '@af-mobile-client-vue3/services/api/common'
22
+ import Uploader from '@af-mobile-client-vue3/components/core/Uploader/index.vue'
23
+ import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
24
+ import XMultiSelect from '@af-mobile-client-vue3/components/core/XMultiSelect/index.vue'
25
+
26
+ const props = defineProps({
27
+ attr: {
28
+ type: Object
29
+ },
30
+ datePickerFilter: {
31
+ type: Function,
32
+ default: () => true
33
+ },
34
+ datePickerFormatter: {
35
+ type: Function,
36
+ default: (type, val) => val
37
+ },
38
+ mode: {
39
+ type: String,
40
+ default: '查询'
41
+ },
42
+ serviceName: {
43
+ type: String,
44
+ default: undefined
45
+ },
46
+ // 调用logic获取数据源的追加参数
47
+ getDataParams: {
48
+ type: Object,
49
+ default: undefined
50
+ },
51
+ disabled: {
52
+ type: Boolean,
53
+ default: false
54
+ },
55
+ modelValue: {
56
+ type: [String, Number, Boolean, Array, Object],
57
+ default: undefined
58
+ }
59
+ })
60
+ let {attr,mode,serviceName,getDataParams,disabled,modelValue} = props
61
+ let calendarShow = ref(false)
62
+ let option = reactive([])
63
+ let localValue = ref<any>()
64
+ let pickerValue = ref(undefined)
65
+ let datePickerValue = ref(undefined)
66
+ let timePickerValue = ref(undefined)
67
+ let area = ref<any>(undefined)
68
+ let calendarValue = ref<any>('')
69
+ let showPicker = ref(false)
70
+ let showDatePicker = ref(false)
71
+ let showTimePicker = ref(false)
72
+ let showArea = ref(false)
73
+ if (modelValue) {
74
+ localValue.value = ref(modelValue)
75
+ } else {
76
+ switch (attr.formType) {
77
+ case 'switch':
78
+ localValue.value = false
79
+ break
80
+ case 'checkbox':
81
+ localValue.value = ''
82
+ break
83
+ case 'checkboxGroup':
84
+ localValue.value = []
85
+ break
86
+ case 'radio':
87
+ localValue.value = ''
88
+ break
89
+ case 'stepper':
90
+ localValue.value = 1
91
+ break
92
+ case 'rate':
93
+ localValue.value = 0
94
+ break
95
+ case 'slider':
96
+ localValue.value = 0
97
+ break
98
+ case 'uploader':
99
+ localValue.value = []
100
+ break
101
+ case 'picker':
102
+ localValue.value = undefined
103
+ break
104
+ case 'datePicker':
105
+ localValue.value = []
106
+ break
107
+ case 'timePicker':
108
+ localValue.value = []
109
+ break
110
+ case 'area':
111
+ localValue.value = ''
112
+ break
113
+ case 'calendar':
114
+ localValue.value = ''
115
+ break
116
+ case 'select':
117
+ localValue.value = []
118
+ break
119
+ case 'mul-select':
120
+ localValue.value = []
121
+ break
122
+ case 'textarea':
123
+ localValue.value = ''
124
+ break
125
+ case 'input':
126
+ localValue.value = ''
127
+ break
128
+ default:
129
+ localValue.value = undefined
130
+ break
131
+ }
132
+ }
133
+ const emits = defineEmits(['update:modelValue'])
134
+ onBeforeMount(()=>{
135
+ init()
136
+ })
137
+ function onCalendarConfirm(values) {
138
+ if (attr.calendarType === 'range'){
139
+ const [start, end] = values;
140
+ calendarValue.value = formatDate(start) + '至' + formatDate(end)
141
+ emits('update:modelValue', calendarValue.value)
142
+ } else {
143
+ calendarValue.value = formatDate(values)
144
+ emits('update:modelValue', calendarValue.value)
145
+ }
146
+ calendarShow.value = false;
147
+ }
148
+ const formatDate = (date) => `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
149
+ function dateInit(date){
150
+ return new Date(date)
151
+ }
152
+ watch(()=> localValue,(newValue, oldValue)=>{
153
+ localValue = newValue
154
+ emits('update:modelValue', localValue.value)
155
+ },{deep:true})
156
+ function init () {
157
+ if (attr.keyName && attr.keyName.indexOf('logic@') !== -1) {
158
+ getData({}, res => {
159
+ option = res
160
+ initRadioValue()
161
+ })
162
+ } else {
163
+ initRadioValue()
164
+ }
165
+ }
166
+ function initRadioValue () {
167
+ if (mode === '新增/修改' && attr.formType === 'radio' && !localValue) {
168
+ if (attr.keys && attr.keys.length > 0) {
169
+ localValue = attr.keys[0].value
170
+ } else if (option && option.length > 0) {
171
+ localValue = option[0].value
172
+ }
173
+ }
174
+ }
175
+ function getData (value, callback) {
176
+ if (value !== '') {
177
+ const logicName = attr.keyName
178
+ const logic = logicName.substring(6)
179
+ // 调用logic前设置参数
180
+ if (getDataParams && getDataParams[attr.model]) {
181
+ Object.assign(value, getDataParams[attr.model])
182
+ }
183
+ runLogic(logic, value, serviceName).then(res => {
184
+ callback(res)
185
+ })
186
+ }
187
+ }
188
+ function onPickerConfirm({ selectedOptions }) {
189
+ showPicker.value = false;
190
+ pickerValue.value = selectedOptions[0].text;
191
+ emits('update:modelValue', [selectedOptions[0].text])
192
+ }
193
+ function onDatePickerConfirm({ selectedValues }) {
194
+ showDatePicker.value = false;
195
+ datePickerValue.value = selectedValues.join('-');
196
+ emits('update:modelValue', datePickerValue.value)
197
+ }
198
+ function onTimePickerConfirm({ selectedValues }) {
199
+ showTimePicker.value = false;
200
+ timePickerValue.value = selectedValues.join(':');
201
+ emits('update:modelValue', timePickerValue.value)
202
+ }
203
+ function onAreaConfirm({ selectedOptions }) {
204
+ area.value = `${selectedOptions[0].text}-${selectedOptions[1].text}-${selectedOptions[2].text}`
205
+ showArea.value = false;
206
+ emits('update:modelValue', {
207
+ province: selectedOptions[0].text,
208
+ city: selectedOptions[1].text,
209
+ district: selectedOptions[2].text
210
+ })
211
+ }
212
+ function handleInput(e) {
213
+ localValue.value = e
214
+ emits('update:modelValue', e)
215
+ }
216
+ function clickShowPicker() {
217
+ showPicker.value = true;
218
+ }
219
+ function updateFile(files, index) {
220
+ files.forEach((file) => {
221
+ if (file.content)
222
+ delete file.content
223
+ if (file.file)
224
+ delete file.file
225
+ if (file.objectUrl)
226
+ delete file.objectUrl
227
+ })
228
+ localValue.value = files
229
+ emits('update:modelValue', localValue.value)
230
+ }
231
+ </script>
232
+
233
+ <template>
234
+ <div>
235
+ <van-field
236
+ v-if="attr.formType === 'switch'"
237
+ name="switch"
238
+ :label="attr.title">
239
+ <template #input>
240
+ <van-switch v-model="localValue" @update:model-value="(value) => emits('update:modelValue', value)"/>
241
+ </template>
242
+ </van-field>
243
+
244
+ <van-field
245
+ v-if="attr.formType === 'checkbox'"
246
+ name="checkbox"
247
+ :label="attr.title">
248
+ <template #input>
249
+ <van-checkbox v-model="localValue" :shape="attr.rule.square" @change="(value) => emits('update:modelValue', value)">
250
+ {{attr.title}}
251
+ </van-checkbox>
252
+ </template>
253
+ </van-field>
254
+
255
+ <van-field
256
+ v-if="attr.formType === 'checkboxGroup'"
257
+ name="checkboxGroup"
258
+ :label="attr.title">
259
+ <template #input>
260
+ <van-checkbox-group v-model="localValue" direction="horizontal" @change="(value) => emits('update:modelValue', value)">
261
+ <van-checkbox style="padding: 2px" :name="item.value" :shape="attr.rule.shape" v-for="(item,index) in attr.selectKey" :key="index" :value="item.value">{{ item.label }}</van-checkbox>
262
+ </van-checkbox-group>
263
+ </template>
264
+ </van-field>
265
+
266
+ <van-field
267
+ v-if="attr.formType === 'radio'"
268
+ name="radio"
269
+ :label="attr.title">
270
+ <template #input>
271
+ <van-radio-group v-model="localValue" direction="horizontal" @change="(value) => emits('update:modelValue', value)">
272
+ <van-radio style="padding: 2px" :name="item.value" v-for="(item,index) in attr.selectKey" :key="index" :value="item.value">{{ item.label }}</van-radio>
273
+ </van-radio-group>
274
+ </template>
275
+ </van-field>
276
+
277
+ <van-field
278
+ v-if="attr.formType === 'stepper'"
279
+ name="stepper"
280
+ v-model="localValue"
281
+ :label="attr.title">
282
+ <template #input>
283
+ <van-stepper v-model="localValue" @change="(value) => emits('update:modelValue', value)"/>
284
+ </template>
285
+ </van-field>
286
+
287
+ <van-field
288
+ v-if="attr.formType === 'rate'"
289
+ name="rate"
290
+ :label="attr.title">
291
+ <template #input>
292
+ <van-rate v-model="localValue" @change="(value) => emits('update:modelValue', value)"/>
293
+ </template>
294
+ </van-field>
295
+
296
+ <van-field
297
+ v-if="attr.formType === 'slider'"
298
+ name="slider"
299
+ :label="attr.title">
300
+ <template #input>
301
+ <van-slider v-model="localValue" @change="(value) => emits('update:modelValue', value)"/>
302
+ </template>
303
+ </van-field>
304
+
305
+ <van-field
306
+ v-if="attr.formType === 'uploader'"
307
+ name="uploader"
308
+ :label="attr.title">
309
+ <template #input>
310
+ <!-- <van-uploader v-model="localValue" />-->
311
+ <uploader
312
+ upload-mode="oss"
313
+ :image-list="localValue"
314
+ authority="admin"
315
+ @update-file-list="updateFile"/>
316
+ </template>
317
+ </van-field>
318
+
319
+ <van-field
320
+ v-if="attr.formType === 'picker'"
321
+ name="picker"
322
+ :label="attr.title"
323
+ is-link
324
+ readonly
325
+ v-model="pickerValue"
326
+ :placeholder="attr.placeholder"
327
+ @click="clickShowPicker">
328
+ </van-field>
329
+ <van-popup v-model:show="showPicker" round position="bottom" teleport="body">
330
+ <van-picker
331
+ v-model="localValue"
332
+ :title="attr.title"
333
+ :columns="attr.selectKey"
334
+ :readonly="attr.readonly"
335
+ @cancel="showPicker = false"
336
+ @confirm="onPickerConfirm"
337
+ :columns-field-names="attr.customFieldName ? attr.customFieldName : {text: 'text',value: 'value',children: 'children'}"
338
+ :confirm-button-text="attr.confirmButtonText || attr.confirmButtonText === '' ? attr.confirmButtonText : '确认'"
339
+ :cancel-button-text="attr.cancelButtonText || attr.cancelButtonText === '' ? attr.cancelButtonText : '取消'"
340
+ />
341
+ </van-popup>
342
+
343
+ <van-field
344
+ v-if="attr.formType === 'datePicker'"
345
+ name="datePicker"
346
+ :label="attr.title"
347
+ is-link
348
+ readonly
349
+ v-model="datePickerValue"
350
+ :placeholder="attr.placeholder"
351
+ @click="showDatePicker=true">
352
+ </van-field>
353
+ <van-popup v-model:show="showDatePicker" v-show="attr.formType === 'datePicker'" position="bottom" teleport="body">
354
+ <van-date-picker
355
+ :title="attr.lable"
356
+ v-model="localValue"
357
+ :confirm-button-text="attr.confirmButtonText ? attr.confirmButtonText : '确认'"
358
+ :cancel-button-text="attr.cancelButtonText ? attr.cancelButtonText : '取消'"
359
+ :columns-type="attr.columnsType ? attr.columnsType : ['year', 'month', 'day']"
360
+ :readonly="attr.readonly ? attr.readonly : false"
361
+ @cancel="showDatePicker = false"
362
+ @confirm="onDatePickerConfirm"
363
+ />
364
+ </van-popup>
365
+
366
+ <van-field
367
+ v-if="attr.formType === 'timePicker'"
368
+ name="timePicker"
369
+ is-link
370
+ v-model="timePickerValue"
371
+ readonly
372
+ :placeholder="attr.placeholder"
373
+ :label="attr.title"
374
+ @click="showTimePicker = true">
375
+ </van-field>
376
+ <van-popup v-model:show="showTimePicker" v-show="attr.formType === 'timePicker'" position="bottom" teleport="body">
377
+ <van-time-picker
378
+ v-model="localValue"
379
+ :title="attr.lable"
380
+ :columns-type="attr.columnsType ? attr.columnsType : ['hour', 'minute', 'second']"
381
+ :min-time="attr.minTime ? attr.minTime : '00:00:00'"
382
+ :max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
383
+ :readonly="attr.readonly ? attr.readonly : false"
384
+ @cancel="showTimePicker = false"
385
+ @confirm="onTimePickerConfirm"
386
+ />
387
+ </van-popup>
388
+
389
+ <van-field
390
+ v-if="attr.formType === 'area'"
391
+ name="area"
392
+ v-model="area"
393
+ is-link
394
+ readonly
395
+ :placeholder="attr.placeholder"
396
+ :label="attr.title"
397
+ @click="showArea = true">
398
+ </van-field>
399
+ <van-popup v-model:show="showArea" position="bottom" teleport="body">
400
+ <van-area
401
+ v-model="localValue" :title="attr.title" :area-list="areaList"
402
+ @confirm="onAreaConfirm"
403
+ @cancel="showArea = false"
404
+ />
405
+ </van-popup>
406
+ <van-field
407
+ v-if="attr.formType === 'calendar'"
408
+ v-model="calendarValue"
409
+ is-link
410
+ readonly
411
+ name="calendar"
412
+ :label="attr.title"
413
+ :placeholder="attr.placeholder"
414
+ @click="calendarShow = true"
415
+ />
416
+ <van-calendar v-model:show="calendarShow" @confirm="onCalendarConfirm" :type="attr.calendarType" teleport="body" :show-confirm="attr.showConfirm"/>
417
+
418
+ <XSelect
419
+ v-if="attr.formType === 'select'"
420
+ clearable
421
+ :rules="attr.rule"
422
+ v-model="localValue"
423
+ :placeholder="attr.placeholder ? attr.placeholder : '请选择' + attr.title"
424
+ :columns="attr.selectKey"
425
+ :option="attr.option ? attr.option : {label:'label', value:'value'}"
426
+ >
427
+ </XSelect>
428
+
429
+ <XMultiSelect
430
+ v-if="attr.formType === 'mul-select'"
431
+ v-model="localValue"
432
+ :placeholder="attr.placeholder ? attr.placeholder : '请选择' + attr.title"
433
+ :columns="attr.itemList"
434
+ :label-width="attr.labelWidth? attr.labelWidth: 100"
435
+ :option="attr.option ? attr.option : {label:'label', value:'value'}"
436
+ >
437
+ </XMultiSelect>
438
+
439
+ <van-field
440
+ v-if="attr.formType === 'textarea'"
441
+ v-model="localValue"
442
+ rows="3"
443
+ autosize
444
+ :label="attr.title"
445
+ type="textarea"
446
+ :maxlength="attr.maxlength"
447
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入' + attr.title"
448
+ show-word-limit
449
+ label-align="top"
450
+ @update:model-value="handleInput"
451
+ />
452
+
453
+ <van-field
454
+ v-if="attr.formType === 'input'"
455
+ v-model="localValue"
456
+ :rules="attr.rules"
457
+ :label="attr.title"
458
+ :required="attr.required"
459
+ :type="attr.formType"
460
+ :readonly="attr.readonly"
461
+ :disabled="attr.disabled"
462
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入' + attr.title"
463
+ :error-message="attr.errorMessage"
464
+ :clearable="attr.clearable"
465
+ @update:model-value="handleInput"
466
+ />
467
+ </div>
468
+ </template>
469
+
470
+ <style scoped>
471
+
472
+ </style>
@@ -0,0 +1,220 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ Cell as vanCell,
4
+ CellGroup as vanCellGroup,
5
+ Field as vanField,
6
+ Form as vanForm,
7
+ Image as vanImage,
8
+ } from 'vant'
9
+ import { reactive, ref } from 'vue'
10
+
11
+ const props = defineProps({
12
+ jsonConfig: Object,
13
+ })
14
+
15
+ const receivedFunction = reactive([])
16
+ const contentForMobile = ref([])
17
+
18
+ function formatConfig() {
19
+ for (let i = 0; i < props.jsonConfig.content.length; i++) {
20
+ let tempObj = {
21
+ label: undefined,
22
+ value: undefined,
23
+ valueType: 'str',
24
+ }
25
+ const item = props.jsonConfig.content[i]
26
+ if (item.type === 'jsonKey') {
27
+ if (receivedFunction[i].labelFunction(props.jsonConfig).type === 'key')
28
+ tempObj.label = props.jsonConfig.data[receivedFunction[i].labelFunction(props.jsonConfig).content]
29
+ else if (receivedFunction[i].labelFunction(props.jsonConfig).type === 'value')
30
+ tempObj.label = receivedFunction[i].labelFunction(props.jsonConfig).content
31
+
32
+ if (receivedFunction[i].valueFunction(props.jsonConfig).type === 'key') {
33
+ tempObj.value = props.jsonConfig.data[receivedFunction[i].valueFunction(props.jsonConfig).content]
34
+ }
35
+ else if (receivedFunction[i].valueFunction(props.jsonConfig).type === 'value') {
36
+ tempObj.value = receivedFunction[i].valueFunction(props.jsonConfig).content
37
+ }
38
+ else if (receivedFunction[i].valueFunction(props.jsonConfig).type === 'img') {
39
+ tempObj.valueType = 'img'
40
+ tempObj.value = receivedFunction[i].valueFunction(props.jsonConfig).content
41
+ }
42
+ contentForMobile.value.push(tempObj)
43
+ tempObj = {
44
+ label: undefined,
45
+ value: undefined,
46
+ valueType: 'str',
47
+ }
48
+ }
49
+ else if (item.type === 'jsonArray') {
50
+ for (let j = 0; j < props.jsonConfig.data[item.jsonArrayDataIndex].length; j++) {
51
+ const jsonArrayItem = props.jsonConfig.data[item.jsonArrayDataIndex][j]
52
+ if (receivedFunction[i].labelFunction(props.jsonConfig, jsonArrayItem).type === 'key')
53
+ tempObj.label = jsonArrayItem[receivedFunction[i].labelFunction(props.jsonConfig, jsonArrayItem).content]
54
+ else if (receivedFunction[i].labelFunction(props.jsonConfig, jsonArrayItem).type === 'value')
55
+ tempObj.label = receivedFunction[i].labelFunction(props.jsonConfig, jsonArrayItem).content
56
+
57
+ if (receivedFunction[i].valueFunction(props.jsonConfig, jsonArrayItem).type === 'key') {
58
+ tempObj.value = jsonArrayItem[receivedFunction[i].valueFunction(props.jsonConfig, jsonArrayItem).content]
59
+ }
60
+ else if (receivedFunction[i].valueFunction(props.jsonConfig, jsonArrayItem).type === 'value') {
61
+ tempObj.value = receivedFunction[i].valueFunction(props.jsonConfig, jsonArrayItem).content
62
+ }
63
+ else if (receivedFunction[i].valueFunction(props.jsonConfig, jsonArrayItem).type === 'img') {
64
+ tempObj.valueType = 'img'
65
+ tempObj.value = receivedFunction[i].valueFunction(props.jsonConfig, jsonArrayItem).content
66
+ }
67
+
68
+ contentForMobile.value.push(tempObj)
69
+ tempObj = {
70
+ label: undefined,
71
+ value: undefined,
72
+ valueType: 'str',
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ // ------------------------- 初始化 -------------------------
79
+ initComponent()
80
+
81
+ function initComponent() {
82
+ for (let i = 0; i < props.jsonConfig.content.length; i++) {
83
+ receivedFunction.push({
84
+ // eslint-disable-next-line no-eval
85
+ labelFunction: eval(`(${props.jsonConfig.content[i].customFunctionForLabel})`),
86
+ // eslint-disable-next-line no-eval
87
+ valueFunction: eval(`(${props.jsonConfig.content[i].customFunctionForValue})`),
88
+ })
89
+ }
90
+ formatConfig()
91
+ }
92
+ </script>
93
+
94
+ <template>
95
+ <div class="main">
96
+ <!-- 标题 -->
97
+ <template v-if="jsonConfig.title">
98
+ <template v-if="jsonConfig.title.type === 'titleKey'">
99
+ <h2 class="title" v-html="jsonConfig.data[jsonConfig.title.value]" />
100
+ </template>
101
+ <template v-else-if="jsonConfig.title.type === 'titleValue'">
102
+ <h2 class="title" v-html="jsonConfig.title.value" />
103
+ </template>
104
+ </template>
105
+ <!-- 内容 -->
106
+ <van-form>
107
+ <van-cell-group inset class="cell_group">
108
+ <template v-for="(row, rowIndex) in contentForMobile" :key="rowIndex">
109
+ <template v-if="row.valueType === 'str'">
110
+ <van-cell center :title="row.label" :value="row.value ? row.value : '无'" />
111
+ </template>
112
+ <template v-else-if="row.valueType === 'img'">
113
+ <template v-for="(img, imgIndex) in row.value" :key="imgIndex">
114
+ <van-field :name="row.label" :label="row.label">
115
+ <template #input>
116
+ <div style="width: 100%;text-align: right">
117
+ <van-image :src="img" width="100" height="100" fit="cover" />
118
+ </div>
119
+ </template>
120
+ </van-field>
121
+ </template>
122
+ </template>
123
+ </template>
124
+ </van-cell-group>
125
+ </van-form>
126
+ </div>
127
+ </template>
128
+
129
+ <style scoped lang="less">
130
+ .main{
131
+ padding-top: 4vh;
132
+ width: 100vw;
133
+ height: 100vh;
134
+ background-color: #eff2f5;
135
+
136
+ .title{
137
+ padding-bottom: 2vh;
138
+ color: rgb(50, 50, 51);
139
+ text-align: center;
140
+ margin: 0 0 3vh;
141
+ }
142
+
143
+ .text_box{
144
+ margin-top: 2vh;
145
+ margin-bottom: 2vh;
146
+ }
147
+
148
+ .main_text{
149
+ padding-left: 16px;
150
+ font-weight: 400;
151
+ line-height: 1.6;
152
+ margin: 0 0 40px;
153
+ color: #969799;
154
+ font-size: 14px;
155
+ }
156
+
157
+ .show_value_item{
158
+ text-align: center;
159
+ font-size: 1.2em;
160
+ }
161
+
162
+ .cell_group{
163
+ margin-top: 2vh;
164
+ margin-bottom: 2vh;
165
+ }
166
+
167
+ .form_item{
168
+ margin-top: 2vh;
169
+ }
170
+
171
+ .button_group{
172
+ text-align: center;
173
+ margin-top: 3vh;
174
+ margin-bottom: 3vh;
175
+ }
176
+
177
+ .button_group>:first-child {
178
+ margin-right: 3vw;
179
+ }
180
+
181
+ .divider{
182
+ color: #1989fa;
183
+ border-color: #1989fa;
184
+ padding: 0 16px
185
+ }
186
+
187
+ .submit_button{
188
+ background-color: #eff2f5;
189
+ padding: 5vh;
190
+ }
191
+ }
192
+
193
+ .skeleton{
194
+ margin-top: 5vh
195
+ }
196
+ .my-cell-group{
197
+ margin: 0 0 10px 0
198
+ }
199
+ :deep(.van-collapse-item__content) {
200
+ background-color: #eff2f5;
201
+ padding: 10px 0;
202
+ }
203
+ :deep(.van-cell-group__title){
204
+ padding-top: 10px;
205
+ padding-bottom: 10px;
206
+ }
207
+ :deep(.van-field__label) {
208
+ font-weight: 600;
209
+ }
210
+ :deep(.van-cell__title) {
211
+ font-weight: 600;
212
+ }
213
+ :deep(.van-uploader__wrapper){
214
+ padding: 10px;
215
+ display: flex;
216
+ flex-wrap: wrap;
217
+ justify-content: space-between; /* 水平方向上左右分散对齐 */
218
+ align-items: center; /* 垂直方向上上下中心对齐 */
219
+ }
220
+ </style>