<template>
<a-form :ref="setExposeObject" class="ELXForm" :model="model" v-bind="$attrs">
	<a-row :gutter="gutter" v-for="(item,index) in colOptions" :key="index">
		<a-col :span="(citem.span || 1)*baseSpan" v-for="(citem,cindex) in item" :key="cindex">
			<a-form-item v-bind="citem.item">
				<slot v-if="citem.slot" :form="citem.form" :item="citem.item" :name='citem.slot' />
				<DIYInput style="width:100%;" v-else-if="citem.mode === 'switch'" v-bind="citem.form" v-model:checked="model[citem.item.name]" />
				<DIYInput style="width:100%;" v-else-if="citem.mode === 'file'" v-bind="citem.form" v-model="model[citem.item.name]" />
				<DIYInput style="width:100%;" v-else-if="citem.mode === 'fileurls'" v-bind="citem.form" v-model:urls="model[citem.item.name]" />
				<DIYInput style="width:100%;" v-else v-bind="citem.form" v-model:value="model[citem.item.name]" />
			</a-form-item>
		</a-col>
	</a-row>
</a-form>
</template>
<script setup>
import { computed, onMounted, reactive, ref, toRefs } from "vue";
const props = defineProps({
	model:{type:Object,default:()=>{return{}}},
	/*
		扩展属性:
			slot:表单插槽,mode:表单类型,values:可选值,default:默认值,span:表单占比(row/col span值)
		FormItem:
			全属性
		Input:
			全属性
	*/
	options:Array,
	column:{type:Number,default:3},
	gutter:{type:Number,default:20},
});

const ExposeObject = {
	get fd(){ return obj_toFormData(props.model) },
};
defineExpose(ExposeObject);


function setExposeObject(el){
	Object.assign(ExposeObject,el);
}
const baseSpan = computed(()=>{
	const defaultValues = {};
	for (const item of props.options) {
		if(item.name){
			if(!props.model[item.name]){
				defaultValues[item.name] = item.default;
			}
		}
	}
	Object.assign(props.model,defaultValues);
	return Math.floor(24 /props.column);
});
const colOptions = computed(()=>{
	const opts = splitOptionsItem(props.options);
	return arr_chunk(opts,props.column);
});
const FormItemKeys = [
	'autoLink','colon','extra','hasFeedback','help','htmlFor','label',
	'labelAlign','labelCol','name','required','rules','validateFirst',
	'validateStatus','validateTrigger','wrapperCol'
];
function splitOptionsItem(options){
	return options.map(v=>{
		let obj = {
			mode:v.mode,
			slot:v.slot || undefined,
			span:v.span || 1,
			item:obj_delete(v,FormItemKeys,true),
			form:obj_delete(v,FormItemKeys,false),
		}
		return obj;
	});
}

function _type(opt){ return Object.prototype.toString.call(opt).slice(8,-1); }

function obj_toFormData(data={},form){
	let formData = new FormData();
	forData(data);
	function forData(data,item=false){
		if(Object.keys(data).length === 0){ return; }
		Object.keys(data).forEach(key=>{
			let val = data[key],
			forKey = item === false ? key : item+`[${key}]`;
			if(['Array','Object'].indexOf(_type(val)) > -1){
				forData(val,forKey);
			} else {
				formData.append(forKey,data[key]);
			}
		});
	}
	return formData;
}
function obj_delete(opt,keys,isNegate){
	if(typeof keys === 'string'){
		keys = keys.split(',');
	}
	let result = {};
	if(!Array.isArray(keys)){ throw new Error('keys 必须是字符串数组！') }
	if(isNegate){
		result = {};
		for(let key of keys){ result[key] = opt[key]; }
	} else {
		result = Object.assign({},opt);
		for(let key of keys){ delete result[key]; }
	}
	return result;
}

function arr_chunk(arr,size=3){
	size = Math.max(Math.floor(size),0)
	const len = arr == null ? 0 : arr.length;
	let result = [];
	if(!len || size < 1){
		return result;
	}
	let index = 0;
	let resIndex = 0;
	while(index < len){
		result[resIndex++] = arr.slice(index,index+=size)
	}
	return result;
}
</script>