diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
index 8fae928..29d581c 100644
--- a/.idea/dataSources.xml
+++ b/.idea/dataSources.xml
@@ -27,5 +27,17 @@
$ProjectFileDir$
+
+ mysql.8
+ true
+ com.mysql.cj.jdbc.Driver
+ jdbc:mysql://127.0.0.1:3306/yn_img_tool?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
+
+
+
+
+
+ $ProjectFileDir$
+
\ No newline at end of file
diff --git a/src/main/java/com/bonus/imgTool/backstage/controller/SynthesisQueryController.java b/src/main/java/com/bonus/imgTool/backstage/controller/SynthesisQueryController.java
index 20a4228..7aeb0b7 100644
--- a/src/main/java/com/bonus/imgTool/backstage/controller/SynthesisQueryController.java
+++ b/src/main/java/com/bonus/imgTool/backstage/controller/SynthesisQueryController.java
@@ -9,6 +9,7 @@ import com.bonus.imgTool.system.vo.EncryptedReq;
import com.bonus.imgTool.utils.ServerResponse;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -31,6 +32,13 @@ public class SynthesisQueryController {
@Resource(name = "SynthesisQueryService")
private SynthesisQueryService synthesisQueryService;
+ @ApiOperation("综合查询-照片综合查询-照片数量")
+ @PostMapping(value = "getImgNum")
+ @DecryptAndVerify(decryptedClass = QueryParamDto.class)
+ public ServerResponse getImgNum(EncryptedReq data) {
+ return synthesisQueryService.getImgNum(data.getData());
+ }
+
@PostMapping(value = "getImgList")
@DecryptAndVerify(decryptedClass = QueryParamDto.class)
@LogAnnotation(operModul = "综合查询-照片综合查询", operation = "查询照片", operDesc = "系统级事件",operType="查询")
diff --git a/src/main/java/com/bonus/imgTool/backstage/dao/SynthesisQueryDao.java b/src/main/java/com/bonus/imgTool/backstage/dao/SynthesisQueryDao.java
index fcc39a2..5be6528 100644
--- a/src/main/java/com/bonus/imgTool/backstage/dao/SynthesisQueryDao.java
+++ b/src/main/java/com/bonus/imgTool/backstage/dao/SynthesisQueryDao.java
@@ -1,6 +1,7 @@
package com.bonus.imgTool.backstage.dao;
import com.bonus.imgTool.backstage.entity.QueryParamDto;
+import com.bonus.imgTool.backstage.entity.SynthesisNumVo;
import com.bonus.imgTool.backstage.entity.SynthesisQueryVo;
import org.springframework.stereotype.Repository;
@@ -15,6 +16,16 @@ import java.util.List;
*/
@Repository(value = "SynthesisQueryDao")
public interface SynthesisQueryDao {
+
+ /**
+ * 综合查询-照片综合查询-照片数量
+ * @param dto
+ * @return SynthesisNumVo
+ * @author cwchen
+ * @date 2025/4/2 15:40
+ */
+ SynthesisNumVo getImgNum(QueryParamDto dto);
+
/**
* 照片综合查询
* @param dto
diff --git a/src/main/java/com/bonus/imgTool/backstage/entity/QueryParamDto.java b/src/main/java/com/bonus/imgTool/backstage/entity/QueryParamDto.java
index 45b422e..7d40eb2 100644
--- a/src/main/java/com/bonus/imgTool/backstage/entity/QueryParamDto.java
+++ b/src/main/java/com/bonus/imgTool/backstage/entity/QueryParamDto.java
@@ -2,6 +2,8 @@ package com.bonus.imgTool.backstage.entity;
import lombok.Data;
+import java.util.List;
+
/**
* @className:QueryParamDto
* @author:cwchen
@@ -16,8 +18,20 @@ public class QueryParamDto {
* 1.我的收藏 2.最近上传
*/
private int queryType;
- /**用户id*/
+ /**
+ * 用户id
+ */
private long userId;
+ /**
+ * 用户管理的工程
+ */
+ private List proIds;
+
+ /**
+ * 角色级别 0.项目部 1.分公司
+ */
+ private String roleLevel;
+
private int pageNum = 1;
private int pageSize = 15;
}
diff --git a/src/main/java/com/bonus/imgTool/backstage/entity/SynthesisNumVo.java b/src/main/java/com/bonus/imgTool/backstage/entity/SynthesisNumVo.java
new file mode 100644
index 0000000..0c8eac2
--- /dev/null
+++ b/src/main/java/com/bonus/imgTool/backstage/entity/SynthesisNumVo.java
@@ -0,0 +1,27 @@
+package com.bonus.imgTool.backstage.entity;
+
+import lombok.Data;
+
+/**
+ * @className:SynthesisNumVo
+ * @author:cwchen
+ * @date:2025-04-02-14:22
+ * @version:1.0
+ * @description:综合查询各类型图片数量
+ */
+@Data
+public class SynthesisNumVo {
+
+ /**总照片数量*/
+ private int totalNum;
+ /**安全违章*/
+ private int safetyVioNum;
+ /**质量检查*/
+ private int qualityInsNum;
+ /**安全措施落实*/
+ private int safetyMeasNum;
+ /**协调照片*/
+ private int coordinatedPhotoNum;
+ /**重要事项及宣传类*/
+ private int importIssuesAndPublicityNum;
+}
diff --git a/src/main/java/com/bonus/imgTool/backstage/entity/SynthesisQueryVo.java b/src/main/java/com/bonus/imgTool/backstage/entity/SynthesisQueryVo.java
index a92c431..5b53f64 100644
--- a/src/main/java/com/bonus/imgTool/backstage/entity/SynthesisQueryVo.java
+++ b/src/main/java/com/bonus/imgTool/backstage/entity/SynthesisQueryVo.java
@@ -15,7 +15,7 @@ import java.util.Date;
@Data
public class SynthesisQueryVo {
- private String id;
+ private Long id;
/**
* 原图图片路径
*/
diff --git a/src/main/java/com/bonus/imgTool/backstage/service/SynthesisQueryService.java b/src/main/java/com/bonus/imgTool/backstage/service/SynthesisQueryService.java
index 1893366..a076da2 100644
--- a/src/main/java/com/bonus/imgTool/backstage/service/SynthesisQueryService.java
+++ b/src/main/java/com/bonus/imgTool/backstage/service/SynthesisQueryService.java
@@ -11,6 +11,16 @@ import com.bonus.imgTool.utils.ServerResponse;
* @description:综合查询
*/
public interface SynthesisQueryService {
+
+ /**
+ * 综合查询-照片综合查询-照片数量
+ * @param data
+ * @return ServerResponse
+ * @author cwchen
+ * @date 2025/4/2 14:59
+ */
+ ServerResponse getImgNum(QueryParamDto data);
+
/**
* 照片综合查询
* @param data
diff --git a/src/main/java/com/bonus/imgTool/backstage/service/impl/SynthesisQueryServiceImpl.java b/src/main/java/com/bonus/imgTool/backstage/service/impl/SynthesisQueryServiceImpl.java
index 0c01fdf..6cf015e 100644
--- a/src/main/java/com/bonus/imgTool/backstage/service/impl/SynthesisQueryServiceImpl.java
+++ b/src/main/java/com/bonus/imgTool/backstage/service/impl/SynthesisQueryServiceImpl.java
@@ -2,10 +2,13 @@ package com.bonus.imgTool.backstage.service.impl;
import com.bonus.imgTool.backstage.dao.SynthesisQueryDao;
import com.bonus.imgTool.backstage.entity.QueryParamDto;
+import com.bonus.imgTool.backstage.entity.SynthesisNumVo;
import com.bonus.imgTool.backstage.entity.SynthesisQueryVo;
import com.bonus.imgTool.backstage.service.SynthesisQueryService;
+import com.bonus.imgTool.system.vo.LoginUser;
import com.bonus.imgTool.utils.ServerResponse;
import com.bonus.imgTool.utils.UserUtil;
+import com.bonus.imgTool.webResult.Constants;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
@@ -14,9 +17,8 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* @className:SynthesisQueryServiceImpl
@@ -32,11 +34,30 @@ public class SynthesisQueryServiceImpl implements SynthesisQueryService {
@Resource(name = "SynthesisQueryDao")
private SynthesisQueryDao synthesisQueryDao;
+ @Override
+ public ServerResponse getImgNum(QueryParamDto dto) {
+ try {
+ String roleLevel = Optional.ofNullable(UserUtil.getLoginUser()).map(LoginUser::getRoleLevel).orElse("0");
+ String proIds = Optional.ofNullable(UserUtil.getLoginUser()).map(LoginUser::getProIds).orElse("-1");
+ if(Objects.equals(roleLevel, Constants.ROLE_LEVEL)){ // 项目部级
+ List proList = Arrays.stream(proIds.split(",")).map(String::trim).filter(s -> !s.isEmpty()).map(Long::valueOf).collect(Collectors.toList());
+ dto.setProIds(proList);
+ }
+ dto.setRoleLevel(roleLevel);
+ SynthesisNumVo vo = Optional.ofNullable(synthesisQueryDao.getImgNum(dto)).orElseGet(SynthesisNumVo::new);
+ return ServerResponse.createSuccess(vo);
+ } catch (Exception e) {
+ log.error(e.toString(),e);
+ return ServerResponse.createErroe("查询失败");
+ }
+ }
+
@Override
public ServerResponse getImgList(QueryParamDto dto) {
PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
try {
- dto.setUserId(UserUtil.getLoginUser() != null ? UserUtil.getLoginUser().getId() : 0);
+ Long userId = Optional.ofNullable(UserUtil.getLoginUser()).map(LoginUser::getId).orElse(0L);
+ dto.setUserId(userId);
List list = Optional.ofNullable(synthesisQueryDao.getImgList(dto)).orElseGet(ArrayList::new);
PageInfo pageInfo = new PageInfo<>(list);
return ServerResponse.createSuccess(pageInfo);
diff --git a/src/main/java/com/bonus/imgTool/model/Role.java b/src/main/java/com/bonus/imgTool/model/Role.java
index c36fb2e..615c364 100644
--- a/src/main/java/com/bonus/imgTool/model/Role.java
+++ b/src/main/java/com/bonus/imgTool/model/Role.java
@@ -58,5 +58,9 @@ public class Role extends PageEntity {
* 角色级别
*/
private Integer level;
+ /**
+ * 角色级别名称
+ */
+ private String levelName;
}
diff --git a/src/main/java/com/bonus/imgTool/model/SysUser.java b/src/main/java/com/bonus/imgTool/model/SysUser.java
index d4a3c08..68d2bf0 100644
--- a/src/main/java/com/bonus/imgTool/model/SysUser.java
+++ b/src/main/java/com/bonus/imgTool/model/SysUser.java
@@ -1,7 +1,11 @@
package com.bonus.imgTool.model;
import com.bonus.imgTool.base.entity.PageEntity;
+import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
@Data
public class SysUser extends PageEntity {
@@ -105,6 +109,11 @@ public class SysUser extends PageEntity {
* 休眠时间
*/
private String sleepTime;
+ /**
+ * 创建时间
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private Date createTime;
private String updatePasswordTime;
@@ -141,6 +150,16 @@ public class SysUser extends PageEntity {
*/
private String signImg;
+ /**
+ * 角色级别
+ */
+ private String roleLevel;
+
+ /**
+ * 工程ID
+ */
+ private String proIds;
+
public interface Status {
int DISABLED = 0;
diff --git a/src/main/java/com/bonus/imgTool/system/controller/UserController.java b/src/main/java/com/bonus/imgTool/system/controller/UserController.java
index 3a11f06..5c0cdab 100644
--- a/src/main/java/com/bonus/imgTool/system/controller/UserController.java
+++ b/src/main/java/com/bonus/imgTool/system/controller/UserController.java
@@ -100,14 +100,14 @@ public class UserController {
try {
SysUser u = userService.getUser(data.getData().getLoginName());
if (u != null) {
- return ServerResponse.createErroe("登录名"+data.getData().getLoginName() + "已存在");
+ return ServerResponse.createErroe("登录账号"+data.getData().getLoginName() + "已存在");
}
- if(StringHelper.isNotEmpty(data.getData().getPhone())){
+ /* if(StringHelper.isNotEmpty(data.getData().getPhone())){
SysUser u2 = userService.getPhone(data.getData().getPhone());
if (u2 != null) {
return ServerResponse.createErroe("手机号"+data.getData().getPhone() + "已存在");
}
- }
+ }*/
ServerResponse response=userService.saveUser(data.getData());
return response;
}catch (Exception e){
diff --git a/src/main/java/com/bonus/imgTool/utils/HighQualityWatermark.java b/src/main/java/com/bonus/imgTool/utils/HighQualityWatermark.java
new file mode 100644
index 0000000..e501419
--- /dev/null
+++ b/src/main/java/com/bonus/imgTool/utils/HighQualityWatermark.java
@@ -0,0 +1,331 @@
+package com.bonus.imgTool.utils;
+import javax.imageio.*;
+import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
+import javax.imageio.stream.FileImageOutputStream;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+/**
+ * @className:HighQualityWatermark
+ * @author:cwchen
+ * @date:2025-04-02-14:04
+ * @version:1.0
+ * @description:
+ */
+public class HighQualityWatermark {
+
+ private static final String DEFAULT_FONT_NAME = "Microsoft YaHei";
+ private static final int DEFAULT_FONT_STYLE = Font.BOLD;
+ private static final Color DEFAULT_COLOR = new Color(195, 32, 32, 255);
+ private static final int MIN_FONT_SIZE = 10;
+ private static final int MAX_FONT_SIZE = 72;
+ private static final float MIN_OPACITY = 0.3f;
+ private static final float MAX_OPACITY = 0.9f;
+ private static final float DEFAULT_QUALITY = 1.0f; // 最高质量(无损)
+
+ /**
+ * 添加高质量多行水印
+ * @param sourceImagePath 源图片路径
+ * @param targetImagePath 目标图片路径
+ * @param textLines 多行水印文本
+ * @param position 水印位置
+ * @param opacity 透明度
+ * @param fontName 字体名称
+ */
+ public static void addHighQualityWatermark(String sourceImagePath, String targetImagePath,
+ List textLines, String position,
+ float opacity, String fontName) throws Exception {
+ // 参数校验
+ if (opacity < MIN_OPACITY || opacity > MAX_OPACITY) {
+ opacity = 0.7f;
+ }
+ // 读取源图片
+ opacity = Math.max(MIN_OPACITY, Math.min(opacity, MAX_OPACITY));
+ // 读取原始图片并获取其类型
+ BufferedImage originalImage = ImageIO.read(new File(sourceImagePath));
+ int imageType = originalImage.getTransparency() == Transparency.OPAQUE
+ ? BufferedImage.TYPE_INT_RGB
+ : BufferedImage.TYPE_INT_ARGB;
+ // 创建与原始图片相同大小的新图像
+ BufferedImage sourceImage = new BufferedImage(
+ originalImage.getWidth(),
+ originalImage.getHeight(),
+ imageType
+ );
+ int imageWidth = sourceImage.getWidth();
+ int imageHeight = sourceImage.getHeight();
+ // 绘制原始图片到新图像
+ Graphics2D g2d = sourceImage.createGraphics();
+ g2d.drawImage(originalImage, 0, 0, null);
+ // 设置最高质量的渲染参数
+ setHighestQuality(g2d);
+ // 计算最大允许宽度(图片宽度的四分之三)
+// int maxAllowedWidth = imageWidth / 2;
+ int maxAllowedWidth = (int) (imageWidth * 3.0 / 4);
+
+ // 确定最佳字体大小
+ Font optimalFont = findOptimalFontSize(g2d, textLines, maxAllowedWidth, imageWidth, imageHeight, fontName);
+ g2d.setFont(optimalFont);
+ FontMetrics fm = g2d.getFontMetrics();
+
+ // 处理每行文本的换行
+ List> wrappedLines = wrapAllLines(g2d, textLines, maxAllowedWidth);
+
+ // 计算水印总高度和最大行宽度
+ int lineHeight = fm.getHeight();
+ int totalHeight = calculateTotalHeight(wrappedLines, lineHeight);
+ int maxLineWidth = findMaxLineWidth(g2d, wrappedLines);
+
+ // 设置水印颜色和透明度
+ Color watermarkColor = new Color(DEFAULT_COLOR.getRed(), DEFAULT_COLOR.getGreen(),
+ DEFAULT_COLOR.getBlue(), (int)(opacity * 255));
+ g2d.setColor(watermarkColor);
+
+ // 计算水印起始位置
+ Point startPoint = calculateWatermarkPosition(position, imageWidth, imageHeight,
+ maxLineWidth, totalHeight, fm);
+
+ // 绘制水印
+ drawWatermarkLines(g2d, wrappedLines, startPoint, lineHeight, position, imageWidth);
+
+ // 释放资源
+ g2d.dispose();
+
+ // 高质量保存图片
+ saveWithHighQuality(sourceImage, targetImagePath);
+ }
+
+ /**
+ * 设置最高质量的渲染参数
+ */
+ private static void setHighestQuality(Graphics2D g2d) {
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ }
+
+ /**
+ * 寻找最佳字体大小
+ */
+ private static Font findOptimalFontSize(Graphics2D g2d, List textLines,
+ int maxAllowedWidth, int imgWidth,
+ int imgHeight, String fontName) {
+ // 基于图片对角线长度计算初始字体大小
+ double diagonal = Math.sqrt(imgWidth * imgWidth + imgHeight * imgHeight);
+ int initialSize = (int)(diagonal * 0.03);
+ initialSize = Math.max(MIN_FONT_SIZE, Math.min(initialSize, MAX_FONT_SIZE));
+
+ Font testFont = new Font(fontName, DEFAULT_FONT_STYLE, initialSize);
+ g2d.setFont(testFont);
+
+ /*// 检查所有行是否都适合
+ boolean allFit = checkAllLinesFit(g2d, textLines, maxAllowedWidth);
+
+ // 如果不适合,逐步减小字体大小
+ int currentSize = initialSize;
+ while (!allFit && currentSize > MIN_FONT_SIZE) {
+ currentSize--;
+ testFont = new Font(fontName, DEFAULT_FONT_STYLE, currentSize);
+ g2d.setFont(testFont);
+ allFit = checkAllLinesFit(g2d, textLines, maxAllowedWidth);
+ }*/
+
+ return testFont;
+ }
+
+ /**
+ * 检查所有行是否适合最大宽度
+ */
+ private static boolean checkAllLinesFit(Graphics2D g2d, List textLines, int maxWidth) {
+ FontMetrics fm = g2d.getFontMetrics();
+ return textLines.stream().allMatch(line -> fm.stringWidth(line) <= maxWidth);
+ }
+
+ /**
+ * 处理所有行的换行
+ */
+ private static List> wrapAllLines(Graphics2D g2d, List textLines, int maxWidth) {
+ List> wrappedLines = new ArrayList<>();
+ for (String line : textLines) {
+ wrappedLines.add(wrapSingleLine(g2d, line, maxWidth));
+ }
+ return wrappedLines;
+ }
+
+ /**
+ * 单行文本换行处理
+ */
+ private static List wrapSingleLine(Graphics2D g2d, String line, int maxWidth) {
+ List wrapped = new ArrayList<>();
+ FontMetrics fm = g2d.getFontMetrics();
+
+ // 如果整行宽度小于最大宽度,直接返回
+ if (fm.stringWidth(line) <= maxWidth) {
+ wrapped.add(line);
+ return wrapped;
+ }
+
+ // 按空格分割单词
+ String[] words = line.split("@@");
+ StringBuilder currentLine = new StringBuilder(words[0]);
+
+ for (int i = 1; i < words.length; i++) {
+ String testLine = currentLine + " " + words[i];
+ if (fm.stringWidth(testLine) <= maxWidth) {
+ currentLine.append(" ").append(words[i]);
+ } else {
+ wrapped.add(currentLine.toString());
+ currentLine = new StringBuilder(words[i]);
+ }
+ }
+ wrapped.add(currentLine.toString());
+
+ return wrapped;
+ }
+
+ /**
+ * 计算水印总高度
+ */
+ private static int calculateTotalHeight(List> allWrappedLines, int lineHeight) {
+ int totalLines = allWrappedLines.stream().mapToInt(List::size).sum();
+ // 总行数 * 行高 + (段落数-1) * 行高/2 (段落间距)
+ return totalLines * lineHeight + (allWrappedLines.size() - 1) * (lineHeight / 2);
+ }
+
+ /**
+ * 查找最大行宽度
+ */
+ private static int findMaxLineWidth(Graphics2D g2d, List> allWrappedLines) {
+ int maxWidth = 0;
+ FontMetrics fm = g2d.getFontMetrics();
+
+ for (List lines : allWrappedLines) {
+ for (String line : lines) {
+ int width = fm.stringWidth(line);
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ }
+ }
+ return maxWidth;
+ }
+
+ /**
+ * 计算水印位置
+ */
+ private static Point calculateWatermarkPosition(String position, int imgWidth, int imgHeight,
+ int maxLineWidth, int totalHeight,
+ FontMetrics fm) {
+ int margin = (int)(Math.min(imgWidth, imgHeight) * 0.05); // 5%边距
+ int x = 0;
+ int y = 0;
+
+ switch (position.toLowerCase()) {
+ case "center":
+ x = (imgWidth - maxLineWidth) / 2;
+ y = (imgHeight - totalHeight) / 2 + fm.getAscent();
+ break;
+ case "top-left":
+ x = margin;
+ y = margin + fm.getAscent();
+ break;
+ case "top-right":
+ x = imgWidth - maxLineWidth - margin;
+ y = margin + fm.getAscent();
+ break;
+ case "bottom-left":
+ x = margin;
+ y = imgHeight - totalHeight - margin + fm.getAscent();
+ break;
+ case "bottom-right":
+ x = imgWidth - maxLineWidth - margin;
+ y = imgHeight - totalHeight - margin + fm.getAscent();
+ break;
+ default: // 默认居中
+ x = (imgWidth - maxLineWidth) / 2;
+ y = (imgHeight - totalHeight) / 2 + fm.getAscent();
+ }
+
+ return new Point(x, y);
+ }
+
+ /**
+ * 绘制水印文本
+ */
+ private static void drawWatermarkLines(Graphics2D g2d, List> allWrappedLines,
+ Point startPoint, int lineHeight,
+ String position, int imgWidth) {
+ int currentY = startPoint.y;
+ FontMetrics fm = g2d.getFontMetrics();
+
+ for (List lines : allWrappedLines) {
+ for (String line : lines) {
+ int lineWidth = fm.stringWidth(line);
+ int x = startPoint.x;
+
+ // 如果是居中位置,每行单独计算x坐标
+ if ("center".equalsIgnoreCase(position)) {
+ x = (imgWidth - lineWidth) / 2;
+ }
+
+ g2d.drawString(line, x, currentY);
+ currentY += lineHeight;
+ }
+ // 段落间距(多行组之间的额外间距)
+ currentY += lineHeight / 8;
+ }
+ }
+
+ /**
+ * 高质量保存JPG图片(无损或接近无损)
+ */
+ private static void saveWithHighQuality(BufferedImage image, String filePath) throws Exception {
+ String formatName = filePath.substring(filePath.lastIndexOf(".") + 1).toLowerCase();
+
+ if ("jpg".equals(formatName) || "jpeg".equals(formatName)) {
+ // JPG特殊处理以保证高质量
+ Iterator writers = ImageIO.getImageWritersByFormatName("jpg");
+ ImageWriter writer = writers.next();
+
+ // 配置JPEG编码参数
+ JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) writer.getDefaultWriteParam();
+ jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
+ jpegParams.setCompressionQuality(DEFAULT_QUALITY); // 1.0 = 最高质量
+ // 写入文件
+ try (FileImageOutputStream output = new FileImageOutputStream(new File(filePath))) {
+ writer.setOutput(output);
+ writer.write(null, new IIOImage(image, null, null), jpegParams);
+ }
+ writer.dispose();
+ } else {
+ // 其他格式直接保存
+ ImageIO.write(image, formatName, new File(filePath));
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ // 准备多行水印文本
+ List watermarkLines = new ArrayList<>();
+ watermarkLines.add("2024-05-12");
+ String proName = "广东电网直流背靠背东莞工程(大湾区南粤直流背靠背工程)南粤±300kV背靠背换流站工程/新增/广东电网直流背靠背东莞工程(大湾区南通道直流背靠背工程)110kV环保城输变电工程(电缆部分)";
+ watermarkLines.add(proName.replaceAll("(.{18})", "$1@@"));
+ watermarkLines.add("安全违章");
+ watermarkLines.add("违章照片");
+ String localPath = "C:\\Users\\10488\\Desktop\\3.jpg";
+ String outPath = "C:\\Users\\10488\\Desktop\\output.jpg";
+ // 添加高质量水印
+ addHighQualityWatermark(localPath, outPath,
+ watermarkLines, "bottom-left",
+ 0.7f, "Microsoft YaHei");
+ System.out.println("高质量水印添加完成,图片已无损输出");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/com/bonus/imgTool/webResult/Constants.java b/src/main/java/com/bonus/imgTool/webResult/Constants.java
index 40bf460..19f1416 100644
--- a/src/main/java/com/bonus/imgTool/webResult/Constants.java
+++ b/src/main/java/com/bonus/imgTool/webResult/Constants.java
@@ -182,5 +182,9 @@ public class Constants
public static final Integer TYPE4 = 4;
public static final Integer TRY_COUNT_NUM = 10;
+ /**角色级别*/
+ public static final String ROLE_LEVEL = "0";
+
+
}
diff --git a/src/main/resources/mappers/backstage/SynthesisQueryMapper.xml b/src/main/resources/mappers/backstage/SynthesisQueryMapper.xml
index b49c8f2..a13e2d7 100644
--- a/src/main/resources/mappers/backstage/SynthesisQueryMapper.xml
+++ b/src/main/resources/mappers/backstage/SynthesisQueryMapper.xml
@@ -3,18 +3,53 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+
+
diff --git a/src/main/resources/mappers/system/UserMapper.xml b/src/main/resources/mappers/system/UserMapper.xml
index d18dfee..9b404a6 100644
--- a/src/main/resources/mappers/system/UserMapper.xml
+++ b/src/main/resources/mappers/system/UserMapper.xml
@@ -73,14 +73,17 @@