feat(mes-report): 新增日产量及良率统计报表页面

新增报表页面,支持按日期范围查询日产量、良率趋势和机台良率汇总数据。
页面包含三个图表展示模块,使用 ECharts 实现数据可视化,并支持 Tab 切换与窗口自适应。
master
zangch@mesnac.com 3 months ago
parent 82cb652625
commit 36a09cdcf0

@ -0,0 +1,208 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="80px">
<el-form-item label="日期" prop="dateRange">
<el-date-picker v-model="dateRange" type="daterange" range-separator="" start-placeholder="" end-placeholder="" value-format="YYYY-MM-DD" />
</el-form-item>
<!-- 工序输入已移除固定为常量2 -->
<el-form-item label="机台" prop="machineId">
<el-input v-model="queryParams.machineId" placeholder="可选机台ID" clearable style="width: 180px" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-tabs v-model="activeTab">
<el-tab-pane label="日产量" name="daily">
<div class="chart-card">
<div ref="chartRefDaily" class="chart" />
</div>
</el-tab-pane>
<el-tab-pane label="良率趋势" name="yieldTrend">
<div class="chart-card">
<div ref="chartRefYieldTrend" class="chart" />
</div>
</el-tab-pane>
<el-tab-pane label="机台良率汇总" name="yieldMachine">
<div class="chart-card">
<div ref="chartRefYieldMachine" class="chart" />
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts" name="ReportDailyOutput">
import * as echarts from 'echarts';
import { onMounted, onBeforeUnmount, ref, getCurrentInstance, watch, nextTick } from 'vue';
import { designDailyOutputInformation, yieldTrendByDate, yieldSummaryByMachine } from '@/api/mes/prodReport';
const { proxy } = getCurrentInstance() as any;
const queryFormRef = ref();
const dateRange = ref<string[] | null>(null);
const activeTab = ref<'daily' | 'yieldTrend' | 'yieldMachine'>('daily');
// ID 2
const DEFAULT_PROCESS_ID = '2';
const queryParams = ref({
beginDate: '',
endDate: '',
processId: DEFAULT_PROCESS_ID,
machineId: ''
});
// refs for three charts
const chartRefDaily = ref<HTMLElement | null>(null);
const chartRefYieldTrend = ref<HTMLElement | null>(null);
const chartRefYieldMachine = ref<HTMLElement | null>(null);
let chartDaily: echarts.ECharts | null = null;
let chartYieldTrend: echarts.ECharts | null = null;
let chartYieldMachine: echarts.ECharts | null = null;
const initChartDaily = () => {
if (!chartRefDaily.value) return;
chartDaily = echarts.init(chartRefDaily.value, 'macarons');
chartDaily.setOption({
tooltip: { trigger: 'axis' },
grid: { left: 40, right: 20, top: 30, bottom: 40 },
xAxis: { type: 'category', boundaryGap: false, data: [] },
yAxis: { type: 'value', name: '完成数量' },
series: [{ name: '日产量', type: 'line', smooth: true, data: [], areaStyle: {} }]
});
};
const initChartYieldTrend = () => {
if (!chartRefYieldTrend.value) return;
chartYieldTrend = echarts.init(chartRefYieldTrend.value, 'macarons');
chartYieldTrend.setOption({
tooltip: { trigger: 'axis', formatter: (p: any) => `${p[0].axisValue}<br/>良率:${p[0].data || 0}%` },
grid: { left: 40, right: 20, top: 30, bottom: 40 },
xAxis: { type: 'category', boundaryGap: false, data: [] },
yAxis: { type: 'value', name: '良率(%)', min: 0, max: 100 },
series: [{ name: '良率(%)', type: 'line', smooth: true, data: [], areaStyle: {} }]
});
};
const initChartYieldMachine = () => {
if (!chartRefYieldMachine.value) return;
chartYieldMachine = echarts.init(chartRefYieldMachine.value, 'macarons');
chartYieldMachine.setOption({
tooltip: { trigger: 'axis' },
grid: { left: 60, right: 20, top: 10, bottom: 60 },
xAxis: { type: 'category', axisLabel: { rotate: 30 }, data: [] },
yAxis: { type: 'value', name: '良率(%)', min: 0, max: 100 },
series: [{ name: '良率(%)', type: 'bar', data: [] }]
});
};
const setChartDailyData = (list: Array<{ productionDate: string; completeAmount: number }>) => {
const x = list.map(i => i.productionDate);
const y = list.map(i => i.completeAmount);
chartDaily?.setOption({ xAxis: { data: x }, series: [{ data: y }] });
};
const setChartYieldTrendData = (list: Array<{ productionDate: string; yield: number }>) => {
const x = list.map(i => i.productionDate);
const y = list.map(i => Number(i.yield || 0));
chartYieldTrend?.setOption({ xAxis: { data: x }, series: [{ data: y }] });
};
const setChartYieldMachineData = (list: Array<{ machineName: string; yield: number }>) => {
const x = list.map(i => i.machineName);
const y = list.map(i => Number(i.yield || 0));
chartYieldMachine?.setOption({ xAxis: { data: x }, series: [{ data: y }] });
};
const getDailyData = async () => {
queryParams.value.beginDate = dateRange.value?.[0] || '';
queryParams.value.endDate = dateRange.value?.[1] || '';
queryParams.value.processId = DEFAULT_PROCESS_ID;
const res = await designDailyOutputInformation(queryParams.value);
setChartDailyData(res.data || []);
};
const getYieldTrend = async () => {
queryParams.value.beginDate = dateRange.value?.[0] || '';
queryParams.value.endDate = dateRange.value?.[1] || '';
queryParams.value.processId = DEFAULT_PROCESS_ID;
const res = await yieldTrendByDate(queryParams.value);
setChartYieldTrendData(res.data || []);
};
const getYieldMachine = async () => {
queryParams.value.beginDate = dateRange.value?.[0] || '';
queryParams.value.endDate = dateRange.value?.[1] || '';
queryParams.value.processId = DEFAULT_PROCESS_ID;
const res = await yieldSummaryByMachine(queryParams.value);
setChartYieldMachineData(res.data || []);
};
const handleQuery = () => {
if (activeTab.value === 'daily') return getDailyData();
if (activeTab.value === 'yieldTrend') return getYieldTrend();
if (activeTab.value === 'yieldMachine') return getYieldMachine();
};
const resetQuery = () => {
queryFormRef.value?.resetFields?.();
// 7
const end = new Date();
const start = new Date();
start.setDate(end.getDate() - 6);
const fmt = (d: Date) => proxy?.parseTime(d, '{y}-{m}-{d}');
dateRange.value = [fmt(start), fmt(end)];
// ID
queryParams.value.processId = DEFAULT_PROCESS_ID;
handleQuery();
};
onMounted(async () => {
await nextTick();
initChartDaily();
initChartYieldTrend();
initChartYieldMachine();
resetQuery();
window.addEventListener('resize', resizeChart);
});
const resizeChart = () => {
chartDaily?.resize();
chartYieldTrend?.resize();
chartYieldMachine?.resize();
};
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeChart);
chartDaily?.dispose();
chartYieldTrend?.dispose();
chartYieldMachine?.dispose();
chartDaily = chartYieldTrend = chartYieldMachine = null;
});
watch(dateRange, () => {
// Tab
handleQuery();
});
watch(activeTab, () => {
// Tab
handleQuery();
});
</script>
<style scoped>
.chart-card {
background: #fff;
padding: 12px;
border-radius: 6px;
}
.chart {
width: 100%;
height: 420px;
}
</style>
Loading…
Cancel
Save