07. 开发物品信息管理功能
SQL
CREATE TABLE `items` (
`id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '名称',
`img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '图片',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '描述',
`requirement` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '交换条件',
`status` tinyint(1) DEFAULT NULL COMMENT '上架状态',
`user_id` int DEFAULT NULL COMMENT '上传人',
`time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '上传时间',
`check_status` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '审核状态',
`reason` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '审核理由',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='物品信息';
Element-Plus 组件宝库
https://www.yuque.com/xiaqing-en2ii/skflxg/hzi02h8qfizne3yv
开发后端接口
Items.java
package com.example.entity;
public class Items {
/**ID */
private Integer id;
/**名称 */
private String name;
/**图片 */
private String img;
/**描述 */
private String description;
/**交换条件 */
private String requirement;
/**上架状态 */
private Boolean status;
/**上传人 */
private Integer userId;
private String userName;
/**上传时间 */
private String time;
private String checkStatus;
private String reason;
public String getCheckStatus() {
return checkStatus;
}
public void setCheckStatus(String checkStatus) {
this.checkStatus = checkStatus;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getRequirement() {
return requirement;
}
public void setRequirement(String requirement) {
this.requirement = requirement;
}
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
ItemsController.java
package com.example.controller;
import com.example.common.Result;
import com.example.entity.Items;
import com.example.service.ItemsService;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 前端操作接口
**/
@RestController
@RequestMapping("/items")
public class ItemsController {
@Resource
private ItemsService itemsService;
/**
* 新增
*/
@PostMapping("/add")
public Result add(@RequestBody Items items) {
itemsService.add(items);
return Result.success();
}
/**
* 删除
*/
@DeleteMapping("/delete/{id}")
public Result deleteById(@PathVariable Integer id) {
itemsService.deleteById(id);
return Result.success();
}
/**
* 用户上架或者下架物品
*/
@PutMapping("/updateStatus")
public Result updateStatus(@RequestBody Items items) {
itemsService.updateById(items);
return Result.success();
}
/**
* 用户修改
*/
@PutMapping("/update")
public Result updateById(@RequestBody Items items) {
items.setCheckStatus("待审核");
itemsService.updateById(items);
return Result.success();
}
/**
* 管理员审核
*/
@PutMapping("/updateForAdmin")
public Result updateByIdForAdmin(@RequestBody Items items) {
itemsService.updateById(items);
return Result.success();
}
/**
* 根据ID查询
*/
@GetMapping("/selectById/{id}")
public Result selectById(@PathVariable Integer id) {
Items items = itemsService.selectById(id);
return Result.success(items);
}
/**
* 查询所有
*/
@GetMapping("/selectAll")
public Result selectAll(Items items) {
List<Items> list = itemsService.selectAll(items);
return Result.success(list);
}
/**
* 分页查询
*/
@GetMapping("/selectPage")
public Result selectPage(Items items,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
PageInfo<Items> page = itemsService.selectPage(items, pageNum, pageSize);
return Result.success(page);
}
}
ItemsMapper.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.ItemsMapper">
<select id="selectAll" resultType="com.example.entity.Items">
select items.*, user.name as userName from `items`
left join user on items.user_id = user.id
<where>
<if test="name != null"> and items.name like concat('%', #{name}, '%')</if>
<if test="userId != null"> and items.user_id = #{userId}</if>
</where>
order by items.id desc
</select>
<insert id="insert" parameterType="com.example.entity.Items" useGeneratedKeys="true">
insert into `items`
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="name != null">name,</if>
<if test="img != null">img,</if>
<if test="description != null">description,</if>
<if test="requirement != null">requirement,</if>
<if test="status != null">status,</if>
<if test="userId != null">user_id,</if>
<if test="time != null">time,</if>
<if test="checkStatus != null">check_status,</if>
<if test="reason != null">reason,</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="name != null">#{name},</if>
<if test="img != null">#{img},</if>
<if test="description != null">#{description},</if>
<if test="requirement != null">#{requirement},</if>
<if test="status != null">#{status},</if>
<if test="userId != null">#{userId},</if>
<if test="time != null">#{time},</if>
<if test="checkStatus != null">#{checkStatus},</if>
<if test="reason != null">#{reason},</if>
</trim>
</insert>
<update id="updateById" parameterType="com.example.entity.Items">
update `items`
<set>
<if test="id != null">
id = #{id},
</if>
<if test="name != null">
name = #{name},
</if>
<if test="img != null">
img = #{img},
</if>
<if test="description != null">
description = #{description},
</if>
<if test="requirement != null">
requirement = #{requirement},
</if>
<if test="status != null">
status = #{status},
</if>
<if test="userId != null">
user_id = #{userId},
</if>
<if test="time != null">
time = #{time},
</if>
<if test="checkStatus != null">
check_status = #{checkStatus},
</if>
<if test="reason != null">
reason = #{reason},
</if>
</set>
where id = #{id}
</update>
</mapper>
开发前端页面
Items.vue
<template>
<div>
<div class="card" style="margin-bottom: 5px;">
<el-input v-model="data.name" 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" v-if="data.user.role === '普通用户'">
<el-button type="primary" @click="handleAdd">新增</el-button>
</div>
<el-table :data="data.tableData" stripe>
<el-table-column prop="name" label="名称"></el-table-column>
<el-table-column prop="img" label="图片">
<template #default="scope">
<img :src="scope.row.img" alt="" style="width: 50px; height: 50px; border-radius: 5px">
</template>
</el-table-column>
<el-table-column prop="description" label="描述" show-overflow-tooltip></el-table-column>
<el-table-column prop="requirement" label="交换条件" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="上传人" v-if="data.user.role === '管理员'"></el-table-column>
<el-table-column prop="time" label="上传时间"></el-table-column>
<el-table-column prop="checkStatus" label="审核状态">
<template v-slot="scope">
<el-tag type="warning" v-if="scope.row.checkStatus === '待审核'">待审核</el-tag>
<el-tag type="success" v-if="scope.row.checkStatus === '通过'">通过</el-tag>
<el-tag type="danger" v-if="scope.row.checkStatus === '拒绝'">拒绝</el-tag>
</template>
</el-table-column>
<el-table-column prop="reason" label="审核理由"></el-table-column>
<el-table-column prop="status" label="上架状态" v-if="data.user.role === '普通用户'">
<template #default="scope">
<el-switch @change="changeStatus(scope.row)" v-model="scope.row.status"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160">
<template #default="scope">
<el-button v-if="data.user.role === '管理员'" type="primary" @click="handleEdit(scope.row)">审核</el-button>
<el-button v-if="data.user.role === '普通用户'" :disabled="scope.row.checkStatus === '待审核'" 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="40%" v-model="data.formVisible" :close-on-click-modal="false" destroy-on-close>
<el-form ref="formRef" :model="data.form" :rules="data.rules" label-width="100px" style="padding-right: 50px">
<div v-if="data.user.role === '普通用户'">
<el-form-item label="名称" prop="name">
<el-input placeholder="请输入名称" v-model="data.form.name" autocomplete="off" />
</el-form-item>
<el-form-item label="图片" prop="img">
<el-upload
:action="baseUrl + '/files/upload'"
:headers="{ 'token': data.user.token }"
: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: 100px; height: 100px; border-radius: 5px; border: 1px dashed #ccc; display: flex; align-items: center; justify-content: center">上传图片</div>
</el-upload>
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input type="textarea" :rows="3" maxlength="200" placeholder="请输入描述" v-model="data.form.description" autocomplete="off" />
</el-form-item>
<el-form-item label="交换条件" prop="requirement">
<el-input type="textarea" :rows="3" maxlength="200" placeholder="请输入交换条件" v-model="data.form.requirement" autocomplete="off" />
</el-form-item>
</div>
<div v-if="data.user.role === '管理员'">
<el-form-item label="审核状态" prop="checkStatus">
<el-radio-group v-model="data.form.checkStatus">
<el-radio-button label="通过" value="通过"></el-radio-button>
<el-radio-button label="拒绝" value="拒绝"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="审核理由" prop="reason">
<el-input type="textarea" :rows="3" maxlength="200" placeholder="请输入审核理由" v-model="data.form.reason" autocomplete="off" />
</el-form-item>
</div>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="data.formVisible = false">取 消</el-button>
<el-button type="primary" @click="save" v-if="data.user.role === '普通用户'">保 存</el-button>
<el-button type="primary" @click="audit" v-if="data.user.role === '管理员'">保 存</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 baseUrl = import.meta.env.VITE_BASE_URL
const formRef = ref()
const data = reactive({
user: JSON.parse(localStorage.getItem('system-user') || '{}'),
pageNum: 1,
pageSize: 10,
total: 0,
formVisible: false,
form: {},
tableData: [],
name: null,
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
],
img: [
{ required: true, message: '请上传图片', trigger: 'blur' }
],
description: [
{ required: true, message: '请输入描述', trigger: 'blur' }
],
requirement: [
{ required: true, message: '请输入交换条件', trigger: 'blur' }
],
checkStatus: [
{ required: true, message: '请选择审核状态', trigger: 'change' }
],
}
})
const handleFileUpload = (res) => {
data.form.img = res.data
}
// 分页查询
const load = () => {
request.get('/items/selectPage', {
params: {
pageNum: data.pageNum,
pageSize: data.pageSize,
name: data.name,
userId: data.user.role === '管理员' ? null : data.user.id
}
}).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 = () => {
data.form.userId = data.user.id
data.form.status = false
request.post('/items/add', data.form).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
data.formVisible = false
} else {
ElMessage.error(res.msg)
}
})
}
const audit = () => {
request.put('/items/updateForAdmin', data.form).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
data.formVisible = false
} else {
ElMessage.error(res.msg)
}
})
}
const changeStatus = (row) => {
request.put('/items/updateStatus', row).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
} else {
ElMessage.error(res.msg)
}
})
}
// 编辑保存
const update = () => {
request.put('/items/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('/items/delete/' + id).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
} else {
ElMessage.error(res.msg)
}
})
}).catch(err => {})
}
// 重置
const reset = () => {
data.name = null
load()
}
load()
</script>