spring
11 小时以前 7972a9b96ccec053cb34a7c31008c5c98c87ad9b
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">
@@ -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)
  }
}
// 修改为返回Promise的异步函数
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 ? '异常' : '正常'
  }))
}
// 刷新数据
// 修改为异步函数,确保数据加载完成后再渲染图表
const refreshData = async () => {
  loading.value = true
  try {
    // 模拟API调用延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    loading.value = true
    
    generateMockData()
    // 等待所有数据加载完成
    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
  }
@@ -277,7 +269,8 @@
      attritionChart = echarts.init(attritionChartRef.value)
    }
    
    renderAllCharts()
    // 初始化时也先加载数据再渲染图表
    refreshData()
  }, 300)
}
@@ -289,13 +282,14 @@
  renderAttritionChart()
}
// 渲染员工流动率趋势图
// 修改为使用API返回的实际数据
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: {
@@ -355,8 +349,8 @@
  if (!departmentChart) return
  
  const data = departmentData.value.map(item => ({
    name: item.department,
    value: item.currentStaff
    name: item.deptName,
    value: item.staffCount
  }))
  
  const option = {
@@ -399,7 +393,7 @@
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 = {
@@ -453,8 +447,8 @@
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: {
@@ -497,8 +491,6 @@
 
// 生命周期
onMounted(() => {
  generateMockData()
  getStaffCount()
  initCharts()
  startAutoRefresh()
})