SpringBoot+LayUI+MybatisPlus 前后端分离 实现系统公告通知

前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java快一年时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。首先给各位粉丝朋友们道个歉,在2022年上半年中,我因为参加实习、做毕设和写论文,以及毕业答辩等诸多原因,不得不停更之前的博客系列,不过现在我忙完后就又回来了,后续将会给大家分享更多的编程干货。
最近这段时间我会将在毕设项目的编写过程中所遇到的问题以及解决问题的方法进行总结,整理成这个 SpringBoot+LayUI前后端分离项目实战系列 。今天分享的问题是:如何使用SpringBootLayUI来实现系统公告通知功能,具体解决方案如下,请各位小伙伴们耐心观看:

1.SpringBoot后端代码

由于我使用的持久层是优秀的Mybatis-Plus框架,可以省去基本增删改查的编写,所以这里只展示Sevice层和Controller层的实现代码

1.1 SportInfoService服务层接口的实现代码

package com.rz.sport_manager.service;

/**
 * @ClassName SportInfoService
 * @Description 运动会信息表 Service层接口
 * @Author 狂奔de蜗牛rz
 * @Date 2022/05/24
 */
public interface SportInfoService extends IService<SportInfo> {
    
    /**
     * 获取最新五条且已发布的运动会信息
     * @return JsonResult<List<SportVo>> 泛型为List<SportVo>的JsonResult结果集
     */
    public JsonResult<List<SportVo>> getLastFifthIsPublishedSportInfoList();

}

1.2 SportInfoServiceImpl服务层接口实现类的实现代码

package com.rz.sport_manager.service.impl;

/**
 * @ClassName SportInfoServiceImpl
 * @Description 运动会信息表 Service层接口实现类
 * @Author 狂奔de蜗牛rz
 * @Date 2022/05/24
 */

// 使用@Service注解, 将该类注册为Service层, 交由Spring的IOC容器统一管理
@Service
public class SportInfoServiceImpl extends ServiceImpl<SportInfoMapper, SportInfo> implements SportInfoService {
 
    // 通过类型自动装配SportInfoMapper接口
    @Autowired
    private SportInfoMapper sportInfoMapper;
    
    /**
     * 获取最新五条且已发布的运动会信息
     * @return JsonResult<List<SportVo>> 泛型为List<SportVo>的JsonResult结果集
     */
    @Override
    public JsonResult<List<SportVo>> getLastFifthIsPublishedSportInfoList() {
        // 创建泛型为sportInfo实体类的QueryWrapper对象
        QueryWrapper<SportInfo> queryWrapper = new QueryWrapper<>();
        // 设置查询条件为状态为1(即运动会信息已公布)
        queryWrapper.eq("status",1);
        // 根据更新时间升序排列
        queryWrapper.orderByDesc(true,"sport_id");
        // 创建sportIPage(存储最新五条的运动会信息)集合
        IPage<SportInfo> sportIPage = new Page<>(1,5);
        // 将sportIPage(存储运动会分页信息的集合)传入到selectPage(查询分页)方法中, queryWrapper参数为null, 获取运动会分页结果(result)
        IPage<SportInfo> result = sportInfoMapper.selectPage(sportIPage, queryWrapper);

        // 获取sportInfoList集合(用于存储已发布的运动会信息的List集合)
        List<SportInfo> sportInfoList = result.getRecords();
        // 创建一个ArrayList集合sportVoList(用来存储sportVo(运动会视图对象)信息)
        List<SportVo> sportVoList = new ArrayList<>();
        // 使用foreach循环遍历sportInfoList(存储分页结果中的所有运动会记录信息的List集合)
        for (SportInfo sportInfo : sportInfoList) {
            // 创建SportVo(运动会视图对象)
            SportVo sportVo = new SportVo();
            // 将SportInfo(运动会信息实体类)中的数据复制到SportVo(运动会视图对象)中
            BeanUtils.copyProperties(sportInfo,sportVo);
            // 将SportVo(运动会视图对象)添加到sportVoList(存储sportVo(运动会视图对象)信息的List集合)
            sportVoList.add(sportVo);
        }
        // 返回值为调用JsonResult结果集的batchDataSuccess方法, 需传入两个参数(分页数据的总行数和存储运动会视图对象的List集合)
        return JsonResult.batchDataSuccess((int) result.getTotal(),sportVoList);
    }
    
}

上面出现的SportVo其实就是 SportInfo(运动会信息实体类)的视图对象,具体代码我就不进行展示了。

1.3 SportInfoController控制层的实现代码

package com.rz.sport_manager.controller;

/**
 * @ClassName SportInfoController
 * @Description 运动会信息表 前端控制器
 * @Author 狂奔de蜗牛rz
 * @Date 2022/05/24
 */
//使用@Controller注解, 使当前类实现Controller接口, 并交由Spring容器统一管理
@Controller
//使用@RequestMapping注解, 设置get类型的请求映射路径
@RequestMapping("/sport_manager/sport_info")
public class SportInfoController {
    
    // 通过类型自动装配SportInfoService接口
    @Autowired
    private SportInfoService sportInfoService;
    
    /**
     * 获取最新五条且已发布的运动会信息
     * @return JsonResult<List<SportVo>> 泛型为List<SportVo>的JsonResult结果集
     */
    // 使用@GetMapping注解, 设置请求映射路径, 请求方式为get类型
    @GetMapping("/getLastFifthIsPublishedSportInfoList")
    // 使用@ResponseBody注解, 把控制视图方法返回到请求页面上
    @ResponseBody
    public JsonResult<List<SportVo>> getLastFifthIsPublishedSportInfoList(){
        // 返回值为调用sportInfoService接口的getLastFifthIsPublishedSportInfoList方法, 获取最新五条且已发布的运动会信息
        return sportInfoService.getLastFifthIsPublishedSportInfoList();
    }
    
}

前面的代码中反复使用到了一个工具类JsonResult,为了方便大家理解,我把实现代码也展示一下:

1.4 JsonResult工具类的实现代码

package com.rz.sport_manager.utils;

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

import java.io.Serializable;

/**
 * @ClassName JsonResult
 * @Description 处理JSON格式的数据结果
 * @Author 狂奔de蜗牛rz
 * @Date 2022/02/24
 */

// 使用@Data注解,引入无参构造器, set和get方法, 以及toString方法等
@Data
// 使用@AllArgsConstructor注解, 引入有参构造方法
@AllArgsConstructor
// 使用@NoArgsConstructor注解, 再次引入无参构造方法, 防止被有参构造覆盖
@NoArgsConstructor
public class  JsonResult<T> implements Serializable {

    /**
     * 返回的状态码: 0表示成功, 1表示失败
     */
    private Integer code;

    /**
     * 返回的状态信息: success表示成功, failure表示失败
     */
    private String msg;

    /**
     * 返回的行数
     */
    private Integer count;

    /**
     * 返回的数据
     */
    private T data;

    /**
     * 单条数据执行成功
     * @param data :返回的数据
     * @return JsonResult<T>
     */
     public static <T> JsonResult<T> oneDataSuccess(T data) {
       //设置单条数据执行成功的状态码,信息以及行数和数据,并将其返回
       return new JsonResult<T>(0,"oneDataSuccess",1,data);
    }

    /**
     * 单条数据执行失败
     * @return JsonResult<T>
     */
    public static <T> JsonResult<T> oneDataFailure() {
        //设置单条数据执行失败的状态码,信息以及行数和数据,并将其返回
        return new JsonResult<T>(1,"oneDataFailure",0,null);
    }

    /**
     * 批量数据执行成功
     * @param count :返回的行数
     * @param data :返回的数据
     */
    public static <T> JsonResult<T> batchDataSuccess(Integer count,T data) {
        //设置多条数据执行失败的状态码,信息以及行数和数据,并将其返回
        return new JsonResult<T>(0,"batchDataSuccess",count,data);
    }

    /**
     * 批量数据执行失败
     * @return JsonResult<T>
     */
    public static <T> JsonResult<T> batchDataFailure() {
        //设置多条数据执行失败的状态码,信息以及行数和数据,并将其返回
        return new JsonResult<T>(1,"batchDataFailure",0,null);
    }

}

后端的主要实现代码基本就是上述这些了,如对其中的实现代码存在疑惑,可以随时私聊我!


2.LayUI前端代码

主要功能就是在系统的后台首页的系统公告区域上展示已经发布的运动会报名信息,其页面代码和显示效果如下所示:

2.1 系统公告的前端实现代码

<!--页面样式-->
<style>
    .welcome .layui-card {border:1px solid #f2f2f2;border-radius:5px;}
    .welcome .layuimini-notice:hover {background:#f6f6f6;}
    .welcome .layuimini-notice {padding:7px 16px;clear:both;font-size:12px !important;cursor:pointer;position:relative;transition:background 0.2s ease-in-out;}
    .welcome .layuimini-notice-title {padding-right:70px !important;text-overflow:ellipsis !important;overflow:hidden !important;white-space:nowrap !important;}
    .welcome .layuimini-notice-title {line-height:28px;font-size:14px;}
    .welcome .layuimini-notice-extra {position:absolute;top:50%;margin-top:-8px;right:16px;display:inline-block;height:16px;color:#999;}
</style>
<div class="layuimini-container layuimini-page-anim">
    <div class="layuimini-main welcome">
        <div class="layui-row layui-col-space20">
            <div class="layui-col-md12">
                <div class="layui-row layui-col-space15">
                    
                <!--系统公告-->
                    <div class="layui-col-md6">
                        <div class="layui-card">
                            <div class="layui-card-header"><i class="fa fa-bullhorn icon icon-tip"></i>系统公告</div>
                            <div class="layui-card-body layui-text">

                                <!-- 系统公告的通知详情 -->
                                <div id="notice" class="layui-card">
                                    <!-- 存放模板的script标签 -->
                                    <script type="text/html" id="noticeTemplate">
                        <!-- 使用layui的each循环, 遍历数据集合信息(注意: 这里一定要使用d.data; 参数index表示集合下标, item表示集合元素) -->
                        {{# layui.each(d.data,function(index,item){ }}
                        <div class="layuimini-notice">
                            <!-- class选择器为"layuimini-notice-title"的div盒子用于存储公告通知中的标题 -->
                            <!-- 判断当前元素下标是否位于集合的前两位, 若为前两位, 则在运动会名称后加上new的字样 -->
                            {{# if(index<=1) { }}
                            <!-- 遍历每个元素值均使用 {{ item.字段名 }} 格式(注意: {{后无需加#号) -->
                            <div class="layuimini-notice-title">{{ item.sportName }}报名开启&nbsp;&nbsp;<span class="label layui-bg-red">new</span></div>
                            {{# } else { }}
                            <!-- 若当前元素下标不位于集合中的前两位, 则无需显示new字样 -->
                            <div class="layuimini-notice-title">{{ item.sportName }}报名开启</div>
                            {{# } }}
                            <!-- class选择器为"layuimini-notice-extra"的div盒子用于存储公告通知中的发布时间 -->
                            <div class="layuimini-notice-extra">{{ item.createTime }}</div>
                            <!-- class选择器为"layuimini-notice-content"的div盒子用于存储公告通知的具体内容, 使用layui-hide将内容隐藏, 在查看详情时展示 -->
                            <div class="layuimini-notice-content layui-hide">
                                <!-- 仍旧是遍历每个元素值, 也是使用 {{ item.字段名 }} 的格式 -->
                                <span style="font-size:14px;font-weight: bolder;color: #000000">运动会名:</span>{{ item.sportName }} <br>
                                <span style="font-size:14px;font-weight: bolder;color: #000000">举办场地:</span>{{ item.place }} <br>
                                <span style="font-size:14px;font-weight: bolder;color: #000000">举办方:</span>{{ item.holder }} <br>
                                <span style="font-size:14px;font-weight: bolder;color: #000000">举办时间:</span>{{ item.startTime}}{{ item.endTime }} <br>
                                <span style="font-size:14px;font-weight: bolder;color: #000000">详情描述:</span>{{ item.description }} <br>
                            </div>
                        </div>
                        <!-- 循环结束记得加上这个 -->
                        {{# }); }}
                    </script>
                                </div>

                            </div>
                        </div>
                    </div>

                </div>
            </div>
        </div>
    </div>
</div>
<script>
    /* 加载layer,form和table等实例 */
    layui.use(['layer','jquery','laytpl'], function () {
        // 获取jquery对象
        var $ = layui.jquery,
            // 获取layer对象
            layer = layui.layer,
            // 获取laytpl对象
            laytpl = layui.laytpl;
        
        // 已发布的运动会信息
        let sportInfoList;    
        /* 编写获取已发布的运动会信息的ajax请求 */
        $.ajax({
            // 请求方式为GET
            type: 'GET',
            // 数据接口:请求JSON数据到后端
            url: 'http://localhost:8080/sport_manager/sport_info/getLastFifthIsPublishedSportInfoList',
            // 数据类型为json格式
            dataType: 'json',
            // 内容类型为json
            contentType: 'application/json',
            // 开启同步
            async: false,
            /* 处理请求的回调函数 */
            success: function (data) {
                // 若返回的状态码为0,则执行成功处理操作
                if(data.code === 0) {
                    // 运动会信息为当前数据
                    sportInfoList = data;
                    // console.log(sportInfoList);
                // 若返回的状态码为1,则执行失败处理操作                
                } else {
                    layer.msg('获取已发布的运动会信息失败!', {icon: 2});
                }
            }
        });

        // 获取通知模板中的html页面代码(noticeTemplate对应script模板中的id选择器)
        let noticeTpl = noticeTemplate.innerHTML,
            // 根据id选择器定位到公告通知的div盒子
            notice = document.getElementById('notice'); 
        // console.log(sportInfoList);
        //渲染模板信息(noticeTpl是模板引擎的html代码, sportInfoList是上面获取到的已发布运动会信息, html用于存储div盒子中的代码)
        laytpl(noticeTpl).render(sportInfoList, function(html) {
           // 获取模板引擎中的html代码, 将其赋值到html参数中去   
           notice.innerHTML = html;
        });

        /**
         * 查看公告详情信息的点击事件
         **/
        $('body').on('click', '.layuimini-notice', function () {
            // 获取公告通知中的标题文本(由于前两条数据的标题后面存在new字样, 这里将其进行替换
            var title = $(this).children('.layuimini-notice-title').text().replace("new",""),
                // 获取公告通知中的发布时间  
                noticeTime = $(this).children('.layuimini-notice-extra').text(),
                // 获取公告通知中的通知详情
                content = $(this).children('.layuimini-notice-content').html();
            // 绘制公告通知详情的html页面(其中\n用于换行)
            var html = '<div style="padding:15px 20px; text-align:justify; line-height: 22px;border-bottom:1px solid #e2e2e2;background-color: #ffffff;color: #000000">\n' +
                '<div style="text-align: center;margin-bottom: 20px;font-weight: bold;border-bottom:1px solid #718fb5;padding-bottom: 5px">\n' +
                '<h3 class="text-danger" style="font-size:16px;font-weight:bolder;color:red;">' + title + '</h3></div>\n' +
                '<div style="font-size: 15px">' + content + '</div>\n' +
                '</div>\n';
            // 打开公告通知页面    
            parent.layer.open({
                // 类型为页面层
                type: 1,
                // 设置公告通知标题
                title: ['系统公告'+ '<span style="float: right;right: 1px;font-size: 14px;color: #b1b3b9;margin-top: 1px">' + noticeTime + '</span>', 'font-size:18px;'],
                // 设置页面的宽高
                area: ['500px','500px'],
                // 开启遮罩效果
                shade: 0.3,
                // 对应公告通知div标签的id 
                id: 'layuimini-notice',
                // 弹出框的按钮
                btn: ['查看', '取消'],
                // 按钮排列为居中对齐
                btnAlign: 'c',
                // 窗口拖拽类型 
                moveType: 1,
                // 页面内容为上面绘制的公告通知详情
                content: html,
                // 请求成功的回调函数(其中layero表示打开的弹出层页面) 
                success: function (layero) {
                    // 首先在弹出层页面中定位btn按钮
                    var btn = layero.find('.layui-layer-btn');
                    // 然后根据btn按钮继续定位第一个btn(即查看)按钮
                    btn.find('.layui-layer-btn0').attr({
                        // 设置点击按钮后跳转地址
                        href: 'https://gitee.com/zhongshaofa/layuimini',
                        // 打开方式为当前页
                        target: '_self'
                    });
                }
            });
        });

    });
</script>

2.2 系统公告的页面显示效果

2.2.1 系统公告整体显示效果

在这里插入图片描述

2.2.2 点击后查看公告详情

在这里插入图片描述


以上就是如何使用SpringBootLayUI来实现系统公告通知功能的所有分享内容了。欢迎各位小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!


参考文档链接LayUI模板文档

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔の蜗牛rz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值