2548 lines
90 KiB
Vue
2548 lines
90 KiB
Vue
<template>
|
||
<div style="padding: 10px; background-color: #f8f8f8">
|
||
<!-- 天气以及设备统计信息 -->
|
||
<el-row :gutter="20" style="margin: 10px 0px 20px 0px">
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
|
||
<!-- 天气 -->
|
||
<el-card
|
||
class="weather-card"
|
||
shadow="hover"
|
||
:style="{
|
||
'--background-start': getBackgroundColor(weatherData.data.type).start,
|
||
'--background-end': getBackgroundColor(weatherData.data.type).end,
|
||
}"
|
||
>
|
||
<!-- 头部:城市名称、日期与星期 -->
|
||
<div class="weather-header">
|
||
<h2>{{ weatherData.city }}</h2>
|
||
<div class="date-week">
|
||
<span>{{ weatherData.data.date }}</span>
|
||
<span>{{ weatherData.data.week }}</span>
|
||
</div>
|
||
<p class="weather-description">{{ weatherData.data.type }}</p>
|
||
</div>
|
||
|
||
<!-- 主体:天气图标与温度 -->
|
||
<div class="weather-main">
|
||
<img :src="weatherData.data.typeIcon" alt="天气图标" class="weather-icon" />
|
||
<div class="temperature">{{ weatherData.data.low }} - {{ weatherData.data.high }}</div>
|
||
</div>
|
||
|
||
<!-- 详情信息:风向、风力 -->
|
||
<div class="weather-details">
|
||
<div class="detail-item">
|
||
<i class="el-icon-cloudy-and-sunny"></i>
|
||
<span class="detail-text">{{ weatherData.data.fengxiang }}</span>
|
||
</div>
|
||
<div class="detail-item">
|
||
<i class="el-icon-s-operation"></i>
|
||
<span class="detail-text">{{ weatherData.data.fengli }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空气质量信息 -->
|
||
<div class="air-quality">
|
||
<div class="aqi-info">
|
||
<span class="aqi-value" :class="aqiClass">空气质量</span>
|
||
<span class="aqi-level" :class="aqiClass">{{ weatherData.air.aqi }}</span>
|
||
<span class="aqi-level">{{ weatherData.air.aqi_name }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 天气提示 -->
|
||
<div class="weather-tip">
|
||
<i class="el-icon-info"></i>
|
||
<span>{{ weatherData.tip }}</span>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
<!-- 设备统计 -->
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="10" :xl="10">
|
||
<el-row :gutter="20" style="height: 420px">
|
||
<el-col :span="8" style="margin-bottom: 20px">
|
||
<!-- 设备数量 -->
|
||
<div class="card-panel" style="background: linear-gradient(135deg, #f0fff0 0%, #f5fffa 100%)">
|
||
<div class="card-content device">
|
||
<div class="card-icon">
|
||
<svg-icon icon-class="device" class-name="card-panel-icon" />
|
||
</div>
|
||
<div class="card-data">
|
||
<div class="card-title">{{ $t('home.number') }}</div>
|
||
<count-to :start-val="0" :end-val="deviceStatistic.deviceCount" :duration="3000" class="card-panel-num" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
<el-col :span="8" style="margin-bottom: 20px">
|
||
<!-- 产品数量 -->
|
||
|
||
<div class="card-panel" style="background: linear-gradient(135deg, #fffaf0 0%, #fff0f5 100%)">
|
||
<div class="card-content product">
|
||
<div class="card-icon">
|
||
<svg-icon icon-class="model" class-name="card-panel-icon" />
|
||
</div>
|
||
<div class="card-data">
|
||
<div class="card-title">{{ $t('home.product') }}</div>
|
||
<count-to :start-val="0" :end-val="deviceStatistic.productCount" :duration="3000" class="card-panel-num" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
<el-col :span="8" style="margin-bottom: 20px">
|
||
<!-- 操作记录 -->
|
||
<div class="card-panel" style="background: linear-gradient(135deg, #fffef3 0%, #fffdf0 100%)">
|
||
<div class="card-content function">
|
||
<div class="card-icon">
|
||
<svg-icon icon-class="log-a" class-name="card-panel-icon" />
|
||
</div>
|
||
<div class="card-data">
|
||
<div class="card-title">{{ $t('home.records') }}</div>
|
||
|
||
<count-to :start-val="0" :end-val="deviceStatistic.functionCount" :duration="3000" class="card-panel-num" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<!-- 监测数据 -->
|
||
<div class="card-panel" style="background: linear-gradient(135deg, #e3f2fd 0%, #e1f5fe 100%)">
|
||
<div class="card-content monitor">
|
||
<div class="card-icon">
|
||
<svg-icon icon-class="monitor-a" class-name="card-panel-icon" />
|
||
</div>
|
||
<div class="card-data">
|
||
<div class="card-title">{{ $t('home.monitoring') }}</div>
|
||
|
||
<count-to :start-val="0" :end-val="deviceStatistic.monitorCount" :duration="3000" class="card-panel-num" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<!-- 告警数量 -->
|
||
<div class="card-panel" style="background: linear-gradient(135deg, #f0e7ff 0%, #f6f0ff 100%)">
|
||
<div class="card-content alert">
|
||
<div class="card-icon">
|
||
<svg-icon icon-class="alert" class-name="card-panel-icon" />
|
||
</div>
|
||
<div class="card-data">
|
||
<div class="card-title">{{ $t('home.alarm') }}</div>
|
||
|
||
<count-to :start-val="0" :end-val="deviceStatistic.alertCount" :duration="3000" class="card-panel-num" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<!-- 上报事件 -->
|
||
<div class="card-panel" style="background: linear-gradient(135deg, #f3f9ec 0%, #edfaea 100%)">
|
||
<div class="card-content reports">
|
||
<div class="card-icon">
|
||
<svg-icon icon-class="event-a" class-name="card-panel-icon" />
|
||
</div>
|
||
<div class="card-data">
|
||
<div class="card-title">{{ $t('home.reports') }}</div>
|
||
<count-to :start-val="0" :end-val="deviceStatistic.eventCount" :duration="3000" class="card-panel-num" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 统计信息 -->
|
||
<!-- <el-card shadow="none" style="height: 220px; background-color: #ccc; margin-bottom: 10px"></el-card>
|
||
<el-card shadow="none" style="height: 220px; background-color: #ccc"></el-card> -->
|
||
</el-col>
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
|
||
<!-- 一个折线图 -->
|
||
|
||
<el-card class="line-card" shadow="hover">
|
||
<div ref="line" style="height: 400px; width: 100%"></div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20" style="margin: 10px 0px 20px 0px">
|
||
<!-- 地图部分 -->
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="16" :xl="16">
|
||
<div class="map-card" shadow="hover">
|
||
<div class="map-container">
|
||
<div ref="map" class="map"></div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
|
||
<!-- mqtt状态数据 -->
|
||
<div class="card-container">
|
||
<div ref="statsChart" style="height: 240px; width: 100%"></div>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-card class="rate" shadow="hover" style="margin: 10px 10px 20px 10px">
|
||
<el-row :gutter="80" v-if="isAdmin">
|
||
<!-- cpu使用率 -->
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="14" :xl="12">
|
||
<div style="">
|
||
<div ref="pieCpu" class="pieCpu"></div>
|
||
</div>
|
||
</el-col>
|
||
<!-- 内存使用率 -->
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="5" :xl="6">
|
||
<div style="">
|
||
<div ref="pieMemery" style="height: 161px"></div>
|
||
</div>
|
||
</el-col>
|
||
<!-- 系统盘使用率 -->
|
||
<el-col :xs="24" :sm="24" :md="24" :lg="5" :xl="6">
|
||
<div style="">
|
||
<div ref="pieDisk" style="height: 161px"></div>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import axios from 'axios';
|
||
import { getDeviceStatistic } from '@/api/iot/device';
|
||
import { listNotice, getNotice } from '@/api/system/notice';
|
||
import CountTo from 'vue-count-to';
|
||
import { loadBMap } from '@/utils/map.js';
|
||
//安装的是echarts完整包,里面包含百度地图扩展,路径为 echarts/extension/bmap/bmap.js,将其引入
|
||
//ECharts的百度地图扩展,可以在百度地图上展现点图,线图,热力图等可视化
|
||
require('echarts/extension/bmap/bmap');
|
||
import { getServer } from '@/api/monitor/server';
|
||
import { listAllDeviceShort } from '@/api/iot/device';
|
||
import 'echarts-liquidfill';
|
||
import { color, time } from 'echarts';
|
||
import { searchUserCount } from '@/api/monitor/jobLog';
|
||
import { getNettyMqttStats, statisticNettyMqtt } from '@/api/iot/netty';
|
||
// import { count } from 'echarts/types/src/component/dataZoom/history.js';
|
||
|
||
export default {
|
||
name: 'Index',
|
||
components: {
|
||
CountTo,
|
||
},
|
||
data() {
|
||
return {
|
||
//天气信息
|
||
weatherData: {
|
||
success: true,
|
||
city: '北京市',
|
||
data: {
|
||
date: '2024-03-14',
|
||
week: '星期四',
|
||
type: '晴',
|
||
typeIcon: require('../../src/assets/icons/qing.png'), // 确保路径正确
|
||
low: '5°C',
|
||
high: '21°C',
|
||
fengxiang: '西南风',
|
||
fengli: '3-4级',
|
||
},
|
||
air: {
|
||
aqi: 85,
|
||
aqi_level: 2,
|
||
aqi_name: '良',
|
||
},
|
||
tip: '天有点冷,注意保暖~',
|
||
},
|
||
// mqtt状态数据
|
||
stats: {},
|
||
// mqtt统计信息
|
||
static: {},
|
||
// 折线图信息
|
||
linechart: {
|
||
date: [],
|
||
counts: [],
|
||
},
|
||
// 遮罩层
|
||
loading: true,
|
||
// 是否显示弹出层
|
||
open: false,
|
||
// 信息列表
|
||
noticeList: [],
|
||
// 信息详情
|
||
notice: {},
|
||
// 是否为管理员
|
||
isAdmin: false,
|
||
// 设备列表
|
||
deviceList: [],
|
||
// 设备统计信息
|
||
deviceStatistic: {},
|
||
// 设备总数
|
||
deviceCount: 0,
|
||
// 版本号
|
||
version: '3.8.0',
|
||
animate: true,
|
||
duration: 10, // 公告滚动一次的时长(单位:秒)
|
||
interval: 2000, // 公告间隔时间(单位:毫秒)
|
||
// 服务器信息
|
||
server: {
|
||
jvm: {
|
||
name: '',
|
||
version: '',
|
||
startTime: '',
|
||
runTime: '',
|
||
used: '',
|
||
total: 100,
|
||
},
|
||
sys: {
|
||
computerName: '',
|
||
osName: '',
|
||
computerIp: '',
|
||
osArch: '',
|
||
},
|
||
cpu: {
|
||
cpuNum: 1,
|
||
},
|
||
mem: {
|
||
total: 2,
|
||
},
|
||
},
|
||
tableData: [],
|
||
};
|
||
},
|
||
computed: {
|
||
aqiClass() {
|
||
switch (this.weatherData.air.aqi_level) {
|
||
case 1:
|
||
return 'aqi-good';
|
||
case 2:
|
||
return 'aqi-moderate';
|
||
case 3:
|
||
return 'aqi-unhealthy';
|
||
default:
|
||
return '';
|
||
}
|
||
},
|
||
},
|
||
mounted() {
|
||
this.startScroll();
|
||
},
|
||
beforeDestroy() {
|
||
this.stopScroll();
|
||
},
|
||
created() {
|
||
this.init();
|
||
this.getAllDevice();
|
||
this.getNoticeList();
|
||
this.getDeviceStatistic();
|
||
this.fetchWeather();
|
||
|
||
this.getMqttStats();
|
||
this.statisticMqtt();
|
||
},
|
||
methods: {
|
||
// 公告栏滚动
|
||
startScroll() {
|
||
this.intervalId = setInterval(() => {
|
||
const firstNotice = this.noticeList.shift();
|
||
this.noticeList.push(firstNotice);
|
||
}, this.interval);
|
||
},
|
||
stopScroll() {
|
||
if (this.intervalId) {
|
||
clearInterval(this.intervalId);
|
||
}
|
||
},
|
||
// 折线图
|
||
getChartData() {
|
||
searchUserCount().then((response) => {
|
||
console.log('折线图信息', response);
|
||
response.data.reverse().forEach((item) => {
|
||
this.linechart.date.push(item.datetime);
|
||
this.linechart.counts.push(item.user_count);
|
||
});
|
||
console.log('折线图数据', this.linechart);
|
||
this.drawLine();
|
||
|
||
// this.responseData.data.forEach(item => {
|
||
// this.chartData.xAxisData.push(item.datetime);
|
||
// this.chartData.yAxisData.push(item.user_count);
|
||
//});
|
||
});
|
||
},
|
||
// mqtt统计数据
|
||
statisticMqtt() {
|
||
statisticNettyMqtt().then((response) => {
|
||
this.static = response.data;
|
||
});
|
||
},
|
||
/** 查询mqtt状态数据*/
|
||
getMqttStats() {
|
||
getNettyMqttStats().then((response) => {
|
||
this.stats = response.data;
|
||
this.drawStats();
|
||
});
|
||
},
|
||
// 绘制柱状图
|
||
drawStats() {
|
||
// 基于准备好的dom,初始化echarts实例
|
||
let myChart = this.$echarts.init(this.$refs.statsChart);
|
||
var option;
|
||
|
||
option = {
|
||
title: {
|
||
text: this.$t('netty.mqtt.564432-12'),
|
||
|
||
textStyle: {
|
||
fontSize: 19,
|
||
color: '#4A4A4A',
|
||
fontWeight: 'bold',
|
||
fontFamily: 'Arial, sans-serif', // 现代字体
|
||
},
|
||
left: 'left',
|
||
top: '5%',
|
||
},
|
||
tooltip: {
|
||
trigger: 'item',
|
||
backgroundColor: 'rgba(255, 255, 255, 0.95)', // 更加柔和的背景
|
||
borderColor: '#FF6F61', // 边框颜色
|
||
borderWidth: 1,
|
||
textStyle: {
|
||
color: '#333', // 文字颜色
|
||
},
|
||
},
|
||
legend: {
|
||
textStyle: {
|
||
color: '#4A4A4A',
|
||
fontFamily: 'Arial, sans-serif',
|
||
},
|
||
orient: 'vertical',
|
||
right: '10%',
|
||
top: '15%',
|
||
itemGap: 10, // 图例之间的间距
|
||
},
|
||
grid: {
|
||
left: '10%',
|
||
right: '10%',
|
||
bottom: '10%',
|
||
containLabel: true,
|
||
},
|
||
xAxis: {
|
||
type: 'value',
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#B0BEC5', // 和谐的轴线颜色
|
||
},
|
||
},
|
||
splitNumber: 3,
|
||
splitLine: {
|
||
lineStyle: {
|
||
type: 'dashed',
|
||
color: '#E0E0E0',
|
||
},
|
||
},
|
||
},
|
||
yAxis: {
|
||
type: 'category',
|
||
axisLabel: {
|
||
fontSize: 14,
|
||
color: '#455A64', // 标签颜色
|
||
fontFamily: 'Arial, sans-serif', // 现代字体
|
||
},
|
||
splitNumber: 3,
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#B0BEC5',
|
||
},
|
||
},
|
||
data: [this.$t('netty.mqtt.564432-13'), this.$t('netty.mqtt.564432-14'), this.$t('netty.mqtt.564432-15'), this.$t('netty.mqtt.564432-16'), this.$t('netty.mqtt.564432-17')],
|
||
},
|
||
series: [
|
||
{
|
||
name: this.$t('netty.mqtt.564432-18'),
|
||
type: 'bar',
|
||
data: [this.stats['connection_count'], this.stats['session_count'], this.stats['subscription_count'], this.stats['retain_count'], this.stats['retain_count']],
|
||
itemStyle: {
|
||
color: new this.$echarts.graphic.LinearGradient(
|
||
0,
|
||
0,
|
||
1,
|
||
0, // 横向渐变
|
||
[
|
||
{ offset: 0, color: '#FFE3E3' }, // 更加浅的粉色
|
||
{ offset: 1, color: '#FFD1D1' }, // 更加柔和的粉色
|
||
]
|
||
),
|
||
borderRadius: [20, 20, 20, 20], // 圆角柱子
|
||
shadowColor: 'rgba(255, 105, 180, 0.5)', // 柔和的阴影
|
||
shadowBlur: 10, // 阴影模糊度
|
||
shadowOffsetX: 5, // 阴影偏移
|
||
shadowOffsetY: 5, // 阴影偏移
|
||
},
|
||
globalCoord: false, // 缺省为 false
|
||
},
|
||
{
|
||
name: this.$t('netty.mqtt.564432-19'),
|
||
type: 'bar',
|
||
data: [this.stats['connection_total'], this.stats['session_total'], this.stats['subscription_total'], this.stats['retain_total'], this.stats['retain_total']],
|
||
itemStyle: {
|
||
color: new this.$echarts.graphic.LinearGradient(
|
||
0,
|
||
0,
|
||
1,
|
||
0, // 横向渐变
|
||
[
|
||
{ offset: 0, color: '#85E3FF' }, // 清新的蓝色
|
||
{ offset: 1, color: '#B9FBC0' }, // 更加柔和的绿色
|
||
]
|
||
),
|
||
borderRadius: [20, 20, 20, 20], // 圆角柱子
|
||
shadowColor: 'rgba(0, 191, 255, 0.5)', // 柔和的阴影
|
||
shadowBlur: 10, // 阴影模糊度
|
||
shadowOffsetX: 5, // 阴影偏移
|
||
shadowOffsetY: 5, // 阴影偏移
|
||
},
|
||
globalCoord: false, // 缺省为 false
|
||
},
|
||
],
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
},
|
||
|
||
// 天气
|
||
async fetchWeather() {
|
||
this.isLoading = true;
|
||
this.error = null;
|
||
try {
|
||
const response = await axios.get('https://api.vvhan.com/api/weather');
|
||
if (response.data && response.data.success) {
|
||
console.log(response.data);
|
||
this.weatherData = {
|
||
success: true,
|
||
city: response.data.city,
|
||
data: {
|
||
date: response.data.data.date,
|
||
week: response.data.data.week,
|
||
type: response.data.data.type,
|
||
typeIcon: this.getTypeIcon(response.data.data.type),
|
||
low: response.data.data.low,
|
||
high: response.data.data.high,
|
||
fengxiang: response.data.data.fengxiang,
|
||
fengli: response.data.data.fengli,
|
||
night: {
|
||
type: response.data.data.night.type,
|
||
fengxiang: response.data.data.night.fengxiang,
|
||
fengli: response.data.data.night.fengli,
|
||
},
|
||
},
|
||
air: {
|
||
aqi: response.data.air.aqi,
|
||
aqi_level: response.data.air.aqi_level,
|
||
aqi_name: response.data.air.aqi_name,
|
||
co: response.data.air.co,
|
||
no2: response.data.air.no2,
|
||
o3: response.data.air.o3,
|
||
pm10: response.data.air.pm10,
|
||
pm2_5: response.data.air.pm2_5,
|
||
so2: response.data.air.so2,
|
||
},
|
||
tip: response.data.tip,
|
||
};
|
||
// 动态设置背景颜色
|
||
const background = this.getBackgroundColor(response.data.data.type);
|
||
document.documentElement.style.setProperty('--background-start', background.start);
|
||
document.documentElement.style.setProperty('--background-end', background.end);
|
||
} else {
|
||
this.error = '获取天气数据失败,请稍后重试。';
|
||
}
|
||
} catch (err) {
|
||
console.error(err);
|
||
this.error = '无法连接到天气服务,请检查网络或稍后再试。';
|
||
} finally {
|
||
this.isLoading = false;
|
||
}
|
||
},
|
||
getBackgroundColor(type) {
|
||
const backgrounds = {
|
||
晴: {
|
||
start: '#FFF0C1', // 浅黄色(柔和的阳光色)
|
||
end: '#FFD1D1', // 柔和的粉色(温暖可爱)
|
||
},
|
||
多云: {
|
||
start: '#F3F6FF', // 极浅的柔和蓝色
|
||
end: '#DCE6FA', // 柔和的蓝灰色(轻盈的云朵感)
|
||
},
|
||
阴: {
|
||
start: '#F5F5F5', // 近乎白色的浅灰色
|
||
end: '#D3D3D3', // 柔和的浅灰色(朦胧感)
|
||
},
|
||
小雨: {
|
||
start: '#D8F0FF', // 非常柔和的浅蓝色(水滴感)
|
||
end: '#BCE0FF', // 更加可爱的浅蓝色
|
||
},
|
||
中雨: {
|
||
start: '#C4DFFF', // 轻柔的灰蓝色
|
||
end: '#A1C4F8', // 带点温柔感的蓝色
|
||
},
|
||
大雨: {
|
||
start: '#A8E3FF', // 清新的浅蓝色
|
||
end: '#8CCFFF', // 柔和的蓝色渐变
|
||
},
|
||
雷阵雨: {
|
||
start: '#F2E7FF', // 柔和的浅紫色(雷电的闪烁感)
|
||
end: '#C2C2C2', // 柔和的灰色(符合雷阵雨的阴沉感)
|
||
},
|
||
暴雨: {
|
||
start: '#D8F0FF', // 非常柔和的浅蓝色(水滴感)
|
||
end: '#C2C2C2', // 柔和的灰色
|
||
},
|
||
};
|
||
return backgrounds[type] || { start: '#F5F9FF', end: '#FBFBFD' }; // 默认柔和的蓝白色背景
|
||
},
|
||
getTypeIcon(type) {
|
||
console.log(type);
|
||
// 根据天气类型返回对应的图标路径
|
||
const icons = {
|
||
晴: require('../../src/assets/icons/qing.png'),
|
||
多云: require('../../src/assets/icons/duoyun.png'),
|
||
阴: require('../../src/assets/icons/yin.png'),
|
||
小雨: require('../../src/assets/icons/xiaoyu.png'),
|
||
中雨: require('../../src/assets/icons/zhongyu.png'),
|
||
大雨: require('../../src/assets/icons/dayu.png'),
|
||
雷阵雨: require('../../src/assets/icons/leizhenyu.png'),
|
||
暴雨: require('../../src/assets/icons/dayu.png'),
|
||
// 添加更多天气类型和对应图标
|
||
};
|
||
return icons[type] || require('../../src/assets/icons/qing.png');
|
||
},
|
||
init() {
|
||
if (this.$store.state.user.roles.indexOf('tenant') === -1 && this.$store.state.user.roles.indexOf('general') === -1) {
|
||
this.isAdmin = true;
|
||
this.getServer();
|
||
this.getChartData();
|
||
}
|
||
},
|
||
//刷新iframe
|
||
flushIframe() {
|
||
var iframe = window.parent.document.getElementById('iframe');
|
||
iframe.contentWindow.location.reload(true);
|
||
},
|
||
/** 查询设备统计信息 */
|
||
getDeviceStatistic() {
|
||
getDeviceStatistic().then((response) => {
|
||
this.deviceStatistic = response.data;
|
||
});
|
||
},
|
||
/** 查询公告列表 */
|
||
getNoticeList() {
|
||
let queryParams = {
|
||
pageNum: 1,
|
||
pageSize: 6,
|
||
};
|
||
listNotice(queryParams).then((response) => {
|
||
this.noticeList = response.rows.splice(0, 6);
|
||
});
|
||
},
|
||
// 打开信息详情
|
||
openDetail(id) {
|
||
this.open = true;
|
||
this.loading = true;
|
||
getNotice(id).then((response) => {
|
||
this.notice = response.data;
|
||
this.open = true;
|
||
this.loading = false;
|
||
});
|
||
},
|
||
// 取消按钮
|
||
closeDetail() {
|
||
this.title = '';
|
||
this.open = false;
|
||
},
|
||
/**查询所有设备 */
|
||
getAllDevice() {
|
||
listAllDeviceShort(this.queryParams).then((response) => {
|
||
this.deviceList = response.rows;
|
||
this.deviceCount = response.total;
|
||
this.loadMap();
|
||
});
|
||
},
|
||
/**加载地图*/
|
||
loadMap() {
|
||
this.$nextTick(() => {
|
||
loadBMap().then(() => {
|
||
this.getmap();
|
||
});
|
||
});
|
||
},
|
||
/** 查询服务器信息 */
|
||
getServer() {
|
||
getServer().then((response) => {
|
||
this.server = response.data;
|
||
console.log(response.data);
|
||
this.tableData = [
|
||
{
|
||
server: this.$t('home.serverName'),
|
||
serverContent: this.server.sys.computerName,
|
||
java: this.$t('home.javaName'),
|
||
javaContent: this.server.jvm.name,
|
||
},
|
||
{
|
||
server: this.$t('home.serverIp'),
|
||
serverContent: this.server.sys.computerIp,
|
||
java: this.$t('home.startTime'),
|
||
javaContent: this.server.jvm.startTime,
|
||
},
|
||
{
|
||
server: this.$t('home.system'),
|
||
serverContent: this.server.sys.osName,
|
||
java: this.$t('home.javaVer'),
|
||
javaContent: this.server.jvm.version,
|
||
},
|
||
{
|
||
server: this.$t('home.architecture'),
|
||
serverContent: this.server.sys.osArch,
|
||
java: this.$t('home.runtime'),
|
||
javaContent: this.server.jvm.runTime,
|
||
},
|
||
{
|
||
server: this.$t('home.core'),
|
||
serverContent: this.server.cpu.cpuNum,
|
||
java: this.$t('home.memory'),
|
||
javaContent: this.server.jvm.used,
|
||
},
|
||
{
|
||
server: this.$t('home.size'),
|
||
serverContent: this.server.mem.total,
|
||
java: this.$t('home.JVM'),
|
||
javaContent: this.server.jvm.total,
|
||
},
|
||
];
|
||
this.$nextTick(() => {
|
||
this.drawPieCpu();
|
||
this.drawPieMemery();
|
||
this.drawPieDisk();
|
||
});
|
||
});
|
||
},
|
||
|
||
/** 地图 */
|
||
getmap() {
|
||
var myChart = this.$echarts.init(this.$refs.map);
|
||
var option;
|
||
|
||
// 单击事件
|
||
myChart.on('click', (params) => {
|
||
if (params.data.deviceId) {
|
||
this.$router.push({
|
||
path: '/iot/device-edit',
|
||
query: {
|
||
t: Date.now(),
|
||
deviceId: params.data.deviceId,
|
||
},
|
||
});
|
||
}
|
||
});
|
||
|
||
// 格式化数据
|
||
let convertData = function (data, status) {
|
||
var res = [];
|
||
for (var i = 0; i < data.length; i++) {
|
||
var geoCoord = [data[i].longitude, data[i].latitude];
|
||
if (geoCoord && data[i].status == status) {
|
||
res.push({
|
||
name: data[i].deviceName,
|
||
value: geoCoord,
|
||
status: data[i].status,
|
||
isShadow: data[i].isShadow,
|
||
firmwareVersion: data[i].firmwareVersion,
|
||
networkAddress: data[i].networkAddress,
|
||
productName: data[i].productName,
|
||
activeTime: data[i].activeTime == null ? '' : data[i].activeTime,
|
||
deviceId: data[i].deviceId,
|
||
serialNumber: data[i].serialNumber,
|
||
locationWay: data[i].locationWay,
|
||
});
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
option = {
|
||
title: {
|
||
text: this.$t('home.onlineDevice') + this.deviceList.filter((x) => x.status == 3).length + ')',
|
||
subtext: 'Lidee open source iot platform',
|
||
sublink: 'https://iot.lidee.cn',
|
||
target: '_blank',
|
||
textStyle: {
|
||
color: '#333',
|
||
textBorderColor: '#fff',
|
||
textBorderWidth: 10,
|
||
},
|
||
top: 10,
|
||
left: 'center',
|
||
},
|
||
tooltip: {
|
||
trigger: 'item',
|
||
formatter: function (params) {
|
||
var htmlStr = '<div style="padding:5px;line-height:28px;">';
|
||
htmlStr += "设备名称: <span style='color:#409EFF'>" + params.data.name + '</span><br />';
|
||
htmlStr += '设备编号: ' + params.data.serialNumber + '<br />';
|
||
htmlStr += '设备状态: ';
|
||
if (params.data.status == 1) {
|
||
htmlStr += "<span style='color:#E6A23C'>未激活</span>" + '<br />';
|
||
} else if (params.data.status == 2) {
|
||
htmlStr += "<span style='color:#F56C6C'>禁用</span>" + '<br />';
|
||
} else if (params.data.status == 3) {
|
||
htmlStr += "<span style='color:#67C23A'>在线</span>" + '<br />';
|
||
} else if (params.data.status == 4) {
|
||
htmlStr += "<span style='color:#909399'>离线</span>" + '<br />';
|
||
}
|
||
if (params.data.isShadow == 1) {
|
||
htmlStr += '设备影子: ' + "<span style='color:#67C23A'>启用</span>" + '<br />';
|
||
} else {
|
||
htmlStr += '设备影子: ' + "<span style='color:#909399'>未启用</span>" + '<br />';
|
||
}
|
||
htmlStr += '产品名称: ' + params.data.productName + '<br />';
|
||
htmlStr += '固件版本: Version ' + params.data.firmwareVersion + '<br />';
|
||
htmlStr += '激活时间: ' + params.data.activeTime + '<br />';
|
||
htmlStr += '定位方式: ';
|
||
if (params.data.locationWay == 1) {
|
||
htmlStr += '自动定位' + '<br />';
|
||
} else if (params.data.locationWay == 2) {
|
||
htmlStr += '设备定位' + '<br />';
|
||
} else if (params.data.locationWay == 3) {
|
||
htmlStr += '自定义位置' + '<br />';
|
||
} else {
|
||
htmlStr += '未知' + '<br />';
|
||
}
|
||
htmlStr += '所在地址: ' + params.data.networkAddress + '<br />';
|
||
htmlStr += '</div>';
|
||
return htmlStr;
|
||
},
|
||
},
|
||
bmap: {
|
||
center: [133, 38],
|
||
zoom: 5,
|
||
roam: true,
|
||
mapStyle: {
|
||
styleJson: [
|
||
{
|
||
featureType: 'water',
|
||
elementType: 'all',
|
||
stylers: {
|
||
color: '#a0cfff',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'land',
|
||
elementType: 'all',
|
||
stylers: {
|
||
color: '#fafafa', // #fffff8 淡黄色
|
||
},
|
||
},
|
||
{
|
||
featureType: 'railway',
|
||
elementType: 'all',
|
||
stylers: {
|
||
visibility: 'off',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'highway',
|
||
elementType: 'all',
|
||
stylers: {
|
||
color: '#fdfdfd',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'highway',
|
||
elementType: 'labels',
|
||
stylers: {
|
||
visibility: 'off',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'arterial',
|
||
elementType: 'geometry',
|
||
stylers: {
|
||
color: '#fefefe',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'arterial',
|
||
elementType: 'geometry.fill',
|
||
stylers: {
|
||
color: '#fefefe',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'poi',
|
||
elementType: 'all',
|
||
stylers: {
|
||
visibility: 'off',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'green',
|
||
elementType: 'all',
|
||
stylers: {
|
||
visibility: 'off',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'subway',
|
||
elementType: 'all',
|
||
stylers: {
|
||
visibility: 'off',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'manmade',
|
||
elementType: 'all',
|
||
stylers: {
|
||
color: '#d1d1d1',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'local',
|
||
elementType: 'all',
|
||
stylers: {
|
||
color: '#d1d1d1',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'arterial',
|
||
elementType: 'labels',
|
||
stylers: {
|
||
visibility: 'off',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'boundary',
|
||
elementType: 'all',
|
||
stylers: {
|
||
color: '#999999',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'building',
|
||
elementType: 'all',
|
||
stylers: {
|
||
color: '#d1d1d1',
|
||
},
|
||
},
|
||
{
|
||
featureType: 'label',
|
||
elementType: 'labels.text.fill',
|
||
stylers: {
|
||
color: '#999999',
|
||
},
|
||
},
|
||
],
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
type: 'scatter',
|
||
coordinateSystem: 'bmap',
|
||
data: convertData(this.deviceList, 1),
|
||
symbolSize: 15,
|
||
itemStyle: {
|
||
color: '#E6A23C',
|
||
},
|
||
},
|
||
{
|
||
type: 'scatter',
|
||
coordinateSystem: 'bmap',
|
||
data: convertData(this.deviceList, 2),
|
||
symbolSize: 15,
|
||
itemStyle: {
|
||
color: '#F56C6C',
|
||
},
|
||
},
|
||
{
|
||
type: 'scatter',
|
||
coordinateSystem: 'bmap',
|
||
data: convertData(this.deviceList, 4),
|
||
symbolSize: 15,
|
||
itemStyle: {
|
||
color: '#909399',
|
||
},
|
||
},
|
||
{
|
||
type: 'effectScatter',
|
||
coordinateSystem: 'bmap',
|
||
data: convertData(this.deviceList, 3),
|
||
symbolSize: 15,
|
||
showEffectOn: 'render',
|
||
rippleEffect: {
|
||
brushType: 'stroke',
|
||
scale: 5,
|
||
},
|
||
label: {
|
||
formatter: '{b}',
|
||
position: 'right',
|
||
show: false,
|
||
},
|
||
itemStyle: {
|
||
color: '#67C23A',
|
||
shadowBlur: 100,
|
||
shadowColor: '#333',
|
||
},
|
||
zlevel: 1,
|
||
},
|
||
],
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
},
|
||
|
||
drawPieCpu() {
|
||
// 基于准备好的dom,初始化echarts实例
|
||
let myChart = this.$echarts.init(this.$refs.pieCpu);
|
||
var option;
|
||
|
||
// 水球图
|
||
option = {
|
||
backgroundColor: '#fff',
|
||
|
||
title: {
|
||
text: this.$t('home.usage'),
|
||
left: 'left',
|
||
textStyle: {
|
||
fontSize: 16,
|
||
},
|
||
},
|
||
|
||
tooltip: {
|
||
trigger: 'item',
|
||
formatter: '{b}: {c}',
|
||
},
|
||
grid: {
|
||
left: '10%',
|
||
right: '10%',
|
||
top: '10%',
|
||
bottom: '10%',
|
||
},
|
||
series: [
|
||
// CPU 用户
|
||
{
|
||
type: 'liquidFill',
|
||
name: this.$t('home.user'),
|
||
radius: '85%',
|
||
center: ['25%', '55%'],
|
||
amplitude: 10,
|
||
backgroundStyle: {
|
||
borderWidth: 1,
|
||
color: 'rgba(246, 65, 108,0.1)',
|
||
},
|
||
itemStyle: {
|
||
shadowColor: 'rgba(0, 0, 0, 0)',
|
||
},
|
||
|
||
color: [
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{ offset: 1, color: '#FFF6B7' },
|
||
{ offset: 0, color: '#fa9eb3' },
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#FFD3A5',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#FFD3A5',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#feada6',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#f5efef',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
],
|
||
data: [
|
||
{
|
||
value: (this.server.cpu.used / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.user'),
|
||
},
|
||
{
|
||
value: (this.server.cpu.used / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.user'),
|
||
direction: 'left',
|
||
},
|
||
{
|
||
value: (this.server.cpu.used / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.user'),
|
||
},
|
||
],
|
||
label: {
|
||
normal: {
|
||
formatter: (value) => {
|
||
return (value.value * 100).toFixed(0) + '%';
|
||
},
|
||
textStyle: {
|
||
fontSize: 20,
|
||
color: '#333',
|
||
},
|
||
},
|
||
},
|
||
outline: {
|
||
show: true,
|
||
itemStyle: {
|
||
borderWidth: 0,
|
||
},
|
||
borderDistance: 0,
|
||
},
|
||
},
|
||
// CPU 系统
|
||
{
|
||
type: 'liquidFill',
|
||
name: this.$t('home.system'),
|
||
radius: '85%',
|
||
center: ['50%', '55%'],
|
||
amplitude: 10,
|
||
backgroundStyle: {
|
||
borderWidth: 1,
|
||
color: 'rgba(201,219,252, 0.5)',
|
||
},
|
||
itemStyle: {
|
||
shadowColor: 'rgba(0, 0, 0, 0)',
|
||
},
|
||
color: [
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{ offset: 1, color: '#3C8CE7' },
|
||
{ offset: 0, color: '#00EAFF' },
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#e0c3fc',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#8ec5fc',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#accbee',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#e7f0fd',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
],
|
||
|
||
data: [
|
||
{
|
||
value: (this.server.cpu.sys / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.system'),
|
||
},
|
||
{
|
||
value: (this.server.cpu.sys / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.system'),
|
||
direction: 'left',
|
||
},
|
||
{
|
||
value: (this.server.cpu.sys / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.system'),
|
||
},
|
||
],
|
||
label: {
|
||
normal: {
|
||
formatter: (value) => {
|
||
return (value.value * 100).toFixed(0) + '%';
|
||
},
|
||
textStyle: {
|
||
fontSize: 20,
|
||
color: '#333',
|
||
},
|
||
},
|
||
},
|
||
outline: {
|
||
show: true,
|
||
itemStyle: {
|
||
borderWidth: 0,
|
||
},
|
||
borderDistance: 0,
|
||
},
|
||
},
|
||
// CPU 空闲
|
||
{
|
||
type: 'liquidFill',
|
||
name: this.$t('home.free'),
|
||
radius: '85%',
|
||
center: ['75%', '55%'],
|
||
amplitude: 10,
|
||
backgroundStyle: {
|
||
borderWidth: 1,
|
||
color: 'rgba(216, 218, 62, 0.1)',
|
||
},
|
||
itemStyle: {
|
||
shadowColor: 'rgba(0, 0, 0, 0)',
|
||
},
|
||
color: [
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#c4f4fe',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#fdefbe',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#FFFEFF',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#D7FFFE',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#abecd6',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#fbed96',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
],
|
||
|
||
data: [
|
||
{
|
||
value: (this.server.cpu.free / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.free'),
|
||
},
|
||
{
|
||
value: (this.server.cpu.free / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.free'),
|
||
direction: 'left',
|
||
},
|
||
{
|
||
value: (this.server.cpu.free / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)).toFixed(2),
|
||
name: this.$t('home.free'),
|
||
},
|
||
],
|
||
label: {
|
||
normal: {
|
||
formatter: (value) => {
|
||
return (value.value * 100).toFixed(0) + '%';
|
||
},
|
||
textStyle: {
|
||
fontSize: 20,
|
||
color: '#333',
|
||
},
|
||
},
|
||
},
|
||
outline: {
|
||
show: true,
|
||
itemStyle: {
|
||
borderWidth: 0,
|
||
},
|
||
borderDistance: 0,
|
||
},
|
||
},
|
||
],
|
||
legend: {
|
||
orient: 'vertical',
|
||
right: 20,
|
||
data: [this.$t('home.user'), this.$t('home.system'), this.$t('home.free')],
|
||
textStyle: {
|
||
color: '#333',
|
||
fontSize: 14,
|
||
},
|
||
},
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
},
|
||
drawPieMemery() {
|
||
// 基于准备好的dom,初始化echarts实例
|
||
let myChart = this.$echarts.init(this.$refs.pieMemery);
|
||
var option;
|
||
|
||
// 水球图
|
||
var value = this.server.mem.used / 10;
|
||
|
||
option = {
|
||
backgroundColor: '#fff',
|
||
title: [
|
||
{
|
||
text: this.$t('home.memory'),
|
||
left: 'left',
|
||
textStyle: {
|
||
fontSize: 16,
|
||
},
|
||
},
|
||
{
|
||
text: '剩余:' + this.server.mem.free + 'G',
|
||
left: '50%',
|
||
top: '55%',
|
||
textAlign: 'center',
|
||
textStyle: {
|
||
fontSize: '13',
|
||
fontWeight: '400',
|
||
color: '#fff',
|
||
|
||
textAlign: 'center',
|
||
},
|
||
},
|
||
{
|
||
text: '已用:' + this.server.mem.used + 'G',
|
||
left: '50%',
|
||
top: '67%',
|
||
textAlign: 'center',
|
||
textStyle: {
|
||
fontSize: '13',
|
||
fontWeight: '400',
|
||
color: '#fff',
|
||
|
||
textAlign: 'center',
|
||
},
|
||
},
|
||
],
|
||
tooltip: {
|
||
trigger: 'item',
|
||
formatter: (value) => {
|
||
return '已使用:' + value.value.toFixed(2);
|
||
},
|
||
},
|
||
legend: {
|
||
orient: 'vertical',
|
||
left: 'right',
|
||
},
|
||
series: [
|
||
{
|
||
type: 'liquidFill',
|
||
radius: '85%',
|
||
z: 6,
|
||
center: ['50%', '55%'],
|
||
amplitude: 10,
|
||
backgroundStyle: {
|
||
borderWidth: 1,
|
||
color: 'rgba(201,219,252, 0.5)', // 球体
|
||
},
|
||
itemStyle: {
|
||
shadowColor: 'rgba(0, 0, 0, 0)',
|
||
},
|
||
color: [
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#fff1eb',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#ace0f9',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#3C8CE7',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#00EAFF',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#e0c3fc',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#8ec5fc',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
],
|
||
data: [
|
||
{
|
||
value: value,
|
||
name: '已使用',
|
||
},
|
||
|
||
{
|
||
value: value,
|
||
direction: 'left',
|
||
name: '已使用',
|
||
},
|
||
{
|
||
value: value,
|
||
name: '已使用',
|
||
},
|
||
],
|
||
label: {
|
||
normal: {
|
||
formatter: (value) => {
|
||
return (value.value * 100).toFixed(0) + '%';
|
||
},
|
||
position: ['53.3%', '40%'],
|
||
textStyle: {
|
||
fontSize: 21,
|
||
color: '#233d7d',
|
||
},
|
||
},
|
||
},
|
||
outline: {
|
||
show: true,
|
||
itemStyle: {
|
||
borderWidth: 0,
|
||
},
|
||
borderDistance: 0,
|
||
},
|
||
},
|
||
],
|
||
};
|
||
option && myChart.setOption(option);
|
||
},
|
||
drawPieDisk() {
|
||
// 基于准备好的dom,初始化echarts实例
|
||
let myChart = this.$echarts.init(this.$refs.pieDisk);
|
||
var option;
|
||
let one = this.server.sysFiles[0].used.replace('GB', '');
|
||
let two = this.server.sysFiles[0].free.replace('GB', '');
|
||
let values = parseFloat(one) / (parseFloat(one) + parseFloat(two));
|
||
// option = {
|
||
// title: {
|
||
// text: this.$t('home.disk'),
|
||
// left: 'left',
|
||
// textStyle: {
|
||
// fontSize: 16,
|
||
// },
|
||
// },
|
||
// tooltip: {
|
||
// trigger: 'item',
|
||
// },
|
||
// legend: {
|
||
// orient: 'vertical',
|
||
// left: 'right',
|
||
// },
|
||
// color: ['#F56C6C', '#DDD'],
|
||
// series: [
|
||
// {
|
||
// name: this.$t('home.diskStatus'),
|
||
// type: 'pie',
|
||
// radius: '55%',
|
||
// label: {
|
||
// show: false,
|
||
// },
|
||
// labelLine: {
|
||
// normal: {
|
||
// position: 'inner',
|
||
// show: false,
|
||
// },
|
||
// },
|
||
// data: [
|
||
// {
|
||
// value: one,
|
||
// name: this.$t('home.used'),
|
||
// },
|
||
// {
|
||
// value: two,
|
||
// name: this.$t('home.available'),
|
||
// },
|
||
// ],
|
||
// },
|
||
// ],
|
||
// };
|
||
// 水球图
|
||
var value = values;
|
||
|
||
option = {
|
||
backgroundColor: '#fff',
|
||
title: [
|
||
{
|
||
text: this.$t('home.disk'),
|
||
left: 'left',
|
||
textStyle: {
|
||
fontSize: 16,
|
||
},
|
||
},
|
||
{
|
||
text: '剩余:' + two + 'G',
|
||
left: '50%',
|
||
top: '55%',
|
||
textAlign: 'center',
|
||
textStyle: {
|
||
fontSize: '13',
|
||
fontWeight: '400',
|
||
color: '#fff',
|
||
|
||
textAlign: 'center',
|
||
},
|
||
},
|
||
{
|
||
text: '已用:' + one + 'G',
|
||
left: '50%',
|
||
top: '67%',
|
||
textAlign: 'center',
|
||
textStyle: {
|
||
fontSize: '13',
|
||
fontWeight: '400',
|
||
color: '#fff',
|
||
|
||
textAlign: 'center',
|
||
},
|
||
},
|
||
],
|
||
tooltip: {
|
||
trigger: 'item',
|
||
formatter: (value) => {
|
||
return '已使用:' + value.value.toFixed(2);
|
||
},
|
||
},
|
||
legend: {
|
||
orient: 'vertical',
|
||
left: 'right',
|
||
},
|
||
series: [
|
||
{
|
||
type: 'liquidFill',
|
||
radius: '85%',
|
||
z: 6,
|
||
center: ['50%', '55%'],
|
||
amplitude: 10,
|
||
backgroundStyle: {
|
||
borderWidth: 1,
|
||
color: 'rgba(245, 239, 239,0.5)', // 球体
|
||
},
|
||
itemStyle: {
|
||
shadowColor: 'rgba(0, 0, 0, 0)',
|
||
},
|
||
color: [
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#feada6',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#feada6',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#FFF6B7',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#FFF6B7',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
{
|
||
type: 'linear',
|
||
x: 0,
|
||
y: 0,
|
||
x2: 0,
|
||
y2: 1,
|
||
colorStops: [
|
||
{
|
||
offset: 1,
|
||
color: '#ff9a9e',
|
||
},
|
||
{
|
||
offset: 0,
|
||
color: '#fecfef',
|
||
},
|
||
],
|
||
globalCoord: false,
|
||
},
|
||
],
|
||
data: [
|
||
{
|
||
value: value,
|
||
name: '已使用',
|
||
},
|
||
|
||
{
|
||
value: value,
|
||
direction: 'left',
|
||
name: '已使用',
|
||
},
|
||
{
|
||
value: value,
|
||
name: '已使用',
|
||
},
|
||
],
|
||
label: {
|
||
normal: {
|
||
formatter: (value) => {
|
||
return (value.value * 100).toFixed(0) + '%';
|
||
},
|
||
position: ['53.3%', '40%'],
|
||
textStyle: {
|
||
fontSize: 21,
|
||
color: '#73545c',
|
||
},
|
||
},
|
||
},
|
||
outline: {
|
||
show: true,
|
||
itemStyle: {
|
||
borderWidth: 0,
|
||
borderColor: '#ff9a9e',
|
||
},
|
||
borderDistance: 0,
|
||
},
|
||
},
|
||
],
|
||
};
|
||
|
||
option && myChart.setOption(option);
|
||
},
|
||
// 折线图的初始化
|
||
drawLine() {
|
||
let myChart = this.$echarts.init(this.$refs.line);
|
||
var option;
|
||
option = {
|
||
title: {
|
||
text: this.$t('views.index.394840-16'),
|
||
left: 'left',
|
||
textStyle: {
|
||
fontSize: 19,
|
||
},
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
},
|
||
legend: {
|
||
orient: 'vertical',
|
||
left: 'right',
|
||
},
|
||
xAxis: [
|
||
{
|
||
type: 'category',
|
||
data: this.linechart.date,
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#999',
|
||
},
|
||
},
|
||
},
|
||
],
|
||
yAxis: [
|
||
{
|
||
type: 'value',
|
||
splitNumber: 4,
|
||
splitLine: {
|
||
lineStyle: {
|
||
type: 'dashed',
|
||
color: '#DDD',
|
||
},
|
||
},
|
||
axisLine: {
|
||
show: false,
|
||
lineStyle: {
|
||
color: '#333',
|
||
},
|
||
},
|
||
nameTextStyle: {
|
||
color: '#999',
|
||
},
|
||
splitArea: {
|
||
show: false,
|
||
},
|
||
},
|
||
],
|
||
series: [
|
||
{
|
||
name: this.$t('views.index.394840-16'),
|
||
type: 'line',
|
||
data: this.linechart.counts,
|
||
radius: '55%',
|
||
|
||
lineStyle: {
|
||
normal: {
|
||
width: 8,
|
||
color: {
|
||
type: 'linear',
|
||
colorStops: [
|
||
{
|
||
offset: 0,
|
||
color: '#A9F387', // 0% 处的颜色
|
||
},
|
||
{
|
||
offset: 1,
|
||
color: '#48D8BF', // 100% 处的颜色
|
||
},
|
||
],
|
||
globalCoord: false, // 缺省为 false
|
||
},
|
||
shadowColor: 'rgba(72,216,191, 0.3)',
|
||
shadowBlur: 10,
|
||
shadowOffsetY: 20,
|
||
},
|
||
},
|
||
itemStyle: {
|
||
normal: {
|
||
color: 'rgba(72,216,191, 0.3)',
|
||
borderWidth: 10,
|
||
/*shadowColor: 'rgba(72,216,191, 0.3)',
|
||
shadowBlur: 100,*/
|
||
borderColor: '#A9F387',
|
||
},
|
||
},
|
||
smooth: true,
|
||
},
|
||
],
|
||
};
|
||
option && myChart.setOption(option);
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
// 天气
|
||
$primary-gradient-start: #a1c4fd;
|
||
$primary-gradient-end: #c2e9fb;
|
||
$secondary-color: #ffffff;
|
||
$icon-color: #ffffff;
|
||
$shadow-color: rgba(0, 0, 0, 0.1);
|
||
$hover-shadow-color: rgba(0, 0, 0, 0.2);
|
||
$aqi-good-color: #4caf50;
|
||
$aqi-moderate-color: #ffeb3b;
|
||
$aqi-unhealthy-color: #f44336;
|
||
|
||
.weather-card {
|
||
height: 420px;
|
||
background: linear-gradient(135deg, var(--background-start) 0%, var(--background-end) 100%);
|
||
border-radius: 15px;
|
||
padding: 16px;
|
||
color: $secondary-color;
|
||
box-shadow: 0 4px 20px $shadow-color;
|
||
transition:
|
||
transform 0.3s,
|
||
box-shadow 0.3s;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 8px 30px $hover-shadow-color;
|
||
}
|
||
|
||
.weather-header {
|
||
text-align: center;
|
||
margin-bottom: 10px;
|
||
|
||
h2 {
|
||
margin: 0;
|
||
font-size: 26px;
|
||
font-weight: bold;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
color: $secondary-color;
|
||
}
|
||
|
||
.date-week {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 10px;
|
||
font-size: 14px;
|
||
color: rgba($secondary-color, 0.8);
|
||
margin-top: 5px;
|
||
}
|
||
|
||
.weather-description {
|
||
margin-top: 5px;
|
||
font-size: 16px;
|
||
color: rgba($secondary-color, 0.9);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
}
|
||
|
||
.weather-main {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
margin-bottom: 10px;
|
||
|
||
.weather-icon {
|
||
width: 100px; // 增大图标尺寸
|
||
height: 100px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.temperature {
|
||
font-size: 23px; // 增大温度字体
|
||
font-weight: bold;
|
||
color: $secondary-color;
|
||
margin-left: 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
}
|
||
|
||
.weather-details {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
margin-top: 10px;
|
||
|
||
.detail-item {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 14px;
|
||
color: $secondary-color;
|
||
|
||
i {
|
||
font-size: 18px;
|
||
margin-right: 5px;
|
||
color: $icon-color;
|
||
}
|
||
|
||
.detail-text {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
}
|
||
}
|
||
|
||
.air-quality {
|
||
margin-top: 15px;
|
||
padding: 10px 15px;
|
||
background-color: rgba($secondary-color, 0.15);
|
||
border-radius: 8px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
|
||
.aqi-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
|
||
.aqi-value {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
padding: 5px 10px;
|
||
border-radius: 5px;
|
||
color: #fff;
|
||
background-color: inherit; // 继承父元素的背景色
|
||
}
|
||
|
||
&.aqi-good {
|
||
background-color: $aqi-good-color;
|
||
}
|
||
|
||
&.aqi-moderate {
|
||
background-color: $aqi-moderate-color;
|
||
}
|
||
|
||
&.aqi-unhealthy {
|
||
background-color: $aqi-unhealthy-color;
|
||
}
|
||
|
||
.aqi-level {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
color: rgba($secondary-color, 0.9);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 天气提示 */
|
||
.weather-tip {
|
||
margin-top: 15px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
background-color: rgba($secondary-color, 0.2);
|
||
padding: 10px 15px;
|
||
border-radius: 10px;
|
||
color: $secondary-color;
|
||
|
||
i {
|
||
font-size: 18px;
|
||
margin-right: 10px;
|
||
color: $icon-color;
|
||
}
|
||
|
||
span {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.weather-card {
|
||
padding: 15px;
|
||
|
||
.weather-header {
|
||
h2 {
|
||
font-size: 22px;
|
||
}
|
||
|
||
.date-week {
|
||
font-size: 12px;
|
||
}
|
||
|
||
.weather-description {
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
|
||
.weather-main {
|
||
flex-direction: column;
|
||
|
||
.temperature {
|
||
margin-left: 0;
|
||
margin-top: 10px;
|
||
font-size: 22px;
|
||
}
|
||
|
||
.weather-icon {
|
||
width: 80px;
|
||
height: 80px;
|
||
}
|
||
}
|
||
|
||
.weather-details {
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.air-quality {
|
||
padding: 8px 12px;
|
||
|
||
.aqi-info {
|
||
flex-direction: row;
|
||
gap: 8px;
|
||
|
||
.aqi-value {
|
||
font-size: 16px;
|
||
padding: 4px 8px;
|
||
}
|
||
|
||
.aqi-level {
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.weather-tip {
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//天气完
|
||
// 设备数据统计显示
|
||
.card-panel {
|
||
height: 200px;
|
||
border-radius: 35px;
|
||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||
padding: 20px;
|
||
transition:
|
||
transform 0.3s ease,
|
||
box-shadow 0.3s ease;
|
||
|
||
/* 悬停效果,增加交互性 */
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
|
||
}
|
||
.device {
|
||
.card-panel-icon {
|
||
fill: #a7de87;
|
||
}
|
||
.card-icon {
|
||
&:hover .card-panel-icon {
|
||
fill: #007aff;
|
||
}
|
||
}
|
||
.card-data {
|
||
.card-panel-num {
|
||
color: #a7de87;
|
||
}
|
||
}
|
||
}
|
||
.product {
|
||
.card-panel-icon {
|
||
fill: #f3728c;
|
||
}
|
||
.card-icon {
|
||
&:hover .card-panel-icon {
|
||
fill: #007aff;
|
||
}
|
||
}
|
||
.card-data {
|
||
.card-panel-num {
|
||
color: #f3728c;
|
||
}
|
||
}
|
||
}
|
||
.function {
|
||
.card-panel-icon {
|
||
fill: #ffc766;
|
||
}
|
||
.card-icon {
|
||
&:hover .card-panel-icon {
|
||
fill: #007aff;
|
||
}
|
||
}
|
||
.card-data {
|
||
.card-panel-num {
|
||
color: #ffc766;
|
||
}
|
||
}
|
||
}
|
||
.monitor {
|
||
.card-panel-icon {
|
||
fill: #66c9ff;
|
||
}
|
||
.card-icon {
|
||
&:hover .card-panel-icon {
|
||
fill: #007aff;
|
||
}
|
||
}
|
||
.card-data {
|
||
.card-panel-num {
|
||
color: #66c9ff;
|
||
}
|
||
}
|
||
}
|
||
.alert {
|
||
.card-panel-icon {
|
||
fill: #a076ef;
|
||
}
|
||
.card-icon {
|
||
&:hover .card-panel-icon {
|
||
fill: #007aff;
|
||
}
|
||
}
|
||
.card-data {
|
||
.card-panel-num {
|
||
color: #a076ef;
|
||
}
|
||
}
|
||
}
|
||
.reports {
|
||
.card-panel-icon {
|
||
fill: #5dd5d1;
|
||
}
|
||
.card-icon {
|
||
&:hover .card-panel-icon {
|
||
fill: #007aff;
|
||
}
|
||
}
|
||
.card-data {
|
||
.card-panel-num {
|
||
color: #5dd5d1;
|
||
}
|
||
}
|
||
}
|
||
|
||
.card-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 100%;
|
||
|
||
.card-icon {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: 55px;
|
||
height: 55px;
|
||
margin-bottom: 15px;
|
||
background-color: rgba(#ffffff, 0.65);
|
||
padding: 10px;
|
||
border-radius: 10px;
|
||
|
||
/* 图标样式 */
|
||
.card-panel-icon {
|
||
width: 80%;
|
||
height: 80%;
|
||
transition: fill 0.3s ease;
|
||
}
|
||
|
||
/* 悬停时图标颜色变化 */
|
||
}
|
||
|
||
/* 数据区域 */
|
||
.card-data {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
|
||
/* 标题样式 */
|
||
.card-title {
|
||
font-size: 1.05rem;
|
||
color: #4d4d4d;
|
||
margin-bottom: 10px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 1px;
|
||
font-weight: 600;
|
||
white-space: nowrap; /* 防止文本换行 */
|
||
overflow: hidden; /* 超出部分隐藏 */
|
||
text-overflow: ellipsis; /* 使用省略号表示超出部分 */
|
||
}
|
||
|
||
/* 数字样式 */
|
||
.card-panel-num {
|
||
font-size: 1.5rem;
|
||
|
||
font-weight: bold;
|
||
position: relative;
|
||
animation: countAnimation 3s ease-out forwards;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 响应式设计,当屏幕宽度小于768px时 */
|
||
@media (max-width: 768px) {
|
||
height: 150px; /* 减小卡片高度 */
|
||
padding: 15px; /* 减小内边距 */
|
||
|
||
.card-content {
|
||
.card-icon {
|
||
width: 40px;
|
||
height: 40px;
|
||
margin-bottom: 10px;
|
||
|
||
.card-panel-icon {
|
||
width: 80%;
|
||
height: 80%;
|
||
}
|
||
}
|
||
|
||
.card-data {
|
||
.card-title {
|
||
font-size: 1rem;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.card-panel-num {
|
||
font-size: 1.5rem;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 数字递增动画关键帧 */
|
||
@keyframes countAnimation {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(-10px);
|
||
}
|
||
50% {
|
||
opacity: 1;
|
||
transform: translateY(5px);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
//数据完
|
||
// 折线图卡片
|
||
.line-card {
|
||
height: 420px;
|
||
border-radius: 15px;
|
||
padding: 16px;
|
||
color: $secondary-color;
|
||
box-shadow: 0 4px 20px $shadow-color;
|
||
transition:
|
||
transform 0.3s,
|
||
box-shadow 0.3s;
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 8px 30px $hover-shadow-color;
|
||
}
|
||
}
|
||
|
||
// 折线图完
|
||
// 地图
|
||
.map-card {
|
||
background: #ffffff; /* 使用纯色背景,增加清新感 */
|
||
border-radius: 15px; /* 略微减小圆角 */
|
||
overflow: hidden;
|
||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); /* 更柔和的阴影 */
|
||
transition:
|
||
transform 0.3s ease,
|
||
box-shadow 0.3s ease;
|
||
height: 500px;
|
||
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
.card-header {
|
||
height: 30px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-bottom: 1px dashed #e0e0e0;
|
||
|
||
.card-title {
|
||
margin: 0;
|
||
color: #333333;
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
i {
|
||
margin-right: 8px;
|
||
color: #409eff; /* 主题色图标 */
|
||
font-size: 20px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.map-container {
|
||
width: 100%;
|
||
height: 500px; /* 减少高度 */
|
||
position: relative;
|
||
border-radius: 15px;
|
||
overflow: hidden;
|
||
|
||
.map {
|
||
width: 100%;
|
||
height: 100%;
|
||
/* 可根据需要添加地图相关样式 */
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.map-card {
|
||
padding: 12px;
|
||
}
|
||
|
||
.card-header {
|
||
padding: 18px 12px;
|
||
|
||
.card-title {
|
||
font-size: 16px;
|
||
|
||
i {
|
||
font-size: 18px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.map-container {
|
||
height: 250px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.map-card {
|
||
padding: 10px;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
.card-header {
|
||
padding: 15px 10px;
|
||
|
||
.card-title {
|
||
font-size: 14px;
|
||
|
||
i {
|
||
font-size: 16px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.map-container {
|
||
height: 200px;
|
||
}
|
||
}
|
||
// 地图完
|
||
// 信息栏
|
||
.message-card {
|
||
height: 240px;
|
||
margin-bottom: 20px;
|
||
border-radius: 15px;
|
||
box-shadow: 0 4px 20px $shadow-color;
|
||
transition:
|
||
transform 0.3s,
|
||
box-shadow 0.3s;
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 8px 30px $hover-shadow-color;
|
||
}
|
||
}
|
||
// 柱状图
|
||
.card-container {
|
||
height: 240px;
|
||
width: 100%;
|
||
padding: 16px;
|
||
background: #ffffff;
|
||
border-radius: 15px;
|
||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
|
||
overflow: hidden;
|
||
transition:
|
||
transform 0.3s ease,
|
||
box-shadow 0.3s ease;
|
||
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
|
||
}
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.card-container {
|
||
.card {
|
||
flex-direction: column;
|
||
height: auto;
|
||
|
||
.card-image {
|
||
width: 100%;
|
||
|
||
height: auto;
|
||
}
|
||
|
||
.card-content {
|
||
width: 100%;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.card-container {
|
||
.card {
|
||
.card-content {
|
||
padding: 10px;
|
||
|
||
.author {
|
||
font-size: 1em;
|
||
}
|
||
|
||
.content {
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
.footer {
|
||
font-size: 0.8em;
|
||
}
|
||
}
|
||
|
||
.card-image {
|
||
.overlay .thumb {
|
||
width: 40px;
|
||
height: 40px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 书摘完
|
||
// 使用率
|
||
.rate {
|
||
border-radius: 15px;
|
||
padding: 16px;
|
||
color: $secondary-color;
|
||
box-shadow: 0 4px 20px $shadow-color;
|
||
transition:
|
||
transform 0.3s,
|
||
box-shadow 0.3s;
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 8px 30px $hover-shadow-color;
|
||
}
|
||
.pieCpu {
|
||
height: 161px;
|
||
}
|
||
@media (max-width: 768px) {
|
||
height: 100%;
|
||
}
|
||
}
|
||
// 使用率完
|
||
.phone-card {
|
||
border-radius: 15px;
|
||
box-shadow: 0 4px 20px $shadow-color;
|
||
transition:
|
||
transform 0.3s,
|
||
box-shadow 0.3s;
|
||
&:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 8px 30px $hover-shadow-color;
|
||
}
|
||
}
|
||
.phone {
|
||
height: 729px;
|
||
width: 370px;
|
||
background-image: url('../assets/images/phone.png');
|
||
background-size: cover;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.phone-container {
|
||
height: 618px;
|
||
width: 343px;
|
||
position: relative;
|
||
top: 46px;
|
||
left: 12px;
|
||
background-color: #fff;
|
||
}
|
||
|
||
.content {
|
||
line-height: 24px;
|
||
padding: 10px;
|
||
border: 1px solid #eee;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
.description {
|
||
font-size: 12px;
|
||
|
||
tr {
|
||
line-height: 20px;
|
||
}
|
||
}
|
||
.notice-bar {
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
.animating {
|
||
animation: scroll 10s linear infinite;
|
||
}
|
||
</style>
|