Compare commits

...

9 Commits

@ -7,7 +7,7 @@ export default defineConfig({
antd: false,
// base: '/slave',
// publicPath: '/slave/static/',
base: '/spa/hrmSalary/hrmSalaryCalculateDetail/',
base: '/spa/personnelReport/',
publicPath: './',
externals: {
echarts: 'echarts',

@ -20,13 +20,17 @@
]
},
"dependencies": {
"@ant-design/charts": "^1.4.2",
"@ant-design/pro-layout": "6.32.1",
"@formily/antd": "^2.0.6",
"@jiaminghi/data-view-react": "^1.2.5",
"@types/lodash": "^4.14.172",
"@ztree/ztree_v3": "^3.5.42",
"ahooks": "^3.1.3",
"antd": "^4.17.3",
"axios": "^0.22.0",
"echarts": "^4.9.0",
"echarts-gl": "^1.1.2",
"fbemitter": "^3.0.0",
"js-base64": "^3.6.1",
"js-cookie": "^2.2.1",
@ -57,7 +61,6 @@
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
"@umijs/plugin-access": "2.4.2",
"umi-plugin-authorize": "^2.8.12",
"@umijs/plugin-dva": "^0.13.0",
"@umijs/plugin-initial-state": "^2.4.0",
"@umijs/plugin-locale": "^0.15.0",
@ -70,6 +73,7 @@
"prettier": "^2.2.0",
"typescript": "^4.3.5",
"umi": "^3.5.20",
"umi-plugin-authorize": "^2.8.12",
"yorkie": "^2.0.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

@ -0,0 +1,172 @@
@node-color: #1890ff;
@line-width: 1px;
@line-color: @node-color;
@expand-icon-size: 16px;
.text-overflow-ellipsis() {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.org-chart {
&-container {
display: flex;
justify-content: center;
margin-top: 26px;
}
&-table {
border-collapse: separate;
border-spacing: 0;
line-height: 1.5715;
.expand-icon {
display: inline-block;
width: @expand-icon-size;
height: @expand-icon-size;
border-radius: 50%;
background-color: @line-color;
position: absolute;
left: 50%;
bottom: 0;
margin-left: -@expand-icon-size / 2;
margin-bottom: -@expand-icon-size / 2;
z-index: 99;
cursor: pointer;
&-expanded,
&-collapsed {
&::before {
content: '';
width: 8px;
height: 2px;
background-color: #fff;
position: absolute;
top: 7px;
left: 4px;
}
}
&-collapsed {
&::after {
content: '';
width: 2px;
height: 8px;
background-color: #fff;
position: absolute;
top: 4px;
left: 7px;
}
}
&:hover {
background-color: darken(@line-color, 5%);
}
}
td {
text-align: center;
padding: 0;
vertical-align: top;
&.hidden {
display: none !important;
}
}
&-node {
display: inline-block;
//border: 1px solid @node-color;
//padding: 0.5rem;
margin: 0 5px;
cursor: pointer;
}
&-line {
height: 20px;
position: relative;
&:not(&-children) {
&:before {
content: '';
position: absolute;
top: 0;
width: @line-width;
height: 100%;
background-color: @line-color;
}
}
&-children {
&:nth-child(odd) {
border-right: @line-width solid @line-color;
}
&:not(:first-child, :last-child) {
border-top: @line-width solid @line-color;
}
}
}
// 水平
&&-horizontal {
.expand-icon {
top: 50%;
bottom: auto;
left: auto;
right: 0;
margin: -@expand-icon-size / 2 -@expand-icon-size / 2 auto auto;
}
td {
vertical-align: middle;
}
tr {
&:nth-child(odd) {
> .org-chart-table-line-children {
border-bottom: @line-width solid @line-color;
}
}
&:not(:first-child, :last-child) {
> .org-chart-table-line-children {
border-left: @line-width solid @line-color;
}
}
}
.org-chart-table {
&-node {
margin: 5px 0;
width: 120px;
&-content {
.text-overflow-ellipsis();
}
}
&-line {
height: auto;
width: 20px;
&:not(&-children) {
&:before {
top: auto;
left: 0;
width: 100%;
height: @line-width;
}
}
&-children {
&:nth-child(odd),
&:not(:first-child, :last-child) {
border: none;
}
}
}
}
}
}
}

@ -0,0 +1,31 @@
import classNames from "classnames";
import React from "react";
import { OrgChartProps } from "./interface";
import OrgChartNode from "./components/OrgChartNode";
import ChartWrapper from "./components/ChartWrapper";
import styles from "./OrgChart.less";
const OrgChart = (props: OrgChartProps) => {
const { data, className, style, pan, zoom, maxZoom,minZoom,zoomStep, ...otherProps } = props;
return !!data ? (
<ChartWrapper
pan={pan}
zoom={zoom}
maxZoom={maxZoom}
minZoom={minZoom}
zoomStep={zoomStep}
>
<div className={classNames(styles["org-chart-container"], className)} style={style}>
<OrgChartNode {...otherProps} data={data}/>
</div>
</ChartWrapper>
) : null;
};
OrgChart.defaultProps = {
direction: "vertical",
expandAll: true,
expandable: false
};
export default OrgChart;

@ -0,0 +1,126 @@
import React from "react";
import styles from "../OrgChart.less";
const clsPrefix = "cp-react-org-chart-chart-wrapper";
export default class ChartWrapper extends React.PureComponent {
static propTypes = {};
static defaultProps = {
maxZoom: 2,
minZoom: 0.5,
zoomStep: 0.03
};
state = {
scale: 1,
isMove: false,
translateX: 0,
translateY: 0,
originX: 0,
originY: 0
};
componentDidMount() {
document.addEventListener("mousemove", this.onMouseMove);
}
componentWillUnmount() {
document.removeEventListener("mousemove", this.onMouseMove);
}
onZoom = e => {
const { zoom, maxZoom, minZoom, zoomStep } = this.props;
if (!zoom) return;
const { deltaY, pageX, pageY } = e;
const { offsetWidth, offsetHeight } = this.wrapper;
let { scale } = this.state;
const { translateX, translateY } = this.state;
if (deltaY < 0 && scale < maxZoom) {
scale += zoomStep;
}
if (deltaY > 0 && scale > minZoom) {
scale -= zoomStep;
}
this.setState({
scale,
originX: pageX,
originY: pageY
});
};
toggleMove(isMove) {
this.setState({ isMove });
}
onMouseDown = e => {
this.toggleMove(true);
const { pageX, pageY } = e;
const { translateX, translateY } = this.state;
this.pageX = pageX;
this.pageY = pageY;
this.translateX = translateX;
this.translateY = translateY;
};
onMouseUp = e => {
this.toggleMove(false);
};
onMouseMove = e => {
const { isMove, scale } = this.state;
if (!isMove) return;
const { pageX, pageY } = e;
const x = (pageX - this.pageX) / scale + this.translateX;
const y = (pageY - this.pageY) / scale + this.translateY;
this.setState({
translateX: x,
translateY: y
});
};
getProps() {
const { zoom, pan } = this.props;
const props = {};
if (zoom) {
props.onWheel = this.onZoom;
}
if (pan) {
props.onMouseUp = this.onMouseUp;
props.onMouseDown = this.onMouseDown;
props.onMouseMove = this.onMouseMove;
}
return props;
}
render() {
const { children } = this.props;
const { scale, translateX, translateY, isMove, originX, originY } = this.state;
const cursor = isMove ? "move" : "default";
const props = this.getProps();
return (
<div className={styles[clsPrefix]} style={{ overflow: "hidden", flex: 1 }}>
<div
ref={node => {
this.wrapper = node;
}}
style={{
cursor,
transform: `scale(${scale}) translate(${translateX}px, ${translateY}px)`,
transformOrigin: `${originX}px ${originY}px`
}}
className={styles["chart-wrapper-main"]}
{...props}
>
{children}
</div>
</div>
);
}
}

@ -0,0 +1,180 @@
import classNames from "classnames";
import React from "react";
import { OrgChartNodeDataType, OrgChartNodeProps, RowProps } from "../interface";
import OrgChartNodeRow from "./OrgChartNodeRow";
import styles from "../OrgChart.less";
const OrgChartNode = (props: OrgChartNodeProps) => {
const {
data,
expandAll,
expandable,
direction,
renderNode,
onExpand,
onClick
} = props;
const [expanded, setExpanded] = React.useState<boolean>(false);
const handleExpandChange = () => {
const newExpanded = !expanded;
setExpanded(newExpanded);
onExpand?.(newExpanded, data);
};
const getOrgNodeRow = (
span: number,
data: OrgChartNodeDataType
): RowProps => {
const contentNode: React.ReactNode = (
<div className={styles["org-chart-table-node-content"]} title={data.label}>
{data.label}
</div>
);
return [
{
span,
content: (
<td>
<div
className={classNames(styles["org-chart-table-node"], data.className)}
style={data.style}
onClick={() => onClick?.(data)}>
{!!renderNode ? renderNode(data, contentNode) : contentNode}
</div>
</td>
)
}
];
};
const getLineRow = (span: number): RowProps => {
return [
{
span,
content: (
<td className={styles["org-chart-table-line"]}>
{expandable ? (
<div
className={classNames({
[styles["expand-icon"]]: expandable,
[styles["expand-icon-expanded"]]: expandable && expanded,
[styles["expand-icon-collapsed"]]: expandable && !expanded
})}
onClick={() => handleExpandChange()}></div>
) : null}
</td>
)
}
];
};
const getChildrenLineRow = (span: number, itemSpan: number): RowProps => {
const cells: RowProps = [];
for (let index = 0; index < span; index = index + itemSpan) {
cells.push({
span: 1,
content: (
<td
key={index}
className={classNames(
styles["org-chart-table-line"],
styles["org-chart-table-line-children"],
{
[styles["hidden"]]: !expanded
}
)}>
&nbsp;
</td>
)
});
}
return cells;
};
const getChildrenNode = (
datas: OrgChartNodeDataType[] = [],
itemSpan: number
): RowProps => {
const cells: RowProps = [];
datas.forEach((data, index) => {
cells[itemSpan * index] = {
span: itemSpan,
content: (
<td
key={data.key}
className={classNames(styles["org-chart-table-node-children"], {
[styles["hidden"]]: !expanded
})}>
<OrgChartNode {...props} data={data}/>
</td>
)
};
});
return cells;
};
const getRows = (): RowProps[] => {
if (data) {
const rows: RowProps[] = [];
const childrenLength = data?.children?.length || 0;
const span = childrenLength * 2;
rows.push(getOrgNodeRow(span, data));
// 判断是否有子节点
if (data.children?.length ?? 0 > 0) {
rows.push(getLineRow(span));
rows.push(getChildrenLineRow(span, 1));
rows.push(getChildrenNode(data.children, 2));
}
if (direction === "horizontal") {
const newRow: RowProps[] = [];
rows.forEach((row, rowIndex) => {
row.forEach((cell, cellIndex) => {
newRow[cellIndex] = newRow[cellIndex] || [];
newRow[cellIndex][rowIndex] = cell;
});
});
return newRow;
}
return rows;
}
return [];
};
const rows = React.useMemo(() => {
return getRows();
}, [data, expanded, direction]);
React.useEffect(() => {
if (expandable === true) {
setExpanded(!!expandAll);
} else {
setExpanded(true);
}
}, [expandAll, expandable]);
return (
<table
className={classNames(styles["org-chart-table"], {
[styles["org-chart-table-horizontal"]]: direction === "horizontal",
[styles["org-chart-table-vertical"]]: direction === "vertical"
})}>
<tbody>
{rows.map((row, index) => (
<OrgChartNodeRow
key={index}
index={index}
row={row}
direction={direction}
/>
))}
</tbody>
</table>
);
};
export default OrgChartNode;

@ -0,0 +1,27 @@
import { OrgChartNodeProps, RowProps } from '../interface';
import React from 'react';
export interface OrgChartNodeRowProps
extends Pick<OrgChartNodeProps, 'direction'> {
className?: string;
index: number;
row: RowProps;
}
const OrgChartNodeRow = (props: OrgChartNodeRowProps) => {
const { className, index, row, direction } = props;
return (
<tr key={index} className={className}>
{row.map((cell, cellIndex) => {
return React.cloneElement(cell.content, {
key: cellIndex,
...(direction === 'horizontal' ? { rowSpan: cell.span } : {}),
...(direction === 'vertical' ? { colSpan: cell.span } : {}),
});
})}
</tr>
);
};
export default OrgChartNodeRow;

@ -0,0 +1,5 @@
// import { OrgChartNodeDataType, OrgChartProps } from './interface';
import OrgChart from './OrgChart';
// export { OrgChartNodeDataType, OrgChartProps };
export default OrgChart;

@ -0,0 +1,43 @@
import React from "react";
export interface CellProps {
span: number;
content: React.ReactElement;
}
export type RowProps = CellProps[];
export interface OrgChartNodeDataType {
key: string | number;
label: string;
operatingIncome?: string;
operatingIncomePercent?: string;
operatingProfit?: string;
operatingProfitPercent?: string;
children?: OrgChartNodeDataType[];
className?: string;
style?: React.CSSProperties;
}
export interface OrgChartNodeProps {
data: OrgChartNodeDataType;
expandAll?: boolean;
expandable?: boolean;
direction?: "horizontal" | "vertical";
renderNode?: (
node: OrgChartNodeDataType,
originNode: React.ReactNode
) => React.ReactNode;
onExpand?: (expanded: boolean, node: OrgChartNodeDataType) => void;
onClick?: (node: OrgChartNodeDataType) => void;
}
export interface OrgChartProps extends Partial<OrgChartNodeProps> {
className?: string;
style?: React.CSSProperties;
pan?: boolean;
zoom?: boolean;
maxZoom?: number;
minZoom?: number;
zoomStep?: number;
}

@ -52,7 +52,7 @@ export type Route = {
} & MenuDataItem;
export type WithFalse<T> = T | false;
export type RouterTypes<P> = {
export type RouterTypes<P extends { [K in keyof P]?: string | undefined; }> = {
computedMatch?: match<P>;
route?: Route;
location: BasicRouteProps['location'] | { pathname?: string };

@ -11,6 +11,7 @@ module.exports = {
"/fileTable.*": "blank",
"/rankMapTable.*": "blank",
"/reportTable.*": "blank",
"/personnelReport.*": "blank",
"/manage.*": "manage",
"/portal.*": "template",
"/passport/oauth-in": "blank",

@ -15,6 +15,7 @@ import { layoutConfig } from "@/layouts/config";
import stores from "@/store";
import "moment/locale/zh-cn";
import "antd/dist/antd.variable.min.css";
// import "../utils/flexible";
moment.locale("zh-cn");

@ -0,0 +1,28 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/6
*/
import React, { FunctionComponent } from "react";
import styles from "./index.less";
interface OwnProps {
children: any;
title: string;
}
type Props = OwnProps;
const frameBox: FunctionComponent<Props> = (props) => {
const { children, title } = props;
return (
<div className={styles.frameBoxWrapper}>
<div className={styles.header}><span><span>{title}</span></span></div>
{children}
</div>
);
};
export default frameBox;

@ -0,0 +1,28 @@
.frameBoxWrapper {
display: flex;
flex-direction: column;
height: 100%;
.header {
height: 54px;
line-height: 54px;
width: 100%;
padding: 0 16px;
& > span {
display: inline-block;
font-size: 18px;
color: #333333;
letter-spacing: 0;
font-weight: 700;
width: 100%;
height: inherit;
border-bottom: 1px solid #e5e5e5;
span {
border-left: 5px solid #0055F3;
padding-left: 8px;
}
}
}
}

@ -0,0 +1,820 @@
import { G2 } from "@ant-design/plots";
const G = G2.getEngine("canvas");
export const structureCardList = [
{
title: "当期总人数",
active: 0,
number: 14338,
unit: "人",
color: "#FFBB31",
yoyVal: "4.75%",
chainVal: "1.75%",
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
tabList: ["本月", "上月"]
},
{
title: "本月入职",
active: 0,
number: 120,
unit: "人",
color: "#3DA5F6",
yoyVal: "3.75%",
chainVal: "4.75%",
yoyIcon: require("../../assets/images/up.png"),
chainIcon: require("../../assets/images/down.png"),
tabList: ["本月", "上月"]
},
{
title: "本月离职",
active: 0,
number: 40,
unit: "人",
color: "#5FD5C7",
yoyVal: "4.75%",
chainVal: "4.75%",
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
tabList: ["本月", "上月"]
},
{
title: "年度累计入职",
active: 0,
number: 238,
unit: "人",
color: "#2B6DF6",
yoyVal: "3.75%",
chainVal: "2.75%",
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
tabList: ["本年", "去年"]
},
{
title: "年度累计离职",
active: 0,
number: 198,
unit: "人",
color: "#B571EA",
yoyVal: "5.75%",
chainVal: "1.75%",
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/down.png"),
tabList: ["本年", "去年"]
},
{
title: "平均年龄",
active: 0,
number: 28.0,
unit: "岁",
color: "#5FCC7B",
yoyVal: "4.75%",
chainVal: "4.75%",
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
tabList: ["本年", "去年"]
}
];
export const frameCard1List = [
{
title: "离职人数",
number: 40,
unit: "人",
color: "#FFD887",
isLine: true,
departureVal: "28人",
refusal: "12人",
icon: require("../../assets/images/lzrs.png")
},
{
title: "离职率",
color: "",
icon: require("../../assets/images/lzl.png"),
number: "0.27",
unit: "%",
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
yoyVal: "4.75%",
chainVal: "1.75%",
isLine: false
// title: "在职人数",
// number: 14338,
// unit: "人",
// color: "#78C0F9",
// isLine: true,
// yoyIcon: require("../../assets/images/down.png"),
// chainIcon: require("../../assets/images/up.png"),
// yoyVal: "4.75%",
// chainVal: "4.75%",
// icon: require("../../assets/images/zzrs.png")
}
];
export const frameCard2List = [
{
title: "全员离职率",
icon: require("../../assets/images/qylzl.png"),
bg: require("../../assets/images/qylzl_bg.png"),
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
yoyVal: "2.75%",
chainVal: "4.75%",
actualValue: {
title: "实际值",
number: 0.22,
unit: "%"
},
contemValue: {
title: "同期值",
number: 0.45,
unit: "%"
}
},
{
title: "关键岗位离职率",
icon: require("../../assets/images/gjgwlzl.png"),
bg: require("../../assets/images/gjgwlzl_bg.png"),
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
yoyVal: "2.32%",
chainVal: "5.67%",
actualValue: {
title: "实际值",
number: 0.32,
unit: "%"
},
contemValue: {
title: "同期值",
number: 0.13,
unit: "%"
}
},
{
title: "绩优员工离职率",
icon: require("../../assets/images/jyyglzl.png"),
bg: require("../../assets/images/jyyglzl_bg.png"),
yoyIcon: require("../../assets/images/down.png"),
chainIcon: require("../../assets/images/up.png"),
yoyVal: "1.09%",
chainVal: "4.78%",
actualValue: {
title: "实际值",
number: 0.12,
unit: "%"
},
contemValue: {
title: "同期值",
number: 0.23,
unit: "%"
}
},
{
title: "培训管理分析",
icon: require("../../assets/images/pxglfx.png"),
bg: require("../../assets/images/pxglfx_bg.png"),
actualValue: {
title: "人均培训费用",
number: "2,266.00",
unit: "元"
},
contemValue: {
title: "人均培训时长",
number: 6,
unit: "小时"
}
}
];
export const personnelFlowTablist = ["全员离职率", "主动离职率", "被动离职率", "关键岗位离职率", "绩优员工离职率", "转正率"];
export const personRankingTablist = ["销售人员有效金额排名", "销售新客户有效金额排名(2022-01-01前入职)", "销售新客户有效金额排名(2022-01-01后入职)"];
export const trainingRankingList = [
{
avatar: require("../../assets/images/zcy.png"),
name: "赵晨雨",
dept: "南京EBU二部项目服务部",
score: "98分"
},
{
avatar: require("../../assets/images/lk.png"),
name: "李坤CZ",
dept: "项目管理部-常州",
score: "94分"
},
{
avatar: require("../../assets/images/zkw.png"),
name: "张开文",
dept: "青岛EBU一部",
score: "93分"
},
{
avatar: require("../../assets/images/zd.png"),
name: "张帝ZZ",
dept: "郑州EBU一部业务二部",
score: "92分"
},
{
avatar: require("../../assets/images/pjj.png"),
name: "潘俊杰",
dept: "南京EBU九部项目服务部",
score: "90分"
},
{
avatar: require("../../assets/images/lwl.png"),
name: "路卫亮",
dept: "河南易筑联合",
score: "88分"
},
{
avatar: require("../../assets/images/lt.png"),
name: "刘彤ZZ",
dept: "项目三部-郑州",
score: "87分"
},
{
avatar: require("../../assets/images/syr.png"),
name: "申衍茹",
dept: "客户服务部-郑州",
score: "85分"
},
{
avatar: require("../../assets/images/ycl.png"),
name: "殷存磊",
dept: "济南EBU四部",
score: "85分"
}
];
export const teamRankingList = [
{
avatar: require("../../assets/images/zbl.png"),
name: "左保林",
dept: "上海EBU二部业务六部",
score: "290.40%"
},
{
avatar: require("../../assets/images/ygf.png"),
name: "杨国福",
dept: "郑州EBU三部",
score: "75.50%"
},
{
avatar: require("../../assets/images/zcycd.png"),
name: "张晨阳(承德)",
dept: "销售管理部-承德",
score: "71.04%"
},
{
avatar: "",
name: "郭彦芳",
dept: "北京EBU十七部业务一部",
score: "58.18%"
},
{
avatar: "",
name: "郭晓龙",
dept: "北京EBU一部业务五部",
score: "53.85%"
}
];
export const humanRankingList = [
{
avatar: require("../../assets/images/lq.png"),
name: "梁倩",
dept: "上海EBU二部销售管理部",
score: "4,260,845.00"
},
{
avatar: require("../../assets/images/zy.png"),
name: "宗殷",
dept: "营销管理部-合肥",
score: "2,607,722.00"
},
{
avatar: require("../../assets/images/hc.png"),
name: "黄超",
dept: "上海EBU十五部销售部",
score: "2,213,232.00"
},
{
avatar: "",
name: "赵艳丽",
dept: "销售管理部-华南二部深圳EBU一部",
score: "2,164,522.00"
},
{
avatar: "",
name: "左文钟",
dept: "上海EBU一部业务四部",
score: "2,038,707.00"
}
];
export const humanRankingList_1 = [
{
avatar: require("../../assets/images/zy.png"),
name: "宗殷",
dept: "营销管理部-合肥",
score: "1,933,749"
},
{
avatar: require("../../assets/images/hc.png"),
name: "黄超",
dept: "上海EBU十五部销售部",
score: "1,857,431"
},
{
avatar: require("../../assets/images/zwz.jpg"),
name: "左文钟",
dept: "上海EBU一部业务四部",
score: "1,609,645"
},
{
avatar: "",
name: "杨艳(BJ)",
dept: "北京EBU一部销售部",
score: "1,295,972"
},
{
avatar: "",
name: "赵礼欢",
dept: "上海EBU七部业务六部销售部",
score: "1,294,900"
}
];
export const humanRankingList_2 = [
{
avatar: require("../../assets/images/nyk.jpg"),
name: "吕燕开",
dept: "北京EBU四部销售部",
score: "1,112,938"
},
{
avatar: require("../../assets/images/wyy.jpg"),
name: "吴洋洋",
dept: "北京EBU六部业务二部销售部",
score: "1,019,063"
},
{
avatar: require("../../assets/images/ljh.jpg"),
name: "罗家辉",
dept: "佛山EBU四部",
score: "737,100"
},
{
avatar: "",
name: "张宇航",
dept: "石家庄EBU四部销售部",
score: "681,590"
},
{
avatar: "",
name: "郑洪顺",
dept: "销售管理部-福州EBU二部",
score: "490,000"
}
];
export const teamAnalysisRankingsOptions = [
{ value: "1", label: "团队负责人(指标<400万" },
{ value: "2", label: "团队负责人(400万<=指标<600万)" },
{ value: "3", label: "团队负责人(600万<=指标<800万)" },
{ value: "4", label: "团队负责人(800万<=指标<1200万)" },
{ value: "5", label: "团队负责人(1200万<=指标<1600万)" },
{ value: "6", label: "团队负责人(1600万<=指标<3000万)" },
{ value: "7", label: "团队负责人(指标>=3000万)" }
];
export const orgList = {
"key": 0,
"label": "泛微总公司",
"operatingIncome": "320165万元",
"operatingIncomePercent": "31.18%",
"operatingProfit": "120165万元",
"operatingProfitPercent": "33.18%",
"children": [
{
"key": 1, "label": "第一集团军",
"operatingIncome": "20,165",
"operatingIncomePercent": "17.23%",
"operatingProfit": "10,165",
"operatingProfitPercent": "13.18%"
},
{
"key": 2, "label": "第二集团军",
"operatingIncome": "30,165",
"operatingIncomePercent": "19.23%",
"operatingProfit": "20,165",
"operatingProfitPercent": "11.18%"
},
{
"key": 3, "label": "第三集团军",
"operatingIncome": "21,065",
"operatingIncomePercent": "20.23%",
"operatingProfit": "12,789",
"operatingProfitPercent": "9.18%",
"children": [
{
"key": 11, "label": "苏皖大区",
"operatingIncome": "9,665",
"operatingIncomePercent": "23.21%",
"operatingProfit": "6,665",
"operatingProfitPercent": "20.43%",
"children": [
{
"key": 20, "label": "泛微南京",
"operatingIncome": "2,102",
"operatingIncomePercent": "23.45%",
"operatingProfit": "120,165",
"operatingProfitPercent": "12.45%"
},
{
"key": 21, "label": "泛微苏州",
"operatingIncome": "1,398",
"operatingIncomePercent": "21.45%",
"operatingProfit": "120,165",
"operatingProfitPercent": "10.34%"
},
{
"key": 22, "label": "泛微无锡",
"operatingIncome": "565.45",
"operatingIncomePercent": "3.45%",
"operatingProfit": "345.56",
"operatingProfitPercent": "3.56%"
},
{
"key": 23, "label": "泛微常州",
"operatingIncome": "343.56",
"operatingIncomePercent": "2,76%",
"operatingProfit": "220,65",
"operatingProfitPercent": "2.76%"
},
{
"key": 24, "label": "泛微南通",
"operatingIncome": "202.67",
"operatingIncomePercent": "2.45%",
"operatingProfit": "120,165",
"operatingProfitPercent": "2.12%"
},
{
"key": 25, "label": "泛微扬州",
"operatingIncome": "240.11",
"operatingIncomePercent": "2.34%",
"operatingProfit": "201.34",
"operatingProfitPercent": "2.09%"
}
]
},
{
"key": 12, "label": "山东大区",
"operatingIncome": "1,165",
"operatingIncomePercent": "9.23%",
"operatingProfit": "1,003",
"operatingProfitPercent": "6.18%"
},
{
"key": 13, "label": "山西大区",
"operatingIncome": "7,135",
"operatingIncomePercent": "17.23%",
"operatingProfit": "6,365",
"operatingProfitPercent": "12.18%"
},
{
"key": 14, "label": "河南大区",
"operatingIncome": "20,165",
"operatingIncomePercent": "19.23%",
"operatingProfit": "9,455",
"operatingProfitPercent": "12.18%"
}
]
},
{
"key": 4, "label": "第四集团军",
"operatingIncome": "19,165",
"operatingIncomePercent": "9.98%",
"operatingProfit": "9,165",
"operatingProfitPercent": "4.98%"
},
{
"key": 5, "label": "第五集团军",
"operatingIncome": "20,987",
"operatingIncomePercent": "13.23%",
"operatingProfit": "12,995",
"operatingProfitPercent": "8.98%"
}
]
};
export const laborProfitData = {
nodes: [
{
id: "-1",
value: {
title: "泛微总公司",
items: [
{
text: "泛微总公司"
}
]
}
},
{
id: "00",
value: {
title: "第一集团军",
items: [
{
text: "第一集团军"
}
]
}
},
{
id: "01",
value: {
title: "第二集团军",
items: [
{
text: "第二集团军"
}
]
}
},
{
id: "02",
value: {
title: "第三集团军",
items: [
{
text: "第三集团军"
}
]
}
},
{
id: "03",
value: {
title: "第四集团军",
items: [
{
text: "第四集团军"
}
]
}
},
{
id: "04",
value: {
title: "第五集团军",
items: [
{
text: "第五集团军"
}
]
}
},
{
id: "1",
value: {
title: "苏皖大区",
items: [
{
text: "苏皖大区"
}
]
}
},
{
id: "2",
value: {
title: "山东大区",
items: [
{
text: "山东大区"
}
]
}
},
{
id: "3",
value: {
title: "山西大区",
items: [
{
text: "山西大区"
}
]
}
},
{
id: "4",
value: {
title: "河南大区",
items: [
{
text: "河南大区"
}
]
}
},
{
id: "6",
value: {
title: "泛微南京",
items: [
{
text: "泛微南京"
}
]
}
},
{
id: "7",
value: {
title: "泛微苏州",
items: [
{
text: "泛微苏州"
}
]
}
},
{
id: "8",
value: {
title: "泛微无锡",
items: [
{
text: "泛微无锡"
}
]
}
},
{
id: "9",
value: {
title: "泛微常州",
items: [
{
text: "泛微常州"
}
]
}
},
{
id: "10",
value: {
title: "泛微南通",
items: [
{
text: "泛微南通"
}
]
}
},
{
id: "11",
value: {
title: "泛微扬州",
items: [
{
text: "泛微扬州"
}
]
}
}
],
edges: [
{
source: "-1",
target: "00",
value: ""
},
{
source: "-1",
target: "01",
value: ""
},
{
source: "-1",
target: "02",
value: ""
},
{
source: "-1",
target: "03",
value: ""
},
{
source: "-1",
target: "04",
value: ""
},
{
source: "02",
target: "1"
},
{
source: "02",
target: "2"
},
{
source: "02",
target: "3"
},
{
source: "02",
target: "4"
},
{
source: "1",
target: "6"
},
{
source: "1",
target: "7"
},
{
source: "1",
target: "8"
},
{
source: "1",
target: "9"
},
{
source: "1",
target: "10"
},
{
source: "1",
target: "11"
}
]
};
export const laborProfitDataConfig = {
data: laborProfitData,
layout: {
rankdir: "TB",
ranksepFunc: () => 20,
nodesepFunc: () => 30
},
nodeCfg: {
anchorPoints: [
[0.5, 0],
[0.5, 1]
],
customContent: (item, group, cfg) => {
console.log(item, group, cfg);
const { startX, startY, width } = cfg;
const { text, value, icon } = item;
let textShape, valueShape, iconShape;
textShape =
text && group.addShape("text", {
attrs: {
textBaseline: "top",
x: startX,
y: startY,
text,
fill: "#f00"
},
// group 内唯一字段
name: `text-${Math.random()}`
});
valueShape =
value &&
group.addShape("text", {
attrs: {
textBaseline: "top",
x: startX + width / 2,
y: startY,
text: value,
fill: "#f00"
},
name: `value-${Math.random()}`
});
iconShape =
icon &&
group.addShape("image", {
attrs: {
x: startX,
y: startY,
width: 72,
height: 72,
img: icon
},
name: `image-${Math.random()}`
});
return Math.max(
textShape?.getBBox().height ?? 0,
valueShape?.getBBox().height ?? 0,
iconShape?.getBBox().height ?? 0
);
}
},
edgeCfg: {
type: "polyline",
endArrow: true
},
markerCfg: (cfg) => {
return {
position: "bottom",
show: laborProfitData.edges.filter((item) => item.source === cfg.id)?.length
};
},
behaviors: ["drag-canvas", "zoom-canvas"]
};

@ -0,0 +1,74 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/5
*/
import React, { FC } from "react";
import { Progress } from "antd";
import styles from "./index.less";
import { TinyArea } from "@ant-design/plots";
interface OwnProps {
title: string;
number: string;
unit: string;
color: string;
icon: any;
isLine: boolean;
yoyVal?: string;
chainVal?: string;
yoyIcon?: any;
departureVal?: string,
refusal?: string,
chainIcon?: any;
}
type Props = OwnProps;
const config = {
height: 60,
autoFit: false,
data: [264, 417, 438, 887, 309, 397, 550],
smooth: true,
areaStyle: {
fill: "#d6e3fd"
},
tooltip: {
showCrosshairs: false,
showContent: false
}
};
const FrameCard1: FC<Props> = (props) => {
const { title, number, unit, color, icon, isLine, yoyIcon, chainIcon, yoyVal, chainVal, departureVal, refusal } = props;
return (
<div className={styles.frameCard1Wrapper}>
<div className={styles.top}>
<div><img src={icon} alt=""/><span>{title}</span></div>
<div><span>{number}</span><span>{unit}</span></div>
</div>
<div className={styles.center}>
{
isLine ?
<TinyArea {..._.assign(config, {
areaStyle: { fill: `l(270) 0:#fff 0.5:${color} 1:${color}` },
line: { color }
})} /> : <Progress percent={0.57} showInfo={false}/>
}
</div>
<div className={styles.bottom}>
{
yoyIcon ? <>
<span><span></span>{yoyIcon && <img src={yoyIcon} alt=""/>}<span>{yoyVal}</span></span>
<span><span></span>{chainIcon && <img src={chainIcon} alt=""/>}<span>{chainVal}</span></span>
</>:<>
<span><span></span>{yoyIcon && <img src={yoyIcon} alt=""/>}<span>{departureVal}</span></span>
<span><span>退</span>{chainIcon && <img src={chainIcon} alt=""/>}<span>{refusal}</span></span>
</>
}
</div>
</div>
);
};
export default FrameCard1;

@ -0,0 +1,51 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/5
*/
import React, { FC } from "react";
import styles from "./index.less";
interface OwnProps {
title: string;
icon: any;
actualValue: any;
contemValue: any;
yoyVal?: string;
chainVal?: string;
yoyIcon?: any;
chainIcon?: any;
}
type Props = OwnProps;
const FrameCard2: FC<Props> = (props) => {
const { title, icon, actualValue, contemValue, yoyIcon, chainIcon, yoyVal, chainVal } = props;
return (
<div className={styles.frameCard2Wrapper}>
<div className={styles.top}>
<div>{title}</div>
<img src={icon} alt=""/>
</div>
<div className={styles.center}>
<div><span>{actualValue?.title}</span>
<div><span>{actualValue?.number}</span><span>{actualValue?.unit}</span></div>
</div>
<div><span>{contemValue?.title}</span>
<div><span>{contemValue?.number}</span><span>{contemValue?.unit}</span></div>
</div>
</div>
{
yoyIcon &&
<div className={styles.bottom}>
<span><span></span>{yoyIcon && <img src={yoyIcon} alt=""/>}<span>{yoyVal}</span></span>
<span><span></span>{chainIcon && <img src={chainIcon} alt=""/>}<span>{chainVal}</span></span>
</div>
}
</div>
);
};
export default FrameCard2;

@ -0,0 +1,193 @@
.frameCard1Wrapper {
display: flex;
flex-direction: column;
overflow: hidden;
width: 100%;
height: 100%;
.top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
& > div:first-child {
display: flex;
flex-direction: column;
align-items: center;
img {
width: 20px;
margin-bottom: 6px;
}
span {
font-size: 16px;
color: #333333;
letter-spacing: 0;
font-weight: 700;
}
}
& > div:last-child {
& > span:first-child {
font-size: 24px;
color: #14224F;
letter-spacing: 0;
font-weight: 700;
}
& > span:last-child {
font-size: 12px;
color: #D4D4D4;
font-weight: 400;
}
}
}
.center {
flex: 1;
display: flex;
align-items: center;
min-height: 83px;
& > div {
width: 100%;
height: 100%;
}
:global {
.ant-progress {
display: flex;
align-items: center;
}
}
}
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 0.5px solid #e5e5e5;
padding-top: 10px;
& > span {
img {
width: 8px;
margin-left: 8px;
margin-right: 4px;
vertical-align: middle;
}
& > span:first-child {
font-size: 12px;
color: #D4D4D4;
font-weight: 400;
}
& > span:last-child {
font-size: 12px;
color: #333333;
font-weight: 400;
}
}
}
}
.frameCard2Wrapper {
display: flex;
flex-direction: column;
overflow: hidden;
width: 100%;
height: 100%;
.top {
display: flex;
justify-content: space-between;
padding-bottom: 16px;
background: url("../../../../assets/images/top_bottom.png") no-repeat;
background-size: 100% auto;
background-position-y: bottom;
& > div {
font-size: 18px;
color: #FFFFFF;
letter-spacing: 0;
font-weight: 700;
}
img {
width: 30px;
}
}
.center {
flex: 1;
display: flex;
justify-content: space-between;
& > div {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
& > span:first-child {
font-size: 16px;
color: #FFFFFF;
letter-spacing: 0;
font-weight: 400;
margin-bottom: 5px;
}
& > div:last-child {
& > span:first-child {
font-size: 24px;
color: #FFF;
letter-spacing: 0;
font-weight: 700;
}
& > span:last-child {
font-size: 12px;
color: #FFF;
font-weight: 400;
}
}
}
}
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
background: rgba(255, 255, 255, 0.3);
border-radius: 2px;
color: #FFF;
padding: 0 8px;
height: 33px;
& > span {
img {
width: 8px;
margin-left: 8px;
margin-right: 4px;
vertical-align: middle;
}
& > span:first-child {
font-size: 12px;
color: #FFF;
font-weight: 400;
}
& > span:last-child {
font-size: 12px;
color: #FFF;
font-weight: 400;
}
}
}
}

@ -0,0 +1,136 @@
const PersonnelFlowBar = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("personnelFlowBar"));
// 配置项
const option = {
tooltip: {
// 坐标轴指示器,坐标轴触发有效
trigger: "axis",
axisPointer: {
// 默认为直线,可选为:'line' | 'shadow'
type: "shadow"
},
formatter: function (params: any) {
let str = params[0].name + "<br>";
for (let item of params) {
str += item.seriesName + " : " + item.value + "%<br>";
}
return str;
}
},
legend: {
icon: "circle",
top: "-1%",
right: "2%",
itemGap: 20,
textStyle: {
fontSize: 12,//字体大小
color: "#B8B8B8"//字体颜色
}
},
grid: {
top: "15%",
left: "2%",
right: "2%",
bottom: "3%",
containLabel: true
},
xAxis: [
{
type: "category",
data: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
axisTick: {
alignWithLabel: true,
show: false
},
// 修改坐标值样式
axisLabel: {
color: "#B8B8B8",
fontSize: 16,
show: true
},
axisLine: {
show: false
}
}
],
yAxis: [
{
type: "value",
name: "%",
// 修改坐标值样式
axisLabel: {
color: "#787E95",
fontSize: 14
// formatter: '{value} 人'
},
nameTextStyle: {
color: "#787E95",
fontSize: 16
},
// 修改坐标轴线样式
axisLine: {
show: true,
lineStyle: {
color: "transparent"
}
},
axisTick: {
show: false // 不显示坐标轴刻度线
},
splitLine: {
lineStyle: {
type: "dashed",
color: "rgba(93,126,158,1)"
}
}
}
],
series: [
{
name: "今年",
type: "bar",
showBackground: false,
barWidth: "15%",
barGap: "80%",
data: initData([12, 10, 23, 15, 3, 7, 11, 20, 17, 15, 8, 12]),
// bar 样式修改
itemStyle: {
color: "#3EA1FF"
}
},
{
name: "去年",
type: "bar",
showBackground: false,
barWidth: "15%",
data: initData([7, 12, 8, 12, 12, 5, 8, 15, 18, 12, 9, 7]),
// bar 样式修改
itemStyle: {
color: "#0ED8F9"
}
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default PersonnelFlowBar;
const initData = (arr: Array<number>) => {
const total = _.reduce(arr, (pre: number, cur: number) => pre + cur, 0);
const serie = [];
for (let i = 0; i < arr.length; i++) {
const num = arr[i];
const numcount = Percentage(num, total);
serie.push(numcount);
}
return serie;
};
const Percentage = (num: number, total: number) => {
return (Math.round(num / total * 100));// 小数点后两位百分比
};

@ -0,0 +1,161 @@
const TrendsInSeparationsCharts = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("trendsInSeparationsCharts"));
// 配置项
const option = {
tooltip: {
// 坐标轴指示器,坐标轴触发有效
trigger: "axis",
axisPointer: {
// 默认为直线,可选为:'line' | 'shadow'
type: "shadow"
}
},
legend: {
icon: "circle",
top: "5%",
right: "center",
itemGap: 20,
textStyle: {
fontSize: 12,//字体大小
color: "#787E95"//字体颜色
}
},
grid: {
top: "20%",
left: "2%",
right: "2%",
bottom: "3%",
containLabel: true
},
xAxis: [
{
type: "category",
data: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
axisTick: {
alignWithLabel: true,
show: false
},
// 修改坐标值样式
axisLabel: {
color: "#B8B8B8",
fontSize: 16,
show: true
},
axisLine: {
show: false
}
}
],
yAxis: [
{
type: "value",
name: "人",
// 修改坐标值样式
axisLabel: {
color: "#787E95",
fontSize: 14
// formatter: '{value} 人'
},
nameTextStyle: {
color: "#787E95",
fontSize: 16
},
// 修改坐标轴线样式
axisLine: {
show: true,
lineStyle: {
color: "transparent"
}
},
axisTick: {
show: false // 不显示坐标轴刻度线
},
splitLine: {
lineStyle: {
type: "dashed",
color: "rgba(93,126,158,1)"
}
}
},
{
type: "value",
// 修改坐标值样式
axisLabel: {
color: "#787E95",
fontSize: 14,
formatter: '{value} %'
},
nameTextStyle: {
color: "#787E95",
fontSize: 16
},
// 修改坐标轴线样式
axisLine: {
show: true,
lineStyle: {
color: "transparent"
}
},
axisTick: {
show: false // 不显示坐标轴刻度线
},
splitLine: {
show: false,
lineStyle: {
type: "dashed",
color: "rgba(93,126,158,1)"
}
}
}
],
series: [
{
name: "主动离职",
type: "bar",
stack:"Search Engine",
showBackground: false,
barWidth: "10%",
barGap: "100%",
data: [80, 30, 10, 38, 45, 70, 70, 70, 40, 50, 30, 10],
// bar 样式修改
itemStyle: {
barBorderRadius: 2,
color: "#00C48B"
}
},
{
name: "辞退",
type: "bar",
stack:"Search Engine",
showBackground: false,
barWidth: "10%",
data: [20, 10, 5, 10, 10, 1, 1, 12, 10, 15, 5, 2],
// bar 样式修改
itemStyle: {
barBorderRadius: 2,
color: "#FFA400"
}
},
{
name: "离职率",
type: "line",
yAxisIndex: 1,
data: [10, 4, 2, 5, 5, 7, 7, 10, 4, 6, 4, 2],
itemStyle: {
normal: {
color: "#66EFE8",
lineStyle: {
color: "#66EFE8"
}
}
},
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default TrendsInSeparationsCharts;

@ -0,0 +1,201 @@
@gap: 16px;
@cardWidth: calc(~"20vw" - 4 * @gap / 5);
.peopleFlowWrapper {
width: 100%;
height: 100%;
background: #e5e5e5;
overflow: auto;
display: flex;
flex-direction: column;
.headerCardWrapper {
display: flex;
margin-bottom: @gap;
padding: 0;
& > li:not(:last-child) {
margin-right: @gap;
}
& > li:not(:first-child) {
background-size: 100% 100% !important;
}
& > li:first-child {
background: #FFF;
}
& > li {
width: @cardWidth;
min-height: 220px;
border-radius: 5px;
padding: 16px;
}
}
.contentBox {
flex: 1;
display: flex;
.contentBoxLeft {
flex: 1;
display: flex;
flex-direction: column;
.contenBoxTop {
flex: 1;
.chartsBox {
flex: 4 1;
display: flex;
& > ul {
width: @cardWidth;
margin: 0 @gap 0 0;
padding: 0;
overflow: hidden;
& > li:first-child {
margin-bottom: @gap;
}
& > li {
background: #FFF;
min-height: 220px;
border-radius: 5px;
padding: 16px;
}
}
& > div {
flex: 3 1;
background: #FFF;
border-radius: 5px;
min-height: 220px;
display: flex;
flex-direction: column;
& > ul {
margin: 20px 16px;
padding: 0;
display: flex;
& > li:hover {
cursor: pointer;
}
& > li.active {
font-size: 16px;
color: #0055F3;
letter-spacing: 0;
font-weight: 700;
border-bottom: 1px solid #0055F3;
}
& > li:not(:last-child) {
margin-right: 26px;
}
li {
font-size: 14px;
color: #999999;
letter-spacing: 0;
font-weight: 400;
padding: 6px 0;
}
}
& > div {
min-height: 377px;
}
}
}
}
.contenBoxBottom {
flex: 1;
margin-top: @gap;
background: #FFF;
border-radius: 5px;
.trendsInSeparations {
min-height: 220px;
max-height: 220px;
}
}
}
.rankingBox {
width: @cardWidth;
margin-left: @gap;
background: #FFF;
border-radius: 5px;
.trainingRanking {
overflow-y: auto;
.rankDescBox {
display: flex;
font-size: 4px;
align-items: center;
img {
width: 30px;
margin-right: 10px;
}
.rankNum {
margin-right: 10px
}
.rankNumber {
width: 30px;
margin-right: 10px;
text-align: center;
}
.rankDescPersBox {
display: flex;
align-items: center;
& > span:last-child {
display: flex;
flex-direction: column;
margin-left: 8px;
& > span:first-child {
font-size: 14px;
color: #333333;
font-weight: 400;
}
& > span:last-child {
font-size: 12px;
color: #B8B8B8;
font-weight: 400;
min-width: 130px;
max-width: 130px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
.rankRow {
background: #FEFAED;
}
:global {
.ant-list-item {
padding: 16px 20px;
}
}
}
}
}
}

@ -0,0 +1,141 @@
/*
* Author:
* name:
* Description:
* Date: 2023/4/27
*/
import React, { FunctionComponent, useEffect, useState } from "react";
// @ts-ignore
import echarts from "echarts";
import { Avatar, List } from "antd";
import FrameCard1 from "./components/frameCard1";
import FrameCard2 from "./components/frameCard2";
import FrameBox from "../components/frameBox";
import { frameCard1List, frameCard2List } from "@/pages/personnelReport/constants";
import PersonnelFlowBar from "./components/personnelFlowCharts";
import TrendsInSeparationsCharts from "./components/trendsInSeparationsCharts";
import { personnelFlowTablist, trainingRankingList } from "../constants";
import cs from "classnames";
import styles from "./index.less";
interface OwnProps {
}
type Props = OwnProps;
const index: FunctionComponent<Props> = (props) => {
const [active, setActive] = useState<number>(0);
useEffect(() => {
const personnelFlowBar = PersonnelFlowBar(echarts);
const trendsInSeparationsCharts = TrendsInSeparationsCharts(echarts);
// 屏幕缩放对chart图表进行自适应处理调用实例的resize方法
window.onresize = () => {
personnelFlowBar.resize();
trendsInSeparationsCharts.resize();
};
return () => {
};
}, []);
return (
<div className={styles.peopleFlowWrapper}>
<ul className={styles.headerCardWrapper}>
<li>
<FrameCard1
title="在职人数"
number="14338"
unit="人"
color="#78C0F9"
isLine
yoyIcon={require("../../../assets/images/down.png")}
chainIcon={require("../../../assets/images/up.png")}
yoyVal="4.75%"
chainVal="4.75%"
icon={require("../../../assets/images/zzrs.png")}
/>
</li>
{_.map(frameCard2List, (item: any, index: number) => {
return (
<li key={index} style={{ background: `url(${item.bg}) no-repeat` }}>
<FrameCard2 {...item} />
</li>
);
})}
</ul>
<div className={styles.contentBox}>
<div className={styles.contentBoxLeft}>
<div className={styles.contenBoxTop}>
<div className={styles.chartsBox}>
<ul>
{_.map(frameCard1List, (item: any, index: number) => {
return (
<li key={index}>
<FrameCard1 {...item} />
</li>
);
})}
</ul>
<div>
<ul>
{
_.map(personnelFlowTablist, (item: any, index: number) => {
const classes = cs({
[styles["active"]]: index === active
});
return <li key={index} className={classes} onClick={() => setActive(index)}>{item}</li>;
})
}
</ul>
<div id="personnelFlowBar"/>
</div>
</div>
</div>
<div className={styles.contenBoxBottom}>
<FrameBox title="离职情况变化趋势">
<div className={styles.trendsInSeparations} id="trendsInSeparationsCharts"/>
</FrameBox>
</div>
</div>
<div className={styles.rankingBox}>
<FrameBox title="培训排名">
<div className={styles.trainingRanking}>
<List
dataSource={trainingRankingList}
renderItem={(item, index) => (
<List.Item key={index}
className={cs({ [styles["rankRow"]]: index === 0 || index === 1 || index === 2 })}>
<List.Item.Meta
title={
<div className={styles.rankDescBox}>
{
(index === 0 || index === 1 || index === 2) ?
<img src={index === 0 ?
require("../../../assets/images/one.png") : index === 1 ?
require("../../../assets/images/two.png") :
require("../../../assets/images/three.png")} alt=""/> :
<span className={styles.rankNumber}>{index + 1}</span>
}
<div className={styles.rankDescPersBox}>
<Avatar src={item.avatar}/>
<span><span>{item.name}</span><span>{item.dept}</span></span>
</div>
</div>
}
/>
<div style={{
fontWeight: (index === 0 || index === 1 || index === 2) ? 700 : 400,
fontSize: (index === 0 || index === 1 || index === 2) ? 16 : 14,
color: index === 0 ? "#FFA000" : index === 1 ? "#6F9DAE" : index === 2 ? "#B0442B" : "#333333"
}}>{item.score}</div>
</List.Item>
)}
/>
</div>
</FrameBox>
</div>
</div>
</div>
);
};
export default index;

@ -0,0 +1,116 @@
const AgeStructureBar = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("ageStructure"));
// 配置项
const option = {
legend: {
icon: "circle",
top: "-1%",
right: "0%",
itemGap: 20,
textStyle:{
fontSize: 12,//字体大小
color: '#ffffff'//字体颜色
},
},
tooltip: {
// 坐标轴指示器,坐标轴触发有效
trigger: "axis",
axisPointer: {
// 默认为直线,可选为:'line' | 'shadow'
type: "shadow"
}
},
grid: {
left: "0%",
top: 20,
right: "0%",
bottom: "0%",
containLabel: true
},
xAxis: {
type: "value",
show: false,
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false // 不显示坐标轴刻度线
}
},
yAxis: {
type: "category",
data: ["30岁以下", "3040岁", "4050岁", "5060岁", "60岁以上"],
// 修改坐标值样式
axisLine: {
show: false
},
axisLabel: {
color: "rgba(255, 255, 255, 1)",
fontSize: 10,
show: true
},
axisTick: {
show: false // 不显示坐标轴刻度线
}
},
series: [
{
name: "男",
type: "bar",
stack: "total",
barWidth: "30%",
label: {
show: true,
color: "rgba(255, 255, 255, 1)",
fontSize: 10
},
emphasis: {
focus: "series"
},
data: [320, 302, 301, 334, 390],
// bar 样式修改
itemStyle: {
barBorderRadius: [10, 0 , 0 , 10],
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: "#3EA1FF" },
{ offset: 0.5, color: "#72CFFF" },
{ offset: 1, color: "#72CFFF" }
]),
},
},
{
name: "女",
type: "bar",
stack: "total",
barWidth: "30%",
label: {
show: true,
color: "rgba(255, 255, 255, 1)",
fontSize: 10
},
emphasis: {
focus: "series"
},
data: [120, 132, 101, 134, 90],
// bar 样式修改
itemStyle: {
barBorderRadius: [0, 10 , 10 , 0],
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: "#B2FDB2" },
{ offset: 0.5, color: "#00D5FF" },
{ offset: 1, color: "#00D5FF" }
]),
},
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default AgeStructureBar;

@ -0,0 +1,119 @@
const PersonnelCategoryBar = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("changeStatistics"));
// 配置项
const option = {
tooltip: {
// 坐标轴指示器,坐标轴触发有效
trigger: "axis",
axisPointer: {
// 默认为直线,可选为:'line' | 'shadow'
type: "shadow"
}
},
grid: {
left: "0%",
top: 10,
right: "0%",
bottom: "4%",
// true: 数值离DOM盒子的距离 false: 坐标轴离DOM盒子的距离
containLabel: true
},
xAxis: [
{
type: "category",
data: ["公司本部", "公司1", "公司2", "公司3", "公司4", "公司5", "公司6", "公司7"],
axisTick: {
alignWithLabel: true
},
// 修改坐标值样式
axisLabel: {
color: "rgba(255, 255, 255, 1)",
fontSize: 10,
show: true
},
axisLine: {
show: false
}
}
],
yAxis: [
{
type: "value",
// 修改坐标值样式
axisLabel: {
color: "rgba(255, 255, 255, 1)",
fontSize: 12
},
// 修改坐标轴线样式
axisLine: {
show: false
},
axisTick: {
show: false // 不显示坐标轴刻度线
},
splitLine: {
lineStyle: {
type: "dashed",
color: "rgba(93,126,158,1)"
}
}
}
],
series: [
{
name: "入职",
type: "bar",
showBackground: false,
barWidth: "10%",
data: [250, 250, 320, 410, 280, 320, 405, 405],
// bar 样式修改
itemStyle: {
barBorderRadius: 10,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#3EA1FF" },
{ offset: 0.5, color: "#72CFFF" },
{ offset: 1, color: "#72CFFF" }
])
}
},
{
name: "离职",
type: "bar",
showBackground: false,
barWidth: "10%",
data: [370, 370, 260, 110, 390, 280, 110, 110],
// bar 样式修改
itemStyle: {
barBorderRadius: 10,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#00D5FF" },
{ offset: 0.5, color: "#B2FDB2" },
{ offset: 1, color: "#B2FDB2" }
])
}
},
{
name: "调职",
type: "bar",
showBackground: false,
barWidth: "10%",
data: [310, 310, 80, 280, 310, 70, 280, 280],
// bar 样式修改
itemStyle: {
barBorderRadius: 10,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#1455FF" },
{ offset: 0.5, color: "#5F9CFF" },
{ offset: 1, color: "#5F9CFF" }
])
}
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default PersonnelCategoryBar;

@ -0,0 +1,103 @@
import { getPie3D } from "@/utils/chart";
const color = ["#FE772D", "#FEDB4B", "#2A71FF", "#00EDFE"];
const DegreeStructurePie = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("degreeStructure"));
// 配置项
const option = {
...getPie3D(setLabel([
{
name: "研究生(博士)",
value: 176
},
{
name: "研究生(硕士)",
value: 288
},
{
name: "本科",
value: 588
},
{
name: "大专及以下",
value: 78
}
], color), 0.6, 240, 26, 18, 1, true)
};
// 配置项给实例对象
myChart.setOption({
...option,
legend: {
orient: "vertical",
icon: "circle",
top: "25%",
left: "10%",
itemGap: 28,
textStyle: {
fontSize: 12,//字体大小
color: "#ffffff"//字体颜色
}
}
});
return myChart;
};
export default DegreeStructurePie;
export const setLabel = (optionData: any, color: any) => {
return optionData.map((item: any, index: number) => {
return {
...item,
itemStyle: {
color: color[index]
},
label: {
normal: {
show: false,
color: color[index],
position: "right",
// distance:-10,
offset: [0, 3],
formatter: [
"{d|{d}%}",
"————",
// '{c|{c}}{b|台}',
"{b|{b}}"
].join("\n"), // 用\n来换行
rich: {
b: {
// color: '#fff',
lineHeight: 25,
align: "left",
color: color[index]
},
c: {
fontSize: 22,
textShadowColor: "#1c90a6",
textShadowOffsetX: 0,
textShadowOffsetY: 2,
textShadowBlur: 5,
color: color[index]
},
d: {
color: color[index],
align: "left"
}
}
}
},
labelLine: {
normal: {
show: false,
length2: 30,
lineStyle: {
width: 1,
color: color[index]
}
}
}
};
});
};

@ -0,0 +1,47 @@
import { getPie3D } from "@/utils/chart";
import { setLabel } from "./degreeStructurePie";
const color = ["#BD42EF", "#6D45F3", "#3358F3", "#6ECDE5"];
const GradAnalysisPie = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("gradAnalysis"));
// 配置项
const option = {
...getPie3D(setLabel([
{
name: "正高级",
value: 500
},
{
name: "副高级",
value: 1120
},
{
name: "中级",
value: 4567
},
{
name: "初级",
value: 5278
}
], color), 0.6, 240, 26, 18, 1, false)
};
// 配置项给实例对象
myChart.setOption({
...option,
legend: {
orient: "vertical",
icon: "circle",
top: "25%",
left: "10%",
itemGap: 28,
textStyle: {
fontSize: 12,//字体大小
color: "#ffffff"//字体颜色
}
}
});
return myChart;
};
export default GradAnalysisPie;

@ -0,0 +1,96 @@
const PersonnelCategoryBar = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("personnelCategory"));
// 配置项
const option = {
tooltip: {
// 坐标轴指示器,坐标轴触发有效
trigger: "axis",
axisPointer: {
// 默认为直线,可选为:'line' | 'shadow'
type: "shadow"
}
},
grid: {
left: "0%",
top: 10,
right: "0%",
bottom: "4%",
// true: 数值离DOM盒子的距离 false: 坐标轴离DOM盒子的距离
containLabel: true
},
xAxis: [
{
type: "category",
data: ["领导班子", "海外中国籍", "正式在岗", "海外外籍", "退休返聘", "其他临时", "劳务派遣", "内退"],
axisTick: {
alignWithLabel: true
},
// 修改坐标值样式
axisLabel: {
color: "rgba(255, 255, 255, 1)",
fontSize: 10,
rotate: 60,
show: true
},
axisLine: {
show: false
}
}
],
yAxis: [
{
type: "value",
// 修改坐标值样式
axisLabel: {
color: "rgba(255, 255, 255, 1)",
fontSize: 12
},
// 修改坐标轴线样式
axisLine: {
show: false
},
axisTick: {
show: false // 不显示坐标轴刻度线
},
splitLine: {
lineStyle: {
type: "dashed",
color: "rgba(93,126,158,1)"
}
}
}
],
series: [
{
name: "直接访问",
type: "bar",
showBackground: true,
barWidth: "30%",
data: [10, 52, 200, 334, 390, 1030, 220, 210],
// bar 样式修改
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#3EA1FF" },
{ offset: 0.5, color: "#72CFFF" },
{ offset: 1, color: "#72CFFF" }
]),
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#AFD8FF" },
{ offset: 0.7, color: "#AFD8FF" },
{ offset: 1, color: "#AFD8FF" }
])
}
}
}
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default PersonnelCategoryBar;

@ -0,0 +1,64 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/4
*/
import React, { FC, useState } from "react";
import cs from "classnames";
import styles from "./index.less";
interface OwnProps {
position: string;
tabList: Array<any>;
children: any;
titleImg: any;
type?: string;
}
type Props = OwnProps;
const FrameComp: FC<Props> = (props) => {
const { position, children, tabList, titleImg } = props;
const [active, setActive] = useState<number>(0);
return (
<div className={styles.frameWrapper}>
<div className={styles.headerTop}>
<div className={cs(styles.headerLeft, { [styles["halfHeaderLeft"]]: position === "right" })}>
<img src={titleImg} alt=""/>
{
position === "right" &&
<ul className={styles.tabWrapper}>
{
_.map(tabList, (item, index) => {
const classes = cs({
[styles["liActive"]]: index === active
});
return <li key={index} onClick={() => setActive(index)} className={classes}>{item}</li>;
})
}
</ul>
}
</div>
<span className={styles.moreWrapper}>More <img src={require("../../../../assets/images/more.png")}
alt=""/></span>
</div>
{
position === "bottom" &&
<ul className={styles.tabWrapper}>
{
_.map(tabList, (item, index) => {
const classes = cs({
[styles["liActive"]]: index === active
});
return <li key={index} onClick={() => setActive(index)} className={classes}>{item}</li>;
})
}
</ul>
}
{children}
</div>
);
};
export default FrameComp;

File diff suppressed because one or more lines are too long

@ -0,0 +1,125 @@
.topPageWrapper {
height: 1.25rem;
position: relative;
background: url("../../../../assets/images/head_bg1.png") no-repeat;
background-size: 100% 100%;
.title {
text-align: center;
line-height: 0.875rem;
position: relative;
.updateTime {
color: #fff;
line-height: 0;
margin-top: 0.0625rem;
img {
width: 0.225rem;
margin-right: .2rem;
}
}
img {
width: 4.475rem;
}
}
.logoWrapper, .showTime {
position: absolute;
}
.showTime {
right: 2.375rem;
top: 0.4rem;
text-align: right;
color: #fff;
.dateDay {
padding: 0 .35rem;
}
}
.logoWrapper {
top: 0.1rem;
left: 2.375rem;
line-height: 0.875rem;
img {
width: 1.675rem;
}
}
}
.mapWrapper {
width: 10.625rem;
height: 8.125rem;
margin-top: 1rem;
}
.frameWrapper {
background: url("../../../../assets/images/frame_bg.png") no-repeat;
background-size: 100% 100%;
margin-bottom: 0.2rem;
.headerTop {
height: 0.475rem;
position: relative;
background: url("../../../../assets/images/frame_title_bg.png") no-repeat;
background-size: 100% 100%;
display: flex;
justify-content: flex-end;
.halfHeaderLeft {
left: 1.45rem !important;
}
.headerLeft {
position: absolute;
left: 0.7375rem;
top: 0.0625rem;
display: flex;
img {
height: 0.3rem;
}
}
.moreWrapper {
color: #fff;
font-size: 0.175rem;
position: absolute;
right: 0.3375rem;
top: 0.1rem;
cursor: pointer;
img {
width: 0.2375rem;
}
}
.tabWrapper {
margin-left: 0.775rem;
padding: 0;
}
}
.tabWrapper {
display: flex;
margin: 0;
padding: 0 0.3375rem;
li {
padding: 0.1rem 0.175rem;
font-size: 14px;
color: #ACACAC;
cursor: pointer;
}
li.liActive {
background: url("../../../../assets/images/tabSelected.png") no-repeat;
background-size: 100% 100%;
background-position-y: .125rem;
}
}
}

@ -0,0 +1,27 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/4
*/
import React, { FC } from "react";
import Chart from "@/utils/chart";
import { mapOptions } from "./options";
// import { mapProvinceOptions } from "./provinceOptions";
import styles from "./index.less";
interface OwnProps {
}
type Props = OwnProps;
const Map: FC<Props> = (props) => {
return (
<div className={styles.mapWrapper}>
<Chart renderer={"canvas"} option={mapOptions({})}/>
{/*<Chart renderer={"canvas"} option={mapProvinceOptions({})}/>*/}
</div>
);
};
export default Map;

@ -0,0 +1,243 @@
import "echarts/map/js/china";
// 地图数据
const mapData = {
citys: [
{
name: "浙江",
value: [120.15, 29.28, -2],
symbolSize: 2,
itemStyle: {
normal: {
color: "#FFF"
}
}
},
{
name: "四川",
value: [103.36, 30.65, -5],
symbolSize: 2,
itemStyle: {
normal: {
color: "#FFF"
}
}
},
{
name: "内蒙古",
value: [112.17, 42.81, -23],
symbolSize: 2,
itemStyle: {
normal: {
color: "#FFF"
}
}
},
{
name: "江苏",
value: [120.26, 32.54, -1],
symbolSize: 2,
itemStyle: {
normal: {
color: "#FFF"
}
}
},
{
name: "西藏",
value: [89.13, 30.66, -1],
symbolSize: 2,
itemStyle: {
normal: {
color: "#FFF"
}
}
}
]
};
export const salaryData = {
header: ["业务板块", "二级机构", "人员类型", "起始时间", "截止时间", "发薪人数", "固定薪酬", "浮动薪酬", "薪酬合计", "薪酬固浮化"],
data: [
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"],
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"],
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"],
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"],
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"],
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"],
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"],
["国内工程", "建设集团", "领导班子", "2023.1", "2023.1", "23", "20,000", "20,000", "20,000", "20,000"]
]
};
export const mapOptions = (params) => ({
title: {
show: false,
text: "全国物流输送图",
left: "center",
textStyle: {
color: "#fff"
}
},
legend: {
show: false
},
geo: [
{
nameMap: {
China: "中国"
},
map: "china",
zlevel: 5,
label: {
normal: {
show: true,
formatter: function (params) {
//圆环显示文字
return params.name === "江苏" || params.name === "浙江" || params.name === "四川" || params.name === "内蒙古" || params.name === "西藏" ? params.name : "";
},
fontSize: 12,
color: "#FFF"
},
emphasis: {
show: true,
color: "#FFF"
}
},
zoom: 1.2,
itemStyle: {
normal: {
borderColor: "rgba(148,224,250, .5)", //区域边框颜色
areaColor: "rgba(82,164,238,.1)", //区域颜色
borderWidth: 1, //区域边框宽度
shadowBlur: 5,
shadowColor: "rgba(3,113,173,.7)"
},
emphasis: {
borderColor: "rgba(148,224,250, .5)",
areaColor: "rgba(6,89,176,.3)",
borderWidth: 2.5,
shadowBlur: 5,
shadowColor: "rgba(3,113,173,.5)"
}
}
},
{
nameMap: {
China: "中国"
},
map: "china",
zlevel: 4,
top: "11%",
label: {
emphasis: {
show: false
}
},
zoom: 1.2,
itemStyle: {
normal: {
// borderColor: 'rgba(255,209,163, .5)', //区域边框颜色
areaColor: "rgba(73,86,166,.1)", //区域颜色
borderWidth: 0.5, //区域边框宽度
shadowBlur: 5,
shadowColor: "rgba(107,91,237,.7)"
},
emphasis: {
borderColor: "transparent",
areaColor: "transparent",
borderWidth: 1,
shadowBlur: 5,
shadowColor: "transparent"
}
}
},
{
nameMap: {
China: "中国"
},
map: "china",
zlevel: 3,
top: "12%",
label: {
emphasis: {
show: false
}
},
zoom: 1.2,
itemStyle: {
normal: {
areaColor: "rgba(73,86,166,.1)", //区域颜色
borderWidth: 0.5, //区域边框宽度
shadowBlur: 5,
shadowColor: "rgba(107,91,237,.7)"
},
emphasis: {
borderColor: "transparent",
areaColor: "transparent",
borderWidth: 1,
shadowBlur: 5,
shadowColor: "transparent"
}
}
},
{
nameMap: {
China: "中国"
},
map: "china",
zlevel: 2,
top: "13%",
label: {
emphasis: {
show: false
}
},
zoom: 1.2,
itemStyle: {
normal: {
// borderColor: 'rgba(255,209,163, .5)', //区域边框颜色
areaColor: "rgba(73,86,166,.1)", //区域颜色
borderWidth: 0.5, //区域边框宽度
shadowBlur: 5,
shadowColor: "rgba(107,91,237,.7)"
},
emphasis: {
borderColor: "transparent",
areaColor: "transparent",
borderWidth: 1,
shadowBlur: 5,
shadowColor: "transparent"
}
}
}
],
series: [
{
name: "地点",
type: "custom",
coordinateSystem: "geo",
zlevel: 12,
renderItem(params, api) {
//具体实现自定义图标的方法
return {
type: "image",
style: {
image: require("../../../../assets/images/zs.png"),
x: api.coord([
mapData.citys[params.dataIndex].value[0],
mapData.citys[params.dataIndex].value[1]
])[0],
y: api.coord([
mapData.citys[params.dataIndex].value[0],
mapData.citys[params.dataIndex].value[1]
])[1]
}
};
},
data: mapData.citys
}
]
});
export const userOptions = (params = {}) => ({
header: params.header,
data: params.data
});

@ -0,0 +1,57 @@
import "./hubei.js";
export const mapProvinceOptions = (params) => ({
title: {
text: "湖北地图",
subtext: "-。-"
},
tooltip: {
trigger: "item",
formatter: function (a) {
return a[2];
}
},
legend: {
orient: "vertical",
x: "right",
data: ["数据名称"]
},
dataRange: {
min: 0,
max: 1000,
color: ["orange", "yellow"],
text: ["高", "低"], // 文本,默认为数值文本
calculable: true
},
series: [
{
name: "数据名称",
type: "map",
mapType: "湖北", //改成对应省份名
selectedMode: "single",
itemStyle: {
normal: { label: { show: true } },
emphasis: { label: { show: true } }
},
//这里的data是辅助改变某个地区颜色的如果你不需要完全可以不加
data: [
{ name: "十堰市", value: Math.round(Math.random() * 1000) },
{ name: "襄樊市", value: Math.round(Math.random() * 1000) },
{ name: "随州市", value: Math.round(Math.random() * 1000) },
{ name: "神农架林区", value: Math.round(Math.random() * 1000) },
{ name: "恩师土家族苗族自治州", value: Math.round(Math.random() * 1000) },
{ name: "宜昌市", value: Math.round(Math.random() * 1000) },
{ name: "荆门市", value: Math.round(Math.random() * 1000) },
{ name: "天门市", value: Math.round(Math.random() * 1000) },
{ name: "潜江市", value: Math.round(Math.random() * 1000) },
{ name: "荆州市", value: Math.round(Math.random() * 1000) },
{ name: "仙桃市", value: Math.round(Math.random() * 1000) },
{ name: "武汉市", value: Math.round(Math.random() * 1000) },
{ name: "黄冈市", value: Math.round(Math.random() * 1000) },
{ name: "鄂州市", value: Math.round(Math.random() * 1000) },
{ name: "咸宁市", value: Math.round(Math.random() * 1000) },
{ name: "黄石市", value: Math.round(Math.random() * 1000) }
]
}
]
});

@ -0,0 +1,53 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/4
*/
import React, { FC, useEffect, useRef, useState } from "react";
import { formatTime } from "@/utils/common";
import styles from "./index.less";
interface OwnProps {
}
type Props = OwnProps;
const weekday = ["星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
const TopPage: FC<Props> = (props) => {
const [timeStr, setTimeStr] = useState<any>({});
const timing = useRef<any>(null);
useEffect(() => {
setTimingFn();
return () => {
timing.current = null;
};
}, []);
const setTimingFn = () => {
timing.current = setInterval(() => {
let dateYear = formatTime(new Date(), "yyyy-MM-dd");
let dateDay = formatTime(new Date(), "HH:mm:ss");
let dateWeek = weekday[new Date().getDay()];
setTimeStr({ dateYear, dateDay, dateWeek });
}, 1000);
};
return (
<div className={styles.topPageWrapper}>
<span className={styles.logoWrapper}><img src={require("../../../../assets/images/weaverlogo.png")}
alt=""/></span>
<div className={styles.title}>
<img src={require("../../../../assets/images/head_title.png")} alt=""/>
<div className={styles.updateTime}>
<img src={require("../../../../assets/images/refresh.png")} alt=""/>
16:02:09
</div>
</div>
<span
className={styles.showTime}><span>{timeStr?.dateYear}</span><span
className={styles.dateDay}>{timeStr?.dateDay}</span><span>{timeStr?.dateWeek}</span></span>
</div>
);
};
export default TopPage;

@ -0,0 +1,115 @@
.screenWrapperRoot {
width: 100%;
height: 100%;
overflow-y: auto;
.screenWrapper {
line-height: 1.15;
min-height: 100vh;
background: url("../../../assets/images/pageBg.png") top center no-repeat;
background-size: 100% 100%;
.screenMain {
display: flex;
min-width: 1024px;
max-width: 1920px;
margin: 0 auto;
padding: 0 0.6875rem;
.screenColCenter {
flex: 5 1;
margin: 0 0.125rem;
position: relative;
.cardWrapper {
display: flex;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 99;
padding: 0.25rem 0.125rem 0;
& > li:not(:last-child) {
margin-right: 0.275rem;
}
& > li {
flex: 1;
min-height: 1.1625rem;
background: url("../../../assets/images/card_bg.png") no-repeat;
background-size: 100% 100%;
display: flex;
align-items: center;
justify-content: center;
img {
width: 0.725rem;
margin-right: 0.2rem;
}
.cardInner {
display: flex;
flex-direction: column;
color: #FFF;
min-width: 1.125rem;
text-align: center;
span:first-child {
font-size: 0.275rem;
margin-bottom: 0.1rem;
}
span:last-child {
font-size: 0.2rem;
}
}
}
}
}
}
.screenCol {
flex: 3 1;
.personnelCate, .ageStruct, .degreeStructure, .gradAnalysis {
height: 3.875rem;
padding: 0 0.3375rem;
}
}
.screenFooter {
display: flex;
min-width: 1024px;
max-width: 1920px;
margin: 0 auto;
padding: 0 0.6875rem;
& > div:first-child {
margin-right: 0.125rem;
}
.screenFooterCol {
flex: 1;
.payrollStatistics {
padding-bottom: 0.2375rem !important;
:global {
.dv-scroll-board {
.rows .row-item, .header {
font-size: 0.15rem !important;
}
}
}
}
.payrollStatistics, .personnelChangeStatistics {
height: 3.5rem;
padding: 0 0.3375rem;
}
}
}
}
}

@ -0,0 +1,147 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/4
*/
import React, { FC, useEffect } from "react";
// @ts-ignore
import echarts from "echarts";
import "echarts-gl";
import TopPage from "./components/topPage";
import Map from "./components/map";
import FrameComp from "./components/frameComp";
import PersonnelCategoryBar from "./components/echarts/personnelCategoryBar";
import AgeStructureBar from "./components/echarts/ageStructureBar";
import DegreeStructurePie from "./components/echarts/degreeStructurePie";
import GradAnalysisPie from "./components/echarts/gradAnalysisPie";
import ChangeStatisticsBar from "./components/echarts/changeStatisticsBar";
import { salaryData, userOptions } from "./components/options";
// @ts-ignore
import { ScrollBoard } from "@jiaminghi/data-view-react";
import styles from "./index.less";
interface OwnProps {
}
type Props = OwnProps;
const Index: FC<Props> = (props) => {
useEffect(() => {
const personnelCategoryBar = PersonnelCategoryBar(echarts);
const ageStructureBar = AgeStructureBar(echarts);
const degreeStructurePie = DegreeStructurePie(echarts);
const gradAnalysisPie = GradAnalysisPie(echarts);
const changeStatisticsBar = ChangeStatisticsBar(echarts);
// 屏幕缩放对chart图表进行自适应处理调用实例的resize方法
window.onresize = () => {
personnelCategoryBar.resize();
ageStructureBar.resize();
degreeStructurePie.resize();
gradAnalysisPie.resize();
changeStatisticsBar.resize();
};
return () => {
};
}, []);
return (
<div className={styles.screenWrapperRoot}>
<div className={styles.screenWrapper}>
<TopPage/>
<div className={styles.screenMain}>
<div className={styles.screenCol}>
<FrameComp position="bottom" tabList={["全部", "总部", "苏皖大区", "山东大区"]}
titleImg={require("../../../assets/images/rylbylb.png")}>
<div className={styles.personnelCate} id="personnelCategory"/>
</FrameComp>
<FrameComp position="bottom" tabList={["全部", "总部", "苏皖大区"]}
titleImg={require("../../../assets/images/hxzgzgnljg.png")}>
<div className={styles.ageStruct} id="ageStructure"/>
</FrameComp>
</div>
<div className={styles.screenColCenter}>
<ul className={styles.cardWrapper}>
<li>
<img src={require("../../../assets/images/xsje.png")} alt=""/>
<div className={styles.cardInner}>
<span>8,29,000</span>
<span></span>
</div>
</li>
<li>
<img src={require("../../../assets/images/xmys.png")} alt=""/>
<div className={styles.cardInner}>
<span>3,29,000</span>
<span></span>
</div>
</li>
<li>
<img src={require("../../../assets/images/yjgz.png")} alt=""/>
<div className={styles.cardInner}>
<span>12,000</span>
<span></span>
</div>
</li>
<li>
<img src={require("../../../assets/images/rwdcl.png")} alt=""/>
<div className={styles.cardInner}>
<span>98%</span>
<span></span>
</div>
</li>
</ul>
<Map/>
</div>
<div className={styles.screenCol}>
<FrameComp position="bottom" tabList={["全部", "总部", "苏皖大区"]}
titleImg={require("../../../assets/images/hxzgzgxljg.png")}>
<div className={styles.degreeStructure} id="degreeStructure"></div>
</FrameComp>
<FrameComp position="bottom" tabList={["全部", "总部", "苏皖大区"]}
titleImg={require("../../../assets/images/hxzgzgdjfx.png")}>
<div className={styles.gradAnalysis} id="gradAnalysis"></div>
</FrameComp>
</div>
</div>
<div className={styles.screenFooter}>
<div className={styles.screenFooterCol}>
<FrameComp position="right" tabList={["全部", "总部", "苏皖大区"]}
titleImg={require("../../../assets/images/zgxcfftj.png")}>
<div className={styles.payrollStatistics}>
<ScrollBoard
config={{
// 表头背景色
headerBGC: "#012B56",
// 奇数行背景色
oddRowBGC: "#042043",
// 偶数行背景色
evenRowBGC: "#00376D",
// 行号
index: false,
// 行号表头
// indexHeader: "序号",
// 宽度
// columnWidth: [],
// 对其方式
align: ["center"],
// 表行数
rowNum: 4,
...userOptions(salaryData)
}}
></ScrollBoard>
</div>
</FrameComp>
</div>
<div className={styles.screenFooterCol}>
<FrameComp position="right" tabList={["全部", "总部", "苏皖大区"]}
titleImg={require("../../../assets/images/hxzgzgrybdtj.png")}>
<div className={styles.personnelChangeStatistics} id="changeStatistics"/>
</FrameComp>
</div>
</div>
</div>
</div>
);
};
export default Index;

@ -0,0 +1,52 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/10
*/
import React, { FunctionComponent } from "react";
import { OrgChartNodeDataType } from "@/components/reactChart/interface";
import styles from "./index.less";
import classNames from "classnames";
interface OwnProps {
node: OrgChartNodeDataType;
}
type Props = OwnProps;
const CompanyItem: FunctionComponent<Props> = (props) => {
const { node } = props;
const classes = classNames(styles["header"], {
[styles["parent"]]: node.key === 0
});
return (
<div className={styles.companyItemWrapper}>
<div className={classes}>{node?.label}</div>
<div className={styles.contBox}>
<div>
<div>
<span></span>
<span>{node?.operatingIncome}</span>
</div>
<div>
<span></span>
<span>{node?.operatingIncomePercent}</span>
</div>
</div>
<div>
<div>
<span></span>
<span>{node?.operatingProfit}</span>
</div>
<div>
<span></span>
<span>{node?.operatingProfitPercent}</span>
</div>
</div>
</div>
</div>
);
};
export default CompanyItem;

@ -0,0 +1,94 @@
const IncomeStatisticsRadar = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("incomeStatisticsRadar"));
// 配置项
const option = {
tooltip: {
show: true
},
legend: {
show: true, //是否显示图例
icon: "rect", //图例形状
bottom: "2%", // 图例距离顶部边距
left: "center", // 图例距离左侧边距
itemWidth: 10, // 图例标记的图形宽度。[ default: 25 ]
itemHeight: 10, // 图例标记的图形高度。[ default: 14 ]
itemGap: 30, // 图例每项之间的间隔。[ default: 10 ]横向布局时为水平间隔,纵向布局时为纵向间隔。
orient: "horizontal", // 图例列表的布局朝向,'horizontal'为横向,''为纵向.
textStyle: { // 图例的公用文本样式。
fontSize: 14,
color: "#D4D4D4"
}
},
radar: {
// shape: 'circle',
// , axisLabel: { show: true } 该属性加上会报错
indicator: [
{ name: "销售", max: 20000 },
{ name: "客服", max: 20000 },
{ name: "开发", max: 20000 },
{ name: "其他", max: 20000 },
{ name: "项目", max: 20000 }
],
splitArea: {
show: false
},
axisLine: {
show: false
}
},
series: [
{
name: "人均浮动收入",
type: "radar",
data: [
{
value: [9000, 2000, 9000, 6000, 6000],
name: "人均浮动收入"
}
],
label: {
show: false,
formatter: function (params: any) {
return params.value;
}
},
itemStyle: { //此属性的颜色和下面areaStyle属性的颜色都设置成相同色即可实现
color: "#64C3FF",
borderColor: "#64C3FF"
},
areaStyle: {
color: "rgba(100,195,255,0.26)"
}
},
{
name: "人均固定收入",
type: "radar",
data: [
{
value: [5500, 8000, 5000, 8800, 8900],
name: "人均固定收入"
}
],
label: {
show: false,
formatter: function (params: any) {
return params.value;
}
},
itemStyle: { //此属性的颜色和下面areaStyle属性的颜色都设置成相同色即可实现
color: "#66EFE8",
borderColor: "#66EFE8"
},
areaStyle: {
color: "rgba(102,239,232,0.26)"
}
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default IncomeStatisticsRadar;

@ -0,0 +1,100 @@
.companyItemWrapper {
display: flex;
flex-direction: column;
.header {
height: 38px;
line-height: 38px;
text-align: center;
color: #FFF;
font-size: 16px;
background: #199DFF;
}
.parent {
background: #1E66F6 !important;
font-size: 16px;
font-weight: 700;
}
.contBox {
display: flex;
padding: 10px;
color: #B8B8B8;
font-size: 12px;
border: 1px solid rgba(25, 157, 255, 1);
border-top: none;
& > div:first-child {
border-right: 1px solid #e5e5e5;
}
& > div {
flex: 1;
display: flex;
flex-direction: column;
& > div:first-child {
margin: 10px;
}
& > div {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
& > span:last-child {
color: #787E95;
}
}
}
}
}
.regionItemWrapper {
display: flex;
flex-direction: column;
background: #EBF5FF;
min-width: 116px;
.header {
height: 38px;
line-height: 38px;
text-align: center;
color: #333333;
font-size: 16px;
}
.contBox {
display: flex;
padding: 10px 0;
color: #B8B8B8;
font-size: 12px;
& > div:first-child {
border-right: 1px solid #e5e5e5;
}
& > div {
flex: 1;
display: flex;
flex-direction: column;
& > div {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
& > span:last-child {
color: #787E95;
}
}
}
}
}
.regionItemWrapperChild {
background: #EAFCFC;
}

@ -0,0 +1,52 @@
/*
* Author:
* name:
* Description:
* Date: 2023/5/10
*/
import React, { FunctionComponent } from "react";
import { OrgChartNodeDataType } from "@/components/reactChart/interface";
import styles from "./index.less";
import classNames from "classnames";
interface OwnProps {
node: OrgChartNodeDataType;
}
type Props = OwnProps;
const RegionItem: FunctionComponent<Props> = (props) => {
const { node } = props;
const classes = classNames(styles["regionItemWrapper"], {
[styles["regionItemWrapperChild"]]: node.key === 20 || node.key === 21 || node.key === 22 || node.key === 23 || node.key === 24 || node.key === 25
});
return (
<div className={classes}>
<div className={styles.header}>{node?.label}</div>
<div className={styles.contBox}>
<div>
<div>
<span></span>
<span>{node?.operatingIncome}</span>
</div>
<div>
<span></span>
<span>{node?.operatingIncomePercent}</span>
</div>
</div>
<div>
<div>
<span></span>
<span>{node?.operatingProfit}</span>
</div>
<div>
<span></span>
<span>{node?.operatingProfitPercent}</span>
</div>
</div>
</div>
</div>
);
};
export default RegionItem;

@ -0,0 +1,133 @@
const TotalCost = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("totalCost"));
// 配置项
const option = {
tooltip: {
// 坐标轴指示器,坐标轴触发有效
trigger: "axis",
axisPointer: {
// 默认为直线,可选为:'line' | 'shadow'
type: "shadow"
}
},
legend: {
icon: "circle",
top: "5%",
right: "2%",
itemGap: 20,
textStyle: {
fontSize: 12,//字体大小
color: "#787E95"//字体颜色
}
},
grid: {
top: "20%",
left: "2%",
right: "2%",
bottom: "3%",
containLabel: true
},
xAxis: [
{
type: "category",
data: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
axisTick: {
alignWithLabel: true,
show: false
},
// 修改坐标值样式
axisLabel: {
color: "#B8B8B8",
fontSize: 16,
show: true
},
axisLine: {
show: false
}
}
],
yAxis: [
{
type: "value",
name: "万元",
// 修改坐标值样式
axisLabel: {
color: "#787E95",
fontSize: 14
// formatter: '{value} 人'
},
nameTextStyle: {
color: "#787E95",
fontSize: 16
},
// 修改坐标轴线样式
axisLine: {
show: true,
lineStyle: {
color: "transparent"
}
},
axisTick: {
show: false // 不显示坐标轴刻度线
},
splitLine: {
lineStyle: {
type: "dashed",
color: "rgba(93,126,158,1)"
}
}
}
],
series: [
{
name: "人工成本",
type: "bar",
showBackground: false,
barWidth: "20%",
data: [200, 120, 230, 225, 165, 135, 165, 120, 210, 120, 85, 210],
// bar 样式修改
itemStyle: {
color: "#4CAEFF"
}
},
{
name: "人工成本",
type: "line",
yAxisIndex: 0,
data: [190, 145, 250, 225, 165, 140, 170, 130, 215, 120, 85, 210],
itemStyle: {
normal: {
color: "#64C3FF",
lineStyle: {
color: "#64C3FF"
}
}
},
areaStyle: {
normal: {
color: {//分隔区域的颜色
x0: 0,
y0: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: "#64C3FF" // 0% 处的颜色
}, {
offset: 1,
color: "rgba(100,195,255,0)" // 100% 处的颜色中间还可以设置50%、20%、70%时的颜色
}],
globalCoord: false // 缺省为 false以确保上面的x,y,x2,y2表示的是百分比
}
}
}
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default TotalCost;

@ -0,0 +1,155 @@
const TotalLaborCostPerCapita = (echarts: any) => {
// 实例化对象
const myChart = echarts.init(document.getElementById("totalLaborCostPerCapita"));
// 配置项
const option = {
tooltip: {
// 坐标轴指示器,坐标轴触发有效
trigger: "axis",
axisPointer: {
// 默认为直线,可选为:'line' | 'shadow'
type: "line"
}
},
legend: {
icon: "circle",
top: "5%",
right: "2%",
itemGap: 20,
textStyle: {
fontSize: 12,//字体大小
color: "#787E95"//字体颜色
}
},
grid: {
top: "20%",
left: "2%",
right: "2%",
bottom: "3%",
containLabel: true
},
xAxis: [
{
type: "category",
boundaryGap: false,
data: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
axisTick: {
alignWithLabel: true,
show: false
},
// 修改坐标值样式
axisLabel: {
color: "#B8B8B8",
fontSize: 16,
show: true
},
axisLine: {
show: false
}
}
],
yAxis: [
{
type: "value",
name: "万元",
// 修改坐标值样式
axisLabel: {
color: "#787E95",
fontSize: 14
// formatter: '{value} 人'
},
nameTextStyle: {
color: "#787E95",
fontSize: 16
},
// 修改坐标轴线样式
axisLine: {
show: true,
lineStyle: {
color: "transparent"
}
},
axisTick: {
show: false // 不显示坐标轴刻度线
},
splitLine: {
lineStyle: {
type: "dashed",
color: "rgba(93,126,158,1)"
}
}
}
],
series: [
{
name: "人工福利",
type: "line",
yAxisIndex: 0,
data: [190, 145, 250, 225, 165, 140, 170, 130, 215, 120, 85, 210],
itemStyle: {
normal: {
color: "#64C3FF",
lineStyle: {
color: "#64C3FF"
}
}
},
areaStyle: {
normal: {
color: {//分隔区域的颜色
x0: 0,
y0: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: "#64C3FF" // 0% 处的颜色
}, {
offset: 1,
color: "rgba(100,195,255,0)" // 100% 处的颜色中间还可以设置50%、20%、70%时的颜色
}],
globalCoord: false // 缺省为 false以确保上面的x,y,x2,y2表示的是百分比
}
}
}
},
{
name: "人均人工成本",
type: "line",
yAxisIndex: 0,
data: [149, 145, 220, 160, 130, 165, 145, 125, 175, 110, 120, 167],
itemStyle: {
normal: {
color: "#66EFE8",
lineStyle: {
color: "#66EFE8"
}
}
},
areaStyle: {
normal: {
color: {//分隔区域的颜色
x0: 0,
y0: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: "#66EFE8" // 0% 处的颜色
}, {
offset: 1,
color: "rgba(102,239,232,0)" // 100% 处的颜色中间还可以设置50%、20%、70%时的颜色
}],
globalCoord: false // 缺省为 false以确保上面的x,y,x2,y2表示的是百分比
}
}
}
}
]
};
// 配置项给实例对象
myChart.setOption(option);
return myChart;
};
export default TotalLaborCostPerCapita;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save