You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
salary-management-oneself/src/pages/salaryItemDiagram/index.tsx

193 lines
5.4 KiB
TypeScript

/*
* Author: 黎永顺
* name: 薪资项目-拓扑图
* Description:
* Date: 2023/10/19
*/
import React, { FunctionComponent, useEffect, useMemo, useState } from "react";
import { DecompositionTreeGraph, NodeConfig } from "@ant-design/graphs";
import { notification } from "antd";
import { exceptStr } from "@/utils/common";
import API from "@/api";
// @ts-ignore
import uuidV4 from "uuid/v4";
interface OwnProps {
}
type Props = OwnProps;
const index: FunctionComponent<Props> = (props) => {
const [dataSource, setDataSource] = useState<any>({});
const [i18n, setI18n] = useState<any>({});
useEffect(() => {
window.parent.postMessage({ type: "initDiagram" }, "*");
window.addEventListener("message", receiveMessageFromIndex, false);
return () => {
window.removeEventListener("message", receiveMessageFromIndex, false);
};
}, []);
const receiveMessageFromIndex = (event: any) => {
const data: any = exceptStr(event.data);
if (!_.isEmpty(data)) {
const { i18n, acctEmpId, salaryItemId, salarySobId } = data;
setI18n(i18n);
init({ acctEmpId, salaryItemId, salarySobId });
}
};
const init = (paylaod: any) => {
API.CalculateService.getSalarysobItemTopology(paylaod).then(({ data }) => {
const { status, data: result } = data;
if (status) {
const dataSource = {
id: result.salaryItemId.toString(),
value: { title: result.salaryItemName, formula: result.formula, items: [{ text: result.result }] },
children: !_.isEmpty(result.children) ? traverse(result.children) : []
};
setDataSource(dataSource);
}
});
};
const getChildren = async (nodeCfg: NodeConfig) => {
return findChildren(extractTree(dataSource.children), nodeCfg.id);
};
const openNotification = (data: any) => {
const { value: { formula } } = data;
notification.destroy();
if (_.isEmpty(formula)) return;
const { formula: description } = formula;
notification.open({
message: i18n["公式"],
duration: 5,
description,
style: { maxWidth: 600 }
});
};
const component: any = useMemo(() => {
const config = {
data: {
...dataSource,
children: dataSource.children ? _.map(dataSource.children, o => ({ ...o, children: null })) : null
},
autoFit: false, animate: true,
nodeCfg: {
getChildren,
autoWidth: true,
title: {
style: { fill: "#333" },
containerStyle: () => {
return {
fill: "#f7fbfe",
stroke: "#e5e5e5"
};
}
},
nodeStateStyles: {
hover: {
stroke: '#e5e5e5',
lineWidth: 1,
},
},
items: {
style: (cfg: any, group: any, type: string) => {
const styles = {
value: { fill: "#333" }
};
return styles[type];
}
},
style: {
stroke: "#e5e5e5"
}
},
markerCfg: (cfg: any) => {
const { g_level, id } = cfg;
return {
show: (g_level === 0 && !_.isEmpty(dataSource.children)) || getStorageIds(dataSource.children).includes(id)
};
},
onReady: (graph: any) => {
graph.on("node:click", (evt: any) => {
if (_.isEmpty(evt.target.attrs) || JSON.stringify(evt.target.attrs).indexOf("cursor") !== -1) return;
openNotification(evt.item._cfg.model);
});
setTimeout(() => {
graph.zoom(1);
});
},
behaviors: ["drag-canvas", "zoom-canvas"]
};
// @ts-ignore
return !_.isEmpty(dataSource) ? <DecompositionTreeGraph {...config} /> : null;
}, [dataSource]);
return component;
};
export default index;
const traverse: any = (arr: any[]) => {
return _.map(arr, item => {
if (!_.isEmpty(item.children)) {
const uuid = uuidV4();
return {
id: uuid,
value: { title: item.salaryItemName, formula: item.formula, items: [{ text: item.result }] },
children: traverse(item.children)
};
} else {
const uuid = uuidV4();
return {
id: uuid, value: { title: item.salaryItemName, formula: item.formula, items: [{ text: item.result }] }
};
}
});
};
const findChildren: any = (arr: any[], id: string) => {
const dataSource = _.find(arr, o => o.id === id).children;
return _.map(dataSource, o => ({ ...o, children: [] }));
};
/*
* Author: 黎永顺
* Description:数组扁平换
* Params:
* Date: 2023/10/26
*/
export const extractTree = (data: any[]) => {
if (!data.length) return [];
const list: any[] = [];
const getObj = (arr: any[]) => {
arr.forEach((row: any) => {
let obj = {};
obj = JSON.parse(JSON.stringify(row));
list.push(obj);
if (row.children) {
getObj(row.children);
}
});
return list;
};
return getObj(data);
};
/*
* Author: 黎永顺
* Description: 有children子集的id集合
* Params:
* Date: 2023/10/26
*/
const getStorageIds = (array: any[]) => {
let ids: any = [];
const getIds = (array: any, ids: any) => {
array.forEach((item: any) => {
if (item.children) ids.push(item.id);
if (item.children) ids = getIds(item.children, ids);
});
return ids;
};
if (Array.isArray(array)) {
if (array.length === 0) return [];
} else {
return [];
}
ids = getIds(array, ids);
return ids;
};