07. 开发轮播图信息管理功能
SQL
CREATE TABLE `carousel` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`goods_id` int DEFAULT NULL COMMENT '商品',
`img` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '图片',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='轮播图信息';
开发后端接口
Carousel.java
package com.example.entity;
public class Carousel {
/**主键ID */
private Integer id;
/**商品 */
private Integer goodsId;
private String goodsName;
/**图片 */
private String img;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getGoodsId() {
return goodsId;
}
public void setGoodsId(Integer goodsId) {
this.goodsId = goodsId;
}
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
}
CarouselMapper.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.CarouselMapper">
<select id="selectAll" resultType="com.example.entity.Carousel">
select carousel.*, goods.name as goodsName from `carousel`
left join goods on carousel.goods_id = goods.id
<where>
<if test="goodsName != null"> and goods.name like concat('%', #{goodsName}, '%')</if>
</where>
order by carousel.id desc
</select>
<select id="selectById" resultType="com.example.entity.Carousel">
select * from `carousel` where id = #{id}
</select>
<delete id="deleteById">
delete from `carousel` where id = #{id}
</delete>
<insert id="insert" parameterType="com.example.entity.Carousel" useGeneratedKeys="true">
insert into `carousel`
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="goodsId != null">goods_id,</if>
<if test="img != null">img,</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="goodsId != null">#{goodsId},</if>
<if test="img != null">#{img},</if>
</trim>
</insert>
<update id="updateById" parameterType="com.example.entity.Carousel">
update `carousel`
<set>
<if test="id != null">
id = #{id},
</if>
<if test="goodsId != null">
goods_id = #{goodsId},
</if>
<if test="img != null">
img = #{img},
</if>
</set>
where id = #{id}
</update>
</mapper>
开发前端页面


Carousel.vue
<template>
<div>
<div class="card" style="margin-bottom: 5px;">
<el-input v-model="data.goodsName" 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 prop="goodsName" label="商品"></el-table-column>
<el-table-column prop="img" label="图片">
<template #default="scope">
<el-image v-if="scope.row.img" :src="scope.row.img" :preview-src-list="[scope.row.img]" preview-teleported style="width: 100px; height: 70px;"></el-image>
</template>
</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 @current-change="load" background layout="total, prev, pager, next" v-model:page-size="data.pageSize" v-model:current-page="data.pageNum" :total="data.total"/>
</div>
<el-dialog title="轮播图信息" width="30%" v-model="data.formVisible" :close-on-click-modal="false" destroy-on-close>
<el-form ref="formRef" :model="data.form" :rules="data.rules" label-width="80px" style="padding-right: 30px; padding-top: 20px">
<el-form-item label="商品" prop="goodsId">
<el-select style="width: 100%" v-model="data.form.goodsId">
<el-option v-for="item in data.goodsList" :key="item.id" :value="item.id" :label="item.name"></el-option>
</el-select>
</el-form-item>
<el-form-item label="图片" prop="img">
<el-upload
:action="baseUrl + '/files/upload'"
:on-success="handleFileUpload"
list-type="picture"
:show-file-list="false"
>
<img v-if="data.form.img" style="width: 200px; height: 100px; border-radius: 5px; " :src="data.form.img" alt="">
<div v-else style="width: 200px; height: 150px; border-radius: 5px; border: 1px dashed #ccc; display: flex; align-items: center; justify-content: center">上传图片</div>
</el-upload>
</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, ref} from "vue";
import {ElMessageBox, ElMessage} from "element-plus";
const formRef = ref()
const data = reactive({
pageNum: 1,
pageSize: 10,
total: 0,
formVisible: false,
form: {},
tableData: [],
goodsList: [],
goodsName: null,
rules: {
goodsId: [
{ required: true, message: '请选择商品', trigger: 'change' },
],
img: [
{ required: true, message: '请上传图片', trigger: 'blur' },
]
}
})
const baseUrl = import.meta.env.VITE_BASE_URL
const handleFileUpload = (res) => {
data.form.img = res.data
}
request.get('/goods/selectAll').then(res => {
data.goodsList = res.data
})
// 分页查询
const load = () => {
request.get('/carousel/selectPage', {
params: {
pageNum: data.pageNum,
pageSize: data.pageSize,
goodsName: data.goodsName
}
}).then(res => {
data.tableData = res.data?.list
data.total = res.data?.total
})
}
load()
// 新增
const handleAdd = () => {
data.form = {}
data.formVisible = true
}
// 编辑
const handleEdit = (row) => {
data.form = JSON.parse(JSON.stringify(row))
data.formVisible = true
}
// 新增保存
const add = () => {
request.post('/carousel/add', data.form).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
data.formVisible = false
} else {
ElMessage.error(res.msg)
}
})
}
// 编辑保存
const update = () => {
request.put('/carousel/update', data.form).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
data.formVisible = false
} else {
ElMessage.error(res.msg)
}
})
}
// 弹窗保存
const save = () => {
formRef.value.validate(valid => {
if (valid) {
// data.form有id就是更新,没有就是新增
data.form.id ? update() : add()
}
})
}
// 删除
const handleDelete = (id) => {
ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
request.delete('/carousel/delete/' + id).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
} else {
ElMessage.error(res.msg)
}
})
}).catch(err => {})
}
// 重置
const reset = () => {
data.goodsName = null
load()
}
</script>