|
|
<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>
|