From 0fa137570bf7ac2bf58c8af2828cd595625fa400 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期日, 19 四月 2026 18:53:45 +0800
Subject: [PATCH] Merge branch 'dev' of http://115.159.85.185:8098/r/SuZhouGuanHong/ShanMeiXinNengYuan into dev
---
Code/WMS/WIDESEA_WMSClient/src/views/Home.vue | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 373 insertions(+), 8 deletions(-)
diff --git a/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue b/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
index 820437a..ea951db 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
+++ b/Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
@@ -1,24 +1,389 @@
<template>
- <div class="title"></div>
+ <div class="dashboard-container">
+ <!-- 椤堕儴锛氭湰鏈堝嚭鍏ュ簱瓒嬪娍 (鍏ㄥ) -->
+ <div class="chart-row full-width">
+ <div class="chart-card">
+ <div class="card-title">姣忔湀鍑哄叆搴撹秼鍔�</div>
+ <div id="chart-monthly-trend" class="chart-content"></div>
+ </div>
+ </div>
+
+ <!-- 绗簩琛岋細姣忔棩鍑哄叆搴撹秼鍔� (鍏ㄥ) -->
+ <div class="chart-row full-width">
+ <div class="chart-card">
+ <div class="card-title">姣忔棩鍑哄叆搴撹秼鍔�</div>
+ <div id="chart-daily" class="chart-content"></div>
+ </div>
+ </div>
+
+ <!-- 绗洓琛岋細浠撳簱鍒嗗竷 -->
+ <div class="chart-row">
+ <div class="chart-card">
+ <div class="card-title">鍚勪粨搴撳簱瀛樺垎甯�</div>
+ <div id="chart-warehouse" class="chart-content"></div>
+ </div>
+ </div>
+ </div>
</template>
<script>
-import { ref, reactive } from 'vue'
+import * as echarts from "echarts";
export default {
- setup() {
+ name: "Home",
+ data() {
return {
+ charts: {},
+ dailyData: [],
+ monthlyData: [],
+ warehouseData: []
+ };
+ },
+ mounted() {
+ this.initCharts();
+ this.loadData();
+ window.addEventListener("resize", this.handleResize);
+ },
+ beforeUnmount() {
+ window.removeEventListener("resize", this.handleResize);
+ Object.values(this.charts).forEach(chart => chart.dispose());
+ },
+ methods: {
+ handleResize() {
+ Object.values(this.charts).forEach(chart => chart.resize());
+ },
+ initCharts() {
+ this.charts.monthlyTrend = echarts.init(document.getElementById("chart-monthly-trend"));
+ this.charts.daily = echarts.init(document.getElementById("chart-daily"));
+ this.charts.warehouse = echarts.init(document.getElementById("chart-warehouse"));
+ },
+
+ async loadData() {
+ await this.loadMonthlyStats();
+ await this.loadDailyStats();
+ await this.loadStockByWarehouse();
+ },
+
+ async loadMonthlyStats() {
+ try {
+ const res = await this.http.get("/api/Dashboard/MonthlyStats", { months: 12 });
+ if (res.status && res.data) {
+ console.log("姣忔湀缁熻鏁版嵁:", res.data);
+ this.monthlyData = res.data;
+ this.updateMonthlyTrendChart();
+ }
+ } catch (e) {
+ console.error("鍔犺浇姣忔湀缁熻澶辫触", e);
+ }
+ },
+
+ async loadDailyStats() {
+ try {
+ const res = await this.http.get("/api/Dashboard/DailyStats", { days: 30 });
+ if (res.status && res.data) {
+ console.log("姣忔棩缁熻鏁版嵁:", res.data);
+ this.dailyData = res.data;
+ this.updateDailyChart();
+ }
+ } catch (e) {
+ console.error("鍔犺浇姣忔棩缁熻澶辫触", e);
+ }
+ },
+
+ async loadStockByWarehouse() {
+ try {
+ const res = await this.http.get("/api/Dashboard/StockByWarehouse");
+ if (res.status && res.data) {
+ console.log("浠撳簱鍒嗗竷鏁版嵁:", res.data);
+ this.warehouseData = res.data.data || res.data;
+ this.updateWarehouseChart();
+ }
+ } catch (e) {
+ console.error("鍔犺浇浠撳簱鍒嗗竷澶辫触", e);
+ }
+ },
+
+ updateMonthlyTrendChart() {
+ const option = {
+ tooltip: { trigger: "axis" },
+ legend: { data: ["鍏ュ簱", "鍑哄簱"], textStyle: { color: "#fff" } },
+ xAxis: {
+ type: "category",
+ data: this.monthlyData.map(m => m.month),
+ axisLabel: { color: "#fff", rotate: 45 }
+ },
+ yAxis: [
+ {
+ type: "value",
+ name: "鏁伴噺",
+ axisLabel: { color: "#fff" }
+ }
+ ],
+ series: [
+ { name: "鍏ュ簱", type: "bar", data: this.monthlyData.map(m => m.inbound), itemStyle: { color: "#5470c6" } },
+ { name: "鍑哄簱", type: "line", data: this.monthlyData.map(m => m.outbound), itemStyle: { color: "#91cc75" } }
+ ]
+ };
+ this.charts.monthlyTrend.setOption(option, true);
+ },
+
+ updateDailyChart() {
+ const option = {
+ tooltip: { trigger: "axis" },
+ legend: { data: ["鍏ュ簱", "鍑哄簱"], textStyle: { color: "#fff" } },
+ xAxis: {
+ type: "category",
+ data: this.dailyData.map(d => d.date),
+ axisLabel: {
+ color: "#fff",
+ interval: 0,
+ rotate: 45,
+ fontSize: 12,
+ margin: 10
+ },
+ axisTick: {
+ alignWithLabel: true
+ }
+ },
+ yAxis: {
+ type: "value",
+ axisLabel: { color: "#fff" }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '15%',
+ top: '10%',
+ containLabel: true
+ },
+ series: [
+ { name: "鍏ュ簱", type: "bar", data: this.dailyData.map(d => d.inbound), itemStyle: { color: "#5470c6" } },
+ { name: "鍑哄簱", type: "bar", data: this.dailyData.map(d => d.outbound), itemStyle: { color: "#91cc75" } }
+ ]
+ };
+ this.charts.daily.setOption(option, true);
+ },
+
+ updateWarehouseChart() {
+ const warehouseNames = this.warehouseData.map(w => w.warehouse);
+ const totalStocks = this.warehouseData.map(w => w.total);
+ const hasStocks = this.warehouseData.map(w => w.hasStock);
+ const noStocks = this.warehouseData.map(w => w.noStock);
+ const hasStockPercentages = this.warehouseData.map(w => w.hasStockPercentage);
+ const noStockPercentages = this.warehouseData.map(w => w.noStockPercentage);
+
+ const option = {
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow'
+ },
+ formatter: function(params) {
+ let tip = params[0].name + '<br/>';
+ params.forEach(param => {
+ const dataIndex = param.dataIndex;
+ const warehouse = window.homeComponent.warehouseData[dataIndex];
+
+ if (param.seriesName === '宸茬敤瀹归噺') {
+ tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.hasStockPercentage})<br/>`;
+ tip += `鏈夊簱瀛�: ${warehouse.hasStock}<br/>`;
+ tip += `鏃犲簱瀛�: ${warehouse.noStock}<br/>`;
+ tip += `鎬诲閲�: ${warehouse.total}`;
+ } else if (param.seriesName === '鍓╀綑瀹归噺') {
+ tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.noStockPercentage})<br/>`;
+ tip += `鏈夊簱瀛�: ${warehouse.hasStock}<br/>`;
+ tip += `鏃犲簱瀛�: ${warehouse.noStock}<br/>`;
+ tip += `鎬诲閲�: ${warehouse.total}`;
+ }
+ });
+ return tip;
+ }
+ },
+ legend: {
+ data: ['宸茬敤瀹归噺', '鍓╀綑瀹归噺'],
+ textStyle: { color: '#fff' }
+ },
+ xAxis: {
+ type: 'category',
+ data: warehouseNames,
+ axisLabel: { color: '#fff', rotate: 30 }
+ },
+ yAxis: {
+ type: 'value',
+ axisLabel: { color: '#fff' }
+ },
+ series: [
+ {
+ name: '宸茬敤瀹归噺',
+ type: 'bar',
+ data: hasStocks.map((value, index) => ({
+ value: value,
+ label: {
+ show: true,
+ position: 'top',
+ formatter: '{c} {a|' + hasStockPercentages[index] + '}',
+ rich: {
+ a: {
+ lineHeight: 20,
+ borderColor: '#91cc75',
+ color: '#91cc75'
+ }
+ }
+ }
+ })),
+ itemStyle: { color: '#91cc75' }
+ },
+ {
+ name: '鍓╀綑瀹归噺',
+ type: 'bar',
+ data: noStocks.map((value, index) => ({
+ value: value,
+ label: {
+ show: true,
+ position: 'top',
+ formatter: '{c} {a|' + noStockPercentages[index] + '}',
+ rich: {
+ a: {
+ lineHeight: 20,
+ borderColor: '#fac858',
+ color: '#fac858'
+ }
+ }
+ }
+ })),
+ itemStyle: { color: '#fac858' }
+ }
+ ]
+ };
+
+ window.homeComponent = this;
+
+ this.charts.warehouse.setOption(option, true);
}
}
-}
+};
</script>
<style scoped>
-.title {
- line-height: 70vh;
+.dashboard-container {
+ padding: 20px;
+ color: #e0e0e0;
+ min-height: calc(100vh - 60px);
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
+ background-attachment: fixed;
+}
+
+.chart-row {
+ display: flex;
+ gap: 20px;
+ margin-bottom: 20px;
+}
+
+.chart-row.full-width {
+ width: 100%;
+}
+
+.chart-card {
+ flex: 1;
+ background: rgba(10, 16, 35, 0.6);
+ backdrop-filter: blur(10px);
+ border: 1px solid rgba(64, 224, 208, 0.3);
+ border-radius: 12px;
+ padding: 15px;
+ position: relative;
+ box-shadow:
+ 0 0 15px rgba(0, 255, 255, 0.1),
+ inset 0 0 10px rgba(64, 224, 208, 0.1);
+ transition: all 0.3s ease;
+ overflow: hidden;
+}
+
+.chart-card:hover {
+ transform: translateY(-5px);
+ box-shadow:
+ 0 0 25px rgba(0, 255, 255, 0.3),
+ inset 0 0 15px rgba(64, 224, 208, 0.2);
+ border: 1px solid rgba(64, 224, 208, 0.6);
+}
+
+.chart-card::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 10px;
+ height: 10px;
+ border-top: 2px solid #00ffff;
+ border-left: 2px solid #00ffff;
+ box-shadow: -2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
+}
+
+.chart-card::after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 10px;
+ height: 10px;
+ border-top: 2px solid #00ffff;
+ border-right: 2px solid #00ffff;
+ box-shadow: 2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
+}
+
+.chart-card::before,
+.chart-card::after {
+ animation: neon-flicker 2s infinite alternate;
+}
+
+@keyframes neon-flicker {
+ 0%, 100% {
+ opacity: 1;
+ box-shadow: -2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
+ }
+ 50% {
+ opacity: 0.8;
+ box-shadow: -2px -2px 5px #00ffff, 0 0 5px rgba(0, 255, 255, 0.5);
+ }
+}
+
+.card-title {
+ color: #00ffff;
+ font-size: 16px;
text-align: center;
- font-size: 28px;
- color: orange;
+ margin-bottom: 10px;
+ text-shadow: 0 0 10px rgba(0, 255, 255, 0.7);
+ font-weight: 500;
+}
+
+.chart-content {
+ height: 280px;
+ width: 100%;
+}
+
+/* 鍏ㄥ鍥捐〃 */
+.full-width .chart-card {
+ flex: none;
+ width: 100%;
+}
+
+.full-width .chart-content {
+ height: 350px;
+}
+
+/* 娣诲姞缃戞牸绾挎晥鏋� */
+.dashboard-container::before {
+ content: "";
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image:
+ linear-gradient(rgba(64, 224, 208, 0.05) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(64, 224, 208, 0.05) 1px, transparent 1px);
+ background-size: 30px 30px;
+ pointer-events: none;
+ z-index: -1;
}
</style>
\ No newline at end of file
--
Gitblit v1.9.3