2521 lines
97 KiB
Vue
2521 lines
97 KiB
Vue
|
<template>
|
|||
|
<div class="home-page-container">
|
|||
|
<!-- 设备统计信息以及天气 -->
|
|||
|
<el-row :gutter="20" class="statistics-container">
|
|||
|
<!-- 设备统计 -->
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="16" :xl="16">
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="8" class="statistics-item">
|
|||
|
<!-- 设备数量 -->
|
|||
|
<div class="card-panel">
|
|||
|
<div class="card-content device">
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="12">
|
|||
|
<div class="card-icon">
|
|||
|
<svg-icon icon-class="device" class-name="card-panel-icon" />
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="12">
|
|||
|
<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>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="8" class="statistics-item">
|
|||
|
<!-- 产品数量 -->
|
|||
|
<div class="card-panel">
|
|||
|
<div class="card-content product">
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="12">
|
|||
|
<div class="card-icon">
|
|||
|
<svg-icon icon-class="model" class-name="card-panel-icon" />
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="12">
|
|||
|
<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>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="8" class="statistics-item">
|
|||
|
<!-- 操作记录 -->
|
|||
|
<div class="card-panel">
|
|||
|
<div class="card-content function">
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="12">
|
|||
|
<div class="card-icon">
|
|||
|
<svg-icon icon-class="log-a" class-name="card-panel-icon" />
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="12">
|
|||
|
<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>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="8">
|
|||
|
<!-- 监测数据 -->
|
|||
|
<div class="card-panel">
|
|||
|
<div class="card-content monitor">
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="12">
|
|||
|
<div class="card-icon">
|
|||
|
<svg-icon icon-class="monitor-a" class-name="card-panel-icon" />
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="12">
|
|||
|
<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>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="8">
|
|||
|
<!-- 告警数量 -->
|
|||
|
<div class="card-panel">
|
|||
|
<div class="card-content alert">
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="12">
|
|||
|
<div class="card-icon">
|
|||
|
<svg-icon icon-class="alert" class-name="card-panel-icon" />
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="12">
|
|||
|
<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>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="8">
|
|||
|
<!-- 上报事件 -->
|
|||
|
<div class="card-panel">
|
|||
|
<div class="card-content reports">
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="12">
|
|||
|
<div class="card-icon">
|
|||
|
<svg-icon icon-class="event-a" class-name="card-panel-icon" />
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="12">
|
|||
|
<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>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</el-col>
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
|
|||
|
<!-- 天气 -->
|
|||
|
<el-card
|
|||
|
class="weather-card"
|
|||
|
shadow="hover"
|
|||
|
:style="{
|
|||
|
'--background-start': getBackgroundColor(weatherData.data.type).start,
|
|||
|
'--background-end': getBackgroundColor(weatherData.data.type).end,
|
|||
|
}"
|
|||
|
>
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :span="10">
|
|||
|
<div class="weather-main">
|
|||
|
<img :src="weatherData.data.typeIcon" alt="天气图标" class="weather-icon" />
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="14">
|
|||
|
<!-- 头部:城市名称、日期与星期 -->
|
|||
|
<div class="weather-header">
|
|||
|
<h2>{{ weatherData.city }}</h2>
|
|||
|
<div class="date-week">
|
|||
|
<span>{{ weatherData.data.date }}</span>
|
|||
|
|
|||
|
<span>{{ weatherData.data.week }}</span>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<el-row :gutter="10" style="margin-top: 10px">
|
|||
|
<el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
|
|||
|
<div class="low-temperature">{{ weatherData.data.low }}</div>
|
|||
|
</el-col>
|
|||
|
<el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
|
|||
|
<!-- 温度 -->
|
|||
|
<div class="high-temperature">/ {{ weatherData.data.high }}</div>
|
|||
|
<p class="weather-description">{{ weatherData.data.type }}</p>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
<!-- 详情信息:风向、风力 -->
|
|||
|
<el-row :gutter="10">
|
|||
|
<div class="weather-details">
|
|||
|
<el-col :span="12">
|
|||
|
<div class="detail-item">
|
|||
|
<svg-icon icon-class="wind_direction" />
|
|||
|
<span class="detail-text">{{ weatherData.data.fengxiang }}</span>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :span="12">
|
|||
|
<div class="detail-item">
|
|||
|
<svg-icon icon-class="wind_speed" />
|
|||
|
<span class="detail-text">{{ weatherData.data.fengli }}</span>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
</div>
|
|||
|
</el-row>
|
|||
|
|
|||
|
<!-- 空气质量信息 -->
|
|||
|
<!-- <div class="air-quality">
|
|||
|
<div class="aqi-info">
|
|||
|
<span class="aqi-level" :class="aqiClass">{{ weatherData.air.aqi }}</span>
|
|||
|
<span class="aqi-value" :class="aqiClass">{{ $t('views.index.394840-18') }}</span>
|
|||
|
<span class="aqi-level">{{ weatherData.air.aqi_name }}</span>
|
|||
|
</div>
|
|||
|
</div> -->
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</el-card>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
|
|||
|
<!-- 地图 -->
|
|||
|
<el-row :gutter="20" class="statistics-container">
|
|||
|
<!-- 地图 -->
|
|||
|
<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>
|
|||
|
<!-- cpu使用率 -->
|
|||
|
<el-card class="rate" shadow="hover" style="margin: 20px 0px">
|
|||
|
<div v-if="isAdmin">
|
|||
|
<div style="">
|
|||
|
<div class="chart-title">{{ $t('home.usage') }}</div>
|
|||
|
<el-row>
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
|||
|
<div ref="pieCpu" class="pieCpu"></div>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
<el-row :gutter="20">
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
|||
|
<div style="">
|
|||
|
<div class="chart-title">{{ $t('home.memoryRate') }}</div>
|
|||
|
<div ref="pieMemery" class="pieMemery"></div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
|||
|
<div style="">
|
|||
|
<div class="chart-title">{{ $t('home.disk') }}</div>
|
|||
|
<div ref="pieDisk" class="pieDisk"></div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</div>
|
|||
|
<div v-else>
|
|||
|
<el-empty style="height: 500px" :description="$t('dataCenter.analysis.349202-7')"></el-empty>
|
|||
|
</div>
|
|||
|
</el-card>
|
|||
|
</el-col>
|
|||
|
<!-- 折线图 -->
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
|
|||
|
<!-- 信息栏 -->
|
|||
|
<el-card shadow="hover" class="message-card">
|
|||
|
<div class="message-title">{{ $t('home.information') }}</div>
|
|||
|
<div class="notice-bar" :class="{ animating: animate }" v-if="noticeList.length > 0">
|
|||
|
<div class="item-wrap" @click="openDetail(item.noticeId)" v-for="item in noticeList" :key="item.noticeId">
|
|||
|
<div class="left-wrap">
|
|||
|
<el-tag size="mini" effect="dark" type="warning" v-if="item.noticeType == 2">{{ $t('home.announcement') }}</el-tag>
|
|||
|
<el-tag size="mini" effect="dark" v-else>{{ $t('home.message') }}</el-tag>
|
|||
|
<span style="margin-left: 8px">{{ item.noticeTitle }}</span>
|
|||
|
</div>
|
|||
|
<div class="right-wrap">
|
|||
|
{{ parseTime(item.createTime, '{y}-{m}-{d}') }}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div v-else>
|
|||
|
<el-empty style="height: 400px" :description="$t('dataCenter.analysis.349202-7')"></el-empty>
|
|||
|
</div>
|
|||
|
</el-card>
|
|||
|
<!-- </div> -->
|
|||
|
<div class="">
|
|||
|
<!-- 登录用户数量 -->
|
|||
|
<el-card class="line-card" shadow="hover">
|
|||
|
<div ref="lineChart" style="height: 300px; width: 100%; margin: 0 10px 24px 0" v-if="isAdmin && linechart.counts"></div>
|
|||
|
<div v-else class="message-title" style="margin: 0px 0 10px">
|
|||
|
{{ $t('views.index.394840-16') }}
|
|||
|
<el-empty style="height: 250px" :description="$t('dataCenter.analysis.349202-7')"></el-empty>
|
|||
|
</div>
|
|||
|
</el-card>
|
|||
|
</div>
|
|||
|
<div class="">
|
|||
|
<!-- mqtt状态数据 -->
|
|||
|
<el-card class="card-container" shadow="hover">
|
|||
|
<div class="">
|
|||
|
<div ref="statsChart" style="height: 300px"></div>
|
|||
|
</div>
|
|||
|
</el-card>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
|
|||
|
<!-- h5手机显示页面 -->
|
|||
|
<!-- <el-card shadow="hover" style="margin: -20px 10px 20px 10px" class="phone-card">
|
|||
|
<el-row :gutter="40">
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" style="padding: 10px">
|
|||
|
<div style="padding: 30px; margin: 20px 0; font-size: 14px">
|
|||
|
<div style="margin-bottom: 20px; font-family: PingFangSC, PingFang SC; font-weight: 600; font-size: 35px; color: #303133; line-height: 49px; text-align: left; font-style: normal">
|
|||
|
{{ $t('views.index.394840-0') }}
|
|||
|
</div>
|
|||
|
<div style="display: table; font-size: 14px; margin-bottom: 10px">
|
|||
|
<div style="display: table-cell; line-height: 22px">
|
|||
|
<b style="margin-right: 10px; font-family: PingFangSC, PingFang SC; font-weight: 500; font-size: 13px; color: #67c23a; line-height: 18px; text-align: left; font-style: normal">
|
|||
|
{{ $t('views.index.394840-1') }}
|
|||
|
</b>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div style="margin-bottom: 10px">
|
|||
|
<div style="width: 70px; font-weight: bold; display: table-cell; padding: 5px 0">{{ $t('views.index.394840-2') }}</div>
|
|||
|
<div style="line-height: 22px">{{ $t('views.index.394840-3') }}</div>
|
|||
|
</div>
|
|||
|
<div style="margin: 10px 0">
|
|||
|
<div style="width: 70px; font-weight: bold; display: table-cell; padding: 5px 0">{{ $t('views.index.394840-4') }}</div>
|
|||
|
<div style="line-height: 22px">
|
|||
|
{{ $t('views.index.394840-5') }}
|
|||
|
<br />
|
|||
|
<el-link target="_blank" href="https://fastbee.cn/doc/pages/sponsor">{{ $t('views.index.394840-6') }}</el-link>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div style="padding: 70px 30px 0 20px; font-size: 14px">
|
|||
|
<div style="float: left; width: 200px">
|
|||
|
<el-image style="width: 180px" :src="require('@/assets/images/code.jpg')"></el-image>
|
|||
|
</div>
|
|||
|
<div style="float: left">
|
|||
|
<div class="mini-program">{{ $t('views.index.394840-7') }}</div>
|
|||
|
<div style="display: table; margin-bottom: 5px">
|
|||
|
<div class="web-site">{{ $t('views.index.394840-9') }}</div>
|
|||
|
<div class="other-site">
|
|||
|
<el-link target="_blank" href="https://fastbee.cn/">www.fastbee.cn</el-link>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div style="display: table; margin-bottom: 5px">
|
|||
|
<div class="web-site">{{ $t('views.index.394840-10') }}</div>
|
|||
|
<div class="other-site">
|
|||
|
<el-link target="_blank" href="https://fastbee.cn/doc">www.fastbee.cn/doc</el-link>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div style="display: table; margin: 5px 0">
|
|||
|
<div class="web-site">{{ $t('views.index.394840-11') }}</div>
|
|||
|
<div class="other-site">
|
|||
|
<span>QQ 164770707</span>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div style="display: table; margin-bottom: 10px">
|
|||
|
<div class="web-site">{{ $t('views.index.394840-12') }}</div>
|
|||
|
<div class="other-site">
|
|||
|
<el-link target="_blank" href="https://gitee.com/kerwincui/wumei-smart" style="font-size: 12px">{{ $t('views.index.394840-13') }}</el-link>
|
|||
|
<el-link target="_blank" href="https://github.com/kerwincui/fastbee" style="margin-left: 20px; font-size: 12px">{{ $t('views.index.394840-14') }}</el-link>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" style="padding: 30px">
|
|||
|
<div class="phone">
|
|||
|
<iframe src="https://iot.fastbee.cn/h5" id="iframe" frameborder="0" scrolling="auto" class="phone-container"></iframe>
|
|||
|
<div class="frame-remark">{{ $t('views.index.394840-8') }}</div>
|
|||
|
</div>
|
|||
|
</el-col>
|
|||
|
</el-row>
|
|||
|
</el-card> -->
|
|||
|
|
|||
|
<!--通知公告详情 -->
|
|||
|
<el-dialog :title="notice.noticeTitle" :visible.sync="open" width="800px" append-to-body>
|
|||
|
<div style="margin-top: -20px; margin-bottom: 10px">
|
|||
|
<el-tag size="mini" effect="dark" type="warning" v-if="notice.noticeType == 2">{{ $t('home.announcement') }}</el-tag>
|
|||
|
<el-tag size="mini" effect="dark" v-else>{{ $t('home.message') }}</el-tag>
|
|||
|
<span style="margin-left: 20px">{{ notice.createTime }}</span>
|
|||
|
</div>
|
|||
|
<div v-loading="loading" class="content">
|
|||
|
<div v-html="notice.noticeContent"></div>
|
|||
|
</div>
|
|||
|
<div slot="footer" class="dialog-footer">
|
|||
|
<el-button type="primary" @click="closeDetail">{{ $t('home.close') }}</el-button>
|
|||
|
</div>
|
|||
|
</el-dialog>
|
|||
|
|
|||
|
<!-- <div class="footer-container">
|
|||
|
<span>
|
|||
|
Copyright © 2021-2025
|
|||
|
<a href="https://fastbee.cn/" target="_blank">FastBee</a>
|
|||
|
|
|
|||
|
<a href="https://fastbee.cn/" target="_blank">{{ $t('views.index.394840-15') }}</a>
|
|||
|
| Apache License
|
|||
|
</span>
|
|||
|
<br />
|
|||
|
<span>
|
|||
|
{{ $t('views.index.394840-17') }}
|
|||
|
<a href="https://fastbee.cn/doc/" target="_blank">https://fastbee.cn/doc/</a>
|
|||
|
</span>
|
|||
|
</div> -->
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import axios from 'axios';
|
|||
|
import moment from 'moment';
|
|||
|
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 * as echarts from 'echarts';
|
|||
|
import { searchUserCount } from '@/api/monitor/jobLog';
|
|||
|
import { getNettyMqttStats, statisticNettyMqtt } from '@/api/iot/netty';
|
|||
|
|
|||
|
export default {
|
|||
|
name: 'Index',
|
|||
|
components: {
|
|||
|
CountTo,
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
//天气信息
|
|||
|
weatherData: {
|
|||
|
success: true,
|
|||
|
city: '---',
|
|||
|
data: {
|
|||
|
date: '---',
|
|||
|
week: '--',
|
|||
|
type: '-',
|
|||
|
typeIcon: require('../../src/assets/icons/qing.png'),
|
|||
|
low: '-°C',
|
|||
|
high: '-°C',
|
|||
|
fengxiang: '---',
|
|||
|
fengli: '--',
|
|||
|
},
|
|||
|
air: {
|
|||
|
aqi: 85,
|
|||
|
aqi_level: 2,
|
|||
|
aqi_name: '良',
|
|||
|
},
|
|||
|
},
|
|||
|
radius: ['55%', '75%'], // 默认半径
|
|||
|
labelFontSize: '24', // 默认圆环内字体大小
|
|||
|
// 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, // 公告间隔时间(单位:毫秒)
|
|||
|
mapChart: null, //地图
|
|||
|
mqttChart: null, // mqtt统计图(为了解决图表切换屏幕后显示问题)
|
|||
|
pieCpuChart: null, //cpu使用率图
|
|||
|
rateChart: null,
|
|||
|
sysChart: null,
|
|||
|
loginUserChart: null,
|
|||
|
// 服务器信息
|
|||
|
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();
|
|||
|
// this.getLocation(); //获取位置信息
|
|||
|
this.$nextTick(() => {
|
|||
|
this.drawPieCpu();
|
|||
|
// 监听窗口大小变化以重新渲染饼图
|
|||
|
window.addEventListener('resize', this.handleResize);
|
|||
|
});
|
|||
|
},
|
|||
|
beforeDestroy() {
|
|||
|
this.stopScroll();
|
|||
|
// 清除监听器
|
|||
|
window.removeEventListener('resize', this.handleResize);
|
|||
|
},
|
|||
|
created() {
|
|||
|
this.init();
|
|||
|
this.getAllDevice(); //获取设备数据
|
|||
|
this.getNoticeList(); //获取公告列表
|
|||
|
this.getDeviceStatistic(); //获取设备统计信息
|
|||
|
this.getMqttStats(); //获取mqtt统计信息
|
|||
|
this.statisticMqtt(); //mqtt统计数据
|
|||
|
},
|
|||
|
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);
|
|||
|
});
|
|||
|
this.drawLine();
|
|||
|
});
|
|||
|
},
|
|||
|
// 检测屏幕宽度并更新 radius
|
|||
|
updateRadius() {
|
|||
|
const isMobile = window.matchMedia('(max-width: 430px)').matches;
|
|||
|
this.radius = isMobile ? ['35%', '45%'] : ['55%', '75%'];
|
|||
|
this.labelFontSize = isMobile ? '16' : '28';
|
|||
|
this.drawPieCpu(); // 更新图表以应用新半径
|
|||
|
},
|
|||
|
// mqtt统计数据
|
|||
|
statisticMqtt() {
|
|||
|
statisticNettyMqtt().then((response) => {
|
|||
|
this.static = response.data;
|
|||
|
});
|
|||
|
},
|
|||
|
/** 查询mqtt状态数据*/
|
|||
|
getMqttStats() {
|
|||
|
getNettyMqttStats().then((response) => {
|
|||
|
this.stats = response.data;
|
|||
|
console.log(this.stats);
|
|||
|
this.drawStats();
|
|||
|
});
|
|||
|
},
|
|||
|
// 绘制柱状图Mqtt状态数据
|
|||
|
drawStats() {
|
|||
|
// 基于准备好的dom,初始化echarts实例
|
|||
|
this.mqttChart = this.$echarts.init(this.$refs.statsChart);
|
|||
|
var option;
|
|||
|
option = {
|
|||
|
title: {
|
|||
|
text: this.$t('views.index.394840-19'), //Mqtt状态数据
|
|||
|
textStyle: {
|
|||
|
ontFamily: 'PingFangSC, PingFang SC',
|
|||
|
lineHeight: 22,
|
|||
|
fontWeight: 600,
|
|||
|
fontSize: 16,
|
|||
|
color: '#303133',
|
|||
|
fontStyle: 'normal',
|
|||
|
textAlign: 'left',
|
|||
|
},
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
trigger: 'axis',
|
|||
|
axisPointer: {
|
|||
|
type: 'shadow',
|
|||
|
},
|
|||
|
},
|
|||
|
legend: {
|
|||
|
data: [this.$t('netty.mqtt.564432-18'), this.$t('netty.mqtt.564432-19')],
|
|||
|
right: '15',
|
|||
|
icon: 'rect',
|
|||
|
itemWidth: 10,
|
|||
|
itemHeight: 10,
|
|||
|
borderRadius: 20,
|
|||
|
textStyle: {
|
|||
|
color: 'rgba(0,0,0,0.65)',
|
|||
|
},
|
|||
|
},
|
|||
|
grid: {
|
|||
|
left: '3%',
|
|||
|
right: '4%',
|
|||
|
bottom: '3%',
|
|||
|
containLabel: true,
|
|||
|
},
|
|||
|
xAxis: {
|
|||
|
type: 'value',
|
|||
|
boundaryGap: [0, 0.01],
|
|||
|
splitLine: {
|
|||
|
show: true,
|
|||
|
lineStyle: {
|
|||
|
type: 'dashed',
|
|||
|
},
|
|||
|
},
|
|||
|
splitNumber: 3, // 分割线
|
|||
|
},
|
|||
|
yAxis: {
|
|||
|
type: 'category',
|
|||
|
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'),
|
|||
|
color: '#0bb9ff',
|
|||
|
type: 'bar',
|
|||
|
data: [this.stats['connection_count'], this.stats['session_count'], this.stats['subscription_count'], this.stats['retain_count'], this.stats['retain_count']],
|
|||
|
},
|
|||
|
{
|
|||
|
name: this.$t('netty.mqtt.564432-19'),
|
|||
|
color: '#4a6ff8',
|
|||
|
type: 'bar',
|
|||
|
data: [this.stats['connection_total'], this.stats['session_total'], this.stats['subscription_total'], this.stats['retain_total'], this.stats['retain_total']],
|
|||
|
},
|
|||
|
],
|
|||
|
};
|
|||
|
option && this.mqttChart.setOption(option);
|
|||
|
},
|
|||
|
// 天气
|
|||
|
getLocation() {
|
|||
|
const geolocation = new BMap.Geolocation();
|
|||
|
geolocation.getCurrentPosition(
|
|||
|
async (r) => {
|
|||
|
const { latitude, longitude } = r;
|
|||
|
await this.fetchWeather1(latitude, longitude);
|
|||
|
},
|
|||
|
(err) => {
|
|||
|
console.log('bai-loc-err', err);
|
|||
|
}
|
|||
|
);
|
|||
|
},
|
|||
|
async fetchWeather1(lat, lon) {
|
|||
|
this.isLoading = true;
|
|||
|
this.error = null;
|
|||
|
const key = process.env.VUE_APP_XIN_ZHI_KEY; // 心知天气API密钥
|
|||
|
const url = `https://api.seniverse.com/v3/weather/daily.json?key=${key}&location=${lat}:${lon}&language=zh-Hans&unit=c`;
|
|||
|
try {
|
|||
|
const response = await axios.get(url);
|
|||
|
const weather = response.data.results[0];
|
|||
|
if (response.data) {
|
|||
|
this.weatherData = {
|
|||
|
success: true,
|
|||
|
city: weather.location.name,
|
|||
|
data: {
|
|||
|
date: weather.daily[0].date,
|
|||
|
week: '',
|
|||
|
type: weather.daily[0].text_day,
|
|||
|
typeIcon: this.getTypeIcon(weather.daily[0].text_day),
|
|||
|
low: weather.daily[0].low + '°C',
|
|||
|
high: weather.daily[0].high + '°C',
|
|||
|
fengxiang: weather.daily[0].wind_direction,
|
|||
|
fengli: weather.daily[0].wind_speed + ' 级',
|
|||
|
night: {
|
|||
|
type: weather.daily[0].text_night,
|
|||
|
fengxiang: weather.daily[0].wind_direction,
|
|||
|
fengli: weather.daily[0].wind_speed,
|
|||
|
},
|
|||
|
},
|
|||
|
air: {
|
|||
|
aqi: 85,
|
|||
|
aqi_level: 2,
|
|||
|
aqi_name: '良',
|
|||
|
},
|
|||
|
};
|
|||
|
const background = this.getBackgroundColor(weather.daily[0].text_day);
|
|||
|
document.documentElement.style.setProperty('--background-start', background.start);
|
|||
|
document.documentElement.style.setProperty('--background-end', background.end);
|
|||
|
} else {
|
|||
|
this.error = '获取天气数据失败,请稍后重试。';
|
|||
|
}
|
|||
|
} catch (err) {
|
|||
|
console.log(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', // 柔和的灰色
|
|||
|
},
|
|||
|
阵雨: {
|
|||
|
start: '#D8F0FF', // 非常柔和的浅蓝色(水滴感)
|
|||
|
end: '#C2C2C2', // 柔和的灰色
|
|||
|
},
|
|||
|
};
|
|||
|
return backgrounds[type] || { start: '#FFF0C1', 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'),
|
|||
|
阵雨: require('../../src/assets/icons/xiaoyu.png'),
|
|||
|
// 添加更多天气类型和对应图标
|
|||
|
};
|
|||
|
return icons[type] || require('../../src/assets/icons/qing.png');
|
|||
|
},
|
|||
|
init() {
|
|||
|
if (this.$store.state.user.roles.includes('admin') || this.$store.state.user.roles.includes('manager') || this.$store.state.user.dept.userName === 'fastbee') {
|
|||
|
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(); // 获取地图
|
|||
|
this.getLocation(); // 获取位置
|
|||
|
});
|
|||
|
});
|
|||
|
},
|
|||
|
/** 查询服务器信息 */
|
|||
|
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() {
|
|||
|
this.mapChart = this.$echarts.init(this.$refs.map);
|
|||
|
var option;
|
|||
|
// 单击事件
|
|||
|
this.mapChart.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: 'Fastbee open source iot platform',
|
|||
|
sublink: 'https://iot.fastbee.cn',
|
|||
|
target: '_blank',
|
|||
|
textStyle: {
|
|||
|
color: '#303133',
|
|||
|
textBorderColor: '#fff',
|
|||
|
textBorderWidth: 10,
|
|||
|
fontSize: 16,
|
|||
|
},
|
|||
|
top: 10,
|
|||
|
left: 'center',
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
trigger: 'item',
|
|||
|
formatter: function (params) {
|
|||
|
var htmlStr = '<div style="padding:5px;line-height:28px;">';
|
|||
|
htmlStr += "设备名称: <span style='color:#486FF2'>" + 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: [105, 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 && this.mapChart.setOption(option);
|
|||
|
},
|
|||
|
handleResize() {
|
|||
|
// 在大小变化时重新渲染图表
|
|||
|
if (this.mapChart) {
|
|||
|
this.mapChart.resize();
|
|||
|
}
|
|||
|
if (this.pieCpuChart) {
|
|||
|
this.pieCpuChart.resize();
|
|||
|
this.updateRadius();
|
|||
|
}
|
|||
|
if (this.rateChart) {
|
|||
|
this.rateChart.resize();
|
|||
|
}
|
|||
|
if (this.sysChart) {
|
|||
|
this.sysChart.resize();
|
|||
|
}
|
|||
|
if (this.loginUserChart) {
|
|||
|
this.loginUserChart.resize();
|
|||
|
}
|
|||
|
if (this.mqttChart) {
|
|||
|
this.mqttChart.resize();
|
|||
|
}
|
|||
|
},
|
|||
|
// cpu使用率
|
|||
|
drawPieCpu() {
|
|||
|
this.pieCpuChart = this.$echarts.init(this.$refs.pieCpu);
|
|||
|
// 基于准备好的dom,初始化echarts实例
|
|||
|
var option;
|
|||
|
let userd = ((this.server.cpu.used / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)) * 100).toFixed(0);
|
|||
|
let sys = ((this.server.cpu.sys / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)) * 100).toFixed(0);
|
|||
|
let free = ((this.server.cpu.free / (this.server.cpu.used + this.server.cpu.sys + this.server.cpu.free)) * 100).toFixed(0);
|
|||
|
|
|||
|
option = {
|
|||
|
title: {
|
|||
|
text: '',
|
|||
|
left: 'center',
|
|||
|
top: '20px',
|
|||
|
textStyle: {
|
|||
|
fontSize: 18,
|
|||
|
color: '#333',
|
|||
|
},
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
clockWise: false,
|
|||
|
startAngle: 90,
|
|||
|
radius: this.radius,
|
|||
|
center: ['15%', '50%'],
|
|||
|
data: [100],
|
|||
|
itemStyle: {
|
|||
|
color: '#eee',
|
|||
|
},
|
|||
|
animation: false,
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
labelLine: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
radius: this.radius,
|
|||
|
center: ['15%', '50%'],
|
|||
|
itemStyle: {
|
|||
|
color: '#000',
|
|||
|
},
|
|||
|
data: [
|
|||
|
{
|
|||
|
value: userd,
|
|||
|
label: {
|
|||
|
normal: {
|
|||
|
formatter: `{label|${userd}%}`,
|
|||
|
position: 'center',
|
|||
|
show: true,
|
|||
|
textStyle: {
|
|||
|
fontSize: '20',
|
|||
|
fontWeight: 'bold',
|
|||
|
color: '#eee',
|
|||
|
lineHeight: 20,
|
|||
|
rich: {
|
|||
|
label: {
|
|||
|
fontFamily: ' Roboto, Roboto',
|
|||
|
textAlign: 'center',
|
|||
|
fontStyle: 'normal',
|
|||
|
fontSize: this.labelFontSize,
|
|||
|
fontWeight: 'bold',
|
|||
|
color: '#303133',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
// 渐变色
|
|||
|
color: new echarts.graphic.LinearGradient(
|
|||
|
0,
|
|||
|
0,
|
|||
|
0,
|
|||
|
1,
|
|||
|
[
|
|||
|
{
|
|||
|
offset: 0,
|
|||
|
color: '#4474ec',
|
|||
|
},
|
|||
|
{
|
|||
|
offset: 1,
|
|||
|
color: '#92b3fa',
|
|||
|
},
|
|||
|
],
|
|||
|
false
|
|||
|
),
|
|||
|
borderRadius: ['50%', '50%'],
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
value: 100 - userd,
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
color: 'transparent',
|
|||
|
borderCap: 'round',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
clockWise: false,
|
|||
|
startAngle: 90,
|
|||
|
radius: this.radius,
|
|||
|
center: ['48%', '50%'],
|
|||
|
data: [100],
|
|||
|
itemStyle: {
|
|||
|
color: '#eee',
|
|||
|
},
|
|||
|
animation: false,
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
labelLine: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
radius: this.radius,
|
|||
|
center: ['48%', '50%'],
|
|||
|
itemStyle: {
|
|||
|
color: '#000',
|
|||
|
},
|
|||
|
data: [
|
|||
|
{
|
|||
|
value: sys,
|
|||
|
label: {
|
|||
|
normal: {
|
|||
|
formatter: `{label|${sys}%}`,
|
|||
|
position: 'center',
|
|||
|
show: true,
|
|||
|
textStyle: {
|
|||
|
fontSize: '20',
|
|||
|
fontWeight: 'bold',
|
|||
|
color: '#eee',
|
|||
|
lineHeight: 20,
|
|||
|
rich: {
|
|||
|
label: {
|
|||
|
fontFamily: ' Roboto, Roboto',
|
|||
|
textAlign: 'center',
|
|||
|
fontStyle: 'normal',
|
|||
|
fontSize: this.labelFontSize,
|
|||
|
fontWeight: 'bold',
|
|||
|
color: '#303133',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
color: new echarts.graphic.LinearGradient(
|
|||
|
0,
|
|||
|
0,
|
|||
|
1,
|
|||
|
0,
|
|||
|
[
|
|||
|
{
|
|||
|
offset: 0,
|
|||
|
color: '#10bcff',
|
|||
|
},
|
|||
|
{
|
|||
|
offset: 1,
|
|||
|
color: '#81e1fd',
|
|||
|
},
|
|||
|
],
|
|||
|
false
|
|||
|
),
|
|||
|
borderRadius: ['50%', '50%'],
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
value: 100 - sys,
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
color: 'transparent',
|
|||
|
borderCap: 'round',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
clockWise: false,
|
|||
|
startAngle: 90,
|
|||
|
radius: this.radius,
|
|||
|
center: ['78%', '50%'],
|
|||
|
data: [100],
|
|||
|
itemStyle: {
|
|||
|
color: '#eee',
|
|||
|
},
|
|||
|
animation: false,
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
labelLine: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
radius: this.radius,
|
|||
|
center: ['78%', '50%'],
|
|||
|
data: [
|
|||
|
{
|
|||
|
value: free,
|
|||
|
label: {
|
|||
|
normal: {
|
|||
|
formatter: `{label|${free}%}`,
|
|||
|
position: 'center',
|
|||
|
show: true,
|
|||
|
textStyle: {
|
|||
|
fontSize: '20',
|
|||
|
fontWeight: 'bold',
|
|||
|
color: '#eee',
|
|||
|
lineHeight: 20,
|
|||
|
rich: {
|
|||
|
label: {
|
|||
|
fontFamily: ' Roboto, Roboto',
|
|||
|
textAlign: 'center',
|
|||
|
fontStyle: 'normal',
|
|||
|
fontSize: this.labelFontSize,
|
|||
|
fontWeight: 'bold',
|
|||
|
color: '#303133',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|||
|
{ offset: 0, color: '#17bcb8' }, // 渐变色
|
|||
|
{ offset: 1, color: '#75e2dc' },
|
|||
|
]),
|
|||
|
borderRadius: ['50%', '50%'],
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
value: 100 - free,
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
color: 'transparent',
|
|||
|
borderCap: 'round',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
},
|
|||
|
],
|
|||
|
graphic: [
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
left: 10, // 第一个图的名称位置
|
|||
|
top: '15%', // 第一个图的名称位置
|
|||
|
style: {
|
|||
|
text: '用户',
|
|||
|
font: ' 400 12px PingFangSC, PingFang SC',
|
|||
|
fill: '#606266',
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
left: '30%',
|
|||
|
top: '15%',
|
|||
|
style: {
|
|||
|
text: '系统',
|
|||
|
font: ' 400 12px PingFangSC, PingFang SC',
|
|||
|
fill: '#606266',
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'text',
|
|||
|
left: '60%',
|
|||
|
top: '15%',
|
|||
|
style: {
|
|||
|
text: '空闲',
|
|||
|
font: ' 400 12px PingFangSC, PingFang SC',
|
|||
|
fill: '#606266',
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
};
|
|||
|
option && this.pieCpuChart.setOption(option);
|
|||
|
},
|
|||
|
// 内存使用率
|
|||
|
drawPieMemery() {
|
|||
|
// 初始化echarts实例
|
|||
|
this.rateChart = this.$echarts.init(this.$refs.pieMemery);
|
|||
|
var option;
|
|||
|
var value = this.server.mem.used / (this.server.mem.used + this.server.mem.free);
|
|||
|
option = {
|
|||
|
title: [
|
|||
|
{
|
|||
|
text: (value * 100).toFixed(0) + '%',
|
|||
|
x: 'center',
|
|||
|
y: '35%',
|
|||
|
textStyle: {
|
|||
|
fontFamily: ' Roboto, Roboto',
|
|||
|
fontWeight: 'bold',
|
|||
|
fontStyle: 'normal',
|
|||
|
fontSize: 24,
|
|||
|
lineHeight: 28,
|
|||
|
color: '#303133',
|
|||
|
alignment: 'center',
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
text: `已用:{a|${this.server.mem.used}}GB\n剩余:{a|${this.server.mem.free}} GB`,
|
|||
|
x: 'center',
|
|||
|
y: '50%',
|
|||
|
borderColor: '#fff',
|
|||
|
textStyle: {
|
|||
|
fontWeight: 'normal',
|
|||
|
fontSize: 12,
|
|||
|
color: '#444',
|
|||
|
rich: {
|
|||
|
a: {
|
|||
|
fontFamily: 'PingFangSC, PingFang SC',
|
|||
|
fontStyle: 'normal',
|
|||
|
textAlign: 'center',
|
|||
|
fontWeight: '400',
|
|||
|
fontSize: 12,
|
|||
|
lineHeight: 17,
|
|||
|
color: '#606266',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
polar: {
|
|||
|
center: ['50%', '50%'],
|
|||
|
radius: ['65%', '90%'],
|
|||
|
},
|
|||
|
angleAxis: {
|
|||
|
max: 100,
|
|||
|
show: false,
|
|||
|
},
|
|||
|
radiusAxis: {
|
|||
|
type: 'category',
|
|||
|
show: true,
|
|||
|
axisLabel: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
axisLine: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
axisTick: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
data: [
|
|||
|
{
|
|||
|
value: (this.server.mem.used / (this.server.mem.used + this.server.mem.free)) * 100,
|
|||
|
name: '已使用',
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|||
|
{ offset: 0, color: '#887BF2' }, // 渐变色
|
|||
|
{ offset: 1, color: '#BDB2FA' },
|
|||
|
]),
|
|||
|
borderRadius: ['50%', '50%'],
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
name: '',
|
|||
|
type: 'bar',
|
|||
|
roundCap: true,
|
|||
|
showBackground: true,
|
|||
|
backgroundStyle: {
|
|||
|
color: '#eaeaf4',
|
|||
|
},
|
|||
|
coordinateSystem: 'polar',
|
|||
|
},
|
|||
|
],
|
|||
|
};
|
|||
|
option && this.rateChart.setOption(option);
|
|||
|
},
|
|||
|
//系统盘使用率
|
|||
|
drawPieDisk() {
|
|||
|
// 基于准备好的dom,初始化echarts实例
|
|||
|
this.sysChart = 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));
|
|||
|
var value = values;
|
|||
|
option = {
|
|||
|
title: [
|
|||
|
{
|
|||
|
text: (value * 100).toFixed(0) + '%',
|
|||
|
x: 'center',
|
|||
|
y: '35%',
|
|||
|
textStyle: {
|
|||
|
fontFamily: ' Roboto, Roboto',
|
|||
|
fontWeight: 'bold',
|
|||
|
fontStyle: 'normal',
|
|||
|
fontSize: 24,
|
|||
|
lineHeight: 28,
|
|||
|
color: '#303133',
|
|||
|
alignment: 'center',
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
text: `{a|已用:${one}}GB\n{a|剩余:${two}} GB`,
|
|||
|
x: 'center',
|
|||
|
y: '50%',
|
|||
|
borderColor: '#fff',
|
|||
|
textStyle: {
|
|||
|
fontWeight: 'normal',
|
|||
|
fontSize: 12,
|
|||
|
color: '#444',
|
|||
|
rich: {
|
|||
|
a: {
|
|||
|
fontFamily: 'PingFangSC, PingFang SC',
|
|||
|
fontStyle: 'normal',
|
|||
|
textAlign: 'center',
|
|||
|
fontWeight: '400',
|
|||
|
fontSize: 12,
|
|||
|
lineHeight: 17,
|
|||
|
color: '#606266',
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
polar: {
|
|||
|
center: ['50%', '50%'],
|
|||
|
radius: ['65%', '90%'],
|
|||
|
},
|
|||
|
angleAxis: {
|
|||
|
max: 100,
|
|||
|
show: false,
|
|||
|
},
|
|||
|
radiusAxis: {
|
|||
|
type: 'category',
|
|||
|
show: true,
|
|||
|
axisLabel: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
axisLine: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
axisTick: {
|
|||
|
show: false,
|
|||
|
},
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
data: [
|
|||
|
{
|
|||
|
value: value * 100,
|
|||
|
name: '已使用',
|
|||
|
itemStyle: {
|
|||
|
normal: {
|
|||
|
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|||
|
{ offset: 0, color: '#F286D8' }, // 渐变色
|
|||
|
{ offset: 1, color: '#FFC3F1' },
|
|||
|
]),
|
|||
|
borderRadius: ['50%', '50%'],
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
name: '',
|
|||
|
type: 'bar',
|
|||
|
roundCap: true,
|
|||
|
showBackground: true,
|
|||
|
backgroundStyle: {
|
|||
|
color: '#eaeaf4',
|
|||
|
},
|
|||
|
coordinateSystem: 'polar',
|
|||
|
},
|
|||
|
],
|
|||
|
};
|
|||
|
option && this.sysChart.setOption(option);
|
|||
|
},
|
|||
|
// 登录用户数量折线图的初始化
|
|||
|
drawLine() {
|
|||
|
this.loginUserChart = this.$echarts.init(this.$refs.lineChart);
|
|||
|
var option;
|
|||
|
option = {
|
|||
|
title: {
|
|||
|
text: this.$t('views.index.394840-16'),
|
|||
|
textStyle: {
|
|||
|
fontFamily: 'PingFangSC, PingFang SC',
|
|||
|
lineHeight: 22,
|
|||
|
fontWeight: 600,
|
|||
|
fontSize: 16,
|
|||
|
color: '#303133',
|
|||
|
fontStyle: 'normal',
|
|||
|
textAlign: 'left',
|
|||
|
},
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
trigger: 'axis',
|
|||
|
},
|
|||
|
xAxis: {
|
|||
|
type: 'category',
|
|||
|
boundaryGap: false,
|
|||
|
data: this.linechart.date,
|
|||
|
axisLabel: {
|
|||
|
formatter: function (value) {
|
|||
|
return moment(value).format('YYYY.MM.DD');
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
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'),
|
|||
|
data: this.linechart.counts,
|
|||
|
radius: '55%',
|
|||
|
type: 'line',
|
|||
|
smooth: true, // 设置为平滑折线
|
|||
|
showSymbol: false,
|
|||
|
lineStyle: {
|
|||
|
width: 3,
|
|||
|
color: '#8095d8', // 折线颜色为蓝色
|
|||
|
},
|
|||
|
areaStyle: {
|
|||
|
// 创建从蓝色渐变到白色的效果
|
|||
|
color: {
|
|||
|
type: 'linear',
|
|||
|
x: 0,
|
|||
|
y: 1,
|
|||
|
x2: 0,
|
|||
|
y2: 0,
|
|||
|
colorStops: [
|
|||
|
{
|
|||
|
offset: 0,
|
|||
|
color: 'rgba(96, 116, 208, 0)', // 深蓝色
|
|||
|
},
|
|||
|
{
|
|||
|
offset: 1,
|
|||
|
color: 'rgba(70, 130, 180, 0.3)', // 透明白色
|
|||
|
},
|
|||
|
],
|
|||
|
global: false, // 不使用全局渐变
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
};
|
|||
|
option && this.loginUserChart.setOption(option);
|
|||
|
},
|
|||
|
},
|
|||
|
};
|
|||
|
</script>
|
|||
|
|
|||
|
<style lang="scss" scoped>
|
|||
|
.home-page-container {
|
|||
|
padding: 10px;
|
|||
|
.statistics-container {
|
|||
|
margin: 10px 0px 20px !important;
|
|||
|
.statistics-item {
|
|||
|
margin-bottom: 10px;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 设备数据统计显示
|
|||
|
.card-panel {
|
|||
|
height: 98px;
|
|||
|
border-radius: 8px;
|
|||
|
background: #fff;
|
|||
|
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1);
|
|||
|
padding: 24px;
|
|||
|
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: #08bdff;
|
|||
|
}
|
|||
|
.card-icon {
|
|||
|
background-color: #e5f8ff;
|
|||
|
&:hover .card-panel-icon {
|
|||
|
fill: #007aff;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
.product {
|
|||
|
.card-panel-icon {
|
|||
|
fill: #f385d9;
|
|||
|
}
|
|||
|
.card-icon {
|
|||
|
background-color: #ffeef8;
|
|||
|
&:hover .card-panel-icon {
|
|||
|
fill: #007aff;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
.function {
|
|||
|
.card-panel-icon {
|
|||
|
fill: #feaf31;
|
|||
|
}
|
|||
|
.card-icon {
|
|||
|
background-color: #fdf0d7;
|
|||
|
&:hover .card-panel-icon {
|
|||
|
fill: #007aff;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
.monitor {
|
|||
|
.card-panel-icon {
|
|||
|
fill: #1cbdb5;
|
|||
|
}
|
|||
|
|
|||
|
.card-icon {
|
|||
|
background-color: #dbf9f7;
|
|||
|
&:hover .card-panel-icon {
|
|||
|
fill: #007aff;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
.alert {
|
|||
|
.card-panel-icon {
|
|||
|
fill: #f66b6c;
|
|||
|
}
|
|||
|
.card-icon {
|
|||
|
background-color: #ffe8e8;
|
|||
|
&:hover .card-panel-icon {
|
|||
|
fill: #007aff;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
.reports {
|
|||
|
.card-panel-icon {
|
|||
|
fill: #a076ef;
|
|||
|
}
|
|||
|
.card-icon {
|
|||
|
background-color: #eae8fe;
|
|||
|
&:hover .card-panel-icon {
|
|||
|
fill: #007aff;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.card-content {
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
justify-content: flex-start;
|
|||
|
align-items: flex-start;
|
|||
|
height: 100%;
|
|||
|
|
|||
|
.card-icon {
|
|||
|
display: flex;
|
|||
|
justify-content: center;
|
|||
|
align-items: center;
|
|||
|
width: 48px;
|
|||
|
height: 48px;
|
|||
|
margin-bottom: 15px;
|
|||
|
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: left;
|
|||
|
float: left;
|
|||
|
margin-left: -10px;
|
|||
|
|
|||
|
/* 标题样式 */
|
|||
|
.card-title {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 400;
|
|||
|
font-size: 13px;
|
|||
|
color: #606266;
|
|||
|
line-height: 18px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
|
|||
|
/* 数字样式 */
|
|||
|
.card-panel-num {
|
|||
|
width: 14px;
|
|||
|
height: 28px;
|
|||
|
font-size: 24px;
|
|||
|
font-weight: 700;
|
|||
|
text-align: left;
|
|||
|
margin-top: 2px;
|
|||
|
font-family: Roboto, Roboto;
|
|||
|
font-weight: bold;
|
|||
|
color: #303133;
|
|||
|
line-height: 28px;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 响应式设计,当屏幕宽度小于968px时 */
|
|||
|
@media screen and (max-width: 968px) {
|
|||
|
height: 100px; /* 减小卡片高度 */
|
|||
|
padding: 10px; /* 减小内边距 */
|
|||
|
margin-bottom: 10px;
|
|||
|
.card-content {
|
|||
|
.card-icon {
|
|||
|
width: 40px;
|
|||
|
height: 40px;
|
|||
|
margin: 20px 0;
|
|||
|
}
|
|||
|
|
|||
|
.card-data {
|
|||
|
.card-title {
|
|||
|
font-size: 12px;
|
|||
|
margin-top: 20px;
|
|||
|
}
|
|||
|
|
|||
|
.card-panel-num {
|
|||
|
margin-bottom: 10px;
|
|||
|
font-size: 10px;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/* 响应式设计,当屏幕宽度小于1920px时 */
|
|||
|
@media screen and (min-width: 1920px) {
|
|||
|
height: 125px;
|
|||
|
padding: 10px;
|
|||
|
margin-bottom: 10px;
|
|||
|
.card-content {
|
|||
|
.card-icon {
|
|||
|
width: 60px;
|
|||
|
height: 60px;
|
|||
|
margin: 20px;
|
|||
|
}
|
|||
|
|
|||
|
.card-data {
|
|||
|
.card-title {
|
|||
|
font-size: 22px;
|
|||
|
margin: 30px 0 5px 10px;
|
|||
|
}
|
|||
|
|
|||
|
.card-panel-num {
|
|||
|
margin: 0px 0 5px 10px;
|
|||
|
|
|||
|
font-size: 22px;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
@media (max-width: 1180px) {
|
|||
|
margin-bottom: 15px;
|
|||
|
}
|
|||
|
|
|||
|
/* 数字递增动画关键帧 */
|
|||
|
@keyframes countAnimation {
|
|||
|
0% {
|
|||
|
opacity: 0;
|
|||
|
transform: translateY(-10px);
|
|||
|
}
|
|||
|
50% {
|
|||
|
opacity: 1;
|
|||
|
transform: translateY(5px);
|
|||
|
}
|
|||
|
100% {
|
|||
|
opacity: 1;
|
|||
|
transform: translateY(0);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//数据完
|
|||
|
// 天气
|
|||
|
$primary-gradient-start: #a1c4fd;
|
|||
|
$primary-gradient-end: #c2e9fb;
|
|||
|
$secondary-color: #000;
|
|||
|
$icon-color: #000;
|
|||
|
$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: 208px;
|
|||
|
background: linear-gradient(135deg, var(--background-start) 0%, var(--background-end) 100%);
|
|||
|
border-radius: 10px;
|
|||
|
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;
|
|||
|
|
|||
|
.weather-header {
|
|||
|
text-align: left;
|
|||
|
margin-bottom: 10px;
|
|||
|
|
|||
|
h2 {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 600;
|
|||
|
font-size: 18px;
|
|||
|
color: #303133;
|
|||
|
line-height: 10px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
|
|||
|
.date-week {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 400;
|
|||
|
font-size: 13px;
|
|||
|
color: #606266;
|
|||
|
line-height: 18px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
}
|
|||
|
@media screen and (min-width: 1920px) {
|
|||
|
height: 270px;
|
|||
|
padding: 10px;
|
|||
|
margin-bottom: 10px;
|
|||
|
}
|
|||
|
|
|||
|
.weather-main {
|
|||
|
//天气图标
|
|||
|
display: flex;
|
|||
|
justify-content: center;
|
|||
|
align-items: center;
|
|||
|
margin: 30px 0;
|
|||
|
|
|||
|
.weather-icon {
|
|||
|
width: 100px; // 增大图标尺寸
|
|||
|
height: 100px;
|
|||
|
flex-shrink: 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.weather-details {
|
|||
|
.detail-item {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
gap: 2px;
|
|||
|
color: #606266;
|
|||
|
|
|||
|
.detail-text {
|
|||
|
font-weight: 500;
|
|||
|
font-size: 12px;
|
|||
|
line-height: 18px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.air-quality {
|
|||
|
margin-top: 15px;
|
|||
|
padding: 5px 10px;
|
|||
|
display: flex;
|
|||
|
justify-content: center;
|
|||
|
align-items: center;
|
|||
|
width: 140px;
|
|||
|
height: 22px;
|
|||
|
border-radius: 2px;
|
|||
|
border: 1px solid #67c23a;
|
|||
|
|
|||
|
.aqi-info {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
gap: 10px;
|
|||
|
width: 105px;
|
|||
|
height: 18px;
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 400;
|
|||
|
font-size: 13px;
|
|||
|
color: #67c23a;
|
|||
|
line-height: 18px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
|
|||
|
.aqi-value {
|
|||
|
font-size: 12px;
|
|||
|
font-weight: bold;
|
|||
|
padding: 5px;
|
|||
|
border-radius: 5px;
|
|||
|
color: #4caf50;
|
|||
|
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: 12px;
|
|||
|
font-weight: bold;
|
|||
|
color: #4caf50;
|
|||
|
background-color: inherit; // 继承父元素的背景色
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//温度
|
|||
|
.low-temperature {
|
|||
|
font-weight: bold;
|
|||
|
font-size: 40px;
|
|||
|
color: #303133;
|
|||
|
line-height: 47px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
.high-temperature {
|
|||
|
font-weight: 400;
|
|||
|
font-size: 14px;
|
|||
|
color: #606266;
|
|||
|
line-height: 16px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
.weather-description {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 500;
|
|||
|
font-size: 14px;
|
|||
|
color: #303133;
|
|||
|
line-height: 20px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
margin: 0px 2px;
|
|||
|
}
|
|||
|
|
|||
|
/* 响应式设计 */
|
|||
|
@media screen and (max-width: 968px) {
|
|||
|
.weather-card {
|
|||
|
padding: 10px;
|
|||
|
height: 400px;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//天气完
|
|||
|
|
|||
|
// 地图
|
|||
|
.map-card {
|
|||
|
background: #ffffff; /* 使用纯色背景,增加清新感 */
|
|||
|
border-radius: 10px; /* 略微减小圆角 */
|
|||
|
overflow: hidden;
|
|||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); /* 更柔和的阴影 */
|
|||
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|||
|
height: 460px;
|
|||
|
|
|||
|
.map-container {
|
|||
|
width: 100%;
|
|||
|
height: 460px; /* 减少高度 */
|
|||
|
position: relative;
|
|||
|
border-radius: 10px;
|
|||
|
overflow: hidden;
|
|||
|
|
|||
|
.map {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
/* 可根据需要添加地图相关样式 */
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 响应式设计 */
|
|||
|
@media screen and (max-width: 968px) {
|
|||
|
.map-card {
|
|||
|
padding: 2px;
|
|||
|
}
|
|||
|
|
|||
|
.card-header {
|
|||
|
padding: 18px 12px;
|
|||
|
|
|||
|
.card-title {
|
|||
|
font-size: 16px;
|
|||
|
|
|||
|
i {
|
|||
|
font-size: 18px;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.map-container {
|
|||
|
height: 250px;
|
|||
|
width: 100%;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@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: 220px;
|
|||
|
}
|
|||
|
}
|
|||
|
// 地图完
|
|||
|
|
|||
|
// 信息栏
|
|||
|
.message-card {
|
|||
|
height: 300px;
|
|||
|
margin-bottom: 20px;
|
|||
|
border-radius: 10px;
|
|||
|
padding: 4px;
|
|||
|
box-shadow: 0 4px 20px $shadow-color;
|
|||
|
transition: transform 0.3s, box-shadow 0.3s;
|
|||
|
white-space: nowrap; /* 不换行 */
|
|||
|
overflow: hidden; /* 隐藏超出部分 */
|
|||
|
text-overflow: ellipsis; /* 使用省略号 */
|
|||
|
.notice-bar {
|
|||
|
overflow: hidden;
|
|||
|
position: relative;
|
|||
|
|
|||
|
.item-wrap {
|
|||
|
display: flex;
|
|||
|
flex-direction: row;
|
|||
|
margin-top: 18px;
|
|||
|
|
|||
|
.left-wrap {
|
|||
|
flex: 1;
|
|||
|
font-weight: 400;
|
|||
|
font-size: 14px;
|
|||
|
color: #303133;
|
|||
|
line-height: 20px;
|
|||
|
white-space: nowrap;
|
|||
|
overflow: hidden;
|
|||
|
text-overflow: ellipsis;
|
|||
|
}
|
|||
|
|
|||
|
.right-wrap {
|
|||
|
font-weight: 400;
|
|||
|
font-size: 12px;
|
|||
|
color: #909399;
|
|||
|
line-height: 17px;
|
|||
|
margin-left: 16px;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//滚动效果
|
|||
|
.animating {
|
|||
|
animation: scroll 10s linear infinite;
|
|||
|
}
|
|||
|
//信息栏标题样式
|
|||
|
.message-title {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 600;
|
|||
|
font-size: 18px;
|
|||
|
color: #303133;
|
|||
|
line-height: 22px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
margin: 0px 0 6px;
|
|||
|
}
|
|||
|
}
|
|||
|
//信息完
|
|||
|
// 登录用户数量
|
|||
|
.line-card {
|
|||
|
height: 320px;
|
|||
|
width: 100%;
|
|||
|
border-radius: 10px;
|
|||
|
padding: 4px;
|
|||
|
color: $secondary-color;
|
|||
|
margin-bottom: 20px;
|
|||
|
box-shadow: 0 4px 20px $shadow-color;
|
|||
|
transition: transform 0.3s, box-shadow 0.3s;
|
|||
|
}
|
|||
|
// 折线图完
|
|||
|
|
|||
|
// 柱状图,mqtt状态数据
|
|||
|
.card-container {
|
|||
|
height: 360px;
|
|||
|
padding: 4px;
|
|||
|
margin-bottom: 20px;
|
|||
|
border-radius: 10px;
|
|||
|
box-shadow: 0 4px 20px $shadow-color;
|
|||
|
overflow: hidden;
|
|||
|
transition: transform 0.3s, box-shadow 0.3s;
|
|||
|
}
|
|||
|
|
|||
|
/* 响应式设计 */
|
|||
|
@media screen and (max-width: 968px) {
|
|||
|
.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 {
|
|||
|
height: 440px;
|
|||
|
padding: 4px;
|
|||
|
width: 100%;
|
|||
|
background: #ffffff;
|
|||
|
border-radius: 10px;
|
|||
|
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
|
|||
|
overflow: hidden;
|
|||
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|||
|
|
|||
|
.chart-title {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 600;
|
|||
|
font-size: 16px;
|
|||
|
color: #303133;
|
|||
|
line-height: 22px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
.pieCpu {
|
|||
|
height: 190px;
|
|||
|
width: 100%;
|
|||
|
margin: 20px 0px;
|
|||
|
display: flex;
|
|||
|
flex: 1;
|
|||
|
background: #f6f7fb;
|
|||
|
}
|
|||
|
@media screen and (max-width: 968px) {
|
|||
|
height: 100%;
|
|||
|
width: 100%;
|
|||
|
margin: 20px 0px;
|
|||
|
.pieCpu {
|
|||
|
height: 176px;
|
|||
|
margin: 20px 0px;
|
|||
|
background: #f6f7fb;
|
|||
|
display: flex;
|
|||
|
flex-direction: row;
|
|||
|
flex-wrap: wrap; /* 允许换行 */
|
|||
|
justify-content: space-around; /* 对齐分布 */
|
|||
|
}
|
|||
|
}
|
|||
|
@media (min-width: 968px) {
|
|||
|
height: 100%;
|
|||
|
width: 100%;
|
|||
|
margin: 20px 0px;
|
|||
|
}
|
|||
|
.pieMemery {
|
|||
|
background: #f6f7fb;
|
|||
|
height: 176px;
|
|||
|
margin: 20px 20px 20px 0px;
|
|||
|
}
|
|||
|
|
|||
|
.pieDisk {
|
|||
|
background: #f6f7fb;
|
|||
|
height: 176px;
|
|||
|
margin: 20px 0px 20px 0px;
|
|||
|
}
|
|||
|
}
|
|||
|
// 使用率完
|
|||
|
|
|||
|
//小程序,h5
|
|||
|
.phone-card {
|
|||
|
border-radius: 10px;
|
|||
|
box-shadow: 0 4px 20px $shadow-color;
|
|||
|
transition: transform 0.3s, box-shadow 0.3s;
|
|||
|
|
|||
|
.mini-program {
|
|||
|
margin: 8px 0px 35px;
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 600;
|
|||
|
font-size: 14px;
|
|||
|
color: #303133;
|
|||
|
line-height: 20px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
.web-site {
|
|||
|
width: 70px;
|
|||
|
font-weight: bold;
|
|||
|
display: table-cell;
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 500;
|
|||
|
font-size: 12px;
|
|||
|
color: #606266;
|
|||
|
line-height: 24px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
.other-site {
|
|||
|
display: table-cell;
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 400;
|
|||
|
font-size: 12px;
|
|||
|
color: #606266;
|
|||
|
line-height: 24px;
|
|||
|
text-align: left;
|
|||
|
font-style: normal;
|
|||
|
}
|
|||
|
}
|
|||
|
.phone {
|
|||
|
height: 650px;
|
|||
|
width: 320px;
|
|||
|
margin-left: 100px;
|
|||
|
background-image: url('../assets/images/phone.png');
|
|||
|
background-size: cover;
|
|||
|
|
|||
|
.frame-remark {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 400;
|
|||
|
font-size: 12px;
|
|||
|
color: #909399;
|
|||
|
line-height: 17px;
|
|||
|
text-align: center;
|
|||
|
font-style: normal;
|
|||
|
margin: 20px auto;
|
|||
|
}
|
|||
|
@media screen and (max-width: 968px) {
|
|||
|
height: 530px;
|
|||
|
width: 260px;
|
|||
|
background-image: url('../assets/images/phone.png');
|
|||
|
background-size: cover;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.phone-container {
|
|||
|
height: 635px;
|
|||
|
width: 291px;
|
|||
|
position: relative;
|
|||
|
border-radius: 35px;
|
|||
|
top: 8px;
|
|||
|
left: 15px;
|
|||
|
background-color: #fff;
|
|||
|
padding-bottom: 0%;
|
|||
|
|
|||
|
@media screen and (max-width: 968px) {
|
|||
|
height: 519px;
|
|||
|
width: 240px;
|
|||
|
position: relative;
|
|||
|
border-radius: 30px;
|
|||
|
top: 5px;
|
|||
|
bottom: 10px;
|
|||
|
left: 10px;
|
|||
|
background-color: #fff;
|
|||
|
padding-bottom: 0%;
|
|||
|
}
|
|||
|
}
|
|||
|
.content {
|
|||
|
line-height: 24px;
|
|||
|
padding: 10px;
|
|||
|
border: 1px solid #eee;
|
|||
|
border-radius: 10px;
|
|||
|
}
|
|||
|
|
|||
|
.description {
|
|||
|
font-size: 12px;
|
|||
|
|
|||
|
tr {
|
|||
|
line-height: 20px;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//底部
|
|||
|
.footer-container {
|
|||
|
font-family: PingFangSC, PingFang SC;
|
|||
|
font-weight: 400;
|
|||
|
font-size: 12px;
|
|||
|
color: #909399;
|
|||
|
line-height: 24px;
|
|||
|
text-align: center;
|
|||
|
font-style: normal;
|
|||
|
margin: 10px 10px 0px 10px;
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|