From b375f09a33904abc093e874495b15a23e196ccaa Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期二, 20 一月 2026 16:42:10 +0800
Subject: [PATCH] 优化人员数据分析页面,对接接口
---
src/views/personnelManagement/analytics/index.vue | 216 ++++++++++++++++++++++++++----------------------------
1 files changed, 104 insertions(+), 112 deletions(-)
diff --git a/src/views/personnelManagement/analytics/index.vue b/src/views/personnelManagement/analytics/index.vue
index 091156d..086dad8 100644
--- a/src/views/personnelManagement/analytics/index.vue
+++ b/src/views/personnelManagement/analytics/index.vue
@@ -1,5 +1,5 @@
<template>
- <div class="app-container analytics-container">
+ <div class="app-container analytics-container" v-loading="loading">
<!-- 鍏抽敭鎸囨爣鍗$墖 -->
<el-row :gutter="20" class="metrics-cards">
@@ -11,7 +11,7 @@
<component :is="item.icon" />
</el-icon>
</div>
- <div class="card-info">
+ <div class="card-info">
<div class="card-number">
<el-skeleton-item v-if="loading" variant="text" style="width: 60px; height: 32px;" />
<span v-else>{{ item.value }}{{ item.unit }}</span>
@@ -64,21 +64,6 @@
<!-- 绗簩琛屽浘琛� -->
<el-row :gutter="20" class="charts-section">
- <!-- 缂栧埗杈炬垚鐜� -->
- <el-col :span="12">
- <el-card class="chart-card">
- <template #header>
- <div class="card-header">
- <span>缂栧埗杈炬垚鐜�</span>
- <el-tag type="warning">鍚勯儴闂ㄥ姣�</el-tag>
- </div>
- </template>
- <div class="chart-container">
- <div ref="staffingChartRef" class="chart"></div>
- </div>
- </el-card>
- </el-col>
-
<!-- 鍛樺伐娴佸け鍘熷洜鍒嗘瀽 -->
<el-col :span="12">
<el-card class="chart-card">
@@ -98,19 +83,15 @@
</template>
<script setup>
-import { ref, reactive, onMounted, onUnmounted } from 'vue'
+import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
-import {
- Refresh,
- User,
- TrendCharts,
- DataAnalysis,
- PieChart,
- ArrowUp,
- ArrowDown
-} from '@element-plus/icons-vue'
import * as echarts from 'echarts'
-import { staffOnJobListPage } from '@/api/personnelManagement/staffOnJob.js'
+import {listDept} from "@/api/system/dept.js";
+import {
+ findStaffAnalysisMonthlyTurnoverRateFor12Months,
+ findStaffLeaveReasonAnalysis,
+ findStaffAnalysisTotalStatistic
+} from "@/api/personnelManagement/staffAnalytics.js";
// 鍝嶅簲寮忔暟鎹�
const loading = ref(false)
@@ -151,14 +132,6 @@
trend: 0
},
{
- label: '缂栧埗杈炬垚鐜�',
- value: 0,
- unit: '%',
- icon: 'DataAnalysis',
- type: 'success',
- trend: 0
- },
- {
label: '鍦ㄨ亴鍛樺伐鏁�',
value: 0,
unit: '浜�',
@@ -171,16 +144,56 @@
// 閮ㄩ棬鏁版嵁
const departmentData = ref([])
+// 鍛樺伐娴佸け鍘熷洜鍒嗘瀽鏁版嵁
+const staffLeaveReasons = ref([])
+// 12涓湀鍛樺伐娴佸姩娴佸け鐜囧垎鏋愭暟鎹�
+const turnoverRateStatistics = ref([])
-// 鑾峰彇鍦ㄨ亴鍛樺伐鏁�
-const getStaffCount = async () => {
+// 鑾峰彇閮ㄩ棬鏁版嵁
+const getDepartmentData = async () => {
try {
- const res = await staffOnJobListPage({ staffState: 1, current: 1, size: 1 })
+ const res = await listDept()
if (res && res.data) {
- keyMetrics.value[3].value = res.data.total || 0
+ departmentData.value = res.data
}
} catch (error) {
- console.error('鑾峰彇鍦ㄨ亴鍛樺伐鏁板け璐�:', error)
+ console.error('鑾峰彇閮ㄩ棬鏁版嵁澶辫触:', error)
+ }
+}
+
+const getStaffLeaveReasonAnalysis = async () => {
+ try {
+ const res = await findStaffLeaveReasonAnalysis()
+ if (res && res.data) {
+ staffLeaveReasons.value = res.data || []
+ }
+ } catch (error) {
+ console.error('鑾峰彇鍛樺伐娴佸け鍘熷洜鍒嗘瀽澶辫触:', error)
+ }
+}
+
+// 淇敼涓鸿繑鍥濸romise鐨勫紓姝ュ嚱鏁�
+const getMonthlyTurnoverRateFor12Months = async () => {
+ try {
+ const res = await findStaffAnalysisMonthlyTurnoverRateFor12Months()
+ if (res && res.data) {
+ turnoverRateStatistics.value = res.data || []
+ }
+ } catch (error) {
+ console.error('鑾峰彇12涓湀鍛樺伐娴佸姩娴佸け鐜囧垎鏋愭暟鎹け璐�:', error)
+ }
+}
+
+const getStaffAnalysisTotalStatistic = async () => {
+ try {
+ const res = await findStaffAnalysisTotalStatistic()
+ if (res && res.data) {
+ keyMetrics.value[0].value = res.data.totalFlowRate || 0
+ keyMetrics.value[1].value = res.data.totalTurnoverRate || 0
+ keyMetrics.value[2].value = res.data.currentOnJobCount || 0
+ }
+ } catch (error) {
+ console.error('鑾峰彇鍛樺伐鍒嗘瀽鎬荤粺璁℃暟鎹け璐�:', error)
}
}
@@ -213,49 +226,28 @@
}
}
-// 鐢熸垚妯℃嫙鏁版嵁
-const generateMockData = () => {
- // 鐢熸垚鍏抽敭鎸囨爣鏁版嵁
- keyMetrics.value[0].value = (Math.random() * 5 + 2).toFixed(1)
- keyMetrics.value[0].trend = (Math.random() * 3 - 1.5).toFixed(1)
-
- keyMetrics.value[1].value = (Math.random() * 3 + 1).toFixed(1)
- keyMetrics.value[1].trend = (Math.random() * 2 - 1).toFixed(1)
-
- keyMetrics.value[2].value = (Math.random() * 15 + 85).toFixed(1)
- keyMetrics.value[2].trend = (Math.random() * 3 - 1.5).toFixed(1)
-
- // 鐢熸垚閮ㄩ棬鏁版嵁
- const departments = ['鎶�鏈儴', '閿�鍞儴', '浜轰簨閮�', '璐㈠姟閮�', '鐢熶骇閮�', '甯傚満閮�']
- departmentData.value = departments.map(dept => ({
- department: dept,
- currentStaff: Math.floor(Math.random() * 30 + 20),
- plannedStaff: Math.floor(Math.random() * 10 + 35),
- staffingRate: Math.floor(Math.random() * 20 + 80),
- turnoverRate: (Math.random() * 4 + 1).toFixed(1),
- attritionRate: (Math.random() * 2 + 0.5).toFixed(1),
- newHires: Math.floor(Math.random() * 5 + 1),
- resignations: Math.floor(Math.random() * 3 + 1),
- status: Math.random() > 0.7 ? '寮傚父' : '姝e父'
- }))
-}
-
-// 鍒锋柊鏁版嵁
+// 淇敼涓哄紓姝ュ嚱鏁帮紝纭繚鏁版嵁鍔犺浇瀹屾垚鍚庡啀娓叉煋鍥捐〃
const refreshData = async () => {
- loading.value = true
try {
- // 妯℃嫙API璋冪敤寤惰繜
- await new Promise(resolve => setTimeout(resolve, 500))
-
- generateMockData()
+ loading.value = true
+
+ // 绛夊緟鎵�鏈夋暟鎹姞杞藉畬鎴�
+ await Promise.all([
+ getDepartmentData(),
+ getStaffLeaveReasonAnalysis(),
+ getMonthlyTurnoverRateFor12Months(),
+ getStaffAnalysisTotalStatistic()
+ ])
+
+ await nextTick()
renderAllCharts()
-
+
if (!autoRefreshEnabled.value) {
ElMessage.success('鏁版嵁鍒锋柊鎴愬姛')
}
} catch (error) {
- console.error('鍒锋柊鏁版嵁澶辫触:', error)
- ElMessage.error('鍒锋柊鏁版嵁澶辫触')
+ console.error('鏁版嵁鍒锋柊澶辫触:', error)
+ ElMessage.error('鏁版嵁鍒锋柊澶辫触')
} finally {
loading.value = false
}
@@ -276,8 +268,9 @@
if (attritionChartRef.value) {
attritionChart = echarts.init(attritionChartRef.value)
}
-
- renderAllCharts()
+
+ // 鍒濆鍖栨椂涔熷厛鍔犺浇鏁版嵁鍐嶆覆鏌撳浘琛�
+ refreshData()
}, 300)
}
@@ -289,14 +282,15 @@
renderAttritionChart()
}
-// 娓叉煋鍛樺伐娴佸姩鐜囪秼鍔垮浘
+// 淇敼涓轰娇鐢ˋPI杩斿洖鐨勫疄闄呮暟鎹�
const renderTurnoverChart = () => {
if (!turnoverChart) return
-
- const months = ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�', '7鏈�', '8鏈�', '9鏈�', '10鏈�', '11鏈�', '12鏈�']
- const turnoverData = months.map(() => (Math.random() * 5 + 2).toFixed(1))
- const attritionData = months.map(() => (Math.random() * 3 + 1).toFixed(1))
-
+
+ // 浣跨敤API杩斿洖鐨勫疄闄呮暟鎹�
+ const months = turnoverRateStatistics.value.map(item => item.month)
+ const turnoverData = turnoverRateStatistics.value.map(item => item.flowRate || 0)
+ const attritionData = turnoverRateStatistics.value.map(item => item.turnoverRate || 0)
+
const option = {
title: {
text: '鍛樺伐娴佸姩鐜囪秼鍔�',
@@ -346,19 +340,19 @@
}
]
}
-
+
turnoverChart.setOption(option)
}
// 娓叉煋閮ㄩ棬浜哄憳鍒嗗竷鍥�
const renderDepartmentChart = () => {
if (!departmentChart) return
-
+
const data = departmentData.value.map(item => ({
- name: item.department,
- value: item.currentStaff
+ name: item.deptName,
+ value: item.staffCount
}))
-
+
const option = {
title: {
text: '閮ㄩ棬浜哄憳鍒嗗竷',
@@ -391,17 +385,17 @@
}
]
}
-
+
departmentChart.setOption(option)
}
// 娓叉煋缂栧埗杈炬垚鐜囧浘
const renderStaffingChart = () => {
if (!staffingChart) return
-
- const departments = departmentData.value.map(item => item.department)
+
+ const departments = departmentData.value.map(item => item.deptName)
const rates = departmentData.value.map(item => item.staffingRate)
-
+
const option = {
title: {
text: '缂栧埗杈炬垚鐜�',
@@ -445,17 +439,17 @@
}
]
}
-
+
staffingChart.setOption(option)
}
// 娓叉煋鍛樺伐娴佸け鍘熷洜鍒嗘瀽鍥�
const renderAttritionChart = () => {
if (!attritionChart) return
-
- const reasons = ['钖祫寰呴亣', '鑱屼笟鍙戝睍', '宸ヤ綔鐜', '涓汉鍘熷洜', '鍏朵粬']
- const data = reasons.map(() => Math.floor(Math.random() * 20 + 5))
-
+
+ const reasons = staffLeaveReasons.value.map(item => item.reasonText)
+ const data = staffLeaveReasons.value.map(item => item.count)
+
const option = {
title: {
text: '鍛樺伐娴佸け鍘熷洜鍒嗘瀽',
@@ -491,14 +485,12 @@
}
]
}
-
+
attritionChart.setOption(option)
}
-
+
// 鐢熷懡鍛ㄦ湡
onMounted(() => {
- generateMockData()
- getStaffCount()
initCharts()
startAutoRefresh()
})
@@ -663,32 +655,32 @@
.analytics-container {
padding: 10px;
}
-
+
.page-header {
padding: 15px;
}
-
+
.page-header h2 {
font-size: 24px;
}
-
+
.header-controls {
flex-direction: column;
gap: 15px;
}
-
+
.refresh-btn {
margin-left: 0;
}
-
+
.metrics-cards .el-col {
margin-bottom: 15px;
}
-
+
.charts-section .el-col {
margin-bottom: 20px;
}
-
+
.chart-container {
height: 300px;
}
@@ -698,11 +690,11 @@
.page-header h2 {
font-size: 20px;
}
-
+
.card-number {
font-size: 24px;
}
-
+
.chart-container {
height: 250px;
}
--
Gitblit v1.9.3