<template>
    <ap-container>
        <ap-aside margin="1111">
            <div class="layout-aside-header">
                <div class="layout-aside-header-title">
                    字段类型
                </div>
                <div class="layout-aside-header-icon">
                    <i class="el-icon-plus" @click="addTable"/>
                    <i class="el-icon-edit-outline" @click="editTable"/>
                    <i class="el-icon-delete" @click="deleteTable"/>
                    <el-popover ref="popoverRef" placement="bottom" trigger="click">
                        <el-button-group>
                            <el-button type="primary" icon="el-icon-top" @click="sortTypeBefore">上移</el-button>
                            <el-button type="primary" icon="el-icon-bottom" @click="sortTypeAfter">下移</el-button>
                            <el-button type="primary" icon="el-icon-s-operation" @click="sortTypeByIndex">
                                一键排序
                            </el-button>
                        </el-button-group>
                        <i slot="reference" class="el-icon-sort"/>
                    </el-popover>
                </div>
            </div>
            <div>
                <el-input v-model="filterText" placeholder="关键字过滤"/>
            </div>
            <div v-loading="loadingTreeFlag" class="layout-aside-content">
                <el-tree
                    ref="typeTree"
                    class="filter-tree"
                    node-key="fdId"
                    :data="typeTreeList"
                    :props="defaultProps"
                    default-expand-all
                    show-checkbox
                    :check-on-click-node="true"
                    :highlight-current="true"
                    :expand-on-click-node="false"
                    :check-strictly="false"
                    :filter-node-method="filterNode"
                    @check="nodeClickEvent"
                />
            </div>
        </ap-aside>
        <ap-split-panel/>
        <ap-container>
            <ap-header margin="1110">
                <el-form
                    ref="searchFormRef"
                    :model="searchForm"
                    :inline="true"
                    class="layout-header-form"
                    @submit.native.prevent="searchEvent"
                >
                    <el-form-item label="搜索:" class="layout-header-form-item" prop="likeStr">
                        <el-input v-model="searchForm.likeStr" placeholder="字段名/注释"/>
                    </el-form-item>
                </el-form>
                <el-button type="primary" @click="searchEvent">查询</el-button>
            </ap-header>
            <ap-main margin="0110">
                <ap-table ref="devDbFieldGrid" :options.sync="tableOpt"/>
            </ap-main>
        </ap-container>


        <el-dialog
            :title="dialogTitle"
            :visible.sync="dialogVisible"
            width="35%"
        >
            <el-form ref="dialogForm" :model="dialogForm" :rules="dialogFormRules" label-width="80px">

                <el-form-item label="父类别">
                    <el-select v-model="dialogForm.fdParentId" filterable placeholder="请选择父节点">
                        <el-option label="无" value=""/>
                        <el-option
                            v-for="item in typeList"
                            :key="item.fdId"
                            :label="item.fdName"
                            :value="item.fdId"
                        />
                    </el-select>
                </el-form-item>

                <el-form-item label="类别名称" prop="fdName">
                    <el-input v-model="dialogForm.fdName"/>
                </el-form-item>

                <el-form-item label="排序" prop="fdSort">
                    <el-input-number v-model="dialogForm.fdSort" controls-position="right"/>
                </el-form-item>
            </el-form>


            <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveTable">确 定</el-button>
      </span>
        </el-dialog>
    </ap-container>
</template>

<script>
import {convertToArrayData, convertToTreeData} from 'ap-util/util/DataUtil'

export default {
    name: 'DevDbField',
    data() {
        const columns = [
            {
                prop: 'fdFieldTypeId',
                label: '字段类型',
                type: 'select',
                addDefaultValue: this.addDefaultValueFn,
                selectOptionsRemote: 'typeList',
                selectOptionsKey: {label: 'fdName', value: 'fdId'},
                rules: [
                    {required: true, message: '请选择类型'}
                ]
            },
            {
                prop: 'fdName',
                label: '字段名称',
                type: 'input',
                rules: [
                    {required: true, message: '字段名称必填'},
                    {min: 1, max: 30, message: '长度在 1 到 30 个字符'}
                ]
            },
            {
                prop: 'fdComment',
                label: '默认注释',
                type: 'input',
                rules: [
                    {required: true, message: '字段注释必填'},
                    {min: 1, max: 30, message: '长度在 1 到 30 个字符'}
                ]
            }, {
                prop: 'fdDataType',
                label: '数据类型',
                type: 'select',
                selectOptions: [
                    {
                        label: '常用',
                        options: [
                            {label: 'char(255)', value: 'char'},
                            {label: 'varchar(6.5万)', value: 'varchar'},
                            {label: 'tinyint(255)', value: 'tinyint'},
                            {label: 'datetime(年月日时分秒)', value: 'datetime'}
                        ]
                    },
                    {
                        label: '字符串',
                        options: [
                            {label: 'char(255)', value: 'char'},
                            {label: 'varchar(6.5万)', value: 'varchar'},
                            {label: 'text(6.5万)', value: 'text'},
                            {label: 'mediumtext(1600万)', value: 'mediumtext'},
                            {label: 'longtext(极长)', value: 'longtext'},
                        ]
                    },
                    {
                        label: '整型数值',
                        options: [
                            {label: 'tinyint(255)', value: 'tinyint'},
                            {label: 'smallint(6.5万)', value: 'smallint'},
                            {label: 'mediumint(1.6千万)', value: 'mediumint'},
                            {label: 'int(4.2亿)', value: 'int'},
                            {label: 'bigint(极大)', value: 'bigint'}
                        ]
                    },
                    {
                        label: '浮点数值',
                        options: [
                            {label: 'float(单精度)', value: 'float'},
                            {label: 'double(双精度)', value: 'double'},
                            {label: 'decimal(小数值)', value: 'decimal'}
                        ]
                    },
                    {
                        label: '日期时间',
                        options: [
                            {label: 'date(年月日)', value: 'date'},
                            {label: 'time(时分秒)', value: 'time'},
                            {label: 'year(年)', value: 'year'},
                            {label: 'datetime(年月日时分秒)', value: 'datetime'},
                            {label: 'timestamp(时间戳)', value: 'timestamp'}
                        ]
                    },
                    {
                        label: '二进制:图片/文件',
                        options: [
                            {label: 'blob(6.5万)', value: 'blob'},
                            {label: 'mediumblob(1600万)', value: 'mediumblob'},
                            {label: 'longblob(极长)', value: 'longblob'},
                        ]
                    }
                ],
                selectFilterable: true,
                selectIsGroup: true,
                selectPlaceholder: '选择数据类型',
                rules: [
                    {required: true, message: '数据类型必选'}
                ]
            }, {
                prop: 'fdSort',
                label: '排序',
                type: 'inputNumber',
                inputNumberMin: 0,
                // inputNumberMax: 10,
                sortable: true,
                rules: [
                    {required: true, message: '请输入排序'}
                ],
                addDefaultValue: 0
            }, {
                prop: 'fdDeleted',
                label: '删除',
                type: 'input',
                hide: true,
                addDefaultValue: 0
            }]
        const tableOpt = {
            title: '字段列表',
            columns: columns,
            pagination: {
                pageSizes: [30, 60, 90],
                pageSize: 30
            },
            dataUrl: '/apd/db/DevDbField/getTDevDbFieldGridList',
            saveUrl: '/apd/db/DevDbField/saveTDevDbFieldGridData',
            editPk: 'fdId',
            deletePk: 'fdId',
            deleteUrl: '/apd/db/DevDbField/deleteTDevDbFieldByFdId',
            toolbarBtn: ['add', 'edit', 'del', 'cancel', 'refresh', 'save', 'separator',
                {
                    btnType: 'primary',
                    text: '上移',
                    icon: 'el-icon-top',
                    onClick: () => {
                        this.sortBefore()
                    }
                },
                {
                    btnType: 'primary',
                    text: '下移',
                    icon: 'el-icon-bottom',
                    onClick: () => {
                        this.sortAfter()
                    }
                },
                {
                    btnType: 'primary',
                    text: '一键排序',
                    icon: 'el-icon-s-operation',
                    onClick: () => {
                        this.doSortByIndex()
                    }
                }, , {
                    btnType: 'info',
                    text: '帮助',
                    icon: 'el-icon-question',
                    onClick: () => {
                        this.openHelp()
                    }
                }],
            initData: false,
            beforeAdd: this.beforeAddFn,
            params: () => {
                return {
                    fdFieldTypeIds: this.selectedFieldTypeIds,
                    likeStr: this.searchForm.likeStr
                }
            }
        }

        return {
            // ----- 左侧树 -----
            loadingTreeFlag: false,
            filterText: '',
            typeTreeList: [],
            defaultProps: {
                children: 'children',
                label: 'fdName'
            },
            selectedFieldTypeIds: '',
            // ----- dialog -----
            typeList: [],
            dialogVisible: false,
            dialogTitle: '', // dialog标题
            isAddDialog: true, // 添加类型dialog
            dialogForm: {
                fdName: '',
                fdParentId: '',
                fdId: '',
                fdSort: undefined
            },
            dialogFormRules: {
                fdSort: [
                    {type: 'number', message: '请输入数字', trigger: 'change'}
                ],
                fdName: [
                    {required: true, message: '请输入类型名称', trigger: 'blur'},
                    {min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur'}
                ]
            },
            // ----- 表格 -----
            searchForm: {
                listStr: ''
            },
            tableOpt: tableOpt
        }
    },
    watch: {
        filterText(val) {
            this.$refs.typeTree.filter(val)
        }
    },
    created() {
        this.loadTreeData()
    },
    methods: {
        // 左侧树：加载数据
        loadTreeData() {
            this.loadingTreeFlag = true
            this.$request({
                url: '/apd/db/DevDbField/getDbFieldTypeList',
                method: 'post'
            }).then(response => {
                this.typeList = JSON.parse(JSON.stringify(response.data))
                this.typeTreeList = convertToTreeData(response.data, {
                    idKey: 'fdId',
                    parentKey: 'fdParentId',
                    childrenKey: 'children'
                })
            }).finally(() => {
                this.loadingTreeFlag = false
            })
        },
        // 左侧树：初始化数据
        initTreeData() {
            // 重置当前选择节点
            this.$refs.typeTree.setCurrentKey()
            this.loadTreeData()
        },
        // 左侧树：过滤节点
        filterNode(value, data) {
            if (!value) return true
            return data.fdName.indexOf(value) !== -1
        },
        // 选择勾选事件
        nodeClickEvent(data, node, comp) {
            const parentKeys = this.$refs.typeTree.getHalfCheckedKeys()
            const selectKeys = this.$refs.typeTree.getCheckedKeys(false)
            this.selectedFieldTypeIds = parentKeys.concat(selectKeys).join(',')
            this.$refs.devDbFieldGrid.refresh()
        },
        // dialog：重置表单
        resetDialogForm() {
            this.dialogForm = {
                fdName: '',
                fdParentId: '',
                fdId: '',
                fdSort: null
            }
        },
        getCurrentNode() {
            return this.$refs.typeTree.getCurrentNode() || {}
        },
        // dialog：添加数据
        addTable() {
            this.resetDialogForm()
            this.dialogVisible = true
            this.dialogTitle = '添加字段类型'
            this.isAddDialog = true
            this.dialogForm.fdParentId = this.getCurrentNode().fdId
        },
        // dialog：编辑数据
        editTable() {
            const currentNodeFdId = this.getCurrentNode().fdId
            if (!currentNodeFdId) {
                this.$message.error('请选择需要编辑的数据！')
                return
            }

            this.resetDialogForm()
            this.dialogVisible = true
            this.dialogTitle = '编辑字段类型'
            this.isAddDialog = false
            this.dialogForm.fdId = currentNodeFdId

            this.$request({
                url: '/apd/db/DevDbField/getDbFieldTypeByFdId',
                method: 'post',
                data: {
                    fdId: currentNodeFdId
                }
            }).then(response => {
                this.dialogForm.fdId = response.data.fdId
                this.dialogForm.fdName = response.data.fdName
                this.dialogForm.fdParentId = response.data.fdParentId
                this.dialogForm.fdSort = response.data.fdSort
            })
        },
        // 删除类型数据
        deleteTable() {
            const currentNode = this.getCurrentNode()
            const currentNodeFdId = currentNode.fdId
            if (!currentNodeFdId) {
                this.$message.error('请选择需要删除的数据！')
                return
            }

            this.$confirm(`确定要删除【${currentNode.fdName}】?`, '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.$request({
                    url: '/apd/db/DevDbField/deleteDbFieldType',
                    method: 'post',
                    data: {
                        fdId: currentNodeFdId
                    }
                }).then(response => {
                    this.$message.success(`删除成功！已删除${response.data}条数据！`)
                    this.initTreeData()
                })
            })
        },
        checkTypeSort() {
            const currentNode = this.getCurrentNode()
            if (currentNode == null) {
                this.$message.error(`请选择需要操作的节点！`)
                return null
            }
            return currentNode
        },
        // 修改排序
        doTypeSortChange(rowFdId, rowFdSort, exchangeRowFdId, exchangeRowFdSort) {
            this.$request({
                url: '/apd/db/DevDbField/updateDbFieldTypeSort',
                method: 'post',
                data: {rowFdId, rowFdSort, exchangeRowFdId, exchangeRowFdSort}
            }).then(response => {
                this.$message.success(`修改成功！`)
                this.$refs.popoverRef.doClose()
                this.loadTreeData()
            })
        },
        // 排序调整：向上
        sortTypeBefore() {
            const currentNode = this.checkTypeSort()
            if (currentNode == null) {
                return
            }

            const arrayData = convertToArrayData(this.typeTreeList)
            let currentNodeIndex = 0
            for (let i = 0; i < arrayData.length; i++) {
                if (arrayData[i].fdId == currentNode.fdId) {
                    currentNodeIndex = i
                    break
                }
            }
            if (currentNodeIndex == 0) {
                this.$message.success(`已经是第一个啦！`)
                return
            }

            const exchangeRow = arrayData[currentNodeIndex - 1]

            this.doTypeSortChange(currentNode.fdId, exchangeRow.fdSort, exchangeRow.fdId, currentNode.fdSort)
        },
        // 排序调整：向下
        sortTypeAfter() {
            const currentNode = this.checkTypeSort()
            if (currentNode == null) {
                return
            }
            const arrayData = convertToArrayData(this.typeTreeList)
            let currentNodeIndex = 0
            for (let i = 0; i < arrayData.length; i++) {
                if (arrayData[i].fdId == currentNode.fdId) {
                    currentNodeIndex = i
                    break
                }
            }

            if (currentNodeIndex == arrayData.length - 1) {
                this.$message.success(`字段已经是最后一个啦！`)
                return
            }

            const exchangeRow = arrayData[currentNodeIndex + 1]

            this.doTypeSortChange(currentNode.fdId, exchangeRow.fdSort, exchangeRow.fdId, currentNode.fdSort)
        },
        // 一键排序
        sortTypeByIndex() {
            const arrayData = convertToArrayData(this.typeTreeList)
            const list = []
            for (let i = 0; i < arrayData.length; i++) {
                list.push({
                    fdId: arrayData[i].fdId,
                    fdSort: i + 1
                })
            }
            this.$request({
                url: '/apd/db/DevDbField/updateDbFieldTypeSortList',
                method: 'post',
                data: {list: JSON.stringify(list)}
            }).then(response => {
                this.$message.success(`排序成功！`)
                this.$refs.popoverRef.doClose()
                this.loadTreeData()
            })
        },
        // dialog：保存类型数据
        saveTable() {
            this.$refs.dialogForm.validate((valid) => {
                if (!valid) {
                    this.$message.error(`数据校验失败，请重新填写信息！`)
                    return false
                }
                if (this.isAddDialog) {
                    // 添加数据
                    this.$request({
                        url: '/apd/db/DevDbField/insertDbFieldType',
                        method: 'post',
                        data: this.dialogForm
                    }).then(response => {
                        this.$message.success(`添加成功！已添加${response.data}条数据！`)
                        this.dialogVisible = false
                        this.initTreeData()
                    })
                } else {
                    // 更新数据
                    this.$request({
                        url: '/apd/db/DevDbField/updateDbFieldType',
                        method: 'post',
                        data: this.dialogForm
                    }).then(response => {
                        this.$message.success(`更新成功！已更新${response.data}条数据！`)
                        this.dialogVisible = false
                        this.initTreeData()
                    })
                }
            })
        },
        // 添加行：数据类型默认值
        beforeAddFn() {
            const fdFieldTypeIds = this.selectedFieldTypeIds
            if (fdFieldTypeIds == null || fdFieldTypeIds == '') {
                this.$message.error(`请先选择字段类型！`)
                return false
            }
            return true
        },
        addDefaultValueFn() {
            return this.getCurrentNode().fdId
        },
        checkSort() {
            const selection = this.$refs.devDbFieldGrid.getSelection()
            if (selection.length == 0) {
                this.$message.error(`请选择需要操作的行！`)
                return null
            } else if (selection.length > 1) {
                this.$message.error(`只能选择一行！`)
                return null
            }
            return selection[0]
        },
        // 修改排序
        doSortChange(rowFdId, rowFdSort, exchangeRowFdId, exchangeRowFdSort) {
            this.$request({
                url: '/apd/db/DevDbField/updateDbFieldSort',
                method: 'post',
                data: {rowFdId, rowFdSort, exchangeRowFdId, exchangeRowFdSort}
            }).then(response => {
                this.$message.success(`修改成功！`)
                this.$refs.devDbFieldGrid.refresh()
            })
        },
        // 排序调整：向上
        sortBefore() {
            const rowData = this.checkSort()
            if (rowData == null) {
                return
            }
            const dataIdx = rowData.dataIdx
            if (dataIdx == 1) {
                this.$message.success(`字段已经是第一个啦！`)
                return
            }

            const exchangeRow = this.tableOpt.data[dataIdx - 2]

            this.doSortChange(rowData.fdId, exchangeRow.fdSort, exchangeRow.fdId, rowData.fdSort)
        },
        // 排序调整：向下
        sortAfter() {
            const rowData = this.checkSort()
            if (rowData == null) {
                return
            }
            const dataIdx = rowData.dataIdx
            if (dataIdx >= this.tableOpt.data.length) {
                this.$message.success(`字段已经是最后一个啦！`)
                return
            }
            const exchangeRow = this.tableOpt.data[dataIdx]

            this.doSortChange(rowData.fdId, exchangeRow.fdSort, exchangeRow.fdId, rowData.fdSort)
        },
        doSortByIndex() {
            const data = this.$refs.devDbFieldGrid.getData()
            const list = []
            for (let i = 0; i < data.length; i++) {
                list.push({
                    fdId: data[i].fdId,
                    fdSort: data[i].dataIdx
                })
            }
            this.$request({
                url: '/apd/db/DevDbField/updateDbFieldSortList',
                method: 'post',
                data: {list: JSON.stringify(list)}
            }).then(response => {
                this.$message.success(`排序成功！`)
                this.$refs.devDbFieldGrid.refresh()
            })
        },
        searchEvent() {
            this.$refs.devDbFieldGrid.refresh()
        },
        openHelp() {
            const msg = `
                <b>一、通用字段：</b><br>
                1、标识类型(0、1)：放在【默认-标识】下。<br>
                2、日期：放在【默认-日期】下。<br>
                3、字符串、数字：放在【默认-常用】下。<br>
                注意：只要是比较通用的字段，都应该放在【默认】的分类下。<br>
                <b>二、特殊字段：</b><br>
                1、字段是业务模块特有的，放在【业务】下的模块。如：固定资产编码fd_asset_type_code，应该放在固定资产下。<br>
                `
            this.$alert(msg, '字段规范说明', {dangerouslyUseHTMLString: true})
        }
    }
}
</script>

<style scoped>
</style>
