<template>
|
<div ref="screenRoot"
|
class="sales-statistics-container"
|
:class="{ 'is-fullscreen': isFullscreen }">
|
<div class="bi-bg"></div>
|
<div class="bi-topbar">
|
<img class="bi-topbar-title-bg"
|
src="@/assets/BI/biaoti.png"
|
alt="生产看板统计" />
|
<div class="bi-topbar-content">
|
<div class="bi-topbar-left">
|
<button class="fullscreen-btn"
|
@click="toggleFullscreen"
|
:title="isFullscreen ? '退出全屏' : '全屏显示'">
|
<svg v-if="!isFullscreen"
|
width="1.6vh"
|
height="1.6vh"
|
viewBox="0 0 24 24"
|
fill="none"
|
stroke="currentColor"
|
stroke-width="2">
|
<path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" />
|
</svg>
|
<svg v-else
|
width="1.6vh"
|
height="1.6vh"
|
viewBox="0 0 24 24"
|
fill="none"
|
stroke="currentColor"
|
stroke-width="2">
|
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" />
|
</svg>
|
</button>
|
</div>
|
<div class="bi-topbar-title">生产看板统计</div>
|
<div class="bi-topbar-meta">
|
<span class="bi-topbar-time">{{ currentTime }}</span>
|
<span class="bi-topbar-sep">|</span>
|
<span class="bi-topbar-date">{{ currentDateText }}</span>
|
</div>
|
</div>
|
</div>
|
<div class="bi-dashboard-grid">
|
<!-- 左上:生产成本单耗统计(砌块) -->
|
<div class="bi-panel bi-panel-top-left">
|
<PanelHeader :isFullscreen="true"
|
title="生产成本单耗统计(砌块)" />
|
<div class="panel-tabs">
|
<span class="tab-item"
|
:class="{ active: blockTimeDimension === 'year' }"
|
@click="handleBlockTimeDimensionChange('year')">年</span>
|
<span class="tab-item"
|
:class="{ active: blockTimeDimension === 'month' }"
|
@click="handleBlockTimeDimensionChange('month')">月</span>
|
</div>
|
<div class="bi-panel-body">
|
<div class="chart-filter-tabs">
|
<span v-for="area in salesAreas"
|
:key="area"
|
class="cf-tab"
|
:class="{ active: blockSelectedArea === area }"
|
@click="handleBlockAreaChange(area)">{{ area }}</span>
|
</div>
|
<div class="material-info-card">
|
<div class="material-icon">
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<path d="M20 7h-4V4c0-1.1-.9-2-2-2h-4c-1.1 0-2 .9-2 2v3H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2z" />
|
<polyline points="22,7 12,13 2,7" />
|
</svg>
|
</div>
|
<div class="material-details">
|
<div class="material-name">{{ blockMaterialType }}AAA</div>
|
<div class="material-stats">
|
<div class="stat-item">
|
<span class="stat-label">月累计单耗</span>
|
<span class="stat-value">78/12</span>
|
<span class="stat-unit">吨</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-label">年累计单耗</span>
|
<span class="stat-value">78/12</span>
|
<span class="stat-unit">吨</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
<!-- <div class="chart-unit-row">
|
<span>单位:立方米</span>
|
</div> -->
|
<div ref="blockCostChart"
|
class="echart-fill"></div>
|
</div>
|
</div>
|
<!-- 右上:产量分析 -->
|
<div class="bi-panel bi-panel-top-right">
|
<PanelHeader :isFullscreen="true"
|
title="物料生产量分析" />
|
<div class="panel-tabs">
|
<span class="tab-item"
|
:class="{ active: productionTimeDimension === 'year' }"
|
@click="handleProductionTimeDimensionChange('year')">年</span>
|
<span class="tab-item"
|
:class="{ active: productionTimeDimension === 'month' }"
|
@click="handleProductionTimeDimensionChange('month')">月</span>
|
</div>
|
<div class="bi-panel-body">
|
<div class="chart-unit-row">
|
<span>单位:件</span>
|
</div>
|
<div ref="productionChart"
|
class="echart-fill"></div>
|
</div>
|
</div>
|
<!-- 中间中心环 -->
|
<div class="center-ring">
|
<!-- <div class="center-ring-box">
|
<div class="center-metric m1">
|
<div class="center-metric-label">项目产量</div>
|
<div class="center-metric-value">{{ projectProduction }}</div>
|
<div class="center-metric-unit">件</div>
|
</div>
|
<div class="center-metric m2">
|
<div class="center-metric-label">固体处理量</div>
|
<div class="center-metric-value">{{ solidWaste处理量 }}</div>
|
<div class="center-metric-unit">吨</div>
|
</div>
|
<div class="center-metric m3">
|
<div class="center-metric-label">砌块产量</div>
|
<div class="center-metric-value">{{ blockProduction }}</div>
|
<div class="center-metric-unit">件</div>
|
</div>
|
<div class="center-metric m4">
|
<div class="center-metric-label">板材产量</div>
|
<div class="center-metric-value">{{ boardProduction }}</div>
|
<div class="center-metric-unit">件</div>
|
</div>
|
</div> -->
|
</div>
|
<!-- 左下:生产成本单耗统计(板材) -->
|
<div class="bi-panel bi-panel-bottom-left">
|
<PanelHeader :isFullscreen="true"
|
title="生产成本单耗统计(板材)" />
|
<div class="panel-tabs">
|
<span class="tab-item"
|
:class="{ active: boardTimeDimension === 'year' }"
|
@click="handleBoardTimeDimensionChange('year')">年</span>
|
<span class="tab-item"
|
:class="{ active: boardTimeDimension === 'month' }"
|
@click="handleBoardTimeDimensionChange('month')">月</span>
|
</div>
|
<div class="bi-panel-body">
|
<div class="chart-filter-tabs">
|
<span v-for="area in salesAreas"
|
:key="area"
|
class="cf-tab"
|
:class="{ active: blockSelectedArea === area }"
|
@click="handleBlockAreaChange(area)">{{ area }}</span>
|
</div>
|
<div class="material-info-card">
|
<div class="material-icon">
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<path d="M20 7h-4V4c0-1.1-.9-2-2-2h-4c-1.1 0-2 .9-2 2v3H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2z" />
|
<polyline points="22,7 12,13 2,7" />
|
</svg>
|
</div>
|
<div class="material-details">
|
<div class="material-name">{{ boardMaterialType }}AAA</div>
|
<div class="material-stats">
|
<div class="stat-item">
|
<span class="stat-label">月累计单耗</span>
|
<span class="stat-value">78/12</span>
|
<span class="stat-unit">吨</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-label">年累计单耗</span>
|
<span class="stat-value">78/12</span>
|
<span class="stat-unit">吨</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
<!-- <div class="chart-unit-row">
|
<span>单位:立方米</span>
|
</div> -->
|
<div ref="boardCostChart"
|
class="echart-fill"></div>
|
</div>
|
</div>
|
<!-- 中下:新增客户趋势分析 -->
|
<div class="bi-panel bi-panel-bottom-center">
|
<PanelHeader :isFullscreen="true"
|
title="固废处理量" />
|
<div class="panel-tabs">
|
<span class="tab-item"
|
:class="{ active: customerTimeDimension === 'year' }"
|
@click="handleCustomerTimeDimensionChange('year')">年</span>
|
<span class="tab-item"
|
:class="{ active: customerTimeDimension === 'month' }"
|
@click="handleCustomerTimeDimensionChange('month')">月</span>
|
</div>
|
<!-- <div class="bi-panel-body">
|
<div class="chart-unit-row chart-unit-single">
|
<span>单位:家</span>
|
</div>
|
<div ref="customerTrendChart"
|
class="echart-fill"></div>
|
</div> -->
|
</div>
|
<!-- 右下:销量排名分析 -->
|
<div class="bi-panel bi-panel-bottom-right">
|
<PanelHeader :isFullscreen="true"
|
title="物料生产量统计" />
|
<div class="panel-tabs">
|
<span class="tab-item"
|
:class="{ active: salesTimeDimension === 'year' }"
|
@click="handleSalesTimeDimensionChange('year')">年</span>
|
<span class="tab-item"
|
:class="{ active: salesTimeDimension === 'month' }"
|
@click="handleSalesTimeDimensionChange('month')">月</span>
|
</div>
|
<div class="bi-panel-body">
|
<!-- <div class="chart-filter-tabs">
|
<span v-for="area in salesAreas"
|
:key="area"
|
class="cf-tab"
|
:class="{ active: selectedArea === area }"
|
@click="handleAreaChange(area)">{{ area }}</span>
|
</div>
|
<div ref="salesRankingChart"
|
class="echart-fill"></div> -->
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import {
|
ref,
|
computed,
|
onMounted,
|
onBeforeUnmount,
|
watch,
|
nextTick,
|
} from "vue";
|
import * as echarts from "echarts";
|
import dayjs from "dayjs";
|
import PanelHeader from "@/views/reportAnalysis/PSIDataAnalysis/components/PanelHeader.vue";
|
|
const screenRoot = ref(null);
|
const isFullscreen = ref(false);
|
|
// 顶部栏时间
|
const now = ref(dayjs());
|
const currentTime = computed(() => now.value.format("HH:mm:ss"));
|
const currentDateText = computed(() => {
|
const weekMap = {
|
0: "星期日",
|
1: "星期一",
|
2: "星期二",
|
3: "星期三",
|
4: "星期四",
|
5: "星期五",
|
6: "星期六",
|
};
|
return `${now.value.format("YYYY-MM-DD")} ${weekMap[now.value.day()] || ""}`;
|
});
|
let timeTicker = null;
|
|
const handleFullscreenChange = () => {
|
isFullscreen.value = !!document.fullscreenElement;
|
nextTick(() => {
|
handleResize();
|
});
|
};
|
|
const toggleFullscreen = async () => {
|
const rootEl = screenRoot.value;
|
if (!rootEl) return;
|
try {
|
if (!document.fullscreenElement) {
|
await rootEl.requestFullscreen();
|
} else {
|
await document.exitFullscreen();
|
}
|
} catch (error) {
|
console.error("全屏切换失败:", error);
|
}
|
};
|
|
// 图表引用
|
const blockCostChart = ref(null);
|
const boardCostChart = ref(null);
|
const productionChart = ref(null);
|
const customerTrendChart = ref(null);
|
const salesRankingChart = ref(null);
|
|
// 选择器数据
|
const blockTimeDimension = ref("year");
|
const blockMaterialType = ref("石灰");
|
const boardTimeDimension = ref("year");
|
const boardMaterialType = ref("石灰");
|
const productionTimeDimension = ref("year");
|
const customerTimeDimension = ref("year");
|
const salesTimeDimension = ref("year");
|
const selectedArea = ref("全部");
|
|
const salesAreas = [
|
"全部",
|
"石灰",
|
"水泥",
|
"铝粉膏",
|
"脱模剂",
|
"防腐剂",
|
"氧化镁",
|
"冷拔丝",
|
];
|
|
// 中心环数据
|
const projectProduction = ref(12345);
|
const solidWaste处理量 = ref(6789);
|
const blockProduction = ref(7812);
|
const boardProduction = ref(7812);
|
|
// 图表实例
|
let blockCostChartInstance = null;
|
let boardCostChartInstance = null;
|
let productionChartInstance = null;
|
let customerTrendChartInstance = null;
|
let salesRankingChartInstance = null;
|
|
// 生产单耗图表配置
|
const blockCostChartOption = computed(() => {
|
const materials = ["消耗量"];
|
const colors = ["#8A6BFF"];
|
const year = 2024;
|
const periodType = blockTimeDimension.value;
|
|
// 生成时间段
|
let periods = [];
|
if (periodType === "year") {
|
// 年度数据:6个月
|
for (let month = 9; month <= 12; month++) {
|
periods.push(`${month}/${year.toString().slice(2)}`);
|
}
|
for (let month = 1; month <= 3; month++) {
|
periods.push(`${month}/${(year + 1).toString().slice(2)}`);
|
}
|
} else {
|
// 月度数据:30天
|
const month = 1;
|
for (let day = 1; day <= 30; day++) {
|
periods.push(`${month}/${day}`);
|
}
|
}
|
|
// 为每种材料生成数据
|
const series = materials.map((material, index) => {
|
const data = periods.map(() => {
|
return periodType === "year"
|
? Math.floor(Math.random() * 50) + 150
|
: Math.floor(Math.random() * 5) + 15;
|
});
|
|
return {
|
name: material,
|
data: data,
|
type: "bar",
|
itemStyle: { color: colors[index] },
|
};
|
});
|
|
return {
|
backgroundColor: "transparent",
|
tooltip: {
|
trigger: "axis",
|
backgroundColor: "rgba(0,0,0,0.55)",
|
borderColor: "rgba(64,158,255,0.25)",
|
borderWidth: getResponsiveValue(1),
|
textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
|
},
|
// legend: {
|
// data: materials,
|
// top: "10%",
|
// right: "1%",
|
// textStyle: {
|
// color: "#B8C8E0",
|
// fontSize: getResponsiveValue(9),
|
// },
|
// itemWidth: getResponsiveValue(10),
|
// itemHeight: getResponsiveValue(10),
|
// },
|
grid: {
|
left: "1%",
|
right: "1%",
|
bottom: "1%",
|
top: "8%",
|
containLabel: true,
|
},
|
xAxis: {
|
type: "category",
|
data: periods,
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisTick: { show: false },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(10),
|
},
|
splitLine: { show: false },
|
},
|
yAxis: {
|
type: "value",
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(8),
|
},
|
splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
|
},
|
series: series,
|
};
|
});
|
|
// 板材单耗图表配置
|
const boardCostChartOption = computed(() => {
|
const materials = ["消耗量"];
|
const colors = ["#00A4ED", "#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447", "#FF6B6B"];
|
const year = 2024;
|
const periodType = boardTimeDimension.value;
|
|
// 生成时间段
|
let periods = [];
|
if (periodType === "year") {
|
// 年度数据:6个月
|
for (let month = 9; month <= 12; month++) {
|
periods.push(`${month}/${year.toString().slice(2)}`);
|
}
|
for (let month = 1; month <= 3; month++) {
|
periods.push(`${month}/${(year + 1).toString().slice(2)}`);
|
}
|
} else {
|
// 月度数据:30天
|
const month = 1;
|
for (let day = 1; day <= 30; day++) {
|
periods.push(`${month}/${day}`);
|
}
|
}
|
|
// 为每种材料生成数据
|
const series = materials.map((material, index) => {
|
const data = periods.map(() => {
|
return periodType === "year"
|
? Math.floor(Math.random() * 50) + 150
|
: Math.floor(Math.random() * 5) + 15;
|
});
|
|
return {
|
name: material,
|
data: data,
|
type: "bar",
|
itemStyle: { color: colors[index] },
|
};
|
});
|
|
return {
|
backgroundColor: "transparent",
|
tooltip: {
|
trigger: "axis",
|
backgroundColor: "rgba(0,0,0,0.55)",
|
borderColor: "rgba(64,158,255,0.25)",
|
borderWidth: getResponsiveValue(1),
|
textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
|
},
|
// legend: {
|
// data: materials,
|
// top: "10%",
|
// right: "1%",
|
// textStyle: {
|
// color: "#B8C8E0",
|
// fontSize: getResponsiveValue(9),
|
// },
|
// itemWidth: getResponsiveValue(10),
|
// itemHeight: getResponsiveValue(10),
|
// },
|
grid: {
|
left: "1%",
|
right: "1%",
|
bottom: "1%",
|
top: "8%",
|
containLabel: true,
|
},
|
xAxis: {
|
type: "category",
|
data: periods,
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisTick: { show: false },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(10),
|
},
|
splitLine: { show: false },
|
},
|
yAxis: {
|
type: "value",
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(8),
|
},
|
splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
|
},
|
series: series,
|
};
|
});
|
|
// 产量分析图表配置
|
const productionChartOption = computed(() => {
|
const salesAreas = ["全部", "砌块", "板材"];
|
const colors = ["#00A4ED", "#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447", "#FF6B6B"];
|
const year = 2024;
|
const periodType = productionTimeDimension.value;
|
|
// 生成时间段
|
let periods = [];
|
if (periodType === "year") {
|
// 年度数据:6个月
|
for (let month = 9; month <= 12; month++) {
|
periods.push(`${month}/${year.toString().slice(2)}`);
|
}
|
for (let month = 1; month <= 3; month++) {
|
periods.push(`${month}/${(year + 1).toString().slice(2)}`);
|
}
|
} else {
|
// 月度数据:30天
|
const month = 1;
|
for (let day = 1; day <= 30; day++) {
|
periods.push(`${month}/${day}`);
|
}
|
}
|
|
// 为每个销售区生成数据
|
const series = salesAreas.map((area, index) => {
|
const data = periods.map(() => {
|
return periodType === "year"
|
? Math.floor(Math.random() * 50) + 150
|
: Math.floor(Math.random() * 5) + 15;
|
});
|
|
return {
|
name: area,
|
data: data,
|
type: "line",
|
smooth: true,
|
lineStyle: { width: getResponsiveValue(2), color: colors[index] },
|
itemStyle: { color: colors[index] },
|
areaStyle: {
|
opacity: 0.3,
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
{ offset: 0, color: colors[index] + "80" },
|
{ offset: 1, color: colors[index] + "00" },
|
]),
|
},
|
};
|
});
|
|
return {
|
backgroundColor: "transparent",
|
tooltip: {
|
trigger: "axis",
|
backgroundColor: "rgba(0,0,0,0.55)",
|
borderColor: "rgba(64,158,255,0.25)",
|
borderWidth: getResponsiveValue(1),
|
textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
|
},
|
legend: {
|
data: salesAreas,
|
top: "10%",
|
right: "1%",
|
textStyle: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(9),
|
},
|
itemWidth: getResponsiveValue(10),
|
itemHeight: getResponsiveValue(10),
|
},
|
grid: {
|
left: "1%",
|
right: "1%",
|
bottom: "1%",
|
top: "28%",
|
containLabel: true,
|
},
|
xAxis: {
|
type: "category",
|
data: periods,
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisTick: { show: false },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(10),
|
},
|
splitLine: { show: false },
|
},
|
yAxis: {
|
type: "value",
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(8),
|
},
|
splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
|
},
|
series: series,
|
};
|
});
|
|
// 新增客户趋势图表配置
|
const customerTrendChartOption = computed(() => {
|
const customerTypes = ["全部", "石灰", "水泥", "铝粉膏", "脱模剂"];
|
const colors = ["#00A4ED", "#34D8F7", "#4A8BFF", "#8A6BFF", "#C8C447"];
|
const year = 2024;
|
const periodType = customerTimeDimension.value;
|
|
// 生成时间段
|
let periods = [];
|
if (periodType === "year") {
|
// 年度数据:6个月
|
for (let month = 9; month <= 12; month++) {
|
periods.push(`${month}/${year.toString().slice(2)}`);
|
}
|
for (let month = 1; month <= 5; month++) {
|
periods.push(`${month}/${(year + 1).toString().slice(2)}`);
|
}
|
} else {
|
// 月度数据:30天
|
const month = 1;
|
for (let day = 1; day <= 30; day++) {
|
periods.push(`${month}/${day}`);
|
}
|
}
|
|
// 为每种客户类型生成数据
|
const series = customerTypes.map((type, index) => {
|
const data = periods.map(() => {
|
return periodType === "year"
|
? Math.floor(Math.random() * 10) + 5
|
: Math.floor(Math.random() * 3) + 1;
|
});
|
|
return {
|
name: type,
|
data: data,
|
type: "line",
|
smooth: true,
|
lineStyle: { width: getResponsiveValue(2), color: colors[index] },
|
itemStyle: { color: colors[index] },
|
areaStyle: {
|
opacity: 0.3,
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
{ offset: 0, color: colors[index] + "80" },
|
{ offset: 1, color: colors[index] + "00" },
|
]),
|
},
|
};
|
});
|
|
return {
|
backgroundColor: "transparent",
|
tooltip: {
|
trigger: "axis",
|
backgroundColor: "rgba(0,0,0,0.55)",
|
borderColor: "rgba(64,158,255,0.25)",
|
borderWidth: getResponsiveValue(1),
|
textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
|
},
|
legend: {
|
data: customerTypes,
|
top: "10%",
|
right: "1%",
|
textStyle: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(9),
|
},
|
itemWidth: getResponsiveValue(10),
|
itemHeight: getResponsiveValue(10),
|
},
|
grid: {
|
left: "1%",
|
right: "1%",
|
bottom: "1%",
|
top: "28%",
|
containLabel: true,
|
},
|
xAxis: {
|
type: "category",
|
data: periods,
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisTick: { show: false },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(10),
|
},
|
splitLine: { show: false },
|
},
|
yAxis: {
|
type: "value",
|
axisLine: { lineStyle: { color: "rgba(184,200,224,0.25)" } },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(8),
|
},
|
splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
|
},
|
series: series,
|
};
|
});
|
|
// 销量排名分析图表配置
|
const salesRankingChartOption = computed(() => {
|
const customers = ["客户BB", "客户AA", "客户CC", "客户DD", "客户DD", "客户DD"];
|
const values = [130, 120, 102, 90, 90, 70];
|
const barColors = [
|
"#34D8F7",
|
"#4A8BFF",
|
"#8A6BFF",
|
"#C8C447",
|
"#C8C447",
|
"#C8C447",
|
];
|
|
return {
|
backgroundColor: "transparent",
|
tooltip: {
|
trigger: "axis",
|
axisPointer: { type: "shadow" },
|
backgroundColor: "rgba(0,0,0,0.55)",
|
borderColor: "rgba(64,158,255,0.25)",
|
borderWidth: getResponsiveValue(1),
|
textStyle: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
|
formatter: "{b}: {c} 立方米",
|
},
|
grid: {
|
left: "14%",
|
right: "6%",
|
top: "16%",
|
bottom: "8%",
|
containLabel: true,
|
},
|
xAxis: {
|
type: "value",
|
axisLine: { show: false },
|
axisLabel: { color: "#B8C8E0", fontSize: getResponsiveValue(11) },
|
splitLine: { lineStyle: { color: "rgba(184,200,224,0.12)" } },
|
},
|
yAxis: {
|
type: "category",
|
data: customers,
|
axisTick: { show: false },
|
axisLine: { show: false },
|
axisLabel: {
|
color: "#B8C8E0",
|
fontSize: getResponsiveValue(11),
|
margin: getResponsiveValue(8),
|
},
|
},
|
series: [
|
{
|
name: "销量(立方米)",
|
type: "bar",
|
barWidth: getResponsiveValue(14),
|
data: values,
|
itemStyle: {
|
color: params => barColors[params.dataIndex] || "#00A4ED",
|
borderRadius: [
|
getResponsiveValue(6),
|
getResponsiveValue(6),
|
getResponsiveValue(6),
|
getResponsiveValue(6),
|
],
|
},
|
},
|
],
|
};
|
});
|
|
const baseWidth = ref(1650);
|
// 计算响应式值
|
const getResponsiveValue = baseValue => {
|
return Math.round((baseValue * window.innerWidth) / baseWidth.value);
|
};
|
|
// 初始化图表
|
const initCharts = () => {
|
// 初始化砌块成本图表
|
if (blockCostChart.value && !blockCostChartInstance) {
|
blockCostChartInstance = echarts.init(blockCostChart.value);
|
}
|
|
// 初始化板材成本图表
|
if (boardCostChart.value && !boardCostChartInstance) {
|
boardCostChartInstance = echarts.init(boardCostChart.value);
|
}
|
|
// 初始化产量分析图表
|
if (productionChart.value && !productionChartInstance) {
|
productionChartInstance = echarts.init(productionChart.value);
|
}
|
|
// 初始化新增客户趋势图表
|
if (customerTrendChart.value && !customerTrendChartInstance) {
|
customerTrendChartInstance = echarts.init(customerTrendChart.value);
|
}
|
|
// 初始化销量排名分析图表
|
if (salesRankingChart.value && !salesRankingChartInstance) {
|
salesRankingChartInstance = echarts.init(salesRankingChart.value);
|
}
|
|
updateCharts();
|
};
|
|
// 更新图表
|
const updateCharts = () => {
|
// 更新砌块成本图表
|
if (blockCostChartInstance) {
|
blockCostChartInstance.setOption(blockCostChartOption.value);
|
}
|
|
// 更新板材成本图表
|
if (boardCostChartInstance) {
|
boardCostChartInstance.setOption(boardCostChartOption.value);
|
}
|
|
// 更新产量分析图表
|
if (productionChartInstance) {
|
productionChartInstance.setOption(productionChartOption.value);
|
}
|
|
// 更新新增客户趋势图表
|
if (customerTrendChartInstance) {
|
customerTrendChartInstance.setOption(customerTrendChartOption.value);
|
}
|
|
// 更新销量排名分析图表
|
if (salesRankingChartInstance) {
|
salesRankingChartInstance.setOption(salesRankingChartOption.value);
|
}
|
};
|
|
// 处理时间维度选择
|
const handleBlockTimeDimensionChange = dimension => {
|
blockTimeDimension.value = dimension;
|
updateCharts();
|
};
|
|
const handleBoardTimeDimensionChange = dimension => {
|
boardTimeDimension.value = dimension;
|
updateCharts();
|
};
|
|
const handleProductionTimeDimensionChange = dimension => {
|
productionTimeDimension.value = dimension;
|
updateCharts();
|
};
|
|
const handleCustomerTimeDimensionChange = dimension => {
|
customerTimeDimension.value = dimension;
|
updateCharts();
|
};
|
|
const handleSalesTimeDimensionChange = dimension => {
|
salesTimeDimension.value = dimension;
|
updateCharts();
|
};
|
|
// 处理材料类型选择
|
const handleBlockMaterialTypeChange = type => {
|
blockMaterialType.value = type;
|
updateCharts();
|
};
|
|
const handleBoardMaterialTypeChange = type => {
|
boardMaterialType.value = type;
|
updateCharts();
|
};
|
|
// 处理销售区选择
|
const handleAreaChange = area => {
|
selectedArea.value = area;
|
updateCharts();
|
};
|
|
// 监听窗口大小变化
|
const handleResize = () => {
|
// 先更新图表选项,重新计算响应式值
|
updateCharts();
|
// 然后调整图表大小
|
if (blockCostChartInstance) {
|
blockCostChartInstance.resize();
|
}
|
if (boardCostChartInstance) {
|
boardCostChartInstance.resize();
|
}
|
if (productionChartInstance) {
|
productionChartInstance.resize();
|
}
|
if (customerTrendChartInstance) {
|
customerTrendChartInstance.resize();
|
}
|
if (salesRankingChartInstance) {
|
salesRankingChartInstance.resize();
|
}
|
};
|
|
// 生命周期
|
onMounted(() => {
|
// 启动顶部栏时间刷新
|
if (!timeTicker) {
|
timeTicker = setInterval(() => {
|
now.value = dayjs();
|
}, 1000);
|
}
|
|
// 等待DOM更新后初始化图表
|
nextTick(() => {
|
initCharts();
|
});
|
|
// 添加窗口大小变化监听
|
window.addEventListener("resize", handleResize);
|
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
});
|
|
// 组件卸载时销毁图表实例
|
onBeforeUnmount(() => {
|
if (timeTicker) {
|
clearInterval(timeTicker);
|
timeTicker = null;
|
}
|
|
if (blockCostChartInstance) {
|
blockCostChartInstance.dispose();
|
}
|
if (boardCostChartInstance) {
|
boardCostChartInstance.dispose();
|
}
|
if (productionChartInstance) {
|
productionChartInstance.dispose();
|
}
|
if (customerTrendChartInstance) {
|
customerTrendChartInstance.dispose();
|
}
|
if (salesRankingChartInstance) {
|
salesRankingChartInstance.dispose();
|
}
|
|
// 移除窗口大小变化监听
|
window.removeEventListener("resize", handleResize);
|
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
});
|
</script>
|
|
<style scoped>
|
.sales-statistics-container {
|
position: relative;
|
width: 100%;
|
min-height: calc(100vh - 8.4vh);
|
overflow: hidden;
|
color: #b8c8e0;
|
background: #041026;
|
}
|
|
.sales-statistics-container.is-fullscreen {
|
min-height: 100vh;
|
height: 100vh;
|
}
|
|
/* 深色背景图 */
|
.bi-bg {
|
position: absolute;
|
inset: 0;
|
/* background-image: url("@/assets/BI/backImage@2x.png"); */
|
background-size: cover;
|
background-position: center;
|
background-repeat: no-repeat;
|
z-index: 0;
|
}
|
|
/* 顶部标题栏 */
|
.bi-topbar {
|
position: relative;
|
z-index: 2;
|
height: 5.8vh;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.bi-topbar-title-bg {
|
position: absolute;
|
top: 0;
|
left: 0;
|
height: 8vh;
|
width: 100%;
|
object-fit: cover;
|
z-index: 0;
|
pointer-events: none;
|
}
|
|
.bi-topbar-content {
|
position: relative;
|
z-index: 1;
|
width: 100%;
|
padding: 0 2.8vh;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.bi-topbar-title {
|
position: absolute;
|
left: 50%;
|
transform: translateX(-50%);
|
font-size: 2.6vh;
|
font-weight: 800;
|
letter-spacing: 0.1vh;
|
background: linear-gradient(180deg, #ffffff 0%, #b8dfff 100%);
|
-webkit-background-clip: text;
|
background-clip: text;
|
-webkit-text-fill-color: transparent;
|
color: transparent;
|
text-shadow: 0 0 2.6vh rgba(0, 164, 237, 0.55);
|
}
|
|
.bi-topbar-left {
|
position: absolute;
|
left: 1vh;
|
display: flex;
|
align-items: center;
|
gap: 0.8vh;
|
color: rgba(208, 231, 255, 0.85);
|
font-size: 1.3vh;
|
}
|
|
.status-sun {
|
color: #ffd85e;
|
text-shadow: 0 0 1vh rgba(255, 216, 94, 0.8);
|
font-size: 1.3vh;
|
line-height: 1;
|
}
|
|
.bi-topbar-meta {
|
position: absolute;
|
right: 5.2vh;
|
/* top: 1.6vh; */
|
font-size: 1.2vh;
|
font-weight: 500;
|
letter-spacing: 0.05vh;
|
color: rgba(208, 231, 255, 0.85);
|
display: flex;
|
align-items: center;
|
gap: 1vh;
|
}
|
|
.fullscreen-btn {
|
position: absolute;
|
bottom: -1vh;
|
transform: none;
|
border: 0.1vh solid rgba(64, 158, 255, 0.45);
|
background: rgba(0, 164, 237, 0.14);
|
color: #d0e7ff;
|
width: 3.4vh;
|
height: 3.4vh;
|
border-radius: 0.6vh;
|
padding: 0;
|
cursor: pointer;
|
transition: all 0.2s ease;
|
z-index: 10;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.fullscreen-btn:hover {
|
background: rgba(0, 164, 237, 0.24);
|
box-shadow: 0 0 1.2vh rgba(0, 164, 237, 0.3);
|
}
|
|
.bi-topbar-sep {
|
opacity: 0.7;
|
}
|
|
/* 主体网格布局 */
|
.bi-dashboard-grid {
|
position: relative;
|
z-index: 2;
|
height: calc(100vh - 8.4vh - 5.8vh);
|
min-height: 45vh;
|
padding: 1vh 1.8vh 1.4vh;
|
display: grid;
|
grid-template-columns: 1fr 1.05fr 1fr;
|
grid-template-rows: 1fr 1fr;
|
gap: 1.2vh;
|
}
|
|
.sales-statistics-container.is-fullscreen .bi-dashboard-grid {
|
height: calc(100vh - 5.8vh);
|
}
|
|
.bi-panel {
|
background: rgba(3, 18, 46, 0.62);
|
border: 0.1vh solid rgba(64, 158, 255, 0.35);
|
border-radius: 0.4vh;
|
overflow: hidden;
|
box-shadow: 0 0 2.2vh rgba(0, 164, 237, 0.12);
|
display: flex;
|
flex-direction: column;
|
position: relative;
|
}
|
|
.bi-panel-title {
|
height: 4.4vh;
|
display: flex;
|
align-items: center;
|
padding: 0 1.8vh;
|
font-size: 1.5vh;
|
font-weight: 700;
|
color: #b8c8e0;
|
background: linear-gradient(
|
90deg,
|
rgba(0, 164, 237, 0.2),
|
rgba(0, 164, 237, 0.04)
|
);
|
border-bottom: 0.1vh solid rgba(64, 158, 255, 0.25);
|
}
|
|
.panel-tabs,
|
.panel-tabs2 {
|
position: absolute;
|
top: 0.8vh;
|
display: flex;
|
gap: 0.6vh;
|
z-index: 4;
|
}
|
|
.panel-tabs {
|
right: 1.2vh;
|
}
|
|
.panel-tabs2 {
|
right: 8vh;
|
}
|
.tab-item {
|
font-size: 1.2vh;
|
color: rgba(184, 200, 224, 0.75);
|
padding: 0.1vh 0.5vh;
|
border: 0.1vh solid rgba(64, 158, 255, 0.25);
|
border-radius: 0.3vh;
|
line-height: 1.4;
|
cursor: pointer;
|
}
|
|
.tab-item.active {
|
color: #ffffff;
|
border-color: rgba(0, 164, 237, 0.65);
|
background: rgba(0, 164, 237, 0.22);
|
}
|
|
.bi-panel-body {
|
flex: 1;
|
padding: 0.8vh 1vh;
|
position: relative;
|
}
|
|
.scroll-table-container {
|
height: 33vh;
|
overflow: hidden;
|
position: relative;
|
}
|
|
.scroll-table {
|
width: 100%;
|
border-collapse: collapse;
|
color: #b8c8e0;
|
}
|
|
.scroll-table th {
|
/* background-color: #0e2a54; */
|
padding: 1.2vh;
|
text-align: left;
|
font-size: 1.2vh;
|
font-weight: bold;
|
border: 1px solid rgba(184, 200, 224, 0.2);
|
}
|
|
.scroll-table td {
|
padding: 1vh;
|
font-size: 1.1vh;
|
border-bottom: 1px solid rgba(184, 200, 224, 0.1);
|
}
|
|
.scroll-table tbody {
|
display: block;
|
height: 35vh;
|
overflow: hidden;
|
}
|
|
.scroll-table thead,
|
.scroll-table tbody tr {
|
display: table;
|
width: 100%;
|
table-layout: fixed;
|
}
|
|
.scroll-table th,
|
.scroll-table td {
|
width: 25%;
|
box-sizing: border-box;
|
font-size: 1.4vh;
|
}
|
|
.scroll-table tbody tr {
|
transition: all 0.5s ease-in-out;
|
}
|
|
/* .scroll-table tbody tr:nth-child(odd) {
|
background-color: rgba(64, 158, 255, 0.05);
|
}
|
|
.scroll-table tbody tr:nth-child(even) {
|
background-color: rgba(64, 158, 255, 0.1);
|
} */
|
.oddTableTr {
|
background-color: rgba(64, 158, 255, 0.05);
|
}
|
.evenTableTr {
|
background-color: rgba(64, 158, 255, 0.1);
|
}
|
|
.scroll-table-container:hover tbody {
|
overflow: hidden;
|
}
|
|
.echart-fill {
|
width: 100%;
|
height: 100%;
|
}
|
|
.chart-filter-tabs {
|
display: flex;
|
gap: 0.6vh;
|
margin: 0 0 0.5vh 0;
|
justify-self: end;
|
}
|
|
.cf-tab {
|
font-size: 1.1vh;
|
color: rgba(184, 200, 224, 0.68);
|
background: rgba(18, 56, 106, 0.65);
|
border: 0.1vh solid rgba(64, 158, 255, 0.25);
|
padding: 0.3vh 0.9vh;
|
line-height: 1;
|
cursor: pointer;
|
}
|
|
.cf-tab.active {
|
color: #d9ecff;
|
background: rgba(0, 108, 208, 0.85);
|
border-color: rgba(64, 158, 255, 0.65);
|
}
|
|
.chart-unit-row {
|
display: flex;
|
justify-content: space-between;
|
font-size: 1.2vh;
|
color: rgba(208, 231, 255, 0.88);
|
margin-bottom: 0.4vh;
|
padding: 0 0.2vh;
|
}
|
|
.dot-legend::before {
|
content: "";
|
display: inline-block;
|
width: 0.8vh;
|
height: 0.8vh;
|
background: #65a0ff;
|
margin-right: 0.6vh;
|
}
|
|
.chart-mini-title {
|
display: flex;
|
align-items: center;
|
gap: 0.8vh;
|
font-size: 1.8vh;
|
color: #d9ecff;
|
}
|
|
/* 面板底部合计行 */
|
.panel-summary-row {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 0.8vh 1.2vh;
|
/* margin-top: 0.8vh; */
|
background: #041e3c;
|
border-top: 0.1vh solid rgba(64, 158, 255, 0.25);
|
border-radius: 0 0 0.4vh 0.4vh;
|
width: 100%;
|
position: absolute;
|
bottom: 0;
|
}
|
|
.summary-label {
|
font-size: 1.3vh;
|
font-weight: 700;
|
color: #b8c8e0;
|
}
|
|
.summary-value {
|
font-size: 1.4vh;
|
font-weight: 800;
|
color: #00a4ed;
|
margin-right: 3.8vh;
|
text-shadow: 0 0 1vh rgba(0, 164, 237, 0.5);
|
}
|
|
.summary-value2 {
|
font-size: 1.4vh;
|
font-weight: 800;
|
color: #00a4ed;
|
margin-right: 5.8vh;
|
text-shadow: 0 0 1vh rgba(0, 164, 237, 0.5);
|
}
|
.diamond {
|
width: 1vh;
|
height: 1vh;
|
background: #1e8bff;
|
transform: rotate(45deg);
|
display: inline-block;
|
}
|
|
.chart-unit-single {
|
justify-content: flex-start;
|
margin-bottom: 0.2vh;
|
}
|
|
.bi-panel-top-left .echart-fill,
|
.bi-panel-bottom-left .echart-fill {
|
height: 24vh;
|
}
|
|
|
.bi-panel-bottom-right .echart-fill {
|
height: calc(100% - 2.8vh);
|
}
|
|
.bi-panel-bottom-center .echart-fill,
|
.bi-panel-top-right .echart-fill {
|
height: calc(100% - 4.4vh);
|
}
|
|
.bi-panel-top-left {
|
grid-column: 1;
|
grid-row: 1;
|
position: relative;
|
}
|
|
.bi-panel-top-right {
|
grid-column: 3;
|
grid-row: 1;
|
position: relative;
|
}
|
|
.bi-panel-bottom-left {
|
grid-column: 1;
|
grid-row: 2;
|
overflow-y: auto;
|
}
|
.bi-panel-bottom-left::-webkit-scrollbar {
|
width: 0vh;
|
height: 0vh;
|
}
|
|
.bi-panel-bottom-center {
|
grid-column: 2;
|
grid-row: 2;
|
}
|
|
.bi-panel-bottom-right {
|
grid-column: 3;
|
grid-row: 2;
|
overflow-y: auto;
|
}
|
.bi-panel-bottom-right::-webkit-scrollbar {
|
width: 0vh;
|
height: 0vh;
|
}
|
|
/* 中心环浮层(绝对定位在网格上方) */
|
.center-ring {
|
grid-column: 2;
|
grid-row: 1 / span 2;
|
position: absolute;
|
background: url("@/assets/BI/imageSS@2x.png") no-repeat bottom center;
|
background-size: 100% 30%;
|
left: 25%;
|
top: 25%;
|
transform: translate(-50%, -50%);
|
width: 60vh;
|
height: 40.5vh;
|
z-index: 3;
|
pointer-events: none;
|
}
|
.center-ring-box {
|
position: absolute;
|
/* inset: 0; */
|
height: 100%;
|
width: 100%;
|
/* background-color: #fff; */
|
background: url("@/assets/BI/imageSStop.png") no-repeat center center;
|
background-size: 80% 90%;
|
}
|
|
.center-ring-bg {
|
width: 100%;
|
height: 100%;
|
object-fit: contain;
|
filter: drop-shadow(0 0 2vh rgba(0, 164, 237, 0.35));
|
}
|
|
.center-ring-content {
|
position: absolute;
|
inset: 0;
|
}
|
|
.center-ring-content::before,
|
.center-ring-content::after {
|
content: "";
|
position: absolute;
|
left: 50%;
|
top: 56%;
|
width: 37vh;
|
height: 14.6vh;
|
transform: translate(-50%, -50%) rotate(-18deg);
|
border: 0.2vh solid rgba(40, 186, 255, 0.45);
|
border-radius: 50%;
|
filter: drop-shadow(0 0 0.8vh rgba(0, 164, 237, 0.35));
|
opacity: 0.7;
|
}
|
|
.center-ring-content::after {
|
width: 36vh;
|
height: 15vh;
|
transform: translate(-50%, -50%) rotate(26deg);
|
border-color: rgba(80, 220, 255, 0.35);
|
opacity: 0.55;
|
}
|
|
.center-ring-title {
|
position: absolute;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
font-size: 3.6vh;
|
line-height: 1.05;
|
text-align: center;
|
font-weight: 900;
|
color: #eaf6ff;
|
text-shadow: 0 0 2.2vh rgba(0, 164, 237, 0.55);
|
z-index: 2;
|
}
|
|
.center-ring-title::before {
|
content: "";
|
position: absolute;
|
left: 50%;
|
top: 50%;
|
width: 15.5vh;
|
height: 15.5vh;
|
transform: translate(-50%, -50%);
|
background: radial-gradient(
|
circle,
|
rgba(43, 199, 255, 0.26) 0%,
|
rgba(8, 28, 61, 0.86) 70%
|
);
|
border: 0.2vh solid rgba(39, 198, 255, 0.46);
|
border-radius: 50%;
|
box-shadow: 0 0 2vh rgba(0, 164, 237, 0.45),
|
inset 0 0 2.6vh rgba(0, 164, 237, 0.2);
|
z-index: -1;
|
}
|
|
.center-metric {
|
position: absolute;
|
width: 15.5vh;
|
z-index: 3;
|
text-align: center;
|
height: 12vh;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
align-items: center;
|
}
|
|
.center-metric-label {
|
font-size: 1.2vh;
|
font-weight: 500;
|
color: rgba(234, 246, 255, 0.9);
|
margin-top: 0;
|
}
|
|
.center-metric-value {
|
font-size: 3.4vh;
|
font-weight: 800;
|
color: #eaf6ff;
|
text-shadow: 0 0 0.8vh rgba(0, 229, 255, 0.22);
|
line-height: 1;
|
}
|
|
.center-metric-unit {
|
margin-top: 0;
|
font-size: 1.2vh;
|
color: rgba(208, 231, 255, 0.85);
|
}
|
|
.m1 {
|
top: 2.5vh;
|
left: 4.8vh;
|
text-align: left;
|
}
|
|
.m2 {
|
top: 4.1vh;
|
right: 8.6vh;
|
text-align: right;
|
}
|
|
.m3 {
|
bottom: 7.9vh;
|
left: 4vh;
|
text-align: left;
|
}
|
|
.m4 {
|
bottom: 7vh;
|
right: 5.4vh;
|
text-align: right;
|
}
|
|
@media (max-width: 1100px) {
|
.bi-topbar-content {
|
padding: 0 1.4vh;
|
}
|
.center-ring {
|
left: 45.2%;
|
width: 33vh;
|
height: 24.5vh;
|
top: 2.4vh;
|
}
|
.center-ring-title {
|
top: 50%;
|
font-size: 2.8vh;
|
transform: translate(-50%, -50%);
|
}
|
.center-metric {
|
height: 10.5vh;
|
}
|
.m1 {
|
top: 5.2vh;
|
left: 4.2vh;
|
}
|
.m2 {
|
top: 5.4vh;
|
right: 4.2vh;
|
}
|
.m3 {
|
bottom: 6.2vh;
|
left: 4.8vh;
|
}
|
.m4 {
|
bottom: 6.8vh;
|
right: 4.4vh;
|
}
|
}
|
.scroll-table-content {
|
height: 39vh;
|
overflow: auto;
|
}
|
.scroll-table-content::-webkit-scrollbar {
|
width: 0;
|
height: 0;
|
background-color: transparent;
|
}
|
.total-row {
|
position: absolute;
|
bottom: 0vh;
|
left: 0;
|
width: 100%;
|
display: flex;
|
height: 3.5vh;
|
justify-content: space-around;
|
align-items: center;
|
background-color: #081843;
|
}
|
|
.total-cell {
|
width: 20%;
|
font-size: 1.4vh;
|
margin-bottom: 0.5vh;
|
line-height: 3.5vh;
|
padding-left: 0.8vh;
|
color: #eaf6ff;
|
text-shadow: 0 0 0.8vh rgba(0, 229, 255, 0.22);
|
text-align: left;
|
color: #c3c3c3;
|
}
|
.total-cell2 {
|
width: 20%;
|
font-size: 1.4vh;
|
margin-bottom: 0.5vh;
|
line-height: 3.5vh;
|
color: #eaf6ff;
|
text-shadow: 0 0 0.8vh rgba(0, 229, 255, 0.22);
|
text-align: left;
|
color: #c3c3c3;
|
}
|
/* 材料信息卡片 */
|
.material-info-card {
|
display: flex;
|
align-items: center;
|
padding: 1.2vh 1.6vh;
|
background: rgba(0, 164, 237, 0.1);
|
border-radius: 0.8vh;
|
margin: 1.2vh 1.6vh;
|
}
|
|
.material-icon {
|
width: 4vh;
|
height: 4vh;
|
background: rgba(0, 164, 237, 0.2);
|
border-radius: 50%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 1.2vh;
|
color: #00a4ed;
|
}
|
|
.material-details {
|
flex: 1;
|
}
|
|
.material-name {
|
font-size: 1.3vh;
|
font-weight: 600;
|
color: #d0e7ff;
|
margin-bottom: 0.6vh;
|
}
|
|
.material-stats {
|
display: flex;
|
gap: 1.6vh;
|
}
|
|
.stat-item {
|
display: flex;
|
align-items: center;
|
gap: 0.4vh;
|
}
|
|
.stat-label {
|
font-size: 1vh;
|
opacity: 0.7;
|
}
|
|
.stat-value {
|
font-size: 1.2vh;
|
font-weight: 600;
|
color: #00a4ed;
|
}
|
|
.stat-unit {
|
font-size: 1vh;
|
opacity: 0.7;
|
}
|
|
</style>
|