系统公告表
CREATE TABLE `notice` (
`id` int(10) 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
public class Notice {
private Integer id;
private String title;
private String content;
private String time;
}
Mapper
public interface NoticeMapper {
int insert(Notice notice);
void updateById(Notice notice);
void deleteById(Integer id);
@Select("select * from `notice` where id = #{id}")
Notice selectById(Integer id);
List<Notice> selectAll(Notice notice);
}
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.NoticeMapper">
<select id="selectAll" resultType="com.example.entity.Notice">
select * from `notice`
<where>
<if test="title != null"> and title like concat('%', #{title}, '%')</if>
</where>
</select>
<delete id="deleteById">
delete from `notice`
where id = #{id}
</delete>
<!-- insert into notice (username, password, ...) values ('notice', 'notice', ...) -->
<insert id="insert" parameterType="com.example.entity.Notice" useGeneratedKeys="true">
insert into `notice`
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="title != null">title,</if>
<if test="content != null">content,</if>
<if test="time != null">time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="title != null">#{title},</if>
<if test="content != null">#{content},</if>
<if test="time != null">#{time},</if>
</trim>
</insert>
<update id="updateById" parameterType="com.example.entity.Notice">
update `notice`
<set>
<if test="title != null">
title = #{title},
</if>
<if test="content != null">
content = #{content},
</if>
<if test="time != null">
time = #{time},
</if>
</set>
where id = #{id}
</update>
</mapper>
Service
@Service
public class NoticeService {
@Resource
private NoticeMapper noticeMapper;
public void add(Notice notice) {
notice.setTime(DateUtil.now());
noticeMapper.insert(notice);
}
public void updateById(Notice notice) {
noticeMapper.updateById(notice);
}
public void deleteById(Integer id) {
noticeMapper.deleteById(id);
}
public void deleteBatch(List<Integer> ids) {
for (Integer id : ids) {
noticeMapper.deleteById(id);
}
}
public Notice selectById(Integer id) {
return noticeMapper.selectById(id);
}
public List<Notice> selectAll(Notice notice) {
return noticeMapper.selectAll(notice);
}
public PageInfo<Notice> selectPage(Notice notice, Integer pageNum, Integer pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<Notice> list = noticeMapper.selectAll(notice);
return PageInfo.of(list);
}
}
Controller
@RestController
@RequestMapping("/notice")
public class NoticeController {
@Resource
private NoticeService noticeService;
/**
* 新增
*/
@PostMapping("/add")
public Result add(@RequestBody Notice notice) {
noticeService.add(notice);
return Result.success();
}
/**
* 修改
*/
@PutMapping("/update")
public Result update(@RequestBody Notice notice) {
noticeService.updateById(notice);
return Result.success();
}
/**
* 单个删除
*/
@DeleteMapping("/delete/{id}")
public Result delete(@PathVariable Integer id) {
noticeService.deleteById(id);
return Result.success();
}
/**
* 批量删除
*/
@DeleteMapping("/delete/batch")
public Result delete(@RequestBody List<Integer> ids) {
noticeService.deleteBatch(ids);
return Result.success();
}
/**
* 单个查询
*/
@GetMapping("/selectById/{id}")
public Result selectById(@PathVariable Integer id) {
Notice notice = noticeService.selectById(id);
return Result.success(notice);
}
/**
* 查询所有
*/
@GetMapping("/selectAll")
public Result selectAll(Notice notice) {
List<Notice> list = noticeService.selectAll(notice);
return Result.success(list);
}
/**
* 分页查询
*/
@GetMapping("/selectPage")
public Result selectPage(Notice notice,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
PageInfo<Notice> pageInfo = noticeService.selectPage(notice, pageNum, pageSize);
return Result.success(pageInfo);
}
}
页面
<template>
<div>
<div class="card" style="margin-bottom: 5px">
<el-input v-model="data.title" prefix-icon="Search" style="width: 240px; margin-right: 10px" placeholder="请输入公告标题查询"></el-input>
<el-button type="info" plain @click="load">查询</el-button>
<el-button type="warning" plain style="margin: 0 10px" @click="reset">重置</el-button>
</div>
<div class="card" style="margin-bottom: 5px">
<el-button type="primary" plain @click="handleAdd">新增</el-button>
<el-button type="danger" plain @click="delBatch">批量删除</el-button>
</div>
<div class="card" style="margin-bottom: 5px">
<el-table stripe :data="data.tableData" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="title" label="公告标题" />
<el-table-column prop="content" label="公告内容" />
<el-table-column prop="time" label="发布时间" />
<el-table-column label="操作" width="100" fixed="right">
<template v-slot="scope">
<el-button type="primary" circle :icon="Edit" @click="handleEdit(scope.row)"></el-button>
<el-button type="danger" circle :icon="Delete" @click="del(scope.row.id)"></el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="card" v-if="data.total">
<el-pagination @current-change="load" background layout="prev, pager, next" :page-size="data.pageSize" v-model:current-page="data.pageNum" :total="data.total" />
</div>
<el-dialog title="公告信息" v-model="data.formVisible" width="40%" destroy-on-close>
<el-form ref="form" :model="data.form" label-width="70px" style="padding: 20px">
<el-form-item prop="title" label="公告标题">
<el-input v-model="data.form.title" placeholder="请输入公告标题"></el-input>
</el-form-item>
<el-form-item prop="content" label="公告内容">
<el-input type="textarea" :rows="4" v-model="data.form.content" placeholder="请输入公告内容"></el-input>
</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 {reactive} from "vue";
import request from "@/utils/request.js";
import {ElMessage, ElMessageBox} from "element-plus";
import {Delete, Edit} from "@element-plus/icons-vue";
const data = reactive({
formVisible: false,
form: {},
tableData: [],
pageNum: 1,
pageSize: 10,
total: 0,
title: null,
ids: []
})
const load = () => {
request.get('/notice/selectPage', {
params: {
pageNum: data.pageNum,
pageSize: data.pageSize,
title: data.title
}
}).then(res => {
if (res.code === '200') {
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') {
ElMessage.success('操作成功')
data.formVisible = false
load()
} else {
ElMessage.error(res.msg)
}
})
}
const update = () => {
request.put('/notice/update', data.form).then(res => {
if (res.code === '200') {
ElMessage.success('操作成功')
data.formVisible = false
load()
}
})
}
const save = () => {
data.form.id ? update() : add()
}
const del = (id) => {
ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
request.delete('/notice/delete/' + id).then(res => {
if (res.code === '200') {
ElMessage.success("删除成功")
load()
} else {
ElMessage.error(res.msg)
}
})
}).catch(err => {
console.error(err)
})
}
const delBatch = () => {
if (!data.ids.length) {
ElMessage.warning("请选择数据")
return
}
ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
request.delete("/notice/delete/batch", {data: data.ids}).then(res => {
if (res.code === '200') {
ElMessage.success('操作成功')
load()
} else {
ElMessage.error(res.msg)
}
})
}).catch(err => {
console.error(err)
})
}
const handleSelectionChange = (rows) => {
data.ids = rows.map(v => v.id)
}
const reset = () => {
data.title = null
load()
}
load()
</script>
管理端首页渲染
Timeline 时间线:https://element-plus.org/zh-CN/component/timeline.html
<div style="display: flex">
<div class="card" style="flex: 50%; height: 350px">
<div style="font-weight: bold; font-size: 18px; padding: 10px 0 30px 10px">系统公告</div>
<el-timeline style="max-width: 600px">
<el-timeline-item
v-for="(item, index) in data.noticeData"
:key="index"
:timestamp="item.time"
>
{{ item.content }}
</el-timeline-item>
</el-timeline>
</div>
<div style="flex: 50%"></div>
</div>
const loadNotice = () => {
request.get('/notice/selectAll').then(res => {
if (res.code === '200') {
data.noticeData = res.data
} else {
ElMessage.error(res.msg)
}
})
}
loadNotice()
前台渲染
<div class="front-notice"><el-icon><Bell /></el-icon>公告:{{ data.top }}</div>
const loadNotice = () => {
request.get('/notice/selectAll').then(res => {
data.noticeData = res.data
let i = 0
if (data.noticeData && data.noticeData.length) {
data.top = data.noticeData[0].content
setInterval(() => {
data.top = data.noticeData[i].content
i++
if (i === data.noticeData.length) {
i = 0
}
}, 2500)
}
})
}
loadNotice()
.front-notice {
padding: 5px 20px;
color: #666;
font-size: 12px;
display: flex;
align-items: center;
}