蔡香满屋
站在牛顿头上吃苹果

首先我们有一个单位表pdm如:

查询该表数据有:

我们最终想要显示的结果如:

后端实现代码如下:

DepartmentTreeVo对象代码如下:
@Getter
@Setter
@ToString
public class DepartmentTreeVo {
	
    /**
     * 单位主键
     */
    private java.lang.String departmentId;
    
     /**
     * 单位号
     */
    private java.lang.String departmentNum;
    
     /**
     * 单位名称
     */
    private java.lang.String departmentName;
    
     /**
     * 单位英文名称
     */
    private java.lang.String parentOrNot;
    
     /**
     * 单位简称
     */
    private java.lang.String parentId;
    
    
    private List<DepartmentTreeVo> children;
}

实现层:

@Override
	public List<DepartmentTreeVo> getTree() {
		DepartmentTreeDto departmentTreeDto = new DepartmentTreeDto();
		// departmentTreeDto.setParentOrNot("true");
		departmentTreeDto.setFirstLevel("true");
		// 查出所有的一级节点
		List<DepartmentTreeVo> list = departmentMapper.getTree(departmentTreeDto);
         /**sql注释
          select
              distinct c.dw_id as departmentId,
              c.dwh as departmentNum,
              c.dwmc as departmentName,
              c.isParent as parentOrNot,
              c.parentId as parentId,
              c.isFirstLevel as firstLevel
          from ( // 自连接
              select
                a.dw_id, a.dwh, a.dwmc, a.lsdwh,
                nvl2(b.dw_id, 'true', 'false') as isParent,
                case when a.lsdwh is null then 'true' else 'false' end as isFirstLevel,
                a.lsdwh as parentId
              from t_ggzy_dwxx a
              left join t_ggzy_dwxx b on a.dwh = b.LSDWH
              ) c
              WHERE c.isFirstLevel = 'true' order by c.dwh asc
            */
          查询截图如:

 


// 遍历下级节点 for (DepartmentTreeVo departmentTreeVo : list) { List<DepartmentTreeVo> departmentTreeList =getChildTree(departmentTreeVo.getDepartmentId()); departmentTreeVo.setChildren(departmentTreeList); } //添加学院虚拟节点 List<DepartmentTreeVo> returnlist=new ArrayList<DepartmentTreeVo>(); DepartmentTreeVo baseVo=new DepartmentTreeVo(); //查询学校信息(学校信息只有一个) SchoolDto schoolDto = new SchoolDto(); List<SchoolVo> schoolvo = schoolMapper.select(schoolDto); // 比如查询出来这个学校叫电力大学 if(schoolvo.size()>0){ baseVo.setDepartmentId(schoolvo.get(0).getSchoolCode()); baseVo.setDepartmentName(schoolvo.get(0).getSchoolName()); } baseVo.setChildren(list); returnlist.add(baseVo); return returnlist ; }
// 递归遍历子节点
public List<DepartmentTreeVo> getChildTree(String departmentId) {
DepartmentTreeDto departmentTree = new DepartmentTreeDto();
departmentTree.setParentId(departmentId);
List<DepartmentTreeVo> list=departmentMapper.getTree(departmentTree);
  /**
   *
departmentMapper.getTree(departmentTree)执行是这段sql查询出子单位
select distinct c.dw_id        as departmentId,
                c.dwh          as departmentNum,
                c.dwmc         as departmentName,
                c.isParent     as parentOrNot,
                c.parentId     as parentId,
                c.isFirstLevel as firstLevel
  from (select a.dw_id,
               a.dwh,
               a.dwmc,
               a.lsdwh,
               nvl2(b.dw_id, 'true', 'false') as isParent,
               case
                 when a.lsdwh is null then
                  'true'
                 else
                  'false'
               end as isFirstLevel,
               a.lsdwh as parentId
          from t_ggzy_dwxx a
          left join t_ggzy_dwxx b
            on a.dwh = b.LSDWH) c
 WHERE c.parentId = '101'
 order by c.dwh asc

  


   */
for (DepartmentTreeVo departmentTreeVo : list) {
departmentTreeVo.setChildren(getChildTree(departmentTreeVo.getDepartmentId()));
}
return list;
}

 数据库xml实现如下:

<!-- 获取树形列表 -->
	<select id="getTree" parameterType="com.ly.education.core.api.dto.DepartmentTreeDto"
		resultType="com.ly.education.core.api.vo.DepartmentTreeVo">
		select distinct c.dw_id as departmentId,
		c.dwh as departmentNum,
		c.dwmc
		as departmentName,
		c.isParent as parentOrNot,
		c.parentId as parentId,
		c.isFirstLevel as firstLevel
		from (
         <!--通过自连接标识出哪个是一级单位--> select a.dw_id, a.dwh, a.dwmc, a.lsdwh, nvl2(b.dw_id, 'true', 'false') as isParent, case when a.lsdwh is null then 'true' else 'false' end as isFirstLevel, a.lsdwh as parentId from t_ggzy_dwxx a left join t_ggzy_dwxx b on a.dwh = b.LSDWH ) c <where> <if test="parentOrNot != null"> and c.isParent = #{parentOrNot,jdbcType=VARCHAR} </if> <if test="firstLevel != null"> and c.isFirstLevel = #{firstLevel,jdbcType=VARCHAR} </if> <if test="parentId != null"> and c.parentId= #{parentId,jdbcType=VARCHAR} </if> </where> order by c.dwh asc </select>

  前端代码react实现如下:

import React from 'react';
import {
    Layout,
    Row,
    Col,
    Tree,
    Button,
    Pagination,
    Modal,
    Icon,
    Divider
} from 'antd';
import { Scrollbars, DragModal, TableBox, Permission } from 'components';
import _SearchModal from './_SearchModal';
import _FormModal from './_FormModal';
import DetailModal from './DetailModal';
import emitter from 'src/utils/events';
import moment from 'moment';
import {
    departmentCreate,
    departmentDetail,
    departmentQuery,
    departmentUpdate,
    departmentBatchDelete,
    departmentTreeList,
    departmentSelectList,
    departmentExportData,
    importExcelData
} from './service';
import {message} from 'antd/lib/index';
import UpdateModal from "src/app/layout/baseInfo/pages/commonCodeManagment/department/UpdateModal";
import TitleTransferModal from "./titleTransfer";
import ImportDataModal from './importData';

const TreeNode = Tree.TreeNode;
const {Sider} = Layout;
const confirm = Modal.confirm;

export default class Department extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: false,
            open: true,
            total: 0,
            departmentId: '', // 当前选中单位
            dataList: [], // 单位数据列表
            departmentTreeList: [], // 单位树形列表
            selectedRows: [],
            schoolCode: '', // 学校代码
            treeNode: {},
            eventTreeNode: [],
            selectedKeys: [], // tree选中列表
            expandedKeys: [],
            parentId: '',
            autoExpandParent: true,
            titleTransferVisible: false, // 导出模态框
            importModalVisible: false, //导入模态框
            departmentSelectList: [],
        };
    }

    componentWillMount() {
    }


    componentDidMount() {
        this.getParentDeptList();
        this.getSelectList();
        this.getDataList();
    }

    // 查询参数
    params = {
        pageNo: 1,
        pageSize: 20,
        // 默认按部门号排序
        sorter: {
            field: 'departmentNum',
            order: 'ascend'
        }
    };

    // 初始获取全部单位信息
    getDataList = params => {
        return new Promise(resolve => {
            const _params = {
                ...this.params,
                ...params
            };
            // 排序
            if (_params.sorter && _params.sorter.field && _params.sorter.order) {
                _params['attributeNamesForOrderBy'] = {
                    [_params.sorter.field]: _params.sorter.order.substring(
                        0,
                        _params.sorter.order.length - 3
                    )
                };
                delete _params.sorter;
            }
            this.setState({
                loading: true
            });
            this.exportParams = _params;
            // 刷新表格数据
            departmentQuery(_params, 'department:query', data => {
                this.setState({
                    loading: false,
                    dataList: data.rows,
                    selectedRows: [],
                    selectedRowKeys: [],
                    total: data.total,
                }, () => {
                    resolve();
                });
            });
        });
    };

    getParentDeptList = () => {
        return new Promise(resolve => {
            this.setState({
                loading: true
            });
            departmentTreeList(null, 'department:query', data => {
                this.setState({
                    loading: false,
                    departmentTreeList: data,// 单位树形列表
                    selectedKeys: [data[0].departmentId], // tree选中列表
                    expandedKeys: [data[0].departmentId],
                    schoolCode: data[0].departmentId, //学校代码
                }, () => {
                    this.getDataList().then(() => {
                        resolve();
                    });
                });
            });
        });
    };

    reloadParentDeptList = () => {
        return new Promise(resolve => {
            this.setState({
                loading: true
            });
            departmentTreeList(null, 'department:query', data => {
                this.setState({
                    loading: false,
                    departmentTreeList: data // 单位树形列表
                }, () => {
                    this.getDataList().then(() => {
                        this.getSelectList()
                        resolve();
                    });
                });
            });
        });
    };

    // 搜索
    onSearch = params => {
        this.params.pageNo = 1;
        if (this.params && this.params.param && params && params.param) {
            let _param = {
                ...this.params.param,
                ...params.param
            };
            params.param = _param;
        }
        this.params = {...this.params, ...params};
        this.getDataList();
    };

    // 切换页数
    pageChange = pageNo => {
        this.params.pageNo = pageNo;
        this.getDataList();
    };

    // 切换条数
    onShowSizeChange = (current, pageSize) => {
        this.params.pageNo = 1;
        this.params.pageSize = pageSize;
        this.getDataList();
    };

    // 获取下拉列表
    getSelectList = () => {
        // 单位下拉
        departmentSelectList(null, 'department:query', data => {
            this.setState({departmentSelectList: data});
        });
    };

    // 添加修改模态框开关
    showAddModal = () => {
        this.setState({
            addModalVisible: !this.state.addModalVisible,
            updateModalVisible: false,
            detailModalVisible: false
        });
    };

    // 详情模态框开关
    showDetailModal = selectRow => {
        this.setState({
            detailRow: selectRow,
            detailModalVisible: !this.state.detailModalVisible
        });
    };

    handleCancel = e => {
        this.setState({
            addModalVisible: false,
            updateModalVisible: false,
            detailModalVisible: false
        });
    };

    showDeleteConfirm = () => {
        let _this = this;
        let departmentIds = this.state.selectedRows.map(item => {
            return item.departmentId;
        });
        if (this.state.selectedRows.length == 0) {
            message.warning('请先选择要删除的项');
            return;
        } else {
            confirm({
                title: '确认',
                content: '确认要删除吗?',
                okText: '确认',
                okType: 'danger',
                cancelText: '返回',
                onOk() {
                    const {parentId} = _this.state;
                    departmentBatchDelete(departmentIds, 'department:delete', () => {
                        // 解决删除整页数据时,页码显示问题
                        if (
                            _this.state.dataList &&
                            _this.state.selectedRowKeys.length >=
                            _this.state.dataList.length &&
                            _this.params.pageNo > 1
                        ) {
                            _this.params.pageNo = _this.params.pageNo - 1;
                        }
                        _this.reloadParentDeptList().then(() => {
                            let key = _this.state.expandedKeys
                            _this.onExpand(departmentIds.indexOf(_this.state.departmentId) >= 0 && parentId ? [parentId] : key, _this.state.eventTreeNode)
                        });
                    });
                },
                onCancel() {
                }
            });
        }
    };

    // 切换开关时改变table的高度
    openChange = open => {
        if (this.tableBoxRef) {
            this.tableBoxRef.setHeight();
        }
    };

    // 获取tablebox的ref
    onTableBoxRef = ref => {
        this.tableBoxRef = ref;
    };

    onSelect = (item, e) => {
        if (e.node) {
            if (e.node.props.dataRef.parentOrNot == 'false') {
                const parentId = e.node.props.dataRef.parentId
                this.setState({
                    parentId
                })
            } else {
                this.setState({
                    parentId: ''
                })
            }
        }
        if (item.length > 0) {
            this.setState({
                selectedKeys: this.state.selectedKeys,
                departmentId: item[0],
                eventTreeNode: e,
                treeNode: e.node
            }, () => {
                this.onExpand(item, e)
            });
        }
    };

    onExpand = (expandedKeys, e) => {
        let keys = expandedKeys[expandedKeys.length - 1];
        return new Promise(resolve => {
            this.setState({
                expandedKeys: expandedKeys,
                selectedKeys: [keys],
                departmentId: keys,
                autoExpandParent: true,
                eventTreeNode: e,
                treeNode: e.node
            }, () => {
                this.onSearch({param: {departmentId: keys == this.state.schoolCode ? '' : keys}});
                resolve();
            });
        });
    };

    // 导入模态框开关
    showImportModal = () => {
        this.setState({
            importModalVisible: !this.state.importModalVisible
        });
    };

    /*// 导入excel处理函数
    handleImportData = (params) => {
        let data = {};
        let formData = new FormData();
        formData.append("file", params.file);
        formData.append("routeKey", params.routeKey);
        let strJson = {
            modelDto: { routeKey: params.routeKey, dto: data }
        };
        importExcelData(formData, strJson, 'department:import', () => {
            this.onSearch({ pageNo: this.params.pageNo });
            this.showImportModal();
        });
    };*/

    // 异步加载子节点数据
    /*onLoadData = treeNode => {
        return new Promise(resolve => {
            departmentChildrenList(treeNode.props.eventKey, data => {
                treeNode.props.dataRef.children = data;
                this.setState({
                    departmentTreeList: [...this.state.departmentTreeList]
                }, () => {
                    resolve();
                });
            });
        });
    };*/

    // 侧边
    toggle = collapsed => {
        this.setState({
            collapsed: !this.state.collapsed
        });
    };

    renderTree = (data, idx) => {
        return data.map(item => {
            if (!item.children) {
                return (
                    <TreeNode
                        title={item.departmentName}
                        key={item.departmentId}
                        dataRef={item}
                        isLeaf={item.parentOrNot == 'false'}
                    />
                );
            } else {
                return (
                    <TreeNode
                        title={item.departmentName}
                        key={item.departmentId}
                        dataRef={item}
                    >
                        {this.renderTree(item.children)}
                    </TreeNode>
                );
            }
        });
    };

    handleTableChange = (pagination, filters, sorter) => {
        this.params.sorter = sorter;
        this.getDataList();
    };

    // 监听捕获新增和修改模态框的参数
    captureFormModal = () => {
        emitter.emit('formModal', this.onOk);
    };

    // 确认
    onOk = params => {
        //时间转换
        params.departmentBuildDate = moment(params.departmentBuildDate).format(
            'YYYY-MM'
        );
        // 修改模态框
        if (this.state.updateModalVisible) {
            Object.assign(params, {
                departmentId: this.state.initialValue.departmentId
            });
            departmentUpdate(params, 'department:update', () => {
                this.setState({
                    addModalVisible: false,
                    updateModalVisible: false
                }, () => {
                    this.reloadParentDeptList().then(() => {
                        this.onSearch();
                    });
                });
            });
        } else {
            // 添加模态框
            departmentCreate(params, 'department:insert', () => {
                this.setState({
                    addModalVisible: false,
                    updateModalVisible: false
                }, () => {
                    this.reloadParentDeptList().then(() => {
                        this.onSearch();
                    });
                });
            });
        }
    };

    // title选择模态框开关
    showTitleTransferModal = () => {
        this.setState({
            titleTransferVisible: !this.state.titleTransferVisible
        });
    };

    // 绑定子组件
    setChild = (ref) => {
        this.child = ref;
    }

    // 导出数据参数
    exportParams = {};

    // 导出数据
    exportData = () => {
        this.refs.titleTransfer.validateFields((err, formData) => {
            if (!err ) {
                let params = {};
                // 组装请求参数
                let temParams = this.exportParams.param;
                delete this.exportParams.param;
                if(formData.exportRange == 2){
                    if(this.state.selectedRows.length > 0){
                        params = {param:{departmentDto:temParams,titleNames:this.child.state.titleNames,exportRange:formData.exportRange,currentChoose:this.state.selectedRows}};
                        Object.assign(params,{...this.exportParams})
                        departmentExportData(params, 'department:exportDepartmentData', (res) => {
                            let fileName = res.headers["content-disposition"].split(";")[1].split("filename=")[1];
                            const aLink = document.createElement('a');
                            document.body.appendChild(aLink);
                            aLink.style.display='none';
                            const objectUrl = URL.createObjectURL(res.data);
                            aLink.href = objectUrl;
                            aLink.download = decodeURI(fileName);
                            aLink.click();
                            document.body.removeChild(aLink);
                            this.showTitleTransferModal();
                            this.onSearch();
                        })
                    }else{
                        message.warning('请选择对应的数据')
                    }

                }else{
                    params = {param:{departmentDto:temParams,titleNames:this.child.state.titleNames,exportRange:formData.exportRange}};
                    Object.assign(params,{...this.exportParams})
                    departmentExportData(params, 'department:exportDepartmentData', (res) => {
                        let fileName = res.headers["content-disposition"].split(";")[1].split("filename=")[1];
                        const aLink = document.createElement('a');
                        document.body.appendChild(aLink);
                        aLink.style.display='none';
                        const objectUrl = URL.createObjectURL(res.data);
                        aLink.href = objectUrl;
                        aLink.download = decodeURI(fileName);
                        aLink.click();
                        document.body.removeChild(aLink);
                        this.showTitleTransferModal();
                        this.onSearch();
                    })
                }

            }
        });
    }

    render() {
        const rowSelection = {
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({
                    selectedRows: selectedRows,
                    selectedRowKeys: selectedRowKeys
                });
            },
            selectedRowKeys: this.state.selectedRowKeys, // 指定选中项的 key 数组
            getCheckboxProps: record => ({
                disabled: record.name === 'Disabled User',
                name: record.name
            })
        };

        const columns = [
            {
                title: '序号',
                align: 'center',
                dataIndex: 'index',
                key: 'index',
                // fixed: 'left',
                width: '5%',
                render: (text, record, index) => {
                    return (
                        (this.params.pageNo - 1) * this.params.pageSize +
                        index +
                        1
                    );
                }
            },
            {
                title: '单位号',
                align: 'center',
                dataIndex: 'departmentNum',
                key: 'departmentNum',
                sorter: true,
                defaultSortOrder: 'ascend',
                width: '10%'
            },
            {
                title: '单位名称',
                align: 'center',
                dataIndex: 'departmentName',
                key: 'departmentName',
                width: '16%'
            },
            {
                title: '英文名称',
                align: 'center',
                dataIndex: 'departmentEnglishName',
                key: 'departmentEnglishName',
                width: '11%'
            },
            {
                title: '单位类别',
                align: 'center',
                dataIndex: 'departmentCategoryName',
                key: 'departmentCategoryName',
                width: '10%'
            },
            {
                title: '是否启用',
                align: 'center',
                dataIndex: 'departmentEnableSign',
                key: 'departmentEnableSign',
                width: '8%',
                render: (text, record, index) => {
                    if (text == '0') {
                        return '否';
                    } else if (text == '1') {
                        return '是';
                    }
                }
            },
            {
                title: '是否实体',
                align: 'center',
                dataIndex: 'departmentEntitySign',
                key: 'departmentEntitySign',
                width: '8%',
                render: (text, record, index) => {
                    if (text == '0') {
                        return '否';
                    } else if (text == '1') {
                        return '是';
                    }
                }
            },
            {
                title: '是否招生单位',
                align: 'center',
                dataIndex: 'departmentRecruitSign',
                key: 'departmentRecruitSign',
                width: '11%',
                render: (text, record, index) => {
                    if (text == '0') {
                        return '否';
                    } else if (text == '1') {
                        return '是';
                    }
                }
            },
            {
                title: '是否开课单位',
                align: 'center',
                dataIndex: 'departmentOpenSign',
                key: 'departmentOpenSign',
                width: '11%',
                render: (text, record, index) => {
                    if (text == '0') {
                        return '否';
                    } else if (text == '1') {
                        return '是';
                    }
                }
            },
            {
                title: '操作',
                align: 'center',
                dataIndex: 'operation',
                width: '10%',
                // fixed: 'right',
                key: 'operation',
                render: (text, record, index) => {
                    return (
                        <div>
                            <Permission name='department:update'>
                                <a
                                    onClick={() => {
                                        departmentDetail(
                                            record.departmentId,
                                            'department:update',
                                            data => {
                                                this.setState({
                                                    updateModalVisible: true,
                                                    initialValue: data
                                                });
                                            }
                                        );
                                    }}
                                >
                                    修改
                                </a>
                            </Permission>
                            <Permission name='department:detail'>
                                <Divider type="vertical" />
                                <a
                                    onClick={() => {
                                        this.showDetailModal(record);
                                    }}
                                >
                                    详情
                                </a>
                            </Permission>
                        </div>
                    );
                }
            }
        ];
        return (
            <Layout className="page_tree">
                <Sider
                    className="page_tree_sider"
                    theme="light"
                    trigger={null}
                    collapsible
                    collapsed={this.state.collapsed}
                >
                    <div className="page_tree_sider_btn" onClick={this.toggle}>
                        <Icon
                            className="trigger"
                            type={this.state.collapsed ? 'right' : 'left'}
                        />
                    </div>
                    <Scrollbars className="page_tree_sider_scroll" style={{width: '100%', height: '100%'}}>
                        <Tree
                            showLine={true}
                            selectedKeys={this.state.selectedKeys}
                            autoExpandParent={this.state.autoExpandParent}
                            expandedKeys={this.state.expandedKeys.slice()}
                            onSelect={this.onSelect}
                            onExpand={this.onExpand}
                            /* loadData={this.onLoadData}*/
                        >
                            {this.renderTree(this.state.departmentTreeList)}
                        </Tree>
                    </Scrollbars>
                </Sider>
            </Layout>
        );
    }
}

  

 

posted on 2019-07-31 21:37  蔡香满屋  阅读(805)  评论(0)    收藏  举报