Java实现数据大屏案例

wen java案例 1

本文目录导读:

Java实现数据大屏案例

  1. 项目结构
  2. pom.xml
  3. 应用主类
  4. 数据模型
  5. 数据服务
  6. WebSocket配置
  7. 控制器
  8. application.yml
  9. 前端大屏页面
  10. 前端JavaScript
  11. 运行与部署
  12. 功能特点
  13. 扩展建议

我来为您提供一个完整的Java数据大屏实现案例,使用Spring Boot + ECharts + WebSocket实现实时数据展示。

项目结构

data-screen/
├── pom.xml
├── src/main/java/com/example/datascreen/
│   ├── DataScreenApplication.java
│   ├── controller/
│   │   └── DataController.java
│   ├── service/
│   │   ├── DataService.java
│   │   └── RealTimeDataService.java
│   ├── config/
│   │   ├── WebSocketConfig.java
│   │   └── CorsConfig.java
│   └── model/
│       └── DataModel.java
└── src/main/resources/
    ├── application.yml
    └── static/
        ├── index.html
        ├── css/style.css
        └── js/
            ├── echarts.min.js
            └── dashboard.js

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>data-screen</artifactId>
    <version>1.0.0</version>
    <name>data-screen</name>
    <description>数据大屏展示系统</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
        <!-- 数据库连接 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

应用主类

package com.example.datascreen;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class DataScreenApplication {
    public static void main(String[] args) {
        SpringApplication.run(DataScreenApplication.class, args);
    }
}

数据模型

package com.example.datascreen.model;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
@Data
public class DataModel {
    // 实时数据
    private Integer totalSales;          // 总销售额
    private Integer totalOrders;         // 总订单数
    private Integer activeUsers;         // 活跃用户数
    private Integer conversionRate;      // 转化率
    // 图表数据
    private List<Map<String, Object>> trendData;    // 趋势数据
    private List<Map<String, Object>> categoryData; // 分类数据
    private List<Map<String, Object>> regionData;   // 地区数据
    private List<Map<String, Object>> realtimeData; // 实时数据
    // 排名数据
    private List<Map<String, Object>> productRanking; // 产品排名
    private List<Map<String, Object>> sellerRanking;  // 商家排名
    // 时间戳
    private LocalDateTime updateTime;
    // 饼图数据
    private List<Map<String, Object>> channelData;    // 渠道数据
    private List<Map<String, Object>> ageDistribution; // 年龄分布
}

数据服务

package com.example.datascreen.service;
import com.alibaba.fastjson.JSON;
import com.example.datascreen.model.DataModel;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
@Service
public class DataService {
    private DataModel dataModel;
    private final Map<String, Object> dataCache = new HashMap<>();
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
    @PostConstruct
    public void init() {
        dataModel = new DataModel();
    }
    /**
     * 获取大屏数据
     */
    public Map<String, Object> getDashboardData() {
        Map<String, Object> result = new HashMap<>();
        // 生成模拟数据
        result.put("totalSales", ThreadLocalRandom.current().nextInt(800, 1200));
        result.put("totalOrders", ThreadLocalRandom.current().nextInt(5000, 8000));
        result.put("activeUsers", ThreadLocalRandom.current().nextInt(10000, 15000));
        result.put("conversionRate", ThreadLocalRandom.current().nextDouble(2.5, 5.0) / 100);
        // 趋势图数据
        result.put("trendData", generateTrendData());
        // 分类数据
        result.put("categoryData", generateCategoryData());
        // 地区数据
        result.put("regionData", generateRegionData());
        // 产品排名
        result.put("productRanking", generateProductRanking());
        // 渠道数据
        result.put("channelData", generateChannelData());
        // 时间
        result.put("updateTime", LocalDateTime.now().format(formatter));
        return result;
    }
    /**
     * 生成趋势数据(最近7天)
     */
    private List<Map<String, Object>> generateTrendData() {
        List<Map<String, Object>> list = new ArrayList<>();
        String[] dates = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        int[] values = {120, 200, 150, 80, 70, 110, 130};
        int[] values2 = {80, 150, 100, 60, 50, 90, 100};
        for (int i = 0; i < dates.length; i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", dates[i]);
            map.put("value", values[i]);
            map.put("value2", values2[i]);
            list.add(map);
        }
        return list;
    }
    /**
     * 生成分类数据
     */
    private List<Map<String, Object>> generateCategoryData() {
        List<Map<String, Object>> list = new ArrayList<>();
        String[] categories = {"电子产品", "服装", "食品", "家居", "美妆", "图书"};
        String[] colors = {"#5470c6", "#91cc75", "#fac858", "#ee6666", "#73c0de", "#3ba272"};
        for (int i = 0; i < categories.length; i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", categories[i]);
            map.put("value", ThreadLocalRandom.current().nextInt(100, 500));
            map.put("color", colors[i]);
            list.add(map);
        }
        return list;
    }
    /**
     * 生成地区数据
     */
    private List<Map<String, Object>> generateRegionData() {
        List<Map<String, Object>> list = new ArrayList<>();
        String[] regions = {"北京", "上海", "广州", "深圳", "杭州", "成都", "武汉"};
        int[][] coordinates = {
            {116.46, 39.92}, {121.48, 31.22}, {113.23, 23.16},
            {114.07, 22.62}, {120.19, 30.26}, {104.06, 30.67}, {114.29, 30.59}
        };
        for (int i = 0; i < regions.length; i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", regions[i]);
            map.put("value", ThreadLocalRandom.current().nextInt(50, 200));
            map.put("coordinate", coordinates[i]);
            list.add(map);
        }
        return list;
    }
    /**
     * 生成产品排名
     */
    private List<Map<String, Object>> generateProductRanking() {
        List<Map<String, Object>> list = new ArrayList<>();
        String[] products = {"iPhone 15", "华为Mate60", "小米14", "OPPO Find X7", 
                            "三星S24", "荣耀Magic6", "vivo X100", "一加12"};
        for (int i = 0; i < products.length; i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", products[i]);
            map.put("value", ThreadLocalRandom.current().nextInt(1000, 5000));
            list.add(map);
        }
        // 按销量排序
        list.sort((a, b) -> ((Integer) b.get("value")).compareTo((Integer) a.get("value")));
        return list;
    }
    /**
     * 生成渠道数据
     */
    private List<Map<String, Object>> generateChannelData() {
        List<Map<String, Object>> list = new ArrayList<>();
        String[] channels = {"线上商城", "实体店", "直播带货", "社交电商", "跨境电商"};
        for (int i = 0; i < channels.length; i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", channels[i]);
            map.put("value", ThreadLocalRandom.current().nextInt(20, 100));
            list.add(map);
        }
        return list;
    }
    /**
     * 实时数据推送(WebSocket)
     */
    public String getRealtimeData() {
        Map<String, Object> data = getDashboardData();
        return JSON.toJSONString(data);
    }
}

WebSocket配置

package com.example.datascreen.config;
import com.example.datascreen.service.DataService;
import com.alibaba.fastjson.JSON;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class WebSocketConfig implements WebSocketConfigurer {
    @Autowired
    private DataService dataService;
    private static final CopyOnWriteArrayList<WebSocketSession> sessions = 
        new CopyOnWriteArrayList<>();
    private static final Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new TextWebSocketHandler() {
            @Override
            public void afterConnectionEstablished(WebSocketSession session) {
                sessions.add(session);
                sessionMap.put(session.getId(), session);
                System.out.println("连接建立: " + session.getId());
            }
            @Override
            protected void handleTextMessage(WebSocketSession session, 
                    TextMessage message) throws Exception {
                // 处理客户端发送的消息
                String payload = message.getPayload();
                System.out.println("收到消息: " + payload);
                // 发送响应
                session.sendMessage(new TextMessage(
                    JSON.toJSONString(dataService.getDashboardData())));
            }
            @Override
            public void afterConnectionClosed(WebSocketSession session, 
                    CloseStatus status) {
                sessions.remove(session);
                sessionMap.remove(session.getId());
                System.out.println("连接关闭: " + session.getId());
            }
            @Override
            public void handleTransportError(WebSocketSession session, 
                    Throwable exception) {
                sessions.remove(session);
                sessionMap.remove(session.getId());
            }
        }, "/websocket").setAllowedOrigins("*");
    }
    /**
     * 定时推送数据(每5秒)
     */
    @Scheduled(fixedRate = 5000)
    public void sendRealtimeData() {
        if (sessions.isEmpty()) return;
        String data = dataService.getRealtimeData();
        TextMessage message = new TextMessage(data);
        for (WebSocketSession session : sessions) {
            try {
                if (session.isOpen()) {
                    synchronized (session) {
                        session.sendMessage(message);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

控制器

package com.example.datascreen.controller;
import com.example.datascreen.service.DataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/data")
@CrossOrigin
public class DataController {
    @Autowired
    private DataService dataService;
    /**
     * 获取大屏数据
     */
    @GetMapping("/dashboard")
    public Map<String, Object> getDashboardData() {
        return dataService.getDashboardData();
    }
    /**
     * 获取实时数据
     */
    @GetMapping("/realtime")
    public Map<String, Object> getRealtimeData() {
        return dataService.getDashboardData();
    }
    /**
     * 获取统计数据
     */
    @GetMapping("/statistics")
    public Map<String, Object> getStatistics() {
        return dataService.getDashboardData();
    }
}

application.yml

server:
  port: 8080
spring:
  application:
    name: data-screen
  datasource:
    url: jdbc:mysql://localhost:3306/data_screen?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
# 自定义配置
data:
  screen:
    # 刷新频率(毫秒)
    refresh-rate: 5000

前端大屏页面

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">大数据可视化大屏</title>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            background: #091828;
            color: #fff;
            font-family: "Microsoft YaHei", sans-serif;
            min-height: 100vh;
            overflow: hidden;
        }
        .dashboard {
            display: grid;
            grid-template-columns: 1fr 2fr 1fr;
            grid-template-rows: 70px 1fr 1fr;
            gap: 10px;
            padding: 20px;
            height: 100vh;
            background: linear-gradient(180deg, #0a1929 0%, #091828 100%);
        }
        /* 大屏标题 */
        .header {
            grid-column: 1 / -1;
            text-align: center;
            padding: 15px;
            background: linear-gradient(90deg, transparent, rgba(0, 150, 255, 0.3), transparent);
            box-shadow: 0 4px 20px rgba(0, 150, 255, 0.2);
        }
        .header h1 {
            font-size: 32px;
            background: linear-gradient(90deg, #ff6b6b, #ffd93d);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            text-shadow: 0 0 30px rgba(255, 107, 107, 0.3);
        }
        /* 图表容器 */
        .chart-container {
            background: rgba(0, 20, 40, 0.6);
            border: 1px solid #1a3a5c;
            border-radius: 8px;
            padding: 15px;
            box-shadow: 0 0 20px rgba(0, 100, 200, 0.1);
        }
        .chart-container .title {
            font-size: 16px;
            margin-bottom: 10px;
            color: #00d4ff;
            border-left: 3px solid #00d4ff;
            padding-left: 10px;
        }
        /* 数字卡片 */
        .stat-cards {
            grid-column: 1 / -1;
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 10px;
        }
        .stat-card {
            background: rgba(0, 20, 40, 0.8);
            border: 1px solid #1a3a5c;
            border-radius: 8px;
            padding: 15px;
            text-align: center;
            transition: all 0.3s;
        }
        .stat-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 5px 20px rgba(0, 150, 255, 0.3);
        }
        .stat-card .value {
            font-size: 28px;
            font-weight: bold;
            background: linear-gradient(90deg, #00d4ff, #0066ff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        .stat-card .label {
            font-size: 14px;
            color: #8ab4f8;
            margin-top: 5px;
        }
        /* 地图容器 */
        #mapChart {
            grid-column: 2;
            grid-row: 2 / 4;
        }
        /* 滚动消息 */
        .scroll-message {
            position: fixed;
            bottom: 10px;
            left: 50%;
            transform: translateX(-50%);
            color: #00d4ff;
            font-size: 12px;
            animation: scroll 10s linear infinite;
        }
        @keyframes scroll {
            0% { opacity: 0; }
            10% { opacity: 1; }
            90% { opacity: 1; }
            100% { opacity: 0; }
        }
        /* 动画效果 */
        @keyframes glowing {
            0% { box-shadow: 0 0 5px rgba(0, 150, 255, 0.5); }
            50% { box-shadow: 0 0 20px rgba(0, 150, 255, 0.8); }
            100% { box-shadow: 0 0 5px rgba(0, 150, 255, 0.5); }
        }
        .glowing {
            animation: glowing 2s infinite;
        }
        /* 自适应 */
        @media (max-width: 768px) {
            .dashboard {
                grid-template-columns: 1fr;
                gap: 5px;
            }
            .stat-cards {
                grid-template-columns: repeat(2, 1fr);
            }
            #mapChart {
                grid-column: 1;
                grid-row: auto;
            }
        }
    </style>
</head>
<body>
    <div class="dashboard">
        <!-- 头部标题 -->
        <div class="header">
            <h1>📊 电商大数据可视化大屏</h1>
        </div>
        <!-- 顶部统计卡片 -->
        <div class="stat-cards">
            <div class="stat-card">
                <div class="value" id="totalSales">0</div>
                <div class="label">总销售额(万)</div>
            </div>
            <div class="stat-card">
                <div class="value" id="totalOrders">0</div>
                <div class="label">总订单数</div>
            </div>
            <div class="stat-card">
                <div class="value" id="activeUsers">0</div>
                <div class="label">活跃用户</div>
            </div>
            <div class="stat-card">
                <div class="value" id="conversionRate">0%</div>
                <div class="label">转化率</div>
            </div>
        </div>
        <!-- 左侧图表 -->
        <div class="chart-container">
            <div class="title">销售趋势</div>
            <div id="trendChart" style="width: 100%; height: 90%;"></div>
        </div>
        <!-- 中间图表 -->
        <div class="chart-container" id="mapChart">
            <div class="title">销售地区分布</div>
            <div id="regionMap" style="width: 100%; height: 90%;"></div>
        </div>
        <!-- 右侧图表 -->
        <div class="chart-container">
            <div class="title">销售渠道分析</div>
            <div id="channelChart" style="width: 100%; height: 90%;"></div>
        </div>
        <!-- 左下角图表 -->
        <div class="chart-container">
            <div class="title">商品分类</div>
            <div id="categoryChart" style="width: 100%; height: 90%;"></div>
        </div>
        <!-- 右下角图表 -->
        <div class="chart-container">
            <div class="title">产品销量排名</div>
            <div id="rankingChart" style="width: 100%; height: 90%;"></div>
        </div>
        <div class="scroll-message">数据更新时间:<span id="updateTime"></span> | 数据每5秒自动刷新</div>
    </div>
    <script src="/js/dashboard.js"></script>
</body>
</html>

前端JavaScript

// dashboard.js
$(document).ready(function() {
    // 初始化所有图表
    initCharts();
    // 连接WebSocket
    connectWebSocket();
    // 定时刷新数据
    setInterval(updateData, 5000);
});
// 图表实例
let trendChart, regionMap, channelChart, categoryChart, rankingChart;
function initCharts() {
    // 趋势图
    trendChart = echarts.init(document.getElementById('trendChart'));
    trendChart.setOption({
        tooltip: { trigger: 'axis' },
        legend: { data: ['销售额', '订单量'], textStyle: { color: '#fff' } },
        grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
        xAxis: {
            type: 'category',
            data: [],
            axisLine: { lineStyle: { color: '#1a3a5c' } },
            axisLabel: { color: '#fff' }
        },
        yAxis: {
            type: 'value',
            axisLine: { lineStyle: { color: '#1a3a5c' } },
            axisLabel: { color: '#fff' },
            splitLine: { lineStyle: { color: '#1a3a5c' } }
        },
        series: [
            {
                name: '销售额',
                type: 'line',
                smooth: true,
                data: [],
                areaStyle: {
                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, 
                        [{ offset: 0, color: 'rgba(0, 212, 255, 0.3)' }, 
                         { offset: 1, color: 'rgba(0, 212, 255, 0)' }])
                }
            },
            {
                name: '订单量',
                type: 'line',
                smooth: true,
                data: [],
                areaStyle: {
                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, 
                        [{ offset: 0, color: 'rgba(255, 107, 107, 0.3)' }, 
                         { offset: 1, color: 'rgba(255, 107, 107, 0)' }])
                }
            }
        ]
    });
    // 地区地图
    regionMap = echarts.init(document.getElementById('regionMap'));
    regionMap.setOption({
        tooltip: { trigger: 'item', formatter: '{b}: {c}' },
        visualMap: {
            min: 0,
            max: 200,
            text: ['高', '低'],
            calculable: true,
            inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }
        },
        series: [{
            type: 'map',
            map: 'china',
            roam: true,
            label: { show: true },
            data: []
        }]
    });
    // 渠道分析(饼图)
    channelChart = echarts.init(document.getElementById('channelChart'));
    channelChart.setOption({
        tooltip: { trigger: 'item', formatter: '{a} <br/>{b}: {c} ({d}%)' },
        legend: { orient: 'vertical', right: 10, textStyle: { color: '#fff' } },
        series: [{
            name: '销售渠道',
            type: 'pie',
            radius: ['40%', '70%'],
            avoidLabelOverlap: false,
            itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 },
            label: { show: false, position: 'center' },
            emphasis: {
                label: { show: true, fontSize: 20, fontWeight: 'bold' }
            },
            data: []
        }]
    });
    // 商品分类(柱状图)
    categoryChart = echarts.init(document.getElementById('categoryChart'));
    categoryChart.setOption({
        tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
        grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
        xAxis: {
            type: 'category',
            data: [],
            axisLabel: { color: '#fff', rotate: 30 },
            axisLine: { lineStyle: { color: '#1a3a5c' } }
        },
        yAxis: {
            type: 'value',
            axisLabel: { color: '#fff' },
            splitLine: { lineStyle: { color: '#1a3a5c' } }
        },
        series: [{
            name: '销售额',
            type: 'bar',
            data: [],
            itemStyle: {
                borderRadius: [5, 5, 0, 0],
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, 
                    [{ offset: 0, color: '#00d4ff' }, 
                     { offset: 1, color: '#0066ff' }])
            }
        }]
    });
    // 产品排名(横向柱状图)
    rankingChart = echarts.init(document.getElementById('rankingChart'));
    rankingChart.setOption({
        tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
        grid: { left: '3%', right: '10%', bottom: '3%', containLabel: true },
        xAxis: {
            type: 'value',
            axisLabel: { color: '#fff' },
            splitLine: { lineStyle: { color: '#1a3a5c' } }
        },
        yAxis: {
            type: 'category',
            data: [],
            axisLabel: { color: '#fff' },
            axisLine: { lineStyle: { color: '#1a3a5c' } }
        },
        series: [{
            name: '销量',
            type: 'bar',
            data: [],
            itemStyle: {
                borderRadius: [0, 5, 5, 0],
                color: new echarts.graphic.LinearGradient(0, 0, 1, 0, 
                    [{ offset: 0, color: '#ff6b6b' }, 
                     { offset: 1, color: '#ffd93d' }])
            }
        }]
    });
}
function updateData() {
    $.ajax({
        url: '/api/data/dashboard',
        type: 'GET',
        dataType: 'json',
        success: function(data) {
            renderData(data);
        },
        error: function() {
            console.log('请求数据失败');
        }
    });
}
function renderData(data) {
    if (!data) return;
    // 更新统计卡片
    animateNumber($('#totalSales'), 0, data.totalSales, 1000);
    animateNumber($('#totalOrders'), 0, data.totalOrders, 1000);
    animateNumber($('#activeUsers'), 0, data.activeUsers, 1000);
    let rate = (data.conversionRate * 100).toFixed(2);
    $('#conversionRate').text(rate + '%');
    // 更新时间
    $('#updateTime').text(data.updateTime);
    // 更新图表
    updateCharts(data);
}
function updateCharts(data) {
    // 更新趋势图
    if (data.trendData) {
        trendChart.setOption({
            xAxis: { data: data.trendData.map(item => item.name) },
            series: [
                { data: data.trendData.map(item => item.value) },
                { data: data.trendData.map(item => item.value2) }
            ]
        });
    }
    // 更新地区地图
    if (data.regionData) {
        regionMap.setOption({
            series: [{
                data: data.regionData.map(item => ({
                    name: item.name,
                    value: item.value
                }))
            }]
        });
    }
    // 更新渠道饼图
    if (data.channelData) {
        channelChart.setOption({
            series: [{ data: data.channelData }]
        });
    }
    // 更新商品分类
    if (data.categoryData) {
        categoryChart.setOption({
            xAxis: { data: data.categoryData.map(item => item.name) },
            series: [{ data: data.categoryData.map(item => item.value) }]
        });
    }
    // 更新产品排名
    if (data.productRanking) {
        rankingChart.setOption({
            yAxis: { data: data.productRanking.map(item => item.name) },
            series: [{ data: data.productRanking.map(item => item.value) }]
        });
    }
}
// 数字动画
function animateNumber($element, start, end, duration) {
    let current = start;
    let step = (end - start) / (duration / 50);
    let timer = setInterval(function() {
        current += step;
        if (current >= end) {
            current = end;
            clearInterval(timer);
        }
        $element.text(Math.round(current).toLocaleString());
    }, 50);
}
// WebSocket连接
function connectWebSocket() {
    const socket = new WebSocket('ws://' + window.location.host + '/websocket');
    socket.onopen = function() {
        console.log('WebSocket连接成功');
    };
    socket.onmessage = function(event) {
        let data = JSON.parse(event.data);
        renderData(data);
    };
    socket.onclose = function() {
        console.log('WebSocket连接关闭');
        // 断线重连
        setTimeout(connectWebSocket, 5000);
    };
    socket.onerror = function(error) {
        console.log('WebSocket错误:', error);
    };
}

运行与部署

打包运行

# 打包
mvn clean package -DskipTests
# 运行
java -jar target/data-screen-1.0.0.jar

访问地址

http://localhost:8080

功能特点

  1. 实时数据展示:通过WebSocket实现数据的实时推送
  2. 多种图表类型:折线图、柱状图、饼图、地图等
  3. 动态数字效果:数字变化的动态展示
  4. 响应式设计:适配不同屏幕尺寸
  5. 自动刷新:定时获取最新数据
  6. 美观的UI设计:科技感十足的大屏样式

扩展建议

  1. 数据库集成:使用MySQL存储真实业务数据
  2. 多数据源:支持Kafka、Flink等实时数据源
  3. 权限控制:添加用户认证和权限管理
  4. 告警功能:添加数据异常预警
  5. 更多图表:添加雷达图、仪表盘等更多可视化组件
  6. 数据导出:支持数据报表导出功能
  7. 多屏幕适配:支持多屏拼接显示

这个数据大屏案例可以直接运行,适合学习大数据可视化和WebSocket实时通信开发,您可以根据实际需求修改数据和样式。

抱歉,评论功能暂时关闭!