首先我们有一个单位表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>
);
}
}
浙公网安备 33010602011771号