<template>
    <ap-container>
        <ap-aside margin="1011" width="28%">
            <ap-container>
                <ap-aside-tree  ref="tableTreeRef" :options.sync="treeOptions" style="width:250px">
                    <div slot="tree" slot-scope="scope" style="width: 100%">
                        <div class="abap-tree-node-left ap-ellipse">
                            <span v-if="scope.data.fdType == 1" style="color: #1890ff;">{{ scope.data.fdName }}</span>
                            <span v-else>{{ scope.data.fdName }}</span>
                        </div>
                        <div style="font-size: 12px;">{{ scope.data.fdDesc }}</div>
                    </div>
                </ap-aside-tree>
                <ap-main margin="0001" class="flex-col flex-1" style="border-left: 1px solid #e9ecf1;padding: 0 0 0 10px;">
                    <sap-table-field ref="tableFieldTreeRef"  :options.sync="fieldTreeOptions"></sap-table-field>
                </ap-main>
            </ap-container>
        </ap-aside>
        <ap-container>
            <ap-aside margin="1111"  class="flex-1 flex-col" >
                <div style="height:40%" class="flex-justify-start">
                    <div class="flex-col ctn-border-right" style="width:25%;height: 100%;overflow: auto;padding-right: 5px">
                        <span class="sap-ctn-title">
                            <span><i class="el-icon-table"/>&nbsp;&nbsp;{{selectedTable }}：{{ tableSapText }}</span>
                            <span class="sap-condition-add" @click="doAddTable(selectedTable)"> <i class="el-icon-s-promotion" /> </span>
                        </span>
                        <div class="sap-ctn-line"><span>{{ tableFunction }}</span></div>
                        <span class="sap-ctn-title" style="margin-top: 5px;">
                            <span><i class="el-icon-success" />&nbsp;&nbsp;{{ selectedField }}：{{ fieldSapText }}</span>
                        </span>
                        <div class="sap-ctn-line">
                            <span>{{ fieldSapDesc }}</span><br><span v-html="fieldFunction"></span>
                        </div>
                        <div class="flex-1 ctn-border-top" style="margin-top: 5px;padding-top: 5px;color:#909399">
                            <span class="sap-ctn-title">
                                <span><i class="el-icon-s-flag" />&nbsp;&nbsp;当前操作表</span>
                            </span>
                            <el-radio-group v-model="currentOperateTable" class="flex-col" @change="changeCurrentOperateTable">
                                <template v-for="item in config.from">
                                    <el-radio :label="item.group" >
                                        <span class="sap-config-param">{{item.group}}： {{item.table}}</span>
                                    </el-radio>
                                </template>
                            </el-radio-group>
                        </div>
                    </div>
                    <div class="flex-1 flex-col" style="height: 100%; margin: 0 5px">
                        <div class="sap-ctn-title"><i class="el-icon-search" />&nbsp;&nbsp;查询条件：</div>
                        <div class="flex-1" style="overflow: auto;">
                            <div class="sap-ctn-line" v-for="item in tableConditionList">
                                <span v-if="item.fdType == 1" class="ap-tag-success sap-condition-icon">必填</span>
                                <span v-if="item.fdType == 2" class="ap-tag-info sap-condition-icon">常用</span>
                                <span v-if="item.fdType == 3" class="ap-tag-info sap-condition-icon">一般</span>
                                &nbsp;&nbsp;
                                <span style="color: #497fd5;font-weight: bold;">{{ item.fdField }}：{{ item.fdRemark }}</span>
                                &nbsp;&nbsp;
                                <span style="text-decoration: underline;">{{ item.fdCondition }}</span>
                                <span class="sap-condition-add" @click="doAddCondition(item.fdField , item.fdCondition)"> <i class="el-icon-s-promotion" /> </span>
                            </div>
                        </div>

                    </div>
                    <div class="ctn-border-left flex-col" style="width:40%;height: 100%;padding-left: 5px;" >
                        <div class="sap-ctn-title"><i class="el-icon-lianjie6" />&nbsp;&nbsp;表关联：</div>
                        <div class="flex-1" style="overflow: auto;">
                            <template v-for="item in tableLinkTree">
                                <div class="sap-ctn-line">
                                    <span style="color: #497fd5;font-weight: bold;">{{ item.table }}：{{ item.type }} <span style="color: #ffba00">{{ item.relation }}</span> </span>
                                    <span class="sap-condition-add" @click="doAddJoinTable(item.table)"> <i class="el-icon-s-promotion" /> </span>
                                </div>
                                <div class="sap-ctn-line">
                                    <span v-html="handleTableCondition(item.table, item.ons)"></span>
                                </div>
                            </template>
                        </div>
                    </div>
                </div>
                <div>
                    <div class="ctn-border-top  flex-justify-start">
                        <div v-show="showConfigFlag"  style="width: 35%;">
                            <span class="sap-ctn-title" @click="showConfigOnConsole"><i class="el-icon-bug"/> <span>参数信息</span></span>
                        </div>
                        <div class="flex-1 flex-justify-between">
                            <div>
                                <span class="sap-ctn-title"><i class="el-icon-mokuai4" @click="showConfig"/>
                                    {{sqlName}}
                                    <span style="color: #909399;font-weight: normal;font-size:12px;">{{sqlRemark}}</span>
                                </span>
                            </div>
                            <div>
                                <el-button-group>
                                    <el-button type="success" size="mini" class="sap-sql-btn" icon="el-icon-magic-stick" @click="sqlPreview">预览</el-button>
                                </el-button-group>
                                &nbsp;
                                <el-button-group>
                                    <el-button type="primary" size="mini" class="sap-sql-btn" icon="el-icon-plus" @click="sqlNew">新建</el-button>
                                    <el-button type="danger" size="mini" class="sap-sql-btn" icon="el-icon-mail-reply" @click="sqlLoad">载入</el-button>
                                    <el-button type="primary" size="mini" class="sap-sql-btn" icon="el-icon-copy" @click="sqlCopy($event)">复制</el-button>
                                    <el-button type="success" size="mini" class="sap-sql-btn" icon="el-icon-edit-outline" @click="sqlEdit">编辑</el-button>
                                </el-button-group>
                                &nbsp;
                                <el-button-group>
                                    <el-button type="primary" size="mini" class="sap-sql-btn" icon="el-icon-floppy-o" @click="sqlSave">保存</el-button>
                                </el-button-group>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="flex-1 flex-justify-start" style="overflow: auto">
                    <div v-show="showConfigFlag" style="width: 35%;height: 100%;overflow: auto;">
                        <div class="sap-ctn-title"><i class="el-icon-search" /> SELECT</div>
                        <div class="sap-ctn-line" v-for="item in config.select">
                            <span>{{item.num}}-{{item.group}}</span>
                            <span class="sap-config-param"> {{item.field}}</span>
                        </div>
                        <div class="sap-ctn-title"><i class="el-icon-table" /> FROM </div>
                        <div class="sap-ctn-line" v-for="item in config.from">
                            <span>{{item.num}}-{{item.group}}-{{item.joinGroup}} </span>
                            <span class="sap-config-param"> {{item.join }} {{item.table}}
                                <span v-if="item.on !=null && item.on !=''"> ON </span>
                            <template v-for="onItem in item.on">
                                {{onItem }}
                            </template>
                            </span>
                        </div>
                        <div class="sap-ctn-title"><i class="el-icon-tiaojian1" /> WHERE</div>
                        <div class="sap-ctn-line" v-for="item in config.where">
                            <span>{{item.num}}-{{item.group}} </span>
                            <span class="sap-config-param">{{item.condition}}</span>
                        </div>
                    </div>

                    <div class="flex-1 flex-col" style="height: 100%;">
                        <div class="flex-1" style="overflow: auto">
                            <codemirror class="sap-sql-code" v-model="sql" :options="sqlOptions" style="height: 100%;"></codemirror>
                        </div>
                    </div>
                </div>
            </ap-aside>
            <ap-main margin="1110" style="width: 250px;flex: initial;">
                <el-tabs v-model="sqlActiveName" :stretch="true" @tab-click="sqlTabClick">
                    <el-tab-pane label="自定义" name="custom">
                        <ap-aside-tree ref="sqlTreeCustomRef" :options.sync="sqlTreeCustomOptions">
                            <span slot="tree" slot-scope="scope" style="width: 100%">
                                 <div class="abap-tree-node-left ap-ellipse">
                                    {{ scope.data.fdName }}
                                </div>
                            </span>
                        </ap-aside-tree>
                    </el-tab-pane>
                    <el-tab-pane label="常用" name="common">
                        <ap-aside-tree ref="sqlTreeCommonRef" :options.sync="sqlTreeCommonOptions">
                            <span slot="tree" slot-scope="scope" style="width: 100%">
                                 <div class="abap-tree-node-left ap-ellipse">
                                    {{ scope.data.fdName }}
                                </div>
                            </span>
                        </ap-aside-tree>
                    </el-tab-pane>
<!--                    <el-tab-pane label="操作记录" name="history">操作记录内容</el-tab-pane>-->
                </el-tabs>
            </ap-main>
        </ap-container>

        <el-dialog title="编辑SQL类型" :visible.sync="showSqlTypeTable" width="600px">
            <ap-table ref="tAbapSqlRef" :options.sync="tAbapSqlOpt" style="height: 400px"></ap-table>
        </el-dialog>
        <el-dialog :title="dialogInfo.title" :visible.sync="dialogInfo.isVisible"
                   width="600px">
            <el-form ref="tAbapSqlFormRef" :model="sqlForm" v-loading="dialogInfo.formIsLoading"
                     label-width="80px" :inline="true">

                <el-form-item label='父类型' prop='fdParentId'>
                    <el-select v-model="sqlForm.fdParentId" style="width: 165px;">
                        <template v-for="item in sqlType">
                                <el-option :value="item.fdId" :label="item.fdName"></el-option>
                        </template>
                    </el-select>
                </el-form-item>
                <el-form-item><el-button size="mini" type="primary" @click="editSqlType">编辑类型</el-button></el-form-item>
                <el-form-item label='名称' prop='fdName'>
                    <el-input v-model='sqlForm.fdName'></el-input>
                </el-form-item>
                <el-form-item label='排序' prop='fdSort'>
                    <el-input v-model='sqlForm.fdSort'></el-input>
                </el-form-item>
                <el-form-item label='配置' prop='fdConfig'>
                    <el-input v-model='sqlForm.fdConfig' :disabled="true"></el-input>
                </el-form-item>
                <el-form-item label='SQL' prop='fdSql'>
                    <el-input v-model='sqlForm.fdSql' :disabled="true"></el-input>
                </el-form-item>
                <el-form-item label='备注' prop='fdRemark'>
                    <el-input type="textarea" v-model='sqlForm.fdRemark'></el-input>
                </el-form-item>
            </el-form>

            <span slot="footer">
                <el-button type="danger"  @click="deleteTAbapSqlForm">删 除</el-button>
                <el-button type="primary" @click="saveTAbapSqlForm"
                           :loading="dialogInfo.saveBtnIsLoading">保 存</el-button>
            </span>
        </el-dialog>

        <el-drawer title="" :visible.sync="showSqlDataTable" :with-header="false" size="800px" class="sap-abap-drawer">
            <div class="flex-col" style="padding: 10px;width: 100%;height: 100%;" v-loading="sqlDataTableLoadingFlag">
                <div>
                    预览行数：<el-input v-model="dataLimit" placeholder="" style="width: 100px"></el-input>
                </div>
                <div class="flex-1" style="height: 100%;overflow: auto;">
                    <el-table :data="sqlData" border style="width: 100%" height="100%" fixed>
                        <el-table-column fixed type="index">
                        </el-table-column>
                        <template v-for="item in sqlDataHeader">
                            <el-table-column :prop="item" :label="item" :show-overflow-tooltip="true"></el-table-column>
                        </template>
                    </el-table>
                </div>
            </div>
        </el-drawer>
    </ap-container>
</template>

<script>
import SapTable from './../components/SapTable'
import SapTableField from './../components/SapTableField'
import {codemirror} from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import "codemirror/theme/eclipse.css"
import "codemirror/mode/sql/sql.js"
import {convertToArrayData} from "ap-util/util/DataUtil";
import clipboard from 'ap-util/util/ClipboardUtil'

export default {
    name: 'SqlPanel',
    components: {
        SapTable,
        SapTableField,
        codemirror,
    },
    data() {
        let columns = [
            {
                prop: 'fdParentId',
                label: '父类型',
                type: 'select',
                selectOptionsKey:{label:"fdName", value:"fdId"},
                selectOptionsRemote: 'parentList',
                width: 100,
            }, {
                prop: 'fdName',
                label: '名称',
                type: 'input',
            }, {
                prop: 'fdCustom',
                label: '分类',
                type: 'select',
                selectOptions: [{label: "自定义", value: 1}, {label: "常用", value: 0}],
                width: 100,
            }, {
                prop: 'fdSort',
                label: '排序',
                type: 'input',
                width: 80,
            }
        ];
        let sqlTableOpt = {
            title: "类型列表",
            columns: columns,
            editPk: "fdId", //默认fdId
            deletePk: "fdId", // 默认fdId
            dataUrl: "/apd/abap/TAbapSql/getAbapSqlTypeGridList",
            saveUrl: "/apd/abap/TAbapSql/saveTAbapSqlGridData",
            deleteUrl: "/apd/abap/TAbapSql/deleteTAbapSqlGridData",
            toolbarBtn: ["add", "edit", "del", "refresh", "save"],
            initData: true, // 默认false
            params: {},
            afterSave: ()=>{
                this.$refs.sqlTreeCustomRef.loadTreeData();
                this.$refs.sqlTreeCommonRef.loadTreeData();
                this.sqlType =  this.getSqlTypeList();
            },
            addDefaultObj: {fdType:1} ,
        };
        return {
            // ----- 左侧树 -----
            treeOptions: this.getTreeOption(),
            selectedTable: "",
            tableFunction: "",
            tableSapText: "",
            fieldTreeData: [],
            fieldTreeLoadingFlag: false,
            fieldTreeFilterText: "",
            selectedField: "",
            fieldSapText: "",
            fieldSapDesc: "",
            fieldFunction: "",
            fieldTreeOptions: this.getFieldTreeOptions(),
            // ----- 中间 -----
            tableConditionList: [],
            tableLinkList: [], // 连接表：list结构
            tableLinkTree: [], // 连接表：树形结构
            currentOperateTable: "", // 当前操作表
            sql: "",
            sqlOptions: {
                tabSize: 4, // tab的空格个数
                theme: 'eclipse',//主题样式
                lineNumbers: true,//是否显示行数
                lineWrapping: true, //是否自动换行
                mode: "sql",
                readOnly: true //只读
            },
            showConfigFlag: false,
            config: this.getInitConfig(),
            aliasMap:{}, // 表别名：group-> a、b、c...
            dialogInfo: {
                title: "保存SQL",
                isVisible: false,
                saveBtnIsLoading: false,
                formIsLoading: false,
                fdId: ""
            },
            sqlName: "未定义名称",
            sqlRemark: "",
            sqlForm: this.getInitSqlForm(),
            sqlType: this.getSqlTypeList(),
            tAbapSqlOpt: sqlTableOpt,
            showSqlTypeTable: false,
            showSqlDataTable: false,
            sqlDataTableLoadingFlag: false,
            dataLimit: 100,
            sqlDataHeader: [],
            sqlData: [],
            // ----- 右侧 -----
            sqlActiveName: "common",
            sqlTreeCommonOptions: this.getSqlTreeOptions(0),
            sqlTreeCustomOptions: this.getSqlTreeOptions(1),

        }
    },
    watch: {
        config: {
            handler: 'initSql',
            deep: true,
            immediate: true,
        }
    },
    methods: {
        // 左侧树：配置
        tableClickEvent(data){
            // 不同时修改当前操作表
            if (this.getTableByGroup(this.currentOperateTable) != data.fdName) {
                this.currentOperateTable = "";
            }
            if (data.fdType != 2) {
                this.resetSelectedInfo();
                return;
            }

            this.tableFunction = data.fdFunction;
            this.selectedTable = data.fdName;
            this.fieldTreeOptions.selectedTable = data.fdName;
            this.$refs.tableFieldTreeRef.refresh();
            this.getSapTableText();
            this.getTableCondition();
            this.getTableLink();
        },
        getTreeOption() {
            let treeOptions = {
                showCheckbox: false,
                defaultExpandAll: false,
                showTitle: false,
                indent: 0,
                onClick: (data, node, comp) => {
                    this.tableClickEvent(data);
                },
                loadOptions: {
                    url: "/apd/abap/AbapTable/getTAbapTableList",
                    treeKey: {
                        idKey: "fdId",
                        parentKey: "fdParentId",
                        childrenKey: "children",
                        label: "fdName"
                    },
                    success: (response) => {

                    },
                }
            };

            return treeOptions;
        },
        getFieldTreeOptions(){
            return {
                selectedTable: this.selectedTable,
                showCheckbox: true, // 可选中
                checkEvent: (data, p2) => {
                    this.doAddField(data, p2);
                }, // 选中事件
                clickEvent: (data) => {
                    this.selectedField = data.fieldName;
                    this.fieldSapText = data.text;
                    let keyStr = data.keyFlag == 'X' ? '[主键] ' : '';
                    let typeStr = "";
                    switch (data.fdType) {
                        case 1:
                            typeStr = "[查询常用] ";
                            break;
                        case 2:
                            typeStr = "[条件常用] ";
                            break;
                    }
                    let notNullStr = data.notNull == 'X' ? '[非空] ' : '';
                    let dataTypeStr = '[' + data.dataType + "-" + data.fieldLength + "-" + data.fieldDecimal+  ']';
                    this.fieldSapDesc = keyStr + typeStr + notNullStr + dataTypeStr;
                    let functionStr = data.fdFunction == null || data.fdFunction == '' ? '-' : data.fdFunction;
                    this.fieldFunction = "<i class=\"el-icon-info\" style='color:#497fd5'></i>&nbsp;&nbsp;" + functionStr;
                },
            }
        },
        getSapTableText() {
            this.$request({
                url: '/apd/abap/AbapTable/getSapTableText',
                method: 'post',
                data: {
                    tableName: this.selectedTable
                }
            }).then(response => {
                this.tableSapText = response.data
            })
        },
        resetSelectedInfo() {
            this.tableSapText = "";
            this.tableFunction = "";
            this.selectedTable = "";
            this.fieldTreeData = [];
            this.selectedField = "";
            this.fieldSapText = "";
            this.fieldSapDesc = "";
        },
        getInitConfig(){
            return JSON.parse(JSON.stringify({
                select:[],
                from:[],
                where:[],
                param:  {
                    num:0,
                    groupNum: 0,
                    group:"",
                }
            }));
        },
        getTableCondition(){
            this.$request({
                url: "/apd/abap/TAbapTableCondition/getTAbapTableConditionList",
                method: 'post',
                data: {
                    tableName: this.selectedTable
                }
            }).then(response => {
                this.tableConditionList = response.data;
            })
        },
        handleTableCondition(table, ons){
            if (ons == null || ons.length < 1) {
                return "";
            }
            let arr = [];
            for (let i = 0; i < ons.length; i++) {
                let str = `<span style="text-decoration: underline;">${ons[i]}</span>`;
                str = str.replaceAll(`#${table}#.`, ``)
                    .replaceAll(`#${this.selectedTable}#`, `t`)
                arr.push(str);
            }
            return arr.join("&nbsp;&nbsp;&nbsp;") ;
        },
        initTableLinkTree() {
            this.tableLinkTree = []
            let linkList = this.tableLinkList;
            let tempObj = {};
            for (let i = 0; i < linkList.length; i++) {
                tempObj[linkList[i].fdTable] = linkList[i].fdTable;
            }

            for (let key in tempObj) {
                let ons = [];
                let relation = "";
                let type = "";
                for (let i = 0; i < linkList.length; i++) {
                    let table = linkList[i].fdTable;
                    if (table == key) {
                        ons.push(linkList[i].fdCondition);
                        relation = linkList[i].fdRelation;
                        type = linkList[i].fdType;
                    }
                }

                switch (type) {
                    case 1:
                        type = "左连接"
                        break
                    case 2:
                        type = "右连接"
                        break
                    case 3:
                        type = "内连接"
                        break
                    case 4:
                        type = "全连接"
                        break
                }
                let item = {
                    table: key,
                    relation: relation,
                    type: type,
                    ons: ons
                }
                this.tableLinkTree.push(item);
            }
        },
        getTableLink(){
            this.$request({
                url: "/apd/abap/TAbapTableLink/getTAbapTableLinkList",
                method: 'post',
                data: {
                    tableName: this.selectedTable
                }
            }).then(response => {
                this.tableLinkList = response.data;

                this.initTableLinkTree();
            })
        },
        // ------------- 操作 start -------------
        showConfigOnConsole(){
            console.log(this.config);
            console.log(JSON.stringify(this.config));
        },
        getNum(){
            return ++ this.config.param.num;
        },
        setGroup(){
            this.config.param.groupNum ++;
            this.config.param.group = "t" + this.config.param.groupNum;
            this.currentOperateTable = this.config.param.group;
        },
        getGroup(){
            return this.config.param.group;
        },
        deleteItem(param, list, key){
            // 删除数组中的某个值
            for (let i = 0; i < list.length; i++) {
                if (list[i][key] == param) {
                    list.splice(i, 1);
                    break;
                }
            }
        },
        // 根据group获取表名
        getTableByGroup(group){
            let tables = this.config.from;
            for (let i = 0; i < tables.length; i++) {
                if (group == tables[i].group) {
                    return tables[i].table;
                }
            }
            return "";
        },
        // 根据group选中字段树的行
        checkFieldTreeByGroup(group){
            let selects = this.config.select;
            let keyArr = [];
            for (let i = 0; i < selects.length; i++) {
                if (selects[i].group == group) {
                    keyArr.push(selects[i].field);
                }
            }
            this.$refs.tableFieldTreeRef.setDefaultCheckKeys(keyArr)
        },
        changeCurrentOperateTable(group){
            // 根据分组获取对应的表id，触发树的点击事件
            let tableTree = convertToArrayData(this.$refs.tableTreeRef.getData());
            let tableData = {};
            for (let i = 0; i < tableTree.length; i++) {
                if (tableTree[i].fdName == this.getTableByGroup(group)) {
                    tableData = tableTree[i];
                    break;
                }
            }
            this.$refs.tableTreeRef.setCurrentKey(tableData.fdId);
            // 默认选中字段行
            this.checkFieldTreeByGroup(group);
            this.tableClickEvent(tableData);

            // 修改当前操作的分组
            this.config.param.group = group;
        },
        checkBeforeAddSql(){
            if (this.config.param.groupNum == 0) {
                this.$message.error("请先添加表");
                return false;
            }
            if (this.getTableByGroup(this.config.param.group) != this.selectedTable) {
                this.$message.error("当前操作表不匹配，请先添加表");
                return false;
            }
            return true;
        },
        doAddTable(table) {
            // 分组+1
            this.setGroup();

            this.config.from.push({
                num: this.getNum(),
                group: this.getGroup(),
                table: table
            });
        },
        getJoinStr(type){
            // 1左连接 2右连接 3内连接 4全连接
            switch (type) {
                case 1:
                    return "LEFT JOIN";
                    break;
                case 2:
                    return "RIGHT JOIN";
                    break;
                case 3:
                    return "INNER JOIN";
                    break;
                case 4:
                    return "FULL JOIN";
                    break;
            }
            return "";
        },
        doAddJoinTable(table){
            if (!this.checkBeforeAddSql()) {
                return;
            }
            // join表对应的group
            let joinGroup = this.getGroup();
            // 分组+1
            this.setGroup();

            let tableLinkList = this.tableLinkList;
            let joinStr = "";
            let onList = [];
            for (let i = 0; i < tableLinkList.length; i++) {
                if (tableLinkList[i].fdTable == table) {
                    onList.push(tableLinkList[i].fdCondition);
                    joinStr = this.getJoinStr(tableLinkList[i].fdType);
                }
            }

            this.config.from.push({
                num: this.getNum(),
                group: this.getGroup(),
                join: joinStr,
                joinGroup: joinGroup,
                table: table,
                on: onList
            });

            // 触发表树的选中事件
            this.changeCurrentOperateTable(this.config.param.group);
        },
        // 重置字段树的选中状态
        resetFieldTreeCheckNode(){
            let selects = this.config.select;
            let currentGroup = this.config.param.group;
            let resetSelects = [];
            for (let i = 0; i < selects.length; i++) {
                if (selects[i].group != currentGroup) {
                    continue;
                }
                resetSelects.push(selects[i].field);
            }

            let checkedKeys = this.$refs.tableFieldTreeRef.getCheckedKeys();

            // 选择状态修改
            for (let m = 0; m < checkedKeys.length; m++) {
                let needCheck = false;
                for (let n = 0; n < resetSelects.length; n++) {
                    if (checkedKeys[m] == resetSelects[n]) {
                        needCheck = true;
                        break
                    }
                }
                this.$refs.tableFieldTreeRef.setChecked(checkedKeys[m], needCheck);
            }
        },
        doAddField(data, param){
            if (!this.checkBeforeAddSql()) {
                this.resetFieldTreeCheckNode();
                return;
            }
            let field = data.fieldName;
            let fieldName = data.fdDesc == null || data.fdDesc == "" ? data.text : data.fdDesc;

            // 是否添加
            let isAdd = param.checkedKeys.indexOf(field) < 0 ? false: true;

            if (isAdd) {
                // 添加
                this.config.select.push({
                    num: this.getNum(),
                    group: this.getGroup(),
                    field: field,
                    fieldName: fieldName
                });
            } else {
                this.deleteItem(field, this.config.select, "field");
            }
        },
        doAddCondition(field, condition){
            if (!this.checkBeforeAddSql()) {
                return;
            }
            this.config.where.push({
                num: this.getNum(),
                group: this.getGroup(),
                field: field,
                condition: condition
            });
        },
        // ------------- 操作 end -------------
        // 初始化表别名映射：roup -> 别名
        initTableAlias(froms){
            for (let i = 0; i < froms.length; i++) {
               this.aliasMap[froms[i].group]= String.fromCharCode(97 + i);
            }
        },
        getAliasByGroup(group){
            return this.aliasMap[group];
        },
        getOnStr(fromItem){
            let onArr = fromItem.on;
            if (onArr == null || onArr.length < 1) {
                return "";
            }
            let tableAlias = this.getAliasByGroup(fromItem.group);
            let tableName = this.getTableByGroup(fromItem.group);

            let joinTableAlias = this.getAliasByGroup(fromItem.joinGroup);
            let joinTableName = this.getTableByGroup(fromItem.joinGroup);

            let onStr = " ON " + onArr.join(" AND ");
            onStr = onStr.replaceAll(`#${tableName}#`, tableAlias)
                .replaceAll(`#${joinTableName}#`, joinTableAlias);
            return onStr;
        },
        getWhereStr(wheres){
            if (wheres == null || wheres.length < 1) {
                return "";
            }

            let whereStr = `\nWHERE\n  `;
            let whereList = [];
            for (let i = 0; i < wheres.length; i++) {
                let item = wheres[i];
                let tableAlias = this.getAliasByGroup(item.group);
                let conditionStr = wheres[i].condition.replaceAll(`#${item.field}#`, `${tableAlias}.${item.field}`);
                whereList.push(conditionStr);
            }
            whereStr = whereStr + whereList.join("\n  AND ")
            return whereStr;
        },
        initSql(){
            // 只读模式才更新sql
            if (!this.sqlOptions.readOnly) {
                return;
            }

            let selects = this.config.select;
            let froms = this.config.from;
            let wheres = this.config.where;

            this.initTableAlias(froms)

            // select/备注语句组装
            let selectStr = `SELECT \n`;
            let remarkStr = "";
            let selectList = [];
            let remarkList = [];
            for (let i = 0; i < selects.length; i++) {
                let selectItem = ` ${this.aliasMap[selects[i].group]}.${selects[i].field}`
                selectList.push(selectItem);
                remarkList.push(selects[i].fieldName);
            }
            selectStr = selectStr + selectList.join(",")

            // 备注
            if (remarkList.length > 0) {
                remarkStr = `-- ${remarkList.join("、")} \n`;
            }

            // from语句组装
            let fromStr = `\nFROM\n`;
            let fromList = [];
            for (let i = 0; i < froms.length; i++) {
                let joinStr = froms[i].join == null? "" : froms[i].join;
                let fromItem = ` ${joinStr} saphanadb.${froms[i].table} ${this.aliasMap[froms[i].group]} ${this.getOnStr(froms[i])}`
                fromList.push(fromItem);
            }
            fromStr = fromStr + fromList.join(" \n ")

            // from语句组装
            let whereStr = `\nWHERE\n`;
            let whereList = [];
            for (let i = 0; i < wheres.length; i++) {
                let whereItem = ` ${this.aliasMap[wheres[i].group]}.${wheres[i].condition}`
                whereList.push(whereItem);
            }

            // where语句组装
            whereStr = this.getWhereStr(wheres)

            this.sql = remarkStr + selectStr + fromStr + whereStr;
        },
        sqlPreview(){
            this.showSqlDataTable = true;
            this.sqlDataTableLoadingFlag = true;
            this.sqlData=[];
            this.sqlDataHeader=[];
            this.$request({
                url: '/apd/abap/TAbapSql/getDataBySql',
                method: 'post',
                data: {
                    sqlStr: this.sql,
                    dataLimit: this.dataLimit
                }
            }).then(response => {
                this.sqlData = response.data.data;
                this.sqlDataHeader = response.data.header;
            }).finally(() => {
                this.sqlDataTableLoadingFlag = false;
            })
        },
        showConfig(){
            this.showConfigFlag = !this.showConfigFlag;
        },
        // 清空所有信息
        clearAll(){
            this.config = this.getInitConfig();
            this.sqlForm = this.getInitSqlForm();
            this.sqlName = "";
            this.sqlRemark = "";
            this.sql = "";
        },
        sqlNew(){
            this.$confirm('当前操作会丢失未保存内容，确认要新建?', '提示', {
                confirmButtonText: '新建',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.clearAll();
            })
        },
        sqlLoad(){
            if (this.sqlOptions.readOnly) {
                this.initSql();
                return;
            }
            this.$confirm('当前操作会删除手动修改内容，确认要重置?', '提示', {
                confirmButtonText: '重置',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                // sql只读
                this.sqlOptions.readOnly = true;
                this.initSql();
            })
        },
        sqlCopy(event){
            clipboard(this.sql, event)
            this.$message.success("复制成功");
        },
        sqlEdit(){
            this.$confirm('SQL编辑后，自动生成会失效确认编辑？', '提示', {
                confirmButtonText: '编辑',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.sqlOptions.readOnly = false;
            })
        },
        sqlSave(){
            this.dialogInfo.isVisible = true;
            this.sqlForm.fdSql = this.sql;
            this.sqlForm.fdConfig = JSON.stringify(this.config);
            this.sqlForm.fdReadonly = this.sqlOptions.readOnly;
        },
        // 重置表单
        getInitSqlForm() {
            return JSON.parse(JSON.stringify({
                fdId: '',
                fdParentId: '',
                fdName: '',
                fdType: '',
                fdConfig: '',
                fdSql: '',
                fdCustom: '',
                fdRemark: '',
            }));
        },
        // dialog表单保存
        getSqlTypeList() {
            this.$request({
                url: '/apd/abap/TAbapSql/getSqlTypeList',
                method: 'post',
                data: {}
            }).then(response => {
                this.sqlType = response.data;
            })
        },
        saveTAbapSqlForm() {
            // 表单rules认证
            this.$refs.tAbapSqlFormRef.validate((valid) => {
                if (!valid) {
                    this.$message.error('数据校验错误！');
                    return false;
                }
                this.dialogInfo.saveBtnIsLoading = true;

                if (this.sqlForm.fdRemark == null) {
                    this.sqlForm.fdRemark = "";
                }
                if (this.sqlForm.fdSort == null) {
                    this.sqlForm.fdSort = "";
                }
                this.sqlForm.fdReadonly = this.sqlForm.fdReadonly ? 1 :0;

                // 添加数据
                this.$request({
                    url: '/apd/abap/TAbapSql/saveTAbapSql',
                    method: 'post',
                    data: this.sqlForm
                }).then(response => {
                    this.$message.success(`保存成功！`)
                    this.$refs.sqlTreeCustomRef.loadTreeData();
                    this.$refs.sqlTreeCommonRef.loadTreeData();
                    this.dialogInfo.isVisible = false;
                    this.selectDbSql(response.data);
                }).finally(() => {
                    this.dialogInfo.saveBtnIsLoading = false;
                })
            });
        },
        // 删除项
        deleteTAbapSqlForm(){
            let fdId = this.sqlForm.fdId;
            if (fdId == null || fdId == "") {
                this.$message.error("删除失败，该数据未保存！");
                return;
            }
            this.$request({
                url: '/apd/abap/TAbapSql/deleteTAbapSqlByFdId',
                method: 'post',
                data: {
                    fdId : fdId
                }
            }).then(response => {
                this.$message.success(`删除成功！`)
                this.$refs.sqlTreeCustomRef.loadTreeData();
                this.$refs.sqlTreeCommonRef.loadTreeData();
                this.dialogInfo.isVisible = false;
                this.clearAll();
            })
        },
        sqlTabClick(tab, event){

        },
        selectDbSql(data){
            if (data.fdType == 1) {
                return
            }

            this.currentOperateTable = "";
            this.sqlOptions.readOnly = data.fdReadonly;
            this.config = JSON.parse(data.fdConfig);
            this.sql = data.fdSql;
            this.sqlName = data.fdName;
            this.sqlRemark = data.fdRemark;
            this.sqlForm = data;
        },
        getSqlTreeOptions(isCustom){
            let treeOptions = {
                showCheckbox: false,
                defaultExpandAll: false,
                showTitle: false,
                onClick: (data, node, comp) => {
                    this.selectDbSql(data);
                },
                loadOptions: {
                    url: "/apd/abap/TAbapSql/getTAbapSqlList",
                    data: () => {
                        return {
                            fdCustom: isCustom
                        }
                    },
                    treeKey: {
                        idKey: "fdId",
                        parentKey: "fdParentId",
                        childrenKey: "children",
                        label: "fdName"
                    },
                    success: (response) => {
                    },
                }
            };
            return treeOptions;
        },
        editSqlType(){
            this.showSqlTypeTable = true;
        }

    }
}
</script>

<style scoped>
.abap-tree-node-left {
    font-size: 13px;
    width: 50%;
    float: left;
}

.ctn-border-left {
    border-left: 1px solid #e9ecf1
}

.ctn-border-right {
    border-right: 1px solid #e9ecf1
}

.ctn-border-bottom {
    border-bottom: 1px solid #e9ecf1
}

.ctn-border-top {
    border-top: 1px solid #e9ecf1
}

.sap-condition-icon {
    padding: 0 5px;
    height: 19px;
    border: 0;
}

.sap-condition-add {
    float: right;
    cursor: pointer;
    color: #909399;
}
.sap-condition-add:hover {
    color: #11b95c;
}

.sap-sql-btn {
    padding: 5px;
}

.sap-config-param {
    color: #ffba00
}
</style>
<style>
.sap-ctn-line{
    line-height: 20px;
    color:#909399;
    font-size: 12px;
}

.sap-ctn-title {
    line-height: 20px;
    color:#497fd5;
    font-size: 13px;
    font-weight: bold;
}

.sap-sql-code .CodeMirror {
    height: 100%;
}
.sap-sql-code .CodeMirror .CodeMirror-code div{
    line-height: 17px;
}
</style>