You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1220 lines
31 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="data-screen" ref="dataScreen">
<!-- 背景 -->
<div class="screen-background"></div>
<!-- 标题 -->
<div class="screen-header">
<img src="../../assets/jsc/jsc-title.png" alt="" />
</div>
<!-- 主要内容区域 -->
<div class="screen-content">
<!-- 左侧区域 -->
<div class="left-section">
<!-- 校友数据卡片 -->
<div class="data-cards-container warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="data-card alumni-card">
<div class="card-icon">
<div class="icon-pyramid">
<img src="../../assets/jsc/icon1.png" alt="">
</div>
</div>
<div class="card-content">
<div class="card-label">校友总数</div>
<div class="card-value">{{ schoolmate_total }}</div>
</div>
</div>
<div class="data-card yearly-card">
<div class="card-icon">
<div class="icon-pyramid blue">
<img src="../../assets/jsc/icon2.png" alt="">
</div>
</div>
<div class="card-content">
<div class="card-label">2025年校友数</div>
<div class="card-value">{{ schoolmate_year }}</div>
</div>
</div>
</div>
<!-- 课堂分类饼图 -->
<div class="chart-container warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="chart-title"><span>课堂分类</span></div>
<div class="pie-chart" ref="pieChart"></div>
<div class="chart-legend">
<div v-for="item in pieData" :key="item.name" class="legend-item">
<span class="legend-color" :style="{ backgroundColor: item.color }"></span>
<span class="legend-text">{{ item.name }} {{ item.percentage }}%</span>
</div>
</div>
</div>
</div>
<!-- 中间地图区域 -->
<div class="center-section warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="map-container">
<div class="map-title">
<span>苏州地区校友分布</span>
</div>
<div class="map-tabs">
<!-- <div class="tab active">苏州</div>
<div class="tab">全国</div> -->
</div>
<div class="map-chart" ref="mapChart"></div>
</div>
</div>
<!-- 右侧区域 -->
<div class="right-section">
<!-- 企业数据卡片 -->
<div class="enterprise-cards">
<!-- 第一行:开课场次和开课天数 -->
<div class="enterprise-card warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="card-content-wrapper">
<div class="card-icon-3d">
<img src="../../assets/jsc/icon7.png" alt="">
</div>
<div class="card-info">
<div class="card-desc">开课场次</div>
<div class="card-number">{{course_total}}</div>
</div>
</div>
</div>
<div class="enterprise-card warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="card-content-wrapper">
<div class="card-icon-3d">
<img src="../../assets/jsc/icon8.png" alt="">
</div>
<div class="card-info">
<div class="card-desc">开课天数</div>
<div class="card-number">{{course_day_total}}</div>
</div>
</div>
</div>
<!-- 第二行:当年开课场次和当年开课天数 -->
<div class="enterprise-card warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="card-content-wrapper">
<div class="card-icon-3d">
<img src="../../assets/jsc/icon7.png" alt="">
</div>
<div class="card-info">
<div class="card-desc">{{currentYear}}</div>
<div class="card-desc">开课场次</div>
<div class="card-number">{{course_year_total}}</div>
</div>
</div>
</div>
<div class="enterprise-card warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="card-content-wrapper">
<div class="card-icon-3d">
<img src="../../assets/jsc/icon8.png" alt="">
</div>
<div class="card-info">
<div class="card-desc">{{currentYear}}</div>
<div class="card-desc">开课天数</div>
<div class="card-number">{{course_year_day_total}}</div>
</div>
</div>
</div>
</div>
<!-- 校友企业所属领域 -->
<div class="field-chart-container warehouse-table">
<!-- 四个角的三角形 -->
<div class="corner top-left"></div>
<div class="corner top-right"></div>
<div class="corner bottom-left"></div>
<div class="corner bottom-right"></div>
<div class="chart-title" style="padding: 2.5vh 0;margin-bottom:0">校友企业所属领域</div>
<div class="field-chart-custom">
<div v-for="(item, index) in fieldData" :key="item.name" class="chart-item">
<div class="item-left">
<div class="number-circle" :style="{ backgroundColor: item.color }">
{{ index + 1 }}
</div>
<span class="item-name">{{ item.name }}</span>
</div>
<div class="item-right">
<div class="bar-container">
<div
class="bar"
:style="{
width: (item.value / fieldData[0].value * 100) + '%',
background: `linear-gradient(90deg, ${item.color}40, ${item.color})`
}"
></div>
</div>
<span class="item-value">{{ item.value }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import {
home
} from "@/api/homeChart.js"
import szMapData from './szmap.json'
export default {
name: 'JSCDataScreen',
data() {
return {
// 校友数据
schoolmate_total: 0,
schoolmate_year: 0,
// 饼图数据
colorList:['#FFB020','#FF6B47','#4299FF','#FF6B9D','#00E5CC','#1890FF','#52C41A','#9254DE','#52C41A','#FFB020','#FF6B47','#4299FF','#FF6B9D','#00E5CC','#1890FF','#52C41A','#9254DE','#52C41A'],
pieData: [],
// 地图数据
mapData: [],
company_market:0,
company_fund:0,
valuation:0,
// 课程统计数据
course_total: 0,
course_day_total: 0,
course_year_total: 0,
course_year_day_total: 0,
// 当前年份
currentYear: new Date().getFullYear(),
// 领域数据(按值从高到低排序)
fieldData: []
}
},
mounted() {
this.$store.dispatch('app/closeSideBar', {
withoutAnimation: false
})
this.getHomeChart()
// this.initCharts()
this.handleResize()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
if (this.pieChartInstance) this.pieChartInstance.dispose()
if (this.mapChartInstance) this.mapChartInstance.dispose()
// fieldChartInstance 不再需要,因为使用 CSS 实现
},
methods: {
// 获取数据
async getHomeChart() {
const res = await home()
console.log('API返回数据:', res) // 调试用
// 校友人数
this.schoolmate_total = res.schoolmate.schoolmate_total
this.schoolmate_year = res.schoolmate.schoolmate_year
// 课堂分类
const total = res.courseTypes.reduce((sum, item) => {
// 处理不存在year_total或非数字的情况转为数字后累加
const yearTotal = Number(item.course_signs_total ?? 0);
return sum + yearTotal;
}, 0);
res.courseTypes.map((item,index)=>{
const yearTotal = Number(item.course_signs_total ?? 0);
// 避免总和为0时的除以0错误
const ratio = total === 0 ? 0 : (yearTotal / total);
this.pieData.push(
{
name: item.name,
value: item.course_signs_total?item.course_signs_total:0,
color: this.colorList[index],
percentage: Number(ratio * 100).toFixed(2)
}
)
})
// 苏州地图
res.suzhou.map(item=>{
this.mapData.push({
name: item.company_area,
value: item.company_total
})
})
// 企业估值
this.company_market = res.company.company_market
this.company_fund = res.company.company_fund
this.valuation = res.company.valuation
// 课程统计 - 从 res.company 获取数据
this.course_total = res.company.course_total || 0
this.course_day_total = res.company.course_day_total || 0
this.course_year_total = res.company.course_total_year || 0
this.course_year_day_total = res.company.course_day_total_year || 0
// 所属领域
res.industryTotal.sort((a, b) => b.total - a.total).map((item,index)=>{
this.fieldData.push({
name:item.industry,
value:item.total,
color:this.colorList[index]
})
})
this.initCharts()
},
// 初始化图表
initCharts() {
this.$nextTick(() => {
this.initPieChart()
this.initMapChart()
// fieldChart 现在使用 CSS 实现,不需要初始化
})
},
// 初始化饼图
initPieChart() {
this.pieChartInstance = echarts.init(this.$refs.pieChart)
const option = {
backgroundColor: 'rgba(14, 87, 180, 0.1)',
tooltip: {
trigger: 'item',
formatter: '{b}: {c}人 ({d}%)',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#3b82f6',
textStyle: {
color: '#fff'
}
},
series: [{
name: '课堂分类',
type: 'pie',
radius: ['15%', '75%'],
center: ['50%', '50%'],
roseType: 'area',
data: this.pieData.map(item => ({
name: item.name,
value: item.value,
itemStyle: {
color: item.color,
borderRadius: 5,
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.3)'
}
})),
label: {
show: true,
position: 'outside',
formatter: function(params) {
return params.name + '\n' + params.value + '人'
},
fontSize: 12,
fontWeight: 'bold',
color: '#ffffff',
lineHeight: 16
},
labelLine: {
show: true,
length: 15,
length2: 10,
smooth: true,
lineStyle: {
color: 'rgba(255, 255, 255, 0.8)',
width: 2
}
},
emphasis: {
itemStyle: {
shadowBlur: 20,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
label: {
fontSize: 14
}
}
}]
}
this.pieChartInstance.setOption(option)
},
// 初始化地图
initMapChart() {
this.mapChartInstance = echarts.init(this.$refs.mapChart)
// 注册苏州地图数据
echarts.registerMap('suzhou', szMapData)
// 调试:检查工业园区
const industrialPark = szMapData.features.find(f => f.properties.name === '工业园区')
console.log('工业园区地图数据:', industrialPark ? '存在' : '不存在')
const industrialParkData = this.mapData.find(d => d.name === '工业园区')
console.log('工业园区数据:', industrialParkData)
const option = {
tooltip: {
trigger: 'item',
formatter: function(params) {
if (params.data) {
return `${params.name}: ${params.data.value || 0}位校友`
}
return `${params.name}: 0位校友`
},
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#3b82f6',
textStyle: {
color: '#fff'
}
},
visualMap: {
min: 0,
max: Math.max(...this.mapData.map(item => item.value)),
inRange: {
color: ['#e0f2ff', '#75c2f6', '#3b82f6', '#1d4ed8']
},
show: false
},
series: [{
name: '校友分布',
type: 'map',
map: 'suzhou',
roam: false,
zlevel: 1,
zoom: 0.95,
center: [120.65, 31.32],
data: this.mapData.map(item => ({
name: item.name,
value: item.value,
itemStyle: item.name === '工业园区' ? {
borderColor: 'red',
borderWidth: 2,
areaColor: 'rgba(255, 0, 0, 0.3)'
} : undefined
})),
itemStyle: {
borderColor: '#ffffff',
borderWidth: 2,
shadowBlur: 4,
shadowColor: 'rgba(0, 0, 0, 0.4)',
shadowOffsetX: 1,
shadowOffsetY: 1
},
emphasis: {
itemStyle: {
areaColor: 'rgba(59, 130, 246, 0.5)',
borderColor: 'transparent',
borderWidth: 5,
shadowBlur: 10,
shadowColor: 'rgba(59, 130, 246, 0.5)'
}
},
label: {
show: true,
position: 'outside',
color: '#333',
fontSize: 11,
fontWeight: 'bold',
padding: [6, 12],
backgroundColor: 'rgba(255, 255, 255, 0.95)',
borderRadius: 15,
borderColor: '#1ea8f9',
borderWidth: 2,
shadowBlur: 8,
shadowColor: 'rgba(0, 0, 0, 0.2)',
formatter: function(params) {
return params.name + ': ' + (params.value || 0) + '人'
}
},
labelLine: {
show: true,
length: 20,
length2: 15,
lineStyle: {
color: 'rgba(255, 255, 255, 0.8)',
width: 2,
type: 'solid'
}
}
}]
}
this.mapChartInstance.setOption(option)
},
// 领域图表现在使用 CSS 实现,不需要 ECharts 初始化
// 响应式处理
handleResize() {
this.$nextTick(() => {
if (this.pieChartInstance) this.pieChartInstance.resize()
if (this.mapChartInstance) this.mapChartInstance.resize()
// fieldChart 使用 CSS 实现,不需要 resize
})
},
}
}
</script>
<style scoped lang="scss">
.data-screen {
position: relative;
width: calc(100vw - 54px);
height: 100vh;
background: url("../../assets/jsc/bg.png") no-repeat left top;
background-size: 100% 100%;
overflow: scroll;
font-family: 'Microsoft YaHei', sans-serif;
}
.screen-header {
position: relative;
z-index: 10;
width: 100%;
top: 0;
left: 0;
img {
width: 100%;
}
}
.screen-content {
display: flex;
width: 100%;
height: calc(100vh - 10vh);
padding: 2vh 2vw;
gap: 2vw;
}
/* */
.left-section {
flex: 0 0 25%;
display: flex;
flex-direction: column;
gap: 2vh;
}
.data-cards-container {
flex: 0 0 35%;
display: flex;
flex-direction: row;
gap: 1.5vw;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(99, 102, 241, 0.1) 100%);
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: 8px;
padding: 2vh 1.5vw;
backdrop-filter: blur(10px);
}
.data-card {
flex: 1;
background: transparent;
border: none;
border-radius: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.card-icon {
margin-right: 0;
margin-bottom: 1vh;
}
.icon-pyramid {
width: 3vw;
height: 3vw;
min-width: 133px;
min-height: 133px;
position: relative;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.card-content {
flex: 1;
width: 100%;
}
.card-label {
color: #fff;
font-size: 1.2vw;
margin-bottom: 0.5vh;
min-font-size: 12px;
}
.card-value {
color: #dc9c61;
font-size: 2.5vw;
font-weight: bold;
text-shadow: 0 0 10px rgba(59, 130, 246, 0.6);
min-font-size: 24px;
}
.chart-container {
flex: 1;
max-height: 60vh;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(99, 102, 241, 0.05) 100%);
border: 1px solid rgba(59, 130, 246, 0.2);
border-radius: 8px;
padding: 1.5vh 1vw;
backdrop-filter: blur(10px);
}
.chart-title {
color: #93ccfd;
font-size: 1.2vw;
text-align: center;
margin-bottom: 1vh;
min-font-size: 14px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.chart-title span {
font-size: 1.2vw;
margin-bottom: 2.5vh;
min-font-size: 14px;
padding: 2.5vh 0;
display: inline-block;
width: 80%;
text-align: center;
position: relative;
/* border-bottom */
border-bottom: none;
/* 使线 */
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
height: 1px;
background: linear-gradient(90deg,
transparent 0%,
#8edbef 20%,
#8edbef 50%,
#8edbef 80%,
transparent 100%);
border-radius: 1px;
}
}
.pie-chart {
height: 20vh;
min-height: 200px;
}
.chart-legend {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5vh;
margin-top: 1vh;
}
.legend-item {
display: flex;
align-items: center;
font-size: 0.8vw;
color: #35d4dd;
min-font-size: 10px;
}
.legend-color {
width: 0.8vw;
height: 0.8vw;
min-width: 8px;
min-height: 8px;
border-radius: 2px;
margin-right: 0.5vw;
}
/* */
.center-section {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2vh 1.5vw;
position: relative;
/* */
background: linear-gradient(135deg,
rgba(14, 87, 180, 0.1) 0%,
rgba(109, 205, 230, 0.05) 50%,
rgba(14, 87, 180, 0.1) 100%);
border-radius: 12px;
/* */
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.1),
inset 0 -1px 0 rgba(0, 0, 0, 0.1),
0 8px 32px rgba(14, 87, 180, 0.3),
0 4px 16px rgba(109, 205, 230, 0.2),
0 2px 8px rgba(0, 0, 0, 0.1);
/* */
border: 1px solid;
border-image: linear-gradient(135deg,
rgba(109, 205, 230, 0.6),
rgba(14, 87, 180, 0.8),
rgba(109, 205, 230, 0.6)) 1;
/* */
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(
circle at 30% 20%,
rgba(109, 205, 230, 0.1) 0%,
transparent 50%
);
border-radius: 12px;
pointer-events: none;
z-index: 1;
}
}
.map-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 1.5vh 1vw;
position: relative;
z-index: 2;
/* */
// background: linear-gradient(135deg,
// rgba(255, 255, 255, 0.05) 0%,
// rgba(109, 205, 230, 0.02) 50%,
// rgba(255, 255, 255, 0.05) 100%);
// border-radius: 8px;
// /* */
// box-shadow:
// inset 0 2px 4px rgba(255, 255, 255, 0.1),
// inset 0 -2px 4px rgba(0, 0, 0, 0.1);
// /* */
// border: 1px solid rgba(109, 205, 230, 0.3);
/* */
// &::after {
// content: '';
// position: absolute;
// top: 2px;
// left: 2px;
// right: 2px;
// bottom: 2px;
// background: linear-gradient(45deg,
// transparent 0%,
// rgba(109, 205, 230, 0.05) 50%,
// transparent 100%);
// border-radius: 6px;
// pointer-events: none;
// }
}
.map-title {
color: #93ccfd;
font-size: 1.2vw;
text-align: center;
margin-bottom: 1.5vh;
min-font-size: 14px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
position: relative;
z-index: 4;
span {
font-size: 1.2vw;
padding: 1.5vh 0;
display: inline-block;
width: 80%;
text-align: center;
position: relative;
/* border-bottom */
border-bottom: none;
/* 使线 */
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
height: 1px;
background: linear-gradient(90deg,
transparent 0%,
#8edbef 20%,
#8edbef 50%,
#8edbef 80%,
transparent 100%);
border-radius: 1px;
}
}
}
.map-tabs {
display: flex;
justify-content: center;
margin-bottom: 2vh;
}
.tab {
padding: 1vh 2vw;
margin: 0 0.5vw;
background: rgba(59, 130, 246, 0.2);
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: 20px;
color: #94a3b8;
cursor: pointer;
transition: all 0.3s;
font-size: 1vw;
min-font-size: 12px;
}
.tab.active {
background: linear-gradient(135deg, #3b82f6, #6366f1);
color: #ffffff;
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
}
.map-chart {
width: 100%;
height: calc(100% - 6vh);
min-height: 400px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
z-index: 3;
/* */
// &::before {
// content: '';
// position: absolute;
// top: 0;
// left: 0;
// right: 0;
// bottom: 0;
// background: radial-gradient(
// circle at 30% 20%,
// rgba(109, 205, 230, 0.08) 0%,
// transparent 60%
// );
// border-radius: 6px;
// pointer-events: none;
// z-index: 1;
// }
/* */
// &::after {
// content: '';
// position: absolute;
// top: 1px;
// left: 1px;
// right: 1px;
// bottom: 1px;
// background: linear-gradient(135deg,
// rgba(255, 255, 255, 0.03) 0%,
// transparent 50%,
// rgba(0, 0, 0, 0.03) 100%);
// border-radius: 4px;
// pointer-events: none;
// z-index: 2;
// }
}
/* */
.right-section {
flex: 0 0 25%;
display: flex;
flex-direction: column;
gap: 2vh;
}
.enterprise-cards {
flex: 0 0 35%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 2vh 2vw;
align-items: stretch;
justify-content: center;
height: 100%;
min-height: 220px;
}
.enterprise-cards .enterprise-card {
background: transparent;
border: none;
border-radius: 0;
padding: 2vh 1.5vw;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
text-align: center;
height: 100%;
min-height: 90px;
width: 100%;
position: relative;
}
.enterprise-card .card-content-wrapper {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 1vw;
width: 100%;
height: 100%;
}
.card-icon-3d {
width: 60px;
height: 40px;
border-radius: 4px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.blue-cube {
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
}
.purple-cube {
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
box-shadow: 0 4px 15px rgba(139, 92, 246, 0.4);
}
.pink-cube {
background: linear-gradient(135deg, #ec4899, #db2777);
box-shadow: 0 4px 15px rgba(236, 72, 153, 0.4);
}
.card-info {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
flex-grow: 1;
justify-content: center;
min-width: 0;
flex: 1;
}
.card-number {
color: #dc9c61;
font-size: 2.5vw;
font-weight: bold;
text-shadow: 0 0 10px rgba(59, 130, 246, 0.6);
margin-bottom: 0.5vh;
min-font-size: 18px;
line-height: 1.2;
}
.card-desc {
color: #fff;
font-size: 0.9vw;
min-font-size: 11px;
line-height: 1.3;
white-space: nowrap;
margin-bottom: 0.5vh;
}
.field-chart-container {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(99, 102, 241, 0.05) 100%);
border: 1px solid rgba(59, 130, 246, 0.2);
border-radius: 8px;
padding: 1.5vh 1vw;
backdrop-filter: blur(10px);
}
.field-chart {
height: calc(100% - 4vh);
min-height: 300px;
}
.field-chart-custom {
width: 100%;
height: calc(100% - 4vh);
min-height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2.5vh;
padding: 1vh 0;
}
.chart-item {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
max-width: 100%;
}
.item-left {
display: flex;
align-items: center;
gap: 1vw;
min-width: 0;
flex: 0 0 40%;
}
.number-circle {
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 10px;
font-weight: bold;
flex-shrink: 0;
}
.item-name {
color: #fff;
font-size: 13px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-right {
display: flex;
align-items: center;
gap: 1vw;
flex: 1;
min-width: 0;
}
.bar-container {
flex: 1;
height: 12px;
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
overflow: hidden;
}
.bar {
height: 100%;
border-radius: 4px;
transition: width 0.8s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
.item-value {
color: #fff;
font-size: 11px;
font-weight: bold;
min-width: 30px;
text-align: right;
flex-shrink: 0;
}
.warehouse-table {
position: relative;
border: 1px solid #0e57b4;
box-shadow: inset 0 0 10px -2px #6dcde6;
border-radius: 0;
}
/* */
.corner {
position: absolute;
width: 0;
height: 0;
border-style: solid;
z-index: 10;
border: none;
width: 10px;
height: 10px;
/* */
}
/* */
.top-left {
top: -1px;
left: -1px;
border-left: 2px solid #6dcde6;
border-top: 2px solid #6dcde6;
}
/* */
.top-right {
top: -1px;
right: -1px;
border-right: 2px solid #6dcde6;
border-top: 2px solid #6dcde6;
}
/* */
.bottom-left {
bottom: -1px;
left: -1px;
border-left: 2px solid #6dcde6;
border-bottom: 2px solid #6dcde6;
}
/* */
.bottom-right {
bottom: -1px;
right: -1px;
border-right: 2px solid #6dcde6;
border-bottom: 2px solid #6dcde6;
}
/* */
@media (max-width: 1440px) {
.header-title {
font-size: 36px;
}
.card-label {
font-size: 18px;
}
.card-value {
font-size: 32px;
}
.chart-title {
font-size: 16px;
}
.tab {
font-size: 14px;
}
.card-number {
font-size: 18px;
}
.card-desc {
font-size: 12px;
}
}
@media (max-width: 1024px) {
.screen-content {
flex-direction: column;
gap: 2vh;
}
.left-section,
.right-section {
flex: none;
}
.center-section {
flex: none;
height: 50vh;
}
.data-cards-container {
flex-direction: column;
gap: 1.5vh;
}
}
</style>