12系统公告的开发和首页渲染

Views: 0

逻辑

前后端交互:

前端通过/notice/开头的接口与后端交互 首页会加载最新公告显示在时间轴上 管理页面可以查看完整公告列表并进行管理操作

数据结构:

每个公告包含4个基本信息:ID、标题(title)、内容(content)和发布时间(time) 核心功能:

增:管理员可以添加新公告,系统会自动记录发布时间

删:可以按ID删除公告

改:可以修改公告的标题和内容

查:

1.  查看所有公告(按时间倒序显示)
2. 按标题关键词搜索公告
3. 分页查看公告列表

业务流程:

管理员发布公告 → 存入数据库 → 首页自动显示 → 学生/教师登录后即可查看

公告修改后所有用户看到的内容会实时更新

创建数据库表

CREATE TABLE `notice` (
 `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
 `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '公告标题',
 `content` text COLLATE utf8mb4_unicode_ci COMMENT '公告内容',
 `time` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '公告时间',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='公告信息';

entity—Notice.java

创建实体类

package com.example.entity;

public class Notice {
   private Integer id;
   private String title;
   private String content;
   private String time;

   public Integer getId() {
       return id;
  }

   public void setId(Integer id) {
       this.id = id;
  }

   public String getTitle() {
       return title;
  }

   public void setTitle(String title) {
       this.title = title;
  }

   public String getContent() {
       return content;
  }

   public void setContent(String content) {
       this.content = content;
  }

   public String getTime() {
       return time;
  }

   public void setTime(String time) {
       this.time = time;
  }
}

前端

Manager.vue

<!--仅管理员可以看到公告信息,教师和学生都看不到 index="2" 是菜单的索引-->
<el-sub-menu index="2">
 <template #title>
   <el-icon><Memo /></el-icon>
   <span>信息管理</span>
 </template>
 <el-menu-item index="/notice" v-if ="data.user.role === 'ADMIN'">
   <el-icon><Bell /></el-icon>
   <span>公告信息</span>
 </el-menu-item>
</el-sub-menu>

配置路由index.js

{ path: 'notice', component: () => import('@/views/manager/Notice.vue')},

Notice.vue

<template>
 <div>

   <div class="card" style="margin-bottom: 5px;">
     <el-input v-model="data.title" style="width: 300px; margin-right: 10px" placeholder="请输入标题查询"></el-input>
     <el-button type="primary" @click="load">查询</el-button>
     <el-button type="info" style="margin: 0 10px" @click="reset">重置</el-button>
   </div>

   <div class="card" style="margin-bottom: 5px">
     <div style="margin-bottom: 10px">
       <el-button type="primary" @click="handleAdd">新增</el-button>
     </div>
     <el-table :data="data.tableData" stripe>
       <el-table-column label="公告标题" prop="title"></el-table-column>
       <el-table-column label="公告内容" prop="content"></el-table-column>
       <el-table-column label="发布时间" prop="time"></el-table-column>
       <el-table-column label="操作" align="center" width="160">
         <template #default="scope">
           <el-button type="primary" @click="handleEdit(scope.row)">编辑</el-button>
           <el-button type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
   </div>

   <div class="card">
     <el-pagination background layout="prev, pager, next" v-model:page-size="data.pageSize" v-model:current-page="data.pageNum" :total="data.total"/>
   </div>

   <el-dialog title="公告信息" width="40%" v-model="data.formVisible" :close-on-click-modal="false" destroy-on-close>
     <el-form :model="data.form" label-width="100px" style="padding-right: 50px">
       <el-form-item label="公告标题" prop="title">
         <el-input v-model="data.form.title" autocomplete="off" />
       </el-form-item>
       <el-form-item label="公告内容" prop="content">
         <el-input type="textarea" :rows="4" v-model="data.form.content" autocomplete="off" />
       </el-form-item>
     </el-form>
     <template #footer>
     <span class="dialog-footer">
       <el-button @click="data.formVisible = false">取 消</el-button>
       <el-button type="primary" @click="save">保 存</el-button>
     </span>
     </template>
   </el-dialog>

 </div>
</template>

<script setup>
import request from "@/utils/request";
import {reactive} from "vue";
import {ElMessageBox, ElMessage} from "element-plus";


const data = reactive({
 pageNum: 1,
 pageSize: 10,
 total: 0,
 formVisible: false,
 form: {},
 tableData: [],
 title: null
})

// 分页查询
const load = () => {
 request.get('/notice/selectPage', {
   params: {
     pageNum: data.pageNum,
     pageSize: data.pageSize,
     title: data.title
  }
}).then(res => {
   data.tableData = res.data?.list
   data.total = res.data?.total
})
}

// 新增
const handleAdd = () => {
 data.form = {}
 data.formVisible = true
}

// 编辑
const handleEdit = (row) => {
 data.form = JSON.parse(JSON.stringify(row))
 data.formVisible = true
}

// 新增保存
const add = () => {
 request.post('/notice/add', data.form).then(res => {
   if (res.code === '200') {
     load()
     ElMessage.success('操作成功')
     data.formVisible = false
  } else {
     ElMessage.error(res.msg)
  }
})
}

// 编辑保存
const update = () => {
 request.put('/notice/update', data.form).then(res => {
   if (res.code === '200') {
     load()
     ElMessage.success('操作成功')
     data.formVisible = false
  } else {
     ElMessage.error(res.msg)
  }
})
}

// 弹窗保存
const save = () => {
 // data.form有id就是更新,没有就是新增
 data.form.id ? update() : add()
}

// 删除
const handleDelete = (id) => {
 ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
   request.delete('/notice/deleteById//' + id).then(res => {
     if (res.code === '200') {
       load()
       ElMessage.success('操作成功')
    } else {
       ElMessage.error(res.msg)
    }
  })
}).catch(err => {})
}

// 重置
const reset = () => {
 data.title = null
 load()
}

load()
</script>

Controller—NoticeController.java

/**
 * 公告信息模块前端操作接口入口
 * 拿到数据后,调用service层的方法,返回结果
 * 前端调用接口时,需要传入参数,调用service层的方法,返回结果
 **/
@RestController
​
@RequestMapping("/notice")
public class NoticeController {
    @Resource
//    注入NoticeService
    private NoticeService noticeService;
​
    /**
     * 新增公告信息
     * */
    @PostMapping("/add")
    public Result add(@RequestBody Notice notice){
        noticeService.add(notice);
        return Result.success();
    }
​
    /**
     * 更新公告信息
     */
    @PutMapping("/update")//更新公告信息信息,前端调用接口时,需要传入参数,调用service层的方法,返回结果
    public Result update(@RequestBody Notice notice){//接收前端传来的参数
        noticeService.updateById(notice);//调用service层的方法,返回结果
        return Result.success();
    }
​
    /**
     * 删除公告信息
     */
    @DeleteMapping("/deleteById/{id}")
    public Result deleteById(@PathVariable Integer id) {
        noticeService.deleteById(id);
        return Result.success();
    }
​
    /**
     * 分页查询
     * */
    @GetMapping("selectPage")
    public Result selectPage(Notice notice,
                             @RequestParam(defaultValue = "1") Integer pageNum,
                             @RequestParam(defaultValue = "5") Integer pageSize){
//        调用service层的方法,返回结果
        PageInfo<Notice> pageInfo = noticeService.selectPage(notice,pageNum,pageSize);
//        总数
        return Result.success(pageInfo);
    }
    /**
     * 查询所有公告信息
     */
    @GetMapping("/selectAll")
    public Result selectAll(){
        List<Notice> list = noticeService.selectAll();
        return Result.success(list);
    }
}
​​

Service—NoticeService.java

/**
 * 公告模块业务逻辑接口
 * 要把数据往数据库里存,调用mapper层的方法,返回结果
 * 业务逻辑接口调用mapper层的方法,返回结果
 */
@Service
public class NoticeService {
    //    注入NoticeMapper
    @Resource
    private NoticeMapper noticeMapper;
    /**
     * 新增公告
     */
    public void add(Notice notice) {
        notice.setTime(DateUtil.now());
        noticeMapper.insert(notice);
    }
    /**
     * 分页查询
     */
    public PageInfo<Notice> selectPage(Notice notice,Integer pageNum, Integer pageSize) {
        // ToDo 分页查询逻辑处理
        // 1. 分页查询公告信息
        // 2. 返回公告信息
        // 3. 如果没有公告信息,返回空列表
        // 4. 如果有公告信息,返回公告信息列表
        List<Notice> list;//定义一个list集合
        PageHelper.startPage(pageNum,pageSize);//分页查询
        if(ObjectUtil.isNotEmpty(notice.getTitle())){//如果title不为空,就按照title查询
            list = noticeMapper.selectByTitle(notice.getTitle());
        }else{//如果title为空,就查询所有公告信息
           list = noticeMapper.selectAll();
        }
        return PageInfo.of(list);//返回公告信息列表
    }
​
    //根据id查询公告信息,返回一个notice对象
    public void updateById(Notice notice) {//传入一个notice对象
        noticeMapper.updateById(notice);//调用mapper层的方法,返回结果
    }
​
​
    //根据id删除公告信息
    public void deleteById(Integer id) {
        noticeMapper.deleteById(id);
    }

Mapper

NoticeMapper.java

import java.util.List;
​
@Mapper
public interface NoticeMapper {
    //新增
    void insert(Notice notice);
    //查询所有
    @Select("select * from notice")
    List<Notice> selectAll();
​
    //根据title查询
    @Select("select * from notice where title like concat('%',#{title},'%')")
    List<Notice> selectByTitle(String title);
​
    //修改
    void updateById(Notice notice);
​
    //删除
    @Delete("delete from notice where id = #{id}")
    void deleteById(Integer id);
}

NoticeMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.NoticeMapper">
    <insert id="insert" parameterType="com.example.entity.Notice" useGeneratedKeys="true">
        insert into notice (title, content, time)
        values (#{title}, #{content}, #{time})
    </insert>
​
    <update id="updateById" parameterType="com.example.entity.Notice">
        update notice
        set title = #{title}, content = #{content}, time = #{time}
        where id = #{id}
--             这里的id是实体类中的属性名,不是数据库中的字段名
    </update>
</mapper>

点击没有反应怎么办?!重点学习

我们要确定的问题是什么?不要慌,是问题总有解决方法不是?!

  1. F12打开,看一下网络请求,接口和参数有没有问题
  2. 如果都对,再看下后台有没有报错
  3. 如果没有,那么就要在后台打个断点,看看具体在什么环节出问题了

比如:

额。。。不仔细公告信息写成公告信息信息了

首页渲染

Timeline: https://element-plus.org/zh-CN/component/timeline.html

Home.vue

<template>
  <div>
    <div class="card" style="line-height: 30px; margin-bottom: 5px">
      <div>欢迎您,{{ data.user.name }} 祝您今天过得开心!</div>
    </div>
​
  <!-- 公告信息 -->
    <div style="display: flex">
      <div class="card"  style="flex: 50%">
        <div style="font-size: 16px; font-weight: bold; padding: 10px 10px 20px">系统公告</div>
        <!--时间轴-->
        <el-timeline>
          <el-timeline-item
              v-for="(item, index) in data.noticeDate"
              :key="index"
              :timestamp="item.time"
          >
            <!--时间轴的内容-->
            {{item.title}}:{{ item.content }}
          </el-timeline-item>
        </el-timeline>
      </div>
        <div style="flex: 50%;margin-left: 5px">
        </div>
      </div>
  </div>
</template>
​
<script setup>
import { reactive } from "vue";
import request from "@/utils/request";
import {ElMessage} from "element-plus";
​
const data = reactive({
  // 用户信息
  user: JSON.parse(localStorage.getItem('system-user') || '{}'),
  // 公告信息
  noticeDate: [],
})
// 加载公告信息
const loadNotice = () => {
  request.get('/notice/selectAll').then(res => {
    if (res.code === '200') {
      data.noticeDate = res.data
    }else {
      ElMessage.error(res.msg)
    }
  })
}
// 初始化 加载数据
loadNotice()
</script>

Controller—NoticeController

/**
 * 查询所有公告信息
 */
@GetMapping("/selectAll")
public Result selectAll(){
    List<Notice> list = noticeService.selectAll();
    return Result.success(list);
}

Service—NoticeService.java

/**
* 查询所有 Notice 对象
*/
public List<Notice> selectAll() {
     return NoticeMapper.selectAll();
}
版权声明

本网站名称:学海拾茜
本文链接:https://www.61lyf.top/12%e7%b3%bb%e7%bb%9f%e5%85%ac%e5%91%8a%e7%9a%84%e5%bc%80%e5%8f%91%e5%92%8c%e9%a6%96%e9%a1%b5%e6%b8%b2%e6%9f%93/
本网站的文章部分内容可能来源于网络,仅供学习与参考,如有侵权,请联系站长进行核实删除。
转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处并附带原文链接!!!
站长邮箱:cyg1900@outlook.com 或studygod825@qq.com ,如不方便留言可邮件联系。
暂无评论

发送评论 编辑评论


				
上一篇
下一篇