<!--
@ 作者: 秦东
@ 时间: 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>