|
|
@@ -0,0 +1,2144 @@
|
|
|
+<template>
|
|
|
+ <vue-fullscreen
|
|
|
+ class="rr-container"
|
|
|
+ v-cloak
|
|
|
+ v-model="isFullscreen"
|
|
|
+ fullscreenClass="rr-container"
|
|
|
+ :exit-on-click-wrapper="false"
|
|
|
+ >
|
|
|
+ <div class="rr-container" v-cloak>
|
|
|
+ <div class="rr-header">
|
|
|
+ <div class="rr-header-side rr-header-left">
|
|
|
+ <!-- <div class="rr-header-chip">黑屏看板</div> -->
|
|
|
+ <el-date-picker
|
|
|
+ v-model="dateRange"
|
|
|
+ class="rr-date-picker"
|
|
|
+ size="mini"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="-"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="rr-title">越隆达再生资源集团公司</div>
|
|
|
+
|
|
|
+ <div class="rr-header-side rr-header-right">
|
|
|
+ <div class="rr-time-box">
|
|
|
+ <span class="rr-date">{{ date }}</span>
|
|
|
+ <span class="rr-week">{{ week }}</span>
|
|
|
+ <span class="rr-time">{{ time }}</span>
|
|
|
+ </div>
|
|
|
+ <span class="rr-weather">晴 27-19°C</span>
|
|
|
+ <span class="rr-fullscreen" @click="onFullscreen">
|
|
|
+ <i
|
|
|
+ v-if="isFullscreen"
|
|
|
+ class="el-icon-_screen-restore"
|
|
|
+ title="退出全屏"
|
|
|
+ ></i>
|
|
|
+ <i v-else class="el-icon-_screen-full" title="全屏"></i>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="rr-body">
|
|
|
+ <div class="rr-side-column">
|
|
|
+ <section class="rr-panel rr-panel-sales">
|
|
|
+ <div class="rr-panel-title">营销总览</div>
|
|
|
+ <div class="rr-summary-strip">
|
|
|
+ <div
|
|
|
+ v-for="item in salesCards"
|
|
|
+ :key="item.key"
|
|
|
+ class="rr-summary-item"
|
|
|
+ >
|
|
|
+ <div class="rr-summary-icon-box">
|
|
|
+ <div class="rr-summary-icon-wrap">
|
|
|
+ <div class="rr-summary-icon-ring"></div>
|
|
|
+ <div class="rr-summary-icon">
|
|
|
+ <img
|
|
|
+ class="rr-summary-icon-img"
|
|
|
+ :src="item.iconSrc"
|
|
|
+ :alt="item.label"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="rr-summary-content">
|
|
|
+ <div class="rr-summary-label">{{ item.label }}</div>
|
|
|
+ <div class="rr-summary-main">
|
|
|
+ <span class="rr-summary-value">{{ item.value }}</span>
|
|
|
+ <span class="rr-summary-unit">{{ item.unit }}</span>
|
|
|
+ <div class="rr-summary-trend" :class="item.trendType">
|
|
|
+ <span class="rr-summary-trend-label">{{
|
|
|
+ item.trendLabel
|
|
|
+ }}</span>
|
|
|
+ <span class="rr-summary-trend-value"
|
|
|
+ >{{ item.trendType === 'up' ? '↗' : '↘'
|
|
|
+ }}{{ item.trend }}%</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-if="item.key !== salesCards[salesCards.length - 1].key"
|
|
|
+ class="rr-summary-divider"
|
|
|
+ ></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="rr-panel rr-panel-procurement">
|
|
|
+ <div class="rr-panel-title">采购总览</div>
|
|
|
+ <div class="rr-procurement-body">
|
|
|
+ <div class="rr-procurement-pane rr-procurement-pane-area">
|
|
|
+ <div class="rr-pane-caption">
|
|
|
+ <span>单位:件</span>
|
|
|
+ <div class="rr-pane-legend">
|
|
|
+ <span class="rr-legend-item rr-legend-item-blue"
|
|
|
+ >采购量</span
|
|
|
+ >
|
|
|
+ <span class="rr-legend-item rr-legend-item-gold"
|
|
|
+ >到货量</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="rr-chart-panel rr-chart-panel-compact">
|
|
|
+ <area-line-chart
|
|
|
+ v-if="isChartReady"
|
|
|
+ :categories="monthCategories"
|
|
|
+ :series="procurementSeries"
|
|
|
+ :colors="['#3c87ff', '#e5b15d']"
|
|
|
+ :show-legend="false"
|
|
|
+ class="rr-fill-chart"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="rr-procurement-pane rr-procurement-pane-bar">
|
|
|
+ <div class="rr-pane-caption rr-pane-caption-right">
|
|
|
+ <span>准时交付率</span>
|
|
|
+ </div>
|
|
|
+ <div class="rr-mini-bar-panel rr-mini-bar-panel-fill">
|
|
|
+ <div ref="procurementBarRef" class="rr-native-chart"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="rr-panel rr-panel-inventory">
|
|
|
+ <div class="rr-panel-title">仓储总览</div>
|
|
|
+ <div class="rr-inventory-body">
|
|
|
+ <div class="rr-inv-left">
|
|
|
+ <div class="rr-inv-chart-wrap">
|
|
|
+ <div ref="inventoryDonutRef" class="rr-native-chart"></div>
|
|
|
+ <div class="rr-inv-center">
|
|
|
+ <span class="rr-inv-center-value">{{ inventoryOverview.total }}</span>
|
|
|
+ <span class="rr-inv-center-label">库存总量</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="rr-inv-right">
|
|
|
+ <div class="rr-inv-trend-caption">周转率</div>
|
|
|
+ <div class="rr-inv-trend-chart">
|
|
|
+ <div ref="inventoryTrendRef" class="rr-native-chart"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <section class="rr-map-panel">
|
|
|
+ <div class="rr-map-head">
|
|
|
+ <div class="rr-map-tabs">
|
|
|
+ <span
|
|
|
+ class="rr-tab"
|
|
|
+ :class="{ active: mapTab === 'nation' }"
|
|
|
+ @click="mapTab = 'nation'"
|
|
|
+ >
|
|
|
+ 全国
|
|
|
+ </span>
|
|
|
+ <span
|
|
|
+ class="rr-tab"
|
|
|
+ :class="{ active: mapTab === 'factory' }"
|
|
|
+ @click="mapTab = 'factory'"
|
|
|
+ >
|
|
|
+ 工厂分布
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="rr-map-summary">
|
|
|
+ <div
|
|
|
+ v-for="item in mapHeaderStats"
|
|
|
+ :key="item.label"
|
|
|
+ class="rr-map-summary-item"
|
|
|
+ >
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
+ <strong>{{ item.value }}</strong>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="rr-map-body">
|
|
|
+ <china-map-chart
|
|
|
+ v-if="isChartReady"
|
|
|
+ :scatter-data="currentMapScatterData"
|
|
|
+ :legend-categories="currentMapLegendCategories"
|
|
|
+ class="rr-map-chart"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <div class="rr-side-column">
|
|
|
+ <section class="rr-panel rr-panel-quality">
|
|
|
+ <div class="rr-panel-title">质量总览</div>
|
|
|
+ <div class="rr-quality-grid">
|
|
|
+ <div
|
|
|
+ v-for="item in qualityCards"
|
|
|
+ :key="item.title"
|
|
|
+ class="rr-quality-card"
|
|
|
+ >
|
|
|
+ <div class="rr-quality-header">
|
|
|
+ <span class="rr-quality-dot"></span>
|
|
|
+ <span>{{ item.title }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="rr-quality-rate">{{ item.passRate }}%</div>
|
|
|
+ <div class="rr-quality-bars">
|
|
|
+ <div class="rr-progress-row">
|
|
|
+ <span>合格率</span>
|
|
|
+ <strong>{{ item.passRate }}%</strong>
|
|
|
+ </div>
|
|
|
+ <div class="rr-progress-track">
|
|
|
+ <span
|
|
|
+ class="rr-progress-fill rr-progress-fill-good"
|
|
|
+ :style="{ width: item.passRate + '%' }"
|
|
|
+ ></span>
|
|
|
+ </div>
|
|
|
+ <div class="rr-progress-row">
|
|
|
+ <span>不合格率</span>
|
|
|
+ <strong>{{ item.failRate }}%</strong>
|
|
|
+ </div>
|
|
|
+ <div class="rr-progress-track">
|
|
|
+ <span
|
|
|
+ class="rr-progress-fill rr-progress-fill-bad"
|
|
|
+ :style="{ width: item.failRate + '%' }"
|
|
|
+ ></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="rr-panel rr-panel-production">
|
|
|
+ <div class="rr-panel-title">生产总览</div>
|
|
|
+ <div class="rr-chart-panel">
|
|
|
+ <area-line-chart
|
|
|
+ v-if="isChartReady"
|
|
|
+ :categories="monthCategories"
|
|
|
+ :series="productionSeries"
|
|
|
+ :colors="['#4fa5ff', '#22d4b8']"
|
|
|
+ class="rr-fill-chart"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="rr-mini-bar-panel">
|
|
|
+ <div ref="productionBarRef" class="rr-native-chart"></div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="rr-panel rr-panel-equipment">
|
|
|
+ <div class="rr-panel-title">设备总览</div>
|
|
|
+ <div class="rr-equipment-body">
|
|
|
+ <div class="rr-equipment-gauge">
|
|
|
+ <div class="rr-gauge-wrap">
|
|
|
+ <div ref="utilDonutRef" class="rr-native-chart"></div>
|
|
|
+ </div>
|
|
|
+ <ul class="rr-equipment-list">
|
|
|
+ <li v-for="item in leftEquipmentList" :key="item.label">
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
+ <strong>{{ item.value }}</strong>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <div class="rr-equipment-gauge">
|
|
|
+ <div class="rr-gauge-wrap">
|
|
|
+ <div ref="faultDonutRef" class="rr-native-chart"></div>
|
|
|
+ </div>
|
|
|
+ <ul class="rr-equipment-list">
|
|
|
+ <li v-for="item in rightEquipmentList" :key="item.label">
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
+ <strong>{{ item.value }}</strong>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </vue-fullscreen>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import { component as VueFullscreen } from 'vue-fullscreen';
|
|
|
+ import * as echarts from 'echarts';
|
|
|
+ import AreaLineChart from './components/charts/AreaLineChart';
|
|
|
+ import ChinaMapChart from './components/charts/ChinaMapChart';
|
|
|
+
|
|
|
+ export default {
|
|
|
+ name: 'RenewableResourcesDashboard',
|
|
|
+ components: {
|
|
|
+ VueFullscreen,
|
|
|
+ AreaLineChart,
|
|
|
+ ChinaMapChart
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ isFullscreen: false,
|
|
|
+ isChartReady: false,
|
|
|
+ resizeTimer: null,
|
|
|
+ clockTimer: null,
|
|
|
+ date: '',
|
|
|
+ time: '',
|
|
|
+ week: '',
|
|
|
+ dateRange: [],
|
|
|
+ mapTab: 'nation',
|
|
|
+ monthCategories: [
|
|
|
+ '1月',
|
|
|
+ '2月',
|
|
|
+ '3月',
|
|
|
+ '4月',
|
|
|
+ '5月',
|
|
|
+ '6月',
|
|
|
+ '7月',
|
|
|
+ '8月',
|
|
|
+ '9月',
|
|
|
+ '10月',
|
|
|
+ '11月',
|
|
|
+ '12月'
|
|
|
+ ],
|
|
|
+ salesCards: [
|
|
|
+ {
|
|
|
+ key: 'order',
|
|
|
+ iconSrc: require('@/assets/renewable_icon_2.svg'),
|
|
|
+ label: '订单量',
|
|
|
+ value: '1024',
|
|
|
+ unit: '万',
|
|
|
+ trend: 25,
|
|
|
+ trendType: 'up',
|
|
|
+ trendLabel: '同比上升'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'ship',
|
|
|
+ iconSrc: require('@/assets/renewable_icon_3.svg'),
|
|
|
+ label: '出货量',
|
|
|
+ value: '2048',
|
|
|
+ unit: '万',
|
|
|
+ trend: 25,
|
|
|
+ trendType: 'warn',
|
|
|
+ trendLabel: '同比上升'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'delivery',
|
|
|
+ iconSrc: require('@/assets/renewable_icon_4.svg'),
|
|
|
+ label: '准时交货率',
|
|
|
+ value: '89',
|
|
|
+ unit: '%',
|
|
|
+ trend: 25,
|
|
|
+ trendType: 'up',
|
|
|
+ trendLabel: '同比下降'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ qualityCards: [
|
|
|
+ { title: '成品质检', passRate: 98, failRate: 2 },
|
|
|
+ { title: '原料质检', passRate: 91, failRate: 9 }
|
|
|
+ ],
|
|
|
+ inventoryOverview: {
|
|
|
+ total: 6247
|
|
|
+ },
|
|
|
+ inventoryStats: [
|
|
|
+ { label: '成品数', value: 2533 },
|
|
|
+ { label: '半成品数', value: 1050 },
|
|
|
+ { label: '原材料数', value: 2523 },
|
|
|
+ { label: '备品备件数', value: 58 },
|
|
|
+ { label: '呆滞品数', value: 83 }
|
|
|
+ ],
|
|
|
+ // mapHeaderStats: [
|
|
|
+ // { label: '覆盖省份', value: 24 },
|
|
|
+ // { label: '合作基地', value: 16 },
|
|
|
+ // { label: '实时车辆', value: 37 }
|
|
|
+ // ],
|
|
|
+ nationMapScatterData: [
|
|
|
+ { name: '新疆', value: [87.6168, 43.8256], category: 0 },
|
|
|
+ { name: '甘肃', value: [103.8236, 36.0581], category: 1 },
|
|
|
+ { name: '河南', value: [113.6254, 34.7466], category: 2 },
|
|
|
+ { name: '山东', value: [117.0208, 36.6683], category: 3 },
|
|
|
+ { name: '江苏', value: [118.7969, 32.0603], category: 0 },
|
|
|
+ { name: '浙江', value: [120.1536, 30.2875], category: 1 },
|
|
|
+ { name: '福建', value: [119.2965, 26.1006], category: 2 },
|
|
|
+ { name: '广东', value: [113.2644, 23.1291], category: 3 }
|
|
|
+ ],
|
|
|
+ factoryMapScatterData: [
|
|
|
+ { name: '乌鲁木齐工厂', value: [87.6168, 43.8256], category: 0 },
|
|
|
+ { name: '兰州工厂', value: [103.8236, 36.0581], category: 1 },
|
|
|
+ { name: '郑州工厂', value: [113.6254, 34.7466], category: 2 },
|
|
|
+ { name: '青岛工厂', value: [120.3826, 36.0671], category: 3 },
|
|
|
+ { name: '南京工厂', value: [118.7969, 32.0603], category: 0 },
|
|
|
+ { name: '广州工厂', value: [113.2644, 23.1291], category: 2 }
|
|
|
+ ],
|
|
|
+ nationMapLegendCategories: [
|
|
|
+ { name: '危废回收', count: 15 },
|
|
|
+ { name: '金属分拣', count: 12 },
|
|
|
+ { name: '塑料再生', count: 10 },
|
|
|
+ { name: '纸类回收', count: 13 }
|
|
|
+ ],
|
|
|
+ factoryMapLegendCategories: [
|
|
|
+ { name: '总装厂', count: 3 },
|
|
|
+ { name: '分拣厂', count: 5 },
|
|
|
+ { name: '再生厂', count: 4 },
|
|
|
+ { name: '仓储站', count: 4 }
|
|
|
+ ],
|
|
|
+ procurementSeries: [
|
|
|
+ {
|
|
|
+ name: '采购量',
|
|
|
+ data: [2100, 3200, 2800, 4200, 4673, 2600, 1800, 2200, 1500, 2800, 4800, 1900]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '到货量',
|
|
|
+ data: [1400, 2100, 1800, 2600, 2895, 1700, 1300, 1600, 1100, 1700, 2500, 1200]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ productionSeries: [
|
|
|
+ {
|
|
|
+ name: '生产量',
|
|
|
+ data: [240, 286, 332, 365, 398, 430, 412, 448, 470, 502, 534, 561]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '达成量',
|
|
|
+ data: [205, 240, 285, 318, 345, 380, 366, 398, 420, 446, 478, 505]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ equipmentOverview: {
|
|
|
+ utilRate: 92,
|
|
|
+ faultRate: 23,
|
|
|
+ online: 1247,
|
|
|
+ waiting: 523,
|
|
|
+ maintenance: 80,
|
|
|
+ scrapped: 23,
|
|
|
+ deviceCount: 533,
|
|
|
+ productCount: 1247,
|
|
|
+ spareCount: 523,
|
|
|
+ toolCount: 80
|
|
|
+ },
|
|
|
+ chartInstances: {
|
|
|
+ procurementBar: null,
|
|
|
+ productionBar: null,
|
|
|
+ inventoryDonut: null,
|
|
|
+ inventoryTrend: null,
|
|
|
+ utilDonut: null,
|
|
|
+ faultDonut: null
|
|
|
+ }
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ currentMapScatterData() {
|
|
|
+ return this.mapTab === 'factory'
|
|
|
+ ? this.factoryMapScatterData
|
|
|
+ : this.nationMapScatterData;
|
|
|
+ },
|
|
|
+ currentMapLegendCategories() {
|
|
|
+ return this.mapTab === 'factory'
|
|
|
+ ? this.factoryMapLegendCategories
|
|
|
+ : this.nationMapLegendCategories;
|
|
|
+ },
|
|
|
+ leftEquipmentList() {
|
|
|
+ return [
|
|
|
+ { label: '在线设备', value: this.equipmentOverview.online },
|
|
|
+ { label: '待机设备', value: this.equipmentOverview.waiting },
|
|
|
+ { label: '维修设备', value: this.equipmentOverview.maintenance }
|
|
|
+ ];
|
|
|
+ },
|
|
|
+ rightEquipmentList() {
|
|
|
+ return [
|
|
|
+ { label: '生产设备', value: this.equipmentOverview.deviceCount },
|
|
|
+ { label: '产品设备', value: this.equipmentOverview.productCount },
|
|
|
+ { label: '备件库存', value: this.equipmentOverview.spareCount }
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.updateTime();
|
|
|
+ this.clockTimer = setInterval(this.updateTime, 1000);
|
|
|
+ const now = new Date();
|
|
|
+ const start = new Date(now.getTime() - 1000 * 60 * 60 * 24 * 30);
|
|
|
+ this.dateRange = [this.formatDate(start), this.formatDate(now)];
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.applyScreenSize();
|
|
|
+ window.addEventListener('resize', this.handleResize);
|
|
|
+ document.addEventListener(
|
|
|
+ 'fullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.addEventListener(
|
|
|
+ 'webkitfullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.isChartReady = true;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.initNativeCharts();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ clearInterval(this.clockTimer);
|
|
|
+ clearTimeout(this.resizeTimer);
|
|
|
+ window.removeEventListener('resize', this.handleResize);
|
|
|
+ document.removeEventListener(
|
|
|
+ 'fullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.removeEventListener(
|
|
|
+ 'webkitfullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ Object.values(this.chartInstances).forEach((chart) => chart?.dispose());
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ formatDate(date) {
|
|
|
+ const pad = (n) => String(n).padStart(2, '0');
|
|
|
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(
|
|
|
+ date.getDate()
|
|
|
+ )}`;
|
|
|
+ },
|
|
|
+ onFullscreen() {
|
|
|
+ this.isFullscreen = !this.isFullscreen;
|
|
|
+ },
|
|
|
+ updateTime() {
|
|
|
+ const now = new Date();
|
|
|
+ const pad = (n) => String(n).padStart(2, '0');
|
|
|
+ this.time = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(
|
|
|
+ now.getSeconds()
|
|
|
+ )}`;
|
|
|
+ this.date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(
|
|
|
+ now.getDate()
|
|
|
+ )}`;
|
|
|
+ const weeks = [
|
|
|
+ '星期日',
|
|
|
+ '星期一',
|
|
|
+ '星期二',
|
|
|
+ '星期三',
|
|
|
+ '星期四',
|
|
|
+ '星期五',
|
|
|
+ '星期六'
|
|
|
+ ];
|
|
|
+ this.week = weeks[now.getDay()];
|
|
|
+ },
|
|
|
+ handleResize() {
|
|
|
+ clearTimeout(this.resizeTimer);
|
|
|
+ this.resizeTimer = setTimeout(() => {
|
|
|
+ this.applyScreenSize();
|
|
|
+ Object.values(this.chartInstances).forEach((chart) =>
|
|
|
+ chart?.resize()
|
|
|
+ );
|
|
|
+ window.dispatchEvent(new Event('resize'));
|
|
|
+ }, 120);
|
|
|
+ },
|
|
|
+ handleFullscreenChange() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.applyScreenSize();
|
|
|
+ Object.values(this.chartInstances).forEach((chart) =>
|
|
|
+ chart?.resize()
|
|
|
+ );
|
|
|
+ window.dispatchEvent(new Event('resize'));
|
|
|
+ }, 160);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ applyScreenSize() {
|
|
|
+ const isFs = !!(
|
|
|
+ document.fullscreenElement || document.webkitFullscreenElement
|
|
|
+ );
|
|
|
+ const deviceWidth = isFs
|
|
|
+ ? window.innerWidth || document.documentElement.clientWidth
|
|
|
+ : document.documentElement.clientWidth;
|
|
|
+ const deviceHeight = isFs
|
|
|
+ ? window.innerHeight || document.documentElement.clientHeight
|
|
|
+ : document.documentElement.clientHeight;
|
|
|
+ const headerH =
|
|
|
+ (!isFs &&
|
|
|
+ document.querySelector('.ele-admin-header')?.offsetHeight) ||
|
|
|
+ 0;
|
|
|
+ const tabsH =
|
|
|
+ (!isFs && document.querySelector('.ele-admin-tabs')?.offsetHeight) ||
|
|
|
+ 0;
|
|
|
+ const sidebarW =
|
|
|
+ (!isFs &&
|
|
|
+ document.querySelector('.ele-admin-sidebar')?.offsetWidth) ||
|
|
|
+ 0;
|
|
|
+ const h = isFs ? deviceHeight : deviceHeight - headerH - tabsH;
|
|
|
+ const w = isFs ? deviceWidth : deviceWidth - sidebarW;
|
|
|
+ document.querySelectorAll('.rr-container').forEach((el) => {
|
|
|
+ el.style.height = `${h}px`;
|
|
|
+ el.style.width = `${w}px`;
|
|
|
+ });
|
|
|
+ const designWidth = 1920;
|
|
|
+ const designHeight = 1080;
|
|
|
+ const scale = Math.min(w / designWidth, h / designHeight);
|
|
|
+ const baseFontSize = isFs ? Math.max(14, Math.min(18, 16 * scale)) : 16;
|
|
|
+ document.documentElement.style.fontSize = `${baseFontSize}px`;
|
|
|
+ },
|
|
|
+ initNativeCharts() {
|
|
|
+ this.initBarChart(
|
|
|
+ 'procurementBar',
|
|
|
+ this.$refs.procurementBarRef,
|
|
|
+ [68, 58, 62, 78, 55, 81, 90, 88, 75, 55, 82, 88],
|
|
|
+ '#1089BB'
|
|
|
+ );
|
|
|
+ this.initBarChart(
|
|
|
+ 'productionBar',
|
|
|
+ this.$refs.productionBarRef,
|
|
|
+ [18, 22, 26, 29, 35, 37, 36, 40, 42, 45, 49, 51],
|
|
|
+ '#22d4b8'
|
|
|
+ );
|
|
|
+ this.initInventoryDonutChart();
|
|
|
+ this.initInventoryTrendChart();
|
|
|
+ this.initGaugeChart(
|
|
|
+ 'utilDonut',
|
|
|
+ this.$refs.utilDonutRef,
|
|
|
+ 92,
|
|
|
+ '#27dfd3'
|
|
|
+ );
|
|
|
+ this.initGaugeChart(
|
|
|
+ 'faultDonut',
|
|
|
+ this.$refs.faultDonutRef,
|
|
|
+ 23,
|
|
|
+ '#ff834d'
|
|
|
+ );
|
|
|
+ },
|
|
|
+ initBarChart(key, el, data, color) {
|
|
|
+ if (!el) return;
|
|
|
+ this.chartInstances[key]?.dispose();
|
|
|
+ const chart = echarts.init(el);
|
|
|
+ if (key === 'procurementBar') {
|
|
|
+ const topColor = '#0DF1FF';
|
|
|
+ const barW = 22;
|
|
|
+ const diamondW = barW;
|
|
|
+ const diamondH = Math.round(diamondW * 0.42);
|
|
|
+ chart.setOption({
|
|
|
+ backgroundColor: 'transparent',
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: { type: 'shadow', shadowStyle: { color: 'rgba(13,241,255,0.06)' } },
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.96)',
|
|
|
+ borderColor: '#ddd',
|
|
|
+ textStyle: { color: '#333', fontSize: 13 },
|
|
|
+ formatter: (params) => {
|
|
|
+ const p = params.find((s) => s.seriesIndex === 1);
|
|
|
+ return p ? `<b>${p.name}</b><br/>准时到货率 <b>${p.value}%</b>` : '';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '6%',
|
|
|
+ right: '4%',
|
|
|
+ top: '12%',
|
|
|
+ bottom: '8%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: this.monthCategories,
|
|
|
+ axisLine: { lineStyle: { color: 'rgba(32, 105, 168, 0.45)' } },
|
|
|
+ axisTick: { show: false },
|
|
|
+ axisLabel: {
|
|
|
+ color: '#d4ebff',
|
|
|
+ fontSize: 11,
|
|
|
+ margin: 8
|
|
|
+ }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ min: 0,
|
|
|
+ max: 100,
|
|
|
+ interval: 20,
|
|
|
+ axisLine: { show: false },
|
|
|
+ axisTick: { show: false },
|
|
|
+ axisLabel: {
|
|
|
+ color: '#b8d4ef',
|
|
|
+ fontSize: 11,
|
|
|
+ formatter: '{value}%'
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: { color: 'rgba(21, 77, 123, 0.22)' }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: 'bg',
|
|
|
+ type: 'bar',
|
|
|
+ data: new Array(data.length).fill(100),
|
|
|
+ barWidth: barW,
|
|
|
+ barGap: '-100%',
|
|
|
+ silent: true,
|
|
|
+ z: 1,
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: 'rgba(16, 137, 187, 0.1)' },
|
|
|
+ { offset: 1, color: 'rgba(16, 137, 187, 0.02)' }
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'value',
|
|
|
+ type: 'bar',
|
|
|
+ data,
|
|
|
+ barWidth: barW,
|
|
|
+ z: 3,
|
|
|
+ itemStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: 'rgba(13, 241, 255, 0.92)' },
|
|
|
+ { offset: 0.4, color: 'rgba(16, 137, 187, 0.82)' },
|
|
|
+ { offset: 1, color: 'rgba(10, 68, 122, 0.72)' }
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'topCap',
|
|
|
+ type: 'pictorialBar',
|
|
|
+ data,
|
|
|
+ symbol: 'diamond',
|
|
|
+ symbolSize: [diamondW, diamondH],
|
|
|
+ symbolOffset: [0, -(diamondH / 2)],
|
|
|
+ symbolPosition: 'end',
|
|
|
+ z: 5,
|
|
|
+ tooltip: { show: false },
|
|
|
+ itemStyle: {
|
|
|
+ color: topColor,
|
|
|
+ shadowBlur: 8,
|
|
|
+ shadowColor: 'rgba(13, 241, 255, 0.55)'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'bottomCap',
|
|
|
+ type: 'pictorialBar',
|
|
|
+ data: new Array(data.length).fill(0.5),
|
|
|
+ symbol: 'diamond',
|
|
|
+ symbolSize: [diamondW, diamondH],
|
|
|
+ symbolOffset: [0, diamondH / 2],
|
|
|
+ symbolPosition: 'start',
|
|
|
+ z: 2,
|
|
|
+ tooltip: { show: false },
|
|
|
+ itemStyle: {
|
|
|
+ color: 'rgba(10, 68, 122, 0.78)'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ this.chartInstances[key] = chart;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ chart.setOption({
|
|
|
+ backgroundColor: 'transparent',
|
|
|
+ grid: {
|
|
|
+ left: '8%',
|
|
|
+ right: '4%',
|
|
|
+ top: '10%',
|
|
|
+ bottom: '12%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: this.monthCategories,
|
|
|
+ axisLine: { lineStyle: { color: '#154d7b' } },
|
|
|
+ axisTick: { show: false },
|
|
|
+ axisLabel: { color: '#b8d4ef', fontSize: 10 }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ axisLine: { show: false },
|
|
|
+ axisTick: { show: false },
|
|
|
+ axisLabel: { color: '#b8d4ef', fontSize: 10 },
|
|
|
+ splitLine: { lineStyle: { color: 'rgba(21, 77, 123, 0.28)' } }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'bar',
|
|
|
+ data,
|
|
|
+ barWidth: '42%',
|
|
|
+ itemStyle: {
|
|
|
+ borderRadius: [6, 6, 0, 0],
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color },
|
|
|
+ { offset: 1, color: color + '2b' }
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ this.chartInstances[key] = chart;
|
|
|
+ },
|
|
|
+ initInventoryDonutChart() {
|
|
|
+ if (!this.$refs.inventoryDonutRef) return;
|
|
|
+ this.chartInstances.inventoryDonut?.dispose();
|
|
|
+ const chart = echarts.init(this.$refs.inventoryDonutRef);
|
|
|
+ const pieColors = ['#2d5dbe', '#ffb648', '#3cd8c8', '#7b69ff', '#1fa4df'];
|
|
|
+ const pieData = [
|
|
|
+ { name: '成品数', value: 2533 },
|
|
|
+ { name: '半成品数', value: 1050 },
|
|
|
+ { name: '原材料数', value: 2523 },
|
|
|
+ { name: '备品备件数', value: 58 },
|
|
|
+ { name: '呆滞品数', value: 83 }
|
|
|
+ ];
|
|
|
+ const cw = chart.getWidth();
|
|
|
+ const ch = chart.getHeight();
|
|
|
+ const isSmall = cw < 240 || ch < 160;
|
|
|
+ const valFs = isSmall ? 12 : 14;
|
|
|
+ const nameFs = isSmall ? 10 : 11;
|
|
|
+ chart.setOption({
|
|
|
+ backgroundColor: 'transparent',
|
|
|
+ color: pieColors,
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item',
|
|
|
+ backgroundColor: 'rgba(8,29,65,0.92)',
|
|
|
+ borderColor: '#124c77',
|
|
|
+ textStyle: { color: '#fff', fontSize: 13 }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['36%', '58%'],
|
|
|
+ center: ['50%', '50%'],
|
|
|
+ padAngle: 2,
|
|
|
+ itemStyle: { borderRadius: 4 },
|
|
|
+ minShowLabelAngle: 2,
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'outside',
|
|
|
+ formatter: (p) => `{val|${p.data.value}}\n{name|${p.name}}`,
|
|
|
+ rich: {
|
|
|
+ val: {
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: valFs,
|
|
|
+ fontWeight: 700,
|
|
|
+ lineHeight: valFs + 6
|
|
|
+ },
|
|
|
+ name: {
|
|
|
+ color: '#c3dfff',
|
|
|
+ fontSize: nameFs,
|
|
|
+ lineHeight: nameFs + 5
|
|
|
+ }
|
|
|
+ },
|
|
|
+ distanceToLabelLine: 2
|
|
|
+ },
|
|
|
+ labelLine: {
|
|
|
+ show: true,
|
|
|
+ length: 10,
|
|
|
+ length2: 20,
|
|
|
+ smooth: false,
|
|
|
+ lineStyle: { color: '#4da6d8', width: 1.2 }
|
|
|
+ },
|
|
|
+ labelLayout: (params) => {
|
|
|
+ const isLeft = params.labelRect.x < cw / 2;
|
|
|
+ return {
|
|
|
+ align: isLeft ? 'right' : 'left',
|
|
|
+ hideOverlap: true
|
|
|
+ };
|
|
|
+ },
|
|
|
+ data: pieData
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['30%', '32%'],
|
|
|
+ center: ['50%', '50%'],
|
|
|
+ silent: true,
|
|
|
+ label: { show: false },
|
|
|
+ labelLine: { show: false },
|
|
|
+ data: [{ value: 1, itemStyle: { color: 'rgba(60, 135, 255, 0.18)' } }]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ this.chartInstances.inventoryDonut = chart;
|
|
|
+ },
|
|
|
+ initInventoryTrendChart() {
|
|
|
+ if (!this.$refs.inventoryTrendRef) return;
|
|
|
+ this.chartInstances.inventoryTrend?.dispose();
|
|
|
+ const chart = echarts.init(this.$refs.inventoryTrendRef);
|
|
|
+ chart.setOption({
|
|
|
+ backgroundColor: 'transparent',
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ backgroundColor: 'rgba(8,29,65,0.92)',
|
|
|
+ borderColor: '#124c77',
|
|
|
+ textStyle: { color: '#fff', fontSize: 12 },
|
|
|
+ formatter: (params) => {
|
|
|
+ const p = params[0];
|
|
|
+ return p ? `${p.name} 周转率: <b>${p.value}%</b>` : '';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '2%',
|
|
|
+ right: '4%',
|
|
|
+ top: '16%',
|
|
|
+ bottom: '10%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: ['数据一', '数据二', '数据三', '数据四', '数据五', '数据六', '数据七'],
|
|
|
+ axisLine: { lineStyle: { color: 'rgba(21, 77, 123, 0.6)' } },
|
|
|
+ axisTick: { show: false },
|
|
|
+ axisLabel: { color: '#b8d4ef', fontSize: 10 }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ min: 50,
|
|
|
+ max: 100,
|
|
|
+ interval: 10,
|
|
|
+ axisLine: { show: false },
|
|
|
+ axisTick: { show: false },
|
|
|
+ axisLabel: { color: '#b8d4ef', fontSize: 10, formatter: '{value}%' },
|
|
|
+ splitLine: { lineStyle: { color: 'rgba(21, 77, 123, 0.24)' } }
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'line',
|
|
|
+ smooth: 0.3,
|
|
|
+ data: [78, 82, 72, 80, 85, 79, 88],
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 8,
|
|
|
+ showSymbol: true,
|
|
|
+ lineStyle: { color: '#3c87ff', width: 2.5 },
|
|
|
+ itemStyle: { color: '#3c87ff', borderColor: '#fff', borderWidth: 2 },
|
|
|
+ areaStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: 'rgba(60, 135, 255, 0.3)' },
|
|
|
+ { offset: 1, color: 'rgba(60, 135, 255, 0.02)' }
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ this.chartInstances.inventoryTrend = chart;
|
|
|
+ },
|
|
|
+ initGaugeChart(key, el, value, color) {
|
|
|
+ if (!el) return;
|
|
|
+ this.chartInstances[key]?.dispose();
|
|
|
+ const chart = echarts.init(el);
|
|
|
+ const label = key === 'utilDonut' ? '设备利用率' : '设备故障率';
|
|
|
+ chart.setOption({
|
|
|
+ backgroundColor: 'transparent',
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'gauge',
|
|
|
+ center: ['50%', '62%'],
|
|
|
+ radius: '90%',
|
|
|
+ startAngle: 200,
|
|
|
+ endAngle: -20,
|
|
|
+ min: 0,
|
|
|
+ max: 100,
|
|
|
+ pointer: { show: false },
|
|
|
+ progress: {
|
|
|
+ show: true,
|
|
|
+ width: 16,
|
|
|
+ roundCap: true,
|
|
|
+ itemStyle: { color }
|
|
|
+ },
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ width: 16,
|
|
|
+ color: [[1, 'rgba(18, 76, 119, 0.32)']]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisTick: { show: false },
|
|
|
+ splitLine: { show: false },
|
|
|
+ axisLabel: {
|
|
|
+ show: true,
|
|
|
+ distance: -32,
|
|
|
+ color: 'rgba(180, 220, 255, 0.6)',
|
|
|
+ fontSize: 10,
|
|
|
+ formatter: (v) => {
|
|
|
+ if (v === 0 || v === 100) return v + '%';
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ title: {
|
|
|
+ show: true,
|
|
|
+ offsetCenter: [0, '38%'],
|
|
|
+ color: '#c3dfff',
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 400
|
|
|
+ },
|
|
|
+ detail: {
|
|
|
+ valueAnimation: true,
|
|
|
+ offsetCenter: [0, '4%'],
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 30,
|
|
|
+ fontWeight: 700,
|
|
|
+ formatter: (v) => {
|
|
|
+ return `{val|${v}}{unit|%}`;
|
|
|
+ },
|
|
|
+ rich: {
|
|
|
+ val: {
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 30,
|
|
|
+ fontWeight: 700
|
|
|
+ },
|
|
|
+ unit: {
|
|
|
+ color: 'rgba(255,255,255,0.68)',
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 400,
|
|
|
+ padding: [0, 0, 2, 2]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data: [{ value, name: label }]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'gauge',
|
|
|
+ center: ['50%', '62%'],
|
|
|
+ radius: '80%',
|
|
|
+ startAngle: 200,
|
|
|
+ endAngle: -20,
|
|
|
+ min: 0,
|
|
|
+ max: 100,
|
|
|
+ pointer: { show: false },
|
|
|
+ progress: { show: false },
|
|
|
+ axisLine: {
|
|
|
+ lineStyle: {
|
|
|
+ width: 1,
|
|
|
+ color: [[1, 'rgba(18, 76, 119, 0.18)']]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisTick: { show: false },
|
|
|
+ splitLine: { show: false },
|
|
|
+ axisLabel: { show: false },
|
|
|
+ title: { show: false },
|
|
|
+ detail: { show: false }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ this.chartInstances[key] = chart;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .rr-container {
|
|
|
+ color: #fff;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+ background: radial-gradient(
|
|
|
+ circle at top center,
|
|
|
+ rgba(30, 113, 255, 0.18),
|
|
|
+ transparent 26%
|
|
|
+ ),
|
|
|
+ radial-gradient(
|
|
|
+ circle at center,
|
|
|
+ rgba(0, 148, 255, 0.08),
|
|
|
+ transparent 40%
|
|
|
+ ),
|
|
|
+ linear-gradient(180deg, #04132e 0%, #051d47 48%, #031229 100%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-header {
|
|
|
+ position: relative;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr auto 1fr;
|
|
|
+ align-items: center;
|
|
|
+ gap: 1rem;
|
|
|
+ min-height: 4.6rem;
|
|
|
+ padding: 0 0.9rem;
|
|
|
+ background: radial-gradient(
|
|
|
+ circle at center top,
|
|
|
+ rgba(37, 118, 255, 0.18),
|
|
|
+ transparent 45%
|
|
|
+ ),
|
|
|
+ linear-gradient(180deg, rgba(8, 33, 78, 0.96), rgba(4, 19, 46, 0.78));
|
|
|
+ border-bottom: 1px solid rgba(59, 132, 255, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-header::before,
|
|
|
+ .rr-header::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 24rem;
|
|
|
+ height: 0.2rem;
|
|
|
+ border-radius: 999px;
|
|
|
+ background: linear-gradient(
|
|
|
+ 90deg,
|
|
|
+ transparent,
|
|
|
+ rgba(95, 182, 255, 0.85),
|
|
|
+ transparent
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-header::before {
|
|
|
+ top: 0.25rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-header::after {
|
|
|
+ bottom: 0.25rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-header-side {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 0.75rem;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-header-right {
|
|
|
+ justify-content: flex-end;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-header-chip {
|
|
|
+ padding: 0.28rem 0.72rem;
|
|
|
+ font-size: 0.78rem;
|
|
|
+ color: #d8efff;
|
|
|
+ border: 1px solid rgba(79, 168, 255, 0.45);
|
|
|
+ background: linear-gradient(
|
|
|
+ 180deg,
|
|
|
+ rgba(12, 74, 160, 0.78),
|
|
|
+ rgba(4, 37, 93, 0.72)
|
|
|
+ );
|
|
|
+ box-shadow: inset 0 0 0.75rem rgba(79, 168, 255, 0.18);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-date-picker {
|
|
|
+ width: 16rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep .rr-date-picker.el-date-editor,
|
|
|
+ ::v-deep .rr-date-picker .el-input__inner,
|
|
|
+ ::v-deep .rr-date-picker.el-range-editor.el-input__inner {
|
|
|
+ background-color: #011944;
|
|
|
+ border: 1px solid #0b6fd5;
|
|
|
+ color: #e9f3ff;
|
|
|
+ box-shadow: 0 0 4px rgba(11, 109, 213, 0.28);
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep .rr-date-picker .el-range-input,
|
|
|
+ ::v-deep .rr-date-picker .el-range-separator,
|
|
|
+ ::v-deep .rr-date-picker .el-range__icon {
|
|
|
+ background: transparent;
|
|
|
+ color: #9fc5ff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-title {
|
|
|
+ position: relative;
|
|
|
+ z-index: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-width: 33rem;
|
|
|
+ height: 1.88rem;
|
|
|
+ padding: 0 4.4rem 0.02rem;
|
|
|
+ font-family: '优设标题黑';
|
|
|
+ font-size: clamp(1.3rem, 1.7vw, 1.76rem);
|
|
|
+ font-style: italic;
|
|
|
+ letter-spacing: 0.01rem;
|
|
|
+ color: #f3fbff;
|
|
|
+ text-align: center;
|
|
|
+ text-shadow: 0 0 0.14rem rgba(255, 255, 255, 0.22),
|
|
|
+ 0 0 0.42rem rgba(80, 184, 255, 0.14);
|
|
|
+ background: radial-gradient(
|
|
|
+ ellipse at 50% 2%,
|
|
|
+ rgba(209, 244, 255, 0.28),
|
|
|
+ rgba(209, 244, 255, 0) 48%
|
|
|
+ ),
|
|
|
+ linear-gradient(
|
|
|
+ 90deg,
|
|
|
+ rgba(14, 76, 194, 0.14) 0%,
|
|
|
+ rgba(54, 148, 255, 0.24) 14%,
|
|
|
+ rgba(118, 213, 255, 0.3) 50%,
|
|
|
+ rgba(54, 148, 255, 0.24) 86%,
|
|
|
+ rgba(14, 76, 194, 0.14) 100%
|
|
|
+ ),
|
|
|
+ linear-gradient(
|
|
|
+ 180deg,
|
|
|
+ rgba(55, 142, 255, 0.92) 0%,
|
|
|
+ rgba(33, 114, 235, 0.92) 36%,
|
|
|
+ rgba(11, 69, 182, 0.96) 74%,
|
|
|
+ rgba(7, 44, 122, 0.98) 100%
|
|
|
+ );
|
|
|
+ border: 1px solid rgba(102, 188, 255, 0.28);
|
|
|
+ border-top-color: rgba(177, 232, 255, 0.42);
|
|
|
+ border-bottom-color: rgba(80, 155, 255, 0.4);
|
|
|
+ clip-path: polygon(
|
|
|
+ 0 0,
|
|
|
+ 100% 0,
|
|
|
+ 100% 68%,
|
|
|
+ 98.8% 80%,
|
|
|
+ 93% 100%,
|
|
|
+ 7% 100%,
|
|
|
+ 1.2% 80%,
|
|
|
+ 0 68%
|
|
|
+ );
|
|
|
+ box-shadow: inset 0 0.05rem 0.16rem rgba(223, 248, 255, 0.14),
|
|
|
+ inset 0 -0.16rem 0.34rem rgba(4, 22, 74, 0.34),
|
|
|
+ 0 0.05rem 0.18rem rgba(0, 0, 0, 0.12);
|
|
|
+ overflow: visible;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-title::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ top: 0.08rem;
|
|
|
+ width: calc(100% + 3.2rem);
|
|
|
+ height: 0.82rem;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ background: radial-gradient(
|
|
|
+ ellipse at 50% 10%,
|
|
|
+ rgba(196, 241, 255, 0.22),
|
|
|
+ rgba(196, 241, 255, 0) 34%
|
|
|
+ ),
|
|
|
+ linear-gradient(
|
|
|
+ 90deg,
|
|
|
+ rgba(20, 83, 210, 0) 0%,
|
|
|
+ rgba(31, 111, 233, 0.03) 14%,
|
|
|
+ rgba(52, 151, 255, 0.08) 24%,
|
|
|
+ rgba(128, 221, 255, 0.18) 50%,
|
|
|
+ rgba(52, 151, 255, 0.08) 76%,
|
|
|
+ rgba(31, 111, 233, 0.03) 86%,
|
|
|
+ rgba(20, 83, 210, 0) 100%
|
|
|
+ );
|
|
|
+ clip-path: polygon(
|
|
|
+ 0 82%,
|
|
|
+ 10% 58%,
|
|
|
+ 22% 28%,
|
|
|
+ 78% 28%,
|
|
|
+ 90% 58%,
|
|
|
+ 100% 82%,
|
|
|
+ 88% 100%,
|
|
|
+ 12% 100%
|
|
|
+ );
|
|
|
+ opacity: 0.52;
|
|
|
+ z-index: -1;
|
|
|
+ filter: drop-shadow(0 0 0.12rem rgba(59, 162, 255, 0.14));
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-title::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ bottom: 0.06rem;
|
|
|
+ width: calc(100% - 4.2rem);
|
|
|
+ height: 0.06rem;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ border-radius: 999px;
|
|
|
+ background: linear-gradient(
|
|
|
+ 90deg,
|
|
|
+ rgba(137, 222, 255, 0) 0%,
|
|
|
+ rgba(137, 222, 255, 0.2) 18%,
|
|
|
+ rgba(212, 246, 255, 0.72) 50%,
|
|
|
+ rgba(137, 222, 255, 0.2) 82%,
|
|
|
+ rgba(137, 222, 255, 0) 100%
|
|
|
+ );
|
|
|
+ box-shadow: 0 0 0.14rem rgba(113, 214, 255, 0.12);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-time-box {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 0.6rem;
|
|
|
+ color: #a9d0ff;
|
|
|
+ font-size: 0.82rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-time {
|
|
|
+ color: #fff;
|
|
|
+ font-size: 1rem;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-weather {
|
|
|
+ color: #f6d067;
|
|
|
+ font-size: 0.82rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-fullscreen {
|
|
|
+ color: #7fa7ce;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-body {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr 1fr 1fr;
|
|
|
+ gap: 0.6rem;
|
|
|
+ padding: 0.55rem 0.75rem 0.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-side-column {
|
|
|
+ min-height: 0;
|
|
|
+ display: grid;
|
|
|
+ grid-template-rows: minmax(6.5rem, auto) minmax(12.4rem, 1fr) minmax(12.4rem, 1fr);
|
|
|
+ gap: 0.6rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-panel,
|
|
|
+ .rr-map-panel {
|
|
|
+ position: relative;
|
|
|
+ min-height: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid rgba(50, 116, 193, 0.55);
|
|
|
+ background: linear-gradient(
|
|
|
+ 180deg,
|
|
|
+ rgba(7, 31, 70, 0.82),
|
|
|
+ rgba(3, 18, 41, 0.92)
|
|
|
+ ),
|
|
|
+ linear-gradient(90deg, rgba(39, 127, 255, 0.1), transparent);
|
|
|
+ box-shadow: inset 0 0 1rem rgba(0, 133, 255, 0.08),
|
|
|
+ 0 0 1rem rgba(0, 0, 0, 0.18);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-panel::before,
|
|
|
+ .rr-map-panel::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ inset: 0.25rem;
|
|
|
+ border: 1px solid rgba(98, 190, 255, 0.08);
|
|
|
+ pointer-events: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-panel {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-panel-title {
|
|
|
+ margin-bottom: 0;
|
|
|
+ min-height: 2rem;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 0.2rem 0.6rem 0.2rem 1.75rem;
|
|
|
+ font-family: '优设标题黑';
|
|
|
+ font-size: 1rem;
|
|
|
+ color: #d6ebff;
|
|
|
+ letter-spacing: 0.06rem;
|
|
|
+ position: relative;
|
|
|
+ background: linear-gradient(180deg, #004085, #003568);
|
|
|
+ border-bottom: 1px solid rgba(18, 76, 119, 0.9);
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-panel-title::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 0.6rem;
|
|
|
+ top: 50%;
|
|
|
+ width: 0.72rem;
|
|
|
+ height: 0.96rem;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ background-image: url('@/assets/renewable_icon_1.svg');
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ background-position: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-panel-sales {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-strip {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ flex: 1 1 auto;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-height: 0;
|
|
|
+ padding: 0.5rem 0.55rem;
|
|
|
+ overflow: hidden;
|
|
|
+ background: radial-gradient(
|
|
|
+ circle at center,
|
|
|
+ rgba(57, 137, 255, 0.06),
|
|
|
+ transparent 55%
|
|
|
+ ),
|
|
|
+ linear-gradient(180deg, rgba(5, 24, 66, 0.18), rgba(5, 24, 66, 0));
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-item {
|
|
|
+ position: relative;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: clamp(2rem, 2.6vw, 2.6rem) minmax(0, 1fr);
|
|
|
+ align-items: center;
|
|
|
+ flex: 1 1 0;
|
|
|
+ max-width: none;
|
|
|
+ min-width: 0;
|
|
|
+ gap: clamp(0.24rem, 0.35vw, 0.4rem);
|
|
|
+ padding: 0 0.15rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-divider {
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ top: 14%;
|
|
|
+ width: 1px;
|
|
|
+ height: 72%;
|
|
|
+ background: linear-gradient(
|
|
|
+ 180deg,
|
|
|
+ rgba(58, 126, 209, 0),
|
|
|
+ rgba(58, 126, 209, 0.45),
|
|
|
+ rgba(58, 126, 209, 0)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-box {
|
|
|
+ width: clamp(2rem, 2.6vw, 2.6rem);
|
|
|
+ flex: 0 0 clamp(2rem, 2.6vw, 2.6rem);
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-wrap {
|
|
|
+ position: relative;
|
|
|
+ width: clamp(2rem, 2.6vw, 2.6rem);
|
|
|
+ height: clamp(2rem, 2.6vw, 2.6rem);
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-ring {
|
|
|
+ position: absolute;
|
|
|
+ inset: 0;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 1px solid rgba(125, 194, 255, 0.45);
|
|
|
+ box-shadow: 0 0 0 0.15rem rgba(41, 118, 255, 0.18),
|
|
|
+ inset 0 0 0.7rem rgba(91, 176, 255, 0.22);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon {
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ top: 50%;
|
|
|
+ width: clamp(1.4rem, 1.8vw, 1.9rem);
|
|
|
+ height: clamp(1.4rem, 1.8vw, 1.9rem);
|
|
|
+ border-radius: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 1.5rem;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #f3fbff;
|
|
|
+ background: radial-gradient(
|
|
|
+ circle at 35% 30%,
|
|
|
+ rgba(124, 198, 255, 0.95),
|
|
|
+ rgba(43, 112, 232, 0.96) 70%
|
|
|
+ );
|
|
|
+ box-shadow: 0 0 1rem rgba(69, 153, 255, 0.42),
|
|
|
+ inset 0 -0.35rem 0.75rem rgba(9, 34, 86, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-img {
|
|
|
+ width: 60%;
|
|
|
+ height: 60%;
|
|
|
+ object-fit: contain;
|
|
|
+ filter: drop-shadow(0 0 0.35rem rgba(255, 255, 255, 0.16));
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-content {
|
|
|
+ min-width: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ justify-content: center;
|
|
|
+ overflow: hidden;
|
|
|
+ text-align: left;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-label {
|
|
|
+ color: #d9ebff;
|
|
|
+ font-size: clamp(0.48rem, 0.58vw, 0.64rem);
|
|
|
+ letter-spacing: 0.02rem;
|
|
|
+ line-height: 1.2;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ text-shadow: 0 0 0.35rem rgba(79, 171, 255, 0.18);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-main {
|
|
|
+ display: flex;
|
|
|
+ align-items: baseline;
|
|
|
+ justify-content: flex-start;
|
|
|
+ gap: 0.06rem;
|
|
|
+ margin-top: 0.08rem;
|
|
|
+ width: 100%;
|
|
|
+ min-width: 0;
|
|
|
+ flex-wrap: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-value {
|
|
|
+ color: #fff;
|
|
|
+ font-size: clamp(0.8rem, 1vw, 1.1rem);
|
|
|
+ line-height: 1;
|
|
|
+ font-weight: 700;
|
|
|
+ letter-spacing: 0.01rem;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-shadow: 0 0 0.55rem rgba(255, 255, 255, 0.12);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-unit {
|
|
|
+ color: rgba(255, 255, 255, 0.72);
|
|
|
+ font-size: clamp(0.36rem, 0.42vw, 0.48rem);
|
|
|
+ line-height: 1;
|
|
|
+ margin-bottom: 0.02rem;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ justify-content: flex-end;
|
|
|
+ gap: 0.02rem;
|
|
|
+ min-width: 0;
|
|
|
+ margin-left: 0.08rem;
|
|
|
+ padding-bottom: 0.02rem;
|
|
|
+ font-size: clamp(0.3rem, 0.36vw, 0.4rem);
|
|
|
+ white-space: nowrap;
|
|
|
+ flex-shrink: 1;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend-label {
|
|
|
+ color: #8db2db;
|
|
|
+ line-height: 1.2;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend-value {
|
|
|
+ font-size: clamp(0.32rem, 0.38vw, 0.42rem);
|
|
|
+ font-weight: 600;
|
|
|
+ line-height: 1.1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend.up .rr-summary-trend-value {
|
|
|
+ color: #2bd38e;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend.warn .rr-summary-trend-value {
|
|
|
+ color: #ff8a65;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-chart-panel,
|
|
|
+ .rr-mini-bar-panel,
|
|
|
+ .rr-fill-chart,
|
|
|
+ .rr-native-chart,
|
|
|
+ .rr-map-body {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-chart-panel {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 9rem;
|
|
|
+ padding: 0.55rem 0.7rem 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-mini-bar-panel {
|
|
|
+ height: 6.2rem;
|
|
|
+ margin-top: 0.2rem;
|
|
|
+ padding: 0 0.7rem 0.55rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-procurement-body {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ padding: 0.7rem 0.75rem 0.75rem;
|
|
|
+ gap: 0.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-procurement-pane {
|
|
|
+ min-width: 0;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-procurement-pane-area {
|
|
|
+ flex: 1.1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-procurement-pane-bar {
|
|
|
+ flex: 0.9;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-pane-caption {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 0.5rem;
|
|
|
+ min-height: 1.2rem;
|
|
|
+ padding: 0 0.15rem;
|
|
|
+ color: #cfe6ff;
|
|
|
+ font-size: 0.72rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-pane-caption-right {
|
|
|
+ justify-content: flex-start;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-pane-legend {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 0.8rem;
|
|
|
+ color: #d6ebff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-legend-item {
|
|
|
+ position: relative;
|
|
|
+ padding-left: 0.9rem;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-legend-item::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 50%;
|
|
|
+ width: 0.5rem;
|
|
|
+ height: 0.12rem;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ border-radius: 999px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-legend-item-blue::before {
|
|
|
+ background: #3c87ff;
|
|
|
+ box-shadow: 0 0 0.35rem rgba(60, 135, 255, 0.7);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-legend-item-gold::before {
|
|
|
+ background: #e5b15d;
|
|
|
+ box-shadow: 0 0 0.35rem rgba(229, 177, 93, 0.7);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-chart-panel-compact {
|
|
|
+ padding: 0.15rem 0 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-mini-bar-panel-fill {
|
|
|
+ flex: 1;
|
|
|
+ height: auto;
|
|
|
+ min-height: 0;
|
|
|
+ margin-top: 0;
|
|
|
+ padding: 0.15rem 0 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inventory-body {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ gap: 0.4rem;
|
|
|
+ padding: 0.5rem 0.6rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-left {
|
|
|
+ flex: 0 0 48%;
|
|
|
+ position: relative;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-right {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-chart-wrap {
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 8rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-center {
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ top: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ text-align: center;
|
|
|
+ pointer-events: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-center-value {
|
|
|
+ display: block;
|
|
|
+ color: #fff;
|
|
|
+ font-size: clamp(1.1rem, 1.5vw, 1.7rem);
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1;
|
|
|
+ text-shadow: 0 0 0.6rem rgba(60, 135, 255, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-center-label {
|
|
|
+ display: block;
|
|
|
+ margin-top: 0.15rem;
|
|
|
+ color: #b4d4f2;
|
|
|
+ font-size: clamp(0.58rem, 0.7vw, 0.78rem);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-trend-caption {
|
|
|
+ flex-shrink: 0;
|
|
|
+ color: #d4ebff;
|
|
|
+ font-size: clamp(0.68rem, 0.8vw, 0.88rem);
|
|
|
+ padding: 0.15rem 0.3rem 0;
|
|
|
+ line-height: 1.4;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-trend-chart {
|
|
|
+ position: relative;
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-panel {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-head {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ gap: 0.75rem;
|
|
|
+ min-height: 2.2rem;
|
|
|
+ padding: 0.35rem 0.75rem 0.2rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-tabs {
|
|
|
+ display: flex;
|
|
|
+ gap: 0.5rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-tab {
|
|
|
+ min-width: 3.6rem;
|
|
|
+ padding: 0.28rem 0.9rem;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 0.76rem;
|
|
|
+ color: #8fc0ff;
|
|
|
+ border: 1px solid rgba(61, 128, 206, 0.45);
|
|
|
+ background: rgba(5, 28, 62, 0.78);
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-tab.active {
|
|
|
+ color: #fff;
|
|
|
+ background: linear-gradient(180deg, #2d84ff, #1163fb);
|
|
|
+ box-shadow: 0 0 0.75rem rgba(17, 99, 251, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-summary {
|
|
|
+ display: flex;
|
|
|
+ gap: 0.45rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-summary-item {
|
|
|
+ min-width: 4.8rem;
|
|
|
+ padding: 0.3rem 0.55rem;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 0.72rem;
|
|
|
+ color: #a9d0ff;
|
|
|
+ background: rgba(6, 34, 82, 0.68);
|
|
|
+ border: 1px solid rgba(55, 120, 196, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-summary-item strong {
|
|
|
+ display: block;
|
|
|
+ margin-top: 0.15rem;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 1rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-body {
|
|
|
+ flex: 1;
|
|
|
+ padding: 0.2rem 0.35rem 0.35rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-quality-grid {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
+ gap: 0.65rem;
|
|
|
+ padding: 0.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-quality-card {
|
|
|
+ padding: 0.75rem;
|
|
|
+ border: 1px solid rgba(55, 120, 196, 0.4);
|
|
|
+ background: rgba(6, 34, 82, 0.6);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-quality-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 0.4rem;
|
|
|
+ color: #cfe6ff;
|
|
|
+ font-size: 0.82rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-quality-dot {
|
|
|
+ width: 0.5rem;
|
|
|
+ height: 0.5rem;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #49b2ff;
|
|
|
+ box-shadow: 0 0 0.4rem rgba(73, 178, 255, 0.9);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-quality-rate {
|
|
|
+ margin: 0.55rem 0 0.75rem;
|
|
|
+ font-size: 2rem;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-progress-row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-top: 0.3rem;
|
|
|
+ font-size: 0.72rem;
|
|
|
+ color: #9fc5ff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-progress-row strong {
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-progress-track {
|
|
|
+ height: 0.42rem;
|
|
|
+ margin-top: 0.22rem;
|
|
|
+ border-radius: 999px;
|
|
|
+ background: rgba(17, 54, 115, 0.85);
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-progress-fill {
|
|
|
+ display: block;
|
|
|
+ height: 100%;
|
|
|
+ border-radius: inherit;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-progress-fill-good {
|
|
|
+ background: linear-gradient(90deg, #21d07a, rgba(33, 208, 122, 0.2));
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-progress-fill-bad {
|
|
|
+ background: linear-gradient(90deg, #ff8a65, rgba(255, 138, 101, 0.2));
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-equipment-body {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
+ gap: 0.65rem;
|
|
|
+ padding: 0.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-equipment-gauge {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 0.45rem;
|
|
|
+ min-height: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-gauge-wrap {
|
|
|
+ position: relative;
|
|
|
+ flex: 1;
|
|
|
+ min-height: 7rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-equipment-list {
|
|
|
+ list-style: none;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-equipment-list li {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 0.6rem;
|
|
|
+ padding: 0.38rem 0.48rem;
|
|
|
+ margin-top: 0.28rem;
|
|
|
+ font-size: 0.74rem;
|
|
|
+ color: #b9d7ef;
|
|
|
+ background: rgba(8, 35, 79, 0.66);
|
|
|
+ border: 1px solid rgba(39, 99, 170, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-equipment-list strong {
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 1600px) {
|
|
|
+ .rr-side-column {
|
|
|
+ grid-template-rows: minmax(6rem, auto) minmax(11rem, 1fr) minmax(11rem, 1fr);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-strip {
|
|
|
+ padding: 0.4rem 0.35rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-item {
|
|
|
+ gap: 0.2rem;
|
|
|
+ padding: 0 0.1rem;
|
|
|
+ grid-template-columns: 1.9rem minmax(0, 1fr);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-box {
|
|
|
+ width: 1.9rem;
|
|
|
+ flex: 0 0 1.9rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-wrap {
|
|
|
+ width: 1.9rem;
|
|
|
+ height: 1.9rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon {
|
|
|
+ width: 1.35rem;
|
|
|
+ height: 1.35rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-label {
|
|
|
+ font-size: 0.42rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-value {
|
|
|
+ font-size: 0.72rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-unit {
|
|
|
+ font-size: 0.32rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend {
|
|
|
+ font-size: 0.28rem;
|
|
|
+ margin-left: 0.06rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend-value {
|
|
|
+ font-size: 0.3rem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (min-width: 1800px) {
|
|
|
+ .rr-summary-strip {
|
|
|
+ padding: 0.55rem 0.6rem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 1280px) {
|
|
|
+ .rr-summary-strip {
|
|
|
+ padding: 0.35rem 0.3rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-item {
|
|
|
+ gap: 0.16rem;
|
|
|
+ padding: 0 0.06rem;
|
|
|
+ grid-template-columns: 1.75rem minmax(0, 1fr);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-box {
|
|
|
+ width: 1.75rem;
|
|
|
+ flex: 0 0 1.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-wrap {
|
|
|
+ width: 1.75rem;
|
|
|
+ height: 1.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon {
|
|
|
+ width: 1.2rem;
|
|
|
+ height: 1.2rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-label {
|
|
|
+ font-size: 0.38rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-value {
|
|
|
+ font-size: 0.65rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-unit {
|
|
|
+ font-size: 0.28rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend {
|
|
|
+ font-size: 0.26rem;
|
|
|
+ margin-left: 0.05rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend-value {
|
|
|
+ font-size: 0.28rem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 1366px) {
|
|
|
+ .rr-title {
|
|
|
+ min-width: 27rem;
|
|
|
+ height: 1.7rem;
|
|
|
+ padding: 0 3.6rem 0.02rem;
|
|
|
+ letter-spacing: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-title::before {
|
|
|
+ width: calc(100% + 2.2rem);
|
|
|
+ height: 0.72rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-title::after {
|
|
|
+ width: calc(100% - 3.4rem);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-body {
|
|
|
+ grid-template-columns: 1fr;
|
|
|
+ grid-template-rows: auto auto auto;
|
|
|
+ overflow: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-side-column {
|
|
|
+ grid-template-columns: 1fr;
|
|
|
+ grid-template-rows: repeat(3, minmax(12rem, auto));
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-panel {
|
|
|
+ min-height: 28rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-map-head {
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-procurement-body,
|
|
|
+ .rr-inventory-body {
|
|
|
+ padding: 0.4rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inventory-body {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-left {
|
|
|
+ flex: 0 0 auto;
|
|
|
+ width: 100%;
|
|
|
+ min-height: 12rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inv-right {
|
|
|
+ min-height: 10rem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 520px) {
|
|
|
+ .rr-title {
|
|
|
+ min-width: 15.8rem;
|
|
|
+ height: 1.46rem;
|
|
|
+ padding: 0 1.8rem 0;
|
|
|
+ letter-spacing: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-title::before {
|
|
|
+ width: calc(100% + 1.2rem);
|
|
|
+ height: 0.56rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-title::after {
|
|
|
+ width: calc(100% - 2.6rem);
|
|
|
+ bottom: 0.04rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-strip {
|
|
|
+ justify-content: flex-start;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 0.6rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-item {
|
|
|
+ padding: 0;
|
|
|
+ max-width: none;
|
|
|
+ grid-template-columns: 1.75rem minmax(0, 1fr);
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-box {
|
|
|
+ width: 1.75rem;
|
|
|
+ flex: 0 0 1.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon-wrap {
|
|
|
+ width: 1.75rem;
|
|
|
+ height: 1.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-icon {
|
|
|
+ width: 1.2rem;
|
|
|
+ height: 1.2rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-label {
|
|
|
+ font-size: 0.42rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-value {
|
|
|
+ font-size: 0.7rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-unit {
|
|
|
+ font-size: 0.3rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-divider {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend {
|
|
|
+ margin-left: 0.06rem;
|
|
|
+ font-size: 0.28rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-summary-trend-value {
|
|
|
+ font-size: 0.3rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-procurement-body {
|
|
|
+ padding: 0.6rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .rr-inventory-body {
|
|
|
+ padding: 0.4rem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|
|
|
+
|
|
|
+<style>
|
|
|
+ .el-icon-_screen-full,
|
|
|
+ .el-icon-_screen-restore {
|
|
|
+ font-size: 1.2rem;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s;
|
|
|
+ color: #7fa7ce;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-icon-_screen-full:hover,
|
|
|
+ .el-icon-_screen-restore:hover {
|
|
|
+ color: #fff;
|
|
|
+ transform: scale(1.1);
|
|
|
+ }
|
|
|
+</style>
|