日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > vue >内容正文

vue

前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~

發(fā)布時間:2024/3/24 vue 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~ 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前后端分離 – 深入淺出系列 Spring Boot + Vue + ElementUI 實現(xiàn)相冊管理系統(tǒng)【文件上傳 分頁 】 文件上傳也不過如此~

引言

Hello,我是Bug終結(jié)者,一名熱愛后端Java的風(fēng)趣且幽默的程序員~ 終于等到幸運(yùn)的你~

快來發(fā)現(xiàn)我的宇宙哦~

博文系列

深入淺出前后端分離系列第一篇:前后端分離 — 深入淺出Spring Boot + Vue實現(xiàn)員工管理系統(tǒng) Vue如此簡單~

項目簡介

開發(fā)一個基于Spring Boot + Vue的前后端分離相冊管理系統(tǒng)項目,完成增、刪、改、列表、多條件、分頁的功能

功能細(xì)節(jié):

  • 實現(xiàn)照片的新增、刪除、修改、列表、多條件、分頁
  • 圖片上傳使用 el-upload 控件,建議設(shè)置 auto-upload 為 false。
  • 控制圖片最大不能超過5M
  • 上傳的必須是圖片,或者約束后綴為 png/jpg/gif/bmp等圖片。
  • 建議先保存標(biāo)題信息到數(shù)據(jù)庫,并返回得到noid的值,然后再上傳圖片,并更新 relative_path字段。
  • 圖片保存文件命名為 yyyyMMdd/HHmmssXXXX.后綴這樣的圖片,例如圖片為 倉鼠.png,保存后類似為 20220107/1115232832.png, XXXX表示4位的隨機(jī)數(shù)字。
  • 圖片在列表上顯示為 200X200大小
  • 列表要支持分頁,分頁控件使用 el-pagination
  • 刪除的時候,要將圖片從硬盤上刪除掉,然后再刪除數(shù)據(jù)庫中的記錄。
  • 列表頁顯示如下

效果圖

開發(fā)環(huán)境

后端:Spring Boot + MyBatis + Maven

前端:Vue + ElementUI

工具:前端使用WebStorm,后端使用IDEA

放松一下~

適度適度~

挺解乏的哦~🥰

言歸正傳~

項目風(fēng)格

請求方式統(tǒng)一為Post請求,目的是保證安全性

規(guī)范了接口層統(tǒng)一返回格式為ResultBean,詳細(xì)如:

統(tǒng)一返回格式風(fēng)格類,ResultBean

狀態(tài)碼,詳細(xì)信息,數(shù)據(jù)

數(shù)據(jù)表

t_picture

CREATE TABLE `t_picture` (`noid` int(11) NOT NULL AUTO_INCREMENT,`picture_name` varchar(64) NOT NULL COMMENT '照片名稱',`relative_path` varchar(128) DEFAULT NULL COMMENT '存儲相對路徑',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',PRIMARY KEY (`noid`) ) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8mb4

項目結(jié)構(gòu)

前端結(jié)構(gòu)

后端結(jié)構(gòu)

項目難點

前端部分難點:

上傳文件采用elementui控件的el-upload,要求不可自動上傳,所以設(shè)置自動上傳為false

其中,要先保存數(shù)據(jù)到數(shù)據(jù)庫在進(jìn)行保存圖片路徑存入數(shù)據(jù)庫,通過存入的數(shù)據(jù)id去修改當(dāng)前的數(shù)據(jù)

顯示圖片時采用了provide / inject組合控制的顯示

因為上傳成功后需要再次刷新,如果不刷新,圖片不出來,那就要重新刷新頁面,但刷新頁面對用戶來說極不友好,而且時間慢,效率低,所以采用該顯示方式,完美解決了二次加載的問題

介紹provide / inject組合控制的顯示到底怎么用

首先在app.vue中加入如下代碼

app.vue

<template><div id="app"><router-view v-if="isRouteAlive"/></div> </template><script>export default {name: 'App',computed: {},watch: {},//加入provideprovide() {return{//返回reload方法,該方法為全局方法reload: this.reload,}},data() {return {isRouteAlive:true};},methods: {//刷新頁面reload() {this.isRouteAlive = false;this.$nextTick(function () {this.isRouteAlive = true;})}}}; </script><style>@import '//at.alicdn.com/t/font_2048717_67mh6lqgbh.css'; </style>

在要二次加載的vue文件中加入provide

執(zhí)行完上傳圖片代碼后,進(jìn)行二次加載

完美解決二次加載

核心源碼

前端源碼

PictureList.vue

<template xmlns:c="http://www.w3.org/1999/html"><div class="box-main2 box-heigt100"><div class="box-search"><div><el-input type="text" size="mini" @keydown.native.enter="clkBtnSearch" @clear="clkBtnSearch" v-model="searchInfo.searchKey" clearable placeholder="請輸入標(biāo)題"></el-input></div><div class="m1"><el-button type="primary" size="mini" @click="clkBtnSearch">搜索</el-button></div><div class="m1"><el-button type="warning" size="mini" @click="clkBtnAdd">新增</el-button></div></div><div class="box-table2"><el-table :data="picturePage.list" border style="width: 100%;"><el-table-column type="index" label="序號" width="120"></el-table-column><el-table-column width="150" label="照片"><template slot-scope="scope"><el-image :src="src_url+scope.row.relative_path"></el-image></template></el-table-column><el-table-column prop="picture_name" label="標(biāo)題"></el-table-column><el-table-column prop="strCreateTime" label="上傳日期"></el-table-column><el-table-column label="操作"><template slot-scope="scope"><el-button type="warning" @click="clkBtnEdit(scope.row)">修改</el-button><el-button type="danger" @click="clkBtnDelete(scope.row)">刪除</el-button></template></el-table-column></el-table></div><div class="box-page1"><el-pagination background :current-page="picturePage.pageNum" :page-size="picturePage.pageSize" :total="picturePage.total"layout="total,prev,pager,next"@current-change="chgPageNum"></el-pagination></div><el-dialog :visible.sync="showPictureDigLog" title="新增/編輯"><el-form label-width="120px"><el-form-item label="標(biāo)題"><el-input type="text" size="mini" placeholder="請輸入標(biāo)題" v-model="picture.picture_name"></el-input></el-form-item><el-form-item label="照片"><el-image v-if="editPicture" style="width: 200px" :src="src_url+picture.relative_path"></el-image><el-uploadclass="upload-demo"ref="upload":action="uploadUrl":data="uploadDataParam":before-upload="checkFileType"accept=".png,.jpg,.gif, .bmp":auto-upload="false"><el-button slot="trigger" size="small" type="primary">選取文件</el-button><div slot="tip" class="el-upload__tip">只能上傳png/jpg/gif/bmp文件,且不超過5M</div></el-upload></el-form-item></el-form><span slot="footer" class="dialog-footer"><el-button type="primary" size="mini" @click="clkBtnSave">確定</el-button><el-button type="warning" size="mini" @click="showPictureDigLog = false">取消</el-button></span></el-dialog></div> </template><script>import request from '@/common/utils/request';export default {computed:{},inject: ['reload'],data() {return {searchInfo: {searchKey:''},picturePage:{pageNum: 1, pageSize: 2, list: []},showPictureDigLog:false,picture:{},uploadUrl:'',uploadDataParam:{},src_url:'http://127.0.0.1:8345/springbootajax/',editPicture:false,};},watch:{'$route.path':{handler:function(newVal){if(newVal == '/picture-list'){this.initData();}}, immediate: true},},mounted() {this.uploadUrl = this.settings.apiUrl + "/picture/upload";this.initData();},methods: {initData() {this.getPictureList();},getPictureList() {let url = this.settings.apiUrl + "/picture/page";let data = {};data.searchKey = this.searchInfo.searchKey;data.pageNum = this.picturePage.pageNum;data.pageSize = this.picturePage.pageSize;console.log(data)request.post(url, data).then((res) => {if (res.code === 0) {this.picturePage = res.data;}})},clkBtnAdd(){this.picture = {};this.showPictureDigLog = true;},clkBtnEdit(row) {this.picture = JSON.parse(JSON.stringify(row));this.editPicture = true;this.showPictureDigLog = true;},checkFileType(file) {let imgSize = file.size / 1024 / 1024;console.log("文件類型:"+file.type);console.log("文件大小:" + imgSize)if (imgSize > 5) {this.$message("文件超出規(guī)定上傳大小,請重新上傳文件!")return false;}//png/jpg/gif/bmp},clkBtnSave() {let url = this.settings.apiUrl + "/picture/save";let data = this.picture;request.post(url, data).then((res) => {if (res.code === 0) {this.uploadDataParam.noid = res.data;this.submitUpload();this.showPictureDigLog = false;this.getPictureList();this.$message("保存成功~")}})},//保存表單提交submitUpload() {this.$refs.upload.submit();this.reload();},clkBtnDelete(row) {this.$confirm("您確信要刪除嗎?", "提示").then(() => {let url = this.settings.apiUrl + "/picture/delete";let data = {noid: row.noid};request.post(url, data).then((res) => {if (res.code === 0) {this.getPictureList();this.$message("刪除成功~");}})}).catch(() => {this.$message("取消刪除~");})},chgPageNum(pageNum) {this.picturePage.pageNum = pageNum;this.getPictureList();},clkBtnSearch() {this.getPictureList();}},}; </script><style lang="scss" scoped="scoped">.box-main2 {width: 90%;margin: 10px;box-table2{height: auto;}.box-search{display: flex;margin: 10px;.m1{padding-left: 10px;}}.box-page1{margin-top: 10px;}}</style>

添加路由

route.js

{path: '/picture-list',meta: {pageTitle: '相冊管理', leftMenuIndex: 'picture-list'},component: () => import('@/views/PictureList') },

添加左側(cè)菜單顯示

LeftMenu.vue

<el-menu-item index="picture-list" @click.native="clkItem('/picture-list')"><i class="menuitem-icon iconfont icon-logging"></i><span class="menuitem-text" slot="title">相冊列表</span> </el-menu-item>

后端源碼

PictureController

package com.wanshi.controller;import com.github.pagehelper.PageInfo; import com.wanshi.bean.Picture; import com.wanshi.bean.ResultBean; import com.wanshi.service.PictureService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile;import java.util.List; import java.util.Map;@RestController @CrossOrigin @RequestMapping("/picture") public class PictureController {@Autowiredprivate PictureService pictureService;/*** 相冊分頁* @param param* @return*/@PostMapping("/page")public ResultBean<PageInfo<Picture>> page(@RequestBody Picture param) {ResultBean<PageInfo<Picture>> res = pictureService.page(param);return res;}/*** 保存,將新增和修改合成了一個方法,根據(jù)id判斷是新增或修改* @param param* @return*/@PostMapping("/save")public ResultBean<Integer> insert(@RequestBody Picture param) {ResultBean<Integer> res = pictureService.save(param);return res;}/*** 刪除圖片* @param param* @return*/@PostMapping("/delete")public ResultBean<Integer> delete(@RequestBody Picture param) {ResultBean<Integer> res = pictureService.delete(param);return res;}/*** 上傳圖片,與上傳信息分開,改為手動上傳,點擊確定后,先保存數(shù)據(jù),再保存圖片相關(guān)信息至數(shù)據(jù)庫* @param map* @param file* @return*/@PostMapping("/upload")public ResultBean<Integer> upload(@RequestParam Map<String, Object> map, MultipartFile file) {ResultBean<Integer> res = pictureService.upload(map, file);return res;}}

PictureService

package com.wanshi.service;import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.wanshi.bean.Picture; import com.wanshi.bean.ResultBean; import com.wanshi.config.GlobalSet; import com.wanshi.mapper.PictureMapper; import com.wanshi.utils.PbFileUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile;import java.io.File; import java.text.SimpleDateFormat; import java.util.List; import java.util.Map;@Service public class PictureService {@Autowiredprivate GlobalSet globalSet;@Autowiredprivate PictureMapper pictureMapper;private SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");public ResultBean<PageInfo<Picture>> page(Picture param) {PageHelper.clearPage();PageHelper.startPage(param.getPageNum(), param.getPageSize());List<Picture> pictureList = pictureMapper.list(param);for (Picture picture : pictureList) {if (picture != null) {picture.setStrCreateTime(sdf.format(picture.getCreate_time()));}}PageInfo<Picture> pageInfo = new PageInfo<>(pictureList);return ResultBean.create(0, "success", pageInfo);}public ResultBean<Integer> save(Picture param) {if (param.getNoid() != null ) {pictureMapper.update(param);} else {pictureMapper.insert(param);}return ResultBean.create(0, "success", param.getNoid());}public ResultBean<Integer> delete(Picture param) {//獲取要刪除的照片存儲相對地址Picture picture = pictureMapper.get(param);//拼接絕對路徑并刪除new File(globalSet.getUploadPath() + picture.getRelative_path()).delete();pictureMapper.delete(param);return ResultBean.create(0, "success", null);}public ResultBean<Integer> upload(Map<String, Object> map, MultipartFile file) {try {//查詢當(dāng)前id是否存在,并上傳過圖片Picture picture2 = new Picture();picture2.setNoid(Integer.valueOf((String)map.get("noid")));Picture picture3 = pictureMapper.get(picture2);if (picture3.getRelative_path() != null) {//拼接絕對路徑并刪除new File(globalSet.getUploadPath() + picture3.getRelative_path()).delete();}//上傳文件,獲得上傳后的文件名稱String uploadName = PbFileUtils.upload(file, globalSet.getUploadPath());if (!StringUtils.isEmpty((String)map.get("noid"))) {Picture picture = new Picture();picture.setNoid((Integer.valueOf((String) map.get("noid"))));picture.setRelative_path(uploadName);pictureMapper.updateImg(picture);}} catch (Exception e) {e.printStackTrace();}return ResultBean.create(0, "success", null);} }

工具類PbFileUtils

package com.wanshi.utils;import com.wanshi.config.GlobalSet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile;import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random;/*** 圖片上傳類*/ public class PbFileUtils {/*** 文件上傳,* @param file 上傳文件* @param uploadPath 要上傳到的路徑* @return* @throws IOException*/public static String upload(MultipartFile file, String uploadPath) throws IOException {String finalFileName = "";if (file.getSize() > 0) {String originalFilename = file.getOriginalFilename();//獲取源文件的后綴名String extName = originalFilename.substring(originalFilename.lastIndexOf("."));//獲取年月SimpleDateFormat sdfYyyyMMdd = new SimpleDateFormat("yyyy-MM");finalFileName = sdfYyyyMMdd.format(new Date()) + "/";//獲取日SimpleDateFormat sdfdd = new SimpleDateFormat("dd");finalFileName += sdfdd.format(new Date()) + "/";//獲取時分秒SimpleDateFormat sdfHHmmss = new SimpleDateFormat("HHmmss");finalFileName += sdfHHmmss.format(new Date());//生成4位隨機(jī)數(shù)字Integer rndNum = new Random().nextInt(1000)+9000;//拼接隨機(jī)數(shù)字和后綴名finalFileName += rndNum + extName;//目標(biāo)文件File f1 = new File(uploadPath+finalFileName);if (!f1.exists()) {f1.mkdirs();}//開始上傳file.transferTo(f1);}return finalFileName;}}

博主寄語

至此,系統(tǒng)到此完美結(jié)束,該案例通俗易懂,詳細(xì)一步步帶入,通過本案例,可提高你的學(xué)習(xí)能力以及訓(xùn)練自己的邏輯思維能力,認(rèn)真學(xué)習(xí)的你很耀眼,相信你的技術(shù)一定會有一個質(zhì)的飛躍,加油,努力練習(xí),祝你成為你想要成為的人!

若在本項目中遇到技術(shù)難題,可在下方評論區(qū)留言或私信我,授人以魚不如授人以漁

如果你覺得博主寫的不錯的話,不妨給個一鍵三連,點擊下方小拳頭即可一鍵三連。

總結(jié)

以上是生活随笔為你收集整理的前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。