一、审核功能实现的方式

1、普通

方案:经办时入A表,审核后从A表读取数据,然后操作目标B表;

优势:思路简单

劣势:对后端功能实行高度的嵌入;审核功能数据操作不统一

2、弹框式

方案:前台实现,操作时判断是否需要权限控制,如果需要,则弹出框,由审核人员进行审核,

审核通过后,进行后续操作。

优势:对后台功能无嵌入;可支持查询、导出、操作等全部功能;

劣势:需要经办人和审核人同时在场操作

3、入参缓冲时

方案:审核功能是独立的功能,前台发起业务后,入参存入数据库。

待审核通过后,后台触发调用相应的接口,并将执行结果通知到经办人。

优势:对前后台功能均无嵌入;支持导出及操作类;经办人和审核人可以异步操作;审核功能数据操作统一;

劣势:需要框架层支持;实现逻辑稍微复杂

4、临时表

方案:所有需要审核功能涉及的表均增加相应的表,该表比源表主要增加1个字段,即审核流水,其余字段命名完全一致;

所有功能操作时先入该表,审核通过后,由后台从该表将数据同步至正表。

优势:无需要框架支持;支持导出及操作类;经办人和审核人可以异步操作;审核功能数据操作统一;

劣势:对后端功能实行高度的嵌入;

二、SpringBoot实现

1.创建数据库表SQL

CREATE TABLE `audit` (`id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '报修名称',`user` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '报修人',`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '报修时间',`img` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '详情图片',`state` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '待审核' COMMENT '待审核,审核通过,审核不通过',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.写Java后端

其实审核功能最主要的就是我们的新增功能,用户只有新增过后,我们的管理员才能去对你的申请进行审核,最后实现效果。

AuditController.Controller

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.example.demo.common.Result;import com.example.demo.entity.Audit;import com.example.demo.entity.Sanitation;import com.example.demo.entity.User;import com.example.demo.mapper.FileMapper;import com.example.demo.service.IAuditService;import com.example.demo.utils.TokenUtils;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;import java.util.List;@CrossOrigin@RestController@RequestMapping("/audit")public class AuditController {@Resourceprivate IAuditService auditService;@Resourceprivate FileMapper fileMapper;////新增或者更新//@PostMapping//public Result save(@RequestBody Audit audit) {//audit.setUser(TokenUtils.getCurrentUser().getUsername());audit.setImg(Files.url);//return Result.success(auditService.saveOrUpdate(audit));//}// 新增或者更新@PostMappingpublic Result save(@RequestBody Audit audit) {if (audit.getId() == null) {// 新增audit.setUser(TokenUtils.getCurrentUser().getUsername());}auditService.saveOrUpdate(audit);return Result.success();}//删除//@DeleteMapping("/{id}")//public Result delete(@PathVariable Integer id) {//return Result.success(userService.removeById(id));//}@PostMapping("/del/batch")public Result deleteBatch(@RequestBody List ids) {//批量删除return Result.success(auditService.removeByIds(ids));}//查询所有数据@GetMappingpublic Result findAll() {return Result.success(auditService.list());}//@GetMapping("/role/{role}")//public Result findNames(@PathVariable String role) {//QueryWrapper queryWrapper = new QueryWrapper();//queryWrapper.eq("role", role);//List list = auditService.list(queryWrapper);//return Result.success(list);//}@GetMapping("/{id}")public Result findOne(@PathVariable Integer id) {return Result.success(auditService.getById(id));}@GetMapping("/username/{username}")public Result findByUsername(@PathVariable String username) {QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("username", username);return Result.success(auditService.getOne(queryWrapper));}@GetMapping("/page")public Result findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(defaultValue = "") String name) {QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.orderByDesc("id");if (!"".equals(name)) {queryWrapper.like("name", name);}User currentUser = TokenUtils.getCurrentUser();//if (RoleEnum.ROLE_USER.toString().equals(currentUser.getRole())) {// 角色是普通用户//queryWrapper.eq("user", currentUser.getUsername());//}return Result.success(auditService.page(new Page(pageNum, pageSize), queryWrapper));}}

三、前端调用

1.实现效果

2.核心代码

审核通过审核不通过

3.后台管理

4.后台管理核心代码

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.example.demo.common.Result;import com.example.demo.entity.Audit;import com.example.demo.entity.User;import com.example.demo.mapper.FileMapper;import com.example.demo.service.IAuditService;import com.example.demo.utils.TokenUtils;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;import java.util.List;@CrossOrigin@RestController@RequestMapping("/audit")public class AuditController {@Resourceprivate IAuditService auditService;@Resourceprivate FileMapper fileMapper;////新增或者更新//@PostMapping//public Result save(@RequestBody Audit audit) {//audit.setUser(TokenUtils.getCurrentUser().getUsername());audit.setImg(Files.url);//return Result.success(auditService.saveOrUpdate(audit));//}// 新增或者更新@PostMappingpublic Result save(@RequestBody Audit audit) {if (audit.getId() == null) {// 新增audit.setUser(TokenUtils.getCurrentUser().getUsername());}auditService.saveOrUpdate(audit);return Result.success();}//删除//@DeleteMapping("/{id}")//public Result delete(@PathVariable Integer id) {//return Result.success(userService.removeById(id));//}@PostMapping("/del/batch")public Result deleteBatch(@RequestBody List ids) {//批量删除return Result.success(auditService.removeByIds(ids));}//查询所有数据@GetMappingpublic Result findAll() {return Result.success(auditService.list());}@GetMapping("/{id}")public Result findOne(@PathVariable Integer id) {return Result.success(auditService.getById(id));}@GetMapping("/username/{username}")public Result findByUsername(@PathVariable String username) {QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("username", username);return Result.success(auditService.getOne(queryWrapper));}@GetMapping("/page")public Result findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(defaultValue = "") String name) {QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.orderByDesc("id");if (!"".equals(name)) {queryWrapper.like("name", name);}User currentUser = TokenUtils.getCurrentUser();//if (RoleEnum.ROLE_USER.toString().equals(currentUser.getRole())) {// 角色是普通用户//queryWrapper.eq("user", currentUser.getUsername());//}return Result.success(auditService.page(new Page(pageNum, pageSize), queryWrapper));}}

5.vue前台完整代码

(1)、前台功能页面

前台负责新增请求,然后保存请求之后,我们管理员审核通过之后就不可以编辑和删除我们的请求,我们会保留数据在前台页面

搜索刷新新增删除编辑点击上传取 消确 定export default {name: "Audit",data() {return {tableData: [],total: 0,pageNum: 1,pageSize: 5,name: "",form: {},dialogFormVisible: false,multipleSelection: [],headerBg: "headerBg",roles: [],user: localStorage.getItem("user") " /> {this.tableData = res.data.recordsthis.total = res.data.total})// this.request.get("/role").then(res => {// this.roles = res.data// })},home() {this.$router.push("/")},save() {this.request.post("/audit", this.form).then(res => {if (res.code === '200') {this.$message.success("保存成功")this.dialogFormVisible = falsethis.load()} else {this.$message.error("保存失败")}})},handleAdd() {this.dialogFormVisible = truethis.form = {}},handleEdit(row) {this.form = rowthis.dialogFormVisible = true},handleSelectionChange(val) {console.log(val)this.multipleSelection = val;},delBatch() {let ids = this.multipleSelection.map(v => v.id)//[{}, {}, {}] => [1,2,3]this.request.post("/audit/del/batch", ids).then(res => {if (res.code === '200') {this.$message.success("删除信息成功")this.load()} else {this.$message.error("删除信息失败")}})},reset() {this.name = ""this.load()},handleSizeChange(pageSize) {console.log(pageSize)this.pageSize = pageSizethis.load()},handleCurrentChange(pageNum) {console.log(pageNum)this.pageNum = pageNumthis.load()},handleImgUploadSuccess(res) {this.form.img = res},}}.headerBg {background: #eee!important;}

(2)、后台管理功能页面

<!----><!--搜索--><!--刷新-->删除审核通过审核不通过export default {name: "Audit",data() {return {tableData: [],total: 0,pageNum: 1,pageSize: 5,username: "",form: {},// dialogFormVisible: false,multipleSelection: [],headerBg: "headerBg",roles: [],user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {},}},created() {this.load()},methods: {load: function () {this.request.get("/audit/page", {params: {pageNum: this.pageNum,pageSize: this.pageSize,username: this.username,}}).then(res => {this.tableData = res.data.recordsthis.total = res.data.total})this.request.get("/role").then(res => {this.roles = res.data})},home() {this.$router.push("/")},save() {this.request.post("/audit", this.form).then(res => {if (res.code === '200') {this.$message.success("保存成功")this.dialogFormVisible = falsethis.load()} else {this.$message.error("保存失败")}})},handleAdd() {this.dialogFormVisible = truethis.form = {}},handleEdit(row) {this.form = rowthis.dialogFormVisible = true},handleSelectionChange(val) {console.log(val)this.multipleSelection = val;},delBatch() {let ids = this.multipleSelection.map(v => v.id)//[{}, {}, {}] => [1,2,3]this.request.post("/audit/del/batch", ids).then(res => {if (res.code === '200') {this.$message.success("删除信息成功")this.load()} else {this.$message.error("删除信息失败")}})},reset() {this.username = ""this.load()},handleSizeChange(pageSize) {console.log(pageSize)this.pageSize = pageSizethis.load()},handleCurrentChange(pageNum) {console.log(pageNum)this.pageNum = pageNumthis.load()},changeState(row, state) {this.form = JSON.parse(JSON.stringify(row))this.form.state = state;this.save();},// handleImgUploadSuccess() {// this.$message.success("图片上传成功")// this.load()// },}}.headerBg {background: #eee!important;}

重点!!!!图片上传

核心代码

CREATE TABLE `file` (`id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件名称',`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件类型',`size` bigint DEFAULT NULL COMMENT '文件大小(kb)',`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '下载链接',`md5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件md5',`creat_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '时间',`is_delete` tinyint(1) DEFAULT '0' COMMENT '是否删除',PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=115 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
import cn.hutool.core.io.FileUtil;import cn.hutool.core.util.IdUtil;import cn.hutool.core.util.StrUtil;import cn.hutool.crypto.SecureUtil;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.example.demo.common.Constants;import com.example.demo.common.Result;import com.example.demo.entity.Files;import com.example.demo.mapper.FileMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import java.io.File;import java.io.IOException;import java.net.URLEncoder;import java.util.List;@RestController@RequestMapping("/file")public class FileController {@Value("${files.upload.path}")private String fileUploadPath;@Value("${server.ip}")private String serverIp;@Resourceprivate FileMapper fileMapper;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@PostMapping("/upload")public String upload(@RequestParam MultipartFile file) throws IOException {String originalFilename = file.getOriginalFilename();String type = FileUtil.extName(originalFilename);long size = file.getSize();// 定义一个文件唯一的标识码String fileUUID = IdUtil.fastSimpleUUID() + StrUtil.DOT + type;File uploadFile = new File(fileUploadPath + fileUUID);// 判断配置的文件目录是否存在,若不存在则创建一个新的文件目录File parentFile = uploadFile.getParentFile();//判断目录是否存在,不存在就新建if (!parentFile.exists()) { parentFile.mkdirs();}String url;// 获取文件的md5String md5 = SecureUtil.md5(file.getInputStream());// 从数据库查询是否存在相同的记录Files dbFiles = getFileByMd5(md5);if (dbFiles != null) {url = dbFiles.getUrl();} else {// 上传文件到磁盘file.transferTo(uploadFile);// 数据库若不存在重复文件,则不删除刚才上传的文件url = "http://" + serverIp + ":9090/file/" + fileUUID;}//存储到数据库Files saveFile = new Files();saveFile.setName(originalFilename);saveFile.setType(type);saveFile.setSize(size/1024);saveFile.setUrl(url);saveFile.setMd5(md5);fileMapper.insert(saveFile);return url;//String md5 = SecureUtil.md5(file.getInputStream());//Files files = getFileByMd5(md5);////String url;//if (files != null) {//url = files.getUrl();//} else {//file.transferTo(uploadFile);//url = "http://localhost:9090/file/" + fileUUID;//}////存储到数据库//Files saveFile = new Files();//saveFile.setName(originalFilename);//saveFile.setType(type);//saveFile.setSize(size/1024);//saveFile.setUrl(url);//saveFile.setMd5(md5);//fileMapper.insert(saveFile);//return url;}@GetMapping("/{fileUUID}")public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {// 根据文件的唯一标识码获取文件File uploadFile = new File(fileUploadPath + fileUUID);// 设置输出流的格式ServletOutputStream os = response.getOutputStream();response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));response.setContentType("application/octet-stream");// 读取文件的字节流os.write(FileUtil.readBytes(uploadFile));os.flush();os.close();}/** * 通过文件的md5查询文件 * @param md5 * @return */private Files getFileByMd5(String md5) {// 查询文件的md5是否存在QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("md5", md5);List filesList = fileMapper.selectList(queryWrapper);return filesList.size() == 0 " /> ids) {// select * from sys_file where id in (id,id,id...)QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.in("id", ids);List files = fileMapper.selectList(queryWrapper);for (Files file : files) {file.setIsDelete(true);fileMapper.updateById(file);}return Result.success();}/** * 分页查询接口 * @param pageNum * @param pageSize * @param name * @return */@GetMapping("/page")public Result findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(defaultValue = "") String name) {QueryWrapper queryWrapper = new QueryWrapper();// 查询未删除的记录queryWrapper.eq("is_delete", false);queryWrapper.orderByDesc("id");if (!"".equals(name)) {queryWrapper.like("name", name);}return Result.success(fileMapper.selectPage(new Page(pageNum, pageSize), queryWrapper));}// 删除缓存private void flushRedis(String key) {stringRedisTemplate.delete(key);}}

⛵小结

以上就是对怎么利用SpringBoot实现审核功能简单的概述,让我们更加了解SpringBoot的作用,为我们的知识储备又加上一笔。

​​​​​​​

如果这篇文章有帮助到你,希望可以给作者点个赞,创作不易,如果有对后端技术、前端领域感兴趣的,也欢迎关注 ,我将会给你带来巨大的收获与惊喜!