/*
 * @Author: zhangzc
 * @Email: zhangzc2@guahao.com
 * @Date: 2019-09-06 11:25:15
 * @Last Modified by: panzw2
 * @Last Modified time: 2022-07-15 15:37:09
 * @Description: 对比元组件
 * @Route: Route
 */
<template>
    <div class="contrast-material-wrapper"> 
        <el-table :data="materialConfig.tableData"
                  v-bind="getMergedObject(materialConfig.extend, {border: true})"
                  :cell-class-name="tableCellClassName">
            <template v-for="(item, i) in tableTitle">
                <el-table-column :prop="item.name"
                                 :label="item.label"
                                 v-bind="getMergedObject(item.extend,
                                                         {width: (i === 0 || item.name === 'operation' ) && (item.width || '120px')}
                                 )">
                    <template slot-scope="scope">
                        <template v-if="item.name === 'operation'">
                            <template v-if="hasField(scope.row, 'readonly')?scope.row.readonly:
                                (hasField(materialConfig, 'readonly')?materialConfig.readonly:readonly)">
                                -
                            </template>
                            <template v-else-if="(contrastConfig.filterSwitch && !noNeedOperation(scope.row)
                                || !contrastConfig.filterSwitch)">
                                <bk-form v-if="visibleAudit(scope.row)"
                                         :ref="`operation-${scope.row[keyValue]}`"
                                         :formConfig="formatFormConfig(item, scope.row)"
                                         @formParamsChange="
                                param => formParamsChange(param, item, scope.row)"
                                         class="contrast-handle-column" />
                            </template>
                        </template>
                        <template v-else-if="item.name !== 'label' && scope.row[configKey]">
                            <el-form :model="scope.row"
                                     class="con-mat-form-wrapper">
                                <bk-form-material :key="scope.row[keyValue]"
                                                  :ref="`${item.name}-${scope.row[keyValue]}`"
                                                  :materialConfig="scope.row[configKey]"
                                                  :formParams="formatFormParams(item, scope.row)"
                                                  :extend="scope.row[configKey]" />
                            </el-form>
                        </template>
                        <template v-else>
                            <div>
                                {{ scope.row[item.name] }}
                            </div>
                        </template>
                    </template>
                </el-table-column>
            </template>
        </el-table>
    </div>
</template>

<script>
import { getMergedObject, hasField, isEmptyObj } from 'utils/util';

export default {
    name: 'BkContrastMaterial',
    props: {
        contrastConfig: {
            type: Object,
            required: true
        },
        materialConfig: {
            type: Object,
            required: true
        },
        // 只读状态操作栏显示 -
        readonly: {
            type: Boolean,
            default: false
        },
        // 对比组件的四个阶段: 'firstAudit'(一列数据操作)、'audit'(两列数据操作)、'autoAudit'(自动比对)、'read'(一列数据无操作)、'contrast'(两列数据无操作)、
        contrastStage: {
            type: String,
            default: 'audit'
        },

        // 单元格需通过config渲染bk-form-material组件
        configKey: {
            type: String,
            default: 'config'
        },
        // 表单操作项的值
        results: {
            type: Object,
            default: () => ({})
        }
    },
    data() {
        return {
            getMergedObject,
            hasField,
            formParams: {}, // 表单值
            submitFormParams: {}, // 提交前格式化好的表单值
            keyValue: '',
            tableTitle: [
                {
                    name: 'label',
                    label: ''
                },
                {
                    name: 'old',
                    label: '修改前信息'
                },
                {
                    name: 'new',
                    label: '本次信息'
                },
                {
                    name: 'operation',
                    label: '操作',
                    formConfig: {
                        name: 'name',
                        type: 'radio',
                        options: [
                            {
                                value: '1',
                                label: ''
                            },
                            {
                                value: '0',
                                label: ''
                            }
                        ],
                        className: 'handleRadio',
                        rules: [{ required: true, message: '请审核' }],
                        grid: 1
                    }
                }
            ]
        };
    },
    computed: {
        stage() {
            return this.materialConfig.stage || this.contrastStage;
        }
    },
    watch: {
        stage(val) {
            this.handleColumn(val);
        },
        'materialConfig.data': {
            handler() {
                this.tableTitle = this.materialConfig.data;
                this.handleColumn(this.stage);
            },
            deep: true
        }
    },
    created() {
        const { data, keyValue } = this.materialConfig;
        if (Array.isArray(data) && data.length) {
            this.tableTitle = data;
        }

        this.keyValue = keyValue || 'value';

        this.handleColumn(this.stage);
    },
    mounted() {
        if (!isEmptyObj(this.results)) {
            this.setFormResults(this.results);
        }
    },
    updated() {
        if (!isEmptyObj(this.results)) {
            this.setFormResults(this.results);
        }
    },
    methods: {
        /**
         * 显示操作按钮
         */
        visibleAudit(row) {
            if (this.stage !== 'autoAudit') return true;
            const { newData, oldData } = row;
            if (
                typeof newData === 'object'
                && typeof oldData === 'object'
                && JSON.stringify(newData) === JSON.stringify(oldData)
            ) {
                return false;
            }
            if (newData === oldData) {
                return false;
            }
            return true;
        },
        /**
         * 返回formConfig支持的配置格式
         * @param {Object} config 操作列的表头配置项
         * @param {Object} data 每行的数据对象
         */
        formatFormConfig(config, data) {
            if (Array.isArray(config.formConfig)) {
                let obj = '';
                if (typeof this.results[data[this.keyValue]] === 'object') {
                    obj = this.results[data[this.keyValue]];
                } else {
                    obj = this.results;
                }
                return {
                    results: obj,
                    data: [
                        {
                            data: config.formConfig
                        }
                    ]
                };
            }
            return {
                results: this.results,
                data: [
                    {
                        data: [Object.assign({}, config.formConfig, { name: data[this.keyValue] })]
                    }
                ]
            };
        },

        /**
         * 格式化单元格表单值
         * @param {Object} config 操作列的表头配置项
         */
        formatFormParams(config) {
            return this.contrastConfig[config.name];
        },

        /**
         * 根据stage配置对表头配置做处理, 仅在表头为默认的audit状态时生效（即根据formConfig动态生成materialConfig时）
         * @param {String} stage stage值，审核阶段
         */
        handleColumn(stage) {
            if (this.tableTitle.length !== 4) return;
            switch (stage) {
            case 'firstAudit':
                this.tableTitle.splice(1, 1);
                break;
            case 'read':
                this.tableTitle.splice(1, 1);
                this.tableTitle.splice(2, 1);
                break;
            case 'contrast':
                this.tableTitle.splice(3, 1);
                break;
            default:
                break;
            }
        },

        /**
         * 表单值发生变化时事件
         * @param {Object} formParams 所在行的操作表单所有参数集合
         * @param {Object} config 操作列的表头配置项
         * @param {Object} rowData 每行的数据对象
         */
        formParamsChange(formParams, config, rowData) {
            if (!Object.keys(this.$refs).length) return;
            if (JSON.stringify(formParams) === JSON.stringify(this.formParams)) return;
            // 判断formParams是否第一次渲染
            let isInitResults = false;
            if (!isEmptyObj(formParams)) {
                Object.keys(formParams).forEach(key => {
                    if (
                        Object.keys(formParams).length === 1 && (this.formParams[key] === undefined || (formParams[key] === this.formParams[key]))
                        && !isEmptyObj(this.results)
                    ) {
                        isInitResults = true;
                    }
                });
            }

            const { formConfig } = config;
            const { type } = this.materialConfig;
            // 判断操作栏是否有多个表单元素
            if (
                (Array.isArray(formConfig)
                && (formConfig.length > 1 || (formConfig.length === 1 && formConfig[0].extraFields)))
                || (!Array.isArray(formConfig) && formConfig.extraFields)
            ) {
                // 将整个表单值的对象放入键名为this.keyValue的字段下
                this.formParams[rowData[this.keyValue]] = formParams;
                const obj = this.$refs[`operation-${rowData[this.keyValue]}`][0];
                this.submitFormParams[rowData[this.keyValue]] = obj.formatFormParams();
                // 审核类型时推送不通过的操作数据
                if (
                    type === 'audit'
                    || this.stage === 'firstAudit'
                    || this.stage === 'audit'
                    || this.stage === 'autoAudit'
                ) {
                    const radioConfig = formConfig.find(item => item.type === 'radio');
                    const checkboxConfig = formConfig.find(item => item.type === 'checkbox');
                    // 推送审核数据
                    if (checkboxConfig) {
                        if (formParams[checkboxConfig.name].length > 0) {
                            this.$emit('handleNoPass', rowData);
                        } else {
                            this.$emit('handlePass', rowData);
                        }
                    } else if (radioConfig) {
                        if (formParams[radioConfig.name] === '0') {
                            this.$emit('handleNoPass', rowData);
                        } else if (formParams[radioConfig.name] === '1') {
                            this.$emit('handlePass', rowData);
                        }
                    }
                }
            } else {
                if (Array.isArray(formConfig)) {
                    Object.assign(this.formParams, { [rowData[this.keyValue]]: formParams[formConfig[0].name] });
                } else {
                    Object.assign(this.formParams, { [rowData[this.keyValue]]: formParams[rowData[this.keyValue]] });
                }
                this.submitFormParams = JSON.parse(JSON.stringify(this.formParams));
                // 审核类型时推送不通过的操作数据
                if (
                    (type === 'audit' && formConfig.type === 'radio')
                    || this.stage === 'firstAudit'
                    || this.stage === 'audit'
                    || this.stage === 'autoAudit'
                ) {
                    if (Array.isArray(formConfig)) {
                        if (formConfig.type === 'checkbox') {
                            if (formParams[formConfig.name].length > 0) {
                                this.$emit('handleNoPass', rowData);
                            } else {
                                this.$emit('handlePass', rowData);
                            }
                        } else if (formParams[formConfig.name] === '0') {
                            this.$emit('handleNoPass', rowData);
                        } else if (formParams[formConfig.name] === '1') {
                            this.$emit('handlePass', rowData);
                        }
                    } else {
                        Object.keys(formParams).forEach(key => {
                            if (formConfig.type === 'checkbox') {
                                if (formParams[key].length > 0) {
                                    this.$emit('handleNoPass', rowData);
                                } else {
                                    this.$emit('handlePass', rowData);
                                }
                            } else if (formParams[key] === '0') {
                                this.$emit('handleNoPass', rowData);
                            } else if (formParams[key] === '1') {
                                this.$emit('handlePass', rowData);
                            }
                        });
                    }
                }
            }
            if (isInitResults) return;
            this.$emit('formParamsChange', {
                formParams: this.formParams,
                submitFormParams: this.submitFormParams,
                keyFieldName: rowData[this.keyValue]
            });
        },

        /**
         * 为table单元格添加对比时前后有差异的红框样式
         * @param {Object} Object.row 行对象
         *                 Object.column 行内每个单元格对象
         *                 Object.columnIndex  行内单元格的列号
         */
        tableCellClassName({ row, columnIndex }) {
            if (this.stage === 'firstAudit' || this.stage === 'read') return '';
            const oldKey = this.materialConfig.data[1].name;
            const newKey = this.materialConfig.data[2].name;
            const oldData = row[oldKey] && typeof row[oldKey] === 'object' ? JSON.stringify(row[oldKey]) : row[oldKey];
            const newData = row[newKey] && typeof row[newKey] === 'object' ? JSON.stringify(row[newKey]) : row[newKey];
            // 对空、null、undfined 处理
            if (!oldData && !newData && oldData !== 0) {
                return '';
            }
            if (columnIndex === 2 && oldData !== newData) {
                const classList = ['dif-border'];
                return classList.join(' ');
            }
            return '';
        },

        /**
         * 表单校验的函数
         * @param {Function} callback 校验通过后的回调函数
         */
        handleVerify(callback) {
            const { $refs } = this;
            const arr = [];
            Object.keys($refs).forEach(key => {
                if (key.indexOf('operation-') !== 0 || !$refs[key][0].handleVerify) return;
                let flag = false;
                $refs[key][0].handleVerify(() => {
                    flag = true;
                });
                arr.push(flag);
            });
            const valid = arr.every(val => val === true);
            if (typeof callback === 'function') {
                callback(valid);
                return true;
            }
            return false;
        },

        /**
         * 给表单操作列赋值的函数
         */
        setFormResults(results) {
            this.$nextTick(() => {
                Object.keys(results).forEach(key => {
                    const ref = `operation-${key}`;
                    const param = typeof results[key] === 'object' ? results[key] : results;
                    const target = this.$refs[ref];
                    if (target && Array.isArray(target)) target[0].formConfig.results = param;
                });
            });
        },

        /**
         * 新老数据同时不存在时不需要审核操作
         */
        noNeedOperation(data) {
            const { newData, oldData } = data;
            if (this.contrastStage === 'firstAudit') {
                return newData !== 0 && !newData;
            }
            return newData !== 0 && !newData && (oldData !== 0 && !oldData);
        }
    }
};
</script>
