| | |
| | | </div> |
| | | <div class="card-content"> |
| | | <div class="card-title">营收金额</div> |
| | | <div class="card-value">¥1,234,567</div> |
| | | <div class="card-trend"> |
| | | <div class="card-value"> |
| | | ¥{{ |
| | | homePageData.revenueAmount |
| | | ? formatThousand(homePageData.revenueAmount) |
| | | : "--" |
| | | }} |
| | | </div> |
| | | <div class="card-trend" v-if="homePageData.trend == '+'"> |
| | | <span class="trend-label">较昨日</span> |
| | | <span class="trend-value up">+12.5%</span> |
| | | <span class="trend-value up">+ {{ homePageData.changeRate }}</span> |
| | | </div> |
| | | <div class="card-trend" v-if="homePageData.trend == '-'"> |
| | | <span class="trend-label">较昨日</span> |
| | | <span class="trend-value down" |
| | | >- {{ homePageData.changeRate }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | |
| | | <div class="stat-card supply"> |
| | | <div class="card-icon"> |
| | | <i class="el-icon-truck"></i> |
| | | </div> |
| | | <div class="card-content"> |
| | | <div class="card-title">供应量</div> |
| | | <div class="card-value">8,965 吨</div> |
| | | <div class="card-trend"> |
| | | <div class="card-value"> |
| | | {{ |
| | | homePageData.saleQuantity |
| | | ? formatThousand(homePageData.saleQuantity) |
| | | : "--" |
| | | }}吨 |
| | | </div> |
| | | <div class="card-trend" v-if="homePageData.trendQuantity == '+'"> |
| | | <span class="trend-label">较昨日</span> |
| | | <span class="trend-value up">+8.2%</span> |
| | | <span class="trend-value up" |
| | | >+ {{ homePageData.saleQuantityRate }}</span |
| | | > |
| | | </div> |
| | | <div class="card-trend" v-if="homePageData.trendQuantity == '-'"> |
| | | <span class="trend-label">较昨日</span> |
| | | <span class="trend-value down" |
| | | >- {{ homePageData.saleQuantityRate }}</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="chart-title">营收分布</div> |
| | | <div ref="pieChart" class="chart-content pie-chart"></div> |
| | | </div> |
| | | |
| | | |
| | | <div class="chart-container"> |
| | | <div class="chart-title">供应量趋势</div> |
| | | <div class="chart-title"> |
| | | <span>供应量趋势</span> |
| | | <div> |
| | | <el-date-picker |
| | | :locale="zhCN" |
| | | v-model="selectMonth" |
| | | type="monthrange" |
| | | placeholder="选择日期" |
| | | format="YYYY/MM" |
| | | value-format="YYYY-MM" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | @change="searchMonth" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div ref="areaChart" class="chart-content area-chart"></div> |
| | | </div> |
| | | </div> |
| | |
| | | <h3>库存统计</h3> |
| | | </div> |
| | | <div class="inventory-items"> |
| | | <div class="inventory-item"> |
| | | <div class="item-name">原煤</div> |
| | | <div class="item-value">15,432 吨</div> |
| | | <div class="item-status normal">正常</div> |
| | | </div> |
| | | <div class="inventory-item"> |
| | | <div class="item-name">精煤</div> |
| | | <div class="item-value">8,765 吨</div> |
| | | <div class="item-status normal">正常</div> |
| | | </div> |
| | | <div class="inventory-item"> |
| | | <div class="item-name">焦煤</div> |
| | | <div class="item-value">3,241 吨</div> |
| | | <div class="item-status low">偏低</div> |
| | | </div> |
| | | <div class="inventory-item"> |
| | | <div class="item-name">块煤</div> |
| | | <div class="item-value">6,789 吨</div> |
| | | <div class="item-status normal">正常</div> |
| | | <div class="inventory-item" v-for="(item, index) in inventoryList.Yvalues" :key="index"> |
| | | <div class="item-name">{{ inventoryList.Xkeys[index]? inventoryList.Xkeys[index] : "--"}}</div> |
| | | <div class="item-value">{{ item ? formatThousand(item) : "0" }}</div> |
| | | <div class="item-status">吨</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | style="width: 100%" |
| | | :header-cell-style="tableHeaderStyle" |
| | | > |
| | | <el-table-column prop="product" label="产品" width="80"></el-table-column> |
| | | <el-table-column prop="quantity" label="数量" width="80"></el-table-column> |
| | | <el-table-column prop="amount" label="金额" width="90"></el-table-column> |
| | | <el-table-column prop="status" label="状态" width="70"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="scope.row.status === '已完成' ? 'success' : 'warning'" |
| | | size="small" |
| | | > |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="coalName" |
| | | label="产品" |
| | | align="center" |
| | | mini-width="50" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="inventoryQuantity" |
| | | label="数量" |
| | | align="center" |
| | | mini-width="50" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="totalAmount" |
| | | label="金额" |
| | | align="center" |
| | | mini-width="50" |
| | | ></el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts' |
| | | <!-- 删除多余的 script 结束标签 --> |
| | | <script setup> |
| | | import { getCoalInfo, getYearlySales } from "@/api/home/index"; |
| | | import { ref, onMounted, nextTick } from "vue"; |
| | | import zhCn from "element-plus/dist/locale/zh-cn.mjs"; |
| | | |
| | | export default { |
| | | name: 'Dashboard', |
| | | data() { |
| | | return { |
| | | salesData: [ |
| | | { product: '原煤', quantity: '1,234吨', amount: '¥456,789', status: '已完成' }, |
| | | { product: '精煤', quantity: '567吨', amount: '¥234,567', status: '已完成' }, |
| | | { product: '焦煤', quantity: '890吨', amount: '¥345,678', status: '进行中' }, |
| | | { product: '块煤', quantity: '432吨', amount: '¥123,456', status: '已完成' }, |
| | | { product: '煤泥', quantity: '678吨', amount: '¥234,567', status: '进行中' } |
| | | ], |
| | | tableHeaderStyle: { |
| | | backgroundColor: '#f5f7fa', |
| | | color: '#606266', |
| | | fontSize: '12px' |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.initCharts() |
| | | }) |
| | | }, |
| | | methods: { |
| | | initCharts() { |
| | | this.initPieChart() |
| | | this.initAreaChart() |
| | | this.initBarChart() |
| | | }, |
| | | |
| | | initPieChart() { |
| | | const chart = echarts.init(this.$refs.pieChart) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'item', |
| | | formatter: '{a} <br/>{b}: {c} ({d}%)' |
| | | }, |
| | | legend: { |
| | | orient: 'vertical', |
| | | left: 'right', |
| | | top: 'center', |
| | | textStyle: { |
| | | fontSize: 12 |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '营收分布', |
| | | type: 'pie', |
| | | radius: ['30%', '70%'], |
| | | center: ['40%', '50%'], |
| | | avoidLabelOverlap: false, |
| | | label: { |
| | | show: false, |
| | | position: 'center' |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: '16', |
| | | fontWeight: 'bold' |
| | | } |
| | | }, |
| | | labelLine: { |
| | | show: false |
| | | }, |
| | | data: [ |
| | | { value: 335, name: '原煤', itemStyle: { color: '#409EFF' } }, |
| | | { value: 310, name: '精煤', itemStyle: { color: '#67C23A' } }, |
| | | { value: 234, name: '焦煤', itemStyle: { color: '#E6A23C' } }, |
| | | { value: 135, name: '块煤', itemStyle: { color: '#F56C6C' } }, |
| | | { value: 155, name: '其他', itemStyle: { color: '#909399' } } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | | chart.setOption(option) |
| | | |
| | | // 响应式 |
| | | window.addEventListener('resize', () => { |
| | | chart.resize() |
| | | }) |
| | | }, |
| | | |
| | | initAreaChart() { |
| | | const chart = echarts.init(this.$refs.areaChart) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label: { |
| | | backgroundColor: '#6a7985' |
| | | } |
| | | } |
| | | }, |
| | | legend: { |
| | | data: ['供应量'], |
| | | top: 10 |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: [ |
| | | { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月'], |
| | | axisLabel: { |
| | | fontSize: 12 |
| | | } |
| | | } |
| | | ], |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | axisLabel: { |
| | | fontSize: 12 |
| | | } |
| | | } |
| | | ], |
| | | series: [ |
| | | { |
| | | name: '供应量', |
| | | type: 'line', |
| | | stack: 'Total', |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: 'rgba(64, 158, 255, 0.3)' }, |
| | | { offset: 1, color: 'rgba(64, 158, 255, 0.1)' } |
| | | ]) |
| | | }, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | data: [1200, 1320, 1010, 1340, 900, 1230, 1100], |
| | | lineStyle: { |
| | | color: '#409EFF' |
| | | }, |
| | | itemStyle: { |
| | | color: '#409EFF' |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | chart.setOption(option) |
| | | |
| | | // 响应式 |
| | | window.addEventListener('resize', () => { |
| | | chart.resize() |
| | | }) |
| | | }, |
| | | |
| | | initBarChart() { |
| | | const chart = echarts.init(this.$refs.barChart) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['原煤', '精煤', '焦煤', '块煤', '煤泥'], |
| | | axisLabel: { |
| | | fontSize: 11 |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLabel: { |
| | | fontSize: 11 |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '销量', |
| | | type: 'bar', |
| | | data: [320, 302, 301, 334, 290], |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: '#409EFF' }, |
| | | { offset: 1, color: '#79bbff' } |
| | | ]) |
| | | }, |
| | | barWidth: '60%' |
| | | } |
| | | ] |
| | | } |
| | | chart.setOption(option) |
| | | |
| | | // 响应式 |
| | | window.addEventListener('resize', () => { |
| | | chart.resize() |
| | | }) |
| | | } |
| | | // 兼容模板变量名,暴露给模板使用 |
| | | const zhCN = zhCn; |
| | | import * as echarts from "echarts"; |
| | | |
| | | const homePageData = ref({}); |
| | | const selectMonth = ref([]); |
| | | |
| | | // 生成无限随机颜色(HSL算法保证高辨识度、柔和不刺眼) |
| | | function generateRandomColors(count = 10) { |
| | | const colors = []; |
| | | const goldenAngle = 137.508; // 黄金角度,保证颜色分布均匀 |
| | | |
| | | for (let i = 0; i < count; i++) { |
| | | // 使用黄金角度分割确保颜色差异大 |
| | | const hue = (i * goldenAngle) % 360; |
| | | |
| | | // 饱和度:40-70% 避免过于鲜艳 |
| | | const saturation = 40 + Math.random() * 30; |
| | | |
| | | // 明度:45-75% 避免过暗或过亮 |
| | | const lightness = 45 + Math.random() * 30; |
| | | |
| | | colors.push( |
| | | `hsl(${Math.round(hue)}, ${Math.round(saturation)}%, ${Math.round( |
| | | lightness |
| | | )}%)` |
| | | ); |
| | | } |
| | | |
| | | return colors; |
| | | } |
| | | |
| | | // HSL转16进制(可选,如果需要hex格式) |
| | | function hslToHex(hsl) { |
| | | const match = hsl.match(/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/); |
| | | if (!match) return hsl; |
| | | |
| | | const h = parseInt(match[1]) / 360; |
| | | const s = parseInt(match[2]) / 100; |
| | | const l = parseInt(match[3]) / 100; |
| | | |
| | | const hue2rgb = (p, q, t) => { |
| | | if (t < 0) t += 1; |
| | | if (t > 1) t -= 1; |
| | | if (t < 1 / 6) return p + (q - p) * 6 * t; |
| | | if (t < 1 / 2) return q; |
| | | if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; |
| | | return p; |
| | | }; |
| | | |
| | | let r, g, b; |
| | | if (s === 0) { |
| | | r = g = b = l; |
| | | } else { |
| | | const q = l < 0.5 ? l * (1 + s) : l + s - l * s; |
| | | const p = 2 * l - q; |
| | | r = hue2rgb(p, q, h + 1 / 3); |
| | | g = hue2rgb(p, q, h); |
| | | b = hue2rgb(p, q, h - 1 / 3); |
| | | } |
| | | |
| | | const toHex = (c) => { |
| | | const hex = Math.round(c * 255).toString(16); |
| | | return hex.length === 1 ? "0" + hex : hex; |
| | | }; |
| | | |
| | | return `#${toHex(r)}${toHex(g)}${toHex(b)}`; |
| | | } |
| | | |
| | | // 便捷方法:直接获取16进制颜色数组 |
| | | function getRandomHexColors(count = 1) { |
| | | return generateRandomColors(count).map(hslToHex); |
| | | } |
| | | |
| | | // 千分位格式化函数 |
| | | function formatThousand(num) { |
| | | if (typeof num === "number") return num.toLocaleString(); |
| | | if (typeof num === "string") { |
| | | const n = Number(num.replace(/,/g, "")); |
| | | if (isNaN(n)) return num; |
| | | return n.toLocaleString(); |
| | | } |
| | | return num; |
| | | } |
| | | |
| | | // 销售数据原始 |
| | | const salesData = ref([]); |
| | | |
| | | const tableHeaderStyle = { |
| | | backgroundColor: "#f5f7fa", |
| | | color: "#606266", |
| | | fontSize: "12px", |
| | | }; |
| | | |
| | | // 图表ref |
| | | const pieChart = ref(null); |
| | | const areaChart = ref(null); |
| | | const barChart = ref(null); |
| | | |
| | | // 饼图初始化 |
| | | const initPieChart = () => { |
| | | const chart = echarts.init(pieChart.value); |
| | | const option = { |
| | | tooltip: { |
| | | trigger: "item", |
| | | formatter: "{a} <br/>{b}: {c} ({d}%)", |
| | | }, |
| | | legend: { |
| | | orient: "vertical", |
| | | left: "right", |
| | | top: "center", |
| | | textStyle: { |
| | | fontSize: 12, |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "营收分布", |
| | | type: "pie", |
| | | radius: ["30%", "70%"], |
| | | center: ["40%", "50%"], |
| | | avoidLabelOverlap: false, |
| | | label: { |
| | | show: false, |
| | | position: "center", |
| | | }, |
| | | emphasis: { |
| | | label: { |
| | | show: true, |
| | | fontSize: "16", |
| | | fontWeight: "bold", |
| | | }, |
| | | }, |
| | | labelLine: { |
| | | show: false, |
| | | }, |
| | | data: revenueDistribution.value, |
| | | }, |
| | | ], |
| | | }; |
| | | chart.setOption(option); |
| | | window.addEventListener("resize", () => { |
| | | chart.resize(); |
| | | }); |
| | | }; |
| | | |
| | | // 面积图初始化 |
| | | const initAreaChart = () => { |
| | | const chart = echarts.init(areaChart.value); |
| | | const option = { |
| | | title: { |
| | | show: supplyTrend.value.length == 0, // 没数据才显示 |
| | | extStyle: { |
| | | color: "grey", |
| | | fontSize: 20, |
| | | }, |
| | | text: "暂无数据", |
| | | left: "center", |
| | | top: "center", |
| | | }, |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "cross", |
| | | label: { |
| | | backgroundColor: "#6a7985", |
| | | }, |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ["供应量"], |
| | | top: 10, |
| | | }, |
| | | grid: { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: [ |
| | | { |
| | | type: "category", |
| | | boundaryGap: false, |
| | | data: supplyTrend.value.Xkeys || [], |
| | | axisLabel: { |
| | | fontSize: 12, |
| | | }, |
| | | }, |
| | | ], |
| | | yAxis: [ |
| | | { |
| | | type: "value", |
| | | axisLabel: { |
| | | fontSize: 12, |
| | | }, |
| | | }, |
| | | ], |
| | | series: [ |
| | | { |
| | | name: "供应量", |
| | | type: "line", |
| | | stack: "Total", |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: "rgba(64, 158, 255, 0.3)" }, |
| | | { offset: 1, color: "rgba(64, 158, 255, 0.1)" }, |
| | | ]), |
| | | }, |
| | | emphasis: { |
| | | focus: "series", |
| | | }, |
| | | data: supplyTrend.value.Yvalues || [], |
| | | lineStyle: { |
| | | color: "#409EFF", |
| | | }, |
| | | itemStyle: { |
| | | color: "#409EFF", |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | chart.setOption(option); |
| | | window.addEventListener("resize", () => { |
| | | chart.resize(); |
| | | }); |
| | | }; |
| | | |
| | | // 柱状图初始化 |
| | | const initBarChart = () => { |
| | | const chart = echarts.init(barChart.value); |
| | | const option = { |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: resultMonthList.value.Xkeys || [], |
| | | axisLabel: { |
| | | fontSize: 11, |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | axisLabel: { |
| | | fontSize: 11, |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "销量", |
| | | type: "bar", |
| | | data: resultMonthList.value.Yvalues || [], |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: "#409EFF" }, |
| | | { offset: 1, color: "#79bbff" }, |
| | | ]), |
| | | }, |
| | | barWidth: "60%", |
| | | }, |
| | | ], |
| | | }; |
| | | chart.setOption(option); |
| | | window.addEventListener("resize", () => { |
| | | chart.resize(); |
| | | }); |
| | | }; |
| | | // 收入分布数据 |
| | | const revenueDistribution = ref([]); |
| | | |
| | | // 初始化所有图表 |
| | | const initCharts = () => { |
| | | initPieChart(); |
| | | initAreaChart(); |
| | | initBarChart(); |
| | | }; |
| | | |
| | | const getList = async () => { |
| | | try { |
| | | searchMonth(); |
| | | const res = await getCoalInfo(); |
| | | homePageData.value = res.data || {}; |
| | | revenueDistribution.value = []; |
| | | if (homePageData.value.revenueDistribution) { |
| | | Object.keys(homePageData.value.revenueDistribution).forEach((key) => { |
| | | let obj = {}; |
| | | obj.name = key; |
| | | obj.value = homePageData.value.revenueDistribution[key]; |
| | | obj.itemStyle = { |
| | | color: getRandomHexColors(1)[0], // 使用随机颜色 |
| | | }; |
| | | revenueDistribution.value.push(obj); |
| | | }); |
| | | } |
| | | if (homePageData.value.inventory) { |
| | | let inventoryListXkeys = Object.keys(homePageData.value.inventory); |
| | | let inventoryListYvalues = Object.values(homePageData.value.inventory); |
| | | inventoryList.value = { |
| | | Xkeys: inventoryListXkeys, |
| | | Yvalues: inventoryListYvalues, |
| | | }; |
| | | } |
| | | if(homePageData.value.resultMouth){ |
| | | let resultMonthXkeys = Object.keys(homePageData.value.resultMouth); |
| | | let resultMonthYvalues = Object.values(homePageData.value.resultMouth); |
| | | resultMonthList.value = { |
| | | Xkeys: resultMonthXkeys, |
| | | Yvalues: resultMonthYvalues, |
| | | }; |
| | | console.log(resultMonthList.value); |
| | | } |
| | | if(homePageData.value.salesResults){ |
| | | salesData.value = homePageData.value.salesResults; |
| | | } |
| | | // 数据加载完成后重新初始化图表 |
| | | nextTick(() => { |
| | | initCharts(); |
| | | }); |
| | | } catch (error) { |
| | | console.error("获取煤种信息失败:", error); |
| | | } |
| | | }; |
| | | const inventoryList = ref([]); |
| | | const resultMonthList = ref([]); |
| | | |
| | | const supplyTrend = ref({}); |
| | | const searchMonth = async () => { |
| | | let res = await getYearlySales({ |
| | | timeRange: selectMonth.value ? selectMonth.value : null, |
| | | }); |
| | | let Xkeys = Object.keys(res.data.data); |
| | | let Yvalues = Object.values(res.data.data); |
| | | supplyTrend.value = { |
| | | Xkeys, |
| | | Yvalues, |
| | | }; |
| | | nextTick(() => { |
| | | initAreaChart(); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | } |
| | | |
| | | .revenue .card-icon { |
| | | background: linear-gradient(135deg, #409EFF, #79bbff); |
| | | background: linear-gradient(135deg, #409eff, #79bbff); |
| | | } |
| | | |
| | | .supply .card-icon { |
| | | background: linear-gradient(135deg, #67C23A, #95d475); |
| | | background: linear-gradient(135deg, #67c23a, #95d475); |
| | | } |
| | | |
| | | .card-content { |
| | |
| | | } |
| | | |
| | | .trend-value.up { |
| | | color: #67C23A; |
| | | color: #67c23a; |
| | | } |
| | | .trend-value.down { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | /* 中间图表区域 */ |
| | |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | } |
| | | .el-scrollbar__view{ |
| | | .el-scrollbar__view { |
| | | width: 100%; |
| | | } |
| | | .chart-container { |
| | |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 2px solid #f0f0f0; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .chart-content { |
| | |
| | | padding: 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 6px; |
| | | border-left: 3px solid #409EFF; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .item-name { |
| | |
| | | |
| | | .item-status.normal { |
| | | background: #f0f9ff; |
| | | color: #67C23A; |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .item-status.low { |
| | | background: #fef0e6; |
| | | color: #E6A23C; |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | /* 柱状图容器 */ |
| | |
| | | .bottom-card.table .el-table th { |
| | | padding: 8px 0; |
| | | } |
| | | :deep(.el-scrollbar__view){ |
| | | :deep(.el-scrollbar__view) { |
| | | width: 100% !important; |
| | | |
| | | } |
| | | :deep(.el-table__header,){ |
| | | width: 100% !important; |
| | | } |
| | | :deep(.el-table__body,){ |
| | | width: 100% !important; |
| | | } |
| | | :deep(.el-table__header, ) { |
| | | width: 100% !important; |
| | | } |
| | | :deep(.el-table__body, ) { |
| | | width: 100% !important; |
| | | } |
| | | /* 响应式设计 */ |
| | | @media (max-width: 1200px) { |
| | | .bottom-section { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | |
| | | .chart-section { |
| | | flex-direction: column; |
| | | } |
| | |
| | | .top-cards { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | |
| | | .dashboard { |
| | | padding: 10px; |
| | | } |
| | | |
| | | |
| | | .stat-card { |
| | | padding: 15px; |
| | | } |
| | | |
| | | |
| | | .card-value { |
| | | font-size: 20px; |
| | | } |