You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
6.5 KiB
223 lines
6.5 KiB
<!--
|
|
@ 作者: 秦东
|
|
@ 时间: 2024-11-02 10:12:55
|
|
@ 备注: 自定义表单画布
|
|
-->
|
|
<script lang='ts' setup>
|
|
import { useRoute,useRouter } from 'vue-router'
|
|
import { FormData } from '@/api/lowCode/form/type';
|
|
import { constFormProps } from '@/api/lowCode/utils';
|
|
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
type?: number // 1新增;2修改;3查看(表单模式)
|
|
formData: FormData
|
|
isWorkFlow: boolean // 是否流程表单
|
|
beforeRequest?: Function // 请求编辑数据前参数处理方法,可对请求参数处理
|
|
afterResponse?: Function | string // 请求数据加载完成后数据处理方法,可对返回数据处理
|
|
beforeSubmit?: Function | string // 表单提交前数据处理,可对提交数据处理,新增和保存都会触发
|
|
afterSubmit?: Function // 表单提交后,默认提示提交结果,可return false阻止提示
|
|
closeAppSubmit?: Function //关闭拉窗
|
|
changeKeyVal?: Function //监听表单值该表
|
|
anewSubmit?: Function //重新提交表单
|
|
saveDraftPage?: Function //保存草稿
|
|
saveEditFormInfo?: Function //保存草稿 只改表单不操作流程
|
|
sendDraftSubmit?: Function //草稿提交审批
|
|
submitEdit?: Function //提交修改数据申请
|
|
value?: { [key: string]: any } // 表单初始值,同setValue
|
|
options?: { [key: string]: any } // 表单组件选项,同setOptions
|
|
dict?: object // 固定匹配的字典
|
|
}>(),{
|
|
type: 1, // 1新增;2修改;3查看(表单模式) ;
|
|
formData: () => {
|
|
return {
|
|
list: [],
|
|
form: {},
|
|
config: {
|
|
style:''
|
|
},
|
|
styles:{
|
|
divStyle:{},
|
|
labelStyle:{},
|
|
inputStyle:{}
|
|
}
|
|
}
|
|
},
|
|
dict: () => {
|
|
return {}
|
|
},
|
|
}
|
|
);
|
|
|
|
const emits = defineEmits<{
|
|
(e: 'btnClick', type: string): void
|
|
(e: 'change', val: any): void // 表单组件值发生变化时
|
|
(e: 'update:issave', type: boolean): void
|
|
(e: 'refresh'): void
|
|
(e: 'optionsValue3Get3', val: any,fieldName: string): void
|
|
}>()
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const appLoading = ref(false)
|
|
const resultDict = ref({})
|
|
// 处理表单值开始
|
|
const model = ref<any>({})
|
|
|
|
const dictForm = computed(() => {
|
|
const storage = window.localStorage.getItem('akFormDict')
|
|
let storageDict = {}
|
|
if (storage) {
|
|
storageDict = JSON.parse(storage)
|
|
}
|
|
// 全局的、当前表单配置的以及接口返回的
|
|
return Object.assign({}, storageDict, props.dict, resultDict.value)
|
|
})
|
|
// 表单参数
|
|
const formProps = computed(() => {
|
|
return {
|
|
model: model.value,
|
|
type: props.type,
|
|
hideField: props.formData.config?.hideField as [],
|
|
showColon: props.formData.form.showColon,
|
|
dict: dictForm.value
|
|
}
|
|
})
|
|
provide(constFormProps, formProps)
|
|
// 注册window事件
|
|
const setWindowEvent = (bool?: boolean) => {
|
|
if (props.data&&props.data.list&&props.data.list.length > 0) {
|
|
const formName = props.data.form?.name
|
|
if (!formName) {
|
|
// 导出.vue时,name可以没有
|
|
return
|
|
}
|
|
eventName = `get${formName}ControlByName`
|
|
getValueEvent = `get${formName}ValueByName`
|
|
if (formName && (!window[eventName as any] || !bool)) {
|
|
// 根据name获取当前数据项
|
|
// @ts-ignore
|
|
window[eventName] = (name: string) => {
|
|
return getNameForEach(props.data.list, name)
|
|
}
|
|
// 根据name获取当前项的值
|
|
// @ts-ignore
|
|
window[getValueEvent] = (name: string) => {
|
|
return model.value[name]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
watch(
|
|
() => props.formData,
|
|
() => {
|
|
emits('update:issave', false)
|
|
},
|
|
{ deep: true }
|
|
)
|
|
watch(
|
|
() => props.formData.config,
|
|
() => {
|
|
if (timer < 2) {
|
|
setWindowEvent() // 简单判断下,这里不是每次都更新
|
|
}
|
|
timer++
|
|
appendRemoveStyle(true) // 更新样式
|
|
},
|
|
{ deep: true }
|
|
)
|
|
setWindowEvent()
|
|
|
|
// 获取表单初始model值
|
|
const getInitModel = () => {
|
|
const obj = {}
|
|
forEachGetFormModel(props.formData.list, obj)
|
|
// console.log("obj===>",obj)
|
|
// console.log("obj===>",props.formData.list)
|
|
model.value = obj
|
|
}
|
|
watch(
|
|
() => props.formData.list,
|
|
() => {
|
|
// formData从接口获取时
|
|
getInitModel()
|
|
}
|
|
)
|
|
// 从表单数据里提取表单所需的model
|
|
const forEachGetFormModel = (list: FormList[], obj: any) => {
|
|
list.forEach((item: any) => {
|
|
if (['table', 'flex'].includes(item.type)) {
|
|
obj[item.name] = jsonParseStringify(item.tableData)
|
|
} else if (['grid', 'tabs'].includes(item.type)) {
|
|
item.columns.forEach((col: any) => {
|
|
forEachGetFormModel(col.list, obj)
|
|
})
|
|
} else if (['card', 'div'].includes(item.type)) {
|
|
forEachGetFormModel(item.list, obj)
|
|
}else {
|
|
const excludeType = ['title', 'divider', 'txt', 'button']
|
|
if (excludeType.indexOf(item.type) === -1) {
|
|
obj[item.name] = jsonParseStringify(item.control.modelValue)
|
|
if(['switch'].includes(item.type)){
|
|
model.value[item.name] = jsonParseStringify(item.control.inactiveValue)
|
|
// console.log(model.value)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
// showOrHide("onMounted")
|
|
}
|
|
// 表单初始值
|
|
watch(
|
|
() => props.value,
|
|
(v: any) => {
|
|
v && setValue(v)
|
|
},
|
|
{
|
|
immediate: true
|
|
}
|
|
)
|
|
// 表单options
|
|
watch(
|
|
() => props.options,
|
|
(v: any) => {
|
|
v && setOptions(v)
|
|
}
|
|
)
|
|
|
|
// 对表单设置初始值
|
|
const setValue = (obj: { [key: string]: any }, filter?: boolean) => {
|
|
// 分两种,false时将obj所有值合并到model,当obj有某些值不存于表单中,也会合并到model,当提交表单也会提交此值
|
|
// true则过滤没用的值,即存在当前表单的才合并
|
|
if (filter) {
|
|
for (const key in obj) {
|
|
if (model.value[key] !== undefined) {
|
|
model.value[key] = obj[key]
|
|
}
|
|
}
|
|
} else {
|
|
model.value = Object.assign({}, model.value, jsonParseStringify(obj)) // 防止列表直接使用set方法对弹窗表单编辑,当重置表单时当前行数据被清空
|
|
}
|
|
}
|
|
const setFormOptions = ref({})
|
|
const setOptions = (obj: { [key: string]: string[] }) => {
|
|
setFormOptions.value = obj
|
|
}
|
|
</script>
|
|
<template>
|
|
<div v-loading="appLoading" element-loading-text="Loading...">
|
|
<el-form
|
|
ref="ruleFormDesign"
|
|
v-bind="formData.form"
|
|
:model="model"
|
|
:disabled="disabled || type === 4"
|
|
class="add-form"
|
|
>
|
|
<FormItemGroup :tableinfo="formData.form" :data="formData.list" :alldata="formData" />
|
|
<slot></slot>
|
|
</el-form>
|
|
</div>
|
|
</template>
|
|
<style lang='scss' scoped>
|
|
|
|
</style>
|