<template>
|
<div class="attendance-statistics">
|
<div class="statistics-controls">
|
<el-date-picker
|
v-model="selectedMonth"
|
type="month"
|
placeholder="选择统计月份"
|
value-format="yyyy-MM"
|
@change="handleMonthChange"
|
/>
|
<el-button type="primary" icon="el-icon-refresh" @click="refreshData">
|
刷新数据
|
</el-button>
|
</div>
|
|
<el-row :gutter="20" class="stats-cards">
|
<el-col :span="6">
|
<el-card shadow="hover">
|
<div class="stat-card">
|
<div class="stat-icon primary">
|
<i class="el-icon-user-solid"></i>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ stats.totalEmployees }}</div>
|
<div class="stat-label">总员工数</div>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
<el-col :span="6">
|
<el-card shadow="hover">
|
<div class="stat-card">
|
<div class="stat-icon success">
|
<i class="el-icon-success"></i>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ stats.attendanceRate }}%</div>
|
<div class="stat-label">平均出勤率</div>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
<el-col :span="6">
|
<el-card shadow="hover">
|
<div class="stat-card">
|
<div class="stat-icon warning">
|
<i class="el-icon-warning"></i>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ stats.totalLate }}</div>
|
<div class="stat-label">总迟到次数</div>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
<el-col :span="6">
|
<el-card shadow="hover">
|
<div class="stat-card">
|
<div class="stat-icon danger">
|
<i class="el-icon-error"></i>
|
</div>
|
<div class="stat-content">
|
<div class="stat-value">{{ stats.totalAbsence }}</div>
|
<div class="stat-label">总缺勤天数</div>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20" class="charts-section">
|
<el-col :span="12">
|
<el-card header="出勤趋势分析" shadow="never">
|
<div class="chart-container">
|
<!-- 这里可以集成 ECharts 图表 -->
|
<div class="chart-placeholder">
|
<i class="el-icon-data-analysis"></i>
|
<p>出勤趋势图表</p>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
<el-col :span="12">
|
<el-card header="考勤分布" shadow="never">
|
<div class="chart-container">
|
<div class="chart-placeholder">
|
<i class="el-icon-pie-chart"></i>
|
<p>考勤分布图表</p>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<el-card header="详细统计表" shadow="never" class="detail-table">
|
<el-table :data="stats.detailData" border>
|
<el-table-column prop="department" label="部门" />
|
<el-table-column prop="employeeCount" label="员工数" />
|
<el-table-column prop="attendanceDays" label="应出勤天数" />
|
<el-table-column prop="actualDays" label="实际出勤" />
|
<el-table-column prop="lateTimes" label="迟到次数" >
|
<template #default="scope">
|
<el-tag v-if="scope.row.lateTimes > 0" type="warning" size="small">
|
{{ scope.row.lateTimes }}
|
</el-tag>
|
<span v-else>{{ scope.row.lateTimes }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column prop="absenceDays" label="缺勤天数" >
|
<template #default="scope">
|
<el-tag v-if="scope.row.absenceDays > 0" type="danger" size="small">
|
{{ scope.row.absenceDays }}
|
</el-tag>
|
<span v-else>{{ scope.row.absenceDays }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column prop="attendanceRate" label="出勤率" >
|
<template #default="scope">
|
<el-progress
|
:percentage="scope.row.attendanceRate"
|
:show-text="false"
|
/>
|
<span>{{ scope.row.attendanceRate }}%</span>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: 'attendance-statistics',
|
props: {
|
data: {
|
type: Array,
|
default: () => []
|
},
|
loading: {
|
type: Boolean,
|
default: false
|
}
|
},
|
data() {
|
return {
|
selectedMonth: new Date().toISOString().slice(0, 7), // 当前年月
|
stats: {
|
totalEmployees: 0,
|
attendanceRate: 0,
|
totalLate: 0,
|
totalAbsence: 0,
|
detailData: []
|
}
|
}
|
},
|
watch: {
|
data: {
|
handler(newData) {
|
this.calculateStats(newData)
|
},
|
immediate: true
|
}
|
},
|
methods: {
|
calculateStats(data) {
|
// 模拟统计计算
|
this.stats = {
|
totalEmployees: 156,
|
attendanceRate: 92.5,
|
totalLate: 24,
|
totalAbsence: 12,
|
detailData: [
|
{ department: '技术部', employeeCount: 45, attendanceDays: 22,
|
actualDays: 41, lateTimes: 8, absenceDays: 2, attendanceRate: 93.2 },
|
{ department: '市场部', employeeCount: 32, attendanceDays: 22,
|
actualDays: 30, lateTimes: 5, absenceDays: 1, attendanceRate: 95.5 },
|
{ department: '人事部', employeeCount: 18, attendanceDays: 22,
|
actualDays: 17, lateTimes: 3, absenceDays: 4, attendanceRate: 89.3 },
|
{ department: '财务部', employeeCount: 15, attendanceDays: 22,
|
actualDays: 14, lateTimes: 2, absenceDays: 1, attendanceRate: 93.8 }
|
]
|
}
|
},
|
|
handleMonthChange(month) {
|
this.$message.info(`切换统计月份: ${month}`)
|
this.refreshData()
|
},
|
|
refreshData() {
|
this.$emit('refresh')
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.attendance-statistics {
|
padding: 20px;
|
}
|
|
.statistics-controls {
|
margin-bottom: 24px;
|
display: flex;
|
gap: 16px;
|
align-items: center;
|
}
|
|
.stats-cards {
|
margin-bottom: 24px;
|
}
|
|
.stat-card {
|
display: flex;
|
align-items: center;
|
padding: 16px;
|
}
|
|
.stat-icon {
|
width: 60px;
|
height: 60px;
|
border-radius: 50%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 16px;
|
font-size: 28px;
|
color: white;
|
}
|
|
.stat-icon.primary { background: #409EFF; }
|
.stat-icon.success { background: #67C23A; }
|
.stat-icon.warning { background: #E6A23C; }
|
.stat-icon.danger { background: #F56C6C; }
|
|
.stat-content {
|
flex: 1;
|
}
|
|
.stat-value {
|
font-size: 28px;
|
font-weight: bold;
|
color: #303133;
|
margin-bottom: 4px;
|
}
|
|
.stat-label {
|
color: #909399;
|
font-size: 14px;
|
}
|
|
.charts-section {
|
margin-bottom: 24px;
|
}
|
|
.chart-container {
|
height: 300px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.chart-placeholder {
|
text-align: center;
|
color: #909399;
|
}
|
|
.chart-placeholder i {
|
font-size: 48px;
|
margin-bottom: 16px;
|
display: block;
|
}
|
|
.detail-table {
|
margin-top: 24px;
|
}
|
</style>
|