mh_jy_safe_web/src/baseComponents/TreeBaseComponent/index.js
2025-08-25 10:08:30 +08:00

766 lines
21 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;