<template>
|
<div class="app-container report-center">
|
<!-- 筛选区 -->
|
<div class="report-header">
|
<div class="header-left">
|
<span class="search_title">统计日期:</span>
|
<el-date-picker
|
v-model="dateRange"
|
type="datetimerange"
|
range-separator="至"
|
start-placeholder="开始日期时间"
|
end-placeholder="结束日期时间"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
:shortcuts="dateShortcuts"
|
style="width: 360px"
|
/>
|
<el-button type="primary" @click="handleQuery" style="margin-left: 10px">查询</el-button>
|
<el-button @click="handleReset">重置</el-button>
|
</div>
|
</div>
|
|
<!-- 一、每日过磅统计报表:车次/货量/偏差率 -->
|
<el-card class="report-card" shadow="hover">
|
<template #header>
|
<div class="card-header">
|
<span>每日过磅统计报表</span>
|
<span class="card-desc">车次、货量、偏差率</span>
|
</div>
|
</template>
|
<div class="chart-row">
|
<div class="chart-wrap" style="flex: 1; min-width: 0;">
|
<Echarts
|
:chartStyle="dailyChartStyle"
|
:grid="dailyGrid"
|
:xAxis="dailyXAxis"
|
:yAxis="dailyYAxis"
|
:series="dailySeries"
|
:tooltip="dailyTooltip"
|
:legend="dailyLegend"
|
style="height: 320px"
|
/>
|
</div>
|
</div>
|
<div class="table-wrap">
|
<el-table
|
:data="dailyTableData"
|
border
|
stripe
|
v-loading="dailyLoading"
|
style="width: 100%"
|
max-height="360"
|
>
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column prop="date" label="日期" width="120" align="center" />
|
<el-table-column prop="tripCount" label="车次" align="center" />
|
<el-table-column prop="cargoVolume" label="货量(吨)" align="center" />
|
<el-table-column prop="deviationRate" label="偏差率(%)" align="center">
|
<template #default="{ row }">
|
<span :class="getDeviationClass(row.deviationRate)">{{ row.deviationRate }}%</span>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</el-card>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, onMounted, getCurrentInstance } from "vue";
|
import Echarts from "@/components/Echarts/echarts.vue";
|
import { getDailyWeighbridgeReport } from "@/api/environmentAccess/reportCenter.js";
|
|
const { proxy } = getCurrentInstance();
|
|
// 日期范围
|
const dateRange = ref([]);
|
const dateShortcuts = [
|
{ text: "最近7天", value: () => {
|
const end = new Date();
|
const start = new Date();
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
|
return [start, end];
|
}},
|
{ text: "最近30天", value: () => {
|
const end = new Date();
|
const start = new Date();
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
return [start, end];
|
}},
|
{ text: "本月", value: () => {
|
const d = new Date();
|
return [new Date(d.getFullYear(), d.getMonth(), 1, 0, 0, 0), d];
|
}},
|
];
|
|
// 默认最近30天
|
function getDefaultDateRange() {
|
const end = new Date();
|
const start = new Date();
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
return [formatDateTime(start), formatDateTime(end)];
|
}
|
function formatDateTime(d) {
|
const y = d.getFullYear(),
|
m = String(d.getMonth() + 1).padStart(2, "0"),
|
day = String(d.getDate()).padStart(2, "0"),
|
hh = String(d.getHours()).padStart(2, "0"),
|
mm = String(d.getMinutes()).padStart(2, "0"),
|
ss = String(d.getSeconds()).padStart(2, "0");
|
return `${y}-${m}-${day} ${hh}:${mm}:${ss}`;
|
}
|
|
// 一、每日过磅统计
|
const dailyLoading = ref(false);
|
const dailyTableData = ref([]);
|
const dailyChartStyle = { width: "100%", height: "100%" };
|
const dailyGrid = { left: "3%", right: "4%", bottom: "12%", top: "10%", containLabel: true };
|
const dailyLegend = { show: true, bottom: 0, data: ["车次", "货量(吨)", "偏差率(%)"] };
|
const dailyTooltip = {
|
trigger: "axis",
|
axisPointer: { type: "shadow" },
|
};
|
const dailyXAxis = ref([{ type: "category", data: [], axisLabel: { rotate: 35 } }]);
|
const dailyYAxis = ref([
|
{ type: "value", name: "车次/货量", position: "left", min: 0 },
|
{ type: "value", name: "偏差率%", position: "right", min: 0, max: 100, axisLabel: { formatter: "{value}%" } },
|
]);
|
const dailySeries = ref([]);
|
|
// mock:每日过磅
|
function getMockDailyData() {
|
const arr = [];
|
for (let i = 6; i >= 0; i--) {
|
const d = new Date();
|
d.setDate(d.getDate() - i);
|
const dateStr = formatDate(d);
|
const trip = 20 + Math.floor(Math.random() * 30);
|
const vol = (Math.random() * 200 + 100).toFixed(1);
|
const dev = (Math.random() * 5).toFixed(2);
|
arr.push({ date: dateStr, tripCount: trip, cargoVolume: vol, deviationRate: dev });
|
}
|
return arr;
|
}
|
|
function getDeviationClass(rate) {
|
const v = parseFloat(rate);
|
if (v <= 1) return "text-success";
|
if (v <= 3) return "text-warning";
|
return "text-danger";
|
}
|
|
function buildDailyChart(arr) {
|
if (!arr || !arr.length) return;
|
dailyXAxis.value[0].data = arr.map((r) => r.date);
|
dailySeries.value = [
|
{ name: "车次", type: "bar", data: arr.map((r) => r.tripCount), itemStyle: { color: "#409EFF" } },
|
{ name: "货量(吨)", type: "bar", data: arr.map((r) => Number(r.cargoVolume)), itemStyle: { color: "#67C23A" } },
|
{ name: "偏差率(%)", type: "line", yAxisIndex: 1, data: arr.map((r) => Number(r.deviationRate)), itemStyle: { color: "#E6A23C" }, symbol: "circle", symbolSize: 8 },
|
];
|
}
|
|
function loadDailyReport() {
|
dailyLoading.value = true;
|
const [start, end] = dateRange.value && dateRange.value.length === 2 ? dateRange.value : getDefaultDateRange();
|
getDailyWeighbridgeReport({ startDate: start, endDate: end })
|
.then((res) => {
|
const list = res?.data?.list ?? res?.data ?? res?.records ?? res;
|
dailyTableData.value = Array.isArray(list) ? list : getMockDailyData();
|
buildDailyChart(dailyTableData.value);
|
})
|
.catch(() => {
|
dailyTableData.value = getMockDailyData();
|
buildDailyChart(dailyTableData.value);
|
})
|
.finally(() => { dailyLoading.value = false; });
|
}
|
|
function handleQuery() {
|
if (!dateRange.value || dateRange.value.length !== 2) {
|
dateRange.value = getDefaultDateRange();
|
}
|
loadDailyReport();
|
}
|
|
function handleReset() {
|
dateRange.value = getDefaultDateRange();
|
handleQuery();
|
}
|
|
onMounted(() => {
|
dateRange.value = getDefaultDateRange();
|
handleQuery();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.report-center {
|
.report-header {
|
display: flex;
|
align-items: center;
|
margin-bottom: 16px;
|
.header-left {
|
display: flex;
|
align-items: center;
|
}
|
.search_title {
|
margin-right: 8px;
|
white-space: nowrap;
|
}
|
}
|
.report-card {
|
margin-bottom: 20px;
|
.card-header {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
.card-desc {
|
color: #909399;
|
font-size: 13px;
|
}
|
}
|
.chart-row {
|
display: flex;
|
gap: 16px;
|
margin-bottom: 16px;
|
.chart-wrap {
|
flex: 1;
|
min-width: 0;
|
}
|
}
|
.table-wrap {
|
margin-top: 12px;
|
}
|
}
|
.text-success { color: #67c23a; }
|
.text-warning { color: #e6a23c; }
|
.text-danger { color: #f56c6c; }
|
}
|
</style>
|