League of Legends赛事数据管理系统开发
❗❗❗本文最后更新于 228 天前,其中的信息可能已经过时;如有错误请在文章下方评论✅,欢迎纠错🥰!

需求分析

系统开发背景、目的及意义

在现代硬件、软件的飞速发展的背景下,人们的物质需求日益满足,科学技术水平日益提高,在人们生活中文化娱乐的占比越来越高。因此不少游戏横空出世,随之电竞行业应运而生,而家长们却把电竞钉上了“误人子弟”的标签。早在2003年11月,电子竞技就已经被体育总局承认为我国正式开展的第99个运动项目。而在2008年,电子竞技被体育总局改批为第78号正式体育竞赛项。尽管电竞行业已经得到国家正视,但是出于人们对于电子竞技的传统观念束缚,所以电竞行业依旧没有很大的起色。直到2013年3月,体育总局决定组建电子竞技国家队后,在各大主流媒体上引起了人们对电子竞技的强烈关注。各种电竞赛事如同雨后春笋一般一个接一个出现。随着电竞行业的不断扩大、规章制度越来越规范、各路媒体以及社会越来越多的关注,电子竞技的影响力也是越来越高,其商业化、规范化也是必然结果。

《英雄联盟》(League of Legends,简称LOL)是由美国拳头游戏(Riot Games)开发、中国内地由腾讯游戏代理运营的英雄对战MOBA竞技网游,自从2013年开始举办LPL春/夏季联赛后,英雄联盟的热度在国内不断提高,关注人群规模庞大,影响群体越来越多,同时随着更多资本入局,联赛奖金的上调以及场馆的建设和周边产品的推出,使得这一游戏已经成为了中国电竞行业的重要组成,这也让更多的赛事选择在中国举办,而中国战队在国际赛事上的表也是精彩纷呈,在S8、S9以及S11三次获得英雄联盟全球总决赛的冠军,中国选手的身价的不断上升,逐渐开始加盟外国战队走向世界,英雄联盟是划时代的产物,它现在的高度不止局限于游戏,它正在慢慢演变成一种潮流、一种文化、一种精神,这也从侧面佐证了我国电竞行业的崛起趋势。

每一年LPL都会举办两季比赛,春季赛和夏季赛。每季比赛又各分为常规赛和季后赛两部分。每年夏季赛结束之后会举办全球总决赛资格赛,选拔当年英雄联盟全球总决赛的参赛队伍。由于每一年都会迎来转会期,所以每个战队在一年后的参赛选手和竞技状态都不同,导致每一年的战队排名也有所变化。

因此设计出一个健全的赛事数据管理系统是非常有必要的,该系统可从头到尾追踪一场比赛的完整流程,从预约比赛战队——添加红蓝方战队以及双方首发队员、添加赛事数据——添加双方比赛数据直至赛事数据管理——通过赛事编号展示对应的战队,成员以及数据。

功能需求分析

预约比赛战队:支持添加赛程,包括赛程名称、赛程阶段、赛程时间、双方战队以及首发队员。

添加赛事数据:添加双方战队每场比赛的相关数据,包括击杀、大龙、小龙、防御塔、金钱以及获胜情况。

赛事数据管理:通过赛事编号查询整条赛事数据,显示对应编号的赛事信息,战队,成员以及赛事数据详情。

系统架构设计

系统框架设计

系统引擎使用“Spring”,框架使用“SpringMVC”,并配合“SpringBoot”快速开发整合包搭建系统运行环境;使用Java语言进行后端开发,系统前端部分整体使用layui框架,采用模块化规范,遵循HTML/CSS/JS 的开发方式,组成SpringBoot+Maven+MongoDB的系统架构。

本系统架构分为前端和后端,即客户端和服务器端。而使用系统的管理者和选手即是用户,系统的功能都是基于客户端、服务器端和数据库交互实现的。

系统实现的结构如图所示:

前端部分

系统从宏观角度仅仅为单个页面,使用户界面结构更加简洁清晰,采用iframe内联框架,其他功能页面内嵌进iframe框架,共计四个页面。

  • index.html

 

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>LOL赛事数据管理系统</title>
  <link crossorigin="anonymous" integrity="sha512-SSF+OBDODWTSIqOivYBOyOKQ93PBDevipJEUEWtkUbTt4v34rmgPcCXcBMolxZIJcuobcdqmYJlonjUBEbOzNw==" href="https://lib.baomitu.com/layui/2.7.6/css/layui.css" rel="stylesheet">
  <link rel="shortcut icon" href="https://lpl.qq.com/favicon.ico" type="image/x-icon">
</head>
<body>
<div class="layui-layout layui-layout-admin">
  <div class="layui-header">
    <div class="layui-logo layui-hide-xs layui-bg-black">LOL赛事数据管理系统</div>
    <!-- 头部区域(可配合layui 已有的水平导航) -->
    <ul class="layui-nav layui-layout-left">
      <!-- 移动端显示 -->
      <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft">
        <i class="layui-icon layui-icon-spread-left"></i>
      </li>

      <li class="layui-nav-item layui-hide-xs"><a href="">nav 1</a></li>
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 2</a></li>
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 3</a></li>
      <li class="layui-nav-item">
        <a href="javascript:;">nav groups</a>
        <dl class="layui-nav-child">
          <dd><a href="">menu 11</a></dd>
          <dd><a href="">menu 22</a></dd>
          <dd><a href="">menu 33</a></dd>
        </dl>
      </li>
    </ul>
    <ul class="layui-nav layui-layout-right">
      <li class="layui-nav-item layui-hide layui-show-md-inline-block">
        <a href="javascript:;">
          <img src="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" class="layui-nav-img">
          Viper3
        </a>
        <dl class="layui-nav-child">
          <dd><a href="">Your Profile</a></dd>
          <dd><a href="">Settings</a></dd>
          <dd><a href="">Sign out</a></dd>
        </dl>
      </li>
      <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
        <a href="javascript:;">
          <i class="layui-icon layui-icon-more-vertical"></i>
        </a>
      </li>
    </ul>
  </div>

  <div class="layui-side layui-bg-black">
    <div class="layui-side-scroll">
      <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
      <ul class="layui-nav layui-nav-tree" lay-filter="test">
        <li class="layui-nav-item layui-nav-itemed">
          <dl class="layui-nav-child">
            <dd><a href="add-team.html" target="index">预约比赛战队</a></dd>
            <dd><a href="add-event.html" target="index">添加赛事数据</a></dd>
            <dd><a href="events-manage.html" target="index">赛事数据管理</a></dd>
          </dl>
        </li>
      </ul>
    </div>
  </div>

  <div class="layui-body">
    <!-- 内容主体区域 -->
    <iframe width="99%" height="100%" name="index"></iframe>
  </div>

  <div class="layui-footer">
    <!-- 底部固定区域 -->
    底部固定区域
  </div>
</div>
<script crossorigin="anonymous" integrity="sha512-mIKH3M2bRlIyhG4tBEbJ8dn8t8JFlNJU2NXlJePgpQ72CK4jAYsZyCGFcASRGtPBbcAQhz67KTkA1Jw6Kizk9g==" src="https://lib.baomitu.com/layui/2.7.6/layui.js"></script>
<script>
  //JS
  layui.use(['element', 'layer', 'util'], function(){
    var element = layui.element
            ,layer = layui.layer
            ,util = layui.util
            ,$ = layui.$;

    //头部事件
    util.event('lay-header-event', {
      //左侧菜单事件
      menuLeft: function(othis){
        layer.msg('展开左侧菜单的操作', {icon: 0});
      }
      ,menuRight: function(){
        layer.open({
          type: 1
          ,content: '<div style="padding: 15px;">处理右侧面板的操作</div>'
          ,area: ['260px', '100%']
          ,offset: 'rt' //右上角
          ,anim: 5
          ,shadeClose: true
        });
      }
    });

  });
</script>
</body>
</html>
  • add-team.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>预约比赛战队</title>
  <link crossorigin="anonymous" integrity="sha512-SSF+OBDODWTSIqOivYBOyOKQ93PBDevipJEUEWtkUbTt4v34rmgPcCXcBMolxZIJcuobcdqmYJlonjUBEbOzNw==" href="https://lib.baomitu.com/layui/2.7.6/css/layui.css" rel="stylesheet">
  <link rel="shortcut icon" href="https://lpl.qq.com/favicon.ico" type="image/x-icon">
</head>
<body>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
  <legend>预约比赛战队</legend>
</fieldset>
<!--面板-->
<div class="layui-card">
  <div class="layui-card-body">
    <!--表单-->
        <form class="layui-form" action="">

            <div class="layui-form-item" style="width: 100%; display: flex; justify-content: center; align-items: center;">
              <label class="layui-form-label">赛事时间</label>
              <div class="layui-inline" style="margin-bottom: 0;"> <!-- 注意:这一层元素并不是必须的 -->
                <input class="layui-input" id="eventTime" placeholder="请选择时间" name="eventTime">
              </div>
            </div>
          <div class="layui-form-item">
            <div class="layui-col-md12">
              <label class="layui-form-label">赛事名称</label>
              <div class="layui-input-block">
                <input type="text" name="eventName" class="layui-input">
              </div>
            </div>
          </div>
          <div class="layui-form-item">
            <div class="layui-col-md12">
              <label class="layui-form-label">赛事阶段</label>
              <div class="layui-input-block">
                <input type="text" name="eventStage" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第一个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">A战队名称</label>
              <div class="layui-input-block">
                <input type="text" name="teamA.name" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第二个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">B战队名称</label>
              <div class="layui-input-block">
                <input type="text" name="teamB.name" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第三个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">A战队上单</label>
              <div class="layui-input-block">
                <input type="text" name="teamA.top" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第四个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">B战队上单</label>
              <div class="layui-input-block">
                <input type="text" name="teamB.top" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第五个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">A战队打野</label>
              <div class="layui-input-block">
                <input type="text" name="teamA.jungle" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第六个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">B战队打野</label>
              <div class="layui-input-block">
                <input type="text" name="teamB.jungle" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第七个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">A战队中单</label>
              <div class="layui-input-block">
                <input type="text" name="teamA.mid" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第八个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">B战队中单</label>
              <div class="layui-input-block">
                <input type="text" name="teamB.mid" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第九个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">A战队ADC</label>
              <div class="layui-input-block">
                <input type="text" name="teamA.adc" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第十个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">B战队ADC</label>
              <div class="layui-input-block">
                <input type="text" name="teamB.adc" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第十一个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">A战队辅助</label>
              <div class="layui-input-block">
                <input type="text" name="teamA.support" class="layui-input">
              </div>
            </div>
          </div>
          <!-- 第十二个输入框 -->
          <div class="layui-col-md6">
            <div class="layui-form-item">
              <label class="layui-form-label">B战队辅助</label>
              <div class="layui-input-block">
                <input type="text" name="teamB.support" class="layui-input">
              </div>
            </div>
          </div>
          <div class="layui-form-item">
            <div style="width:100%; text-align:center">
              <button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
              <button type="reset" class="layui-btn layui-btn-primary">重置</button>
            </div>
          </div>
        </form>
  </div>
</div>

<script crossorigin="anonymous" integrity="sha512-mIKH3M2bRlIyhG4tBEbJ8dn8t8JFlNJU2NXlJePgpQ72CK4jAYsZyCGFcASRGtPBbcAQhz67KTkA1Jw6Kizk9g==" src="https://lib.baomitu.com/layui/2.7.6/layui.js"></script>
<script>
  layui.use('laydate', function(){
    var laydate = layui.laydate;

    //执行一个laydate实例
    laydate.render({
      elem: '#eventTime',
      format: 'yyyy-MM-dd HH:mm:ss', //可任意组合
      type: 'datetime',
      theme: 'molv',
    });
  });
</script>
<script src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js"></script>
<script>
  layui.use('form',function(){
    var form=layui.form;
    form.on('submit(formDemo)',function(data){
      $.ajax({
        url: "/raceflow/add",
        type: "POST",
        data: data.field,
        datatype: "JSON",
        success: function(result){
          layer.msg(result);
        }
      });
      return false;
    });
  });
</script>
</body>
</html>
  • add-event.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>添加赛事数据</title>
    <link crossorigin="anonymous" integrity="sha512-SSF+OBDODWTSIqOivYBOyOKQ93PBDevipJEUEWtkUbTt4v34rmgPcCXcBMolxZIJcuobcdqmYJlonjUBEbOzNw==" href="https://lib.baomitu.com/layui/2.7.6/css/layui.css" rel="stylesheet">
    <link rel="shortcut icon" href="https://lpl.qq.com/favicon.ico" type="image/x-icon">
</head>
<body>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
    <legend>添加赛事数据</legend>
</fieldset>
<!--面板-->
<div class="layui-card">
    <div class="layui-card-body">
        <!--表单-->
        <form class="layui-form" action="">
            <div class="layui-form-item" style="width: 100%; display: flex; justify-content: center; align-items: center;">
                <label class="layui-form-label">赛事编号</label>
                <div class="layui-inline" style="margin-bottom: 0;">
                    <input type="text" name="raceFlowId" class="layui-input">
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">A战队击杀</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventA.kill" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">B战队击杀</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventB.kill" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">A战队大龙</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventA.baron" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">B战队大龙</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventB.baron" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">A战队小龙</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventA.dragon" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">B战队小龙</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventB.dragon" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">A战队防御塔</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventA.tower" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">B战队防御塔</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventB.tower" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">A战队金钱</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventA.money" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">B战队金钱</label>
                    <div class="layui-input-block">
                        <input type="text" name="eventB.money" class="layui-input">
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">A队获胜情况</label>
                    <div class="layui-inline" style="margin-bottom: 0;">
                        <select name="eventA.outcome">
                            <option value="">请选择获胜情况</option>
                            <option value="victory">胜利</option>
                            <option value="defeat">失败</option>
                        </select>
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label">B队获胜情况</label>
                    <div class="layui-inline" style="margin-bottom: 0;">
                        <select name="eventB.outcome">
                            <option value="">请选择获胜情况</option>
                            <option value="victory">胜利</option>
                            <option value="defeat">失败</option>
                        </select>
                    </div>
                </div>
            </div>
            <div class="layui-form-item" style="width: 100%; display: flex; justify-content: center; align-items: center;">
                <label class="layui-form-label">赛程状态</label>
                <div class="layui-inline" style="margin-bottom: 0;">
                    <select name="status">
                        <option value="">请选择赛程状态</option>
                        <option value="未开始">未开始</option>
                        <option value="进行中">进行中</option>
                        <option value="已结束">已结束</option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item" style="width: 100%; display: flex; justify-content: center; align-items: center;">
                <div class="layui-inline" style="margin-bottom: 0;">
                    <button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
                    <button type="reset" class="layui-btn layui-btn-primary">重置</button>
                </div>
            </div>
        </form>
    </div>
</div>

<script crossorigin="anonymous" integrity="sha512-mIKH3M2bRlIyhG4tBEbJ8dn8t8JFlNJU2NXlJePgpQ72CK4jAYsZyCGFcASRGtPBbcAQhz67KTkA1Jw6Kizk9g==" src="https://lib.baomitu.com/layui/2.7.6/layui.js"></script>
<script src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js"></script>
<script>
    layui.use('form',function(){
        var form=layui.form;
        form.on('submit(formDemo)',function(data){
            $.ajax({
                url: "/raceflow/update",
                type: "POST",
                data: data.field,
                datatype: "JSON",
                success: function(result){
                    layer.msg(result);
                }
            });
            return false;
        });
    });
</script>
</body>
</html>
  • events-manage.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>赛事数据管理</title>
    <link rel="stylesheet" href="https://lib.baomitu.com/layui/2.7.6/css/layui.min.css">
    <link rel="shortcut icon" href="https://lpl.qq.com/favicon.ico" type="image/x-icon">
</head>
<body>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
    <legend>赛事数据管理</legend>
</fieldset>
<!-- 面板 -->
<div class="layui-card">
    <div class="layui-card-body">
        <label class="layui-form-label">赛事编号</label>
        <div class="layui-input-inline">
            <input type="text" id="id" class="layui-input">
        </div>
        <button onclick="search();" class="layui-btn"><i class="layui-icon">&#xe615;</i></button>
    </div>
</div>

<div style="padding: 20px;margin-bottom: 100px;">
    <!-- 面板 -->
    <div class="layui-col-md12">
        <div class="layui-card">
            <div class="layui-card-header">赛程信息</div>
            <div class="layui-card-body" id="raceFlow" style="font-size: 16px">


            </div>
        </div>
    </div>
    <!-- 面板 -->
    <div class="layui-col-md12">
        <div class="layui-card">
            <div class="layui-card-header">赛事数据</div>
            <div class="layui-col-md6">
                <div class="layui-card">
                    <div class="layui-card-body">
                        <!-- 时间线 -->
                        <ul class="layui-timeline" id="events_A">

                        </ul>
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-card">
                    <div class="layui-card-body">
                        <!-- 时间线 -->
                        <ul class="layui-timeline" id="events_B">

                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="layui-col-md12">
        <!-- 面板 -->
        <div class="layui-card">
            <div class="layui-card-header">赛事数据列表</div>
            <div class="layui-card-body">
                <!-- 数据表格 -->
                <table id="raceflowList" lay-filter="raceflowTable"></table>
            </div>
        </div>
    </div>
</div>
<!-- 头工具栏事件 筛选/导出/打印 -->
<script type="text/html" id="toolbarDemo"></script>
<!-- 行工具事件 -->
<script type="text/html" id="barDemo">
    <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
    <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>

<script src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js"></script>
<script src="https://lib.baomitu.com/layui/2.7.6/layui.min.js"></script>
<script>
    // 搜索
    function search() {
        // 赛事编号
        var id = $("#id").val();
        $.ajax({
            url: "/raceflow/" + id,
            type: "GET",
            dataType: "JSON",
            // 拼接处理返回结果
            success: function (raceFlow) {
                if (raceFlow == null || raceFlow == undefined || raceFlow == "") {
                    layer.msg("赛程信息不存在");
                    return;
                }
                let teamA = raceFlow['teamA']
                let teamB = raceFlow['teamB']
                // 处理比赛信息
                $("#raceFlow").append("<h4>" + "赛事编号:" + id + "(" + raceFlow["status"] + ")" + "</h4>" + "<hr/>")
                    .append("<h5>" + "赛事名称:" + raceFlow["eventName"] + "</h5>")
                    .append("<h5>" + "赛事阶段:" + raceFlow["eventStage"] + "<h5>")
                    .append("<h5>" + "赛程时间:" + raceFlow["eventTime"] + "</h5>" + "<hr/>")
                    .append("<h4>"+ "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp" +  teamA["name"] + "&nbsp&nbsp&nbsp&nbsp" + "VS" + "&nbsp&nbsp&nbsp&nbsp" + teamB["name"] + "<h4>")
                    .append("TOP:" + teamA["top"] + "⚔" + "TOP:" + teamB["top"] + "<br/>")
                    .append("JUG:" + teamA["jungle"] + "⚔" + "JUG:" + teamB["jungle"] + "<br/>")
                    .append("MID:" + teamA["mid"] + "⚔" + "MID:" + teamB["mid"] + "<br/>")
                    .append("ADC:" + teamA["adc"] + "⚔" + "ADC:" + teamB["adc"] + "<br/>")
                    .append("SUP:" + teamA["support"] + "⚔" + "SUP:" + teamB["support"] + "<hr/>");
                // 获取战队信息
                let events = raceFlow['events'];
                // 循环
                for (var i = 0; i < events.length; i++) {
                    // 处理赛事数据信息
                    $("#events_A").append('<li class="layui-timeline-item">' +
                        '<i class="layui-icon layui-timeline-axis"></i>' +
                        '<div class="layui-timeline-content layui-text">' +
                        '<h3 class="layui-timeline-title">' + teamA.name + '</h3>' +
                        '<h5>' + 'BO' + (i + 1) + '(' + raceFlow.status + ')' + '</h5>' +
                        '<p>击杀:' + events[i].eventA.kill + '&nbsp;' + '&nbsp;' +
                        '大龙:' + events[i].eventA.baron + '&nbsp;' + '&nbsp;' +
                        '小龙:' + events[i].eventA.dragon + '&nbsp;'+ '&nbsp;' +
                        '金钱:' + events[i].eventA.money + '&nbsp;'+ '&nbsp;' +
                        '防御塔:' + events[i].eventA.tower + '&nbsp;'+ '&nbsp;' +
                        '获胜情况:' + events[i].eventA.outcome +'</p></div></li>');
                    // 处理赛事数据信息
                    $("#events_B").append('<li class="layui-timeline-item">' +
                        '<i class="layui-icon layui-timeline-axis"></i>' +
                        '<div class="layui-timeline-content layui-text">' +
                        '<h3 class="layui-timeline-title">' + teamB.name + '</h3>' +
                        '<h5>' + 'BO' + (i + 1) + '(' + raceFlow.status + ')' + '</h5>' +
                        '<p>击杀:' + events[i].eventB.kill + '&nbsp;' + '&nbsp;' +
                        '大龙:' + events[i].eventB.baron + '&nbsp;' + '&nbsp;' +
                        '小龙:' + events[i].eventB.dragon + '&nbsp;'+ '&nbsp;' +
                        '金钱:' + events[i].eventB.money + '&nbsp;'+ '&nbsp;' +
                        '防御塔:' + events[i].eventB.tower + '&nbsp;'+ '&nbsp;' +
                        '获胜情况:' + events[i].eventB.outcome +'</p></div></li>');
                }
            },
        });
    }

    // 数据表格
    layui.use('table', function () {
        var table = layui.table;
        //第一个实例
        table.render({
            elem: '#raceflowList',
            url: '/raceflow/list', //数据接口
            page: true, //开启分页
            toolbar: '#toolbarDemo', // 头工具栏
            cols: [[ // 表头
                {field: 'id', title: '赛事编号', sort: true, fixed: 'left'},
                {field: 'status', title: '赛程状态'},
                {field: 'eventTime', title: '比赛时间', sort: true},
                {field: 'eventName', title: '赛事名称'},
                {field: 'eventStage', title: '赛事阶段'},
                {field: 'teamAName', title: 'A战队名称'},
                {field: 'teamBName', title: 'B战队名称'},
                {fixed: 'right', title: '操作', toolbar: '#barDemo'} // 行工具栏
            ]]
        });

        //工具条事件
        table.on('tool(raceflowTable)', function (obj) { //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter="对应的值"
            var data = obj.data; //获得当前行数据
            var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
            var tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)

            if (layEvent === 'detail') { //查看
                //do somehing
            } else if (layEvent === 'del') { //删除
                layer.confirm('确定删除吗', function (index) {
                    obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
                    layer.close(index);
                    //向服务端发送删除指令
                    $.ajax({
                        url: "/raceflow/delete",
                        type: "POST",
                        data: {"id": data.id},
                        dataType: "JSON",
                        success: function (result) {
                            layer.msg(result);
                        }
                    });
                });
            } else if (layEvent === 'edit') { //编辑
                //do something

                //同步更新缓存对应的值
                obj.update({
                    username: '123'
                    , title: 'xxx'
                });
            } else if (layEvent === 'LAYTABLE_TIPS') {
                layer.alert('Hi,头部工具栏扩展的右侧图标。');
            }
        });
    });
</script>
</body>
</html>

后端部分

本系统后端共包含7个类,Model层用于存放实体类,构建数据结构,利于数据存储和数据处理,并与数据库中的属性值基本保持一致;RaceFlowController类用于接受前端的传来的参数,通过调用service层,来实现数据的编辑,然后再返回;RaceFlowService类用于存放业务逻辑处理,调用Model层并提供给controller层使用,间接与数据库连接;RaceFlowVO类用于将前端需要的数据做封装,方便前端获取数据;

  • Model层(数据库实体层):

RaceFlow类

package com.lol.loleventdatamanagement.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.util.Date;
import java.util.List;


@Data
@NoArgsConstructor
@AllArgsConstructor

public class RaceFlow implements Serializable{
    private String id; // 赛事编号
    private String status; // 赛程状态

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date eventTime; // 赛程时间
    private String eventName; // 赛事名称
    private String eventStage; // 赛事阶段

    private Team teamA; //A战队信息
    private Team teamB; //B战队信息

    private List<EventDouble> events; // 双方赛事数据
}

Team类

package com.lol.loleventdatamanagement.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor

public class Team implements Serializable {
    private String name; // 战队名称
    private String top; // 上单
    private String jungle; // 打野
    private String mid; // 中单
    private String adc; // ADC
    private String support; // 辅助
}

Event类

package com.lol.loleventdatamanagement.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Event implements Serializable {
    /**
     * 赛程明细
     */
    private int kill; // 击杀
    private int baron; // 大龙
    private int dragon; // 小龙
    private int money; // 金钱
    private int tower; // 防御塔
    private String outcome; // 获胜情况
}

EventDouble类

package com.lol.loleventdatamanagement.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class EventDouble implements Serializable {
    /**
     * 赛程明细
     */
    private String raceFlowId;  // 区别RaceFlow类中的id
    private String status;  // 用以更新赛事状态
    private Event eventA;  // 用以存储events列表中eventA字段
    private Event eventB;  // 用以存储events列表中eventB字段
}
  • VO层(数据展示层):

RaceFlowVO类

package com.lol.loleventdatamanagement.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.util.Date;


@Data
@NoArgsConstructor
@AllArgsConstructor

public class RaceFlowVO implements Serializable{
    private String id; // 赛事编号
    private String status; // 赛程状态

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date eventTime; // 比赛时间
    private String eventName; // 赛事名称
    private String eventStage; // 赛事阶段

    private String teamAName;  //提取嵌入式文档的内层属性用以页面展示
    private String teamBName;  //提取嵌入式文档的内层属性用以页面展示
}
  • Service层(服务层):

RaceFlowService类

package com.lol.loleventdatamanagement.service;

import cn.hutool.core.util.IdUtil;
import com.lol.loleventdatamanagement.pojo.EventDouble;
import com.lol.loleventdatamanagement.pojo.RaceFlow;
import com.lol.loleventdatamanagement.vo.RaceFlowVO;
import com.mongodb.client.result.DeleteResult;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class RaceFlowService {
    @Resource
    private MongoTemplate mongoTemplate;

    /**
     * 添加比赛流程至MongoDB
     * @param raceFlow
     */

    public void addRaceFlow(RaceFlow raceFlow){
        // 比赛编号根据雪花算法生成
        raceFlow.setId(IdUtil.getSnowflake(1, 1).nextIdStr());
        // 设置比赛状态
        raceFlow.setStatus("未开始");
        // 添加预约比赛至MongoDB
        mongoTemplate.insert(raceFlow, "lol");
    }

        /**
         * 更新比赛信息
         * 追加战队信息
         */
    public void updateAndAddEvent(EventDouble eventDouble) {
        // 获取赛程状态
        String status = eventDouble.getStatus();
        // 初始化Query对象,根据赛事编号查询
        Query query = new Query(Criteria.where("_id").is(eventDouble.getRaceFlowId()));
        // 初始化Update对象
        Update update = new Update();
        // 更新比赛状态
        update.set("status", status);
        // 追加比赛数据
        update.push("events", eventDouble);
        // 更新比赛信息
        mongoTemplate.upsert(query, update, EventDouble.class, "lol");
    }
        /**
         * 通过赛事编号查询
         *
         * @param id
         * @return
         */
    public RaceFlow selectEventById(String id) {
        // 初始化Query对象,根据赛事编号查询
        Query query = new Query(Criteria.where("_id").is(id));
        return mongoTemplate.findOne(query, RaceFlow.class, "lol");
    }
        /**
         * 查询所有订单
         *
         * @return
         */
    public Map<String, Object> selectTeamList() {
        List<RaceFlow> raceFlowList = mongoTemplate.findAll(RaceFlow.class, "lol");
        List<RaceFlowVO> list = new ArrayList<>();
        for(RaceFlow raceFlow: raceFlowList){
            RaceFlowVO raceFlowVO = new RaceFlowVO();
            raceFlowVO.setId(raceFlow.getId());
            raceFlowVO.setStatus(raceFlow.getStatus());
            raceFlowVO.setEventTime(raceFlow.getEventTime());
            raceFlowVO.setEventName(raceFlow.getEventName());
            raceFlowVO.setEventStage(raceFlow.getEventStage());
            raceFlowVO.setTeamAName(raceFlow.getTeamA().getName());
            raceFlowVO.setTeamBName(raceFlow.getTeamB().getName());
            list.add(raceFlowVO);
        }
        Map<String, Object> result = new HashMap<>();
        if (list == null || list.isEmpty()) {
            result.put("code", "0");
            result.put("message", "没有相关赛事信息");
        } else {
            result.put("code", "0");
            result.put("count", list.size());
            result.put("data", list);
        }
        return result;
    }
        /**
         * 根据赛事编号删除赛程信息
         *
         * @param id
         * @return
         */
    public boolean deleteTeamById(String id) {
        // 初始化 Query 对象,根据赛事编号查询
        Query query = new Query(Criteria.where("_id").is(id));
        DeleteResult result = mongoTemplate.remove(query, RaceFlow.class, "lol");
        return result.getDeletedCount() > 0 ? true : false;
    }
}
  • Controller层(控制层):

RaceFlowController类

package com.lol.loleventdatamanagement.controller;
import com.lol.loleventdatamanagement.pojo.EventDouble;
import com.lol.loleventdatamanagement.pojo.RaceFlow;
import com.lol.loleventdatamanagement.service.RaceFlowService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;

@RestController
@RequestMapping("raceflow")
public class RaceFlowController {
    @Resource
    private RaceFlowService eventService;
    /**
     * 添加首发队员至MongoDB
     *
     * @param raceFlow
     */
    @PostMapping("add")
    public String addRaceFlow(RaceFlow raceFlow) {
        eventService.addRaceFlow(raceFlow);
        return "成功添加赛事流程,比赛即将开始---";
    }

    /**
     * 更新赛事信息
     * 添加战队信息
     * @param eventDouble
     * @return
     */
    @PostMapping("update")
    public String updateAndAddEvent(EventDouble eventDouble) {
        eventService.updateAndAddEvent(eventDouble);
        return "赛事数据更新成功";
    }
    /**
     * 通过赛事编号查询
     *
     * @param id
     * @return
     */
    @GetMapping("{id}")
    public RaceFlow selectEventById(@PathVariable String id) {
        return eventService.selectEventById(id);
    }
    /**
     * 查询所有比赛
     *
     * @return
     */
    @GetMapping("list")
    public Map<String, Object> selectTeamList() {
        return eventService.selectTeamList();
    }
    /**
     * 根据赛事编号删除比赛记录
     *
     * @param id
     * @return
     */
    @PostMapping("delete")
    public String deleteTeamById(String id) {
        eventService.deleteTeamById(id);
        return "删除成功";
    }
}

数据存储架构设计

数据库的选择

本项目内容繁多,数据类型复杂,对于赛事数据信息的存储,赛事列表需要不断的添加新的记录,假设后期赛制更新需求变更需要添加字段,对于关系新数据库又需要重新建立表格,很繁琐,但是对于MongoDB就可做到随时添加随时使用,因此将MongoDB作为数据库是优质且高效的选择。

数据存储位置

在Windows服务器(Windows Server2012RS镜像)部署MongoDB服务并实现了MongoDB分片功能:

configServer(123.57.50.204:27019/123.57.50.204:27020、123.57.50.204:27021)

shard(123.57.50.204:3000、123.57.50.204:3001、123.57.50.204:3002)

mongos(123.57.50.204:27010)

数据存储文档结构

{
    _id: 字符串类型雪花算法生成id,
    status: 最后一小场的赛程状态,
    eventTime: 赛程时间,
    eventName: "2022职业联赛",
    eventStage: "全球总决赛资格赛",
    teamA: {
        name: 战队名称,
        top: 战队上单,
        jungle: 战队打野,
        mid: 战队中单,
        adc: 战队ADC,
        support: 战队辅助
    },
    teamB: {
        name: 战队名称,
        top: 战队上单,
        jungle: 战队打野,
        mid: 战队中单,
        adc: 战队ADC,
        support: 战队辅助
    },
    _class: "com.lol.loleventdatamanagement.event.RaceFlow",
    events: [
        {
            raceFlowId: 与id一致,
            status: "进行中",
            eventA: {
                kill: 击杀数,
                baron: 大龙数,
                dragon: 小龙数,
                money: 金钱,
                tower: 防御塔数,
                outcome: 获胜情况
            },
            eventB: {
                kill: 击杀数,
                baron: 大龙数,
                dragon: 小龙数,
                money: 金钱,
                tower: 防御塔数,
                outcome: 获胜情况
            },
            _class: "com.lol.loleventdatamanagement.event.EventDouble"
        }
	……
    ]
}

系统详细功能设计与实现

系统运行环境及配置

框架:SpringMVC+Layui+Maven+MongoDB

开发语言:Java、HTML5、CSS3、JavaScript、Python

JDK:17

Python:3.10.7

Maven:3.6.3

数据库与数据库可视化管理工具:MongoDB4.2.2 、Robo 3T1.3.1

开发工具:Intellij IDEA(Ultimate Edition)2022.2.1

PyCharm(Professional Edition)2022.1.1

浏览器:Microsoft Edge107.0.1418.62 (正式版本) (64 位)

涉及到的技术:MongoDB、Springboot、lombok、layui、spider

配置Spring boot运行环境

创建项目

  • 在IDEA中新建项目,生成器选择Spring Initializr。其中语言选择Java,类型选择Maven,组与工件设置好后,名称与软件包名称随之变化。JDK版本大于等于Java版本,点击下一步。

  • Spring Boot版本默认为7.5,依赖项:Developer Tools选择Lombok,Web选择Spring Web,NoSQL选择Spring Data MongoDB,点击创建。

导入并配置Maven

  • IDEA会自动同步该项目的依赖项与插件并导入Maven,等待即可。

  • 进入IDEA设置,依次进入“构建、执行、部署——构建工具——Maven”,设置Maven主路径、用户设置文件、本地仓库。

  • 在xml中的dependencies标签下追加以下内容:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.3</version>
</dependency>
  • 在xml中的build标签下有plugin标签,此处可能会报错,可在artifactId标签后加入version标签,填入2.7.5,点击右上角的变更按钮,即可完成插件同步。

配置MongoDB

  • 在项目根目录下的src目录下存在resources文件夹,双击文件夹下的properties文件,输入spring.data.mongodb.uri = mongodb://123.57.50.204:27010/LeagueofLegends。

分片功能实现

根据数据存储位置,选择Windows Server2012R2服务器部署分片集群,下载并安装Windows版本MongoDB,在根目录下创建部署分片的目录,data与logs,创建好之后,在bin目录下运行cmd,输入如下命令用以开启服务:

mongod --port 3000 --bind_ip 0.0.0.0 --shardsvr --replSet rs-a --dbpath "C:\Program Files\mongodb_4.2.2\shardcluster\data\rs0" --logpath "C:\Program Files\mongodb_4.2.2\shardcluster\log\rs0.log"

mongod --port 3001 --bind_ip 0.0.0.0 --shardsvr --replSet rs-a --dbpath "C:\Program Files\mongodb_4.2.2\shardcluster\data\rs1" --logpath "C:\Program Files\mongodb_4.2.2\shardcluster\log\rs1.log"

mongod --port 3002 --bind_ip 0.0.0.0 --shardsvr --replSet rs-a --dbpath "C:\Program Files\mongodb_4.2.2\shardcluster\data\rs2" --logpath "C:\Program Files\mongodb_4.2.2\shardcluster\log\rs2.log"

mongod --port 27019 --bind_ip 0.0.0.0 --configsvr --replSet rs-conf --dbpath "C:\Program Files\mongodb_4.2.2\shardcluster\data\config0" --logpath "C:\Program Files\mongodb_4.2.2\shardcluster\log\config0.log"

mongod --port 27020 --bind_ip 0.0.0.0 --configsvr --replSet rs-conf --dbpath "C:\Program Files\mongodb_4.2.2\shardcluster\data\config1" --logpath "C:\Program Files\mongodb_4.2.2\shardcluster\log\config1.log"

mongod --port 27021 --bind_ip 0.0.0.0 --configsvr --replSet rs-conf --dbpath "C:\Program Files\mongodb_4.2.2\shardcluster\data\config2" --logpath "C:\Program Files\mongodb_4.2.2\shardcluster\log\config2.log"

mongos --configdb rs-conf/localhost:27019,localhost:27020,localhost:27021 --logpath "C:\Program Files\mongodb_4.2.2\shardcluster\log\mongos.log" --port 27010 --bind_ip 0.0.0.0

随后登录configserver、shard主节点的客户端,进行初始化与添加节点,再登录mongos客户端,添加分片节点;

mongos

然后输入use config,db.settings.save({“_id”:”chunksize”,”value”:1});接下来创建LeagueofLegends数据库,在该数据库写入文档;

实现数据库分片功能,sh.enableSharding(“LeagueofLegends”),为集合user创建索引,use LeagueofLegends,db.user.createIndex({“id”:1});以索引“id”作为分片键,对集合user进行分片操作,use gateway、sh.shardCollection(“LeagueofLegends.user”,{“id”:1});

最后在项目中的application.properties配置为分片集群的路由节点,连接至mongos:spring.data.mongodb.uri=mongodb://123.57.50.204:27010/LeagueofLegends即可。

赛事数据来源

为使本项目拥有一定的数据基础,本小组利用Python进行爬取数据,赛事数据来源于https://lpl.qq.com/es/lpl/2022/,采用了selenium模块对网站信息进行获取,首先向网页发起请求并通过网页链接访问相应的页面,运用selenium第三方库爬取相关数据,由于目标数据分布在单页面中(使用JavaScript单页放置元素)导致异步加载,因此需要依靠msedgedriver来模拟鼠标操作,同时,该手段需要依赖selenium.webdriver.common.by的子模块By来定位元素标签,使用browers.find_element方法来定位元素,By所支持的定位器分类如下:

  • CLASS_NAME = ‘class name’
  • CSS_SELECTOR = ‘css selector’
  • ID = ‘id’;LINK_TEXT = ‘link text’
  • NAME = ‘name’
  • PARTIAL_LINK_TEXT = ‘partial link text’
  • TAG_NAME = ‘tag name’
  • XPATH = ‘xpath’

在多次踩坑之后,解决了模拟鼠标操作之后页面不稳定以及页面焦点不在新页面上的问题,即使用time.sleep方法稳定跳转后的页面。在selenium模块爬取过程中,使用BeautifulSoup的find与find_all方法来查找元素。在所有场次的数据采集过程中,嵌套了tqdm进度条模块,使得爬取过程可视化,更加直观、清晰。使用time.perf_counter方法记录程序开始与结束时间,用于统计程序执行耗费的时间。在获取数据以后,使用json.loads()函数将str对象转换为dict(字典)对象,再使用字典和列表的方法就可以将想要的数据提取出来,并且存放到另外一个字典里面。最后将嵌入式文档写入列表,利用tqdm模块将遍历列表写入数据的过程可视化并存储到MongoDB数据库中,至此,数据采集阶段结束,所有数据已经准备就绪。

系统功能实现

预约比赛战队

在预约比赛战队页面中,设置提交按钮的“lay-submit lay-filter”属性,值为formDemo。Script标签中有对应名的按钮处理程序form.on(‘submit(formDemo)’,function(data)。点击提交按钮时,将表单中的信息传递给JavaScript处理,其中包含url、type、data、datatype属性,JavaScript程序又将表单提交的值传递至url路径中的程序处理,提交方式为 “POST”,数据为表单中传递的值。数据类型为“JSON”。

因此,对应至本项目,数据传递至RaceFlowController类中的addRaceFlow方法处理。RaceFlowController类中的addRaceFlow方法又调用对象eventService的addRaceFlow方法处理。随后将传递至EventService类对象eventService的参数赋值给形参RaceFlow类的对象raceFlow,并调用addRaceFlow方法,将订单信息写入MongoDB中。执行完毕后RaceFlowController类中的addRaceFlow方法返回“成功添加赛事流程,比赛即将开始—”。add-team页面收到返回信息之后,通过屏幕快闪的方式显示该信息。

预约比赛战队界面如图所示:

添加赛事数据

在添加赛事数据页面中,设置提交按钮的“lay-submit lay-filter”属性,值为formDemo。Script标签中有对应名的按钮处理程序form.on(‘submit(formDemo)’,function(data)。点击提交按钮时,将表单中的信息传递给JavaScript处理,其中包含url、type、data、datatype属性,JavaScript程序又将表单提交的值传递至url路径中的程序处理,提交方式为 “POST”,数据为表单中传递的值。数据类型为“JSON”。

因此,对应至本项目,数据传递至EventController类中的updateAndAddEvent方法处理。RaceFlowController类中的updateAndAddEvent方法又调用对象eventService的updateAndAddEvent方法处理。随后将传递至EventService类对象eventService的参数赋值给形参EventDouble类的对象eventDouble,随后对象eventDouble的参数传至形参Event类的对象eventA和eventB用以存储events列表中eventA和eventB字段,并调用updateAndAddEvent方法,将订单信息写入MongoDB中。执行完毕后RaceFlowController类中的updateAndAddEvent方法返回“赛事数据更新成功”。add-event页面收到返回信息之后,通过屏幕快闪的方式显示该信息。

添加赛事数据界面如图所示:

赛事数据管理

在赛事数据管理页面中,由于存在两个战队,需要设置两个时间线,设置时间线中ul标签的id为events_A和events_B,数据表格id为raceflowList,lay-filter属性为raceflowTable,设置头工具栏事“筛选/导出/打印”的id属性为toolbarDemo,设置行工具栏事件的id属性为barDemo。

因此,对应至本项目,数据传递至RaceFlowController类中的deleteTeamById方法处理。RaceFlowController类中的deleteById方法又调用对象eventService的deleteTeamById方法处理。随后将传递至RaceFlowService类对象eventService的deleteTeamById的参数赋值给形参String类的对象id,并调用mongoTemplate的remove删除查询到的赛事信息。执行完毕后RaceFlowController类中的deleteTeamById方法返回“删除成功”。events-manage页面收到返回信息之后,通过屏幕快闪的方式显示该信息。

通过输入id将数据传递至RaceFlowController类中的selectEventById方法处理。RaceFlowController类中的selectEventById方法又调用对象eventService的selectEventById方法处理。随后将传递至RaceFlowService类对象eventService的selectEventById的参数赋值给形参String类的对象id,执行完毕后RaceFlowController类中的selectEventById方法调用mongoTemplate的findOne返回查询到的订单信息。events-manage页面收到返回信息之后,将数据呈现在面板中。

数据传递至RaceFlowController类中的selectTeamList方法处理。RaceFlowController类中的selectTeamList方法又调用对象eventService的selectTeamList方法处理。随后将传递至RaceFlowService类对象eventService的selectTeamList的参数赋值给Map方法,执行完毕后RaceFlowController类中的selectTeamList方法调用mongoTemplate的findAll查询订单信息,通过for循环将数据存到list列表中。events-manage页面收到返回信息之后,将数据呈现在数据表格中。

赛事数据管理界面如图所示:

总结

在现代硬件、软件的飞速发展,人民对文化产业的消费比重日益增加的情况下,电竞赛事规模也越来越大,其中也伴随着博彩行业的介入。线上赛的公平、公正难以得到保障,而规模越来越大的情况下,管理事项越来越多,战队、选手、场地、时间、比赛器材、工作人员的统筹工作需要一个管理系统去协助赛事管理者,提高管理者管理的效率,同时保障电子竞技比赛的公平性。

本项目的设计与实现,主要是利用Java与HTML语言来完成的,能够模拟赛事从预约到结束的全过程,对于爬取到的数据可以保存在MongoDB数据库中,基本上体现了信息管理系统各方面的优点。但随着电子竞技的赛事的扩大,管理者会有更多事务处理,更多信息需要调配,所以本系统还有许多待开发功能,例如选手转会期间的自由交易市场、与游戏数据的互通、自动化规划赛程等等功能。

通过本次实践的学习,使得我们对HTML以及Java的编程和应用有了更加深刻的了解,并且在此过程中多次操作MongoDB数据库以及对相关依赖包的使用,让我们更加熟悉关系型数据库和相关技术的使用,也通过解决问题的方式,了解了更多此前仅从书面上不曾学到的东西,让我们不仅体会到了技术发展的日新月异,也感受到了技术与技术间的碰撞以及相互促进带来的创新与发展。

第一阶段:需求分析阶段。只有充分了解了用户的需求才能开发功能完整、性能良好的项目。在这个阶段,我们小组听取了每个同学对于这个网站各个功能模块的描述,并做详细的记录,同时通过英雄联盟官网的数据进行结构设计。这项工作为我们后面项目的度量提供了可靠的材料。

第二阶段:项目分析设计阶段。整个项目在这个阶段的工作要多一点,它直接关系到后一阶段的编码,所以它起到了承上启下的作用。这一阶段的主要任务包括分析项目中对象,再根据对象设计数据库,在此包括其建模设计,在完成数据库后就是数据流程图了,它大体上描述了程序走的流程,以及大体的一个架构。完成上述工作后就是类的设计了,它是根据数据流图的设计来设计的,写好每个模块的每一个类,为下一阶段做好准备。在此,我们就完成了整个系统的一个架构。

第三阶段:编码阶段。用代码将整个系统的业务逻辑表达出来。其中和遇到好多问题:对java中的好多现有的类不熟悉,使得编写的代码质量不高,代码的复用性不高,好多问题还都没有解决。

第四阶段:测试。主要是对项目所涉及的功能进行功能测试。发现问题及时解决。

通过对这门课的学习,我们对这门课程有了更深层次得到了解,也有了更浓厚的兴趣。尤其是对网页制作的过程与一些技巧手法更有了另外一番了解,对网页制作的基础知识也有了一定的掌握。

  1. 确定网页设计的内容:一个优秀的网站要有一个明确的主题,整个网站围绕这个主题,也就是你在网页设计之前要明确你这个网站有什么目的,用来做什么,所有页面都是围绕着这个内容来制作,有了明确的内容对排名有很重要的作用。
  2. 了解你网站相关的客户:用户是一个网站成败的关键,如果用户要花很多时间进入你网站很有可能用户会立即关掉你网站,或者你网站操作很不方便用户也会马上离开,这种网站是很失败的设计,只会让用户失望的离去。
  3. 做一个典型用户:一定要以用户身份亲身体验网站你才能发现问题,才知道那些需要改进,尽量不要让客户去发现问题,在前期设计时就应该把这些问题解决。

在具体的规划一个网站时,可以用树状结构先把每个页面的内容大纲列出来,尤其要制作一个大的网站(有很多页面)的时候,特别需要把这个架构规划好,也要考虑到以后可能的扩充性,免得做好以后又要一改再改整个网站的架构,很浪费时间和财力。大纲列出来后,还必须考虑每个页面之间的链接关系。是星形、树形、或是网形链接。这也是判别一个网站优劣的重要标志,因为链接混乱,层次不清的站点会造成浏览困难,影响内容的发挥。在框架定下来了后,然后开始一步一步有条理,有次序地做来,就胸有成竹得多,也会为网站将来发展打下良好的基础。

通过一步一步制作最终把自己的网页上传到互联网上,那种成就感是无法用语言形容的。在今后的闲余时间,我们将会继续学习制作网页的更多知识,使它成为自己的一项技能。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇