计划:处理时进入A表,审核后从A表读取数据,然后操作目标表B;
优点:简单的想法
缺点:后端功能嵌入程度高;审计功能的数据操作不统一
方案:前端实现,判断运行时是否需要权限控制,如果需要,会弹出一个框,由审核者审核。审核通过后,将进行后续操作。
优点:无需嵌入后台功能;可支持查询、导出、操作等全部功能;
缺点:需要经理和审稿人同时在场
方案:审计功能是一个独立的功能。前台发起业务后,将输入的参数存入数据库。审核通过后,后台触发调用相应接口,并通知负责人执行结果。
优点:无需嵌入前后端功能;支持导出和操作类;处理程序和审查程序可以异步操作;审核功能统一数据操作;
缺点:需要框架层支持;实现逻辑稍复杂
计划:审计功能涉及到的所有表都需要添加到对应的表中。该表主要相比源表增加了1个字段,即审计流程,其他字段命名完全一样;所有的函数操作都首先输入到这个表中。审核通过后,后端会将此表的数据同步到主表。
优点:无需框架支持;支持导出和操作类;处理程序和审查程序可以异步操作;审核功能数据操作统一;
缺点:后端功能高度嵌入;
创建 表 `审核`( `id` int NOT NULL自动增量注释'ID', `名称` varchar(255)整理 utf8mb4_unicode_ci 默认 NULL 评论 '报修改名称', `用户` varchar(255) 整理 utf8mb4_unicode_ci 默认 NULL 评论 '报修人', `create_time` 日期时间 默认 CURR ENT_TIMESTAMP COMMENT '报修改时间', `img` varchar(255) 整理 utf8mb4_unicode_ci 默认 NULL 注释 '详情图片', `状态` varchar(255) 整理 utf8mb4_unicode_ci 默认 '待审核' COMMENT '待审核,审核通过,审核不通过', 主要KEY(`id`))引擎=InnoDB AUTO_INCRMENT=12 默认 CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
其实评论功能最重要的就是我们的新功能。只有添加用户后,我们的管理员才能审核您的申请并最终达到效果。
审计控制器
导入 com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;导入 www.sychzs.cn;导入com .example.demo.common.Result;import com.example.demo.entity.Audit;import com.example.demo.entity.Sanitation;import com.example.demo.entity.User;导入 com.example.demo.mapper.FileMapper;导入 com.example.demo.service.IAuditService;导入 com.example.demo.utils.TokenUtils;import org.springframework.web.bind.annotation.*; importjavax.annot化.资源;导入 java.util.List; @CrossOrigin@RestController@RequestMapping( “/审核”)公共 类 AuditController { @Resource 私有 IAuditService auditService; @Resource privateFileMapper fileMapper;// //添加或更新// @PostMapping// public Result save(@RequestBody Auditaudit) {//audit.setUser(Token Utils.getCurrentUser().getUsername( ); //添加或更新 @PostMapping public 结果保存(@RequestBody Audit审核) {“ if (audit.getId() == null) { //新建 audit.setUser(TokenUtils. getCurrentUser().getUsername()); | Result.success(); // @DeleteMapping("/{id}")// public 结果删除(@PathVariable Integer id) {// return Result.success(userService.removeById(id)); // } @PostMapping(“/删除/批次”? ids) {//批量删除返回 Result.success(auditService.removeByIds(ids)); } / /查询所有数据 @GetMapping public结果findAll() { return 结果.成功(auditService.list()); } // @GetMapping("/role/{role}")// public Result findNames(@PathVariable String role) { // QueryWrapper queryWrapper = new QueryWra pper<>();// QueryWrapper.eq("role", role);// List list =auditService.list(queryWrap每) ;//返回Result.success(列表);// ) public结果findOne(@PathVariable In编号) { return Result.success(auditService.getById(id)); } @GetMapping("/用户名/{用户名}") public 结果通过用户名查找(@PathVariable字符串用户名) { QueryWrapper queryWrapper = 新 QueryWrapper<> (); queryWrapper.eq("用户名", 用户名); 返回 Result.success(auditService.getOne(queryWrapper)); } @GetMapping("/页") public 结果 findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(defaultValue = "") 字符串名称) { QueryWrapper queryWrapper = new QueryWrapper <>(); queryWrapper.orderByDesc("id"); if(!"".等于(名称)) { www.sychzs.cn("名称",名称); }User currentUser = TokenUtils.getCurrentUser();// If (RoleEnum.ROLE_USER.toString().equals(currentUser.getRole())) { // 角色是普通用户// queryW rapper。 eq("user", currentUser.getUsername());// 当前用户。 new 页<>(pageNum, pageSize) , queryWrapper)); }}
<el-table-column 标签=“审核” 宽度="240"> <模板V型槽=“范围”> el按钮类型=》 success" @click="changeState(scope.row, '已批准...主人正在路上')":禁用 ="scope.row.state !== '待审核'">已批准el-button> <el按钮类型="危险"@点击="changeState(scope.row, '审核失败')" :已禁用? 模板>el-table-column>
导入 com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;导入 www.sychzs.cn;导入com .example.demo.common.Result;import com.example.demo.entity.Audit;import com.example.demo.entity.User;import com.example.demo.mapper.FileMapper;导入 com.example.demo.service.IAuditService;导入 com.example.demo.utils.TokenUtils;导入 org.springframework.web.bind.annotation.*; 导入javax.annotation.Resource;导入java.util.List; @CrossOrigin @RestController@RequestMapping("/审核")公共 类 AuditController { @Resource privateIAuditService auditService; @Resource 私有FileMapper fileMapper; // //新增或者更新// @PostMapping//public Result save(@RequestBody Audit audit) {// audit.setUser(TokenUtils.getCurrentUser().getUsername()); audit.setImg(Files.url);// 返回结果。 success(auditService.saveOrUpdate(audit));// } // 新增或者更新 @PostMapping public结果保存(@RequestBody审核审核){ if(audit.getId() == null){ // 新增 audit.setUser(TokenUtils.getCurrentUser().getUsername()); } 审核Service.saveOrUpdate(audit); 返回结果.success(); } //删除// @DeleteMapping("/{id}")// 公共结果删除(@PathVariable Integer id) {// return Result.success(userService.removeById(id));// } @PostMapping("/删除/批次") 公共结果删除批次(@RequestBody List ids) {//批量删除 return Result.success(auditService.removeByIds(ids)); } //所有数据 @GetMapping public 结果findAll() { 返回 Result.success(auditService.list()); } @GetMapping("/{id}" ) public结果findOne(@PathVariable整数id){ 返回Result.success(auditService.getById( id)); } @GetMapping("/用户名/{用户名}" ) 公共结果findByUsername(@PathVariable字符串用户名){ QueryWrapperqueryW rapper = new QueryWrapper<>(); queryWrapper.eq("用户名",用户名); return Result.success(auditService.getOne(queryWrapper)); } @GetMapping("/页") public结果findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(defaultValue = "")字符串名称){ QueryWrapper queryWrapper = 新QueryWrapper<>(); queryWrapper.orderByDesc("id"); if (!"".equals(名称)){ www.sychzs.cn("name", name); } 用户currentUser = TokenUtils.getCurrentUser();// if (RoleEnum.ROLE_USER.toString() .equals(currentUser.getRole())) { // 角色是普通用户// queryWrapper.eq("user", currentUser.getUsername());// } 返回 Result.success(www.sychzs.cn(new Page<>(pageNum, pageSize), queryWrapper)); }}
(1)、前台功能页
前台负责添加新的请求,然后保存请求后,我们的管理员在批准后无法编辑或删除我们的请求。我们会将数据保留在前台页面
<模板> <div> <div 样式=“边距:10px 0” > <el-input 样式=》宽度:200px;左边距:10px"占位符=》请输入维修描述“ clearable v-model=“名称” >el-输入> < el-button 类="ml-5" 类型=“主要”@点击 ="负载"><i 类=“el-图标搜索” />搜索 el-按钮> el-按钮 type= “警告”@点击=》重置"><i 类="el-图标刷新" /> 刷新el按钮> | "边距: 10px 0"> <el-buttontype=“主要” @点击= "手动添加" 类="ml- 10"><i 类="el-icon-circle-plus-outline"/>新el-button> <el-pop确认 班级="ml-5" 确认按钮文本= '确认' 取消按钮文本='取消' 图标颜色=“红色” 标题="您确定要删除吗批量这些信息吗?" @确认="delBatch"> <el -按钮 类型=“危险” 插槽=“参考” ><i 班级="el-icon-remove -outline"/>删除el-按钮>el-popconfirm> div> <el-table :data="tableData" 边框 stripe:标头单元格类-name="headerBg" 选择更改="handleSelectionChange"> <el-table栏 类型="选择" 宽度= "55">el-table-column> <el-table-column prop=》名称" 标签="报修描述" >el-表格列> <el-表格列 prop="用户" 标签="用户">el-table-column> <el-table-column prop="createTime" label="创建"" >时间el-table-column > <el-table-column 标签="图片"> <模板 插槽范围=“范围”> <el-image 样式=“宽度:100px;高度:1 00px“ :src=”范围。 row.img" :preview-src-list="[scope.row.img]">el-image > 模板> el-表格列> <el-table-column prop="状态" 标签="进度">el-table-column > <el-表格列 标签="操作"> <模板 插槽范围="范围" > <el按钮 类型=“成功” @点击=“handleEdit(scope.row)” :已禁用="scope.row.state !=='待审核'"><i 班级="el-icon-编辑-大纲" />编辑el-按钮> 模板> el-桌子-列> el-table> <div 样式=“内边距:10px 0”> <el-分页 @尺寸更改=“handleSizeChange” @当前更改=“handleCurrentChange” :当前页面="pageNum" :页面大小 ="[ 5, 10, 15]" :页面大小="pageSize" 布局="总计、尺寸、上一页、寻呼机、下一页、跳线" :总计="总计" > el-分页> div> <el-dialog 标题="用户信息" :visible.sync="dialogFormVisible" 宽度="30%"> < el-form 标签宽度="100px" 尺寸 ="小"> <el -form-item 标签="报修描述" > el-输入 v-模型="www.sychzs.cn" 自动完成="关闭">el-input > el-form-item> <el-form-item 标签=“物品图片” > <el上传 动作="http://localhost:9090/file/upload" ref="img" :成功="handleImgUploadSuccess"> <el按钮 尺寸=“小” 类型= "主要">点击上传el-button> el-上传> el-表单项> el-form> < div 插槽=“页脚” 类=“对话框页脚”> <el-按钮 @点击="dialogFormVisible = false">取消 el-按钮> <el-按钮 类型="主要"@点击="s ave">准确定el按钮> div> el-dialog> div>模板> <脚本>导出 默认 { 名称 : “审核”, data() { 返回 { tableData: [], 总计: 0, 页数: 1, 页面大小: 5, 姓名:"", 表单: {}, dialogFormVisible: 假, 多重选择: [], headerBg: "headerBg", 角色: [], 用户: localStorage.getItem(“用户”)? JSON.parse(localStorage.getItem("用户")) : {} } } , 已创建() { 这个.load() }, 方法: { 负载:功能(){ 这个.request.get("/审核/页面", { 参数:{ 页码: 这个.pageNum, pageSize: 这个.pageSize, 名称: 这个.name, } }).then(res => { 这个.tableData = res.data.records 这个.total = www.sychzs.cn }) // this.request.get("/role").then(res => { // this.roles = www.sychzs.cn //}) } , home() { 这个.$router.push("/") }, 保存() { 这个.www.sychzs.cn("/审核", 这个.form).then() res => { if (res.code === '200') { 这个.$message.success("保存成功") 这个.dialogFormVisible = 假 这个.load() } else { 这个.$message.error("保存失败") } }) }, handleAdd() { 这个.dialogFormVisible = true 这个.form = {} }, handleEdit(row) { 这个。表单 = row 这个.dialogFormVisible = true }, handleSelectionChange(val) { 控制台.log(val) 这个.multipleSelection = val; }, delBatch() { let ids = 这个.www.sychzs.cn(v=>www.sychzs.cn) //[{}, {}, {}] => [ 1,2,3] 这个.www.sychzs.cn("/audit/del/batch", ids).then() res=> { if(res.code === '200') { 这个.$message.success(“删除信息成功”) 这个.load() } 否则 { 这个.$消息。错误("删除信息失败") } }) }, 重置() { 这个.name = "" 这个.load() }, handleSizeChange(pageSize) { 控制台.log(pageSize) 这个.pageSize = pageSize 这个.load() }, handleCurrentChange(pageNum) { 控制台.log(pageNum) 这个.pageNum = pageNum 这个.load() },handleImgUploadSuccess( res } 脚本> <样式> .headerBg {背景:#eee!重要!;}style>
(2)、后台管理功能页面
<template> <div> <div style="margin: 10px 0"> <el-popconfirm class="ml-5" confirm-button-text='确认' cancel-button-text='取消' icon="el-icon-info" icon-color="red" title="确定批量删除这些信息吗?" @confirm="delBatch"> <el-button type="danger" slot="reference" ><i class="el-icon-remove-outline" />删除el-button> el-popconfirm> div> <el-table :data="tableData" border stripe :header-cell-class-name="headerBg" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55">el-table-column> <el-table-column prop="name" label="报修描述" >el-table-column> <el-table-column prop="user" label="用户" >el-table-column> <el-table-column prop="createTime" label="创建时间" >el-table-column> <el-table-column prop="img" label="详情图片" > <template slot-scope="scope"> <el-image style="width: 100px; height: 100px" :src="scope.row.img" :preview-src-list="[scope.row.img]">el-image> template> el-table-column> <el-table-column prop="state" label="进度">el-table-column> <el-table-column label="审核" width="240"> <template v-slot="scope"> <el-button type="success" @click="changeState(scope.row, '审核通过...师傅正在赶来的路上')" :disabled="scope.row.state !== '待审核'">审核通过el-button> <el-button type="danger" @click="changeState(scope.row, '审核不通过')" :disabled="scope.row.state !== '待审核'">审核不通过el-button> template> el-table-column> el-table> <div style="padding: 10px 0"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageNum" :page-sizes="[ 5, 10, 15]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total"> el-pagination> div> div>template> <script>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.records this.total = www.sychzs.cn }) this.request.get("/role").then(res => { this.roles = www.sychzs.cn }) }, home() { this.$router.push("/") }, save() { this.www.sychzs.cn("/audit", this.form).then(res => { if (res.code === '200') { this.$message.success("保存成功") this.dialogFormVisible = false this.load() } else { this.$message.error("保存失败") } }) }, handleAdd() { this.dialogFormVisible = true this.form = {} }, handleEdit(row) { this.form = row this.dialogFormVisible = true }, handleSelectionChange(val) { console.log(val) this.multipleSelection = val; }, delBatch() { let ids = this.www.sychzs.cn(v => www.sychzs.cn) //[{}, {}, {}] => [1,2,3] this.www.sychzs.cn("/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 = pageSize this.load() }, handleCurrentChange(pageNum) { console.log(pageNum) this.pageNum = pageNum this.load() }, changeState(row, state) { this.form = JSON.parse(JSON.stringify(row)) this.form.state = state; this.save(); }, // handleImgUploadSuccess() { // this.$message.success("图片上传成功") // this.load() // }, }}script> <style>.headerBg { background: #eee!important;}style>
重点!!!!图片上传
核心代码
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 www.sychzs.cnUtil;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import www.sychzs.cn;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 www.sychzs.cn.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; @Resource private FileMapper fileMapper; @Autowired private 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() + www.sychzs.cn + type; File uploadFile = new File(fileUploadPath + fileUUID); // 判断配置的文件目录是否存在,若不存在则创建一个新的文件目录 File parentFile = uploadFile.getParentFile(); //判断目录是否存在,不存在就新建 if (!parentFile.exists()) { parentFile.mkdirs(); } String url; // 获取文件的md5 String md5 = www.sychzs.cn5(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 = www.sychzs.cn5(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 = www.sychzs.cnList(queryWrapper); return filesList.size() == 0 ? null : filesList.get(0); } // @CachePut(value = "files", key = "'frontAll'") @PostMapping("/update") public Result update(@RequestBody Files files) { fileMapper.updateById(files); flushRedis(Constants.FILES_KEY); return Result.success(); } @GetMapping("/detail/{id}") public Result getById(@PathVariable Integer id) { return Result.success(www.sychzs.cnById(id)); } //清除一条缓存,key为要清空的数据// @CacheEvict(value="files",key="'frontAll'") @DeleteMapping("/{id}") public Result delete(@PathVariable Integer id) { Files files = www.sychzs.cnById(id); files.setIsDelete(true); fileMapper.updateById(files); flushRedis(Constants.FILES_KEY); return Result.success(); } @PostMapping("/del/batch") public Result deleteBatch(@RequestBody List ids) { // select * from sys_file where id in (id,id,id...) QueryWrapper queryWrapper = new QueryWrapper<>(); www.sychzs.cn("id", ids); List files = www.sychzs.cnList(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)) { www.sychzs.cn("name", name); } return Result.success(www.sychzs.cnPage(new Page<>(pageNum, pageSize), queryWrapper)); } // 删除缓存 private void flushRedis(String key) { stringRedisTemplate.delete(key); }}
以上就是对怎么利用springboot实现审核功能简单的概述,让我们更加了解SpringBoot的作用,为我们的知识储备又加上一笔。
构建高质量的技术交流社群,欢迎从事编程开发、技术招聘HR进群,也欢迎大家分享自己公司的内推信息,相互帮助,一起进步!