Merge remote-tracking branch 'origin/0.8.X' into 0.8.X
This commit is contained in:
@@ -1,10 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
<el-form-item label="入职时间" prop="changeTime">
|
<el-form-item label="入职时间">
|
||||||
<el-date-picker clearable v-model="queryParams.changeTime" type="date" value-format="yyyy-MM-dd"
|
<el-date-picker
|
||||||
placeholder="请选择入职时间">
|
v-model="queryParams.changeTimeRange"
|
||||||
</el-date-picker>
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
style="width: 240px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="异动原因" prop="changeReason">
|
<!-- <el-form-item label="异动原因" prop="changeReason">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -280,6 +286,9 @@ export default {
|
|||||||
infoId: undefined,
|
infoId: undefined,
|
||||||
changeType: 0,
|
changeType: 0,
|
||||||
changeTime: undefined,
|
changeTime: undefined,
|
||||||
|
changeStartTime: undefined,
|
||||||
|
changeEndTime: undefined,
|
||||||
|
changeTimeRange: [],
|
||||||
changeReason: undefined,
|
changeReason: undefined,
|
||||||
changeHandler: undefined,
|
changeHandler: undefined,
|
||||||
attachment: undefined,
|
attachment: undefined,
|
||||||
@@ -387,12 +396,23 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
|
// 处理时间范围
|
||||||
|
if (this.queryParams.changeTimeRange && this.queryParams.changeTimeRange.length === 2) {
|
||||||
|
this.queryParams.changeStartTime = this.queryParams.changeTimeRange[0];
|
||||||
|
this.queryParams.changeEndTime = this.queryParams.changeTimeRange[1];
|
||||||
|
} else {
|
||||||
|
this.queryParams.changeStartTime = undefined;
|
||||||
|
this.queryParams.changeEndTime = undefined;
|
||||||
|
}
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm");
|
||||||
|
this.queryParams.changeTimeRange = [];
|
||||||
|
this.queryParams.changeStartTime = undefined;
|
||||||
|
this.queryParams.changeEndTime = undefined;
|
||||||
this.handleQuery();
|
this.handleQuery();
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
|
|||||||
@@ -33,6 +33,17 @@
|
|||||||
<el-option label="已转正" value="1" />
|
<el-option label="已转正" value="1" />
|
||||||
<el-option label="未转正" value="0" />
|
<el-option label="未转正" value="0" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="转正时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryParams.regularTimeRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
style="width: 240px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="在职情况" prop="isLeave">
|
<el-form-item label="在职情况" prop="isLeave">
|
||||||
<el-select v-model="queryParams.isLeave" placeholder="请选择在职情况" clearable @change="handleQuery">
|
<el-select v-model="queryParams.isLeave" placeholder="请选择在职情况" clearable @change="handleQuery">
|
||||||
@@ -335,6 +346,11 @@ export default {
|
|||||||
age: undefined,
|
age: undefined,
|
||||||
gender: undefined,
|
gender: undefined,
|
||||||
education: undefined,
|
education: undefined,
|
||||||
|
isRegular: undefined,
|
||||||
|
isLeave: undefined,
|
||||||
|
regularStartTime: undefined,
|
||||||
|
regularEndTime: undefined,
|
||||||
|
regularTimeRange: [],
|
||||||
},
|
},
|
||||||
// 表单参数
|
// 表单参数
|
||||||
form: {},
|
form: {},
|
||||||
@@ -444,12 +460,23 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
|
// 处理时间范围
|
||||||
|
if (this.queryParams.regularTimeRange && this.queryParams.regularTimeRange.length === 2) {
|
||||||
|
this.queryParams.regularStartTime = this.queryParams.regularTimeRange[0];
|
||||||
|
this.queryParams.regularEndTime = this.queryParams.regularTimeRange[1];
|
||||||
|
} else {
|
||||||
|
this.queryParams.regularStartTime = undefined;
|
||||||
|
this.queryParams.regularEndTime = undefined;
|
||||||
|
}
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm");
|
||||||
|
this.queryParams.regularTimeRange = [];
|
||||||
|
this.queryParams.regularStartTime = undefined;
|
||||||
|
this.queryParams.regularEndTime = undefined;
|
||||||
this.handleQuery();
|
this.handleQuery();
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
|
|||||||
@@ -33,6 +33,17 @@
|
|||||||
<el-option label="已转正" value="1" />
|
<el-option label="已转正" value="1" />
|
||||||
<el-option label="未转正" value="0" />
|
<el-option label="未转正" value="0" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="入职时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryParams.entryTimeRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
style="width: 240px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="在职情况" prop="isLeave">
|
<el-form-item label="在职情况" prop="isLeave">
|
||||||
<el-select v-model="queryParams.isLeave" placeholder="请选择在职情况" clearable @change="handleQuery">
|
<el-select v-model="queryParams.isLeave" placeholder="请选择在职情况" clearable @change="handleQuery">
|
||||||
@@ -328,6 +339,11 @@ export default {
|
|||||||
age: undefined,
|
age: undefined,
|
||||||
gender: undefined,
|
gender: undefined,
|
||||||
education: undefined,
|
education: undefined,
|
||||||
|
isRegular: undefined,
|
||||||
|
isLeave: undefined,
|
||||||
|
entryStartTime: undefined,
|
||||||
|
entryEndTime: undefined,
|
||||||
|
entryTimeRange: [],
|
||||||
},
|
},
|
||||||
// 表单参数
|
// 表单参数
|
||||||
form: {},
|
form: {},
|
||||||
@@ -423,12 +439,23 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
|
// 处理时间范围
|
||||||
|
if (this.queryParams.entryTimeRange && this.queryParams.entryTimeRange.length === 2) {
|
||||||
|
this.queryParams.entryStartTime = this.queryParams.entryTimeRange[0];
|
||||||
|
this.queryParams.entryEndTime = this.queryParams.entryTimeRange[1];
|
||||||
|
} else {
|
||||||
|
this.queryParams.entryStartTime = undefined;
|
||||||
|
this.queryParams.entryEndTime = undefined;
|
||||||
|
}
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm");
|
||||||
|
this.queryParams.entryTimeRange = [];
|
||||||
|
this.queryParams.entryStartTime = undefined;
|
||||||
|
this.queryParams.entryEndTime = undefined;
|
||||||
this.handleQuery();
|
this.handleQuery();
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
<el-form-item label="离职时间" prop="changeTime">
|
<el-form-item label="离职时间">
|
||||||
<el-date-picker clearable v-model="queryParams.changeTime" type="date" value-format="yyyy-MM-dd"
|
<el-date-picker
|
||||||
placeholder="请选择离职时间">
|
v-model="queryParams.changeTimeRange"
|
||||||
</el-date-picker>
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
style="width: 240px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="异动原因" prop="changeReason">
|
<!-- <el-form-item label="异动原因" prop="changeReason">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -138,6 +144,9 @@ export default {
|
|||||||
infoId: undefined,
|
infoId: undefined,
|
||||||
changeType: 1,
|
changeType: 1,
|
||||||
changeTime: undefined,
|
changeTime: undefined,
|
||||||
|
changeStartTime: undefined,
|
||||||
|
changeEndTime: undefined,
|
||||||
|
changeTimeRange: [],
|
||||||
changeReason: undefined,
|
changeReason: undefined,
|
||||||
changeHandler: undefined,
|
changeHandler: undefined,
|
||||||
attachment: undefined,
|
attachment: undefined,
|
||||||
@@ -245,12 +254,23 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
|
// 处理时间范围
|
||||||
|
if (this.queryParams.changeTimeRange && this.queryParams.changeTimeRange.length === 2) {
|
||||||
|
this.queryParams.changeStartTime = this.queryParams.changeTimeRange[0];
|
||||||
|
this.queryParams.changeEndTime = this.queryParams.changeTimeRange[1];
|
||||||
|
} else {
|
||||||
|
this.queryParams.changeStartTime = undefined;
|
||||||
|
this.queryParams.changeEndTime = undefined;
|
||||||
|
}
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm");
|
||||||
|
this.queryParams.changeTimeRange = [];
|
||||||
|
this.queryParams.changeStartTime = undefined;
|
||||||
|
this.queryParams.changeEndTime = undefined;
|
||||||
this.handleQuery();
|
this.handleQuery();
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
|
|||||||
@@ -10,6 +10,17 @@
|
|||||||
<el-form-item label="新部门" prop="newDept">
|
<el-form-item label="新部门" prop="newDept">
|
||||||
<el-input v-model="queryParams.newDept" placeholder="请输入新部门" clearable @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.newDept" placeholder="请输入新部门" clearable @keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="转岗时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryParams.transferTimeRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
style="width: 240px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="转岗经办人" prop="transferHandler">
|
<el-form-item label="转岗经办人" prop="transferHandler">
|
||||||
<el-input v-model="queryParams.transferHandler" placeholder="请输入转岗经办人" clearable
|
<el-input v-model="queryParams.transferHandler" placeholder="请输入转岗经办人" clearable
|
||||||
@keyup.enter.native="handleQuery" />
|
@keyup.enter.native="handleQuery" />
|
||||||
@@ -146,6 +157,9 @@ export default {
|
|||||||
newDept: undefined,
|
newDept: undefined,
|
||||||
newJobType: undefined,
|
newJobType: undefined,
|
||||||
transferHandler: undefined,
|
transferHandler: undefined,
|
||||||
|
transferStartTime: undefined,
|
||||||
|
transferEndTime: undefined,
|
||||||
|
transferTimeRange: [],
|
||||||
},
|
},
|
||||||
// 部门列表
|
// 部门列表
|
||||||
deptList: [],
|
deptList: [],
|
||||||
@@ -233,12 +247,23 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
|
// 处理时间范围
|
||||||
|
if (this.queryParams.transferTimeRange && this.queryParams.transferTimeRange.length === 2) {
|
||||||
|
this.queryParams.transferStartTime = this.queryParams.transferTimeRange[0];
|
||||||
|
this.queryParams.transferEndTime = this.queryParams.transferTimeRange[1];
|
||||||
|
} else {
|
||||||
|
this.queryParams.transferStartTime = undefined;
|
||||||
|
this.queryParams.transferEndTime = undefined;
|
||||||
|
}
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm");
|
||||||
|
this.queryParams.transferTimeRange = [];
|
||||||
|
this.queryParams.transferStartTime = undefined;
|
||||||
|
this.queryParams.transferEndTime = undefined;
|
||||||
this.handleQuery();
|
this.handleQuery();
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
|
|||||||
730
klp-ui/src/views/wms/hrm/report/employee.vue
Normal file
730
klp-ui/src/views/wms/hrm/report/employee.vue
Normal file
@@ -0,0 +1,730 @@
|
|||||||
|
<template>
|
||||||
|
<div class="employee-report" v-loading="loading">
|
||||||
|
<!-- 第一行:时间段筛选 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<el-form :inline="true" class="demo-form-inline">
|
||||||
|
<el-form-item label="调动时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
type="datetimerange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
format="yyyy-MM-dd hh:mm:ss"
|
||||||
|
value-format="yyyy-MM-dd hh:mm:ss"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="入职时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="employeeDateRange"
|
||||||
|
type="datetimerange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
format="yyyy-MM-dd hh:mm:ss"
|
||||||
|
value-format="yyyy-MM-dd hh:mm:ss"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二行:员工情况统计信息和图表 -->
|
||||||
|
<div class="stats-section">
|
||||||
|
<div class="stats-cards">
|
||||||
|
<el-card shadow="hover" class="stat-card">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value">{{ stats.totalEmployees }}</div>
|
||||||
|
<div class="stat-label">总人数</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="hover" class="stat-card">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value">{{ stats.entryCount }}</div>
|
||||||
|
<div class="stat-label">入职人数</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="hover" class="stat-card">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value">{{ stats.leaveCount }}</div>
|
||||||
|
<div class="stat-label">离职人数</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="hover" class="stat-card">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value">{{ stats.regularCount }}</div>
|
||||||
|
<div class="stat-label">转正人数</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="hover" class="stat-card">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value">{{ stats.transferCount }}</div>
|
||||||
|
<div class="stat-label">调岗次数</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第三行:互动筛选图表区 -->
|
||||||
|
<div class="interactive-charts-section">
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<!-- <div slot="header" class="clearfix">
|
||||||
|
<span>学历分布</span>
|
||||||
|
</div> -->
|
||||||
|
<div id="educationChart" style="width: 100%; height: 300px;"></div>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<!-- <div slot="header" class="clearfix">
|
||||||
|
<span>年龄段分布</span>
|
||||||
|
</div> -->
|
||||||
|
<div id="ageChart" style="width: 100%; height: 300px;"></div>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<!-- <div slot="header" class="clearfix">
|
||||||
|
<span>性别分布</span>
|
||||||
|
</div> -->
|
||||||
|
<div id="genderChart" style="width: 100%; height: 300px;"></div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第四行:多轴折线图 -->
|
||||||
|
<div class="trend-section">
|
||||||
|
<!-- <el-card shadow="hover"> -->
|
||||||
|
<!-- <div slot="header" class="clearfix">
|
||||||
|
<span>员工变动趋势</span>
|
||||||
|
</div> -->
|
||||||
|
<div id="trendChart" style="width: 100%; height: 400px;"></div>
|
||||||
|
<!-- </el-card> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第五行:明细数据表 -->
|
||||||
|
<div class="details-section">
|
||||||
|
<el-tabs v-model="activeTab">
|
||||||
|
<el-tab-pane label="当前员工" name="current">
|
||||||
|
<el-table :data="currentEmployees" style="width: 100%" height="400">
|
||||||
|
<el-table-column prop="name" label="员工姓名" />
|
||||||
|
<el-table-column prop="dept" label="部门" />
|
||||||
|
<el-table-column prop="jobType" label="职位" />
|
||||||
|
<el-table-column prop="entryTime" label="入职日期" />
|
||||||
|
<!-- <el-table-column prop="status" label="状态" /> -->
|
||||||
|
<el-table-column prop="education" label="学历" />
|
||||||
|
<el-table-column prop="age" label="年龄" />
|
||||||
|
<el-table-column prop="gender" label="性别" />
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="离职记录" name="leave">
|
||||||
|
<el-table :data="leaveRecords" style="width: 100%" height="400">
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.dept" label="部门" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.jobType" label="职位" />
|
||||||
|
<el-table-column prop="changeTime" label="离职日期" />
|
||||||
|
<el-table-column prop="changeReason" label="离职原因" />
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="入职记录" name="entry">
|
||||||
|
<el-table :data="entryRecords" style="width: 100%" height="400">
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.dept" label="部门" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.jobType" label="职位" />
|
||||||
|
<el-table-column prop="entryDate" label="入职日期" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.education" label="学历" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.gender" label="性别" />
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="转正记录" name="regular">
|
||||||
|
<el-table :data="regularRecords" style="width: 100%" height="400">
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.dept" label="部门" />
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.jobType" label="职位" />
|
||||||
|
<el-table-column prop="regularDate" label="转正日期" />
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="调岗记录" name="transfer">
|
||||||
|
<el-table :data="transferRecords" style="width: 100%" height="400">
|
||||||
|
<el-table-column prop="wmsEmployeeInfo.name" label="员工姓名" />
|
||||||
|
<el-table-column prop="transferTime" label="调岗日期" />
|
||||||
|
<el-table-column prop="oldDept" label="原部门" />
|
||||||
|
<el-table-column prop="oldJobType" label="原职位" />
|
||||||
|
<el-table-column prop="newDept" label="新部门" />
|
||||||
|
<el-table-column prop="newJobType" label="新职位" />
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
import { listEmployeeInfo } from '@/api/wms/employeeInfo'
|
||||||
|
import { listEmployeeChange } from '@/api/wms/employeeChange'
|
||||||
|
import { listEmployeeTransfer } from '@/api/wms/employeeTransfer'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'EmployeeReport',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dateRange: this.getMonthRange(), // 默认选中本月
|
||||||
|
employeeDateRange: ['', ''],
|
||||||
|
shortcuts: [
|
||||||
|
{
|
||||||
|
text: '本月',
|
||||||
|
value: () => {
|
||||||
|
return this.getMonthRange()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '上个月',
|
||||||
|
value: () => {
|
||||||
|
const date = new Date()
|
||||||
|
const firstDay = new Date(date.getFullYear(), date.getMonth() - 1, 1, 0, 0, 0)
|
||||||
|
const lastDay = new Date(date.getFullYear(), date.getMonth(), 0, 23, 59, 59)
|
||||||
|
|
||||||
|
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return [formatDate(firstDay), formatDate(lastDay)]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '近三个月',
|
||||||
|
value: () => {
|
||||||
|
const date = new Date()
|
||||||
|
const lastDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
|
||||||
|
const firstDay = new Date(date.getFullYear(), date.getMonth() - 2, 1, 0, 0, 0)
|
||||||
|
|
||||||
|
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return [formatDate(firstDay), formatDate(lastDay)]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '本年',
|
||||||
|
value: () => {
|
||||||
|
const date = new Date()
|
||||||
|
const firstDay = new Date(date.getFullYear(), 0, 1, 0, 0, 0)
|
||||||
|
const lastDay = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
|
||||||
|
|
||||||
|
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return [formatDate(firstDay), formatDate(lastDay)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
stats: {
|
||||||
|
totalEmployees: 0,
|
||||||
|
regularEmployees: 0,
|
||||||
|
probationEmployees: 0,
|
||||||
|
entryCount: 0,
|
||||||
|
leaveCount: 0,
|
||||||
|
regularCount: 0,
|
||||||
|
transferCount: 0
|
||||||
|
},
|
||||||
|
currentEmployees: [],
|
||||||
|
leaveRecords: [],
|
||||||
|
entryRecords: [],
|
||||||
|
regularRecords: [],
|
||||||
|
transferRecords: [],
|
||||||
|
activeTab: 'current',
|
||||||
|
charts: {},
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 默认设置为当前月
|
||||||
|
this.dateRange = this.getMonthRange()
|
||||||
|
this.initCharts()
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getMonthRange() {
|
||||||
|
const date = new Date()
|
||||||
|
// 当月第一天,00:00:00
|
||||||
|
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0)
|
||||||
|
// 当月最后一天,23:59:59
|
||||||
|
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59)
|
||||||
|
|
||||||
|
// 格式化日期为yyyy-MM-dd HH:mm:ss格式
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return [formatDate(firstDay), formatDate(lastDay)]
|
||||||
|
},
|
||||||
|
initCharts() {
|
||||||
|
this.charts.educationChart = echarts.init(document.getElementById('educationChart'))
|
||||||
|
this.charts.ageChart = echarts.init(document.getElementById('ageChart'))
|
||||||
|
this.charts.genderChart = echarts.init(document.getElementById('genderChart'))
|
||||||
|
this.charts.trendChart = echarts.init(document.getElementById('trendChart'))
|
||||||
|
|
||||||
|
// 监听窗口大小变化,自适应图表
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
Object.values(this.charts).forEach(chart => chart.resize())
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleQuery() {
|
||||||
|
const queryParams = {
|
||||||
|
startTime: this.dateRange ? this.dateRange[0] : '',
|
||||||
|
endTime: this.dateRange ? this.dateRange[1] : '',
|
||||||
|
entryStartTime: this.employeeDateRange ? this.employeeDateRange[0] : '',
|
||||||
|
entryEndTime: this.employeeDateRange ? this.employeeDateRange[1] : '',
|
||||||
|
}
|
||||||
|
this.loadData(queryParams)
|
||||||
|
},
|
||||||
|
async loadData(queryParams) {
|
||||||
|
this.loading = true
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
this.loadEmployeeData(queryParams),
|
||||||
|
this.loadChangeData(queryParams),
|
||||||
|
this.loadTransferData(queryParams)
|
||||||
|
])
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetQuery() {
|
||||||
|
this.dateRange = this.getMonthRange()
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
loadEmployeeData(queryParams) {
|
||||||
|
console.log(queryParams)
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
listEmployeeInfo(queryParams).then(response => {
|
||||||
|
const data = response.rows
|
||||||
|
this.currentEmployees = data
|
||||||
|
|
||||||
|
// 统计当前员工信息
|
||||||
|
this.stats.totalEmployees = data.length
|
||||||
|
this.stats.regularEmployees = data.filter(item => item.status === '已转正').length
|
||||||
|
this.stats.probationEmployees = data.filter(item => item.status === '试用期').length
|
||||||
|
|
||||||
|
// 生成学历分布图表
|
||||||
|
this.updateEducationChart()
|
||||||
|
// 生成年龄段分布图表
|
||||||
|
this.updateAgeChart()
|
||||||
|
// 生成性别分布图表
|
||||||
|
this.updateGenderChart()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loadChangeData(queryParams) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
listEmployeeChange({
|
||||||
|
changeStartTime: queryParams.startTime,
|
||||||
|
changeEndTime: queryParams.endTime
|
||||||
|
}).then(response => {
|
||||||
|
const data = response.rows
|
||||||
|
|
||||||
|
// 分类处理异动记录
|
||||||
|
this.entryRecords = data.filter(item => item.changeType == 0)
|
||||||
|
this.leaveRecords = data.filter(item => item.changeType == 1)
|
||||||
|
this.regularRecords = data.filter(item => item.changeType == 2)
|
||||||
|
|
||||||
|
// 统计异动数据
|
||||||
|
this.stats.entryCount = this.entryRecords.length
|
||||||
|
this.stats.leaveCount = this.leaveRecords.length
|
||||||
|
this.stats.regularCount = this.regularRecords.length
|
||||||
|
|
||||||
|
// 更新趋势图表
|
||||||
|
this.updateTrendChart()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loadTransferData(queryParams) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
listEmployeeTransfer({
|
||||||
|
transferStartTime: queryParams.startTime,
|
||||||
|
transferEndTime: queryParams.endTime
|
||||||
|
}).then(response => {
|
||||||
|
const data = response.rows
|
||||||
|
console.log(data, '调岗记录')
|
||||||
|
this.transferRecords = data
|
||||||
|
this.stats.transferCount = data.length
|
||||||
|
|
||||||
|
// 更新趋势图表
|
||||||
|
this.updateTrendChart()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateEducationChart() {
|
||||||
|
// 统计学历分布
|
||||||
|
const educationData = {}
|
||||||
|
this.currentEmployees.forEach(emp => {
|
||||||
|
const edu = emp.education || '未知'
|
||||||
|
educationData[edu] = (educationData[edu] || 0) + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '学历分布',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '学历',
|
||||||
|
type: 'pie',
|
||||||
|
radius: '50%',
|
||||||
|
data: Object.entries(educationData).map(([name, value]) => ({ name, value })),
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
this.charts.educationChart.setOption(option)
|
||||||
|
},
|
||||||
|
updateAgeChart() {
|
||||||
|
// 统计年龄段分布
|
||||||
|
const ageGroups = {
|
||||||
|
'20岁以下': 0,
|
||||||
|
'20-30岁': 0,
|
||||||
|
'30-40岁': 0,
|
||||||
|
'40-50岁': 0,
|
||||||
|
'50岁以上': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentEmployees.forEach(emp => {
|
||||||
|
const age = parseInt(emp.age) || 0
|
||||||
|
if (age < 20) ageGroups['20岁以下']++
|
||||||
|
else if (age < 30) ageGroups['20-30岁']++
|
||||||
|
else if (age < 40) ageGroups['30-40岁']++
|
||||||
|
else if (age < 50) ageGroups['40-50岁']++
|
||||||
|
else ageGroups['50岁以上']++
|
||||||
|
})
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '年龄段分布',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: Object.keys(ageGroups)
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '人数',
|
||||||
|
type: 'bar',
|
||||||
|
data: Object.values(ageGroups),
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409EFF'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
this.charts.ageChart.setOption(option)
|
||||||
|
},
|
||||||
|
updateGenderChart() {
|
||||||
|
// 统计性别分布
|
||||||
|
const genderData = {
|
||||||
|
'男': 0,
|
||||||
|
'女': 0
|
||||||
|
}
|
||||||
|
this.currentEmployees.forEach(emp => {
|
||||||
|
if (emp.gender === '男' || emp.gender === '女') {
|
||||||
|
genderData[emp.gender]++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '性别分布',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '性别',
|
||||||
|
type: 'pie',
|
||||||
|
radius: '50%',
|
||||||
|
data: Object.entries(genderData).map(([name, value]) => ({ name, value })),
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
this.charts.genderChart.setOption(option)
|
||||||
|
},
|
||||||
|
updateTrendChart() {
|
||||||
|
// 生成时间序列数据
|
||||||
|
const timeRange = this.generateTimeRange()
|
||||||
|
const trendData = {
|
||||||
|
entry: new Array(timeRange.length).fill(0),
|
||||||
|
leave: new Array(timeRange.length).fill(0),
|
||||||
|
regular: new Array(timeRange.length).fill(0),
|
||||||
|
transfer: new Array(timeRange.length).fill(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取日期部分的辅助函数
|
||||||
|
const getDatePart = (datetime) => {
|
||||||
|
if (!datetime) return ''
|
||||||
|
return datetime.split(' ')[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充入职数据
|
||||||
|
this.entryRecords.forEach(record => {
|
||||||
|
const datePart = getDatePart(record.changeTime)
|
||||||
|
const index = timeRange.indexOf(datePart)
|
||||||
|
if (index !== -1) trendData.entry[index]++
|
||||||
|
})
|
||||||
|
|
||||||
|
// 填充离职数据
|
||||||
|
this.leaveRecords.forEach(record => {
|
||||||
|
const datePart = getDatePart(record.changeTime)
|
||||||
|
const index = timeRange.indexOf(datePart)
|
||||||
|
if (index !== -1) trendData.leave[index]++
|
||||||
|
})
|
||||||
|
|
||||||
|
// 填充转正数据
|
||||||
|
this.regularRecords.forEach(record => {
|
||||||
|
const datePart = getDatePart(record.changeTime)
|
||||||
|
const index = timeRange.indexOf(datePart)
|
||||||
|
if (index !== -1) trendData.regular[index]++
|
||||||
|
})
|
||||||
|
|
||||||
|
// 填充调岗数据
|
||||||
|
this.transferRecords.forEach(record => {
|
||||||
|
const datePart = getDatePart(record.transferTime)
|
||||||
|
const index = timeRange.indexOf(datePart)
|
||||||
|
if (index !== -1) trendData.transfer[index]++
|
||||||
|
})
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '员工变动趋势',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['入职', '离职', '转正', '调岗'],
|
||||||
|
bottom: 0
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '15%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: timeRange
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '入职',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
data: trendData.entry,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#67C23A'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '离职',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
data: trendData.leave,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#F56C6C'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '转正',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
data: trendData.regular,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409EFF'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '调岗',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
data: trendData.transfer,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#E6A23C'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
this.charts.trendChart.setOption(option)
|
||||||
|
},
|
||||||
|
generateTimeRange() {
|
||||||
|
// 生成时间范围内的日期数组
|
||||||
|
const start = this.dateRange && this.dateRange[0] ? new Date(this.dateRange[0]) : new Date()
|
||||||
|
const end = this.dateRange && this.dateRange[1] ? new Date(this.dateRange[1]) : new Date()
|
||||||
|
const timeRange = []
|
||||||
|
|
||||||
|
// 如果没有设置时间范围,默认显示最近30天
|
||||||
|
if (!this.dateRange || !this.dateRange[0] || !this.dateRange[1]) {
|
||||||
|
const thirtyDaysAgo = new Date()
|
||||||
|
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30)
|
||||||
|
start.setTime(thirtyDaysAgo.getTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
const current = new Date(start)
|
||||||
|
while (current <= end) {
|
||||||
|
const dateStr = current.toISOString().split('T')[0]
|
||||||
|
timeRange.push(dateStr)
|
||||||
|
current.setDate(current.getDate() + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeRange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.employee-report {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
gap: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #409EFF;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-chart {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interactive-charts-section {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trend-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details-section {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user