From 8ec05fab8142361f6f78827526d9074a3ed1d1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=8E=E6=B0=B8=E9=A1=BA?= <971387674@qq.com> Date: Wed, 26 Apr 2023 11:34:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=9B=E5=BE=AE=E8=96=AA=E8=B5=84=E6=A0=B8?= =?UTF-8?q?=E7=AE=97iframe=E8=A1=A8=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/personnelReport/constants.js | 459 ++++++++++++++++++++++++- src/pages/personnelReport/index.less | 28 +- src/pages/personnelReport/index.tsx | 256 ++++++++++++-- 3 files changed, 713 insertions(+), 30 deletions(-) diff --git a/src/pages/personnelReport/constants.js b/src/pages/personnelReport/constants.js index c258040..3c52dfa 100644 --- a/src/pages/personnelReport/constants.js +++ b/src/pages/personnelReport/constants.js @@ -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,9 @@ export const rankingConfig = { dodgePadding: 2, // 分组柱状图 组间的间距 (像素级别) intervalPadding: 10, + columnStyle: { + radius: [20, 20, 0], + }, label: { // 可手动配置 label 数据标签位置 position: "middle", @@ -534,3 +537,457 @@ export const rankingConfig = { } }; +//人效分析数据 +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", + // 'top', 'middle', 'bottom' + // 可配置附加的布局方法 + layout: [ + // 柱形图数据标签位置自动调整 + { + type: "interval-adjust-position" + }, // 数据标签防遮挡 + { + type: "interval-hide-overlap" + }, // 数据标签文颜色自动调整 + { + type: "adjust-color" + } + ] + } +}; +//人效排名数据 +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 `
${text}
`; +} + + diff --git a/src/pages/personnelReport/index.less b/src/pages/personnelReport/index.less index b73becc..ec9a462 100644 --- a/src/pages/personnelReport/index.less +++ b/src/pages/personnelReport/index.less @@ -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; } } diff --git a/src/pages/personnelReport/index.tsx b/src/pages/personnelReport/index.tsx index 84b404e..18fc776 100644 --- a/src/pages/personnelReport/index.tsx +++ b/src/pages/personnelReport/index.tsx @@ -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) => {
- - {/**/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/**/} + + + + + + + + + + + + + + + + +
人员流动情况趋势图
@@ -66,7 +69,204 @@ const index: FC = (props) => {
{/*人才利润报表*/} -
+
+
+
人效分析
+ +
+
+
人效分析排名
+ + + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+
+
+
+
团队效能排名
+ + + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+ + ( + more]}> + } + title={{item.title}} + description={item.description} + /> +
{item.rank}
+
+ )} + /> +
+
+
+
+
人均收入
+ + + + + + + + +
+
+
人工成本
+ + + + + + + + +
+
{/*人员流量表*/}
@@ -75,7 +275,7 @@ const index: FC = (props) => {
详细图表
- +
培训管理分析
@@ -83,7 +283,7 @@ const index: FC = (props) => {
培训排名
- +