准备页面修改

This commit is contained in:
lSun 2025-07-03 09:25:38 +08:00
parent 8afb989c93
commit 773dd51d44
13 changed files with 888 additions and 15 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

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

View File

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

View File

@ -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">闲置时间 &gt;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">闲置时间 &lt;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>

View File

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

View File

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

View File

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