<!--
@ 作者: 秦东
@ 时间: 2024-11-13 14:30:45
@ 备注: 表单循环组件
-->
<script lang='ts' setup>
import { useRoute,useRouter } from 'vue-router'
import { 
    formatNumber, 
	objectToArray,
	constControlChange,
    constSetFormOptions,
    constFormProps,
    constGetControlByName
} from '@/api/lowCode/utils';
import { AnalysisCss,AnalysisInputCss } from '@/api/common/cssInfo'
import validate from "@/api/lowCode/form/validate"
import { Md5 } from 'ts-md5'
import { debounce } from '@/utils/lowCode/item/index'

//辅助控件
import OrgCitys from '@/components/lowCode/assistant/orgCitys.vue'
import UploadPage from '@/components/lowCode/assistant/uploadPage.vue'
import CascaderPage from '@/components/lowCode/assistant/cascader.vue'
import DatePickerPage from '@/components/lowCode/assistant/datePicker.vue'
import ExpandUser from '@/components/lowCode/assistant/user.vue'
import LowcodeImagePage from '@/components/lowCode/assistant/lowcodeImage.vue'
import BaiDuMap from '@/components/lowCode/assistant/baiDuMap.vue' 
import OwnerPage from '@/components/lowCode/assistant/ownerPage.vue'   
import SerialNumber from '@/components/lowCode/assistant/serialNumber.vue'   
import FounderForm from '@/components/lowCode/assistant/founder.vue'
import FounderTime from '@/components/lowCode/assistant/founderTime.vue'
import EditTime from '@/components/lowCode/assistant/editTime.vue'
import VideoUpAndPlay from '@/components/lowCode/assistant/videoUpAndPlay.vue'  
import LowcodeCarsusel from '@/components/lowCode/assistant/lowcodeCarsusel.vue'  
import SignatureMap from '@/components/lowCode/assistant/signatureMap.vue'  
import AssociatedForms from '@/components/lowCode/assistant/associatedForms.vue'  
import LowcodeTransfer from '@/components/lowCode/assistant/lowcodeTransfer.vue'   
import UrlLink from '@/components/lowCode/assistant/urlLink.vue' 
import DepartmentOrg from '@/components/lowCode/assistant/departmentOrg.vue'   



const props = withDefaults(
    defineProps<{
		data: FormList
		modelValue?: any // 子表和弹性布局时时有传
		tProp?: string // 子表时的form-item的prop值，用于子表校验用
		nodeKey?:string
		purview?:any[]
		optionsValue3Get1?:any
		tablekey?:any
		numrun?:any
		rowIndex?:any
    }>(),
    {}
)
const emits = defineEmits<{
    (e: 'update:modelValue', val: any): void
	(e: 'optionsValue3Get1', val: any,fieldName: string): void
	(e: 'asfValueChanged', val: any): void
}>()
const route = useRoute()
const formProps = inject(constFormProps, {}) as any
const imgUploadApiUrl = import.meta.env.VITE_APP_BASE_API+"/api/upordown"
//执行类型
const type = computed(() => {
    return formProps.value.type
})
//配置
const config = computed(() => {
    return props.data.config || {}
})
//组件css部分
const configStyle = computed(() => {
    return props.data.styles || {}
})
const control = computed(() => {
	if(props.data.type == "upload"){
		props.data.control.action = uploadUrl
	}
    return props.data.control
})
const options = ref(props.data.options) //附属属性值
const changeEvent = inject(constControlChange, '') as any
//更新数值
const updateModel = (val: any) => {
	let controlAttribute = ""
	if(props.data.control){
		if(props.data.control.type){
			controlAttribute = props.data.control.type
		}
	}
    changeEvent &&
    changeEvent({
        key: props.data.name,
        value: val,
        data: props.data,
        tProp: props.tProp,
		type: props.data.type,
		attribute: controlAttribute
    })
}
//获取值
const value = computed({
    get() {
		if (props.tProp) {
			// 表格和弹性布局
			return props.modelValue
		} else {
			if(props.data.type == "checkbox"){
				if (formProps.value.model[props.data.name] == null || formProps.value.model[props.data.name] == ""){
					// formProps.value.model[props.data.name] = []
					// return formProps.value.model[props.data.name]
					return []
				}else{
					return formProps.value.model[props.data.name]
				}
			}else{
				return formProps.value.model[props.data.name]
			}
			
		}
    },
    set(newVal: any) {
		if (props.tProp) {
			emits('update:modelValue', newVal)
		}
		updateModel(newVal)
    }
})
const getControlByName = inject(constGetControlByName) as any
// 对单选多选select设置options
const formOptions = inject(constSetFormOptions, {}) as any

// 返回当前item项的校验规则
const itemRules = computed(() => {
    let temp
    const itemR: any = props.data.item?.rules || []
    const customR = formatCustomRules()
    // 如果三个都没有设置，则返回undefined
    if (itemR?.length || customR?.length) {
      	temp = [...customR, ...itemR]
    }
    return temp
})
// 处理自定义校验规则，将customRules转换后追加到rules里
const formatCustomRules = () => {
    const rulesReg: any = {}
    validate &&
    validate.forEach(item => {
        rulesReg[item.type] = item.regExp
    })

    // 获取校验方法 父级使用provide方法注入
    const temp: any = []
    props.data.customRules?.forEach((item: any) => {
		if (!item.message && item.type !== 'methods') {
			return // 方法时允许提示信息为空
		}
		let obj = {}
		if (item.type === 'required') {
			obj = { required: true }
		} else if (item.type === 'rules') {
			// 自定义表达式
			obj = { pattern: item.rules }
		} else if (item.type === 'methods') {
			// 方法时
			const methods: any = item.methods
			if (methods) {
			obj = { validator: inject(methods, {}) }
			}
		} else if (item.type) {
			obj = { pattern: rulesReg[item.type as string] }
		}
		// 这里判断下防某些条件下重复push的可能或存重复校验类型
		let message: any = { message: item.message }
		if (!item.message) {
			// 当使用validator校验时，如果存在message字段则不能使用 callback(new Error('x'));的提示
			message = {}
		}
		temp.push(
			Object.assign(
				{
					trigger: item.trigger || 'blur'
				},
				obj,
				message
			)
		)
    })
    return temp
}
// 控制编辑模式下是否可用
const editDisabled = computed(() => {
    if (type.value === 3) {
      	return true // 查看模式，为不可编辑状态
    }
    if (type.value === 1 && config.value.addDisabled) {
      	return true
    }
    if (type.value === 2 && config.value.editDisabled) {
      	return true // 编辑模式
    }
	// return judgeIsDisabled(key)
    return control.value.disabled
})
//获取标签
const getLabel = (ele: FormItem) => {
    const showColon = formProps.value.showColon ? '：' : ''
    if (ele) {
    	return ele.showLabel ? '' : ele.label + showColon
    } else {
      	return ''
    }
}
/**
@ 作者: 秦东
@ 时间: 2024-11-13 14:36:08
@ 功能: 解析css
*/
const getFormItemLableStyle = (ele: any) => {
    if(ele?.labelStyle){ 
    //   console.log("返回栅格宽度3",AnalysisCss(ele))
    	return AnalysisCss(ele?.labelStyle)
    }
}
const getFormItemInputStyle = (ele: any,sty:number) => {
    if(ele?.inputStyle){
    //   console.log("返回栅格宽度4",AnalysisInputCss(ele?.inputStyle,sty))
      return AnalysisInputCss(ele?.inputStyle,sty)
    }
}
/**
@ 作者: 秦东
@ 时间: 2024-07-27 15:11:42
@ 功能: 判断是否禁用
*/
const judgeIsDisabled = (key:string)  => {
	if (type.value === 3) {
      	return true // 查看模式，为不可编辑状态
    }
    if (type.value === 1 && config.value.addDisabled) {
      	return true
    }
    if (type.value === 2 && config.value.editDisabled) {
      	return true // 编辑模式
    }
	if(props.nodeKey != undefined && props.purview != undefined && props.purview != null && props.purview != null && props.purview != "" && props.purview != "") {
		if(props.purview.length < 1){
			return false;
		}else{
			let isShow = true;
			props.purview.forEach((item)=>{
				if(item.nodeKey == props.nodeKey){
					
					if(item.powerAry && item.powerAry.length > 0){
						item.powerAry.forEach((itm)=>{
							if(itm.id == key){
								console.log("判断此组件是否禁用",itm,itm.id == key,"--------->",itm.isLook)
								isShow =  !itm.isEdit
								
							}
						})
					}
				}
				
			})
			return isShow
		}
	}else{
		return false;
	}
}
/****input slot处理***/
const getInputSlot = (key?: string) => {
    const slot = key === 'p' ? config.value.prepend : config.value.append
    const has = slot.indexOf('key:') === 0
    if (!has) {
      	return false
    }
    const slotKey = slot.replace('key:', '')
    const control = getControlByName(slotKey)
    if (!control || Object.keys(control)?.length === 0) {
      	return false
    }
    return control
}
// 选择数据转换，默认尝试转数字
const transformOption = (val: string | number, type?: string) => {
    switch (config.value.transformData || type) {
		case 'none':
				return val
		case 'string':
			try {
				return val.toString()
			} catch (e) {
				return val
			}
    }
    return formatNumber(val)
}
//输入框中下拉值改变
const inputSlotChange = (val: string | number, name: string) => {
    changeEvent &&
    changeEvent({
        key: name,
        value: val,
        data: {},
        tProp: ''
    })
}
// data 根据条件搜索，select远程搜索里data有值
const getAxiosOptions = debounce((data?: any) => {
	//console.log(props.data)
    const {
		optionsType,
		optionsFun,
		method = 'post',
		afterResponse,
		beforeRequest,
		label,
		value,
		debug // =true可用于调试，不存sessionStorage
    } = config.value
    if (optionsType !== 0) {
      	let sourceFun = optionsFun
      	// 接口数据源
      	if (optionsType === 1 && sourceFun) {
        	// 当前控件为动态获取数据，防多次加载，先从本地取。data=true时直接请求
			let md5Object:any = new Md5()
			md5Object.appendAsciiStr(JSON.stringify(sourceFun + data))
			let md5Str = md5Object.end()
			// const key = 'getOptions_' + props.data.name + md5(sourceFun + data)
			const key = 'getOptions_' + props.data.name + md5Str
			const storage = window.sessionStorage.getItem(key)
            if (storage && !data && !debug) {
                const val = JSON.parse(storage)
                if (props.data.type === 'treeSelect') {
                    control.value.data = val
                } else {
                    options.value = val
                }
            } else {
          	// 从url里提取一个动态值,${name}形式提取name
                if (sourceFunKey.value) {
                    const val = formProps.value.model[sourceFunKey.value]
                    const string = '${' + sourceFunKey.value + '}'
                    sourceFun = sourceFun.replace(string, val)
                }
                // 处理请求前的数据
                //let newData = Object.assign({}, data || {}, queryParams)
                let newData = data || {}
                if (typeof beforeRequest === 'function') {
                    newData =
                    beforeRequest(newData, route, formProps.value.model) ?? data
                }
                if (newData === false) {
                    return
                }
                if (method === 'get') {
                    newData = { params: newData }
                }
        	}
    	}else if(optionsType === 3){//liwenxuan 20240611 系统表单字段效果实现
			/*
				在这里请求后台获取字段
			*/
			//console.log("formItem---291",props.data.control.optionsValue3Field)
			if(props.data.control.optionsValue3Field && props.data.control.optionsValue3Field != "" && props.data.control.optionsValue3Field != null && props.data.control.optionsValue3Field != "undefined"){
				//console.log(111)
				getFieldRecord(props.data.control.optionsValue3Field).then(({ data }) => {
					
					let fieldName = props.data.name
					//console.log(data,fieldName)
					emits('optionsValue3Get1',data,fieldName)
					
				})
			}
			
		}
      	setFormDict(formProps.value.dict) // 表格里新增时行时需要重新设一次
    }
})
// 从数据接口获取数据设置options，在表单添加或编辑时数据加载完成
const setFormDict = (val: any) => {
	// console.log("从数据接口获取数据设置options",val)
    if (val && config.value.optionsType === 2) {
      		const opt = val[config.value.optionsFun] || val[props.data.name] // 不填写默认为当前字段名
      	if (opt !== undefined) {
        	options.value = objectToArray(opt)
      	}
    }
}
/**
@ 作者: 秦东
@ 时间: 2024-11-13 16:18:59
@ 功能: 自定义组件
*/
const currentComponent = computed(() => {
    if (props.data.type === "component") {
        // 自定义组件
        return config.value.componentName;
    }
    if (props.data.type === 'organization') {   //联系地址
      	return markRaw(OrgCitys)
    }
    if (props.data.type === 'upload') { //文件
      	return markRaw(UploadPage)
    }
    if (props.data.type === 'cascader') { //文件
      	return markRaw(CascaderPage)
    }
    if (props.data.type === 'datePicker') { //日期
        props.data.control.valueFormat = "x";
      	return markRaw(DatePickerPage)
    }
    if (props.data.type === 'expand-user') { //选择用户
        return markRaw(ExpandUser);
    }
    if (props.data.type === "lowcodeImage") {
        return markRaw(LowcodeImagePage);
    }
    if (props.data.type === "baidumap") {
        return markRaw(BaiDuMap);
    }
    if (props.data.type === "owner") {
        return markRaw(OwnerPage);
    }
    if (props.data.type === "serialNumber") {
        return markRaw(SerialNumber);
    }
    if (props.data.type === "founder") {
        return markRaw(FounderForm);
    }
    if (props.data.type === "founderTime") {
        return markRaw(FounderTime);
    }
    if (props.data.type === "editTime") {
        return markRaw(EditTime);
    }
    if (props.data.type === "videoUpAndPlay") {
        return markRaw(VideoUpAndPlay);
    }
    if (props.data.type === "lowcodeCarsusel") {
        return markRaw(LowcodeCarsusel);
    }
    if (props.data.type === "signaturemap") {
        return markRaw(SignatureMap);
    }
    if (props.data.type === "associatedForms") {
        return markRaw(AssociatedForms);
    }
    if (props.data.type === "lowcodeTransfer") {
        return markRaw(LowcodeTransfer);
    }
    if (props.data.type === "urllink") {
        return markRaw(UrlLink);
    }
    if (props.data.type === "deptOrg") {
        return markRaw(DepartmentOrg);
    }
    return `el-${props.data.type}`
})
</script>
<template>
    <div>
        <template class="form-value" v-if="type === 15">
            2
        </template>
        <template v-if="data.type=='index'"></template>
        <template class="form-value" v-else>
            
            <el-form-item
                v-bind="data.item"
                :prop="tProp || data.name"
                :class="config.className"
                :rules="itemRules as any"
                :label="getLabel(data.item as FormItem)"
            >
                <template #label v-if="config.help">
                    <span :style="getFormItemLableStyle(configStyle)">{{ getLabel(data.item) }}</span>
                    <Tooltips :content="config.help" />
                </template>
                <template #label v-else>
                    <span :style="getFormItemLableStyle(configStyle)" >{{ getLabel(data.item) }}</span>
                </template>
                <el-input
                    v-bind="control"
                    v-model="value"
                    :disabled="judgeIsDisabled(data.name)"
                    :type="data.type === 'password' ? 'password' : 'text'"
                    :style="getFormItemInputStyle(configStyle,2)"
                    :input-style="getFormItemInputStyle(configStyle,3)"
                    v-if="['input', 'password'].includes(data.type)"
                    :placeholder="data.control.placeholder?data.control.placeholder:'请输入'+getLabel(data.item)"
                >
                    <template #prepend v-if="config.prepend">
                        <div v-if="getInputSlot('p')">
                            <SelectDesign 
                                :data="getInputSlot('p')"
                                :disabled="judgeIsDisabled(data.name)"
                                :transform-option="transformOption"
                                @change="inputSlotChange"
                                type="slot"
                            />
                        </div>
                        <span v-else>{{ config.append }}</span>
                    </template>
                    <template #append v-if="config.append">
                        <div v-if="getInputSlot()">
                            <SelectDesign 
                                :data="getInputSlot()"
                                :disabled="judgeIsDisabled(data.name)"
                                :transform-option="transformOption"
                                @change="inputSlotChange"
                                type="slot"
                            />
                        </div>
                        <span v-else>{{ config.append }}</span>
                    </template>
                </el-input>
                <!--多行文本-->
                <el-input
                    v-bind="control"
                    v-model="value"
                    :disabled="judgeIsDisabled(data.name)"
                    type="textarea"
                    :placeholder="data.control.placeholder?data.control.placeholder:'请输入'+getLabel(data.item)"
                    :style="getFormItemInputStyle(configStyle,2)"
                    :input-style="getFormItemInputStyle(configStyle,3)"
                    v-if="['textarea', 'description'].includes(data.type)"
                />
                <!--单选-->
                <el-radio-group
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    v-model="value"
                    v-if="data.type === 'radio'"
                    :style="getFormItemInputStyle(configStyle,4)"
                >
                    <el-radio
                        :key="index"
                        :label="transformOption(item.value)"
                        v-for="(item, index) in props.data.options"
                        
                    >
                        <span :style="getFormItemInputStyle(configStyle,5)">{{ item.label }}</span>
                    </el-radio>
                </el-radio-group>
                <!--时间-->
                <el-time-picker
                    v-if="data.type == 'timePicker'"
                    v-model="value"
                    value-format="x"
                    :placeholder="
                    data.control.placeholder
                        ? data.control.placeholder
                        : '请选择' + getLabel(data.item)
                    "
                />
                <!--多选-->
                <el-checkbox-group
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    v-model="value"
                    v-if="data.type === 'checkbox'"
                    :style="getFormItemInputStyle(configStyle,4)"
                >
                    <el-checkbox
                        v-for="(item, index) in props.data.options"
                        :key="index"
                        :label="transformOption(item.value)"
                    >
                    <span :style="getFormItemInputStyle(configStyle,5)">{{ item.label }}</span>
                    </el-checkbox>
                </el-checkbox-group>
                <!--下拉-->
                <SelectDesign 
                    v-if="data.type === 'select' || (type === 15 && data.type === 'inputSlot')"
                    :data="data"
                    :disabled="judgeIsDisabled(data.name)"
                    v-model="value"
                    :options="props.data.options"
                    :remote-method="getAxiosOptions"
                    :transformOption="transformOption"
                    :placeholder="data.control.placeholder?data.control.placeholder:'请选择'+getLabel(data.item)"
                />
                <!--联系地址-->
                <component
                    v-if="['organization'].includes(data.type)"
                    :is="currentComponent"
                    :data="data"
                    v-bind="control"
                    :control="control"
                    :config="config"
                    :name="control.file || 'file'"
                    :disabled="judgeIsDisabled(data.name)"
                    :options="options"
                    v-model="value"
                />
                <!--上传-->
                <component
                    v-if="['upload'].includes(data.type)"
                    :is="currentComponent"
                    :data="data"
                    v-bind="control"
                    :control="control"
                    :config="config"
                    :name="control.file || 'file'"
                    :disabled="judgeIsDisabled(data.name)"
                    :options="options"
                    v-model="value"
                />
                <!--级联选择器-->
                <component
                    v-if="['cascader'].includes(data.type)"
                    :is="currentComponent"
                    v-bind="control"
                    :data="data"
                    :control="control"
                    :config="config"
                    :disabled="judgeIsDisabled(data.name)"
                    :options="options"
                    v-model="value"
                    
                />
                <!--树形控件-->
                <component
                    v-if="['treeSelect'].includes(data.type)"
                    :is="currentComponent"
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    :options="options"
                    v-model="value"
                />
                <!--日期选择器-->
                <component
                    v-if="['datePicker'].includes(data.type)"
                    :is="currentComponent"
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    :data="data"
                    :placeholder="
                    data.control.placeholder
                        ? data.control.placeholder
                        : '请选择' + getLabel(data.item)
                    "
                    v-model="value"
                />
                <!--综合-->
                <component
                    v-if="
                    [
                        'rate',
                        'slider',
                        'switch',
                        'inputNumber',
                        'colorPicker',
                        'component',
                    ].includes(data.type)
                    "
                    :is="currentComponent"
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    :placeholder="
                    data.control.placeholder
                        ? data.control.placeholder
                        : '请选择' + getLabel(data.item)
                    "
                    v-model="value"
                />
                <!--选择用户-->
                <component
                    v-if="['expand-user'].includes(data.type)"
                    :is="currentComponent"
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    :data="data"
                    :placeholder="
                    data.control.placeholder
                        ? data.control.placeholder
                        : '请选择' + getLabel(data.item)
                    "
                    v-model="value"
                />
                <!--图片-->
                <component
                    v-if="['lowcodeImage'].includes(data.type)"
                    :is="currentComponent"
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    :placeholder="
                    data.control.placeholder
                        ? data.control.placeholder
                        : '请选择' + getLabel(data.item)
                    "
                    :data="data"
                    :tablekey="props.tablekey"
                    :form-table-set-up="props.alldata"
                    v-model="value"
                />
                <!--富文本-->
                <div class="form-value" v-else-if="data.type == 'tinymce'" v-html="value"></div>
                <!--地图-->
                <component
                    v-if="['baidumap'].includes(data.type)"
                    :is="currentComponent"
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    :placeholder="
                    data.control.placeholder
                        ? data.control.placeholder
                        : '请选择' + getLabel(data.item)
                    "
                    :data="data"
                    :tablekey="props.tablekey"
                    :form-table-set-up="props.alldata"
                    v-model="value"
                />
                <!--拥有者-->
                <component
                    v-if="['owner'].includes(data.type)"
                    :is="currentComponent"
                    v-bind="control"
                    :disabled="judgeIsDisabled(data.name)"
                    :placeholder="
                    data.control.placeholder
                        ? data.control.placeholder
                        : '请选择' + getLabel(data.item)
                    "
                    :data="data"
                    :tablekey="props.tablekey"
                    :form-table-set-up="props.alldata"
                    v-model="value"
                />
                <!--编码、创建人、创建时间、修改时间、视频、轮播图、签名板、链接-->
                <component
                    v-if="[
                        'serialNumber',
                        'founder',
                        'founderTime',
                        'editTime',
                        'videoUpAndPlay',
                        'lowcodeCarsusel',
                        'signaturemap',
                        'urllink',
                        'deptOrg'
                    ].includes(data.type)"
                    :is="currentComponent"
                    :data="data"
                    v-bind="control"
                    :control="control"
                    :config="config"
                    :name="control.file || 'file'"
                    :disabled="judgeIsDisabled(data.name)"
                    :options="options"
                    v-model="value"
                />
                <!--关联表单-->
                <component
                    v-if="['associatedForms'].includes(data.type)"
                    :is="currentComponent"
                    :data="data"
                    v-bind="control"
                    :control="control"
                    :config="config"
                    :name="control.file || 'file'"
                    :disabled="judgeIsDisabled(data.name)"
                    :options="options"
                    v-model="value"
                />
                <!--穿梭框-->
                <component
                    v-if="['lowcodeTransfer'].includes(data.type)"
                    :is="currentComponent"
                    :data="data"
                    v-bind="control"
                    :control="control"
                    :config="config"
                    :name="control.file || 'file'"
                    :disabled="judgeIsDisabled(data.name)"
                    :options="options"
                    v-model="value"
                />


















            </el-form-item>
        </template>
    </div>
</template>
<style  lang='scss' scoped>

</style>