Merge remote-tracking branch 'origin/0.8.X' into 0.8.X
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<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
|
||||
v-for="item in dictOptions"
|
||||
:key="item.dictValue"
|
||||
@@ -35,7 +40,6 @@
|
||||
width="600px"
|
||||
append-to-body
|
||||
>
|
||||
<!-- 快捷新增表单区域【仅做新增,无编辑功能】 -->
|
||||
<el-form
|
||||
ref="dictFormRef"
|
||||
:model="form"
|
||||
@@ -140,7 +144,7 @@
|
||||
</template>
|
||||
|
||||
<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'
|
||||
|
||||
export default {
|
||||
@@ -152,6 +156,7 @@ export default {
|
||||
value: { type: String, default: '' },
|
||||
placeholder: { type: String, default: '请选择' },
|
||||
refresh: { type: Boolean, default: true },
|
||||
multiple: { type: Boolean, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -178,8 +183,22 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
innerValue: {
|
||||
get() { return this.value },
|
||||
set(val) { this.$emit('input', val) }
|
||||
get() {
|
||||
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: {
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
<MemoInput storageKey="surfaceTreatmentDesc" v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入锌层"
|
||||
<el-form-item label="镀层质量">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入镀层质量"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -56,7 +56,7 @@
|
||||
<el-table-column label="材质" prop="material" />
|
||||
<el-table-column label="厂家" prop="manufacturer" />
|
||||
<el-table-column label="表面处理" prop="surfaceTreatmentDesc" />
|
||||
<el-table-column label="锌层" prop="zincLayer" />
|
||||
<el-table-column label="镀层质量" prop="zincLayer" />
|
||||
</el-table>
|
||||
|
||||
<!-- 卡片布局 -->
|
||||
@@ -74,7 +74,7 @@
|
||||
<div class="info-item">材质:<span>{{ item.material || '-' }}</span></div>
|
||||
<div class="info-item">厂家:<span>{{ item.manufacturer || '-' }}</span></div>
|
||||
<div class="info-item">表面处理:<span>{{ item.surfaceTreatmentDesc || '-' }}</span></div>
|
||||
<div class="info-item">锌层:<span>{{ item.zincLayer || '-' }}</span></div>
|
||||
<div class="info-item">镀层质量:<span>{{ item.zincLayer || '-' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
<MemoInput storageKey="surfaceTreatmentDesc" v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入锌层"
|
||||
<el-form-item label="镀层质量">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入镀层质量"
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -56,7 +56,7 @@
|
||||
<el-table-column label="材质" prop="material" />
|
||||
<el-table-column label="厂家" prop="manufacturer" />
|
||||
<el-table-column label="表面处理" prop="surfaceTreatmentDesc" />
|
||||
<el-table-column label="锌层" prop="zincLayer" />
|
||||
<el-table-column label="镀层质量" prop="zincLayer" />
|
||||
</el-table>
|
||||
|
||||
<!-- 卡片布局 -->
|
||||
@@ -74,7 +74,7 @@
|
||||
<div class="info-item">材质:<span>{{ item.material || '-' }}</span></div>
|
||||
<div class="info-item">厂家:<span>{{ item.manufacturer || '-' }}</span></div>
|
||||
<div class="info-item">表面处理:<span>{{ item.surfaceTreatmentDesc || '-' }}</span></div>
|
||||
<div class="info-item">锌层:<span>{{ item.zincLayer || '-' }}</span></div>
|
||||
<div class="info-item">镀层质量:<span>{{ item.zincLayer || '-' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<el-descriptions-item label="表面处理">
|
||||
{{ productFull.surfaceTreatment || '--' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="锌层">
|
||||
<el-descriptions-item label="镀层质量">
|
||||
{{ productFull.zincLayer || '--' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="厂家">
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
{{ product.surfaceTreatment || '--' }}
|
||||
</el-descriptions-item>
|
||||
<!-- 锌层 -->
|
||||
<el-descriptions-item label="锌层">
|
||||
<el-descriptions-item label="镀层质量">
|
||||
{{ product.zincLayer || '--' }}
|
||||
</el-descriptions-item>
|
||||
<!-- 厂家 -->
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<el-descriptions-item label="规格">{{ materialFull.specification || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="材质">{{ materialFull.material || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="表面处理">{{ materialFull.surfaceTreatment || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="锌层">{{ materialFull.zincLayer || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="镀层质量">{{ materialFull.zincLayer || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="厂家">{{ materialFull.manufacturer || '--' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
{{ material.surfaceTreatment || '--' }}
|
||||
</el-descriptions-item>
|
||||
<!-- 锌层 -->
|
||||
<el-descriptions-item label="锌层">
|
||||
<el-descriptions-item label="镀层质量">
|
||||
{{ material.zincLayer || '--' }}
|
||||
</el-descriptions-item>
|
||||
<!-- 厂家 -->
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
<el-form-item label="表面处理">
|
||||
<MemoInput storageKey="surfaceTreatmentDesc" v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入锌层" @keyup.enter.native="handleQuery" />
|
||||
<el-form-item label="镀层质量">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入镀层质量" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
<el-form-item label="表面处理">
|
||||
<MemoInput storageKey="surfaceTreatmentDesc" v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入锌层" @keyup.enter.native="handleQuery" />
|
||||
<el-form-item label="镀层质量">
|
||||
<MemoInput storageKey="zincLayer" v-model="queryParams.zincLayer" placeholder="请输入镀层质量" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
@@ -64,7 +64,7 @@
|
||||
<div class="info-item">材质:<span>{{ item.material || '-' }}</span></div>
|
||||
<div class="info-item">厂家:<span>{{ item.manufacturer || '-' }}</span></div>
|
||||
<div class="info-item">表面处理:<span>{{ item.surfaceTreatmentDesc || '-' }}</span></div>
|
||||
<div class="info-item">锌层:<span>{{ item.zincLayer || '-' }}</span></div>
|
||||
<div class="info-item">镀层质量:<span>{{ item.zincLayer || '-' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<span class="param-value">{{ item.rawMaterial.surfaceTreatment }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.rawMaterial.zincLayer">
|
||||
<span class="param-label">锌层:</span>
|
||||
<span class="param-label">镀层质量:</span>
|
||||
<span class="param-value">{{ item.rawMaterial.zincLayer }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.rawMaterial.manufacturer">
|
||||
@@ -96,7 +96,7 @@
|
||||
<span class="param-value">{{ item.product.surfaceTreatment }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.product.zincLayer">
|
||||
<span class="param-label">锌层:</span>
|
||||
<span class="param-label">镀层质量:</span>
|
||||
<span class="param-value">{{ item.product.zincLayer }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.product.manufacturer">
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<span class="param-value">{{ item.rawMaterial.surfaceTreatment }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.rawMaterial.zincLayer">
|
||||
<span class="param-label">锌层:</span>
|
||||
<span class="param-label">镀层质量:</span>
|
||||
<span class="param-value">{{ item.rawMaterial.zincLayer }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.rawMaterial.manufacturer">
|
||||
@@ -97,7 +97,7 @@
|
||||
<span class="param-value">{{ item.product.surfaceTreatment }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.product.zincLayer">
|
||||
<span class="param-label">锌层:</span>
|
||||
<span class="param-label">镀层质量:</span>
|
||||
<span class="param-value">{{ item.product.zincLayer }}</span>
|
||||
</div>
|
||||
<div class="param-row" v-if="item.product.manufacturer">
|
||||
|
||||
@@ -96,8 +96,20 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="用餐总人数" align="center" prop="totalPeople" />
|
||||
<el-table-column label="堂食人数" align="center" prop="dineInPeople" />
|
||||
<el-table-column label="打包人数" align="center" prop="takeoutPeople" />
|
||||
<el-table-column label="堂食人数" align="center" prop="dineInPeople">
|
||||
<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">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.hrm_leave_employee" :value="scope.row.reportUserName"/>
|
||||
@@ -150,11 +162,13 @@
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<DictSelect dictType="hrm_department" v-model="form.deptName" placeholder="请选择部门名称"></DictSelect>
|
||||
</el-form-item>
|
||||
<el-form-item label="堂食人数" prop="dineInPeople">
|
||||
<el-input v-model="form.dineInPeople" placeholder="请输入堂食人数" type="number" min="0" />
|
||||
<el-form-item label="堂食成员" prop="dineInPeopleList">
|
||||
<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 label="打包人数" prop="takeoutPeople">
|
||||
<el-input v-model="form.takeoutPeople" placeholder="请输入打包人数" type="number" min="0" />
|
||||
<el-form-item label="打包成员" prop="takeoutPeopleList">
|
||||
<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 label="用餐总人数" prop="totalPeople">
|
||||
<el-input v-model="form.totalPeople" placeholder="请输入用餐总人数" disabled />
|
||||
@@ -261,6 +275,16 @@ export default {
|
||||
this.calcTableSum(); // 重新计算统计数据
|
||||
});
|
||||
},
|
||||
/** 新增:处理堂食成员选择变化 */
|
||||
handleDineInPeopleChange(val) {
|
||||
this.form.dineInPeople = val?.length || 0;
|
||||
this.calcTotalPeople();
|
||||
},
|
||||
/** 新增:处理打包成员选择变化 */
|
||||
handleTakeoutPeopleChange(val) {
|
||||
this.form.takeoutPeople = val?.length || 0;
|
||||
this.calcTotalPeople();
|
||||
},
|
||||
/** 核心修改:区分有效/无效统计 */
|
||||
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>
|
||||
@@ -22,8 +22,8 @@
|
||||
<el-form-item label="表面处理" prop="surfaceTreatmentDesc">
|
||||
<el-input v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层" prop="zincLayer">
|
||||
<el-input v-model="queryParams.zincLayer" placeholder="请输入锌层" clearable />
|
||||
<el-form-item label="镀层质量" prop="zincLayer">
|
||||
<el-input v-model="queryParams.zincLayer" placeholder="请输入镀层质量" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
@@ -58,7 +58,7 @@
|
||||
<el-table-column label="材质" align="center" prop="material" />
|
||||
<el-table-column label="厂家" align="center" prop="manufacturer" />
|
||||
<el-table-column label="表面处理" align="center" prop="surfaceTreatmentDesc" />
|
||||
<el-table-column label="锌层" align="center" prop="zincLayer" />
|
||||
<el-table-column label="镀层质量" align="center" prop="zincLayer" />
|
||||
<el-table-column label="计量单位" align="center" prop="unit" />
|
||||
<el-table-column label="是否启用" align="center" prop="isEnabled">
|
||||
<template slot-scope="scope">
|
||||
@@ -117,8 +117,8 @@
|
||||
<el-input v-model="form.surfaceTreatmentDesc" placeholder="请输入表面处理" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="锌层" prop="zincLayer">
|
||||
<el-input v-model="form.zincLayer" placeholder="请输入锌层" />
|
||||
<el-form-item label="镀层质量" prop="zincLayer">
|
||||
<el-input v-model="form.zincLayer" placeholder="请输入镀层质量" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
<el-form-item label="表面处理" prop="surfaceTreatmentDesc">
|
||||
<el-input v-model="queryParams.surfaceTreatmentDesc" placeholder="请输入表面处理" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="锌层" prop="zincLayer">
|
||||
<el-input v-model="queryParams.zincLayer" placeholder="请输入锌层" clearable />
|
||||
<el-form-item label="镀层质量" prop="zincLayer">
|
||||
<el-input v-model="queryParams.zincLayer" placeholder="请输入镀层质量" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
@@ -91,7 +91,7 @@
|
||||
<el-table-column label="材质" align="center" prop="material" />
|
||||
<el-table-column label="厂家" align="center" prop="manufacturer" />
|
||||
<el-table-column label="表面处理" align="center" prop="surfaceTreatmentDesc" />
|
||||
<el-table-column label="锌层" align="center" prop="zincLayer" />
|
||||
<el-table-column label="镀层质量" align="center" prop="zincLayer" />
|
||||
<!-- <el-table-column label="参数" align="center">
|
||||
<template slot-scope="scope">
|
||||
<BomInfoMini :bomId="scope.row.bomId" />
|
||||
@@ -152,8 +152,8 @@
|
||||
<el-input v-model="form.surfaceTreatmentDesc" placeholder="请输入表面处理" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="锌层" prop="zincLayer">
|
||||
<el-input v-model="form.zincLayer" placeholder="请输入锌层" />
|
||||
<el-form-item label="镀层质量" prop="zincLayer">
|
||||
<el-input v-model="form.zincLayer" placeholder="请输入镀层质量" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
|
||||
Reference in New Issue
Block a user