af-mobile-client-vue3 1.3.12 → 1.3.14
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/.claude/settings.local.json +10 -0
- package/.cursorrules +60 -60
- package/.editorconfig +9 -9
- package/.env +10 -10
- package/.env.development +1 -1
- package/.env.production +1 -1
- package/.node-version +1 -1
- package/.vscode/extensions.json +12 -12
- package/.vscode/settings.json +66 -66
- package/CLAUDE.md +189 -184
- package/README.md +182 -181
- package/af-example-mobile-vue-web.iml +9 -9
- package/build/vite/index.ts +98 -98
- package/build/vite/optimize.ts +34 -34
- package/build/vite/vconsole.ts +47 -47
- package/commitlint.config.ts +32 -32
- package/compress.js +36 -36
- package/eslint.config.ts +30 -30
- package/index.html +23 -23
- package/mock/data.ts +20 -20
- package/mock/index.ts +7 -7
- package/mock/modules/prose.mock.ts +13 -13
- package/mock/modules/user.mock.ts +152 -152
- package/mock/util.ts +19 -19
- package/netlify.toml +12 -12
- package/package.json +114 -114
- package/postcss.config.ts +27 -27
- package/public/favicon.svg +4 -4
- package/public/safari-pinned-tab.svg +4 -4
- package/scripts/verifyCommit.js +19 -19
- package/src/App.vue +79 -79
- package/src/api/mock/index.ts +30 -30
- package/src/api/user/index.ts +40 -40
- package/src/assets/img/user/login/background-shadow-1.svg +20 -20
- package/src/assets/img/user/login/logo-background.svg +20 -20
- package/src/bootstrap.ts +26 -26
- package/src/components/core/BeautifulLoading/index.vue +52 -52
- package/src/components/core/ImageUploader/index.vue +244 -244
- package/src/components/core/NavBar/index.vue +53 -53
- package/src/components/core/Tabbar/index.vue +32 -32
- package/src/components/core/Uploader/index.vue +124 -124
- package/src/components/core/XGridDropOption/index.vue +154 -156
- package/src/components/core/XMultiSelect/index.vue +183 -183
- package/src/components/core/XSelect/index.vue +149 -149
- package/src/components/data/InfoDisplay/index.vue +132 -0
- package/src/components/data/UserDetail/api.ts +24 -0
- package/src/components/data/UserDetail/index.vue +620 -0
- package/src/components/data/UserDetail/recordEntries.ts +159 -0
- package/src/components/data/UserDetail/types.ts +26 -0
- package/src/components/data/XBadge/index.vue +82 -82
- package/src/components/data/XCellDetail/index.vue +105 -105
- package/src/components/data/XCellList/XCellList.md +313 -313
- package/src/components/data/XCellList/index.vue +1075 -1075
- package/src/components/data/XCellListFilter/QrScanner/index.vue +207 -207
- package/src/components/data/XCellListFilter/QrScanner/startScanAnimation.ts +53 -53
- package/src/components/data/XCellListFilter/VpnRecognition/index.vue +119 -119
- package/src/components/data/XCellListFilter/index.vue +705 -705
- package/src/components/data/XForm/index.vue +659 -659
- package/src/components/data/XFormGroup/doc/DeviceForm.vue +122 -122
- package/src/components/data/XFormGroup/doc/FormGroupDemo.vue +56 -56
- package/src/components/data/XFormGroup/doc/README.md +286 -273
- package/src/components/data/XFormGroup/doc/UserForm.vue +102 -102
- package/src/components/data/XFormGroup/index.vue +240 -240
- package/src/components/data/XFormItem/index.vue +1310 -1310
- package/src/components/data/XOlMap/README.md +227 -227
- package/src/components/data/XOlMap/XLocationPicker/index.vue +226 -225
- package/src/components/data/XOlMap/index.vue +1490 -1490
- package/src/components/data/XOlMap/types.ts +149 -149
- package/src/components/data/XOlMap/utils/wgs84ToGcj02.js +154 -154
- package/src/components/data/XReportForm/DateTimeSecondsPicker.vue +208 -208
- package/src/components/data/XReportForm/XReportFormJsonRender.vue +220 -220
- package/src/components/data/XReportForm/index.vue +1393 -1393
- package/src/components/data/XReportGrid/XAddReport/XAddReport.vue +198 -198
- package/src/components/data/XReportGrid/XAddReport/index.js +3 -3
- package/src/components/data/XReportGrid/XAddReport/index.md +53 -52
- package/src/components/data/XReportGrid/XAddReport/index.ts +10 -10
- package/src/components/data/XReportGrid/XReport.vue +960 -960
- package/src/components/data/XReportGrid/XReportDemo.vue +33 -33
- package/src/components/data/XReportGrid/XReportDesign.vue +597 -597
- package/src/components/data/XReportGrid/XReportDrawer/XReportDrawer.vue +148 -148
- package/src/components/data/XReportGrid/XReportDrawer/index.js +3 -3
- package/src/components/data/XReportGrid/XReportDrawer/index.ts +10 -10
- package/src/components/data/XReportGrid/XReportJsonRender.vue +399 -399
- package/src/components/data/XReportGrid/XReportTrGroup.vue +592 -592
- package/src/components/data/XReportGrid/index.md +46 -42
- package/src/components/data/XReportGrid/print.js +184 -184
- package/src/components/data/XSignature/index.vue +284 -285
- package/src/components/data/XTag/index.vue +10 -10
- package/src/components/layout/NormalDataLayout/index.vue +69 -69
- package/src/components/layout/TabBarLayout/index.vue +40 -40
- package/src/composables/dark.ts +5 -5
- package/src/config/routes.ts +9 -9
- package/src/constants/index.ts +2 -2
- package/src/enums/requestEnum.ts +25 -25
- package/src/expression/ExpressionRunner.ts +28 -28
- package/src/expression/TestExpression.ts +510 -510
- package/src/expression/core/Delegate.ts +116 -116
- package/src/expression/core/Expression.ts +1359 -1359
- package/src/expression/core/Program.ts +985 -985
- package/src/expression/core/Token.ts +29 -29
- package/src/expression/enums/ExpressionType.ts +81 -81
- package/src/expression/enums/TokenType.ts +11 -11
- package/src/expression/exception/BreakWayException.ts +2 -2
- package/src/expression/exception/ContinueWayException.ts +2 -2
- package/src/expression/exception/ExpressionException.ts +29 -29
- package/src/expression/exception/ReturnWayException.ts +14 -14
- package/src/expression/exception/ServiceException.ts +22 -22
- package/src/expression/instances/JSONArray.ts +52 -52
- package/src/expression/instances/JSONObject.ts +118 -118
- package/src/expression/instances/LogicConsole.ts +31 -31
- package/src/font-style/font.css +4 -4
- package/src/hooks/useBoolean.ts +26 -0
- package/src/hooks/useCommon.ts +9 -9
- package/src/hooks/useLoading.ts +16 -0
- package/src/hooks/useLogin.ts +97 -97
- package/src/icons/svg/check-in.svg +32 -32
- package/src/icons/svg/dark.svg +4 -4
- package/src/icons/svg/github.svg +4 -4
- package/src/icons/svg/light.svg +4 -4
- package/src/icons/svg/link.svg +4 -4
- package/src/icons/svgo.yml +22 -22
- package/src/layout/GridView/index.vue +16 -16
- package/src/layout/PageLayout.vue +9 -9
- package/src/layout/SingleLayout.vue +9 -9
- package/src/locales/en-US.json +128 -128
- package/src/locales/zh-CN.json +128 -128
- package/src/logic/LogicRunner.ts +67 -67
- package/src/logic/TestLogic.ts +13 -13
- package/src/logic/plugins/common/DateTools.ts +35 -35
- package/src/logic/plugins/common/VueTools.ts +30 -30
- package/src/logic/plugins/index.ts +7 -7
- package/src/main.ts +44 -44
- package/src/plugins/AppData.ts +38 -38
- package/src/plugins/GetLoginInfoService.ts +10 -10
- package/src/plugins/collectIcons.ts +10 -0
- package/src/plugins/index.ts +11 -11
- package/src/router/README.md +8 -8
- package/src/router/guards.ts +59 -59
- package/src/router/index.ts +35 -35
- package/src/router/invoiceRoutes.ts +33 -33
- package/src/router/routes.ts +341 -177
- package/src/router/types.ts +7 -7
- package/src/services/api/Login.ts +6 -6
- package/src/services/api/common.ts +109 -109
- package/src/services/api/index.ts +7 -7
- package/src/services/api/manage.ts +8 -8
- package/src/services/api/search.ts +16 -16
- package/src/services/api/user.ts +17 -17
- package/src/services/restTools.ts +56 -56
- package/src/services/v3Api.ts +147 -147
- package/src/stores/index.ts +11 -11
- package/src/stores/modules/counter.ts +19 -19
- package/src/stores/modules/routeCache.ts +23 -23
- package/src/stores/modules/setting.ts +76 -76
- package/src/stores/modules/user.ts +235 -235
- package/src/stores/mutation-type.ts +7 -7
- package/src/styles/app.less +36 -36
- package/src/styles/login.less +109 -109
- package/src/styles/var.less +16 -16
- package/src/types/env.d.ts +16 -16
- package/src/types/settings.ts +1 -1
- package/src/types/vue-router.d.ts +9 -9
- package/src/utils/Storage.ts +124 -124
- package/src/utils/authority-utils.ts +84 -84
- package/src/utils/common.ts +41 -41
- package/src/utils/crypto.ts +39 -39
- package/src/utils/dataUtil.ts +42 -42
- package/src/utils/dictUtil.ts +52 -52
- package/src/utils/http/index.ts +199 -199
- package/src/utils/i18n.ts +72 -72
- package/src/utils/indexedDB.ts +195 -195
- package/src/utils/inline-px-to-vw.ts +28 -28
- package/src/utils/mobileUtil.ts +34 -34
- package/src/utils/progress.ts +19 -19
- package/src/utils/routerUtil.ts +271 -271
- package/src/utils/runEvalFunction.ts +13 -13
- package/src/utils/secureStorage.ts +71 -71
- package/src/utils/set-page-title.ts +5 -5
- package/src/utils/validate.ts +6 -6
- package/src/utils/wechatUtil.ts +9 -9
- package/src/views/chat/index.vue +153 -153
- package/src/views/common/LoadError.vue +63 -63
- package/src/views/common/NotFound.vue +67 -67
- package/src/views/component/EvaluateRecordView/index.vue +40 -40
- package/src/views/component/IconifyView/index.vue +504 -507
- package/src/views/component/UserDetailView/UserDetailPage.vue +77 -0
- package/src/views/component/UserDetailView/index.vue +234 -0
- package/src/views/component/XCellDetailView/index.vue +217 -217
- package/src/views/component/XCellListView/index.vue +108 -157
- package/src/views/component/XFormAppraiseView/index.vue +174 -174
- package/src/views/component/XFormGroupView/index.vue +78 -82
- package/src/views/component/XFormView/index.vue +27 -27
- package/src/views/component/XOlMapView/XLocationPicker/index.vue +118 -118
- package/src/views/component/XOlMapView/index.vue +434 -434
- package/src/views/component/XOlMapView/testData.ts +64 -64
- package/src/views/component/XReportFormIframeView/index.vue +47 -47
- package/src/views/component/XReportFormView/index.vue +13 -13
- package/src/views/component/XReportGridView/index.vue +17 -17
- package/src/views/component/XRequestView/index.vue +234 -234
- package/src/views/component/XSignatureView/index.vue +50 -50
- package/src/views/component/index.vue +181 -177
- package/src/views/component/menu.vue +117 -117
- package/src/views/component/notice.vue +46 -46
- package/src/views/component/topNav.vue +36 -36
- package/src/views/invoiceShow/index.vue +61 -61
- package/src/views/user/login/ForgetPasswordForm.vue +94 -94
- package/src/views/user/login/LoginForm.vue +346 -346
- package/src/views/user/login/LoginTitle.vue +76 -76
- package/src/views/user/login/LoginWave.vue +109 -109
- package/src/views/user/login/index.vue +22 -22
- package/src/views/user/my/comm/ModifyPassword.vue +346 -346
- package/src/views/user/my/index.vue +340 -340
- package/src/views/userRecords/AbnormalAlarmRecords.vue +21 -0
- package/src/views/userRecords/CardReplacementRecords.vue +21 -0
- package/src/views/userRecords/ChangeRecords.vue +19 -0
- package/src/views/userRecords/CommandViewRecords.vue +20 -0
- package/src/views/userRecords/GasCompensationRecords.vue +20 -0
- package/src/views/userRecords/InstrumentCollectionRecords.vue +21 -0
- package/src/views/userRecords/MeterRecords.vue +20 -0
- package/src/views/userRecords/OperateRecords.vue +51 -0
- package/src/views/userRecords/OtherChargeRecords.vue +19 -0
- package/src/views/userRecords/PaymentRecords.vue +28 -0
- package/src/views/userRecords/PriceAdjustmentRecords.vue +19 -0
- package/src/views/userRecords/ReplacementRecords.vue +19 -0
- package/src/views/userRecords/SafetyRecords.vue +19 -0
- package/src/views/userRecords/TransactionRecords.vue +21 -0
- package/src/views/userRecords/TransferRecords.vue +19 -0
- package/src/views/userRecords/operateRecordDetail/index.vue +316 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AddUserDetail.vue +124 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AdvanceDeliveryDetail.vue +88 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsCancelDetail.vue +205 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsDetail.vue +192 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankDkDetail.vue +192 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankPayDetail.vue +192 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BlacklistDetail.vue +153 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CancellationDetail.vue +101 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterCancelDetail.vue +127 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterDetail.vue +153 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardOverUserDetail.vue +153 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterCancelDetail.vue +166 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterDetail.vue +205 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/DisableManageDetail.vue +127 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/EnableManageDetail.vue +114 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FaZheChangeDetail.vue +124 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FeeDeductionDetail.vue +153 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/GasPriceChangeDetail.vue +126 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/InputtorChangeDetail.vue +126 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterCancelDetail.vue +114 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterDetail.vue +127 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotOpenDetail.vue +88 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineCardDetail.vue +101 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterCancelDetail.vue +218 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterDetail.vue +153 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OffGasAddGasDetail.vue +140 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeCancelDetail.vue +127 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeDetail.vue +114 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OverUserChangeDetail.vue +127 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReBillDetail.vue +127 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/RefundDetail.vue +114 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageCancelDetail.vue +127 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageDetail.vue +114 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/SaleCardGasDetail.vue +140 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageCancelDetail.vue +152 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageDetail.vue +178 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/UserChangeDetail.vue +123 -0
- package/src/views/userRecords/operateRecordDetail/operateRecordDetails/WechatPayDetail.vue +192 -0
- package/src/views/userRecords/types.ts +66 -0
- package/tsconfig.json +39 -39
- package/uno.config.ts +82 -78
- package/vite.config.ts +118 -118
- package/src/views/component/XFormGroupView/xformgroup222.vue +0 -97
|
@@ -1,659 +1,659 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { FormInstance } from 'vant'
|
|
3
|
-
import XFormItem from '@af-mobile-client-vue3/components/data/XFormItem/index.vue'
|
|
4
|
-
import XOlMap from '@af-mobile-client-vue3/components/data/XOlMap/index.vue'
|
|
5
|
-
import { formatDate } from '@af-mobile-client-vue3/hooks/useCommon'
|
|
6
|
-
import { addOrModifyEntity, getConfigByName, runLogic } from '@af-mobile-client-vue3/services/api/common'
|
|
7
|
-
import { useUserStore } from '@af-mobile-client-vue3/stores'
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
showFailToast,
|
|
11
|
-
showSuccessToast,
|
|
12
|
-
Button as VanButton,
|
|
13
|
-
CellGroup as VanCellGroup,
|
|
14
|
-
Form as VanForm,
|
|
15
|
-
} from 'vant'
|
|
16
|
-
import { computed, defineEmits, defineProps, inject, nextTick, onBeforeMount, reactive, ref, watch } from 'vue'
|
|
17
|
-
|
|
18
|
-
interface FormItem {
|
|
19
|
-
addOrEdit: string
|
|
20
|
-
isOnlyAddOrEdit?: boolean
|
|
21
|
-
type?: string
|
|
22
|
-
model?: string
|
|
23
|
-
name?: string
|
|
24
|
-
rule?: {
|
|
25
|
-
type: string
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface SilenceAddFormItem extends FormItem {
|
|
30
|
-
silencePurpose: string
|
|
31
|
-
silenceSource?: string
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface GroupFormItems {
|
|
35
|
-
btnName?: string
|
|
36
|
-
formJson: any[] // 根据实际类型调整
|
|
37
|
-
showSubmitBtn?: boolean
|
|
38
|
-
groupName?: string
|
|
39
|
-
tableName?: string
|
|
40
|
-
paramLogicName?: string
|
|
41
|
-
isGroupForm?: boolean
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface InitParams {
|
|
45
|
-
formItems?: GroupFormItems
|
|
46
|
-
formData?: object
|
|
47
|
-
getDataParams?: object
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const props = withDefaults(defineProps<{
|
|
51
|
-
configName?: string
|
|
52
|
-
groupTitle?: string
|
|
53
|
-
groupFormItems?: GroupFormItems
|
|
54
|
-
serviceName?: string
|
|
55
|
-
formData?: object
|
|
56
|
-
formName?: string
|
|
57
|
-
mode?: string
|
|
58
|
-
submitButton?: boolean
|
|
59
|
-
isHandleFormKey?: boolean
|
|
60
|
-
paramLogicNameParam?: any
|
|
61
|
-
isGroupForm?: boolean
|
|
62
|
-
}>(), {
|
|
63
|
-
configName: undefined,
|
|
64
|
-
groupTitle: undefined,
|
|
65
|
-
groupFormItems: null,
|
|
66
|
-
serviceName: undefined,
|
|
67
|
-
formData: null,
|
|
68
|
-
formName: 'default',
|
|
69
|
-
mode: '查询',
|
|
70
|
-
submitButton: true,
|
|
71
|
-
isHandleFormKey: true,
|
|
72
|
-
paramLogicNameParam: {},
|
|
73
|
-
isGroupForm: false,
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
const emits = defineEmits(['onSubmit', 'xFormItemEmitFunc'])
|
|
77
|
-
const userStore = useUserStore()
|
|
78
|
-
|
|
79
|
-
// inject
|
|
80
|
-
const formDataChange = inject('formDataChange', null)
|
|
81
|
-
|
|
82
|
-
// 核心状态
|
|
83
|
-
const xFormRef = ref<FormInstance>()
|
|
84
|
-
const loaded = ref(false)
|
|
85
|
-
const form = ref({})
|
|
86
|
-
const rules = reactive({})
|
|
87
|
-
const myGetDataParams = ref({})
|
|
88
|
-
|
|
89
|
-
// 配置相关状态
|
|
90
|
-
const formConfig = ref<GroupFormItems | null>(null)
|
|
91
|
-
const formGroupName = ref<string>('default')
|
|
92
|
-
const myServiceName = ref('')
|
|
93
|
-
const tableName = ref('')
|
|
94
|
-
|
|
95
|
-
// 计算属性
|
|
96
|
-
const realJsonData = computed(() => {
|
|
97
|
-
const sourceFormItems = formConfig.value?.formJson
|
|
98
|
-
if (!sourceFormItems)
|
|
99
|
-
return []
|
|
100
|
-
|
|
101
|
-
return sourceFormItems.filter((item) => {
|
|
102
|
-
return item.addOrEdit !== 'no'
|
|
103
|
-
})
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
// 过滤出用于静默新增场景的表单项
|
|
107
|
-
const silenceAddJsonData = computed(() => {
|
|
108
|
-
return realJsonData.value.filter((item) => {
|
|
109
|
-
return item.addOrEdit === 'silenceAdd'
|
|
110
|
-
}) as SilenceAddFormItem[]
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
const resolvedSubmitButton = computed(() => {
|
|
114
|
-
if (props.configName && formConfig.value?.showSubmitBtn !== undefined) {
|
|
115
|
-
return formConfig.value.showSubmitBtn
|
|
116
|
-
}
|
|
117
|
-
return props.submitButton
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
// 地图预览相关
|
|
121
|
-
const previewMapRef = ref(null)
|
|
122
|
-
const previewLonLatKey = computed(() => {
|
|
123
|
-
const item = realJsonData.value.find(i => i.type === 'addressSearch')
|
|
124
|
-
return item ? `${item.model}_lon_lat` : null
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
const previewMapPoint = computed(() => {
|
|
128
|
-
const val = form.value[previewLonLatKey.value]
|
|
129
|
-
if (val && typeof val === 'string' && val.includes(',')) {
|
|
130
|
-
const [lon, lat] = val.split(',').map(Number)
|
|
131
|
-
if (!Number.isNaN(lon) && !Number.isNaN(lat)) {
|
|
132
|
-
return [lon, lat]
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return null
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
// 地图初始化逻辑
|
|
139
|
-
const previewMapInited = ref(false)
|
|
140
|
-
watch(previewMapPoint, async (val) => {
|
|
141
|
-
await nextTick()
|
|
142
|
-
if (val && previewMapRef.value) {
|
|
143
|
-
if (!previewMapInited.value) {
|
|
144
|
-
await previewMapRef.value.init({ center: val, zoom: 16, isPreview: true })
|
|
145
|
-
previewMapInited.value = true
|
|
146
|
-
}
|
|
147
|
-
previewMapRef.value.setCenter(val, true)
|
|
148
|
-
previewMapRef.value.updateLocationMarker(val)
|
|
149
|
-
}
|
|
150
|
-
}, { immediate: true })
|
|
151
|
-
|
|
152
|
-
// 统一的初始化函数 - 仅在组件挂载时调用
|
|
153
|
-
async function initializeForm() {
|
|
154
|
-
loaded.value = false
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
if (props.configName) {
|
|
158
|
-
await loadFormConfig()
|
|
159
|
-
}
|
|
160
|
-
else if (props.groupFormItems) {
|
|
161
|
-
await initWithGroupFormItems()
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
console.warn('未提供配置名称或表单配置,等待 init 函数调用')
|
|
165
|
-
resetForm()
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
catch (error) {
|
|
169
|
-
console.error('表单初始化失败:', error)
|
|
170
|
-
resetForm()
|
|
171
|
-
}
|
|
172
|
-
finally {
|
|
173
|
-
loaded.value = true
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// 加载配置的方式初始化
|
|
178
|
-
async function loadFormConfig(): Promise<void> {
|
|
179
|
-
return new Promise((resolve, reject) => {
|
|
180
|
-
getConfigByName(props.configName!, (result) => {
|
|
181
|
-
if (result) {
|
|
182
|
-
setupFormConfig(result)
|
|
183
|
-
resolve()
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
console.warn(`配置 '${props.configName}' 不存在`)
|
|
187
|
-
reject(new Error(`配置 '${props.configName}' 不存在`))
|
|
188
|
-
}
|
|
189
|
-
}, props.serviceName)
|
|
190
|
-
})
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// 直接使用 groupFormItems 初始化
|
|
194
|
-
async function initWithGroupFormItems() {
|
|
195
|
-
if (!props.groupFormItems) {
|
|
196
|
-
throw new Error('groupFormItems 不能为空')
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
setupFormConfig(props.groupFormItems)
|
|
200
|
-
|
|
201
|
-
// 设置表名
|
|
202
|
-
if (props.groupFormItems.tableName) {
|
|
203
|
-
tableName.value = props.groupFormItems.tableName.split(' ')[0] || ''
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// 设置表单配置
|
|
208
|
-
function setupFormConfig(config: GroupFormItems) {
|
|
209
|
-
loadParamLogicNameData(config.paramLogicName)
|
|
210
|
-
formConfig.value = config
|
|
211
|
-
myServiceName.value = props.serviceName || ''
|
|
212
|
-
formGroupName.value = config.groupName || 'default'
|
|
213
|
-
form.value = props.formData || {}
|
|
214
|
-
// 清理并重新设置验证规则
|
|
215
|
-
setupValidationRules()
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 设置验证规则
|
|
219
|
-
function setupValidationRules() {
|
|
220
|
-
// 清理现有规则
|
|
221
|
-
Object.keys(rules).forEach(key => delete rules[key])
|
|
222
|
-
|
|
223
|
-
// 为每个表单项设置规则
|
|
224
|
-
for (const item of realJsonData.value) {
|
|
225
|
-
if (item.rule) {
|
|
226
|
-
setFormRule(item)
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// 设置单个表单项的验证规则
|
|
232
|
-
function setFormRule(item: FormItem) {
|
|
233
|
-
if (!item.model || !item.rule)
|
|
234
|
-
return
|
|
235
|
-
|
|
236
|
-
rules[item.model] = []
|
|
237
|
-
let defaultValue: any
|
|
238
|
-
let message: string
|
|
239
|
-
|
|
240
|
-
switch (item.rule.type) {
|
|
241
|
-
case 'number':
|
|
242
|
-
message = '数字'
|
|
243
|
-
defaultValue = 0
|
|
244
|
-
break
|
|
245
|
-
case 'integer':
|
|
246
|
-
message = '整数'
|
|
247
|
-
defaultValue = 0
|
|
248
|
-
break
|
|
249
|
-
case 'float':
|
|
250
|
-
message = '小数'
|
|
251
|
-
defaultValue = 0.0
|
|
252
|
-
break
|
|
253
|
-
case 'string':
|
|
254
|
-
message = '字符串'
|
|
255
|
-
defaultValue = ''
|
|
256
|
-
break
|
|
257
|
-
default:
|
|
258
|
-
return
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
rules[item.model].push({
|
|
262
|
-
type: item.rule.type,
|
|
263
|
-
message: `${item.name || item.model}必须为${message}`,
|
|
264
|
-
transform: (value: any) => {
|
|
265
|
-
if (value && value.length !== 0) {
|
|
266
|
-
return Number(value)
|
|
267
|
-
}
|
|
268
|
-
else {
|
|
269
|
-
return defaultValue
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
trigger: 'blur',
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// 重置表单状态
|
|
277
|
-
function resetForm() {
|
|
278
|
-
formConfig.value = null
|
|
279
|
-
formGroupName.value = 'default'
|
|
280
|
-
myServiceName.value = ''
|
|
281
|
-
tableName.value = ''
|
|
282
|
-
form.value = {}
|
|
283
|
-
Object.keys(rules).forEach(key => delete rules[key])
|
|
284
|
-
myGetDataParams.value = {}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// 监听 formData 变化
|
|
288
|
-
watch(() => props.formData, (newVal) => {
|
|
289
|
-
if (newVal) {
|
|
290
|
-
Object.assign(form, newVal)
|
|
291
|
-
}
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
watch(form, (newVal) => {
|
|
295
|
-
if (typeof formDataChange === 'function') {
|
|
296
|
-
formDataChange(newVal)
|
|
297
|
-
}
|
|
298
|
-
}, { deep: true })
|
|
299
|
-
|
|
300
|
-
// 组件挂载时初始化
|
|
301
|
-
onBeforeMount(() => {
|
|
302
|
-
initializeForm()
|
|
303
|
-
})
|
|
304
|
-
|
|
305
|
-
// 支持函数调用方式初始化
|
|
306
|
-
function init(params: InitParams) {
|
|
307
|
-
const {
|
|
308
|
-
formItems,
|
|
309
|
-
formData = {},
|
|
310
|
-
getDataParams = {},
|
|
311
|
-
} = params
|
|
312
|
-
|
|
313
|
-
// 重置状态
|
|
314
|
-
loaded.value = false
|
|
315
|
-
|
|
316
|
-
try {
|
|
317
|
-
if (props.configName) {
|
|
318
|
-
// 通过 props 中的配置名称初始化
|
|
319
|
-
loadFormConfig()
|
|
320
|
-
}
|
|
321
|
-
else if (formItems) {
|
|
322
|
-
// 直接使用传入的配置初始化
|
|
323
|
-
setupFormConfig(formItems)
|
|
324
|
-
form.value = formData || props.formData || {}
|
|
325
|
-
myGetDataParams.value = getDataParams
|
|
326
|
-
|
|
327
|
-
// 设置表名
|
|
328
|
-
if (formItems.tableName) {
|
|
329
|
-
tableName.value = formItems.tableName.split(' ')[0] || ''
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
console.warn('init 函数调用时既没有 props.configName 也没有 formItems')
|
|
334
|
-
resetForm()
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
catch (error) {
|
|
338
|
-
console.error('init 函数初始化失败:', error)
|
|
339
|
-
resetForm()
|
|
340
|
-
}
|
|
341
|
-
finally {
|
|
342
|
-
loaded.value = true
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function loadParamLogicNameData(paramLogicName) {
|
|
347
|
-
// 如果有 paramLogicName,自动请求并赋值
|
|
348
|
-
if (paramLogicName && (!props.formData || (props.formData && Object.keys(props.formData).length === 0))) {
|
|
349
|
-
let logicParam = props?.paramLogicNameParam || {}
|
|
350
|
-
if (typeof logicParam === 'string') {
|
|
351
|
-
try {
|
|
352
|
-
logicParam = JSON.parse(logicParam)
|
|
353
|
-
}
|
|
354
|
-
catch {
|
|
355
|
-
logicParam = { value: logicParam }
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
logicParam = {
|
|
359
|
-
...logicParam,
|
|
360
|
-
currUserName: userStore.getUserInfo().name,
|
|
361
|
-
currUserId: userStore.getUserInfo().id,
|
|
362
|
-
orgId: userStore.getUserInfo().orgid,
|
|
363
|
-
}
|
|
364
|
-
runLogic(paramLogicName, logicParam || {}, props.serviceName).then((data: any) => {
|
|
365
|
-
if (data) {
|
|
366
|
-
form.value = data
|
|
367
|
-
}
|
|
368
|
-
})
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
function setForm(obj: object) {
|
|
373
|
-
Object.assign(form.value, obj)
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// 获取表单字段实际值
|
|
377
|
-
function getRealKey(key: string, mustHandleKey = false) {
|
|
378
|
-
if (key === 'selected_id')
|
|
379
|
-
return key
|
|
380
|
-
if (props.isHandleFormKey || mustHandleKey) {
|
|
381
|
-
return key.substring(key.indexOf('_') + 1)
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
return key
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
async function asyncSubmit() {
|
|
389
|
-
return new Promise((resolve, reject) => {
|
|
390
|
-
validate().then(async () => {
|
|
391
|
-
const cleanedForm = prepareForm()
|
|
392
|
-
await appendSilenceAddFields(cleanedForm)
|
|
393
|
-
const realForm = handleFormKeys(cleanedForm)
|
|
394
|
-
resolve({
|
|
395
|
-
realForm,
|
|
396
|
-
mode: props.mode,
|
|
397
|
-
serviceName: props.serviceName,
|
|
398
|
-
currUserName: userStore.getUserInfo().name,
|
|
399
|
-
currUserId: userStore.getUserInfo().id,
|
|
400
|
-
orgId: userStore.getUserInfo().orgid,
|
|
401
|
-
})
|
|
402
|
-
}).catch((error) => {
|
|
403
|
-
reject(error)
|
|
404
|
-
})
|
|
405
|
-
})
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
function handleFormKeys(form: any, mustHandleKey = false) {
|
|
409
|
-
const realForm: any = {}
|
|
410
|
-
for (const key of Object.keys(form)) {
|
|
411
|
-
const value = form[key]
|
|
412
|
-
const extraFormKeyTagIndex = key.indexOf('@')
|
|
413
|
-
if (extraFormKeyTagIndex !== -1) {
|
|
414
|
-
const extraFormKey = key.substring(0, extraFormKeyTagIndex)
|
|
415
|
-
const realKey = key.substring(extraFormKeyTagIndex + 1)
|
|
416
|
-
if (!realForm[extraFormKey]) {
|
|
417
|
-
realForm[extraFormKey] = {}
|
|
418
|
-
}
|
|
419
|
-
realForm[extraFormKey][realKey] = value
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
const realKey = props.isHandleFormKey || mustHandleKey ? getRealKey(key, mustHandleKey) : key
|
|
423
|
-
// 如果发生重名,不覆盖,把key的别名带上
|
|
424
|
-
if (realForm[realKey]) {
|
|
425
|
-
realForm[key] = value
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
realForm[realKey] = value
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return realForm
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
async function appendSilenceAddFields(form: any) {
|
|
436
|
-
if (props.mode === '新增') {
|
|
437
|
-
for (const item of silenceAddJsonData.value) {
|
|
438
|
-
switch (item.silencePurpose) {
|
|
439
|
-
case 'createTime':
|
|
440
|
-
form[item.model] = formatDate(new Date())
|
|
441
|
-
break
|
|
442
|
-
case 'operator':
|
|
443
|
-
form[item.model] = userStore.getUserInfo().name
|
|
444
|
-
break
|
|
445
|
-
case 'operatorId':
|
|
446
|
-
form[item.model] = userStore.getUserInfo().id
|
|
447
|
-
break
|
|
448
|
-
case 'orgId':
|
|
449
|
-
form[item.model] = userStore.getUserInfo().orgid
|
|
450
|
-
break
|
|
451
|
-
case 'orgName':
|
|
452
|
-
form[item.model] = userStore.getUserInfo().orgs
|
|
453
|
-
break
|
|
454
|
-
case 'depId':
|
|
455
|
-
form[item.model] = userStore.getUserInfo().depids
|
|
456
|
-
break
|
|
457
|
-
case 'depName':
|
|
458
|
-
form[item.model] = userStore.getUserInfo().deps
|
|
459
|
-
break
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
for (const item of silenceAddJsonData.value.filter(item => item.silencePurpose === 'customize')) {
|
|
463
|
-
const result: any = await runLogic(item.silenceSource!, form, props.serviceName)
|
|
464
|
-
if (result) {
|
|
465
|
-
const keys = Object.keys(result)
|
|
466
|
-
if (keys.length === 1 && keys[0] === 'value') {
|
|
467
|
-
form[item.model] = result.value
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
form[item.model] = result
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
else {
|
|
474
|
-
form[item.model] = result
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
function prepareForm() {
|
|
481
|
-
const formObj = { ...form.value }
|
|
482
|
-
const cleanedForm: any = {}
|
|
483
|
-
|
|
484
|
-
for (const key of Object.keys(formObj)) {
|
|
485
|
-
const value = formObj[key]
|
|
486
|
-
|
|
487
|
-
// 跳过无效值
|
|
488
|
-
if (value === null || value === undefined || value === '') {
|
|
489
|
-
continue
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// 处理数组
|
|
493
|
-
if (Array.isArray(value)) {
|
|
494
|
-
// 过滤掉空字符串、null、undefined
|
|
495
|
-
const filteredArray = value.filter(item =>
|
|
496
|
-
item !== null && item !== undefined && item !== '',
|
|
497
|
-
)
|
|
498
|
-
// 只有当数组不为空时才添加
|
|
499
|
-
if (filteredArray.length > 0) {
|
|
500
|
-
cleanedForm[key] = filteredArray
|
|
501
|
-
}
|
|
502
|
-
continue
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
// 处理对象
|
|
506
|
-
if (typeof value === 'object' && value !== null) {
|
|
507
|
-
// 检查对象是否为空
|
|
508
|
-
const objectKeys = Object.keys(value)
|
|
509
|
-
if (objectKeys.length === 0) {
|
|
510
|
-
continue
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// 递归清理对象内部
|
|
514
|
-
const cleanedObject: any = {}
|
|
515
|
-
let hasValidValue = false
|
|
516
|
-
|
|
517
|
-
for (const objKey of objectKeys) {
|
|
518
|
-
const objValue = value[objKey]
|
|
519
|
-
if (objValue !== null && objValue !== undefined && objValue !== '') {
|
|
520
|
-
cleanedObject[objKey] = objValue
|
|
521
|
-
hasValidValue = true
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
// 只有当对象有有效值时才添加
|
|
526
|
-
if (hasValidValue) {
|
|
527
|
-
cleanedForm[key] = cleanedObject
|
|
528
|
-
}
|
|
529
|
-
continue
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
// 处理基本类型
|
|
533
|
-
if (value !== null && value !== undefined && value !== '') {
|
|
534
|
-
cleanedForm[key] = value
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
return cleanedForm
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
function getFormData() {
|
|
542
|
-
return prepareForm()
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
async function onSubmit() {
|
|
546
|
-
await validate()
|
|
547
|
-
// 清理表单数据
|
|
548
|
-
const cleanedForm = prepareForm()
|
|
549
|
-
if (!props.configName && props.groupFormItems) {
|
|
550
|
-
// 只有单表才可以成功,多表关联或者自定义sql不行
|
|
551
|
-
await appendSilenceAddFields(cleanedForm)
|
|
552
|
-
const realForm = handleFormKeys(cleanedForm)
|
|
553
|
-
|
|
554
|
-
try {
|
|
555
|
-
addOrModifyEntity(realForm, tableName.value, props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME).then(() => {
|
|
556
|
-
showSuccessToast('提交成功!!')
|
|
557
|
-
})
|
|
558
|
-
}
|
|
559
|
-
catch (error) {
|
|
560
|
-
showFailToast('提交失败!!')
|
|
561
|
-
}
|
|
562
|
-
finally {
|
|
563
|
-
setTimeout(() => {
|
|
564
|
-
history.back()
|
|
565
|
-
}, 1000)
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
else {
|
|
569
|
-
// 使用清理后的数据
|
|
570
|
-
emits('onSubmit', cleanedForm)
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
async function validate() {
|
|
574
|
-
await xFormRef.value?.validate()
|
|
575
|
-
}
|
|
576
|
-
function emitFunc(func: any, data: any, value: any) {
|
|
577
|
-
emits(func, data, value)
|
|
578
|
-
emits('xFormItemEmitFunc', func, data, value)
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
defineExpose({ init, form, formGroupName, validate, asyncSubmit, setForm, getFormData })
|
|
582
|
-
</script>
|
|
583
|
-
|
|
584
|
-
<template>
|
|
585
|
-
<VanForm v-if="loaded" ref="xFormRef" class="x-form-container" :class="{ 'use-full-height': !props.isGroupForm }" @submit="onSubmit">
|
|
586
|
-
<div class="form-fields-scrollable">
|
|
587
|
-
<VanCellGroup :title="groupTitle">
|
|
588
|
-
<XFormItem
|
|
589
|
-
v-for="(item, index) in realJsonData"
|
|
590
|
-
:key="index"
|
|
591
|
-
v-model="form[item.model]"
|
|
592
|
-
:mode="props.mode"
|
|
593
|
-
:form="form"
|
|
594
|
-
:attr="item"
|
|
595
|
-
:rules="rules"
|
|
596
|
-
:service-name="myServiceName"
|
|
597
|
-
:get-data-params="myGetDataParams"
|
|
598
|
-
@set-form="setForm"
|
|
599
|
-
@x-form-item-emit-func="emitFunc"
|
|
600
|
-
/>
|
|
601
|
-
<slot name="extraFormItem" />
|
|
602
|
-
</VanCellGroup>
|
|
603
|
-
<slot name="extraCellGroup" />
|
|
604
|
-
<!-- 地图预览,统一放在表单项下方,只在有经纬度时显示 -->
|
|
605
|
-
<div v-if="previewMapPoint" style="height: 200px; margin-top: 12px; position: relative;">
|
|
606
|
-
<XOlMap
|
|
607
|
-
ref="previewMapRef"
|
|
608
|
-
:center="previewMapPoint"
|
|
609
|
-
:style="{ height: '100%' }"
|
|
610
|
-
/>
|
|
611
|
-
<div class="map-mask" />
|
|
612
|
-
</div>
|
|
613
|
-
</div>
|
|
614
|
-
<div v-if="resolvedSubmitButton && props.mode !== '预览'" class="form-footer-fixed">
|
|
615
|
-
<VanButton class="action-btn" round block type="primary" native-type="submit">
|
|
616
|
-
{{ props.groupFormItems?.btnName ? props.groupFormItems.btnName : '提交' }}
|
|
617
|
-
</VanButton>
|
|
618
|
-
<slot />
|
|
619
|
-
</div>
|
|
620
|
-
<slot name="extraActionSpace" />
|
|
621
|
-
</VanForm>
|
|
622
|
-
</template>
|
|
623
|
-
|
|
624
|
-
<style scoped>
|
|
625
|
-
.use-full-height {
|
|
626
|
-
height: calc(100vh - var(--van-nav-bar-height) - 20px);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
.x-form-container {
|
|
630
|
-
display: flex;
|
|
631
|
-
flex-direction: column;
|
|
632
|
-
max-height: 100vh;
|
|
633
|
-
overflow: hidden;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
.form-fields-scrollable {
|
|
637
|
-
flex: 1;
|
|
638
|
-
overflow-y: auto;
|
|
639
|
-
min-height: 0;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
.form-footer-fixed {
|
|
643
|
-
margin: 16px;
|
|
644
|
-
flex-shrink: 0;
|
|
645
|
-
.action-btn {
|
|
646
|
-
border-radius: 10px;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
.map-mask {
|
|
650
|
-
position: absolute;
|
|
651
|
-
left: 0;
|
|
652
|
-
top: 0;
|
|
653
|
-
width: 100%;
|
|
654
|
-
height: 100%;
|
|
655
|
-
pointer-events: all;
|
|
656
|
-
background: transparent;
|
|
657
|
-
z-index: 10;
|
|
658
|
-
}
|
|
659
|
-
</style>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { FormInstance } from 'vant'
|
|
3
|
+
import XFormItem from '@af-mobile-client-vue3/components/data/XFormItem/index.vue'
|
|
4
|
+
import XOlMap from '@af-mobile-client-vue3/components/data/XOlMap/index.vue'
|
|
5
|
+
import { formatDate } from '@af-mobile-client-vue3/hooks/useCommon'
|
|
6
|
+
import { addOrModifyEntity, getConfigByName, runLogic } from '@af-mobile-client-vue3/services/api/common'
|
|
7
|
+
import { useUserStore } from '@af-mobile-client-vue3/stores'
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
showFailToast,
|
|
11
|
+
showSuccessToast,
|
|
12
|
+
Button as VanButton,
|
|
13
|
+
CellGroup as VanCellGroup,
|
|
14
|
+
Form as VanForm,
|
|
15
|
+
} from 'vant'
|
|
16
|
+
import { computed, defineEmits, defineProps, inject, nextTick, onBeforeMount, reactive, ref, watch } from 'vue'
|
|
17
|
+
|
|
18
|
+
interface FormItem {
|
|
19
|
+
addOrEdit: string
|
|
20
|
+
isOnlyAddOrEdit?: boolean
|
|
21
|
+
type?: string
|
|
22
|
+
model?: string
|
|
23
|
+
name?: string
|
|
24
|
+
rule?: {
|
|
25
|
+
type: string
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface SilenceAddFormItem extends FormItem {
|
|
30
|
+
silencePurpose: string
|
|
31
|
+
silenceSource?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface GroupFormItems {
|
|
35
|
+
btnName?: string
|
|
36
|
+
formJson: any[] // 根据实际类型调整
|
|
37
|
+
showSubmitBtn?: boolean
|
|
38
|
+
groupName?: string
|
|
39
|
+
tableName?: string
|
|
40
|
+
paramLogicName?: string
|
|
41
|
+
isGroupForm?: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface InitParams {
|
|
45
|
+
formItems?: GroupFormItems
|
|
46
|
+
formData?: object
|
|
47
|
+
getDataParams?: object
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const props = withDefaults(defineProps<{
|
|
51
|
+
configName?: string
|
|
52
|
+
groupTitle?: string
|
|
53
|
+
groupFormItems?: GroupFormItems
|
|
54
|
+
serviceName?: string
|
|
55
|
+
formData?: object
|
|
56
|
+
formName?: string
|
|
57
|
+
mode?: string
|
|
58
|
+
submitButton?: boolean
|
|
59
|
+
isHandleFormKey?: boolean
|
|
60
|
+
paramLogicNameParam?: any
|
|
61
|
+
isGroupForm?: boolean
|
|
62
|
+
}>(), {
|
|
63
|
+
configName: undefined,
|
|
64
|
+
groupTitle: undefined,
|
|
65
|
+
groupFormItems: null,
|
|
66
|
+
serviceName: undefined,
|
|
67
|
+
formData: null,
|
|
68
|
+
formName: 'default',
|
|
69
|
+
mode: '查询',
|
|
70
|
+
submitButton: true,
|
|
71
|
+
isHandleFormKey: true,
|
|
72
|
+
paramLogicNameParam: {},
|
|
73
|
+
isGroupForm: false,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
const emits = defineEmits(['onSubmit', 'xFormItemEmitFunc'])
|
|
77
|
+
const userStore = useUserStore()
|
|
78
|
+
|
|
79
|
+
// inject
|
|
80
|
+
const formDataChange = inject('formDataChange', null)
|
|
81
|
+
|
|
82
|
+
// 核心状态
|
|
83
|
+
const xFormRef = ref<FormInstance>()
|
|
84
|
+
const loaded = ref(false)
|
|
85
|
+
const form = ref({})
|
|
86
|
+
const rules = reactive({})
|
|
87
|
+
const myGetDataParams = ref({})
|
|
88
|
+
|
|
89
|
+
// 配置相关状态
|
|
90
|
+
const formConfig = ref<GroupFormItems | null>(null)
|
|
91
|
+
const formGroupName = ref<string>('default')
|
|
92
|
+
const myServiceName = ref('')
|
|
93
|
+
const tableName = ref('')
|
|
94
|
+
|
|
95
|
+
// 计算属性
|
|
96
|
+
const realJsonData = computed(() => {
|
|
97
|
+
const sourceFormItems = formConfig.value?.formJson
|
|
98
|
+
if (!sourceFormItems)
|
|
99
|
+
return []
|
|
100
|
+
|
|
101
|
+
return sourceFormItems.filter((item) => {
|
|
102
|
+
return item.addOrEdit !== 'no'
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
// 过滤出用于静默新增场景的表单项
|
|
107
|
+
const silenceAddJsonData = computed(() => {
|
|
108
|
+
return realJsonData.value.filter((item) => {
|
|
109
|
+
return item.addOrEdit === 'silenceAdd'
|
|
110
|
+
}) as SilenceAddFormItem[]
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const resolvedSubmitButton = computed(() => {
|
|
114
|
+
if (props.configName && formConfig.value?.showSubmitBtn !== undefined) {
|
|
115
|
+
return formConfig.value.showSubmitBtn
|
|
116
|
+
}
|
|
117
|
+
return props.submitButton
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// 地图预览相关
|
|
121
|
+
const previewMapRef = ref(null)
|
|
122
|
+
const previewLonLatKey = computed(() => {
|
|
123
|
+
const item = realJsonData.value.find(i => i.type === 'addressSearch')
|
|
124
|
+
return item ? `${item.model}_lon_lat` : null
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const previewMapPoint = computed(() => {
|
|
128
|
+
const val = form.value[previewLonLatKey.value]
|
|
129
|
+
if (val && typeof val === 'string' && val.includes(',')) {
|
|
130
|
+
const [lon, lat] = val.split(',').map(Number)
|
|
131
|
+
if (!Number.isNaN(lon) && !Number.isNaN(lat)) {
|
|
132
|
+
return [lon, lat]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
// 地图初始化逻辑
|
|
139
|
+
const previewMapInited = ref(false)
|
|
140
|
+
watch(previewMapPoint, async (val) => {
|
|
141
|
+
await nextTick()
|
|
142
|
+
if (val && previewMapRef.value) {
|
|
143
|
+
if (!previewMapInited.value) {
|
|
144
|
+
await previewMapRef.value.init({ center: val, zoom: 16, isPreview: true })
|
|
145
|
+
previewMapInited.value = true
|
|
146
|
+
}
|
|
147
|
+
previewMapRef.value.setCenter(val, true)
|
|
148
|
+
previewMapRef.value.updateLocationMarker(val)
|
|
149
|
+
}
|
|
150
|
+
}, { immediate: true })
|
|
151
|
+
|
|
152
|
+
// 统一的初始化函数 - 仅在组件挂载时调用
|
|
153
|
+
async function initializeForm() {
|
|
154
|
+
loaded.value = false
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
if (props.configName) {
|
|
158
|
+
await loadFormConfig()
|
|
159
|
+
}
|
|
160
|
+
else if (props.groupFormItems) {
|
|
161
|
+
await initWithGroupFormItems()
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.warn('未提供配置名称或表单配置,等待 init 函数调用')
|
|
165
|
+
resetForm()
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.error('表单初始化失败:', error)
|
|
170
|
+
resetForm()
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
loaded.value = true
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 加载配置的方式初始化
|
|
178
|
+
async function loadFormConfig(): Promise<void> {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
getConfigByName(props.configName!, (result) => {
|
|
181
|
+
if (result) {
|
|
182
|
+
setupFormConfig(result)
|
|
183
|
+
resolve()
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
console.warn(`配置 '${props.configName}' 不存在`)
|
|
187
|
+
reject(new Error(`配置 '${props.configName}' 不存在`))
|
|
188
|
+
}
|
|
189
|
+
}, props.serviceName)
|
|
190
|
+
})
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 直接使用 groupFormItems 初始化
|
|
194
|
+
async function initWithGroupFormItems() {
|
|
195
|
+
if (!props.groupFormItems) {
|
|
196
|
+
throw new Error('groupFormItems 不能为空')
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
setupFormConfig(props.groupFormItems)
|
|
200
|
+
|
|
201
|
+
// 设置表名
|
|
202
|
+
if (props.groupFormItems.tableName) {
|
|
203
|
+
tableName.value = props.groupFormItems.tableName.split(' ')[0] || ''
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 设置表单配置
|
|
208
|
+
function setupFormConfig(config: GroupFormItems) {
|
|
209
|
+
loadParamLogicNameData(config.paramLogicName)
|
|
210
|
+
formConfig.value = config
|
|
211
|
+
myServiceName.value = props.serviceName || ''
|
|
212
|
+
formGroupName.value = config.groupName || 'default'
|
|
213
|
+
form.value = props.formData || {}
|
|
214
|
+
// 清理并重新设置验证规则
|
|
215
|
+
setupValidationRules()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 设置验证规则
|
|
219
|
+
function setupValidationRules() {
|
|
220
|
+
// 清理现有规则
|
|
221
|
+
Object.keys(rules).forEach(key => delete rules[key])
|
|
222
|
+
|
|
223
|
+
// 为每个表单项设置规则
|
|
224
|
+
for (const item of realJsonData.value) {
|
|
225
|
+
if (item.rule) {
|
|
226
|
+
setFormRule(item)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 设置单个表单项的验证规则
|
|
232
|
+
function setFormRule(item: FormItem) {
|
|
233
|
+
if (!item.model || !item.rule)
|
|
234
|
+
return
|
|
235
|
+
|
|
236
|
+
rules[item.model] = []
|
|
237
|
+
let defaultValue: any
|
|
238
|
+
let message: string
|
|
239
|
+
|
|
240
|
+
switch (item.rule.type) {
|
|
241
|
+
case 'number':
|
|
242
|
+
message = '数字'
|
|
243
|
+
defaultValue = 0
|
|
244
|
+
break
|
|
245
|
+
case 'integer':
|
|
246
|
+
message = '整数'
|
|
247
|
+
defaultValue = 0
|
|
248
|
+
break
|
|
249
|
+
case 'float':
|
|
250
|
+
message = '小数'
|
|
251
|
+
defaultValue = 0.0
|
|
252
|
+
break
|
|
253
|
+
case 'string':
|
|
254
|
+
message = '字符串'
|
|
255
|
+
defaultValue = ''
|
|
256
|
+
break
|
|
257
|
+
default:
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
rules[item.model].push({
|
|
262
|
+
type: item.rule.type,
|
|
263
|
+
message: `${item.name || item.model}必须为${message}`,
|
|
264
|
+
transform: (value: any) => {
|
|
265
|
+
if (value && value.length !== 0) {
|
|
266
|
+
return Number(value)
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
return defaultValue
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
trigger: 'blur',
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// 重置表单状态
|
|
277
|
+
function resetForm() {
|
|
278
|
+
formConfig.value = null
|
|
279
|
+
formGroupName.value = 'default'
|
|
280
|
+
myServiceName.value = ''
|
|
281
|
+
tableName.value = ''
|
|
282
|
+
form.value = {}
|
|
283
|
+
Object.keys(rules).forEach(key => delete rules[key])
|
|
284
|
+
myGetDataParams.value = {}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// 监听 formData 变化
|
|
288
|
+
watch(() => props.formData, (newVal) => {
|
|
289
|
+
if (newVal) {
|
|
290
|
+
Object.assign(form, newVal)
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
watch(form, (newVal) => {
|
|
295
|
+
if (typeof formDataChange === 'function') {
|
|
296
|
+
formDataChange(newVal)
|
|
297
|
+
}
|
|
298
|
+
}, { deep: true })
|
|
299
|
+
|
|
300
|
+
// 组件挂载时初始化
|
|
301
|
+
onBeforeMount(() => {
|
|
302
|
+
initializeForm()
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
// 支持函数调用方式初始化
|
|
306
|
+
function init(params: InitParams) {
|
|
307
|
+
const {
|
|
308
|
+
formItems,
|
|
309
|
+
formData = {},
|
|
310
|
+
getDataParams = {},
|
|
311
|
+
} = params
|
|
312
|
+
|
|
313
|
+
// 重置状态
|
|
314
|
+
loaded.value = false
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
if (props.configName) {
|
|
318
|
+
// 通过 props 中的配置名称初始化
|
|
319
|
+
loadFormConfig()
|
|
320
|
+
}
|
|
321
|
+
else if (formItems) {
|
|
322
|
+
// 直接使用传入的配置初始化
|
|
323
|
+
setupFormConfig(formItems)
|
|
324
|
+
form.value = formData || props.formData || {}
|
|
325
|
+
myGetDataParams.value = getDataParams
|
|
326
|
+
|
|
327
|
+
// 设置表名
|
|
328
|
+
if (formItems.tableName) {
|
|
329
|
+
tableName.value = formItems.tableName.split(' ')[0] || ''
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
console.warn('init 函数调用时既没有 props.configName 也没有 formItems')
|
|
334
|
+
resetForm()
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
console.error('init 函数初始化失败:', error)
|
|
339
|
+
resetForm()
|
|
340
|
+
}
|
|
341
|
+
finally {
|
|
342
|
+
loaded.value = true
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function loadParamLogicNameData(paramLogicName) {
|
|
347
|
+
// 如果有 paramLogicName,自动请求并赋值
|
|
348
|
+
if (paramLogicName && (!props.formData || (props.formData && Object.keys(props.formData).length === 0))) {
|
|
349
|
+
let logicParam = props?.paramLogicNameParam || {}
|
|
350
|
+
if (typeof logicParam === 'string') {
|
|
351
|
+
try {
|
|
352
|
+
logicParam = JSON.parse(logicParam)
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
logicParam = { value: logicParam }
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
logicParam = {
|
|
359
|
+
...logicParam,
|
|
360
|
+
currUserName: userStore.getUserInfo().name,
|
|
361
|
+
currUserId: userStore.getUserInfo().id,
|
|
362
|
+
orgId: userStore.getUserInfo().orgid,
|
|
363
|
+
}
|
|
364
|
+
runLogic(paramLogicName, logicParam || {}, props.serviceName).then((data: any) => {
|
|
365
|
+
if (data) {
|
|
366
|
+
form.value = data
|
|
367
|
+
}
|
|
368
|
+
})
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function setForm(obj: object) {
|
|
373
|
+
Object.assign(form.value, obj)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// 获取表单字段实际值
|
|
377
|
+
function getRealKey(key: string, mustHandleKey = false) {
|
|
378
|
+
if (key === 'selected_id')
|
|
379
|
+
return key
|
|
380
|
+
if (props.isHandleFormKey || mustHandleKey) {
|
|
381
|
+
return key.substring(key.indexOf('_') + 1)
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
return key
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async function asyncSubmit() {
|
|
389
|
+
return new Promise((resolve, reject) => {
|
|
390
|
+
validate().then(async () => {
|
|
391
|
+
const cleanedForm = prepareForm()
|
|
392
|
+
await appendSilenceAddFields(cleanedForm)
|
|
393
|
+
const realForm = handleFormKeys(cleanedForm)
|
|
394
|
+
resolve({
|
|
395
|
+
realForm,
|
|
396
|
+
mode: props.mode,
|
|
397
|
+
serviceName: props.serviceName,
|
|
398
|
+
currUserName: userStore.getUserInfo().name,
|
|
399
|
+
currUserId: userStore.getUserInfo().id,
|
|
400
|
+
orgId: userStore.getUserInfo().orgid,
|
|
401
|
+
})
|
|
402
|
+
}).catch((error) => {
|
|
403
|
+
reject(error)
|
|
404
|
+
})
|
|
405
|
+
})
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function handleFormKeys(form: any, mustHandleKey = false) {
|
|
409
|
+
const realForm: any = {}
|
|
410
|
+
for (const key of Object.keys(form)) {
|
|
411
|
+
const value = form[key]
|
|
412
|
+
const extraFormKeyTagIndex = key.indexOf('@')
|
|
413
|
+
if (extraFormKeyTagIndex !== -1) {
|
|
414
|
+
const extraFormKey = key.substring(0, extraFormKeyTagIndex)
|
|
415
|
+
const realKey = key.substring(extraFormKeyTagIndex + 1)
|
|
416
|
+
if (!realForm[extraFormKey]) {
|
|
417
|
+
realForm[extraFormKey] = {}
|
|
418
|
+
}
|
|
419
|
+
realForm[extraFormKey][realKey] = value
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
const realKey = props.isHandleFormKey || mustHandleKey ? getRealKey(key, mustHandleKey) : key
|
|
423
|
+
// 如果发生重名,不覆盖,把key的别名带上
|
|
424
|
+
if (realForm[realKey]) {
|
|
425
|
+
realForm[key] = value
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
realForm[realKey] = value
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return realForm
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
async function appendSilenceAddFields(form: any) {
|
|
436
|
+
if (props.mode === '新增') {
|
|
437
|
+
for (const item of silenceAddJsonData.value) {
|
|
438
|
+
switch (item.silencePurpose) {
|
|
439
|
+
case 'createTime':
|
|
440
|
+
form[item.model] = formatDate(new Date())
|
|
441
|
+
break
|
|
442
|
+
case 'operator':
|
|
443
|
+
form[item.model] = userStore.getUserInfo().name
|
|
444
|
+
break
|
|
445
|
+
case 'operatorId':
|
|
446
|
+
form[item.model] = userStore.getUserInfo().id
|
|
447
|
+
break
|
|
448
|
+
case 'orgId':
|
|
449
|
+
form[item.model] = userStore.getUserInfo().orgid
|
|
450
|
+
break
|
|
451
|
+
case 'orgName':
|
|
452
|
+
form[item.model] = userStore.getUserInfo().orgs
|
|
453
|
+
break
|
|
454
|
+
case 'depId':
|
|
455
|
+
form[item.model] = userStore.getUserInfo().depids
|
|
456
|
+
break
|
|
457
|
+
case 'depName':
|
|
458
|
+
form[item.model] = userStore.getUserInfo().deps
|
|
459
|
+
break
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
for (const item of silenceAddJsonData.value.filter(item => item.silencePurpose === 'customize')) {
|
|
463
|
+
const result: any = await runLogic(item.silenceSource!, form, props.serviceName)
|
|
464
|
+
if (result) {
|
|
465
|
+
const keys = Object.keys(result)
|
|
466
|
+
if (keys.length === 1 && keys[0] === 'value') {
|
|
467
|
+
form[item.model] = result.value
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
form[item.model] = result
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
form[item.model] = result
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function prepareForm() {
|
|
481
|
+
const formObj = { ...form.value }
|
|
482
|
+
const cleanedForm: any = {}
|
|
483
|
+
|
|
484
|
+
for (const key of Object.keys(formObj)) {
|
|
485
|
+
const value = formObj[key]
|
|
486
|
+
|
|
487
|
+
// 跳过无效值
|
|
488
|
+
if (value === null || value === undefined || value === '') {
|
|
489
|
+
continue
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// 处理数组
|
|
493
|
+
if (Array.isArray(value)) {
|
|
494
|
+
// 过滤掉空字符串、null、undefined
|
|
495
|
+
const filteredArray = value.filter(item =>
|
|
496
|
+
item !== null && item !== undefined && item !== '',
|
|
497
|
+
)
|
|
498
|
+
// 只有当数组不为空时才添加
|
|
499
|
+
if (filteredArray.length > 0) {
|
|
500
|
+
cleanedForm[key] = filteredArray
|
|
501
|
+
}
|
|
502
|
+
continue
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// 处理对象
|
|
506
|
+
if (typeof value === 'object' && value !== null) {
|
|
507
|
+
// 检查对象是否为空
|
|
508
|
+
const objectKeys = Object.keys(value)
|
|
509
|
+
if (objectKeys.length === 0) {
|
|
510
|
+
continue
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// 递归清理对象内部
|
|
514
|
+
const cleanedObject: any = {}
|
|
515
|
+
let hasValidValue = false
|
|
516
|
+
|
|
517
|
+
for (const objKey of objectKeys) {
|
|
518
|
+
const objValue = value[objKey]
|
|
519
|
+
if (objValue !== null && objValue !== undefined && objValue !== '') {
|
|
520
|
+
cleanedObject[objKey] = objValue
|
|
521
|
+
hasValidValue = true
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// 只有当对象有有效值时才添加
|
|
526
|
+
if (hasValidValue) {
|
|
527
|
+
cleanedForm[key] = cleanedObject
|
|
528
|
+
}
|
|
529
|
+
continue
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// 处理基本类型
|
|
533
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
534
|
+
cleanedForm[key] = value
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return cleanedForm
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function getFormData() {
|
|
542
|
+
return prepareForm()
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
async function onSubmit() {
|
|
546
|
+
await validate()
|
|
547
|
+
// 清理表单数据
|
|
548
|
+
const cleanedForm = prepareForm()
|
|
549
|
+
if (!props.configName && props.groupFormItems) {
|
|
550
|
+
// 只有单表才可以成功,多表关联或者自定义sql不行
|
|
551
|
+
await appendSilenceAddFields(cleanedForm)
|
|
552
|
+
const realForm = handleFormKeys(cleanedForm)
|
|
553
|
+
|
|
554
|
+
try {
|
|
555
|
+
addOrModifyEntity(realForm, tableName.value, props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME).then(() => {
|
|
556
|
+
showSuccessToast('提交成功!!')
|
|
557
|
+
})
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
showFailToast('提交失败!!')
|
|
561
|
+
}
|
|
562
|
+
finally {
|
|
563
|
+
setTimeout(() => {
|
|
564
|
+
history.back()
|
|
565
|
+
}, 1000)
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
// 使用清理后的数据
|
|
570
|
+
emits('onSubmit', cleanedForm)
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
async function validate() {
|
|
574
|
+
await xFormRef.value?.validate()
|
|
575
|
+
}
|
|
576
|
+
function emitFunc(func: any, data: any, value: any) {
|
|
577
|
+
emits(func, data, value)
|
|
578
|
+
emits('xFormItemEmitFunc', func, data, value)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
defineExpose({ init, form, formGroupName, validate, asyncSubmit, setForm, getFormData })
|
|
582
|
+
</script>
|
|
583
|
+
|
|
584
|
+
<template>
|
|
585
|
+
<VanForm v-if="loaded" ref="xFormRef" class="x-form-container" :class="{ 'use-full-height': !props.isGroupForm }" @submit="onSubmit">
|
|
586
|
+
<div class="form-fields-scrollable">
|
|
587
|
+
<VanCellGroup :title="groupTitle">
|
|
588
|
+
<XFormItem
|
|
589
|
+
v-for="(item, index) in realJsonData"
|
|
590
|
+
:key="index"
|
|
591
|
+
v-model="form[item.model]"
|
|
592
|
+
:mode="props.mode"
|
|
593
|
+
:form="form"
|
|
594
|
+
:attr="item"
|
|
595
|
+
:rules="rules"
|
|
596
|
+
:service-name="myServiceName"
|
|
597
|
+
:get-data-params="myGetDataParams"
|
|
598
|
+
@set-form="setForm"
|
|
599
|
+
@x-form-item-emit-func="emitFunc"
|
|
600
|
+
/>
|
|
601
|
+
<slot name="extraFormItem" />
|
|
602
|
+
</VanCellGroup>
|
|
603
|
+
<slot name="extraCellGroup" />
|
|
604
|
+
<!-- 地图预览,统一放在表单项下方,只在有经纬度时显示 -->
|
|
605
|
+
<div v-if="previewMapPoint" style="height: 200px; margin-top: 12px; position: relative;">
|
|
606
|
+
<XOlMap
|
|
607
|
+
ref="previewMapRef"
|
|
608
|
+
:center="previewMapPoint"
|
|
609
|
+
:style="{ height: '100%' }"
|
|
610
|
+
/>
|
|
611
|
+
<div class="map-mask" />
|
|
612
|
+
</div>
|
|
613
|
+
</div>
|
|
614
|
+
<div v-if="resolvedSubmitButton && props.mode !== '预览'" class="form-footer-fixed">
|
|
615
|
+
<VanButton class="action-btn" round block type="primary" native-type="submit">
|
|
616
|
+
{{ props.groupFormItems?.btnName ? props.groupFormItems.btnName : '提交' }}
|
|
617
|
+
</VanButton>
|
|
618
|
+
<slot />
|
|
619
|
+
</div>
|
|
620
|
+
<slot name="extraActionSpace" />
|
|
621
|
+
</VanForm>
|
|
622
|
+
</template>
|
|
623
|
+
|
|
624
|
+
<style scoped>
|
|
625
|
+
.use-full-height {
|
|
626
|
+
height: calc(100vh - var(--van-nav-bar-height) - 20px);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
.x-form-container {
|
|
630
|
+
display: flex;
|
|
631
|
+
flex-direction: column;
|
|
632
|
+
max-height: 100vh;
|
|
633
|
+
overflow: hidden;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
.form-fields-scrollable {
|
|
637
|
+
flex: 1;
|
|
638
|
+
overflow-y: auto;
|
|
639
|
+
min-height: 0;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
.form-footer-fixed {
|
|
643
|
+
margin: 16px;
|
|
644
|
+
flex-shrink: 0;
|
|
645
|
+
.action-btn {
|
|
646
|
+
border-radius: 10px;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
.map-mask {
|
|
650
|
+
position: absolute;
|
|
651
|
+
left: 0;
|
|
652
|
+
top: 0;
|
|
653
|
+
width: 100%;
|
|
654
|
+
height: 100%;
|
|
655
|
+
pointer-events: all;
|
|
656
|
+
background: transparent;
|
|
657
|
+
z-index: 10;
|
|
658
|
+
}
|
|
659
|
+
</style>
|