<template>
  <div class="by-form" :style="{width:attrs.width}">
    <el-descriptions v-if="attrs.showType=='desc'" :title="attrs.title" :column="attrs.itemCount" :border="attrs.border" :direction="attrs.direction" 
    :size="attrs.size?attrs.size:'default'" :colon="attrs.colon">
      <template v-for="(itemChild,index) of columns">
        <el-descriptions-item :label="item.label" v-for="(item,_ind) of itemChild" :span="item.colspan" :key="index+'-'+_ind">
          <slot v-if="item.descSlot" :name='item.prop+"_desc"' :value='value'></slot>
          <component v-else-if="item.showComp" v-bind:is="item.component" :propConfig="item.compConfig" :ref="item.prop+suffixCode" :parentValue="value" :propValue="value[item.prop]"  />
          <template v-else>{{value[item.prop]?value[item.prop]:'--'}}</template>
        </el-descriptions-item>
      </template>
    </el-descriptions>
    <el-form class="byForm" v-else :style="{ height: attrs.height ? attrs.height + 'px' : 'auto' }" :model="value" ref="byForm" :validate-on-rule-change="false" 
    :inline-message="true" v-bind="$attrs" :disabled="attrs.disabled" :label-width="attrs.labelWidth?attrs.labelWidth:'100px'" :rules="attrs.readonly?{}:attrs.rules"
    :label-position="attrs.labelPosition ? attrs.labelPosition : 'right'">
      <el-row class="form-row" v-for="(itemChild,index) of columns" :key="index">
        <el-col v-for="(item,_ind) of itemChild" :span="item.span" :key="'itemChild'+_ind">
          <el-form-item class="by-form-item" 
            :label="item.label" :rules="attrs.readonly?[]:item.rules" :prop="item.prop" :required="item.required" :error="item.error" :size="item.size" 
            :label-width="item.labelWidth">
            <component v-bind:is="item.component" 
              class="form-comp" :propConfig="item.compConfig" :ref="item.prop+suffixCode" :parentValue="value" :propValue="value[item.prop]" 
              @onChange="onChange($event,item)" v-bind="$attrs" />
            <slot v-if="item.slot" :name='item.prop' :value='value'></slot>
            <div class="readonly-cover" v-if="attrs.readonly"></div>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <!-- <el-button @click="getValueData">获取数据</el-button> -->
  </div>
</template>

<script setup>
  import { computed,getCurrentInstance,nextTick  } from "vue";
  const { proxy,ctx:that } = getCurrentInstance();
  const suffixCode=ref("--comp")
  const value = ref({})
  const emit = defineEmits();
  const config = ref({})
  const props = defineProps({
    propConfig:{},
    propValue:{},
    parentValue:{}
  })
  const requestConfig = computed({
    get() {
      return config.value.request ? config.value.request : null;
    }
  })
  const attrs = computed({
    get() {
      return config.value.attr ? config.value.attr : {};
    }
  })
  const getValueData = () =>{
    console.log(value.value)
  }
  const columns = computed({
    get() {
      let columns = config.value?.columns ? config.value.columns : []
      //分栏设置
      if(columns.length > 0){
        for (const itemChild of columns) {
          let spans = 24
          let n = itemChild.length
          for(const item of itemChild){
            if (item && ((Number(item.span) > 0 && Number(item.span) <= 24))) {
              spans = spans - Number(item.span)
              n--;
            }
          }

          for(const item of itemChild){
            if (Number(item.span) > 0 && Number(item.span) <= 24) {
              item.span = Number(item.span)
            } else {
              item.span = spans / n
            }
          }
          
        }
      }
      return columns
    }
  })
  const setValue = data => {
    
    if(data){
      value.value = proxy.lodash.cloneDeep(data);
    }else{
      value.value = {};
    }
    nextTick(()=>{
      setChildrenComValue();
    })
    
    proxy.$forceUpdate();
  }
  const clearValue = () => {
    value.value = {};
    clearChildrenComp();
    defaultHandle();
    setTimeout(()=>{
      clearValidate();
    },100)
  }
  const getValue = () => {
    return proxy.lodash.cloneDeep(value.value);
  }
  //设置表单内某组件配置
  const setCompConfig = (code, c) => {
    if(proxy.$refs[code+suffixCode.value] && proxy.$refs[code+suffixCode.value][0] && proxy.$refs[code+suffixCode.value][0].setConfig){
      proxy.$refs[code+suffixCode.value][0].setConfig(c)
    }
  }
  const setConfigAfter = () => {
    nextTick(()=>{
      if(columns.length > 0){
        for(const itemData of columns){
          for(const item of itemData){
            if(proxy.$refs[item.prop+suffixCode.value] && proxy.$refs[item.prop+suffixCode.value][0] && proxy.$refs[item.prop+suffixCode.value][0].setConfig){
              proxy.$refs[item.prop+suffixCode.value][0].setConfig(item.compConfig)
            }
          }
        }
      }
    })
  }
  //清除下级组件组件值
  const clearChildrenComp = () => {
    for(const key in proxy.$refs){
      if(key.indexOf(suffixCode.value) >= 0 && proxy.$refs[key][0] && proxy.$refs[key][0].clearValue){
        proxy.$refs[key][0].clearValue()
      }
    }
  }
  //下级组件默认值
  const defaultHandle = () => {
    for(const key in proxy.$refs){
      if(key.indexOf(suffixCode) >= 0 && proxy.$refs[key][0] && proxy.$refs[key][0].defaultHandle){
        proxy.$refs[key][0].defaultHandle()
      }
    }
  }
  //设置下级组件值
  const setChildrenComValue = () => {
    for(const key in proxy.$refs){
      if(key.indexOf(suffixCode.value) >= 0 && proxy.$refs[key][0] && proxy.$refs[key][0].setValue){
        const code = key.split(suffixCode.value)[0];
        if(value.value){
          proxy.$refs[key][0].setValue(value.value[code])
        }else{
          proxy.$refs[key][0].setValue(null)
        }
      }
    }
  }
  //表单数据变化
  const onChange = (v, config) => {
    let code = config.prop;
    if (v && v.constructor === Object){
      for(const key in v){
        value.value[key] = v[key]
        // changeSetValue(key,v[key])
      }
    }else{
      value.value[code] = v
      // changeSetValue(code,v)
    }
    if(proxy.$refs.byForm){
      proxy.$refs.byForm.validateField(code);
    }
    emit('formChange',{value:v,code:code})
  }
  const changeSetValue = (code, v) => {
    if(value.value[code]){
      value.value[code] = v;
    }else{
      Vue.set(value.value, code, v);
    }
  }
  //表单验证
  const validate = parames => {
    return new Promise((resolve, reject) => {
      if(!proxy.$refs.byForm){
        resolve(true)
      }
      const failHandel = () => {
        if(!parames || !parames.noMsg){
          proxy.$message({
            showClose: true,
            message: '验证未通过，请检查！',
            type: 'warning'
          })
        }
        reject()
      }
      proxy.$refs.byForm.validate(valid => {
        if (valid) {
          let va = true
          for(const col of columns.value){
            for(const item of col){
              if(proxy.$refs[item.prop+suffixCode] && proxy.$refs[item.prop+suffixCode][0] && proxy.$refs[item.prop+suffixCode][0].validate){
                va = proxy.$refs[item.prop+suffixCode][0].validate()
                if(!va) break
              }
            }
            if(!va) break
          }
          if(va){
            resolve(true)
          }else{
            failHandel()
          }
          
        } else {
          failHandel()
        }
      });
    })
  }
  //清除过滤提示
  const clearValidate = () => {
    if(proxy.$refs.byForm){
      proxy.$refs.byForm.clearValidate();
    }
  }
  //设置配置
  const setConfig = c => {
    if(c){
      config.value = c;
    }
    setConfigAfter()
  }

  //获取配置
  const getConfig = () => {
    return lodash.cloneDeep(config.value)
  }

  if(props.propConfig){
    setConfig(props.propConfig)
  }
  defineExpose({
    getValue,setValue,getConfig,setConfig,clearValidate,validate,clearValue
  })
</script>

<style lang="scss" scoped>
.by-form{
  width: 100%;
  margin: 0 auto;
  .form-comp{
    width: 100%;
  }
  .readonly-cover{
    position: absolute;
    height: 100%;
    width: 100%;
    left: 0;
    top: 0;
  }
}
</style>
<style lang="scss">
.by-form-item{
  margin-bottom: 10px !important;
}
</style>