|
@@ -1,860 +1,703 @@
|
|
|
-<!DOCTYPE html>
|
|
|
|
|
<template>
|
|
<template>
|
|
|
- <div style="display: flex; justify-content: center; align-items: center; ">
|
|
|
|
|
- <iframe src="../../../public/html/resourceStatistics.html" style="width: 100%; height: 100vh"></iframe>
|
|
|
|
|
|
|
+ <div class="rresource-statistics">
|
|
|
|
|
+ <div class="container">
|
|
|
|
|
+ <h1>资源库统计分析</h1>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 摘要信息 -->
|
|
|
|
|
+ <div class="summary-row">
|
|
|
|
|
+ <div class="summary-box">
|
|
|
|
|
+ <h3>总资源数</h3>
|
|
|
|
|
+ <p>{{ summaryData.totalResources }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="summary-box">
|
|
|
|
|
+ <h3>总存储空间</h3>
|
|
|
|
|
+ <p>{{ summaryData.totalStorage }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="summary-box">
|
|
|
|
|
+ <h3>总观看人数</h3>
|
|
|
|
|
+ <p>{{ summaryData.totalViews }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="summary-box">
|
|
|
|
|
+ <h3>总收藏人数</h3>
|
|
|
|
|
+ <p>{{ summaryData.totalFavorites }}</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 存储空间信息 -->
|
|
|
|
|
+ <div class="storage-info">
|
|
|
|
|
+ <h3>资源库存储空间使用情况</h3>
|
|
|
|
|
+ <p>当前资源库总容量:10 TB | 已使用:4.2 TB | 使用率:42%</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 筛选器 -->
|
|
|
|
|
+ <div class="filters">
|
|
|
|
|
+ <label>筛选院系:</label>
|
|
|
|
|
+ <a-select
|
|
|
|
|
+ v-model:value="filters.department"
|
|
|
|
|
+ style="width: 150px; margin-right: 20px"
|
|
|
|
|
+ @change="handleDepartmentChange"
|
|
|
|
|
+ >
|
|
|
|
|
+ <a-select-option value="all">全部院系</a-select-option>
|
|
|
|
|
+ <a-select-option value="aviation">航空学院</a-select-option>
|
|
|
|
|
+ <a-select-option value="military">军事管理系</a-select-option>
|
|
|
|
|
+ <a-select-option value="politics">政治工作部</a-select-option>
|
|
|
|
|
+ <a-select-option value="maintenance">地面维修中心</a-select-option>
|
|
|
|
|
+ <a-select-option value="other">其他部门</a-select-option>
|
|
|
|
|
+ </a-select>
|
|
|
|
|
+
|
|
|
|
|
+ <label>时间范围:</label>
|
|
|
|
|
+ <a-select v-model:value="filters.timeRange" style="width: 120px" @change="handleTimeChange">
|
|
|
|
|
+ <a-select-option value="all">全部时间</a-select-option>
|
|
|
|
|
+ <a-select-option value="30">最近30天</a-select-option>
|
|
|
|
|
+ <a-select-option value="90">最近90天</a-select-option>
|
|
|
|
|
+ <a-select-option value="180">最近180天</a-select-option>
|
|
|
|
|
+ <a-select-option value="365">最近1年</a-select-option>
|
|
|
|
|
+ </a-select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 资源类型分布 -->
|
|
|
|
|
+ <div class="chart-container">
|
|
|
|
|
+ <h2>资源类型分布</h2>
|
|
|
|
|
+ <div class="chart-row">
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="typeChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="departmentChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 资源可见性与热度 -->
|
|
|
|
|
+ <div class="chart-container">
|
|
|
|
|
+ <h2>资源可见性与热度</h2>
|
|
|
|
|
+ <div class="chart-row">
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="visibilityChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="hotnessChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 文件格式分布 -->
|
|
|
|
|
+ <div class="chart-container">
|
|
|
|
|
+ <h2>文件格式分布</h2>
|
|
|
|
|
+ <div class="chart-row">
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="formatChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="storageChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 资源使用情况分析 -->
|
|
|
|
|
+ <div class="chart-container">
|
|
|
|
|
+ <h2>资源使用情况分析</h2>
|
|
|
|
|
+ <div class="chart-row">
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="viewsChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="chart-col">
|
|
|
|
|
+ <div ref="engagementChartRef" class="chart"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 时间趋势分析 -->
|
|
|
|
|
+ <div class="chart-container">
|
|
|
|
|
+ <h2>上传与访问时间趋势</h2>
|
|
|
|
|
+ <div ref="trendChartRef" class="chart-full"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <footer>
|
|
|
|
|
+ <p>数据更新时间: {{ updateTime }} | 资源库统计分析系统</p>
|
|
|
|
|
+ </footer>
|
|
|
</div>
|
|
</div>
|
|
|
-<!-- <div class="container">-->
|
|
|
|
|
-<!-- <h1>资源库统计分析</h1>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 摘要信息 –>-->
|
|
|
|
|
-<!-- <div class="row">-->
|
|
|
|
|
-<!-- <div class="col summary-box">-->
|
|
|
|
|
-<!-- <h3>总资源数</h3>-->
|
|
|
|
|
-<!-- <p id="total-resources">1,247</p>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- <div class="col summary-box">-->
|
|
|
|
|
-<!-- <h3>总存储空间</h3>-->
|
|
|
|
|
-<!-- <p id="total-storage">4.2 TB</p>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- <div class="col summary-box">-->
|
|
|
|
|
-<!-- <h3>总观看人数</h3>-->
|
|
|
|
|
-<!-- <p id="total-views">89,532</p>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- <div class="col summary-box">-->
|
|
|
|
|
-<!-- <h3>总收藏人数</h3>-->
|
|
|
|
|
-<!-- <p id="total-favorites">15,678</p>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 存储空间信息 –>-->
|
|
|
|
|
-<!-- <div class="storage-info">-->
|
|
|
|
|
-<!-- <h3>资源库存储空间使用情况</h3>-->
|
|
|
|
|
-<!-- <p>当前资源库总容量:10 TB | 已使用:4.2 TB | 使用率:42%</p>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 筛选器 –>-->
|
|
|
|
|
-<!-- <div class="filters">-->
|
|
|
|
|
-<!-- <label for="department-filter">筛选院系:</label>-->
|
|
|
|
|
-<!-- <select id="department-filter">-->
|
|
|
|
|
-<!-- <option value="all">全部院系</option>-->
|
|
|
|
|
-<!-- <option value="aviation">航空学院</option>-->
|
|
|
|
|
-<!-- <option value="military">军事管理系</option>-->
|
|
|
|
|
-<!-- <option value="politics">政治工作部</option>-->
|
|
|
|
|
-<!-- <option value="maintenance">地面维修中心</option>-->
|
|
|
|
|
-<!-- <option value="other">其他部门</option>-->
|
|
|
|
|
-<!-- </select>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <label for="time-filter">时间范围:</label>-->
|
|
|
|
|
-<!-- <select id="time-filter">-->
|
|
|
|
|
-<!-- <option value="all">全部时间</option>-->
|
|
|
|
|
-<!-- <option value="30">最近30天</option>-->
|
|
|
|
|
-<!-- <option value="90">最近90天</option>-->
|
|
|
|
|
-<!-- <option value="180">最近180天</option>-->
|
|
|
|
|
-<!-- <option value="365">最近1年</option>-->
|
|
|
|
|
-<!-- </select>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 资源类型分布 –>-->
|
|
|
|
|
-<!-- <div class="chart-container">-->
|
|
|
|
|
-<!-- <h2>资源类型分布</h2>-->
|
|
|
|
|
-<!-- <div class="row">-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <div ref="typeChart" style="width: 100%; height: 500px;"></div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <div ref="departmentChart" style="width: 100%; height: 500px;"></div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 资源可见性与热度 –>-->
|
|
|
|
|
-<!-- <div class="chart-container">-->
|
|
|
|
|
-<!-- <h2>资源可见性与热度</h2>-->
|
|
|
|
|
-<!-- <div class="row">-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <div ref="visibilityChart" style="width: 100%; height: 500px;"></div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <div ref="hotnessChart" style="width: 100%; height: 500px;"></div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 文件格式分布 –>-->
|
|
|
|
|
-<!-- <div class="chart-container">-->
|
|
|
|
|
-<!-- <h2>文件格式分布</h2>-->
|
|
|
|
|
-<!-- <div class="row">-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <canvas id="formatChart"></canvas>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <canvas id="storageChart"></canvas>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 资源使用情况分析 –>-->
|
|
|
|
|
-<!-- <div class="chart-container">-->
|
|
|
|
|
-<!-- <h2>资源使用情况分析</h2>-->
|
|
|
|
|
-<!-- <div class="row">-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <canvas id="viewsChart"></canvas>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- <div class="col">-->
|
|
|
|
|
-<!-- <canvas id="engagementChart"></canvas>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <!– 时间趋势分析 –>-->
|
|
|
|
|
-<!-- <div class="chart-container">-->
|
|
|
|
|
-<!-- <h2>上传与访问时间趋势</h2>-->
|
|
|
|
|
-<!-- <canvas id="trendChart"></canvas>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-<!-- <footer>-->
|
|
|
|
|
-<!-- <p>数据更新时间: 2025年8月18日 | 资源库统计分析系统</p>-->
|
|
|
|
|
-<!-- </footer>-->
|
|
|
|
|
-<!-- </div>-->
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+ </div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
+
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-// 模拟数据 - 包含文件数量和存储空间数据
|
|
|
|
|
-import * as echarts from "echarts";
|
|
|
|
|
-
|
|
|
|
|
-const typeChart = ref(null)
|
|
|
|
|
-let typeChartInstance = null
|
|
|
|
|
-
|
|
|
|
|
-const departmentChart = ref(null)
|
|
|
|
|
-let departmentChartInstance = null
|
|
|
|
|
-
|
|
|
|
|
-const visibilityChart = ref(null)
|
|
|
|
|
-let visibilityChartInstance = null
|
|
|
|
|
-
|
|
|
|
|
-const hotnessChart = ref(null)
|
|
|
|
|
-let hotnessChartInstance = null
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-// const visibilityChart = ref(null)
|
|
|
|
|
-// let visibilityChartInstance = null
|
|
|
|
|
-//
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-const mockData = {
|
|
|
|
|
- // 资源类型数据
|
|
|
|
|
- types: ['航空教学', '部队管理', '政治工作', '地面维修', '其他'],
|
|
|
|
|
- typeCounts: [345, 278, 192, 231, 201],
|
|
|
|
|
- typeStorage: [1.2, 0.8, 0.6, 0.9, 0.7], // TB
|
|
|
|
|
-
|
|
|
|
|
- // 院系数据
|
|
|
|
|
- departments: ['航空学院', '军事管理系', '政治工作部', '地面维修中心', '其他部门'],
|
|
|
|
|
- departmentCounts: [412, 289, 176, 223, 147],
|
|
|
|
|
- departmentStorage: [1.5, 0.9, 0.5, 0.8, 0.5], // TB
|
|
|
|
|
-
|
|
|
|
|
- // 可见性数据
|
|
|
|
|
- visibility: ['公开', '非公开'],
|
|
|
|
|
- visibilityCounts: [987, 260],
|
|
|
|
|
-
|
|
|
|
|
- // 热度数据
|
|
|
|
|
- hotness: ['热门', '非热门'],
|
|
|
|
|
- hotnessCounts: [312, 935],
|
|
|
|
|
- recommended: ['已推荐', '未推荐'],
|
|
|
|
|
- recommendedCounts: [187, 1060],
|
|
|
|
|
-
|
|
|
|
|
- // 文件格式数据 - 包含文件数量和平均文件大小
|
|
|
|
|
- formats: ['mp4', 'pdf', 'docx', 'pptx', 'xlsx', 'jpg', 'avi', 'wmv', 'mkv', 'other'],
|
|
|
|
|
- formatCounts: [320, 312, 135, 189, 98, 167, 56, 67, 41, 163],
|
|
|
|
|
- formatStorage: [2.1, 0.3, 0.15, 0.25, 0.1, 0.08, 0.4, 0.3, 0.2, 0.12], // TB
|
|
|
|
|
- formatAvgSize: ['6.6GB', '960MB', '1.1MB', '1.3MB', '1.0MB', '500KB', '7.1GB', '4.5GB', '4.9GB', '750KB'],
|
|
|
|
|
-
|
|
|
|
|
- // 用户参与度数据
|
|
|
|
|
- engagement: ['观看', '收藏', '分享'],
|
|
|
|
|
- engagementCounts: [89532, 15678, 7892],
|
|
|
|
|
-
|
|
|
|
|
- // 时间趋势数据
|
|
|
|
|
- trendLabels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月'],
|
|
|
|
|
- uploadTrend: [120, 95, 140, 110, 135, 150, 130, 80],
|
|
|
|
|
- viewTrend: [8500, 7200, 9800, 9200, 10500, 11200, 10800, 12300]
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-//
|
|
|
|
|
-// // 可见性分析
|
|
|
|
|
-// new Chart(document.getElementById('visibilityChart'), {
|
|
|
|
|
-// type: 'bar',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.visibility,
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// label: '资源数量',
|
|
|
|
|
-// data: mockData.visibilityCounts,
|
|
|
|
|
-// backgroundColor: [
|
|
|
|
|
-// 'rgba(46, 204, 113, 0.8)',
|
|
|
|
|
-// 'rgba(231, 76, 60, 0.8)'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderColor: [
|
|
|
|
|
-// '#2ecc71', '#e74c3c'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderWidth: 1
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// scales: {
|
|
|
|
|
-// y: {
|
|
|
|
|
-// beginAtZero: true,
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '资源数量'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// },
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '资源公开情况'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-//
|
|
|
|
|
-
|
|
|
|
|
-// // 文件数量分布 - 水平条形图
|
|
|
|
|
-// new Chart(document.getElementById('formatChart'), {
|
|
|
|
|
-// type: 'bar',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.formats,
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// label: '文件数量',
|
|
|
|
|
-// data: mockData.formatCounts,
|
|
|
|
|
-// backgroundColor: 'rgba(52, 73, 94, 0.7)',
|
|
|
|
|
-// borderColor: 'rgba(52, 73, 94, 1)',
|
|
|
|
|
-// borderWidth: 1
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// indexAxis: 'y',
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// scales: {
|
|
|
|
|
-// x: {
|
|
|
|
|
-// beginAtZero: true,
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '文件数量'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// },
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '不同文件格式的数量分布'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-//
|
|
|
|
|
-// // 存储空间占用分布 - 饼图
|
|
|
|
|
-// new Chart(document.getElementById('storageChart'), {
|
|
|
|
|
-// type: 'pie',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.formats,
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// label: '存储空间 (TB)',
|
|
|
|
|
-// data: mockData.formatStorage,
|
|
|
|
|
-// backgroundColor: [
|
|
|
|
|
-// '#e74c3c', '#3498db', '#2ecc71', '#f39c12',
|
|
|
|
|
-// '#9b59b6', '#1abc9c', '#34495e', '#d35400',
|
|
|
|
|
-// '#8e44ad', '#7f8c8d'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderWidth: 2
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '不同文件格式的存储空间占用'
|
|
|
|
|
-// },
|
|
|
|
|
-// tooltip: {
|
|
|
|
|
-// callbacks: {
|
|
|
|
|
-// label: function(context) {
|
|
|
|
|
-// const label = context.label || '';
|
|
|
|
|
-// const value = context.parsed;
|
|
|
|
|
-// const count = mockData.formatCounts[context.dataIndex];
|
|
|
|
|
-// const avgSize = mockData.formatAvgSize[context.dataIndex];
|
|
|
|
|
-// return [
|
|
|
|
|
-// `${label}: ${value} TB`,
|
|
|
|
|
-// `文件数量: ${count}`,
|
|
|
|
|
-// `平均大小: ${avgSize}`
|
|
|
|
|
-// ];
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-//
|
|
|
|
|
-// // 观看情况分析
|
|
|
|
|
-// new Chart(document.getElementById('viewsChart'), {
|
|
|
|
|
-// type: 'bar',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.types,
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// label: '平均观看人数',
|
|
|
|
|
-// data: [1250, 890, 620, 980, 450],
|
|
|
|
|
-// backgroundColor: 'rgba(41, 128, 185, 0.7)',
|
|
|
|
|
-// borderColor: 'rgba(41, 128, 185, 1)',
|
|
|
|
|
-// borderWidth: 1
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// scales: {
|
|
|
|
|
-// y: {
|
|
|
|
|
-// beginAtZero: true,
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '平均观看人数'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// },
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '各类资源平均观看人数'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-//
|
|
|
|
|
-// // 用户参与度分析
|
|
|
|
|
-// new Chart(document.getElementById('engagementChart'), {
|
|
|
|
|
-// type: 'bar',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: ['观看人数', '收藏人数', '分享次数'],
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// label: '用户参与度',
|
|
|
|
|
-// data: mockData.engagementCounts,
|
|
|
|
|
-// backgroundColor: 'rgba(155, 89, 182, 0.7)',
|
|
|
|
|
-// borderColor: 'rgba(155, 89, 182, 1)',
|
|
|
|
|
-// borderWidth: 1
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// scales: {
|
|
|
|
|
-// y: {
|
|
|
|
|
-// beginAtZero: true,
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '数量'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// },
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '资源使用情况统计'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-//
|
|
|
|
|
-// // 时间趋势分析
|
|
|
|
|
-// new Chart(document.getElementById('trendChart'), {
|
|
|
|
|
-// type: 'line',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.trendLabels,
|
|
|
|
|
-// datasets: [
|
|
|
|
|
-// {
|
|
|
|
|
-// label: '资源上传数量',
|
|
|
|
|
-// data: mockData.uploadTrend,
|
|
|
|
|
-// borderColor: '#3498db',
|
|
|
|
|
-// backgroundColor: 'rgba(52, 152, 219, 0.1)',
|
|
|
|
|
-// fill: true,
|
|
|
|
|
-// tension: 0.4
|
|
|
|
|
-// },
|
|
|
|
|
-// {
|
|
|
|
|
-// label: '资源观看人数',
|
|
|
|
|
-// data: mockData.viewTrend,
|
|
|
|
|
-// borderColor: '#e74c3c',
|
|
|
|
|
-// backgroundColor: 'rgba(231, 76, 60, 0.1)',
|
|
|
|
|
-// fill: true,
|
|
|
|
|
-// tension: 0.4
|
|
|
|
|
-// }
|
|
|
|
|
-// ]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// interaction: {
|
|
|
|
|
-// mode: 'index',
|
|
|
|
|
-// intersect: false
|
|
|
|
|
-// },
|
|
|
|
|
-// scales: {
|
|
|
|
|
-// y: {
|
|
|
|
|
-// beginAtZero: true,
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '数量'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// },
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '资源上传与访问趋势 (2025年)'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-
|
|
|
|
|
-const initHotnessChart = () => {
|
|
|
|
|
- hotnessChartInstance = echarts.init(hotnessChart.value);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- let option = {
|
|
|
|
|
- title: {
|
|
|
|
|
- text: '资源热度分析',
|
|
|
|
|
- left: 'center'
|
|
|
|
|
- },
|
|
|
|
|
- xAxis: {
|
|
|
|
|
- type: 'category',
|
|
|
|
|
- data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
|
|
|
- },
|
|
|
|
|
- yAxis: {
|
|
|
|
|
- type: 'value'
|
|
|
|
|
- },
|
|
|
|
|
- series: [
|
|
|
|
|
- {
|
|
|
|
|
- data: [120, 200, 150, 80, 70, 110, 130],
|
|
|
|
|
- type: 'bar'
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
- };
|
|
|
|
|
- option.series[0].data = []
|
|
|
|
|
- option.xAxis.data = []
|
|
|
|
|
- let backgroundColors = [
|
|
|
|
|
- 'rgba(255, 99, 132, 0.8)',
|
|
|
|
|
- 'rgba(54, 162, 235, 0.8)',
|
|
|
|
|
- 'rgba(255, 206, 86, 0.8)',
|
|
|
|
|
- 'rgba(75, 192, 192, 0.8)',
|
|
|
|
|
- 'rgba(153, 102, 255, 0.8)']
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- for (let i = 0; i < mockData.visibility.length; i++) {
|
|
|
|
|
- option.series[0].data.push({
|
|
|
|
|
- value: mockData.visibilityCounts[i],
|
|
|
|
|
- name : mockData.visibility[i],
|
|
|
|
|
- itemStyle: {
|
|
|
|
|
- color: backgroundColors[i],
|
|
|
|
|
- },
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ import { ref, onMounted, nextTick } from 'vue'
|
|
|
|
|
+ import * as echarts from 'echarts'
|
|
|
|
|
+
|
|
|
|
|
+ // 响应式数据
|
|
|
|
|
+ const summaryData = ref({
|
|
|
|
|
+ totalResources: '1,247',
|
|
|
|
|
+ totalStorage: '4.2 TB',
|
|
|
|
|
+ totalViews: '89,532',
|
|
|
|
|
+ totalFavorites: '15,678'
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- option.xAxis.data.push(mockData.visibility[i])
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const filters = ref({
|
|
|
|
|
+ department: 'all',
|
|
|
|
|
+ timeRange: 'all'
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
|
|
+ const updateTime = ref('2025年8月19日')
|
|
|
|
|
+
|
|
|
|
|
+ // 图表引用
|
|
|
|
|
+ const typeChartRef = ref()
|
|
|
|
|
+ const departmentChartRef = ref()
|
|
|
|
|
+ const visibilityChartRef = ref()
|
|
|
|
|
+ const hotnessChartRef = ref()
|
|
|
|
|
+ const formatChartRef = ref()
|
|
|
|
|
+ const storageChartRef = ref()
|
|
|
|
|
+ const viewsChartRef = ref()
|
|
|
|
|
+ const engagementChartRef = ref()
|
|
|
|
|
+ const trendChartRef = ref()
|
|
|
|
|
+
|
|
|
|
|
+ // 模拟数据
|
|
|
|
|
+ const mockData = {
|
|
|
|
|
+ types: ['航空教学', '部队管理', '政治工作', '地面维修', '其他'],
|
|
|
|
|
+ typeCounts: [345, 278, 192, 231, 201],
|
|
|
|
|
+ typeStorage: [1.2, 0.8, 0.6, 0.9, 0.7],
|
|
|
|
|
+
|
|
|
|
|
+ departments: ['航空学院', '军事管理系', '政治工作部', '地面维修中心', '其他部门'],
|
|
|
|
|
+ departmentCounts: [412, 289, 176, 223, 147],
|
|
|
|
|
+ departmentStorage: [1.5, 0.9, 0.5, 0.8, 0.5],
|
|
|
|
|
+
|
|
|
|
|
+ visibility: ['公开', '非公开'],
|
|
|
|
|
+ visibilityCounts: [987, 260],
|
|
|
|
|
+
|
|
|
|
|
+ hotness: ['热门', '非热门'],
|
|
|
|
|
+ hotnessCounts: [312, 935],
|
|
|
|
|
+ recommended: ['已推荐', '未推荐'],
|
|
|
|
|
+ recommendedCounts: [187, 1060],
|
|
|
|
|
+
|
|
|
|
|
+ formats: ['mp4', 'pdf', 'docx', 'pptx', 'xlsx', 'jpg', 'avi', 'wmv', 'mkv', 'other'],
|
|
|
|
|
+ formatCounts: [320, 312, 135, 189, 98, 167, 56, 67, 41, 163],
|
|
|
|
|
+ formatStorage: [2.1, 0.3, 0.15, 0.25, 0.1, 0.08, 0.4, 0.3, 0.2, 0.12],
|
|
|
|
|
+ formatAvgSize: ['6.6GB', '960MB', '1.1MB', '1.3MB', '1.0MB', '500KB', '7.1GB', '4.5GB', '4.9GB', '750KB'],
|
|
|
|
|
+
|
|
|
|
|
+ engagement: ['观看', '收藏', '分享'],
|
|
|
|
|
+ engagementCounts: [89532, 15678, 7892],
|
|
|
|
|
+
|
|
|
|
|
+ trendLabels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月'],
|
|
|
|
|
+ uploadTrend: [120, 95, 140, 110, 135, 150, 130, 80],
|
|
|
|
|
+ viewTrend: [8500, 7200, 9800, 9200, 10500, 11200, 10800, 12300]
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- hotnessChartInstance.setOption(option);
|
|
|
|
|
-
|
|
|
|
|
-// // 热度分析
|
|
|
|
|
-// new Chart(document.getElementById('hotnessChart'), {
|
|
|
|
|
-// type: 'polarArea',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: ['热门资源', '推荐资源', '热门且推荐'],
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// label: '资源数量',
|
|
|
|
|
-// data: [312, 187, 89],
|
|
|
|
|
-// backgroundColor: [
|
|
|
|
|
-// 'rgba(231, 76, 60, 0.7)',
|
|
|
|
|
-// 'rgba(52, 152, 219, 0.7)',
|
|
|
|
|
-// 'rgba(155, 89, 182, 0.7)'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderColor: [
|
|
|
|
|
-// 'rgba(231, 76, 60, 1)',
|
|
|
|
|
-// 'rgba(52, 152, 219, 1)',
|
|
|
|
|
-// 'rgba(155, 89, 182, 1)'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderWidth: 1
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '资源热度分析'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-//
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-const initTypeChart = () => {
|
|
|
|
|
- typeChartInstance = echarts.init(typeChart.value);
|
|
|
|
|
- let option = {
|
|
|
|
|
- title: {
|
|
|
|
|
- text: '按资源类型分类 (数量)',
|
|
|
|
|
- left: 'center'
|
|
|
|
|
- },
|
|
|
|
|
- tooltip: {
|
|
|
|
|
- trigger: 'item'
|
|
|
|
|
- },
|
|
|
|
|
- legend: {
|
|
|
|
|
- bottom: 10,
|
|
|
|
|
- },
|
|
|
|
|
- series: [
|
|
|
|
|
- {
|
|
|
|
|
- type: 'pie',
|
|
|
|
|
- radius: '50%',
|
|
|
|
|
- data: [
|
|
|
|
|
- {value: 1048, name: 'Search Engine'},
|
|
|
|
|
- {value: 735, name: 'Direct'},
|
|
|
|
|
- {value: 580, name: 'Email'},
|
|
|
|
|
- {value: 484, name: 'Union Ads'},
|
|
|
|
|
- {value: 300, name: 'Video Ads'}
|
|
|
|
|
- ],
|
|
|
|
|
- emphasis: {
|
|
|
|
|
- itemStyle: {
|
|
|
|
|
- shadowBlur: 10,
|
|
|
|
|
- shadowOffsetX: 0,
|
|
|
|
|
- shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
|
|
+ // 初始化图表
|
|
|
|
|
+ const initCharts = () => {
|
|
|
|
|
+ // 资源类型分布图
|
|
|
|
|
+ if (typeChartRef.value) {
|
|
|
|
|
+ const typeChart = echarts.init(typeChartRef.value)
|
|
|
|
|
+ typeChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '按资源类型分类 (数量)',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'item'
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ bottom: '5%',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: ['40%', '70%'],
|
|
|
|
|
+ data: mockData.types.map((name, index) => ({
|
|
|
|
|
+ value: mockData.typeCounts[index],
|
|
|
|
|
+ name
|
|
|
|
|
+ })),
|
|
|
|
|
+ emphasis: {
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ shadowBlur: 10,
|
|
|
|
|
+ shadowOffsetX: 0,
|
|
|
|
|
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 院系分布图
|
|
|
|
|
+ if (departmentChartRef.value) {
|
|
|
|
|
+ const departmentChart = echarts.init(departmentChartRef.value)
|
|
|
|
|
+ departmentChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '按院系分布 (数量)',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'item'
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ bottom: '5%',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: ['50%', '70%'],
|
|
|
|
|
+ avoidLabelOverlap: false,
|
|
|
|
|
+ data: mockData.departments.map((name, index) => ({
|
|
|
|
|
+ value: mockData.departmentCounts[index],
|
|
|
|
|
+ name
|
|
|
|
|
+ }))
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 可见性分析
|
|
|
|
|
+ if (visibilityChartRef.value) {
|
|
|
|
|
+ const visibilityChart = echarts.init(visibilityChartRef.value)
|
|
|
|
|
+ visibilityChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '资源公开情况',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ axisPointer: {
|
|
|
|
|
+ type: 'shadow'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: mockData.visibility
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '资源数量'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '资源数量',
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: mockData.visibilityCounts,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: function (params) {
|
|
|
|
|
+ const colors = ['#2ecc71', '#e74c3c']
|
|
|
|
|
+ return colors[params.dataIndex]
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 热度分析
|
|
|
|
|
+ if (hotnessChartRef.value) {
|
|
|
|
|
+ const hotnessChart = echarts.init(hotnessChartRef.value)
|
|
|
|
|
+ hotnessChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '资源热度分析',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'item'
|
|
|
|
|
+ },
|
|
|
|
|
+ angleAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: ['热门资源', '推荐资源', '热门且推荐']
|
|
|
|
|
+ },
|
|
|
|
|
+ radiusAxis: {},
|
|
|
|
|
+ polar: {},
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: [312, 187, 89],
|
|
|
|
|
+ coordinateSystem: 'polar',
|
|
|
|
|
+ name: '资源数量',
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: function (params) {
|
|
|
|
|
+ const colors = ['#e74c3c', '#3498db', '#9b59b6']
|
|
|
|
|
+ return colors[params.dataIndex]
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 文件格式数量分布
|
|
|
|
|
+ if (formatChartRef.value) {
|
|
|
|
|
+ const formatChart = echarts.init(formatChartRef.value)
|
|
|
|
|
+ formatChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '不同文件格式的数量分布',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ axisPointer: {
|
|
|
|
|
+ type: 'shadow'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ grid: {
|
|
|
|
|
+ left: '3%',
|
|
|
|
|
+ right: '4%',
|
|
|
|
|
+ bottom: '3%',
|
|
|
|
|
+ containLabel: true
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '文件数量'
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: mockData.formats
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '文件数量',
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: mockData.formatCounts,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#34495e'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 存储空间占用分布
|
|
|
|
|
+ if (storageChartRef.value) {
|
|
|
|
|
+ const storageChart = echarts.init(storageChartRef.value)
|
|
|
|
|
+ storageChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '不同文件格式的存储空间占用',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'item',
|
|
|
|
|
+ formatter: function (params) {
|
|
|
|
|
+ const index = params.dataIndex
|
|
|
|
|
+ return `${params.name}: ${params.value} TB<br/>文件数量: ${mockData.formatCounts[index]}<br/>平均大小: ${mockData.formatAvgSize[index]}`
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ bottom: '5%',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: '50%',
|
|
|
|
|
+ data: mockData.formats.map((name, index) => ({
|
|
|
|
|
+ value: mockData.formatStorage[index],
|
|
|
|
|
+ name
|
|
|
|
|
+ })),
|
|
|
|
|
+ emphasis: {
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ shadowBlur: 10,
|
|
|
|
|
+ shadowOffsetX: 0,
|
|
|
|
|
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 观看情况分析
|
|
|
|
|
+ if (viewsChartRef.value) {
|
|
|
|
|
+ const viewsChart = echarts.init(viewsChartRef.value)
|
|
|
|
|
+ viewsChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '各类资源平均观看人数',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ axisPointer: {
|
|
|
|
|
+ type: 'shadow'
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
- };
|
|
|
|
|
- option.series[0].data = []
|
|
|
|
|
- for (let i = 0; i < mockData.types.length; i++) {
|
|
|
|
|
- option.series[0].data.push({
|
|
|
|
|
- value: mockData.typeCounts[i],
|
|
|
|
|
- name: mockData.types[i]
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: mockData.types
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '平均观看人数'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '平均观看人数',
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: [1250, 890, 620, 980, 450],
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#2980b9'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 用户参与度分析
|
|
|
|
|
+ if (engagementChartRef.value) {
|
|
|
|
|
+ const engagementChart = echarts.init(engagementChartRef.value)
|
|
|
|
|
+ engagementChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '资源使用情况统计',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ axisPointer: {
|
|
|
|
|
+ type: 'shadow'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ data: ['观看人数', '收藏人数', '分享次数']
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '数量'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '用户参与度',
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: mockData.engagementCounts,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#9b59b6'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 时间趋势分析
|
|
|
|
|
+ if (trendChartRef.value) {
|
|
|
|
|
+ const trendChart = echarts.init(trendChartRef.value)
|
|
|
|
|
+ trendChart.setOption({
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: '资源上传与访问趋势 (2025年)',
|
|
|
|
|
+ left: 'center'
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis'
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ data: ['资源上传数量', '资源观看人数'],
|
|
|
|
|
+ top: '10%'
|
|
|
|
|
+ },
|
|
|
|
|
+ grid: {
|
|
|
|
|
+ left: '3%',
|
|
|
|
|
+ right: '4%',
|
|
|
|
|
+ bottom: '3%',
|
|
|
|
|
+ containLabel: true
|
|
|
|
|
+ },
|
|
|
|
|
+ xAxis: {
|
|
|
|
|
+ type: 'category',
|
|
|
|
|
+ boundaryGap: false,
|
|
|
|
|
+ data: mockData.trendLabels
|
|
|
|
|
+ },
|
|
|
|
|
+ yAxis: {
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ name: '数量'
|
|
|
|
|
+ },
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '资源上传数量',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: mockData.uploadTrend,
|
|
|
|
|
+ smooth: true,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#3498db'
|
|
|
|
|
+ },
|
|
|
|
|
+ areaStyle: {
|
|
|
|
|
+ color: 'rgba(52, 152, 219, 0.1)'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: '资源观看人数',
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ data: mockData.viewTrend,
|
|
|
|
|
+ smooth: true,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#e74c3c'
|
|
|
|
|
+ },
|
|
|
|
|
+ areaStyle: {
|
|
|
|
|
+ color: 'rgba(231, 76, 60, 0.1)'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ // 筛选器处理函数
|
|
|
|
|
+ const handleDepartmentChange = (value) => {
|
|
|
|
|
+ console.log('筛选院系:', value)
|
|
|
|
|
+ // 这里可以添加重新加载数据的逻辑
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const handleTimeChange = (value) => {
|
|
|
|
|
+ console.log('时间范围:', value)
|
|
|
|
|
+ // 这里可以添加重新加载数据的逻辑
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- typeChartInstance.setOption(option);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-// 资源类型分布图
|
|
|
|
|
-// new Chart(document.getElementById('typeChart'), {
|
|
|
|
|
-// type: 'pie',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.types,
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// data: mockData.typeCounts,
|
|
|
|
|
-// backgroundColor: [
|
|
|
|
|
-// '#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderWidth: 2
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '按资源类型分类 (数量)'
|
|
|
|
|
-// },
|
|
|
|
|
-// legend: {
|
|
|
|
|
-// position: 'bottom'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-}
|
|
|
|
|
-const initDepartmentChart = () => {
|
|
|
|
|
- departmentChartInstance = echarts.init(departmentChart.value);
|
|
|
|
|
- let option = {
|
|
|
|
|
- title: {
|
|
|
|
|
- text: '按院系分布 (数量)',
|
|
|
|
|
- top: 'center'
|
|
|
|
|
- },
|
|
|
|
|
- tooltip: {
|
|
|
|
|
- trigger: 'item'
|
|
|
|
|
- },
|
|
|
|
|
- legend: {
|
|
|
|
|
- bottom: 10,
|
|
|
|
|
- },
|
|
|
|
|
- series: [
|
|
|
|
|
- {
|
|
|
|
|
- type: 'pie',
|
|
|
|
|
- data: [
|
|
|
|
|
- {value: 1048, name: 'Search Engine'},
|
|
|
|
|
- {value: 735, name: 'Direct'},
|
|
|
|
|
- {value: 580, name: 'Email'},
|
|
|
|
|
- {value: 484, name: 'Union Ads'},
|
|
|
|
|
- {value: 300, name: 'Video Ads'}
|
|
|
|
|
- ],
|
|
|
|
|
- emphasis: {
|
|
|
|
|
- itemStyle: {
|
|
|
|
|
- shadowBlur: 10,
|
|
|
|
|
- shadowOffsetX: 0,
|
|
|
|
|
- shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
- };
|
|
|
|
|
- option.series[0].data = []
|
|
|
|
|
- let backgroundColors = [
|
|
|
|
|
- 'rgba(255, 99, 132, 0.8)',
|
|
|
|
|
- 'rgba(54, 162, 235, 0.8)',
|
|
|
|
|
- 'rgba(255, 206, 86, 0.8)',
|
|
|
|
|
- 'rgba(75, 192, 192, 0.8)',
|
|
|
|
|
- 'rgba(153, 102, 255, 0.8)']
|
|
|
|
|
- for (let i = 0; i < mockData.departments.length; i++) {
|
|
|
|
|
- option.series[0].data.push({
|
|
|
|
|
- value: mockData.departmentCounts[i],
|
|
|
|
|
- name: mockData.departments[i],
|
|
|
|
|
- itemStyle: {
|
|
|
|
|
- color: backgroundColors[i],
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ // 组件挂载后初始化图表
|
|
|
|
|
+ onMounted(() => {
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ initCharts()
|
|
|
})
|
|
})
|
|
|
|
|
+ })
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+ .resource-statistics {
|
|
|
|
|
+ font-family: 'Arial', sans-serif;
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ background-color: #f5f5f5;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ min-height: 100vh;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ .container {
|
|
|
|
|
+ max-width: 1200px;
|
|
|
|
|
+ margin: 0 auto;
|
|
|
|
|
+ background-color: white;
|
|
|
|
|
+ padding: 30px;
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ h1,
|
|
|
|
|
+ h2,
|
|
|
|
|
+ h3 {
|
|
|
|
|
+ color: #2c3e50;
|
|
|
|
|
+ border-bottom: 2px solid #3498db;
|
|
|
|
|
+ padding-bottom: 10px;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- departmentChartInstance.setOption(option);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-// // 院系分布图
|
|
|
|
|
-// new Chart(document.getElementById('departmentChart'), {
|
|
|
|
|
-// type: 'doughnut',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.departments,
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// data: mockData.departmentCounts,
|
|
|
|
|
-// backgroundColor: [
|
|
|
|
|
-// '#1abc9c', '#3498db', '#8e44ad', '#e67e22', '#e74c3c'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderWidth: 2
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '按院系分布 (数量)'
|
|
|
|
|
-// },
|
|
|
|
|
-// legend: {
|
|
|
|
|
-// position: 'bottom'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-const initVisibilityChart = () => {
|
|
|
|
|
- visibilityChartInstance = echarts.init(visibilityChart.value);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- let option = {
|
|
|
|
|
- title: {
|
|
|
|
|
- text: '资源公开情况',
|
|
|
|
|
- left: 'center'
|
|
|
|
|
- },
|
|
|
|
|
- xAxis: {
|
|
|
|
|
- type: 'category',
|
|
|
|
|
- data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
|
|
|
- },
|
|
|
|
|
- yAxis: {
|
|
|
|
|
- type: 'value'
|
|
|
|
|
- },
|
|
|
|
|
- series: [
|
|
|
|
|
- {
|
|
|
|
|
- data: [120, 200, 150, 80, 70, 110, 130],
|
|
|
|
|
- type: 'bar'
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
- };
|
|
|
|
|
- option.series[0].data = []
|
|
|
|
|
- option.xAxis.data = []
|
|
|
|
|
- let backgroundColors = [
|
|
|
|
|
- 'rgba(255, 99, 132, 0.8)',
|
|
|
|
|
- 'rgba(54, 162, 235, 0.8)',
|
|
|
|
|
- 'rgba(255, 206, 86, 0.8)',
|
|
|
|
|
- 'rgba(75, 192, 192, 0.8)',
|
|
|
|
|
- 'rgba(153, 102, 255, 0.8)']
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- for (let i = 0; i < mockData.visibility.length; i++) {
|
|
|
|
|
- option.series[0].data.push({
|
|
|
|
|
- value: mockData.visibilityCounts[i],
|
|
|
|
|
- name : mockData.visibility[i],
|
|
|
|
|
- itemStyle: {
|
|
|
|
|
- color: backgroundColors[i],
|
|
|
|
|
- },
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .summary-row {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 20px;
|
|
|
|
|
+ margin-bottom: 30px;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- option.xAxis.data.push(mockData.visibility[i])
|
|
|
|
|
|
|
+ .summary-box {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-width: 200px;
|
|
|
|
|
+ background-color: #ecf0f1;
|
|
|
|
|
+ padding: 15px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ text-align: center;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ .summary-box h3 {
|
|
|
|
|
+ margin: 0 0 10px 0;
|
|
|
|
|
+ color: #2c3e50;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- visibilityChartInstance.setOption(option);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-// // 院系分布图
|
|
|
|
|
-// new Chart(document.getElementById('departmentChart'), {
|
|
|
|
|
-// type: 'doughnut',
|
|
|
|
|
-// data: {
|
|
|
|
|
-// labels: mockData.departments,
|
|
|
|
|
-// datasets: [{
|
|
|
|
|
-// data: mockData.departmentCounts,
|
|
|
|
|
-// backgroundColor: [
|
|
|
|
|
-// '#1abc9c', '#3498db', '#8e44ad', '#e67e22', '#e74c3c'
|
|
|
|
|
-// ],
|
|
|
|
|
-// borderWidth: 2
|
|
|
|
|
-// }]
|
|
|
|
|
-// },
|
|
|
|
|
-// options: {
|
|
|
|
|
-// responsive: true,
|
|
|
|
|
-// plugins: {
|
|
|
|
|
-// title: {
|
|
|
|
|
-// display: true,
|
|
|
|
|
-// text: '按院系分布 (数量)'
|
|
|
|
|
-// },
|
|
|
|
|
-// legend: {
|
|
|
|
|
-// position: 'bottom'
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// });
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-//
|
|
|
|
|
-// // 筛选器交互功能
|
|
|
|
|
-// document.getElementById('department-filter').addEventListener('change', function() {
|
|
|
|
|
-// console.log('筛选院系:', this.value);
|
|
|
|
|
-// });
|
|
|
|
|
-//
|
|
|
|
|
-// document.getElementById('time-filter').addEventListener('change', function() {
|
|
|
|
|
-// console.log('时间范围:', this.value);
|
|
|
|
|
-// });
|
|
|
|
|
-onMounted(() => {
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- // initTypeChart()
|
|
|
|
|
- // initDepartmentChart()
|
|
|
|
|
- // initVisibilityChart()
|
|
|
|
|
- // initHotnessChart()
|
|
|
|
|
- })
|
|
|
|
|
-})
|
|
|
|
|
-</script>
|
|
|
|
|
-<style scoped>
|
|
|
|
|
-body {
|
|
|
|
|
- font-family: 'Arial', sans-serif;
|
|
|
|
|
- margin: 0;
|
|
|
|
|
- padding: 20px;
|
|
|
|
|
- background-color: #f5f5f5;
|
|
|
|
|
- color: #333;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.container {
|
|
|
|
|
- max-width: 1200px;
|
|
|
|
|
- margin: 0 auto;
|
|
|
|
|
- background-color: white;
|
|
|
|
|
- padding: 30px;
|
|
|
|
|
- border-radius: 10px;
|
|
|
|
|
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-h1, h2, h3 {
|
|
|
|
|
- color: #2c3e50;
|
|
|
|
|
- border-bottom: 2px solid #3498db;
|
|
|
|
|
- padding-bottom: 10px;
|
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.chart-container {
|
|
|
|
|
- margin-bottom: 40px;
|
|
|
|
|
- padding: 20px;
|
|
|
|
|
- background-color: #f9f9f9;
|
|
|
|
|
- border-radius: 8px;
|
|
|
|
|
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.row {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- gap: 20px;
|
|
|
|
|
- margin-bottom: 30px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.col {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- min-width: 300px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.summary-box {
|
|
|
|
|
- background-color: #ecf0f1;
|
|
|
|
|
- padding: 15px;
|
|
|
|
|
- border-radius: 8px;
|
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.summary-box h3 {
|
|
|
|
|
- margin: 0 0 10px 0;
|
|
|
|
|
- color: #2c3e50;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.summary-box p {
|
|
|
|
|
- margin: 0;
|
|
|
|
|
- font-size: 24px;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: #3498db;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.filters {
|
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
|
- padding: 15px;
|
|
|
|
|
- background-color: #f1f8ff;
|
|
|
|
|
- border-radius: 8px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.filters label {
|
|
|
|
|
- margin-right: 15px;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.filters select {
|
|
|
|
|
- padding: 5px;
|
|
|
|
|
- border: 1px solid #ddd;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-footer {
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- margin-top: 40px;
|
|
|
|
|
- color: #7f8c8d;
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.storage-info {
|
|
|
|
|
- background-color: #e8f4fc;
|
|
|
|
|
- padding: 15px;
|
|
|
|
|
- border-radius: 8px;
|
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.storage-info h3 {
|
|
|
|
|
- margin: 0 0 10px 0;
|
|
|
|
|
- color: #2980b9;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.storage-info p {
|
|
|
|
|
- margin: 0;
|
|
|
|
|
- font-size: 18px;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ .summary-box p {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #3498db;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .storage-info {
|
|
|
|
|
+ background-color: #e8f4fc;
|
|
|
|
|
+ padding: 15px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .storage-info h3 {
|
|
|
|
|
+ margin: 0 0 10px 0;
|
|
|
|
|
+ color: #2980b9;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .storage-info p {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .filters {
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ padding: 15px;
|
|
|
|
|
+ background-color: #f1f8ff;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .filters label {
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ margin-right: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .chart-container {
|
|
|
|
|
+ margin-bottom: 40px;
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ background-color: #f9f9f9;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .chart-row {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 20px;
|
|
|
|
|
+ margin-bottom: 30px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .chart-col {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-width: 300px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .chart {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 400px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .chart-full {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 400px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ footer {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ margin-top: 40px;
|
|
|
|
|
+ color: #7f8c8d;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ footer p {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @media (max-width: 768px) {
|
|
|
|
|
+ .summary-row {
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .chart-row {
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .chart-col {
|
|
|
|
|
+ min-width: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .filters {
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
</style>
|
|
</style>
|