mh_jy_safe_web/src/baseComponents/TreeBaseComponent/index.js

766 lines
21 KiB
JavaScript
Raw Normal View History

2025-08-25 10:08:30 +08:00
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;