准备页面修改
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 233 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 24 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="title">
|
||||
<span>{{ title }}</span>
|
||||
<img v-if="showReset" src="@/assets/img/reset.png" alt="" style="width: 20px;height: 20px;cursor: pointer;" @click="reset">
|
||||
<!-- <img v-if="showReset" src="@/assets/img/reset.png" alt="" style="width: 20px;height: 20px;cursor: pointer;" @click="reset">-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -26,9 +26,9 @@ const reset = () => {
|
|||
.title {
|
||||
/* padding: 12px 6px; */
|
||||
height: 36px;
|
||||
padding-left: 30px;
|
||||
line-height: 25px;
|
||||
color: #ccc;
|
||||
padding-left: 55px;
|
||||
line-height: 37px;
|
||||
color: #fff;
|
||||
/* background: linear-gradient(to right, #086c94, #0e557f, #06112c); */
|
||||
background: url('@/assets/img/screen/title_bg.png') no-repeat;
|
||||
|
||||
|
|
@ -36,5 +36,6 @@ const reset = () => {
|
|||
letter-spacing: 4px;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@
|
|||
<div class="box center">
|
||||
<CenterModel />
|
||||
</div>
|
||||
<div class="box">
|
||||
<RightTwoModel />
|
||||
</div>
|
||||
<div class="box">
|
||||
<!-- <div class="box">-->
|
||||
<!-- <RightTwoModel />-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="box">
|
||||
<LeftThreeModel />
|
||||
</div>
|
||||
</div>-->
|
||||
<div class="box">
|
||||
<RightThreeModel />
|
||||
</div>
|
||||
|
|
@ -34,12 +34,12 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import LeftOneModel from './model-components/left-one-model.vue'
|
||||
import LeftTwoModel from './model-components/left-two-model.vue'
|
||||
import LeftOneModel from './model-components/left-one-model-new.vue'
|
||||
import LeftTwoModel from './model-components/left-two-model-new.vue'
|
||||
import LeftThreeModel from './model-components/left-three-model.vue'
|
||||
import RightOneModel from './model-components/right-one-model.vue'
|
||||
import RightOneModel from './model-components/right-one-model-new.vue'
|
||||
import RightTwoModel from './model-components/right-two-model.vue'
|
||||
import RightThreeModel from './model-components/right-three-model.vue'
|
||||
import RightThreeModel from './model-components/right-three-model-new.vue'
|
||||
import CenterModel from './model-components/center-model.vue'
|
||||
|
||||
const router = useRouter()
|
||||
|
|
@ -95,7 +95,7 @@ const back = () => {
|
|||
.dashboard {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 6fr 1.9fr;
|
||||
grid-template-rows: repeat(3, 1fr);
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
gap: 0.5rem;
|
||||
height: calc(100% - 130px);
|
||||
// padding: 0.5rem;
|
||||
|
|
@ -104,7 +104,7 @@ const back = () => {
|
|||
}
|
||||
|
||||
.center {
|
||||
grid-row: 1 / span 3;
|
||||
grid-row: 1 / span 2;
|
||||
grid-column: 2;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,156 @@
|
|||
<template>
|
||||
<!-- 闲置装备分析 -->
|
||||
<div class="container">
|
||||
<ScreenTitle :title="`装备闲置数`" />
|
||||
|
||||
<div class="content">
|
||||
<!-- 数据展示 -->
|
||||
<div class="data-blocks">
|
||||
<!-- 左侧数据块 -->
|
||||
<div class="data-block left">
|
||||
<img class="icon icon1" src="@/assets/img/screen/left-top.png" alt="Icon 1" />
|
||||
<div style='display:flex;'>
|
||||
<div class="value">{{ idle80 || 0 }}</div>
|
||||
<div class="unit">台</div>
|
||||
</div>
|
||||
<div class="label">闲置时间 >80%</div>
|
||||
</div>
|
||||
|
||||
<!-- 中间数据块 -->
|
||||
<div class="data-block center">
|
||||
<img class="icon icon2" src="@/assets/img/screen/left-top.png" alt="Icon 2" />
|
||||
<div style='display:flex;'>
|
||||
<div class="value">{{ idle3080 || 0 }}</div>
|
||||
<div class="unit">台</div>
|
||||
</div>
|
||||
<div class="label">闲置时间 30%-80%</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧数据块 -->
|
||||
<div class="data-block right">
|
||||
<img class="icon icon3" src="@/assets/img/screen/left-top.png" alt="Icon 3" />
|
||||
<div style='display:flex;'>
|
||||
<div class="value">{{ idle30 || 0 }}</div>
|
||||
<div class="unit">台</div>
|
||||
</div>
|
||||
<div class="label">闲置时间 <30%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ScreenTitle from 'components/ScreenTitle/index.vue'
|
||||
import { getIdleDevRatioApi } from 'http/api/screen/index'
|
||||
const leftData_1 = ref<any>([])
|
||||
const idle80 = ref<any>(0)
|
||||
const idle3080 = ref<any>(0)
|
||||
const idle30 = ref<any>(0)
|
||||
const getIdleDevRatioData = async () => {
|
||||
const { data: res }: any = await getIdleDevRatioApi()
|
||||
console.log('🚀 ~ getIdleDevRatioData ~ 左上:', res)
|
||||
// leftData_1.value = res
|
||||
idle80.value = res.idle80
|
||||
idle3080.value = res.idle3080
|
||||
idle30.value = res.idle30
|
||||
}
|
||||
|
||||
getIdleDevRatioData()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@font-face {
|
||||
font-family: 'DS-TITle';
|
||||
src: url('@/assets/font-family/DS-Digital/DS-TITle.ttf');
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: url('@/assets/img/screen/bg_1.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
background: url('@/assets/img/screen/ring_chart.png') no-repeat center center;
|
||||
|
||||
.data-blocks {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.data-block {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: -30px; /* 根据具体需求调整 */
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.icon1 {
|
||||
margin-top: -30px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.icon2 {
|
||||
margin-top: 90px;
|
||||
margin-left: -70px;
|
||||
}
|
||||
|
||||
.icon3 {
|
||||
margin-top: -60px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-family: DS-TITle;
|
||||
font-size: 30px;
|
||||
color: #7FE4CC;
|
||||
}
|
||||
|
||||
.unit {
|
||||
font-size: 14px;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
align-self: flex-start;
|
||||
margin-top: 200px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.center {
|
||||
align-self: center;
|
||||
margin-top: -270px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.right {
|
||||
align-self: flex-end;
|
||||
margin-right: 20px;
|
||||
margin-top: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
<template>
|
||||
<!-- 出租装备分析 -->
|
||||
<div class="container">
|
||||
<ScreenTitle :title="`出租装备数`" />
|
||||
|
||||
<!-- 数据展示 -->
|
||||
<div class="data-blocks">
|
||||
<!-- 输电线路类 -->
|
||||
<div class="data-block transmission">
|
||||
<div class="icon-container">
|
||||
<img src="@/assets/img/screen/ta.png" alt="输电线路类图标" />
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title">输电线路类</div>
|
||||
<div style='display: flex'>
|
||||
<div class="value">210<span class="unit">个</span></div>
|
||||
<div class="percentage">50%</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 变电安装类 -->
|
||||
<div class="data-block transformer">
|
||||
<div class="icon-container">
|
||||
<img src="@/assets/img/screen/ta.png" alt="变电安装类图标" />
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title">变电安装类</div>
|
||||
<div style='display: flex'>
|
||||
<div class="value">120<span class="unit">个</span></div>
|
||||
<div class="percentage">30%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 检修调试类 -->
|
||||
<div class="data-block maintenance">
|
||||
<div class="icon-container">
|
||||
<img src="@/assets/img/screen/ta.png" alt="检修调试类图标" />
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title">检修调试类</div>
|
||||
<div style='display: flex'>
|
||||
<div class="value">80<span class="unit">个</span></div>
|
||||
<div class="percentage">20%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ScreenTitle from 'components/ScreenTitle/index.vue'
|
||||
import { getLeaseCountByTypeNameApi } from 'http/api/screen/index'
|
||||
const leftData_2 = ref<any>([])
|
||||
const getLeaseCountByTypeNameData = async () => {
|
||||
const { data: res }: any = await getLeaseCountByTypeNameApi()
|
||||
leftData_2.value = res
|
||||
leftData_2.value.sort((a: any, b: any) => b.ratio - a.ratio)
|
||||
leftData_2.value.forEach((e: any) => {
|
||||
e.ratio = e.ratio.toFixed(2)
|
||||
})
|
||||
}
|
||||
getLeaseCountByTypeNameData()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@font-face {
|
||||
font-family: 'DS-TITle';
|
||||
src: url('@/assets/font-family/DS-Digital/DS-TITle.ttf');
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: url('@/assets/img/screen/bg_1.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.data-blocks {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
||||
.data-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
.icon-container {
|
||||
margin-leftl: 20px;
|
||||
img {
|
||||
width: 85px; // 根据实际需求调整图标大小
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
margin-left: 10px;
|
||||
.title {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-family: DS-TITle;
|
||||
font-size: 30px;
|
||||
color: #7FE4CC;
|
||||
.unit {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.percentage {
|
||||
font-size: 16px;
|
||||
color: #00b9c7;
|
||||
margin-top: 5px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.transmission {
|
||||
background: url('@/assets/img/screen/left-bottom.png');
|
||||
background-size: 100% 100%;
|
||||
height: 26%;
|
||||
width: 95%;
|
||||
margin-left: 2%;
|
||||
margin-top: 5%;
|
||||
}
|
||||
|
||||
.transformer {
|
||||
background: url('@/assets/img/screen/left-bottom.png');
|
||||
background-size: 100% 100%;
|
||||
width: 95%;
|
||||
margin-left: 2%;
|
||||
height: 26%;
|
||||
}
|
||||
|
||||
.maintenance {
|
||||
background: url('@/assets/img/screen/left-bottom.png');
|
||||
background-size: 100% 100%;
|
||||
width: 95%;
|
||||
margin-left: 2%;
|
||||
height: 26%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,282 @@
|
|||
<template>
|
||||
<!-- 装备共享排名 -->
|
||||
<div class="container">
|
||||
<ScreenTitle :title="`装备共享排名`" />
|
||||
<div class="content" ref="echartsRef"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ScreenTitle from 'components/ScreenTitle/index.vue'
|
||||
import { getDeviceShareRankingApi } from 'http/api/screen/index'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
const getDeviceShareRankingData = async () => {
|
||||
const { data: res }: any = await getDeviceShareRankingApi()
|
||||
console.log('🚀 ~ getDeviceShareRankingData ~ res:', res)
|
||||
chartData.value = res.map((e: any) =>
|
||||
e.comName.length > 6 ? e.comName.slice(0, 6) + '...' : e.comName,
|
||||
)
|
||||
chartDataNew.value = res.map((e: any) => e.comName)
|
||||
state.value = res.map((e: any) => e.deviceCount)
|
||||
console.log('🚀 ~ getDeviceShareRankingData ~ state.value:', state.value)
|
||||
}
|
||||
getDeviceShareRankingData()
|
||||
|
||||
const chartData = ref<any>([])
|
||||
const chartDataNew = ref<any>([])
|
||||
const state = ref<any>([])
|
||||
|
||||
const echartsRef = ref(null)
|
||||
const initEChart = () => {
|
||||
console.log('🚀 ~ initEChart ~ state.value:', state.value)
|
||||
const chart = echarts.init(echartsRef.value)
|
||||
const opt = {
|
||||
index: 0,
|
||||
}
|
||||
var data: any = state.value
|
||||
var className = chartData.value
|
||||
var colorArray = [
|
||||
'#61DEF9', // 黄色
|
||||
'#19DBC8', // 绿色
|
||||
'#E0EE81', // 蓝色
|
||||
'#C6DADC', // 深蓝色
|
||||
]
|
||||
|
||||
const option = {
|
||||
grid: {
|
||||
left: '0',
|
||||
right: '0',
|
||||
bottom: '0%',
|
||||
top: '0',
|
||||
containLabel: true,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'none',
|
||||
},
|
||||
formatter: function (params: any, index: any) {
|
||||
let companyName = ''
|
||||
chartDataNew.value.forEach((e: any) => {
|
||||
if (e.indexOf(params[0].name.slice(0, 6)) != -1) {
|
||||
companyName = e
|
||||
}
|
||||
})
|
||||
return `${companyName} ${params[0].value} 台`
|
||||
},
|
||||
},
|
||||
backgroundColor: '',
|
||||
xAxis: {
|
||||
show: false,
|
||||
type: 'value',
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
inverse: true,
|
||||
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
color: '#e4e6e8',
|
||||
fontSize: 13,
|
||||
formatter: function (value: any, index: any) {
|
||||
if (index < 3) {
|
||||
return '{idx' + index + '|' + (1 + index) + '} {title|' + value + '}'
|
||||
} else if (opt.index !== 0 && index + opt.index < 9) {
|
||||
return '{idx|0' + (1 + index + opt.index) + '} {title|' + value + '}'
|
||||
} else {
|
||||
return '{idx|' + (1 + index + opt.index) + '} {title|' + value + '}'
|
||||
}
|
||||
},
|
||||
rich: {
|
||||
idx0: {
|
||||
color: '#000',
|
||||
backgroundColor: '#6AE7FF',
|
||||
borderRadius: 100,
|
||||
padding: [5, 8],
|
||||
},
|
||||
idx1: {
|
||||
color: '#000',
|
||||
backgroundColor: '#13E3CC',
|
||||
borderRadius: 100,
|
||||
padding: [5, 8],
|
||||
},
|
||||
idx2: {
|
||||
color: '#000',
|
||||
backgroundColor: '#029fd8',
|
||||
borderRadius: 100,
|
||||
padding: [5, 8],
|
||||
},
|
||||
idx: {
|
||||
color: '#9ABDC1',
|
||||
// backgroundColor: '#E2F079',
|
||||
// borderRadius: 100,
|
||||
padding: [5, 8],
|
||||
},
|
||||
title: {
|
||||
color: '#e4e6e8',
|
||||
fontSize: 13,
|
||||
},
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
// axisLine: {
|
||||
// show: false,
|
||||
// },
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#ffffff', // 白色实线
|
||||
width: 1,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
data: className,
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
inverse: true,
|
||||
axisTick: 'none',
|
||||
axisLine: 'none',
|
||||
show: true,
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#e4e6e8',
|
||||
fontSize: '13',
|
||||
},
|
||||
formatter: function (value: any) {
|
||||
return value + ' 台'
|
||||
},
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bar',
|
||||
zlevel: 1,
|
||||
/*itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: 0,
|
||||
color: function (params: any) {
|
||||
let num = colorArray.length
|
||||
return {
|
||||
type: 'linear',
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: colorArray[params.dataIndex % num].bottom,
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: colorArray[params.dataIndex % num].top,
|
||||
},
|
||||
{
|
||||
offset: 0,
|
||||
color: colorArray[params.dataIndex % num].bottom,
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: colorArray[params.dataIndex % num].top,
|
||||
},
|
||||
{
|
||||
offset: 0,
|
||||
color: colorArray[params.dataIndex % num].bottom,
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: colorArray[params.dataIndex % num].top,
|
||||
},
|
||||
{
|
||||
offset: 0,
|
||||
color: colorArray[params.dataIndex % num].bottom,
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: colorArray[params.dataIndex % num].top,
|
||||
},
|
||||
{
|
||||
offset: 0,
|
||||
color: colorArray[params.dataIndex % num].bottom,
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: colorArray[params.dataIndex % num].top,
|
||||
},
|
||||
{
|
||||
offset: 0,
|
||||
color: colorArray[params.dataIndex % num].bottom,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
},*/
|
||||
itemStyle: {
|
||||
normal: {
|
||||
// barBorderRadius: [5, 5, 0, 0],
|
||||
color: function (params: any) {
|
||||
return colorArray[params.dataIndex % colorArray.length]
|
||||
},
|
||||
},
|
||||
},
|
||||
barWidth: 12,
|
||||
data: data,
|
||||
},
|
||||
/*{
|
||||
name: '背景',
|
||||
type: 'bar',
|
||||
barWidth: 12,
|
||||
barGap: '-100%',
|
||||
data: defaultData,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#0b1330',
|
||||
barBorderRadius: 100,
|
||||
},
|
||||
},
|
||||
},*/
|
||||
],
|
||||
}
|
||||
chart.setOption(option)
|
||||
}
|
||||
onMounted(() => {
|
||||
Promise.all([getDeviceShareRankingData()]).then(() => {
|
||||
initEChart()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: url('@/assets/img/screen/bg_1.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.content {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
padding: 0 8px;
|
||||
.item {
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
background-color: #072949;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
<template>
|
||||
<!-- 出租租赁数 -->
|
||||
<div class="container">
|
||||
<ScreenTitle :title="`出租租赁数`" />
|
||||
<div class="tab-buttons" style="position: absolute; top: 15%; left: 30%; z-index: 9999;">
|
||||
<button @click="toggleTab('lease')" :class="{ active: currentTab === 'lease' }">租赁排名</button>
|
||||
<button @click="toggleTab('rent')" :class="{ active: currentTab === 'rent' }">出租排名</button>
|
||||
</div>
|
||||
<div class="content" ref="echartsRef"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ScreenTitle from 'components/ScreenTitle/index.vue'
|
||||
import { getLeaseCountByPublishCompanyApi } from 'http/api/screen/index'
|
||||
import * as echarts from 'echarts'
|
||||
const echartsRef = ref(null)
|
||||
const pieData = ref([])
|
||||
const currentTab = ref('lease') // 默认显示租赁排名
|
||||
|
||||
const toggleTab = (tab: string) => {
|
||||
currentTab.value = tab
|
||||
initCharts() // 切换标签时重新初始化图表
|
||||
}
|
||||
const getLeaseCountByPublishCompanyData = async () => {
|
||||
const { data: res }: any = await getLeaseCountByPublishCompanyApi()
|
||||
pieData.value = res.map((e: any) => {
|
||||
return {
|
||||
value: e.leaseCount,
|
||||
name: e.publishCompany,
|
||||
// e.publishCompany.length > 6
|
||||
// ? e.publishCompany.slice(0, 6) + '..'
|
||||
// : e.publishCompany,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function formatXAxisLabel(value) {
|
||||
let formatted = '';
|
||||
const len = value.length;
|
||||
|
||||
// 每 4 个字符插入一个换行符 \n
|
||||
for (let i = 0; i < len; i++) {
|
||||
formatted += value[i];
|
||||
if ((i + 1) % 4 === 0 && i !== len - 1) {
|
||||
formatted += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// 如果总长度超过 10 字符,则截断并加 ...
|
||||
if (value.length > 10) {
|
||||
const lines = formatted.split('\n');
|
||||
let result = '';
|
||||
let count = 0;
|
||||
for (const line of lines) {
|
||||
if (count + line.length <= 10) {
|
||||
result += line + '\n';
|
||||
count += line.length;
|
||||
} else {
|
||||
result += line.slice(0, 10 - count) + '...';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
const initCharts = () => {
|
||||
const myChart = echarts.init(echartsRef.value)
|
||||
|
||||
// 数据源:第一行为维度名,后续为数据
|
||||
const dataset = {
|
||||
source: [
|
||||
['公司', '租赁', '出租'],
|
||||
['安徽新力电业科技咨询有限公司', 85, 30],
|
||||
['安徽三环电力工程集团有限公司', 64, 45],
|
||||
['安徽明都能源建设集团有限公司', 46, 56],
|
||||
['安徽莱特实业集团有限公司', 32, 78],
|
||||
['安徽宏源电力建设投资有限公司', 18, 10]
|
||||
]
|
||||
};
|
||||
// 处理 x 轴文本
|
||||
const xAxisData = dataset.source.slice(1).map(item => formatXAxisLabel(item[0]));
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' }
|
||||
},
|
||||
legend: {
|
||||
show: false // 隐藏图例
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '10%',
|
||||
bottom: '13%',
|
||||
top: '20%',
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
axisLabel: {
|
||||
color: '#e4e6e8',
|
||||
fontSize: 10,
|
||||
formatter: function (value) {
|
||||
return value.split('@').join('\n'); // 将 @ 替换为换行符 \n
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#ffffff', // 白色实线
|
||||
width: 1,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '台',
|
||||
nameTextStyle: {
|
||||
color: '#e4e6e8'
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#e4e6e8'
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
type: 'dashed',
|
||||
color: 'rgba(255,255,255,0.1)',
|
||||
width: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: currentTab.value === 'lease' ? '租赁' : '出租',
|
||||
type: 'bar',
|
||||
zlevel: 1,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
color: '#fff'
|
||||
},
|
||||
itemStyle: {
|
||||
color: function (params) {
|
||||
const colorArray = [
|
||||
// 第一个柱子 - 带透明度
|
||||
{
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(58,159,174, 0.5)' }, // 带透明度
|
||||
{ offset: 1, color: 'rgba(27,131,144, 0.3)' }
|
||||
]
|
||||
},
|
||||
// 第二个柱子
|
||||
{
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(58, 170, 169, 0.5)' },
|
||||
{ offset: 1, color: 'rgba(24, 133, 141, 0.3)' }
|
||||
]
|
||||
},
|
||||
// 第三个柱子
|
||||
{
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(229,239,145, 0.9)' },
|
||||
{ offset: 1, color: 'rgba(61,139,119, 0.3)' }
|
||||
]
|
||||
},
|
||||
// 第四个柱子(默认)
|
||||
{
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(120, 171, 177, 0.5)' },
|
||||
{ offset: 1, color: 'rgba(55, 134, 145, 0.3)' }
|
||||
]
|
||||
}
|
||||
];
|
||||
return colorArray[params.dataIndex < 3 ? params.dataIndex : 3];
|
||||
},
|
||||
borderWidth: 2,
|
||||
shadowBlur: 1,
|
||||
shadowColor: '#fff',
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 0,
|
||||
opacity: 1,
|
||||
borderColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||
offset: 0,
|
||||
color: '#64BDCB'
|
||||
}, {
|
||||
offset: 1,
|
||||
color: '#48A1AF'
|
||||
}]),
|
||||
},
|
||||
barWidth: '40%',
|
||||
data: dataset.source.slice(1).map(item => item[currentTab.value === 'lease' ? 1 : 2])
|
||||
}
|
||||
]
|
||||
}
|
||||
myChart.setOption(option)
|
||||
// 图例点击事件:切换租赁/出租
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
Promise.all([getLeaseCountByPublishCompanyData()]).then(() => {
|
||||
initCharts()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
.content {
|
||||
flex: 1;
|
||||
background: url('@/assets/img/screen/bg_1.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
z-index: 100;
|
||||
// background-color: orange;
|
||||
}
|
||||
|
||||
.tab-buttons {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
button {
|
||||
padding: 5px 10px;
|
||||
margin-right: 5px;
|
||||
background-color: #09403F;
|
||||
color: #fff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
border-radius: 20px;
|
||||
&.active {
|
||||
background-color: #00b9c7;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.center-icon {
|
||||
position: absolute;
|
||||
top: 41%;
|
||||
left: 17.5%;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
z-index: 1;
|
||||
background: url('@/assets/img/screen/right_3.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||