766 lines
21 KiB
JavaScript
766 lines
21 KiB
JavaScript
|
|
import React from 'react';
|
|||
|
|
import { message, Alert, Icon, Menu } from 'antd';
|
|||
|
|
import { Search } from '@woowalker/feui'
|
|||
|
|
import ComponentBase from "../ComponentBase";
|
|||
|
|
import styles from '../Component.css';
|
|||
|
|
import _ from 'lodash';
|
|||
|
|
import { addRuleAndGroups, extendRule, getDataFieldValue, guid, initFilter, permissionUtils } from "../../utils/common";
|
|||
|
|
|
|||
|
|
class TreeBaseComponent extends ComponentBase {
|
|||
|
|
constructor(props) {
|
|||
|
|
super(props);
|
|||
|
|
this.state = {
|
|||
|
|
data: {},
|
|||
|
|
treeConfig: {},
|
|||
|
|
treeLoadParam: {},
|
|||
|
|
treeSelectedNodeId: {},
|
|||
|
|
treeExpandedKeys: {}
|
|||
|
|
};
|
|||
|
|
this.defaultTreeCode = 'tree';
|
|||
|
|
};
|
|||
|
|
componentDidMount() {
|
|||
|
|
super.componentDidMount();
|
|||
|
|
this.onLoadData();
|
|||
|
|
const { onRegLoadFunc, } = this.props;
|
|||
|
|
if (typeof onRegLoadFunc === 'function') {
|
|||
|
|
onRegLoadFunc(({ treeCode = this.defaultTreeCode, searchValue }) => {
|
|||
|
|
this.onLoadTreeData({
|
|||
|
|
treeCode,
|
|||
|
|
searchValue,
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
componentWillReceiveProps(NextProps) {
|
|||
|
|
super.componentWillReceiveProps(NextProps);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onLoadData() {
|
|||
|
|
const treeConfigs = this.onLoadTreeConfigList();
|
|||
|
|
if (treeConfigs && treeConfigs.length) {
|
|||
|
|
let treeConfig = this.state.treeConfig;
|
|||
|
|
if (!treeConfig) {
|
|||
|
|
treeConfig = {};
|
|||
|
|
}
|
|||
|
|
treeConfigs.forEach(t => {
|
|||
|
|
if (t.treeCode === undefined) {
|
|||
|
|
t.treeCode = this.defaultTreeCode;
|
|||
|
|
}
|
|||
|
|
treeConfig[t.treeCode] = t;
|
|||
|
|
});
|
|||
|
|
this.setState({
|
|||
|
|
treeConfig,
|
|||
|
|
}, () => {
|
|||
|
|
const tempTreeConfig = this.state.treeConfig;
|
|||
|
|
if (tempTreeConfig) {
|
|||
|
|
Object.keys(tempTreeConfig).forEach((n) => {
|
|||
|
|
this.onLoadTreeData({
|
|||
|
|
treeCode: n,
|
|||
|
|
treeConfig: tempTreeConfig[n],
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onLoadTreeConfigList() { }
|
|||
|
|
|
|||
|
|
onLoadTreeData({ treeCode, searchValue, onComplete }) {
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode });
|
|||
|
|
if (treeConfig) {
|
|||
|
|
const { sort, order, relationField, relationId, api, orgType, ignoreOrgRule } = treeConfig;
|
|||
|
|
|
|||
|
|
if (!api) return;
|
|||
|
|
const treeLoadParam = this.state.treeLoadParam;
|
|||
|
|
let loadParam = treeLoadParam[treeCode];
|
|||
|
|
|
|||
|
|
if (!loadParam) {
|
|||
|
|
loadParam = initFilter(this.props.login.OrgId, '', sort, order);
|
|||
|
|
treeLoadParam[treeCode] = loadParam;
|
|||
|
|
}
|
|||
|
|
const rules = this.props && this.props.data && this.props.data.rules ? this.props.data.rules : [];
|
|||
|
|
const json = JSON.parse(JSON.stringify(loadParam));//{ ...loadParam };
|
|||
|
|
if (
|
|||
|
|
(!relationField || relationField !== "PARENT_ID") &&
|
|||
|
|
_.findIndex(rules, (o) => { return o.field === 'PARENT_ID' }) < 0) {
|
|||
|
|
extendRule(json, "PARENT_ID", 1, "");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (rules) {
|
|||
|
|
rules.forEach(item => {
|
|||
|
|
extendRule(json, item.field, item.operator, item.value, item.isSysParam);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
if (orgType) {
|
|||
|
|
json.OrgType = orgType;
|
|||
|
|
}
|
|||
|
|
if (searchValue) {
|
|||
|
|
addRuleAndGroups(json, searchValue);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//填加关联字段过滤
|
|||
|
|
if (relationField && relationId) {
|
|||
|
|
extendRule(json, relationField, 1, relationId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 是否忽略组织权限
|
|||
|
|
if (ignoreOrgRule) {
|
|||
|
|
json.IgnoreOrgRule = ignoreOrgRule
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.props.dispatch({
|
|||
|
|
type: 'app/getTableData',
|
|||
|
|
payload: json,
|
|||
|
|
url: api,
|
|||
|
|
onComplete: (ret) => {
|
|||
|
|
if (ret) {
|
|||
|
|
if (!ret.IsSuccessful) {
|
|||
|
|
message.error(ret.ErrorMessage);
|
|||
|
|
}
|
|||
|
|
this.setTreeData({
|
|||
|
|
treeCode,
|
|||
|
|
data: ret.Data,
|
|||
|
|
onComplete,
|
|||
|
|
}, () => {
|
|||
|
|
this.onAfterLoadTreeData();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onAfterLoadTreeData() { }
|
|||
|
|
|
|||
|
|
onLoadTreeChildData({ treeCode, treeNode }) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
if (treeNode.props.dataRef.IS_LEAF) {
|
|||
|
|
reject();
|
|||
|
|
} else {
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode });
|
|||
|
|
if (treeConfig) {
|
|||
|
|
const { sort, order, api } = treeConfig;
|
|||
|
|
let json = initFilter(this.props.login.OrgId, '', sort, order);
|
|||
|
|
extendRule(json, "PARENT_ID", 1, treeNode.props.dataRef.ID);
|
|||
|
|
this.props.dispatch({
|
|||
|
|
type: 'app/getTableData',
|
|||
|
|
payload: json,
|
|||
|
|
url: api,
|
|||
|
|
onComplete: (ret) => {
|
|||
|
|
if (ret) {
|
|||
|
|
if (!ret.IsSuccessful) {
|
|||
|
|
message.error(ret.ErrorMessage);
|
|||
|
|
}
|
|||
|
|
const treeData = this.getTreeData({ treeCode });
|
|||
|
|
this.getTreeDataById(treeData, treeNode.props.dataRef.ID, (data) => {
|
|||
|
|
if (!data.Children) {
|
|||
|
|
data.Children = [];
|
|||
|
|
}
|
|||
|
|
if (ret.Data) {
|
|||
|
|
ret.Data.forEach(t => {
|
|||
|
|
data.Children.push(t);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
this.setTreeData({
|
|||
|
|
treeCode,
|
|||
|
|
data: treeData,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
resolve();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取树配置
|
|||
|
|
*/
|
|||
|
|
getTreeConfig(params) {
|
|||
|
|
const { treeCode = this.defaultTreeCode } = params ? params : {};
|
|||
|
|
let treeConfig = this.state.treeConfig;
|
|||
|
|
if (!treeConfig) {
|
|||
|
|
treeConfig = {};
|
|||
|
|
}
|
|||
|
|
return treeConfig[treeCode];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
设置树配置
|
|||
|
|
*/
|
|||
|
|
setTreeConfig(params) {
|
|||
|
|
const { treeConfig, onComplete } = params ? params : {};
|
|||
|
|
let tempTreeConfig = this.state.treeConfig;
|
|||
|
|
if (!tempTreeConfig) {
|
|||
|
|
tempTreeConfig = {};
|
|||
|
|
}
|
|||
|
|
if (treeConfig.treeCode === undefined) {
|
|||
|
|
treeConfig.treeCode = this.defaultTreeCode;
|
|||
|
|
}
|
|||
|
|
tempTreeConfig = {
|
|||
|
|
...tempTreeConfig,
|
|||
|
|
[treeConfig.treeCode]: treeConfig,
|
|||
|
|
};
|
|||
|
|
this.setState({
|
|||
|
|
treeConfig: tempTreeConfig
|
|||
|
|
}, () => {
|
|||
|
|
if (typeof onComplete === 'function') {
|
|||
|
|
onComplete();
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取树数据
|
|||
|
|
*/
|
|||
|
|
getTreeData(params) {
|
|||
|
|
const { treeCode = this.defaultTreeCode } = params ? params : {};
|
|||
|
|
let data = this.state.treeData;
|
|||
|
|
if (!data) {
|
|||
|
|
data = {};
|
|||
|
|
}
|
|||
|
|
return data[treeCode];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
设置树数据
|
|||
|
|
*/
|
|||
|
|
setTreeData({ treeCode, data, onComplete }) {
|
|||
|
|
let tempData = this.state.treeData;
|
|||
|
|
if (!tempData) {
|
|||
|
|
tempData = {};
|
|||
|
|
}
|
|||
|
|
if (treeCode === undefined) {
|
|||
|
|
treeCode = this.defaultTreeCode;
|
|||
|
|
}
|
|||
|
|
tempData = {
|
|||
|
|
...tempData,
|
|||
|
|
[treeCode]: data,
|
|||
|
|
};
|
|||
|
|
this.setState({
|
|||
|
|
treeData: tempData,
|
|||
|
|
}, () => {
|
|||
|
|
if (typeof onComplete === 'function') {
|
|||
|
|
onComplete();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取选中节点ID
|
|||
|
|
*/
|
|||
|
|
getSelectedNodeId(params) {
|
|||
|
|
const { treeCode = this.defaultTreeCode } = params ? params : {};
|
|||
|
|
let treeSelectedNodeId = this.state.treeSelectedNodeId;
|
|||
|
|
if (!treeSelectedNodeId) {
|
|||
|
|
treeSelectedNodeId = {};
|
|||
|
|
}
|
|||
|
|
return treeSelectedNodeId[treeCode];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
设置选中节点ID
|
|||
|
|
*/
|
|||
|
|
setSelectedNodeId({ treeCode, id, onComplete }) {
|
|||
|
|
let treeSelectedNodeId = this.state.treeSelectedNodeId;
|
|||
|
|
if (!treeSelectedNodeId) {
|
|||
|
|
treeSelectedNodeId = {};
|
|||
|
|
}
|
|||
|
|
if (treeCode === undefined) {
|
|||
|
|
treeCode = this.defaultTreeCode;
|
|||
|
|
}
|
|||
|
|
treeSelectedNodeId = {
|
|||
|
|
...treeSelectedNodeId,
|
|||
|
|
[treeCode]: id
|
|||
|
|
};
|
|||
|
|
this.setState({
|
|||
|
|
treeSelectedNodeId
|
|||
|
|
}, () => {
|
|||
|
|
if (typeof onComplete === 'function') {
|
|||
|
|
onComplete();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取树节点标题
|
|||
|
|
*/
|
|||
|
|
getTreeNodeTitle({ treeCode, titleColumns, data }) {
|
|||
|
|
if (data.isAdd) {
|
|||
|
|
return '新增节点';
|
|||
|
|
}
|
|||
|
|
if (!titleColumns) {
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode });
|
|||
|
|
if (treeConfig) {
|
|||
|
|
titleColumns = treeConfig.titleColumns;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (titleColumns && titleColumns.length) {
|
|||
|
|
let title = '';
|
|||
|
|
titleColumns.forEach(t => {
|
|||
|
|
let tmpValue = getDataFieldValue(data, t.field);
|
|||
|
|
tmpValue = tmpValue == null || tmpValue == undefined ? '' : tmpValue;
|
|||
|
|
title += tmpValue + "/";
|
|||
|
|
});
|
|||
|
|
title = title.substring(0, title.length - 1);
|
|||
|
|
return title;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
树拖拽
|
|||
|
|
{treeCode:树编号,dragId:当前拖拽的节点ID,dragParentId:拖拽后节点父节点ID,
|
|||
|
|
originDragParentId:原始节点父节点ID,dropId:拖拽到节点ID(一般不用)}
|
|||
|
|
*/
|
|||
|
|
onTreeDrop({ treeCode, dragId, dragParentId, originDragParentId, dropId }) {
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
/*
|
|||
|
|
获取选中节点标题
|
|||
|
|
*/
|
|||
|
|
getTreeNodeSelectedTitle(params) {
|
|||
|
|
const { treeCode = this.defaultTreeCode } = params ? params : {};
|
|||
|
|
let data = null;
|
|||
|
|
const selectId = this.getSelectedNodeId({ treeCode });
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode });
|
|||
|
|
if (selectId) {
|
|||
|
|
const treeData = this.getTreeData({ treeCode });
|
|||
|
|
this.getTreeDataById(
|
|||
|
|
treeData,
|
|||
|
|
selectId,
|
|||
|
|
(nodeData) => {
|
|||
|
|
data = nodeData;
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
if (data) {
|
|||
|
|
if (data.isAdd) {
|
|||
|
|
return '新增节点';
|
|||
|
|
}
|
|||
|
|
if (treeConfig && treeConfig.titleColumns && treeConfig.titleColumns.length) {
|
|||
|
|
return this.getTreeNodeTitle({ treeCode, titleColumns: treeConfig.titleColumns, data });
|
|||
|
|
}
|
|||
|
|
return data.NAME;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/*
|
|||
|
|
选中树节点
|
|||
|
|
*/
|
|||
|
|
selectTreeNode = (params) => {
|
|||
|
|
const { treeCode = this.defaultTreeCode, id } = params ? params : {};
|
|||
|
|
if (id) {
|
|||
|
|
const treeData = this.getTreeData({ treeCode });
|
|||
|
|
this.getTreeDataById(treeData, id, (ret) => {
|
|||
|
|
this.setSelectedNodeId({
|
|||
|
|
treeCode,
|
|||
|
|
id,
|
|||
|
|
onComplete: () => {
|
|||
|
|
this.onSelectedTreeNode({
|
|||
|
|
...params,
|
|||
|
|
treeCode,
|
|||
|
|
data: ret,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.setSelectedNodeId({
|
|||
|
|
treeCode,
|
|||
|
|
id,
|
|||
|
|
onComplete: () => {
|
|||
|
|
this.onSelectedTreeNode({
|
|||
|
|
...params,
|
|||
|
|
treeCode,
|
|||
|
|
data: null,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
选中树节点事件
|
|||
|
|
*/
|
|||
|
|
onSelectedTreeNode(params) {
|
|||
|
|
const { treeCode, id, data } = params ? params : {};
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
设置展开树键值
|
|||
|
|
*/
|
|||
|
|
setTreeExpandedKeys({ treeCode, expandedKeys, onComplete }) {
|
|||
|
|
if (treeCode === undefined) {
|
|||
|
|
treeCode = this.defaultTreeCode;
|
|||
|
|
}
|
|||
|
|
let treeExpandedKeys = this.state.treeExpandedKeys;
|
|||
|
|
if (!treeExpandedKeys) {
|
|||
|
|
treeExpandedKeys = {};
|
|||
|
|
}
|
|||
|
|
treeExpandedKeys = {
|
|||
|
|
...treeExpandedKeys,
|
|||
|
|
[treeCode]: expandedKeys,
|
|||
|
|
};
|
|||
|
|
this.setState({
|
|||
|
|
treeExpandedKeys
|
|||
|
|
}, () => {
|
|||
|
|
if (typeof onComplete === 'function') {
|
|||
|
|
onComplete();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取右键菜单
|
|||
|
|
*/
|
|||
|
|
getTreeNodeContextMenu(params) {
|
|||
|
|
const { data, treeCode = this.defaultTreeCode } = params ? params : {};
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode });
|
|||
|
|
const selectId = this.getSelectedNodeId({ treeCode });
|
|||
|
|
if (treeConfig) {
|
|||
|
|
//添加同级菜单按钮到列表中
|
|||
|
|
if (treeConfig.btns) {
|
|||
|
|
const index = treeConfig.btns.findIndex(t => t.btnType === 3);
|
|||
|
|
const index2 = treeConfig.btns.findIndex(t => t.btnType === 3 && t.isAddChild);
|
|||
|
|
if (index !== -1 && index2 === -1) {
|
|||
|
|
const item = treeConfig.btns[index];
|
|||
|
|
treeConfig.btns.splice(index, 0, { ...item, id: guid(), pId: item.id, isAddChild: true });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return <Menu className={styles.contextMenuList}>
|
|||
|
|
{
|
|||
|
|
treeConfig.btns ? treeConfig.btns.map(t => {
|
|||
|
|
if (t.btnType === undefined) return null;
|
|||
|
|
if (t.isRule && !permissionUtils(this.props.login).checkBtn(treeConfig.formId, (t.pId ? t.pId : t.id))) return null;
|
|||
|
|
if (!this.showBtn(t, data)) return null;
|
|||
|
|
if (t.btnType === 3) {//新增
|
|||
|
|
if (t.isAddChild) {
|
|||
|
|
return <Menu.Item key="sibling" onClick={() => this.addTreeNode({ treeCode, level: 'parent', id: data.ID })} disabled={data.isAdd || t.disabled || selectId !== data.ID}>
|
|||
|
|
<Icon type="plus" />新增同级
|
|||
|
|
</Menu.Item>
|
|||
|
|
}
|
|||
|
|
return <Menu.Item key="next" onClick={() => this.addTreeNode({ treeCode, level: 'childred', id: data.ID })} disabled={data.isAdd || t.disabled || selectId !== data.ID}>
|
|||
|
|
<Icon type="plus" />新增下级
|
|||
|
|
</Menu.Item>
|
|||
|
|
}
|
|||
|
|
else if (t.btnType === 4) {//删除
|
|||
|
|
return <Menu.Item key="del" onClick={() => this.deleteTreeNode({ treeCode, id: data.ID })} disabled={t.disabled || selectId !== data.ID}>
|
|||
|
|
<Icon type="delete" />删除
|
|||
|
|
</Menu.Item>
|
|||
|
|
}
|
|||
|
|
else if (t.btnType === 10) {//复制新增
|
|||
|
|
return <Menu.Item key={'copy'} onClick={() => this.addTreeNode({ treeCode, level: 'parent', id: data.ID, isCopy: true })}
|
|||
|
|
disabled={data.isAdd || !selectId || t.disabled || selectId !== data.ID}>
|
|||
|
|
<Icon type="copy" />复制新增
|
|||
|
|
</Menu.Item>
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}) : null
|
|||
|
|
}
|
|||
|
|
{
|
|||
|
|
this.onTreeNodeContextMenu({ ...params, treeConfig })
|
|||
|
|
}
|
|||
|
|
</Menu>;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
showBtn = (t, nodeData) => {
|
|||
|
|
let isshow = false;
|
|||
|
|
if (!t.btn_condition) {
|
|||
|
|
isshow = true;
|
|||
|
|
} else {
|
|||
|
|
isshow = false;
|
|||
|
|
const conditions = t.btn_condition.split('|');
|
|||
|
|
for (let condition of conditions) {
|
|||
|
|
const fields = condition.split(',');
|
|||
|
|
const val = getDataFieldValue(nodeData, fields[0]);
|
|||
|
|
if (parseInt(fields[1], 10) === 1 && String(val) === String(fields[2])) {
|
|||
|
|
isshow = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return isshow
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取树节点右击菜单
|
|||
|
|
{
|
|||
|
|
data, //节点数据
|
|||
|
|
treeCode,//树编号
|
|||
|
|
treeConfig//树配置信息
|
|||
|
|
}
|
|||
|
|
*/
|
|||
|
|
onTreeNodeContextMenu(params) {
|
|||
|
|
const { data, treeCode, treeConfig } = params ? params : {};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
新增树节点
|
|||
|
|
*/
|
|||
|
|
addTreeNode({ treeCode, isCopy, level, id }) {
|
|||
|
|
let treeData = this.getTreeData({ treeCode });
|
|||
|
|
if(!treeData){
|
|||
|
|
treeData=[];
|
|||
|
|
}
|
|||
|
|
const newId = guid();
|
|||
|
|
const menuKey = 'treeNodeMenuKey_' + treeCode + '_' + id;//右击菜单键值 用于菜单隐藏
|
|||
|
|
const data = { ID: newId, IS_LEAF: true, isAdd: true };
|
|||
|
|
let treeExpandedKeys = this.state.treeExpandedKeys;//展开键值列表
|
|||
|
|
if (!treeExpandedKeys) {
|
|||
|
|
treeExpandedKeys = {};
|
|||
|
|
}
|
|||
|
|
let parentId = null;
|
|||
|
|
if (level === 'parent') {//新增当前节点同级
|
|||
|
|
this.getTreeParentById(treeData, id, (parent) => {
|
|||
|
|
if (parent) {
|
|||
|
|
parentId = parent.ID;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else if (level === 'childred') {//新增当前节点下级
|
|||
|
|
parentId = id;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除前一次增加未保存项
|
|||
|
|
function delAdding(loop) {
|
|||
|
|
if (loop) {
|
|||
|
|
loop.forEach((item, key) => {
|
|||
|
|
if (item.hasOwnProperty("isAdd") && item["isAdd"]) {
|
|||
|
|
loop.splice(key, 1);
|
|||
|
|
}
|
|||
|
|
if (item.Children) {
|
|||
|
|
delAdding(item.Children)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
delAdding(treeData);
|
|||
|
|
|
|||
|
|
//添加到树数据中
|
|||
|
|
this.addTreeDataByParentId(treeData, parentId, data);
|
|||
|
|
|
|||
|
|
if (parentId) {
|
|||
|
|
let tempKeys = treeExpandedKeys[treeCode];
|
|||
|
|
if (!tempKeys) {
|
|||
|
|
tempKeys = [];
|
|||
|
|
}
|
|||
|
|
tempKeys.push(parentId);
|
|||
|
|
treeExpandedKeys = {
|
|||
|
|
...treeExpandedKeys,
|
|||
|
|
[treeCode]: tempKeys,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
let numArr = treeData
|
|||
|
|
let num = 0;
|
|||
|
|
if (parentId) {
|
|||
|
|
// 找跟自己同级的节点,并分配NUM
|
|||
|
|
const findChildren = function (arr, targetId) {
|
|||
|
|
const find = arr.find(ar => ar.ID === targetId)
|
|||
|
|
if (find && find.Children && find.Children.length) {
|
|||
|
|
numArr = find.Children
|
|||
|
|
} else {
|
|||
|
|
for (let i = 0, j = arr.length; i < j; i++) {
|
|||
|
|
if (arr[i].Children && arr[i].Children.length) {
|
|||
|
|
findChildren(arr[i].Children, targetId)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
findChildren(treeData, parentId)
|
|||
|
|
}
|
|||
|
|
if (numArr) {
|
|||
|
|
numArr.forEach((n, i) => {
|
|||
|
|
if (n.NUM && n.NUM > num) {
|
|||
|
|
num = n.NUM;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
num++;
|
|||
|
|
data.NUM = num;
|
|||
|
|
data.PARENT_ID = parentId;
|
|||
|
|
let copySrcId = '';
|
|||
|
|
if (isCopy) {
|
|||
|
|
copySrcId = id;
|
|||
|
|
}
|
|||
|
|
this.setState({
|
|||
|
|
treeExpandedKeys,
|
|||
|
|
[menuKey]: false,
|
|||
|
|
copySrcId,
|
|||
|
|
}, () => {
|
|||
|
|
this.setTreeData({
|
|||
|
|
treeCode, data: treeData, onComplete: () => {
|
|||
|
|
this.selectTreeNode({ treeCode, isAdd: true, id: newId });
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
this.onAfterAddTreeNode({ treeCode, newId, parentId, id, isCopy, newData: data, });
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
新增树节点 后
|
|||
|
|
treeCode,
|
|||
|
|
newId, //新增节点ID
|
|||
|
|
parentId,//新增节点的父节点ID
|
|||
|
|
id,//来源节点ID 可能为空
|
|||
|
|
isCopy,//是否拷贝
|
|||
|
|
newData,//新增节点数据
|
|||
|
|
*/
|
|||
|
|
onAfterAddTreeNode(params) {
|
|||
|
|
const { treeCode, newId, parentId, id, isCopy, newData } = params;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
删除树节点
|
|||
|
|
*/
|
|||
|
|
deleteTreeNode(params) {
|
|||
|
|
const { treeCode = this.defaultTreeCode, id } = params ? params : {};
|
|||
|
|
const menuKey = 'treeNodeMenuKey_' + treeCode + '_' + id;//右击菜单键值 用于菜单隐藏
|
|||
|
|
this.setState({
|
|||
|
|
[menuKey]: false,
|
|||
|
|
});
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode });
|
|||
|
|
if (treeConfig) {
|
|||
|
|
const { deleteApi } = treeConfig;
|
|||
|
|
const doDeleteTreeNode = () => {
|
|||
|
|
const treeData = this.getTreeData({ treeCode });
|
|||
|
|
let nodeData = null;
|
|||
|
|
this.deleteTreeDataById(treeData, id, null, (d) => {
|
|||
|
|
nodeData = d;
|
|||
|
|
});
|
|||
|
|
if (deleteApi) {
|
|||
|
|
this.addDeleteLog({ formCode: treeConfig.formCode, ids: id, formId: treeConfig.formId, extData: ('删除数据,详情:' + (nodeData ? JSON.stringify(nodeData) : '')) });
|
|||
|
|
}
|
|||
|
|
this.setState({
|
|||
|
|
parentId: '',
|
|||
|
|
}, () => {
|
|||
|
|
this.selectTreeNode({ treeCode, id: null });
|
|||
|
|
this.onAfterDeleteTreeNode({ treeCode, id });
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
if (deleteApi) {
|
|||
|
|
this.props.dispatch({
|
|||
|
|
type: 'app/deleteItemBatch',
|
|||
|
|
payload: {
|
|||
|
|
ids: id
|
|||
|
|
},
|
|||
|
|
url: deleteApi,
|
|||
|
|
onComplete: (ret) => {
|
|||
|
|
if (ret) {
|
|||
|
|
message.success('删除成功');
|
|||
|
|
doDeleteTreeNode();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
doDeleteTreeNode();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
删除树节点 后
|
|||
|
|
{
|
|||
|
|
treeCode,树编号
|
|||
|
|
id//删除节点ID
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
*/
|
|||
|
|
onAfterDeleteTreeNode(params) {
|
|||
|
|
const { treeCode, id } = params ? params : {};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
根据树编号渲染树
|
|||
|
|
*/
|
|||
|
|
getRenderTreeByConfig(treeCode) {
|
|||
|
|
if (treeCode === undefined) {
|
|||
|
|
treeCode = this.defaultTreeCode;
|
|||
|
|
}
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode });
|
|||
|
|
if (treeConfig) {
|
|||
|
|
const treeData = this.getTreeData({ treeCode });
|
|||
|
|
const hasData = treeData && treeData.length;
|
|||
|
|
const { formCode, queryCode, sort, order, titleColumns, draggable } = treeConfig;
|
|||
|
|
const title = this.getTreeNodeSelectedTitle({ treeCode });
|
|||
|
|
const expandedKeys = this.state.treeExpandedKeys[treeCode];
|
|||
|
|
const selectedId = this.getSelectedNodeId({ treeCode });
|
|||
|
|
return <div className={styles.treeBox}>
|
|||
|
|
<Search formCode={formCode} code={queryCode} onSearch={(value) => this.onLoadTreeData({ treeCode, searchValue: value })} />
|
|||
|
|
{
|
|||
|
|
hasData
|
|||
|
|
? <div className={styles.tipToContextMenu}>右键[添加/修改]</div>
|
|||
|
|
: <div className={`${styles.tipToContextMenu} ${styles.addNode}`} onClick={() => this.addTreeNode({ treeCode, level: 'all', id: null })}><Icon type="plus" />新增</div>
|
|||
|
|
}
|
|||
|
|
{
|
|||
|
|
title
|
|||
|
|
&& <Alert message={<span>当前选中:{title}</span>} type="success" />
|
|||
|
|
}
|
|||
|
|
{
|
|||
|
|
hasData
|
|||
|
|
? this.getRenderTree({
|
|||
|
|
data: treeData, //数据
|
|||
|
|
treeCode,//树编号
|
|||
|
|
onLoadData: (({ treeCode: tempTreeCode, treeNode }) => {//加载数据事件
|
|||
|
|
return this.onLoadTreeChildData({
|
|||
|
|
treeCode: tempTreeCode,
|
|||
|
|
treeNode
|
|||
|
|
});
|
|||
|
|
}),
|
|||
|
|
onSelect: (params => {//选中节点事件
|
|||
|
|
this.selectTreeNode(params);
|
|||
|
|
}),
|
|||
|
|
expandedKeys,//已展开直接列表
|
|||
|
|
selectedId,//当前选中节点ID
|
|||
|
|
onExpand: ({ expandedKeys }) => {//展开事件
|
|||
|
|
this.setTreeExpandedKeys({ treeCode, expandedKeys });
|
|||
|
|
},
|
|||
|
|
sort,//排序字段
|
|||
|
|
order,//排序类型
|
|||
|
|
onContextMenu: (params) => {//获取节点右击菜单列表事件
|
|||
|
|
return this.getTreeNodeContextMenu({ ...params, treeCode });
|
|||
|
|
},
|
|||
|
|
getTreeNodeTitle: ({ data }) => {//获取节点标题函数
|
|||
|
|
return this.getTreeNodeTitle({ treeCode, titleColumns, data });
|
|||
|
|
},
|
|||
|
|
draggable,//是否拖拽
|
|||
|
|
onDrop: (updateData, dragId, dragParentId, dropId, originDragParentId) => {//拖拽事件
|
|||
|
|
this.setTreeData({
|
|||
|
|
treeCode, data: updateData, onComplete: () => {
|
|||
|
|
this.onTreeDrop({ treeCode, dragId, dragParentId, dropId, originDragParentId });
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
}) : <div style={{ textAlign: "center" }}>无数据</div>
|
|||
|
|
}
|
|||
|
|
</div>
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
render() {
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
</div>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default TreeBaseComponent;
|