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 `