<template>
    <div style="width: 100%"  ref="selectDiv">
        <template v-if="!isShowSpan">
            <span class="jlcombobox-container" v-if="!showText">
                <template v-for="(obj,key) in optionMap">
                    <el-form-item :prop="obj.field" :rules="rules[obj.field]">
                        <el-select v-model="formData[obj.field]" v-if="!obj.isHidden"
                                   :ref="obj.field"
                                   placeholder="请选择"
                                   :size="size"
                                   :style="style"
                                   :multiple="obj.multiple"
                                   :disabled="obj.disabled"
                                   filterable
                                   @change="obj.onChange(formData[obj.field])"
                                   popper-class="jlcombobox"
                                   :popper-class="skinType === 'dark' ? 'listview-dark' : ''" :clearable="clearable">
                        <el-option-group
                                v-if="obj.needGroup"
                                v-for="group in obj.datas"
                                :key="group.id"
                                :label="group.name">
                                <el-option
                                        v-for="item in group.datas"
                                        :key="item[valueField]"
                                        :label="item[labelField]"
                                        :value="item[valueField]">
                                </el-option>
                        </el-option-group>
                        <el-option
                                v-if="!obj.needGroup"
                                v-for="item in obj.datas"
                                :key="item[valueField]"
                                :label="item[labelField]"
                                :value="item[valueField]">
                        </el-option>
                    </el-select>
                        <span style="margin: 0 2px" v-if="key != Object.keys(optionMap)[Object.keys(optionMap).length -1]">{{obj.separator}}</span>
                    </el-form-item>
                </template>
            </span>
            <div v-if="showText" style="height: 36px;">
                {{valueLabel}}
            </div>
        </template>
        <span class="jlcombobox-container" v-else>
            <div v-if="showText" style="height: 36px;">
                {{valueLabel}}
            </div>
            <div v-else>
                <el-select v-model="oneLevel" placeholder="请选择一级选项" @change="changeSelect" :popper-class="skinType === 'dark' ? 'listview-dark' : ''"
                           style="width: calc(50% - 8px)">
                    <el-option
                        v-for="item in selectData"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                    </el-option>
                </el-select>
                -
                <el-select v-model="twoLevel" placeholder="请选择二级选项" :popper-class="skinType === 'dark' ? 'listview-dark' : ''"
                           style="width: calc(50% - 8px)">
                      <el-option
                          v-for="item in secondary"
                          :key="item.value"
                          :label="item.label"
                          :value="item.value">
                      </el-option>
                </el-select>
            </div>
        </span>
    </div>
</template>

<script>
    export default {
        name: "pl-cascade-select-form",//级联下拉框,用于表单校验
        props: {
            formData: {type: Object, required: true},//表单对象
            field: {type: String, required: true},//操作字段
            typeId: {type: String, required: true},//数据字典IDh
            hasParentJudge:{type: String, default: ""},//是否需要父级
            parentId:{type: String},//父级ID
            dataUrl:{type: String},//数据来源
            separator:{type: String, default: "-"},//分隔符
            valueField: {type: String, default: "id"},//值域字段名称
            labelField: {type: String, default: "dataName"},//显示域字段名称
            parentField: {type: String, default: "parentId"},//父级字段名称
            multiple: {type: String,  default: ""},//是否多选
            disabled: {type: String,  default: ""},//是否只读
            isHidden: {type: String, default: ""},//是否隐藏
            defaultValue: {type: String, default: ""},//默认值
            clickCallback:{type:Function,default: null},
            size:{type: String,  default: "small"},
            clearable:{type:Boolean,default:true},//是否可清除
            rules:{type:Object,default:() => {return {};}},
            showText:{required: false, default: false, type: Boolean},
            rememberSysDataObj:{type:Function},
            width:{required: false},
            skinType: {type: String, default: ""}, //组件皮肤类型
        },
        data() {
            return {
                dataMap : {},
                dataIdMap : {},
                optionMap : {},
                parentTempId:"-1",
                OBJ_DATAS: {},
                valueLabel:"",
                style:{},
                isShowSpan:false,
                selectData:[{
                    value: 'firstOption',
                    label: '选项1',
                    children: [{
                        value: 'firstGroupOne',
                        label: '选项1-1',
                    }, {
                        value: 'firstGroupTwo',
                        label: '选项1-2',
                    }]
                },  {
                    value: 'secondOption',
                    label: '选项2',
                    children: [{
                        value: 'secondGroupOne',
                        label: '选项2-1'
                    }, {
                        value: 'secondGroupTwo',
                        label: '选项2-2'
                    }, {
                        value: 'secondGroupThird',
                        label: '选项2-3'
                    }]
                }],
                oneLevel:'',
                twoLevel:'',
                secondary:[],
            }
        },
        watch:{
            parentId(){
                this.initCascadeSelect();
            },
            typeId(){
                this.isShowSpan = !this.typeId
            },
            "formData.refreshUUId":{
                deep:true,
                handler:function(){
                    if(this.formData.refreshUUId){
                        this.initCascadeSelect();
                    }
                }
            }
        },
        created() {
            this.isShowSpan = !this.typeId;
            if(this.isShowSpan){
                return;
            }
            this.initCascadeSelect();
        },

        methods: {
            changeSelect(){
                let vm = this;
                vm.twoLevel = '';
                vm.selectData.forEach(item => {
                    if(item.value == vm.oneLevel){
                        vm.secondary = item.children
                    }
                })
            },
            /**
             * 获取控件将用到的元数据，并根据parentId进行存储
             * @param callBackFunc  回调函数
             */
            getAllData(callBackFunc){
                let vm = this;
                // 根据元数据类型获取元数据
                vm.DATA_GLOBAL.getDatas(vm.typeId,vm.parentId).then(datas => {
                    // 遍历返回的元数据数组
                    for(let dataTemp of datas){
                        // 若该元数据存在父级ID与ID
                        if(dataTemp[vm.parentField] && dataTemp[vm.valueField]) {
                            // 若未有该父级ID的元数据，则初始化
                            if (!vm.dataMap[dataTemp[vm.parentField]]){
                                vm.dataMap[dataTemp[vm.parentField]] = [];
                            }
                            // 将元数据添加到以父级ID为键与以ID为键的MAP中
                            vm.dataMap[dataTemp[vm.parentField]].push(dataTemp);
                            vm.dataIdMap[dataTemp[vm.valueField]] = dataTemp;
                        }
                    }
                    // 存在回调函数时，进行调用
                    if(callBackFunc && typeof callBackFunc == "function"){
                        callBackFunc();
                    }
                });
            },
            /**
             * 获取下拉框数据源并校正选择值
             * @param parentId  父级ID
             * @param field     字段
             */
            getSelectData(parentId, casField){
                let vm = this;
                let fieldArr = casField.split(",") || [];
                let field = fieldArr[0];
                // 若MAP中未找到该字段对应的配置，则退出
                if(!vm.optionMap[field]){
                    return;
                }
                // 若parentId为空，则清空数据源与选择值
                if(parentId && parentId.length){
                    let datasTemp = [];
                    let datasRecord = []; // 记录添加的数据源
                    //如果parentId 是字符串类型
                    if(typeof parentId === 'string'){
                        let dataTempMap = {};
                        vm.DATA_GLOBAL.getDatas(vm.typeId,parentId).then(datas =>  {
                            // 遍历返回的元数据数组
                            for(let dataTemp of datas){
                                // 若该元数据存在父级ID与ID
                                if(dataTemp[vm.parentField] && dataTemp[vm.valueField]) {
                                    // 若未有该父级ID的元数据，则初始化
                                    if (!dataTempMap[dataTemp[vm.parentField]]){
                                        dataTempMap[dataTemp[vm.parentField]] = [];
                                    }
                                    // 将元数据添加到以父级ID为键与以ID为键的MAP中
                                    dataTempMap[dataTemp[vm.parentField]].push(dataTemp);
                                    dataTempMap[dataTemp[vm.valueField]] = dataTemp;
                                }
                            }
                            datasRecord = dataTempMap[parentId];

                            //数据重置与赋值 optionMap
                            if(field){
                                vm.setFormData(datasRecord,field);
                                // 若有下级下拉框，则继续重置
                                if(vm.optionMap[field].casField){
                                    vm.parentTempId  =  vm.formData[field];
                                    vm.getSelectData(vm.formData[field], vm.optionMap[field].casField);
                                }
                            }
                        });
                    }else {
                        // 分组对象
                        let groupTemp;
                        // 遍历parentId数组，添加对应parentId的数据源
                        for (let parentIdTemp of parentId) {
                            // 保存分组对象信息
                            groupTemp  = {"id" : parentIdTemp
                                , "name" : vm.dataIdMap[parentIdTemp] ? vm.dataIdMap[parentIdTemp][vm.labelField] : ""
                                , "datas" : []};
                            for(let dataTemp of vm.dataMap[parentIdTemp]){
                                // 讲元数据保存到元数据组中
                                groupTemp.datas.push(dataTemp);
                                datasRecord.push(dataTemp);
                            }
                            datasTemp.push(groupTemp);
                        }

                        // 若只有一组元数据，则取消分组
                        if(datasTemp.length == 1){
                            datasTemp = datasTemp[0].datas;
                            vm.optionMap[field].needGroup = false;
                        }else{
                            vm.optionMap[field].needGroup = true;
                        }

                        if(field){
                            //数据重置与赋值 formData
                            vm.setFormData(datasTemp,field);

                            // 若有下级下拉框，则继续重置
                            if(vm.optionMap[field].casField){
                                vm.parentTempId  =  vm.formData[field];
                                vm.getSelectData(vm.formData[field], vm.optionMap[field].casField);
                            }
                        }
                    }
                }else {
                    fieldArr.forEach(field => {
                        vm.optionMap[field].datas = [];
                        vm.optionMap[field].needGroup = false;
                        vm.formData[field] = vm.optionMap[field].multiple ? [] : "";
                    });
                }
            },


            /**
             * 重置下一级下拉列表与赋值  formData
             * */
            setFormData(datasRecord,field){
                let vm = this;
                vm.optionMap[field].datas = datasRecord;
                let arrDatasObj = {};
                (datasRecord||[]).forEach(item => {
                    arrDatasObj[item.id]=item.dataName;
                });
                vm.rememberSysDataObj && vm.rememberSysDataObj(field,arrDatasObj);
                // 获取当前值
                let curValue = vm.formData[field];
                // 获取当前选择值的数组形式
                let curValueArr = typeof curValue == "object" ? curValue : [curValue];
                valueEach:
                    for (let i = curValueArr.length - 1; i >= 0; i--) {
                        if(datasRecord && datasRecord.constructor === Array && datasRecord.length > 0){
                            for (let dataObj of datasRecord) {
                                // 若当前选择的值存在于新数据源中，则跳入外层下一次循环
                                if (dataObj && dataObj[vm.valueField] == curValueArr[i]) {
                                    continue valueEach;
                                }
                            }
                        }
                        // 若当前选择的值不存在于新数据源，则删除该选择值
                        curValueArr.splice(i, 1);
                    }
                // 根据是否多选来赋值
                vm.formData[field] = typeof curValue == "object" ? curValueArr : curValueArr.join("");

            },



            /**
             * 初始化级联下拉框
             */
            initCascadeSelect() {
                let vm = this;
                // 初始化宽度
                if(this.width){
                    this.style = {'width':this.width};
                }
                this.$nextTick(() => {
                    if(!this.width){
                        let AllWidth = this.$refs.selectDiv.offsetWidth;
                        let fieldArr = vm.field.split(",");
                        let selectWidth = AllWidth - (fieldArr.length - 1) * 11;
                        let eachWidth = selectWidth/fieldArr.length;
                        this.style = {'width':eachWidth + "px"};
                    }
                })
                if(vm.showText){
                    let fieldArr = vm.field.split(",");
                    let dataIds = "";
                    fieldArr.forEach(item => {
                      if(vm.formData.hasOwnProperty(item)&&vm.formData[item]) {
                        dataIds += "," + vm.formData[item];
                      }
                    });
                    dataIds = dataIds.substring(1);
                    vm.DATA_GLOBAL.getDataByIds(dataIds).then(datas => {
                        if(vm.field.indexOf(",") > -1){
                            vm.valueLabel = datas.join(" - ");
                        }else{
                            vm.valueLabel = datas;
                        }
                    });
                    // return vm.valueLabel;
                }

                // 获取元数据
                vm.getAllData(() => {
                    // 字段数组
                    let fieldArr = vm.field.split(",");
                    // 多选设置数组
                    let multipleArr = (vm.multiple || "").split(",");
                    // 只读设置数组
                    let disabledArr = (vm.disabled || "").split(",");
                    //隐藏设置数组
                    let hiddenArr = (vm.isHidden || "").split(",");
                    // 默认值数组
                    let defaultValueArr = (vm.defaultValue || "").split(",");

                    // 遍历字段数组，将配置保存在MAP中
                    for(let i = 0; i < fieldArr.length; i++){
                        let optionObj = {};
                        optionObj.field = fieldArr[i] + "";
                        optionObj.multiple = multipleArr[i] == 'true';
                        optionObj.disabled = disabledArr[i] == 'true';
                        optionObj.isHidden = hiddenArr[i] == 'true';

                        // Element下拉框多选与单选值类型不同，所以进行处理
                        if(optionObj.multiple){
                            optionObj.defaultValue = defaultValueArr[i] ? [defaultValueArr[i]] : [];
                        }else{
                            optionObj.defaultValue = defaultValueArr[i] ? defaultValueArr[i] : "";
                        }
                        vm.formData[fieldArr[i]] = vm.formData[fieldArr[i]] && vm.formData[fieldArr[i]].length
                            ? vm.formData[fieldArr[i]]
                            : optionObj.defaultValue;
                        //formData中移除 vm.field
                        // if( vm.field in vm.formData){
                        //     delete vm.formData[vm.field];
                        // }
                        optionObj.datas = [];
                        if(i != fieldArr.length -1) {
                            // 存关联的下拉框字段
                            optionObj.casField = "";
                           for(let j = i+1;j < fieldArr.length;j++){
                               optionObj.casField += "," + fieldArr[j];
                           }
                           if(optionObj.casField){
                               optionObj.casField = optionObj.casField.substring(1);
                           }
                            optionObj.separator = vm.separator;
                            // 值改变事件
                            optionObj.onChange = (value) => {
                                let dataName = ''; //当前label值
                                vm.getSelectData(vm.formData[fieldArr[i]], optionObj.casField);
                                // 重置数据源与选中值
                                vm.optionMap = Object.assign({}, vm.optionMap);
                                let currenData = optionObj.datas || [];
                                Object.keys(currenData).forEach(key => {
                                    if(currenData[key].id === value){
                                        dataName = currenData[key].dataName;
                                        return;
                                    }
                                });
                                if(vm.clickCallback !== null){
                                    vm.clickCallback(dataName,optionObj.field,value); //回传label 和当前选中字段 和value
                                }
                            };
                        }else{
                            optionObj.onChange = (value) => {
                                let dataName = '';
                                vm.optionMap = Object.assign({}, vm.optionMap);
                                let currenData = optionObj.datas || [];
                                Object.keys(currenData).forEach(key => {
                                    if(currenData[key].id === value){
                                        dataName = currenData[key].dataName;
                                        return;
                                    }
                                });
                                if(vm.clickCallback !== null){
                                    vm.clickCallback(dataName,optionObj.field,value);   //回传label 和当前选中字段
                                }
                            };
                        }
                        vm.optionMap[optionObj.field] = optionObj;

                        // 初始化数据源与选中值
                        if(i == 0){
                            vm.getSelectData(vm.hasParentJudge == "true" ? vm.parentId : "-1" , optionObj.field);
                        }else{
                            vm.getSelectData(vm.formData[fieldArr[i-1]], optionObj.field);
                        }
                    }

                    vm.optionMap = Object.assign({}, vm.optionMap);

                });
            }
        }
    }
</script>

<style scoped>
    .jlcombobox-container .el-form-item{
        display: inline-block;
    }
    ::v-deep .el-form-item__error{
        margin-top: 0!important;
        position: absolute!important;
    }
</style>
