SpringBoot-Vue_开发前后端分离的旅游管理系统_Jerry_House-CSDN博客_springboot_flowable

SpringBoot + Vue 开发前后端分离的旅游管理系统_Jerry House-CSDN博客_springboot flowable

java知识

SpringBoot + Vue 开发前后端分离的旅游管理系统

旅游管理系统

  • 项目简介
    • 项目演示
    • 数据库建表
  • 环境搭建
    • 引入依赖(pom.xml)
    • 配置文件(application.properties)
  • href="javascript:;" 含义
  • select - option 绑定 Vue 实例
  • 删除时增加确认选项
  • Vue 获取地址栏跳转的参数
  • 前后端分离项目—验证码功能
  • 前后端分离项目—分页功能
  • 前后端分离项目—日期数据类型的处理
  • 前后端分离项目—文件上��

好像没有必要一段段的把代码贴上来,毫无意义,不如把完整的项目放出来,基本有点基础的都可以看懂哈,然后博客记录一下遇到的问题和重要的知识点。。

项目 github 网址:https://github.com/szluyu99/travels/tree/master

视频链接:https://www.bilibili.com/video/BV1Nt4y127Jh?p=19

项目简介

所需技术栈

  • 后端技术栈:springboot + mybatis
  • 前后端分离:axios、json
  • 前端技术栈、技术架构:Vue、node.js

前置知识

  • 了解 Vue 组件之前的知识
  • 对 springboot + mybatis 较熟悉

开发流程:

  • 需求分析
  • 库表设计
  • 编码(项目环境搭建+编码)
  • 项目调试
  • 项目部署上线

需求分析

  • 用户模块:登录 + 注册
  • 省份模块:一个省份可能存在多个景点
  • 景点模块:一个景点对应多个省份

项目演示

进入系统需登录:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70-6.png

用户注册页面:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70-5.png

省份列表页面:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70-4.png

添加省份页面:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70-2.png

修改省份页面:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70-3.png

景点列表页面:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70.png

添加景点页面:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70-7.png

修改景点页面:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ-,size_16,color_FFFFFF,t_70-1.png

数据库建表

用户表t_user —— 独立的表

  • id、username、password、email

省份表t_province[省份表 : 景点表] —— [1 : N]

  • id、name、tags、placecounts

景点表t_place

  • id、name、picpath、hottime、hotticket、dimticket、placedes、provinceid(外键)

数据库名:travels

用户表 SQL:

CREATE TABLE t_user(id INT(6) PRIMARY KEY AUTO_INCREMENT,username VARCHAR(60),password VARCHAR(60),email VARCHAR(60)
);
123456

省份表 SQL:

CREATE TABLE t_province(id INT(6) PRIMARY KEY AUTO_INCREMENT,name VARCHAR(60),tags VARCHAR(80),placecounts INT(4)
);
123456

景点表 SQL:

CREATE TABLE t_place(id INT(6) PRIMARY KEY AUTO_INCREMENT,name VARCHAR(60),picpath MEDIUMTEXT,hottime	TIMESTAMP,hotticket	DOUBLE(7,2),dimticket	DOUBLE(7,2),placedes	VARCHAR(300),provinceid	INT(6) REFERENCES t_province(id)
);
12345678910

环境搭建

利用 Spring Initializr 快速搭建 SpringBoot 项目。

引入依赖(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!--继承springboot父项目--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.1.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.yusael</groupId><artifactId>mytravels</artifactId><version>0.0.1-SNAPSHOT</version><name>mytravels</name><description>springboot + vue</description><properties><java.version>1.8</java.version></properties><dependencies><!--web依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--mybatis依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.2</version></dependency><!--热部署--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.12</version></dependency><!--test--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!--文件上传--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency><!--测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495

配置文件(application.properties)

application.properties:

server.port=8989
spring.application.name=travelsspring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/travels?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=1234mybatis.mapper-locations=classpath:com/yusael/travels/mapper/*.xml
mybatis.type-aliases-package=com.yusael.travels.entitylogging.level.root=info
logging.level.com.yusael.travels.dao=debug# 上传的图片存放的路径
upload.dir=D:/CodePro/IdeaPro/SpringBoot/travels/images
spring.resources.static-locations=file:${upload.dir}
123456789101112131415161718

href=“javascript:;” 含义

代码中经常遇到这种写法:

<a href="javascript:;" @click="deleteProvince(province.id)">删除省份</a>
1

其中的 href="javascript:;" 是什么意思呢?

  • javascript: 表示在触发默认动作时,执行一段 JavaScript 代码;
  • javascript:; 表示什么都不执行,这样点击时就没有任何反应,相当于去掉 a 标签的默认行为。

select - option 绑定 Vue 实例

select 中 通过 v-model 绑定当前的选项,option 中使用 v-for 遍历显示所有选项。

<label><div class="label-text">所属省份:</div><select v-model="place.provinceid"><option v-for="(pro,index) in provinces" :value="pro.id" v-text="pro.name"></option></select></label>
123456

删除时增加确认选项

if (confirm("确定要删除景点吗?")) {// code....
}
123

20200626210046689.png

Vue 获取地址栏跳转的参数

对于这么一个 a 标签,我们要在另一个页面获取这个 url 的参数 id:

<a :href="'./updateprovince.html?id=' + province.id">修改省份</a>
1

可以通过 location.href 获取 url 再进行截取:

var id = location.href.substring(location.href.indexOf("=") + 1);
1

前后端分离项目—验证码功能

验证码工具类:

package com.yusael.travels.utils;import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;import javax.imageio.ImageIO;public class CreateImageCode {// 图片的宽度。private int width = 160;// 图片的高度。private int height = 40;// 验证码字符个数private int codeCount = 4;// 验证码干扰线数private int lineCount = 20;// 验证码private String code = null;// 验证码图片Bufferprivate BufferedImage buffImg = null;Random random = new Random();public CreateImageCode() {creatImage();}public CreateImageCode(int width, int height) {this.width = width;this.height = height;creatImage();}public CreateImageCode(int width, int height, int codeCount) {this.width = width;this.height = height;this.codeCount = codeCount;creatImage();}public CreateImageCode(int width, int height, int codeCount, int lineCount) {this.width = width;this.height = height;this.codeCount = codeCount;this.lineCount = lineCount;creatImage();}// 生成图片private void creatImage() {int fontWidth = width / codeCount;// 字体的宽度int fontHeight = height - 5;// 字体的高度int codeY = height - 8;// 图像bufferbuffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = buffImg.getGraphics();//Graphics2D g = buffImg.createGraphics();// 设置背景色g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);// 设置字体//Font font1 = getFont(fontHeight);Font font = new Font("Fixedsys", Font.BOLD, fontHeight);g.setFont(font);// 设置干扰线for (int i = 0; i < lineCount; i++) {int xs = random.nextInt(width);int ys = random.nextInt(height);int xe = xs + random.nextInt(width);int ye = ys + random.nextInt(height);g.setColor(getRandColor(1, 255));g.drawLine(xs, ys, xe, ye);}// 添加噪点float yawpRate = 0.01f;// 噪声率int area = (int) (yawpRate * width * height);for (int i = 0; i < area; i++) {int x = random.nextInt(width);int y = random.nextInt(height);buffImg.setRGB(x, y, random.nextInt(255));}String str1 = randomStr(codeCount);// 得到随机字符this.code = str1;for (int i = 0; i < codeCount; i++) {String strRand = str1.substring(i, i + 1);g.setColor(getRandColor(1, 255));// g.drawString(a,x,y);// a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处g.drawString(strRand, i*fontWidth+3, codeY);}}// 得到随机字符private String randomStr(int n) {String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";String str2 = "";int len = str1.length() - 1;double r;for (int i = 0; i < n; i++) {r = (Math.random()) * len;str2 = str2 + str1.charAt((int) r);}return str2;}// 得到随机颜色private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色if (fc > 255)fc = 255;if (bc > 255)bc = 255;int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}/*** 产生随机字体*/private Font getFont(int size) {Random random = new Random();Font font[] = new Font[5];font[0] = new Font("Ravie", Font.PLAIN, size);font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);font[2] = new Font("Fixedsys", Font.PLAIN, size);font[3] = new Font("Wide Latin", Font.PLAIN, size);font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);return font[random.nextInt(5)];}// 扭曲方法private void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private void shearX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(2);boolean borderGap = true;int frames = 1;int phase = random.nextInt(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private void shearY(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(40) + 10; // 50;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}public void write(OutputStream sos) throws IOException {ImageIO.write(buffImg, "png", sos);sos.close();}public BufferedImage getBuffImg() {return buffImg;}public String getCode() {return code.toLowerCase();}//使用方法/*public void getCode3(HttpServletRequest req, HttpServletResponse response,HttpSession session) throws IOException{// 设置响应的类型格式为图片格式response.setContentType("image/jpeg");//禁止图像缓存。response.setHeader("Pragma", "no-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);CreateImageCode vCode = new CreateImageCode(100,30,5,10);session.setAttribute("code", vCode.getCode());vCode.write(response.getOutputStream());}*/}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230

后台控制器:需要对生成的验证码图片进行 Base64 编码后传到前端页面,前端再解析展示图片。

@RestController
@RequestMapping("/user")
@CrossOrigin // 允许跨域(前后端分离)
@Slf4j // 日志对象
public class UserController {/*** 生成验证码* @throws IOException*/@GetMapping("/getImage")public Map<String, String> getImage(HttpServletRequest request) throws IOException {Map<String, String> result = new HashMap<>();CreateImageCode createImageCode = new CreateImageCode();// 获取验证码String securityCode = createImageCode.getCode();// 验证码存入sessionString key = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());request.getServletContext().setAttribute(key, securityCode);// 生成图片BufferedImage image = createImageCode.getBuffImg();//进行base64编码ByteArrayOutputStream bos = new ByteArrayOutputStream();ImageIO.write(image, "png", bos);String string = Base64Utils.encodeToString(bos.toByteArray());result.put("key", key);result.put("image", string);return result;}
}
1234567891011121314151617181920212223242526272829

前端页面:

<!--前后端分离的架构, 动态访问验证码-->
<img :src="src" id="img-vcode" @click="getImage" :key="key">
<label><div class="label-text">验证码:</div><input type="text" name="vcode" style="width: 100px">
</label>
123456
<script>const app = new Vue({el: "#app",data: {src: "",key: ""},methods: {getImage() {_this = this;axios.get("http://localhost:8989/user/getImage").then((res) => {console.log(res.data);_this.src = "data:image/png;base64," + res.data.image;_this.key = res.data.key;})}},created() {this.getImage(); // 获取验证码}});
</script>
12345678910111213141516171819202122

前后端分离项目—分页功能

mysql 的 LIMIT 分页语句:

  • LIMIT n: 取前 n 个数据,相当于 LIMIT 0, n
  • LIMIT 2, 4: 从第 3 行开始检索 4 条数据;

分页查询的SQL语句:参数1是开始查询的数据行,参数2是查询数据条数。

<!--分页查询所有-->
<select id="findByPage" resultType="Province">SELECT * FROM t_provinceORDER BY placecountsLIMIT #{start}, #{rows}
</select>
123456

后台业务层代码:

传入的参数是当前所在页数,以及页面显示数量,无法直接应用 MySQL 的 limit 查询子句中,需要转换一下:start = (page - 1) * rows 计算出 limit 字句的第一个参数。

@Override
public List<Province> findByPage(Integer page, Integer rows) {// 传入的是当前页数, 以及页面显示的数量// 所以要根据这两个参数计算从mysql中查询数据要从第几行开始查几条int start = (page - 1) * rows; // 计算要查询的数据是从第几条数据开始的return provinceDAO.findByPage(start, rows);
}
1234567

后台控制器代码:

/*** 分页查询数据*/
@GetMapping("/findByPage")
public Map<String, Object> findByPage(Integer page, Integer rows) {page = page==null ? 1 : page;rows = rows==null ? 4 : rows;System.out.println(page + " : " + rows);HashMap<String, Object> map = new HashMap<>();// 分页查询出当前页面显示的数据List<Province> provinces = provinceService.findByPage(page, rows);// 查询总数据条数, 用于计算总页数Integer totals = provinceService.findTotals();// 计算总页数// 如果总数据条数可以整除每一页数据个数, 说明结果正好为总页数// 如果总数据条数无法整除每一页数据个数, 说明总页数需要结果 + 1Integer totalPage = totals % rows == 0 ? totals / rows : totals / rows + 1;map.put("provinces", provinces);map.put("totals", totals);map.put("totalPage", totalPage);map.put("page", page);map.forEach((k, v) -> {System.out.println(k + ": " + v);});return map;
}
123456789101112131415161718192021222324252627282930

前端页面:

<div id="pages"><!--上一页, 只有当前所在页数>1才会显示--><a href="javascript:;" class="page" v-if="page > 1" @click="findAll(page - 1)">&lt;上一页</a><!--页面--><a href="javascript:;" class="page" v-for="index in totalPage" @click="findAll(index)" v-text="index"></a><!--下一页, 只有当前所在页数<总页数才会显示--><a href="javascript:;" class="page" v-if="page < totalPage" @click="findAll(page + 1)">下一页&gt;</a>
</div>
12345678

超链接的写法可以更优化一下:优化后点击当前所在页数无效(不会发送任何请求)。

<div id="pages"><a href="javascript:;" class="page" v-if="page > 1" @click="findAllPage(page - 1)">&lt;上一页</a><span v-for="index in totalPage"><a href="javascript:;" class="page" v-if="page == index" v-text="index"></a><a href="javascript:;" class="page" v-if="page != index" @click="findAllPage(index)" v-text="index"></a></span><a href="javascript:;" class="page" v-if="page < totalPage" @click="findAllPage(page + 1)">下一页&gt;</a>
</div>
12345678
<script>const app = new Vue({el: "#app",data: {provinces : [],page : 1,rows : 4,totalPage : 0,totals : 0,},methods: {findAll(indexpage) { // 查询某一页的数据if (indexpage) {this.page = indexpage;}_this = this; // 保存当前对象, 用于下面的作用域axios.get("http://localhost:8989/province/findByPage?page=" + this.page + "&rows=" + this.rows).then((res) => {_this.provinces = res.data.provinces;_this.page = res.data.page;_this.totalPage = res.data.totalPage;_this.totals = res.data.totals;});},},created() {this.findAll();}});
</script>
1234567891011121314151617181920212223242526272829

前后端分离项目—日期数据类型的处理

前后端数据交互采用的是 Json 的话,只需要在实体类中的属性加一个注解即可:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString
public class Place {private String id;private String name;private String picpath;@JsonFormat(pattern = "yyyy-MM-dd")private Date hottime; // 前后端分离项目对日期数据类型的处理private Double hotticket;private Double dimticket;private String placedes;private String provinceid;
}
123456789101112131415161718

前后端分离项目—文件上传

注:由于我们往数据库中插入的是文件的 Base64 编码,因此需要将 数据库中 picpath 字段的大小设置的足够大,可以使用以下几个数据类型:

数据类型 最大长度 近似值
TINYTEXT 256 bytes
TEXT 65,535 bytes ~64kb
MEDIUMTEXT 16,777,215 bytes ~16MB
LONGTEXT 4,294,967,295 bytes ~4GB

在配置文件 application.properties 中配置文件上传的路径:

spring.resources.static-locations=file:${upload.dir}
upload.dir=D:/CodePro/IdeaPro/SpringBoot/travels/images
12

在后台控制器中 注入路径,并实现文件上传(用 Base64 编码进行处理):

@RestController
@RequestMapping("/place")
@CrossOrigin
public class PlaceController {@Autowiredprivate PlaceService placeService;@Value("${upload.dir}") // 注入private String realPath;/*** 保存景点信息* @param pic* @return*/@PostMapping("save")public Result save(MultipartFile pic, Place place) throws IOException {Result result = new Result();try {// 文件上传String extension = FilenameUtils.getExtension(pic.getOriginalFilename());String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + extension;// base64编码处理(注意, 这一步必须放在 transferTo 操作前面!)place.setPicpath(Base64Utils.encodeToString(pic.getBytes()));// 文件上传File file = new File(realPath);pic.transferTo(new File(file,newFileName));// 保存place对象placeService.save(place);result.setMsg("保存景点信息成功!!!");} catch (Exception e) {e.printStackTrace();result.setState(false).setMsg(e.getMessage());}return result;}
}
1234567891011121314151617181920212223242526272829303132333435

前端中上传文件:给标签添加属性 ref="myFile"

<div class="label-text">印象图片:</div>
<div style="text-align: center;padding-left: 36%"><div id="upload-tip">+</div><img src="" alt="" id="img-show" style="display: none"><input type="file" id="imgfile" ref="myFile" style="display: none" onchange="imgfileChange()">
</div>
123456
<script>const app = new Vue({el: "#app",data: {provinces: [],place: {},id: "",},methods: {savePlaceInfo() { // 保存景点的方法console.log(this.place); // 获取到了place对象let myFile = this.$refs.myFile;let files = myFile.files;let file = files[0];let formData = new FormData();formData.append("pic", file);formData.append("name", this.place.name);formData.append("hottime", this.place.hottime);formData.append("hotticket", this.place.hotticket);formData.append("dimticket", this.place.dimticket);formData.append("placedes", this.place.placedes);formData.append("provinceid", this.place.provinceid);//axiosaxios({method: 'post',url: 'http://localhost:8989/place/save',data: formData,headers: {'Content-Type': 'multipart/form-data'}}).then((res) => {console.log(res.data);if (res.data.state) {alert(res.data.msg + ",点击确定回到景点列表");location.href = "./viewspotlist.html?id=" + this.place.provinceid;} else {alert(res.data.msg + ",点击确定回到景点列表");}});}},});
</script>
12345678910111213141516171819202122232425262728293031323334353637383940414243

前端中展示 base64 格式的文件:

<img :src="'data:image/png;base64,' + place.picpath" class="viewspotimg">
1

#### _Springboot_集成flowable-modeler(6.4.1) 实现免登(BPMN组件已汉化)

03-15
好几天的阅读分析源码,才能把flowable的流程设计器与idm完全剥离实现免登BPMN组件已汉化

江南一点雨的专栏

%!(EXTRA markdown.ResourceType=, string=, string=)

7万+

SpringBoot+Vue_前后_端__分离,使用SpringSecurity完美处理权限问题(一)

当前后_端__分离_时,权限问题的处理也和我们传统的处理方式有一点差异。笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方案,希望这个系列能够给小伙伴一些帮助。本系列文章并不是手把手的教程,主要介绍了核心思路并讲解了核心代码,完整的代码小伙伴们可以在GitHub上star并clone下来研究。另外,原本计划把项目跑起来放到网...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1180264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源AI绘图落地难点突破:麦橘超然生产环境部署

开源AI绘图落地难点突破&#xff1a;麦橘超然生产环境部署 1. 引言 随着生成式AI技术的快速发展&#xff0c;开源图像生成模型在本地化、私有化部署场景中的需求日益增长。然而&#xff0c;受限于显存占用高、部署流程复杂、依赖管理混乱等问题&#xff0c;许多开发者在将先进…

通义千问3-4B部署成本测算:不同云厂商价格对比实战

通义千问3-4B部署成本测算&#xff1a;不同云厂商价格对比实战 1. 引言 随着大模型轻量化趋势的加速&#xff0c;40亿参数级别的小模型正成为端侧AI和边缘计算场景的重要选择。通义千问 3-4B-Instruct-2507&#xff08;Qwen3-4B-Instruct-2507&#xff09;作为阿里于2025年8月…

Kotaemon长期运行方案:云端GPU+自动启停省钱法

Kotaemon长期运行方案&#xff1a;云端GPU自动启停省钱法 你是不是也有这样的困扰&#xff1f;手头有个基于Kotaemon搭建的个人AI助手或知识库系统&#xff0c;需要长期对外提供服务——比如自动回答客户问题、处理文档检索、做智能客服入口。但一想到要24小时开着GPU服务器&a…

RexUniNLU医疗报告处理:症状与诊断关系

RexUniNLU医疗报告处理&#xff1a;症状与诊断关系 1. 引言 在医疗自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;从非结构化文本中提取关键医学信息是实现智能辅助诊断、病历结构化和临床决策支持的核心任务。传统的信息抽取方法通常依赖大量标注数据&#xff0c…

SpringBoot配置文件(1)

简单来说&#xff1a;ConfigurationProperties 是为了“批量、规范”地管理配置&#xff0c;而 Value 是为了“简单、直接”地注入单个值。以下是对这两种方式的详细对比总结&#xff1a;1. 核心对比总览表为了让你一目了然&#xff0c;我们先看特性对比&#xff1a;特性Config…

如何高效做中文情感分析?试试这款集成Web界面的StructBERT镜像

如何高效做中文情感分析&#xff1f;试试这款集成Web界面的StructBERT镜像 1. 背景与挑战&#xff1a;传统中文情感分析的落地瓶颈 在自然语言处理&#xff08;NLP&#xff09;的实际应用中&#xff0c;中文情感分析是企业级服务中高频出现的核心能力。无论是电商评论、客服对…

Qwen1.5-0.5B功能测评:轻量级对话模型真实表现

Qwen1.5-0.5B功能测评&#xff1a;轻量级对话模型真实表现 1. 引言 在当前大模型技术快速发展的背景下&#xff0c;如何在资源受限的设备上实现高效、可用的智能对话能力&#xff0c;成为开发者和企业关注的核心问题。阿里通义千问推出的 Qwen1.5-0.5B-Chat 模型&#xff0c;…

YOLO11架构详解:深度剖析其网络结构创新点

YOLO11架构详解&#xff1a;深度剖析其网络结构创新点 YOLO11是目标检测领域的一次重要演进&#xff0c;它在继承YOLO系列高效推理能力的基础上&#xff0c;引入了多项关键的网络结构创新。作为YOLOv8之后的全新版本&#xff08;尽管官方尚未发布YOLO11&#xff0c;本文基于社…

5个高性价比AI镜像:开箱即用免配置,低价畅玩视觉AI

5个高性价比AI镜像&#xff1a;开箱即用免配置&#xff0c;低价畅玩视觉AI 对于数字游民来说&#xff0c;在咖啡馆的碎片时间里学习前沿技术是常态。但公共网络不稳定、笔记本资源有限&#xff0c;让复杂的环境配置和大文件下载成了难以逾越的障碍。你是否也曾因为想研究YOLOv…

Glyph视觉推理优化:缓存机制减少重复计算的成本

Glyph视觉推理优化&#xff1a;缓存机制减少重复计算的成本 1. 技术背景与问题提出 在当前大模型应用中&#xff0c;长文本上下文处理已成为关键瓶颈。传统基于Token的上下文扩展方式&#xff08;如Transformer-XL、FlashAttention等&#xff09;虽然有效&#xff0c;但其计算…

SSM项目的部署

Mysql8.0、Tomcat9.0、jdk1.8 单体项目 第一阶段&#xff1a;环境搭建 (JDK, MySQL, Tomcat) 在部署项目之前&#xff0c;服务器必须具备运行环境。 1. 安装 JDK 1.8 SSM 项目通常依赖 JDK 1.8。 检查是否已安装&#xff1a; java -version安装 (以 CentOS 为例): # 搜索…

MinerU多文档处理技巧:云端GPU并行转换省时70%

MinerU多文档处理技巧&#xff1a;云端GPU并行转换省时70% 你是不是也遇到过这样的情况&#xff1f;手头有几百份PDF电子书要处理&#xff0c;比如出版社的编辑需要把老教材批量转成Markdown格式用于数字出版&#xff0c;或者研究人员想把大量学术论文结构化入库。本地电脑打开…

AI读脸术用户体验优化:加载动画与错误提示改进

AI读脸术用户体验优化&#xff1a;加载动画与错误提示改进 1. 引言 1.1 业务场景描述 在基于计算机视觉的Web应用中&#xff0c;用户上传图像后等待系统处理的过程是影响整体体验的关键环节。尤其在AI推理类服务中&#xff0c;尽管底层模型具备高效推理能力&#xff0c;但若…

Qwen快速入门:云端GPU懒人方案,打开浏览器就能用

Qwen快速入门&#xff1a;云端GPU懒人方案&#xff0c;打开浏览器就能用 你是不是也遇到过这样的情况&#xff1f;作为产品经理&#xff0c;想亲自体验一下大模型到底能做什么、反应有多快、输出质量如何&#xff0c;好为自己的产品设计找点灵感。可一想到要装环境、配CUDA、拉…

没万元显卡怎么玩AI编程?Seed-Coder-8B-Base云端镜像解救你

没万元显卡怎么玩AI编程&#xff1f;Seed-Coder-8B-Base云端镜像解救你 你是不是也刷到过那种视频&#xff1a;AI自动写游戏脚本、几秒生成一个贪吃蛇小游戏&#xff0c;甚至还能自己调试逻辑&#xff1f;看着特别酷&#xff0c;心里直痒痒。可一查实现方式&#xff0c;发现人…

通义千问2.5-7B-Instruct性能优化:让推理速度提升30%

通义千问2.5-7B-Instruct性能优化&#xff1a;让推理速度提升30% 随着大语言模型在实际应用中的广泛落地&#xff0c;推理效率成为决定用户体验和部署成本的关键因素。Qwen2.5-7B-Instruct作为通义千问系列中兼具高性能与实用性的指令调优模型&#xff0c;在自然语言理解、代码…

乐理笔记秒变语音:基于Supertonic的设备端高效转换

乐理笔记秒变语音&#xff1a;基于Supertonic的设备端高效转换 1. 引言&#xff1a;从乐理笔记到语音输出的技术跃迁 在音乐学习和创作过程中&#xff0c;大量的理论知识往往以文本形式记录&#xff0c;例如调式规则、音程关系、和弦构成等。对于像《理工男的乐理入门》这类结…

从零搭建高精度中文ASR系统|FunASR + speech_ngram_lm_zh-cn实战

从零搭建高精度中文ASR系统&#xff5c;FunASR speech_ngram_lm_zh-cn实战 1. 引言&#xff1a;构建高可用中文语音识别系统的现实需求 随着智能语音交互场景的不断扩展&#xff0c;对高精度、低延迟、易部署的中文自动语音识别&#xff08;ASR&#xff09;系统的需求日益增…

Cute_Animal_For_Kids_Qwen_Image从零开始:儿童AI绘画完整教程

Cute_Animal_For_Kids_Qwen_Image从零开始&#xff1a;儿童AI绘画完整教程 1. 学习目标与前置知识 本教程旨在帮助开发者、教育工作者及家长快速掌握如何使用基于阿里通义千问大模型的图像生成工具 Cute_Animal_For_Kids_Qwen_Image&#xff0c;实现为儿童定制化生成可爱风格…

数字人短视频矩阵:Live Avatar批量生成方案

数字人短视频矩阵&#xff1a;Live Avatar批量生成方案 你是不是也遇到过这样的困境&#xff1f;团队每天要产出20条以上的短视频内容&#xff0c;文案、拍摄、剪辑、发布一整套流程下来&#xff0c;人力成本高、效率低&#xff0c;还容易出错。更头疼的是&#xff0c;一旦主I…