feat(DictSelect): 支持多选模式并添加标签折叠功能
feat(meal): 修改用餐人数为成员选择并显示详细名单 feat: 新增用餐报表页面,包含数据统计和可视化图表
This commit is contained in:
@@ -1,7 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="display: flex; align-items: center;" v-loading="loading">
|
<div style="display: flex; align-items: center;" v-loading="loading">
|
||||||
<!-- 下拉选择器:绑定计算属性做双向绑定,保留原有样式+清空功能 -->
|
<!-- 下拉选择器:绑定计算属性做双向绑定,保留原有样式+清空功能 -->
|
||||||
<el-select v-model="innerValue" :placeholder="placeholder" clearable filterable style="width: 200px;">
|
<el-select
|
||||||
|
v-model="innerValue"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
clearable filterable
|
||||||
|
style="width: 200px;"
|
||||||
|
:multiple="multiple" collapse-tags>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in dictOptions"
|
v-for="item in dictOptions"
|
||||||
:key="item.dictValue"
|
:key="item.dictValue"
|
||||||
@@ -35,7 +40,6 @@
|
|||||||
width="600px"
|
width="600px"
|
||||||
append-to-body
|
append-to-body
|
||||||
>
|
>
|
||||||
<!-- 快捷新增表单区域【仅做新增,无编辑功能】 -->
|
|
||||||
<el-form
|
<el-form
|
||||||
ref="dictFormRef"
|
ref="dictFormRef"
|
||||||
:model="form"
|
:model="form"
|
||||||
@@ -140,7 +144,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getDicts, addData, updateData, delData, listData } from '@/api/system/dict/data'
|
import { addData, updateData, delData, listData } from '@/api/system/dict/data'
|
||||||
import { listType } from '@/api/system/dict/type'
|
import { listType } from '@/api/system/dict/type'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -152,6 +156,7 @@ export default {
|
|||||||
value: { type: String, default: '' },
|
value: { type: String, default: '' },
|
||||||
placeholder: { type: String, default: '请选择' },
|
placeholder: { type: String, default: '请选择' },
|
||||||
refresh: { type: Boolean, default: true },
|
refresh: { type: Boolean, default: true },
|
||||||
|
multiple: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -178,8 +183,22 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
innerValue: {
|
innerValue: {
|
||||||
get() { return this.value },
|
get() {
|
||||||
set(val) { this.$emit('input', val) }
|
if (this.multiple) {
|
||||||
|
if (!this.value) return []
|
||||||
|
return this.value?.split(',') || []
|
||||||
|
}
|
||||||
|
return this.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
if (this.multiple) {
|
||||||
|
this.$emit('input', val?.join(',') || '')
|
||||||
|
this.$emit('change', val)
|
||||||
|
} else {
|
||||||
|
this.$emit('input', val)
|
||||||
|
this.$emit('change', val)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
@@ -96,8 +96,20 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="用餐总人数" align="center" prop="totalPeople" />
|
<el-table-column label="用餐总人数" align="center" prop="totalPeople" />
|
||||||
<el-table-column label="堂食人数" align="center" prop="dineInPeople" />
|
<el-table-column label="堂食人数" align="center" prop="dineInPeople">
|
||||||
<el-table-column label="打包人数" align="center" prop="takeoutPeople" />
|
<template slot-scope="scope">
|
||||||
|
<el-tooltip :content="scope.row.dineInPeopleList || 0" placement="top">
|
||||||
|
<span style="cursor: pointer;">{{ scope.row.dineInPeople || 0 }}人</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="打包人数" align="center" prop="takeoutPeople">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tooltip :content="scope.row.takeoutPeopleList || 0" placement="top">
|
||||||
|
<span style="cursor: pointer;">{{ scope.row.takeoutPeople || 0 }}人</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="报餐人姓名" align="center" prop="reportUserName">
|
<el-table-column label="报餐人姓名" align="center" prop="reportUserName">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="dict.type.hrm_leave_employee" :value="scope.row.reportUserName"/>
|
<dict-tag :options="dict.type.hrm_leave_employee" :value="scope.row.reportUserName"/>
|
||||||
@@ -150,11 +162,13 @@
|
|||||||
<el-form-item label="部门名称" prop="deptName">
|
<el-form-item label="部门名称" prop="deptName">
|
||||||
<DictSelect dictType="hrm_department" v-model="form.deptName" placeholder="请选择部门名称"></DictSelect>
|
<DictSelect dictType="hrm_department" v-model="form.deptName" placeholder="请选择部门名称"></DictSelect>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="堂食人数" prop="dineInPeople">
|
<el-form-item label="堂食成员" prop="dineInPeopleList">
|
||||||
<el-input v-model="form.dineInPeople" placeholder="请输入堂食人数" type="number" min="0" />
|
<dict-select dictType="hrm_leave_employee" v-model="form.dineInPeopleList" placeholder="请选择堂食成员" multiple @change="handleDineInPeopleChange"/>
|
||||||
|
<div>({{ form.dineInPeople || 0 }}人)</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="打包人数" prop="takeoutPeople">
|
<el-form-item label="打包成员" prop="takeoutPeopleList">
|
||||||
<el-input v-model="form.takeoutPeople" placeholder="请输入打包人数" type="number" min="0" />
|
<dict-select dictType="hrm_leave_employee" v-model="form.takeoutPeopleList" placeholder="请选择打包成员" multiple @change="handleTakeoutPeopleChange"/>
|
||||||
|
<div>({{ form.takeoutPeople || 0 }}人)</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="用餐总人数" prop="totalPeople">
|
<el-form-item label="用餐总人数" prop="totalPeople">
|
||||||
<el-input v-model="form.totalPeople" placeholder="请输入用餐总人数" disabled />
|
<el-input v-model="form.totalPeople" placeholder="请输入用餐总人数" disabled />
|
||||||
@@ -261,6 +275,16 @@ export default {
|
|||||||
this.calcTableSum(); // 重新计算统计数据
|
this.calcTableSum(); // 重新计算统计数据
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/** 新增:处理堂食成员选择变化 */
|
||||||
|
handleDineInPeopleChange(val) {
|
||||||
|
this.form.dineInPeople = val?.length || 0;
|
||||||
|
this.calcTotalPeople();
|
||||||
|
},
|
||||||
|
/** 新增:处理打包成员选择变化 */
|
||||||
|
handleTakeoutPeopleChange(val) {
|
||||||
|
this.form.takeoutPeople = val?.length || 0;
|
||||||
|
this.calcTotalPeople();
|
||||||
|
},
|
||||||
/** 核心修改:区分有效/无效统计 */
|
/** 核心修改:区分有效/无效统计 */
|
||||||
calcTableSum(){
|
calcTableSum(){
|
||||||
// 初始化统计变量
|
// 初始化统计变量
|
||||||
|
|||||||
546
klp-ui/src/views/wms/hrm/report/meal.vue
Normal file
546
klp-ui/src/views/wms/hrm/report/meal.vue
Normal file
@@ -0,0 +1,546 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container" v-loading="loading">
|
||||||
|
<!-- 1. 筛选区域:日期选择器 -->
|
||||||
|
<div class="filter-wrapper" style="padding: 16px; background: #fff; margin-bottom: 16px;">
|
||||||
|
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" @change="handleDateChange" />
|
||||||
|
<el-button type="primary" style="margin-left: 8px;" @click="getMealReportList">查询</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2. 核心指标卡片 -->
|
||||||
|
<div class="card-wrapper" style="display: flex; gap: 16px; padding: 0 16px; margin-bottom: 16px;">
|
||||||
|
<el-card class="stat-card" style="flex: 1;">
|
||||||
|
<div class="stat-item">
|
||||||
|
<span class="stat-label">报餐总次数</span>
|
||||||
|
<span class="stat-value">{{ totalReportTimes }}</span>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="stat-card" style="flex: 1;">
|
||||||
|
<div class="stat-item">
|
||||||
|
<span class="stat-label">用餐总人数</span>
|
||||||
|
<span class="stat-value">{{ totalDinePeople }}</span>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="stat-card" style="flex: 1;">
|
||||||
|
<div class="stat-item">
|
||||||
|
<span class="stat-label">打包总人数</span>
|
||||||
|
<span class="stat-value">{{ totalTakeoutPeople }}</span>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="stat-card" style="flex: 1;">
|
||||||
|
<div class="stat-item">
|
||||||
|
<span class="stat-label">堂食总人数</span>
|
||||||
|
<span class="stat-value">{{ totalDineInPeople }}</span>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 3. 图表区域 -->
|
||||||
|
<div class="chart-wrapper" style="padding: 0 16px; margin-bottom: 16px;">
|
||||||
|
<div style="display: flex; gap: 16px; height: 400px;">
|
||||||
|
<!-- 3.1 按天汇总折线图 -->
|
||||||
|
<div class="chart-item" style="flex: 1;" ref="lineChart"></div>
|
||||||
|
<!-- 3.2 按餐别汇总饼图 -->
|
||||||
|
<div class="chart-item" style="flex: 1;" ref="pieChart"></div>
|
||||||
|
<!-- 3.3 按部门汇总柱状图 -->
|
||||||
|
<div class="chart-item" style="flex: 1;" ref="barChart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 4. 人员明细表格 -->
|
||||||
|
<div class="table-wrapper" style="padding: 0 16px;">
|
||||||
|
<el-table :data="userMealTableData" border style="width: 100%;" stripe>
|
||||||
|
<el-table-column label="用餐人" prop="userName" align="center" />
|
||||||
|
<el-table-column label="早餐" align="center">
|
||||||
|
<el-table-column label="堂食次数" prop="breakfastDineIn" align="center" />
|
||||||
|
<el-table-column label="打包次数" prop="breakfastTakeout" align="center" />
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="午餐" align="center">
|
||||||
|
<el-table-column label="堂食次数" prop="lunchDineIn" align="center" />
|
||||||
|
<el-table-column label="打包次数" prop="lunchTakeout" align="center" />
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="晚餐" align="center">
|
||||||
|
<el-table-column label="堂食次数" prop="dinnerDineIn" align="center" />
|
||||||
|
<el-table-column label="打包次数" prop="dinnerTakeout" align="center" />
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="夜宵" align="center">
|
||||||
|
<el-table-column label="堂食次数" prop="supperDineIn" align="center" />
|
||||||
|
<el-table-column label="打包次数" prop="supperTakeout" align="center" />
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listMealReport } from "@/api/wms/mealReport";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MealReport",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 日期范围(绑定选择器)
|
||||||
|
dateRange: [],
|
||||||
|
// 原始报表数据
|
||||||
|
mealReportList: [],
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
startTime: "",
|
||||||
|
endTime: "",
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 1000,
|
||||||
|
},
|
||||||
|
// 指标卡数据
|
||||||
|
totalReportTimes: 0, // 报餐总次数
|
||||||
|
totalDinePeople: 0, // 用餐总人数(去重)
|
||||||
|
totalTakeoutPeople: 0, // 打包总人数(去重)
|
||||||
|
totalDineInPeople: 0, // 堂食总人数(去重)
|
||||||
|
// 图表实例
|
||||||
|
lineChart: null,
|
||||||
|
pieChart: null,
|
||||||
|
barChart: null,
|
||||||
|
// 人员明细表格数据
|
||||||
|
userMealTableData: [],
|
||||||
|
// 餐别映射(1-早餐 2-午餐 3-晚餐 4-夜宵)
|
||||||
|
mealTypeMap: {
|
||||||
|
1: "早餐",
|
||||||
|
2: "午餐",
|
||||||
|
3: "晚餐",
|
||||||
|
4: "夜宵",
|
||||||
|
},
|
||||||
|
// 加载状态
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 初始化默认日期(本月第一天至今日)
|
||||||
|
this.initDefaultDate();
|
||||||
|
// 初始化图表
|
||||||
|
this.initCharts();
|
||||||
|
// 获取报表数据
|
||||||
|
this.getMealReportList();
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 销毁图表实例,防止内存泄漏
|
||||||
|
if (this.lineChart) this.lineChart.dispose();
|
||||||
|
if (this.pieChart) this.pieChart.dispose();
|
||||||
|
if (this.barChart) this.barChart.dispose();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatDateToYMD(date) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
// 月份补0(原生月份是0-11,所以要+1)
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
// 日期补0
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// ========== 修改:初始化默认日期(纯原生Date实现) ==========
|
||||||
|
initDefaultDate() {
|
||||||
|
const now = new Date(); // 当前日期
|
||||||
|
|
||||||
|
// 1. 获取本月第一天
|
||||||
|
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
|
// 2. 获取今日
|
||||||
|
const today = new Date(now);
|
||||||
|
|
||||||
|
// 格式化为 YYYY-MM-DD
|
||||||
|
const startStr = this.formatDateToYMD(startOfMonth);
|
||||||
|
const todayStr = this.formatDateToYMD(today);
|
||||||
|
|
||||||
|
// 赋值给日期选择器和查询参数
|
||||||
|
this.dateRange = [startStr, todayStr];
|
||||||
|
this.queryParams.startTime = startStr;
|
||||||
|
this.queryParams.endTime = todayStr;
|
||||||
|
},
|
||||||
|
// 初始化图表实例
|
||||||
|
initCharts() {
|
||||||
|
// 折线图(按天汇总)
|
||||||
|
this.lineChart = echarts.init(this.$refs.lineChart);
|
||||||
|
// 饼图(按餐别汇总)
|
||||||
|
this.pieChart = echarts.init(this.$refs.pieChart);
|
||||||
|
// 柱状图(按部门汇总)
|
||||||
|
this.barChart = echarts.init(this.$refs.barChart);
|
||||||
|
},
|
||||||
|
// 日期选择器变化事件
|
||||||
|
handleDateChange(val) {
|
||||||
|
if (val && val.length === 2) {
|
||||||
|
this.queryParams.startTime = val[0];
|
||||||
|
this.queryParams.endTime = val[1];
|
||||||
|
} else {
|
||||||
|
// 清空日期时重置为默认
|
||||||
|
this.initDefaultDate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取报表数据
|
||||||
|
getMealReportList() {
|
||||||
|
this.loading = true; // 显示加载中状态
|
||||||
|
listMealReport(this.queryParams)
|
||||||
|
.then((res) => {
|
||||||
|
this.mealReportList = res.rows || [];
|
||||||
|
// 处理数据:计算指标、图表、表格数据
|
||||||
|
this.handleReportData();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("获取报表数据失败:", err);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false; // 加载完成后隐藏状态
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 核心:处理报表数据(指标/图表/表格)
|
||||||
|
handleReportData() {
|
||||||
|
const list = this.mealReportList;
|
||||||
|
if (!list.length) {
|
||||||
|
// 清空数据
|
||||||
|
this.resetReportData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 1. 计算指标卡数据 ==========
|
||||||
|
// 所有人员去重(用餐总人数)
|
||||||
|
const allPeopleSet = new Set();
|
||||||
|
// 打包人员去重
|
||||||
|
const takeoutPeopleSet = new Set();
|
||||||
|
// 堂食人员去重
|
||||||
|
const dineInPeopleSet = new Set();
|
||||||
|
|
||||||
|
list.forEach((item) => {
|
||||||
|
// 拆分人员列表并去重加入集合
|
||||||
|
if (item.dineInPeopleList) {
|
||||||
|
item.dineInPeopleList.split(",").forEach((name) => {
|
||||||
|
if (name) {
|
||||||
|
dineInPeopleSet.add(name.trim());
|
||||||
|
allPeopleSet.add(name.trim());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (item.takeoutPeopleList) {
|
||||||
|
item.takeoutPeopleList.split(",").forEach((name) => {
|
||||||
|
if (name) {
|
||||||
|
takeoutPeopleSet.add(name.trim());
|
||||||
|
allPeopleSet.add(name.trim());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.totalDinePeople += item.totalPeople;
|
||||||
|
this.totalTakeoutPeople += item.takeoutPeople;
|
||||||
|
this.totalDineInPeople += item.dineInPeople;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.totalReportTimes = list.length; // 报餐总次数=记录数
|
||||||
|
// this.totalDinePeople = dineInPeopleSet.size; // 堂食总人数(去重)
|
||||||
|
// this.totalTakeoutPeople = takeoutPeopleSet.size; // 打包总人数(去重)
|
||||||
|
// this.totalDineInPeople = dineInPeopleSet.size; // 堂食总人数(去重)
|
||||||
|
|
||||||
|
// ========== 2. 处理折线图数据(按天汇总) ==========
|
||||||
|
// 按日期分组:key=日期(YYYY-MM-DD),value=统计数据
|
||||||
|
const dayGroup = {};
|
||||||
|
list.forEach((item) => {
|
||||||
|
// 格式化日期(去掉时分秒)
|
||||||
|
const reportDate = this.parseTime(item.reportDate, "{y}-{m}-{d}");
|
||||||
|
if (!dayGroup[reportDate]) {
|
||||||
|
dayGroup[reportDate] = {
|
||||||
|
reportCount: 0, // 报餐次数
|
||||||
|
totalPeople: 0, // 报餐人数
|
||||||
|
takeoutPeople: 0, // 打包人数
|
||||||
|
dineInPeople: 0, // 堂食人数
|
||||||
|
};
|
||||||
|
}
|
||||||
|
dayGroup[reportDate].reportCount += 1;
|
||||||
|
dayGroup[reportDate].totalPeople += item.totalPeople;
|
||||||
|
dayGroup[reportDate].takeoutPeople += item.takeoutPeople;
|
||||||
|
dayGroup[reportDate].dineInPeople += item.dineInPeople;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提取日期和对应数值
|
||||||
|
const dayLabels = Object.keys(dayGroup).sort(); // 按日期排序
|
||||||
|
const reportCountData = dayLabels.map((day) => dayGroup[day].reportCount);
|
||||||
|
const totalPeopleData = dayLabels.map((day) => dayGroup[day].totalPeople);
|
||||||
|
const takeoutPeopleData = dayLabels.map((day) => dayGroup[day].takeoutPeople);
|
||||||
|
const dineInPeopleData = dayLabels.map((day) => dayGroup[day].dineInPeople);
|
||||||
|
|
||||||
|
// 渲染折线图
|
||||||
|
this.renderLineChart(dayLabels, reportCountData, totalPeopleData, takeoutPeopleData, dineInPeopleData);
|
||||||
|
|
||||||
|
// ========== 3. 处理饼图数据(按餐别汇总) ==========
|
||||||
|
const mealTypeGroup = {};
|
||||||
|
list.forEach((item) => {
|
||||||
|
const mealType = item.mealType;
|
||||||
|
if (!mealTypeGroup[mealType]) {
|
||||||
|
mealTypeGroup[mealType] = {
|
||||||
|
count: 0, // 报餐次数
|
||||||
|
people: 0, // 报餐人数
|
||||||
|
};
|
||||||
|
}
|
||||||
|
mealTypeGroup[mealType].count += 1;
|
||||||
|
mealTypeGroup[mealType].people += item.totalPeople;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 饼图-报餐次数
|
||||||
|
const pieCountData = Object.keys(mealTypeGroup).map((type) => ({
|
||||||
|
name: this.mealTypeMap[type] || `未知(${type})`,
|
||||||
|
value: mealTypeGroup[type].count,
|
||||||
|
}));
|
||||||
|
// 饼图-报餐人数
|
||||||
|
const piePeopleData = Object.keys(mealTypeGroup).map((type) => ({
|
||||||
|
name: this.mealTypeMap[type] || `未知(${type})`,
|
||||||
|
value: mealTypeGroup[type].people,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 渲染饼图
|
||||||
|
this.renderPieChart(pieCountData, piePeopleData);
|
||||||
|
|
||||||
|
// ========== 4. 处理柱状图数据(按部门汇总) ==========
|
||||||
|
const deptGroup = {};
|
||||||
|
list.forEach((item) => {
|
||||||
|
const deptName = item.deptName || "未知部门";
|
||||||
|
if (!deptGroup[deptName]) {
|
||||||
|
deptGroup[deptName] = {
|
||||||
|
reportCount: 0, // 报餐次数
|
||||||
|
totalPeople: 0, // 报餐人数
|
||||||
|
takeoutPeople: 0, // 打包人数
|
||||||
|
dineInPeople: 0, // 堂食人数
|
||||||
|
};
|
||||||
|
}
|
||||||
|
deptGroup[deptName].reportCount += 1;
|
||||||
|
deptGroup[deptName].totalPeople += item.totalPeople;
|
||||||
|
deptGroup[deptName].takeoutPeople += item.takeoutPeople;
|
||||||
|
deptGroup[deptName].dineInPeople += item.dineInPeople;
|
||||||
|
});
|
||||||
|
|
||||||
|
const deptLabels = Object.keys(deptGroup);
|
||||||
|
const deptReportCount = deptLabels.map((dept) => deptGroup[dept].reportCount);
|
||||||
|
const deptTotalPeople = deptLabels.map((dept) => deptGroup[dept].totalPeople);
|
||||||
|
const deptTakeoutPeople = deptLabels.map((dept) => deptGroup[dept].takeoutPeople);
|
||||||
|
const deptDineInPeople = deptLabels.map((dept) => deptGroup[dept].dineInPeople);
|
||||||
|
|
||||||
|
// 渲染柱状图
|
||||||
|
this.renderBarChart(deptLabels, deptReportCount, deptTotalPeople, deptTakeoutPeople, deptDineInPeople);
|
||||||
|
|
||||||
|
// ========== 5. 处理人员明细表格数据 ==========
|
||||||
|
const userGroup = {};
|
||||||
|
list.forEach((item) => {
|
||||||
|
const mealType = item.mealType; // 1-早餐 2-午餐 3-晚餐 4-夜宵
|
||||||
|
// 处理堂食人员
|
||||||
|
if (item.dineInPeopleList) {
|
||||||
|
item.dineInPeopleList.split(",").forEach((name) => {
|
||||||
|
name = name.trim();
|
||||||
|
if (!name) return;
|
||||||
|
if (!userGroup[name]) {
|
||||||
|
// 初始化用户数据
|
||||||
|
userGroup[name] = {
|
||||||
|
userName: name,
|
||||||
|
breakfastDineIn: 0,
|
||||||
|
breakfastTakeout: 0,
|
||||||
|
lunchDineIn: 0,
|
||||||
|
lunchTakeout: 0,
|
||||||
|
dinnerDineIn: 0,
|
||||||
|
dinnerTakeout: 0,
|
||||||
|
supperDineIn: 0,
|
||||||
|
supperTakeout: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 根据餐别累加堂食次数
|
||||||
|
switch (mealType) {
|
||||||
|
case 1:
|
||||||
|
userGroup[name].breakfastDineIn += 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
userGroup[name].lunchDineIn += 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
userGroup[name].dinnerDineIn += 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
userGroup[name].supperDineIn += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 处理打包人员
|
||||||
|
if (item.takeoutPeopleList) {
|
||||||
|
item.takeoutPeopleList.split(",").forEach((name) => {
|
||||||
|
name = name.trim();
|
||||||
|
if (!name) return;
|
||||||
|
if (!userGroup[name]) {
|
||||||
|
userGroup[name] = {
|
||||||
|
userName: name,
|
||||||
|
breakfastDineIn: 0,
|
||||||
|
breakfastTakeout: 0,
|
||||||
|
lunchDineIn: 0,
|
||||||
|
lunchTakeout: 0,
|
||||||
|
dinnerDineIn: 0,
|
||||||
|
dinnerTakeout: 0,
|
||||||
|
supperDineIn: 0,
|
||||||
|
supperTakeout: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 根据餐别累加打包次数
|
||||||
|
switch (mealType) {
|
||||||
|
case 1:
|
||||||
|
userGroup[name].breakfastTakeout += 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
userGroup[name].lunchTakeout += 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
userGroup[name].dinnerTakeout += 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
userGroup[name].supperTakeout += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 转换为表格数组
|
||||||
|
this.userMealTableData = Object.values(userGroup);
|
||||||
|
},
|
||||||
|
// 重置报表数据(无数据时)
|
||||||
|
resetReportData() {
|
||||||
|
this.totalReportTimes = 0;
|
||||||
|
this.totalDinePeople = 0;
|
||||||
|
this.totalTakeoutPeople = 0;
|
||||||
|
this.totalDineInPeople = 0;
|
||||||
|
this.userMealTableData = [];
|
||||||
|
// 清空图表
|
||||||
|
this.lineChart.setOption({ series: [] });
|
||||||
|
this.pieChart.setOption({ series: [] });
|
||||||
|
this.barChart.setOption({ series: [] });
|
||||||
|
},
|
||||||
|
// 渲染按天汇总折线图
|
||||||
|
renderLineChart(dayLabels, reportCount, totalPeople, takeoutPeople, dineInPeople) {
|
||||||
|
const option = {
|
||||||
|
title: { text: "按天汇总数据", left: "center" },
|
||||||
|
tooltip: { trigger: "axis" },
|
||||||
|
legend: { top: "bottom", data: ["报餐次数", "报餐人数", "打包人数", "堂食人数"] },
|
||||||
|
grid: { left: "3%", right: "4%", bottom: "15%", containLabel: true },
|
||||||
|
xAxis: { type: "category", boundaryGap: false, data: dayLabels },
|
||||||
|
yAxis: { type: "value", min: 0 },
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "报餐次数",
|
||||||
|
type: "line",
|
||||||
|
data: reportCount,
|
||||||
|
smooth: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "报餐人数",
|
||||||
|
type: "line",
|
||||||
|
data: totalPeople,
|
||||||
|
smooth: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "打包人数",
|
||||||
|
type: "line",
|
||||||
|
data: takeoutPeople,
|
||||||
|
smooth: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "堂食人数",
|
||||||
|
type: "line",
|
||||||
|
data: dineInPeople,
|
||||||
|
smooth: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
this.lineChart.setOption(option);
|
||||||
|
// 自适应窗口大小
|
||||||
|
window.addEventListener("resize", () => this.lineChart.resize());
|
||||||
|
},
|
||||||
|
// 渲染按餐别汇总饼图
|
||||||
|
renderPieChart(pieCountData, piePeopleData) {
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: "按餐别汇总",
|
||||||
|
left: "center",
|
||||||
|
subtext: "次数/人数",
|
||||||
|
},
|
||||||
|
tooltip: { trigger: "item" },
|
||||||
|
legend: { orient: "vertical", left: "left", data: pieCountData.map((item) => item.name) },
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "报餐次数",
|
||||||
|
type: "pie",
|
||||||
|
radius: ["30%", "40%"],
|
||||||
|
center: ["30%", "50%"],
|
||||||
|
data: pieCountData,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "报餐人数",
|
||||||
|
type: "pie",
|
||||||
|
radius: ["30%", "40%"],
|
||||||
|
center: ["70%", "50%"],
|
||||||
|
data: piePeopleData,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
this.pieChart.setOption(option);
|
||||||
|
window.addEventListener("resize", () => this.pieChart.resize());
|
||||||
|
},
|
||||||
|
// 渲染按部门汇总柱状图
|
||||||
|
renderBarChart(deptLabels, reportCount, totalPeople, takeoutPeople, dineInPeople) {
|
||||||
|
const option = {
|
||||||
|
title: { text: "按部门汇总数据", left: "center" },
|
||||||
|
tooltip: { trigger: "axis" },
|
||||||
|
legend: { top: "bottom", data: ["报餐次数", "报餐人数", "打包人数", "堂食人数"] },
|
||||||
|
grid: { left: "3%", right: "4%", bottom: "15%", containLabel: true },
|
||||||
|
xAxis: { type: "category", data: deptLabels },
|
||||||
|
yAxis: { type: "value", min: 0 },
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: "报餐次数",
|
||||||
|
type: "bar",
|
||||||
|
data: reportCount,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "报餐人数",
|
||||||
|
type: "bar",
|
||||||
|
data: totalPeople,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "打包人数",
|
||||||
|
type: "bar",
|
||||||
|
data: takeoutPeople,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "堂食人数",
|
||||||
|
type: "bar",
|
||||||
|
data: dineInPeople,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
this.barChart.setOption(option);
|
||||||
|
window.addEventListener("resize", () => this.barChart.resize());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.stat-card {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item .stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item .stat-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #1989fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-item {
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user