泛微薪资核算iframe表格

custom-人事报表/V2-demo
黎永顺 2 years ago
parent 093e4838a8
commit 8ec05fab81

@ -1,4 +1,4 @@
import { G2 } from "@ant-design/plots";
import { G2, measureTextWidth } from "@ant-design/plots";
const G = G2.getEngine("canvas");
@ -514,6 +514,72 @@ export const rankingConfig = {
dodgePadding: 2,
// 分组柱状图 组间的间距 (像素级别)
intervalPadding: 10,
columnStyle: {
radius: [20, 20, 0],
},
label: {
// 可手动配置 label 数据标签位置
position: "middle",
// 'top', 'middle', 'bottom'
// 可配置附加的布局方法
layout: [
// 柱形图数据标签位置自动调整
{
type: "interval-adjust-position"
}, // 数据标签防遮挡
{
type: "interval-hide-overlap"
}, // 数据标签文颜色自动调整
{
type: "adjust-color"
}
]
}
};
//人效分析数据
export const humanAnalysisData = [
{
"name": "销售投入回报",
"company": "公司1",
"value": 18.9
},
{
"name": "销售投入回报",
"company": "公司2",
"value": 28.8
},
{
"name": "人均利润",
"company": "公司1",
"value": 12.4
},
{
"name": "人均利润",
"company": "公司2",
"value": 23.2
},
{
"name": "人均销售额",
"company": "公司1",
"value": 12.4
},
{
"name": "人均销售额",
"company": "公司2",
"value": 23.2
}
];
export const humanAnalysisconfig = {
data: humanAnalysisData,
isGroup: true,
xField: "company",
yField: "value",
seriesField: "name",
// 分组柱状图 组内柱子间的间距 (像素级别)
dodgePadding: 2,
// 分组柱状图 组间的间距 (像素级别)
intervalPadding: 50,
label: {
// 可手动配置 label 数据标签位置
position: "middle",
@ -533,4 +599,395 @@ export const rankingConfig = {
]
}
};
//人效排名数据
export const humanEfficiencyRankingData = [
{
title: '员工1',
description: "公司1",
rank:1
},
{
title: '员工2',
description: "公司2",
rank:2
},
{
title: '员工3',
description: "公司3",
rank:3
},
{
title: '员工4',
description: "公司4",
rank:4
},
];
//销售新客户合同数量排名
export const saleEfficiencyRankingData = [
{
title: '员工5',
description: "公司1",
rank:1
},
{
title: '员工6',
description: "公司2",
rank:2
},
{
title: '员工7',
description: "公司3",
rank:3
},
{
title: '员工8',
description: "公司4",
rank:4
},
];
//新销售有效合同
export const newSaleEfficiencyRankingData = [
{
title: '员工9',
description: "公司1",
rank:1
},
{
title: '员工10',
description: "公司2",
rank:2
},
{
title: '员工11',
description: "公司3",
rank:3
},
{
title: '员工12',
description: "公司4",
rank:4
},
];
//人工总成本数据
export const totalLaborCostdata = [
{
time: 'Jan.',
value: 350,
count: 800,
},
{
time: 'Feb.',
value: 900,
count: 600,
},
{
time: 'Mar.',
value: 300,
count: 400,
},
{
time: 'Apr.',
value: 450,
count: 380,
},
{
time: 'May.',
value: 470,
count: 220,
},
{
time: 'Jun.',
value: 470,
count: 220,
},
{
time: 'Jul.',
value: 470,
count: 220,
},
{
time: 'Aug.',
value: 470,
count: 220,
},
];
export const totalLaborCostConfig = {
data: [totalLaborCostdata, totalLaborCostdata],
xField: 'time',
yField: ['value', 'count'],
yAxis: {
// 格式化左坐标轴
value: {
min: 0,
label: {
formatter: (val) => `${val}W`,
},
},
// 隐藏右坐标轴
count: false,
},
geometryOptions: [
{
geometry: 'column',
color: '#5B8FF9',
columnWidthRatio: 0.4,
label: {
position: 'middle',
},
},
{
geometry: 'line',
smooth: true,
color: '#5AD8A6',
},
],
interactions: [
{
type: 'element-highlight',
},
{
type: 'active-region',
},
],
annotations: {
value: [
{
type: 'text',
position: ['2019-06', 'max'],
content: '柱线混合图',
},
],
count: [
{
type: 'dataMarker',
top: true,
position: ['2019-05', 400],
line: {
length: 20,
},
text: {
content: '2019-05, 发布新版本',
style: {
textAlign: 'left',
},
},
},
],
},
};
//人均收入配置数据 1、人均固定收入 2、人均浮动收入
export const fixedIncomePerData = [
{
type: '销售',
value: 27,
},
{
type: '项目',
value: 25,
},
{
type: '开发',
value: 18,
},
{
type: '客服',
value: 15,
},
{
type: '其他',
value: 10,
},
{
type: '其他',
value: 5,
},
];
export const floatingIncomePerData = [
{
type: '销售',
value: 18,
},
{
type: '项目',
value: 29,
},
{
type: '开发',
value: 23,
},
{
type: '客服',
value: 3,
},
{
type: '其他',
value: 22,
},
{
type: '其他',
value: 5,
},
];
//人均收入配置信息
export const perCapitaIncomeConfig = {
appendPadding: 10,
data:[],
angleField: 'value',
colorField: 'type',
radius: 1,
innerRadius: 0.64,
meta: {
value: {
formatter: (v) => `${v} ¥`,
},
},
label: {
type: 'inner',
offset: '-50%',
style: {
textAlign: 'center',
},
autoRotate: false,
content: '{value}',
},
statistic: {
title: {
offsetY: -4,
customHtml: (container, view, datum) => {
const { width, height } = container.getBoundingClientRect();
const d = Math.sqrt(Math.pow(width / 2, 2) + Math.pow(height / 2, 2));
//总计
const text = datum ? datum.type : '';
return renderStatistic(d, text, {
fontSize: 28,
});
},
},
content: {
offsetY: 4,
style: {
fontSize: '32px',
},
customHtml: (container, view, datum, data) => {
const { width } = container.getBoundingClientRect();
const text = datum ? `¥ ${datum.value}` : `¥ ${data.reduce((r, d) => r + d.value, 0)}`;
return renderStatistic(width, "", {
fontSize: 32,
});
},
},
},
// 添加 中心统计文本 交互
interactions: [
],
};
//人均人工成本数据
export const laborCostsPerCapitaData = [
{
year: 'Jan.',
value: 3,
count: 10,
},
{
year: 'Feb.',
value: 4,
count: 4,
},
{
year: 'Mar.',
value: 3.5,
count: 5,
},
{
year: 'Apr.',
value: 5,
count: 5,
},
{
year: 'May.',
value: 4.9,
count: 4.9,
},
{
year: 'Jun.',
value: 6,
count: 35,
},
{
year: 'Jul.',
value: 7,
count: 7,
},
{
year: 'Aug.',
value: 9,
count: 1,
},
];
export const laborCostsPerCapitaConfig = {
data: [laborCostsPerCapitaData, laborCostsPerCapitaData],
xField: 'year',
yField: ['value', 'count'],
geometryOptions: [
{
geometry: 'line',
smooth: true,
color: '#5B8FF9',
label: {
formatter: (datum) => {
return `${datum.value}w`;
},
},
lineStyle: {
lineWidth: 3,
lineDash: [5, 5],
},
},
{
geometry: 'line',
smooth: true,
color: '#5AD8A6',
lineStyle: {
lineWidth: 4,
opacity: 0.5,
},
label: {
formatter: (datum) => {
return `${datum.count}w`;
},
},
point: {
shape: 'circle',
size: 4,
style: {
opacity: 0.5,
stroke: '#5AD8A6',
fill: '#fff',
},
},
},
],
};
function renderStatistic(containerWidth, text, style) {
const { width: textWidth, height: textHeight } = measureTextWidth(text, style);
const R = containerWidth / 2; // r^2 = (w / 2)^2 + (h - offsetY)^2
let scale = 1;
if (containerWidth < textWidth) {
scale = Math.min(Math.sqrt(Math.abs(Math.pow(R, 2) / (Math.pow(textWidth / 2, 2) + Math.pow(textHeight, 2)))), 1);
}
const textStyleStr = `width:${containerWidth}px;`;
return `<div style="${textStyleStr};font-size:${scale}em;line-height:${scale < 1 ? 1 : 'inherit'};">${text}</div>`;
}

@ -5,8 +5,9 @@
height: 100%;
background: #e5e5e5;
padding: 8px;
overflow: hidden;
.talentTableBox, .flowRateTableBox {
.talentTableBox, .flowRateTableBox, .profitTableBox {
display: flex;
align-items: center;
@ -22,6 +23,29 @@
padding: 40px 10px 8px;
overflow: hidden;
:global {
.ant-tabs {
height: 100%;
line-height: normal;
.ant-tabs-content-holder {
flex: 1;
.ant-tabs-content {
height: 100%;
.ant-tabs-tabpane {
overflow-y: auto;
& > div {
height: 100% !important;
}
}
}
}
}
}
.title {
position: absolute;
left: 2%;
@ -33,6 +57,8 @@
}
& > div {
margin-bottom: 8px;
flex: 1;
overflow: hidden;
}
}

@ -1,23 +1,27 @@
import React, { FC } from "react";
import { Tabs } from "antd";
import { Column, Funnel, Pie } from "@ant-design/plots";
import { Avatar, List, Tabs } from "antd";
import { Column, Funnel, Pie, DualAxes } from "@ant-design/plots";
import {
degreeData,
flowingConfig,
flowingTrendconfig,
genderData,
humanAnalysisconfig,
humanEfficiencyRankingData,
institutionConfig,
internData,
linesData,
multiplData,
multipleConfig, newSaleEfficiencyRankingData,
personChangeConfig,
personChangeData,
rankingConfig,
rankingData, saleEfficiencyRankingData,
seniorityConfig,
seniorityData,
multiplData,
multipleConfig,
trainingData,
rankingData,
rankingConfig
trainingData,totalLaborCostConfig,
laborCostsPerCapitaConfig,
perCapitaIncomeConfig, fixedIncomePerData, floatingIncomePerData
} from "./constants";
import styles from "./index.less";
@ -37,24 +41,23 @@ const index: FC<Props> = (props) => {
<Pie {...flowingConfig} />
</div>
<div style={{ paddingTop: 0 }}>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="司龄占比" key="1">
<Pie {...seniorityConfig} data={seniorityData}/>
{/*<Tabs defaultActiveKey="1">*/}
{/* <Tabs.TabPane tab="司龄占比" key="1">*/}
{/* <Pie {...seniorityConfig} data={seniorityData}/>*/}
{/* </Tabs.TabPane>*/}
{/* <Tabs.TabPane tab="性别占比" key="2">*/}
{/* <Pie {...seniorityConfig} data={genderData}/>*/}
{/* </Tabs.TabPane>*/}
{/* <Tabs.TabPane tab="学历分布" key="3">*/}
{/* <Pie {...seniorityConfig} data={degreeData}/>*/}
{/* </Tabs.TabPane>*/}
{/* <Tabs.TabPane tab="条线占比" key="4">*/}
{/* <Pie {...seniorityConfig} data={linesData}/>*/}
{/* </Tabs.TabPane>*/}
{/* <Tabs.TabPane tab="实习生占比" key="5">*/}
{/* <Pie {...seniorityConfig} data={internData}/>*/}
{/* </Tabs.TabPane>*/}
{/*</Tabs>*/}
</Tabs.TabPane>
<Tabs.TabPane tab="性别占比" key="2">
<Pie {...seniorityConfig} data={genderData}/>
</Tabs.TabPane>
<Tabs.TabPane tab="学历分布" key="3">
<Pie {...seniorityConfig} data={degreeData}/>
</Tabs.TabPane>
<Tabs.TabPane tab="条线占比" key="4">
<Pie {...seniorityConfig} data={linesData}/>
</Tabs.TabPane>
<Tabs.TabPane tab="实习生占比" key="5">
<Pie {...seniorityConfig} data={internData}/>
</Tabs.TabPane>
</Tabs>
</div>
<div>
<div className={styles.title}></div>
@ -66,7 +69,204 @@ const index: FC<Props> = (props) => {
</div>
</div>
{/*人才利润报表*/}
<div className={styles.profitTableBox}></div>
<div className={styles.profitTableBox}>
<div>
<div className={styles.title}></div>
<Column {...humanAnalysisconfig} />
</div>
<div>
<div className={styles.title}></div>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="有效金额排名" key="1">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="合同数量排名" key="2">
<List
itemLayout="horizontal"
dataSource={saleEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="有效合同排名" key="3">
<List
itemLayout="horizontal"
dataSource={newSaleEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
</Tabs>
</div>
<div>
<div className={styles.title}></div>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="指标400万" key="1">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="400万≤指标600万" key="2">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="600万≤指标800万" key="3">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="800万≤指标1200万" key="4">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="1200万≤指标1600万" key="5">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="1600万≤指标3000万" key="6">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="指标>=3000万" key="7">
<List
itemLayout="horizontal"
dataSource={humanEfficiencyRankingData}
renderItem={item => (
<List.Item actions={[<a key="list-loadmore-more">more</a>]}>
<List.Item.Meta
avatar={<Avatar src="https://joeschmoe.io/api/v1/random"/>}
title={<a href="https://ant.design">{item.title}</a>}
description={item.description}
/>
<div>{item.rank}</div>
</List.Item>
)}
/>
</Tabs.TabPane>
</Tabs>
</div>
<div>
<div className={styles.title}></div>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="人均固定收入" key="1">
<Pie {...perCapitaIncomeConfig} data={fixedIncomePerData}/>
</Tabs.TabPane>
<Tabs.TabPane tab="人均浮动收入" key="2">
<Pie {...perCapitaIncomeConfig} data={floatingIncomePerData}/>
</Tabs.TabPane>
</Tabs>
</div>
<div>
<div className={styles.title}></div>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="人工总成本" key="1">
<DualAxes {...totalLaborCostConfig} />
</Tabs.TabPane>
<Tabs.TabPane tab="人均人工成本" key="2">
<DualAxes {...laborCostsPerCapitaConfig} />
</Tabs.TabPane>
</Tabs>
</div>
</div>
{/*人员流量表*/}
<div className={styles.flowRateTableBox}>
<div>
@ -75,7 +275,7 @@ const index: FC<Props> = (props) => {
</div>
<div>
<div className={styles.title}></div>
<Column {...multipleConfig} data={multiplData} />
<Column {...multipleConfig} data={multiplData}/>
</div>
<div>
<div className={styles.title}></div>
@ -83,7 +283,7 @@ const index: FC<Props> = (props) => {
</div>
<div>
<div className={styles.title}></div>
<Column {...rankingConfig} data={rankingData} />
<Column {...rankingConfig} data={rankingData}/>
</div>
</div>
</div>

Loading…
Cancel
Save