diff --git a/bonus-common-biz/pom.xml b/bonus-common-biz/pom.xml
index 9b98d0fe..30315ab2 100644
--- a/bonus-common-biz/pom.xml
+++ b/bonus-common-biz/pom.xml
@@ -176,6 +176,23 @@
org.springframework.data
spring-data-redis
+
+
+ com.google.zxing
+ core
+ 3.3.0
+
+
+ com.google.zxing
+ javase
+ 3.3.0
+
+
+
+ org.apache.commons
+ commons-compress
+ 1.22
+
diff --git a/bonus-common-biz/src/main/java/com/bonus/common/biz/config/BackstageApplication.java b/bonus-common-biz/src/main/java/com/bonus/common/biz/config/BackstageApplication.java
new file mode 100644
index 00000000..af87c3fa
--- /dev/null
+++ b/bonus-common-biz/src/main/java/com/bonus/common/biz/config/BackstageApplication.java
@@ -0,0 +1,63 @@
+package com.bonus.common.biz.config;
+
+/**
+ * 二维码类路径
+ * @Author ma_sh
+ * @create 2024/10/22 15:18
+ */
+public class BackstageApplication {
+
+ private final static String CS_LOGIN_PATH = "ahjj.jypxks.com:9988";
+ // private final static String CS_LOGIN_PATH = "112.30.107.201:9988";
+ //测试环境
+ //private final static String CS_LOGIN_PATH = "192.168.0.14:2011";
+
+ private final static String CS_USER_NAME = "root";
+
+ private final static String CS_PASSWORD = "bonusadmin";
+
+ private final static String CS_EP_ID = "system";
+
+ private final static String url = "http://ahjj.jypxks.com:9988/imw/";
+ // private final static String url = "http://192.168.0.6:18082/imt_cs/";
+ //private final static String url = "http://192.168.0.14:2011/imw_cs/";
+
+
+
+ private final static String imageUrlPrefix = "http://ahjj.jypxks.com:9988/imw/images/";
+
+ //测试环境
+ //private final static String imageUrlPrefix = "http://192.168.0.14:2011/imt_cs/images/";
+
+ private final static String fileUrlPrefix = "http://ahjj.jypxks.com:9988/imw/maTypeFile/";
+ //测试环境
+ // private final static String fileUrlPrefix = "http://192.168.0.14:2011/imt_cs/maTypeFile/";
+
+ public static String getCsLoginPath() {
+ return CS_LOGIN_PATH;
+ }
+
+ public static String getCsUserName() {
+ return CS_USER_NAME;
+ }
+
+ public static String getCsPassword() {
+ return CS_PASSWORD;
+ }
+
+ public static String getCsEpId() {
+ return CS_EP_ID;
+ }
+
+ public static String getUrl() {
+ return url;
+ }
+
+ public static String getImageUrlPrefix(){
+ return imageUrlPrefix;
+ }
+
+ public static String getFileurlprefix() {
+ return fileUrlPrefix;
+ }
+}
diff --git a/bonus-common-biz/src/main/java/com/bonus/common/biz/config/DateTimeHelper.java b/bonus-common-biz/src/main/java/com/bonus/common/biz/config/DateTimeHelper.java
new file mode 100644
index 00000000..0e28aa89
--- /dev/null
+++ b/bonus-common-biz/src/main/java/com/bonus/common/biz/config/DateTimeHelper.java
@@ -0,0 +1,603 @@
+package com.bonus.common.biz.config;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @Author ma_sh
+ * @create 2024/10/22 14:36
+ */
+public class DateTimeHelper {
+
+ private static final SimpleDateFormat FULL_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ /**
+ * 获取当前时间的年份
+ *
+ * @return
+ */
+ public static String getNowYear() {
+ return format(new Date(), "yyyy");
+ }
+
+ public static String getNowMonthAndDay() {
+ return format(new Date(), "MM-dd");
+ }
+
+ public static String getYear(Date d) {
+ int year = d.getYear() + 1900;
+ return year + "";
+ }
+
+
+
+ /**
+ * 格式化 时间
+ *
+ * @param format
+ * @return
+ */
+ public static String format(Date d, String format) {
+ SimpleDateFormat df = new SimpleDateFormat(format);
+ return df.format(d);
+ }
+
+ public static String format(String str, String format, String disFormat) {
+ Date d = parse(str, format);
+ return format(d, disFormat);
+ }
+
+ /**
+ * 格式化 时间
+ *
+ * @param format
+ * @return
+ */
+ public static String format(Date d, DateFormat format) {
+ return format.format(d);
+ }
+
+ /**
+ * 格式化 时间
+ *
+ * @param format
+ * @return Date
+ * @throws ParseException
+ */
+ public static Date parse(String dateStr, String format) {
+ SimpleDateFormat df = new SimpleDateFormat(format);
+ try {
+ return df.parse(dateStr);
+ } catch (ParseException e) {
+ return new Date();
+ }
+ }
+
+ public static Date parse(String dateStr, String format, Date d) {
+ try {
+ SimpleDateFormat df = new SimpleDateFormat(format);
+ return df.parse(dateStr);
+ } catch (Exception e) {
+ return d;
+ }
+ }
+
+ /**
+ * 解析时间
+ *
+ * @return Date
+ * @throws ParseException
+ */
+ public static Date parse(String dateStr, DateFormat format) throws ParseException {
+ return format.parse(dateStr);
+ }
+
+ public static Date parseDate(String dateStr) throws ParseException {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ return sdf.parse(dateStr);
+ }
+
+ /**
+ * 获取当前时间的年月
+ *
+ * @return
+ */
+ public static String getPrevMonth() {
+ return minusMonth(new Date(), 1);
+ }
+
+ /**
+ * 获取当前时间的上个年月
+ *
+ * @return
+ */
+ public static String getNowMonth() {
+ return format(new Date(), "yyyy-MM");
+ }
+
+ /**
+ * 获取当前时间的上个年月格式化
+ *
+ * @return
+ */
+ public static String getNowMonthFomart() {
+ return format(new Date(), "yyyyMM");
+ }
+
+ /**
+ * 获取当前时间的前一天
+ *
+ * @return
+ */
+ public static String getPreDate(String dateStr) {
+ Date date = parse(dateStr, "yyyy-MM-dd");
+ Calendar c = Calendar.getInstance();
+ c.setTime(date);
+ c.add(Calendar.DAY_OF_MONTH, -1);
+ return format(c.getTime(), "yyyy-MM-dd");
+ }
+
+ /**
+ * 获取当前时间的上一个月
+ *
+ * @return
+ */
+ public static String getPreMonthDate() {
+ Date date = new Date();
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date); // 设置为当前时间
+ calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); // 设置为上一个月
+ date = calendar.getTime();
+ return format(date, "yyyy-MM-dd");
+ }
+
+ public static String getPreMonth() {
+ Date date = new Date();
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); // 设置为上一个月
+ date = calendar.getTime();
+ return format(date, "yyyy-MM");
+ }
+
+ /**
+ * 获取当前时间的前两个月
+ *
+ * @return
+ */
+ public static String getTwoMonthDate() {
+ Date date = new Date();
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date); // 设置为当前时间
+ calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 2); // 设置为前两个月
+ date = calendar.getTime();
+ return format(date, "yyyy-MM-dd");
+ }
+
+ /**
+ * 获取当前时间的上一年
+ *
+ * @return
+ */
+ public static String getPreYearDate() {
+ Date date = new Date();
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date); // 设置为当前时间
+ calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1); // 设置为上一年
+ date = calendar.getTime();
+ return format(date, "yyyy-MM-dd");
+ }
+
+ /**
+ * 获取当前时间的年月日
+ *
+ * @return
+ */
+ public static String getNowDate() {
+ return format(new Date(), "yyyy-MM-dd");
+ }
+
+ public static String getNowDateFomart() {
+ return format(new Date(), "yyyyMMdd");
+ }
+
+ /**
+ * 明年的昨天
+ *
+ * @param dateStr
+ * @return
+ */
+ public static String getNextYearDate(String dateStr) {
+ Date date = parse(dateStr, "yyyy-MM-dd");
+ Calendar c = Calendar.getInstance();
+ c.setTime(date);
+ c.add(Calendar.YEAR, 1);
+ c.add(Calendar.DAY_OF_MONTH, -1);
+ return format(c.getTime(), "yyyy-MM-dd");
+ }
+
+ /**
+ * 获取前年
+ *
+ * @param dateStr
+ * @return
+ */
+ public static String getBeforeYearDate(String dateStr) {
+ Date date = parse(dateStr, "yyyy-MM-dd");
+ Calendar c = Calendar.getInstance();
+ c.setTime(date);
+ c.add(Calendar.YEAR, -1);
+// c.add(Calendar.DAY_OF_MONTH, 1);
+ return format(c.getTime(), "yyyy-MM-dd");
+ }
+
+ /**
+ * 获取明天时间的年月日
+ *
+ * @return
+ */
+ public static String getTomorrowDate(String nowDate) {
+ Date date = parse(nowDate, "yyyy-MM-dd");
+ Calendar c = Calendar.getInstance();
+ c.setTime(date);
+ c.add(Calendar.DATE, 1);
+ return format(c.getTime(), "yyyy-MM-dd");
+ }
+
+ /**
+ * 获取当前时间
+ *
+ * @return
+ */
+ public static String getNowTime() {
+ return format(new Date(), "yyyy-MM-dd HH:mm:ss");
+ }
+
+ public static String getNowTimeFomart() {
+ return format(new Date(), "yyyyMMddHHmmss");
+ }
+
+ public static String getNextYear() {
+ return format(new Date(), "yyyy-MM-dd HH:mm:ss");
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static String minusMonth(Date date, int c) {
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
+ try {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.MONTH, -c);
+ return format(cal.getTime(), df);
+ } catch (Exception e) {
+ return format(date, df);
+ }
+ }
+
+ /**
+ *
+ * @param month
+ * @return
+ */
+ public static String minusMonth(String month, int c) {
+ try {
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
+ Date date = parse(month, df);
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.MONTH, -c);
+
+ return format(cal.getTime(), df);
+ } catch (Exception e) {
+ return month;
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static Date minus(Date d, int type, int c) {
+ try {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(d);
+ cal.add(type, -c);
+ return cal.getTime();
+ } catch (Exception e) {
+ return new Date();
+ }
+ }
+
+ /**
+ * 得到前一个月
+ *
+ * @param month
+ * @return
+ */
+ public static String prevMonth(String month) {
+ return minusMonth(month, 1);
+ }
+
+ /**
+ * 得到前一个月
+ *
+ * @param month
+ * @return
+ */
+ public static String prevMonth(String month, int c) {
+ return minusMonth(month, c);
+ }
+
+ public static float duration(String startTime, String stopTime) {
+ Date sd = DateTimeHelper.parse(startTime, "yyyy-MM-dd HH:mm");
+ long sl = sd.getTime();
+
+ Date ed = DateTimeHelper.parse(stopTime, "yyyy-MM-dd HH:mm");
+ long el = ed.getTime();
+
+ float l = el - sl;
+ if (l <= 0) {
+ l = 0;
+ }
+ l = l / (1000 * 60);
+ return l;
+ }
+
+ public static String getStartYearMonthBySeason(String year, int season) {
+ switch (season) {
+ case 1:
+ return getYearMonth(year, "01");
+ case 2:
+ return getYearMonth(year, "04");
+ case 3:
+ return getYearMonth(year, "07");
+ case 4:
+ return getYearMonth(year, "10");
+ default:
+ return getYearMonth(year, "01");
+ }
+ }
+
+ private static String getYearMonth(String year, String month) {
+ return year + "-" + month;
+ }
+
+ public static String getEndYearMonthBySeason(String year, int season) {
+ switch (season) {
+ case 1:
+ return getYearMonth(year, "03");
+ case 2:
+ return getYearMonth(year, "06");
+ case 3:
+ return getYearMonth(year, "09");
+ case 4:
+ return getYearMonth(year, "12");
+ default:
+ return getYearMonth(year, "03");
+ }
+ }
+
+ public static String getAddNumDay(String giveTime, int addDay) {
+ String time = giveTime;
+ Date date = new Date();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ Calendar calendar = Calendar.getInstance();
+ try {
+ date = sdf.parse(time);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ calendar.setTime(date);
+ calendar.add(Calendar.DAY_OF_MONTH, +addDay);// +1今天的时间加一天
+ date = calendar.getTime();
+ time = sdf.format(date);
+ return time;
+ }
+
+ /**
+ * date2比date1多的天数
+ *
+ * @param date1
+ * @param date2
+ * @return
+ */
+ public static int differentDays(Date date1, Date date2) {
+ Calendar cal1 = Calendar.getInstance();
+ cal1.setTime(date1);
+
+ Calendar cal2 = Calendar.getInstance();
+ cal2.setTime(date2);
+ int day1 = cal1.get(Calendar.DAY_OF_YEAR);
+ int day2 = cal2.get(Calendar.DAY_OF_YEAR);
+
+ int year1 = cal1.get(Calendar.YEAR);
+ int year2 = cal2.get(Calendar.YEAR);
+ if (year1 != year2) // 同一年
+ {
+ int timeDistance = 0;
+ for (int i = year1; i < year2; i++) {
+ if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) // 闰年
+ {
+ timeDistance += 366;
+ } else // 不是闰年
+ {
+ timeDistance += 365;
+ }
+ }
+
+ return timeDistance + (day2 - day1);
+ } else // 不同年
+ {
+// System.out.println("判断day2 - day1 : " + (day2 - day1));
+ return day2 - day1;
+ }
+ }
+
+ /**
+ * 通过时间秒毫秒数判断两个时间的间隔
+ *
+ * @param date1
+ * @param date2
+ * @return
+ */
+ public static int differentDaysByMillisecond(Date date1, Date date2) {
+ int days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
+ return days;
+ }
+
+ public static int calcDate(String dateStr, String dateStr2) {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ try {
+ Date date = format.parse(dateStr);
+ Date date2 = format.parse(dateStr2);
+ return DateTimeHelper.differentDays(date, date2);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ // 判断时间date1是否在时间date2之前
+ // 时间格式 2005-4-21
+ public static boolean isDateBefore(String date1, String date2) {
+ try {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ Date bt = sdf.parse(date1);
+ Date et = sdf.parse(date2);
+ if (bt.before(et)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ } catch (ParseException e) {
+ System.out.print("[SYS] " + e.getMessage());
+ return false;
+ }
+ }
+
+ public static boolean isFirstDay() {
+ Calendar c = Calendar.getInstance();
+ c.setTime(new Date());
+ return c.get(Calendar.DAY_OF_MONTH) == 1;
+ }
+
+ public static String getFirstDay() {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ // 获取当前月第一天:
+ Calendar c = Calendar.getInstance();
+ c.add(Calendar.MONTH, 0);
+ c.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
+ String first = format.format(c.getTime());
+ return first;
+ }
+
+ public static String getLastDay() {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ // 获取当前月最后一天
+ Calendar ca = Calendar.getInstance();
+ ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
+ String last = format.format(ca.getTime());
+ return last;
+ }
+
+ public static String getPreFirstDay() {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ // 获取当前月第一天:
+ Calendar c = Calendar.getInstance();
+ c.add(Calendar.MONTH, -1);
+ c.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
+ String first = format.format(c.getTime());
+ return first;
+ }
+
+ public static String getPreLastDay() {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ // 获取当前月最后一天
+ Calendar c = Calendar.getInstance();
+ c.add(Calendar.MONTH, -1);
+ c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
+ String last = format.format(c.getTime());
+ return last;
+ }
+
+ // 计算两个日期相差年数
+ public static int yearDateDiff(String startDate, String endDate) {
+ int year = 0;
+ try {
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ Calendar bef = Calendar.getInstance();
+ Calendar aft = Calendar.getInstance();
+ bef.setTime(sdf.parse(startDate));
+
+ aft.setTime(sdf.parse(endDate));
+ year = aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR);
+
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return year;
+ }
+
+ public static boolean isInXMinutes(String createTime, int x) {
+ try {
+ Date date = FULL_SDF.parse(createTime);
+ Date now = new Date();
+ long diff = now.getTime() - date.getTime();
+ return diff <= x * 60 * 1000;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public static boolean isMonthStartAndEnd(String startDateStr, String endDateStr) {
+ try {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ Date startDate = sdf.parse(startDateStr);
+ Date endDate = sdf.parse(endDateStr);
+ Calendar startCal = Calendar.getInstance();
+ startCal.setTime(startDate);
+ Calendar endCal = Calendar.getInstance();
+ endCal.setTime(endDate);
+ Calendar today = Calendar.getInstance();
+ today.setTime(new Date());
+ if (startCal.get(Calendar.DAY_OF_MONTH) == 1
+ && endCal.get(Calendar.DAY_OF_MONTH) == endCal.getActualMaximum(Calendar.DAY_OF_MONTH)
+ && startCal.get(Calendar.YEAR) == endCal.get(Calendar.YEAR)
+ && startCal.get(Calendar.MONTH) == endCal.get(Calendar.MONTH) && startCal.before(today)
+ && endCal.before(today)) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 判断当前时间是否为当月的最后一天
+ *
+ * @return
+ */
+ public static boolean isLastDayOfMonth() {
+ String day = getLastDay();
+ String currentDay = getNowDate();
+ if (day.equals(currentDay)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
+
diff --git a/bonus-common-biz/src/main/java/com/bonus/common/biz/config/QrCodeUtils.java b/bonus-common-biz/src/main/java/com/bonus/common/biz/config/QrCodeUtils.java
new file mode 100644
index 00000000..9ab5c30a
--- /dev/null
+++ b/bonus-common-biz/src/main/java/com/bonus/common/biz/config/QrCodeUtils.java
@@ -0,0 +1,180 @@
+package com.bonus.common.biz.config;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.client.j2se.MatrixToImageConfig;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Hashtable;
+
+/**
+ * @Author ma_sh
+ * @create 2024/10/22 14:40
+ */
+public class QrCodeUtils {
+
+ /** 二维码宽度 */
+ private static int width = 280;
+
+ /** 二维码高度 */
+ private static int height = 280;
+
+ /** 前景色 */
+ private static int onColor = 0xFF000000;
+
+ /** 背景色 */
+ private static int offColor = 0xFFFFFFFF;
+
+ /** 白边大小,取值范围0~4 */
+ private static int margin = 0;
+
+ /** 二维码容错率 */
+ private static ErrorCorrectionLevel level = ErrorCorrectionLevel.L;
+
+ /**
+ * 生成带logo的二维码图片
+ *
+ * @param txt //二维码内容
+ * @param logoPath //logo绝对物理路径
+ * @param imgPath //二维码保存绝对物理路径
+ * @param imgName //二维码文件名称
+ * @param suffix //图片后缀名
+ * @throws Exception
+ */
+ public static void generateQRImage(String txt, String logoPath, String imgPath, String imgName, String suffix)
+ throws Exception {
+ File filePath = new File(imgPath);
+ if (!filePath.exists()) {
+ filePath.mkdirs();
+ }
+ if (imgPath.endsWith("/")) {
+ imgPath += imgName;
+ } else {
+ imgPath += "/" + imgName;
+ }
+ Hashtable hints = new Hashtable();
+ hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
+ hints.put(EncodeHintType.ERROR_CORRECTION, level);
+ // 设置白边
+ hints.put(EncodeHintType.MARGIN, margin);
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(txt, BarcodeFormat.QR_CODE, width, height, hints);
+ File qrcodeFile = new File(imgPath);
+ writeToFile(bitMatrix, suffix, qrcodeFile, logoPath);
+ }
+
+ /**
+ * 生成二维码
+ *
+ * @param txt //二维码内容
+ * @param imgPath //二维码保存物理路径
+ * @param imgName //二维码文件名称
+ * @param suffix //图片后缀名
+ */
+ public static void generateQRImage(String txt, String imgPath, String imgName, String suffix) {
+
+ File filePath = new File(imgPath);
+ if (!filePath.exists()) {
+ filePath.mkdirs();
+ }
+ File imageFile = new File(imgPath, imgName);
+ Hashtable hints = new Hashtable<>();
+ // 指定纠错等级
+ hints.put(EncodeHintType.ERROR_CORRECTION, level);
+ // 指定编码格式
+ hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+ // 设置白边
+ hints.put(EncodeHintType.MARGIN, margin);
+ try {
+ MatrixToImageConfig config = new MatrixToImageConfig(onColor, offColor);
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(txt, BarcodeFormat.QR_CODE, width, height, hints);
+ // bitMatrix = deleteWhite(bitMatrix);
+ MatrixToImageWriter.writeToPath(bitMatrix, suffix, imageFile.toPath(), config);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @param matrix 二维码矩阵相关
+ * @param format 二维码图片格式
+ * @param file 二维码图片文件
+ * @param logoPath logo路径
+ * @throws IOException
+ */
+ public static void writeToFile(BitMatrix matrix, String format, File file, String logoPath) throws IOException {
+ BufferedImage image = toBufferedImage(matrix);
+ Graphics2D gs = image.createGraphics();
+
+ int ratioWidth = image.getWidth() * 2 / 10;
+ int ratioHeight = image.getHeight() * 2 / 10;
+ // 载入logo
+ Image img = ImageIO.read(new File(logoPath));
+ int logoWidth = img.getWidth(null) > ratioWidth ? ratioWidth : img.getWidth(null);
+ int logoHeight = img.getHeight(null) > ratioHeight ? ratioHeight : img.getHeight(null);
+
+ int x = (image.getWidth() - logoWidth) / 2;
+ int y = (image.getHeight() - logoHeight) / 2;
+
+ gs.drawImage(img, x, y, logoWidth, logoHeight, null);
+ gs.setColor(Color.black);
+ gs.setBackground(Color.WHITE);
+ gs.dispose();
+ img.flush();
+ if (!ImageIO.write(image, format, file)) {
+ throw new IOException("Could not write an image of format " + format + " to " + file);
+ }
+ }
+
+ /**
+ * 压缩目录中的图片到ZIP文件
+ *
+ * @param sourceDir 源目录
+ * @param zipFilePath ZIP文件路径
+ * @throws IOException 如果压缩过程失败
+ */
+ public static void zipImages(Path sourceDir, Path zipFilePath) throws IOException {
+ try (FileOutputStream fos = new FileOutputStream(zipFilePath.toFile());
+ ZipArchiveOutputStream zos = new ZipArchiveOutputStream(fos)) {
+
+ Files.walk(sourceDir)
+ .filter(Files::isRegularFile)
+ .forEach(file -> {
+ try {
+ ZipArchiveEntry zipEntry = new ZipArchiveEntry(file.toFile(), sourceDir.relativize(file).toString());
+ zos.putArchiveEntry(zipEntry);
+ Files.copy(file, zos);
+ zos.closeArchiveEntry();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+ }
+
+ public static BufferedImage toBufferedImage(BitMatrix matrix) {
+ int width = matrix.getWidth();
+ int height = matrix.getHeight();
+ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ image.setRGB(x, y, matrix.get(x, y) ? onColor : offColor);
+ }
+ }
+ return image;
+ }
+}
+
diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/controller/PurchaseBindController.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/controller/PurchaseBindController.java
index eac40258..bb12972f 100644
--- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/controller/PurchaseBindController.java
+++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/controller/PurchaseBindController.java
@@ -13,6 +13,7 @@ import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@@ -76,4 +77,15 @@ public class PurchaseBindController extends BaseController {
public AjaxResult getInfo(PurchaseDto dto) {
return purchaseBindService.selectPurchaseCheckInfoById(dto);
}
+
+ /**
+ * 二维码生成下载一体操作
+ * @param response
+ * @param purchaseDto
+ */
+ @PostMapping(value = "/downloadQrCode")
+ @RequiresPermissions("purchase:bpmPurchaseInfo:query")
+ public void downloadQrCode(HttpServletResponse response, PurchaseDto purchaseDto) {
+ purchaseBindService.downloadQrCode(response, purchaseDto);
+ }
}
diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/dto/PurchaseDto.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/dto/PurchaseDto.java
index c7328e57..b0dc37cc 100644
--- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/dto/PurchaseDto.java
+++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/dto/PurchaseDto.java
@@ -1,9 +1,12 @@
package com.bonus.material.purchase.dto;
import com.bonus.common.core.web.domain.BaseEntity;
+import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
import lombok.Data;
+import java.util.Date;
import java.util.List;
/**
@@ -11,7 +14,8 @@ import java.util.List;
* @create 2024/10/21 13:58
*/
@Data
-public class PurchaseDto extends BaseEntity {
+@Builder
+public class PurchaseDto {
@ApiModelProperty(value = "id")
private String taskId;
@@ -63,4 +67,12 @@ public class PurchaseDto extends BaseEntity {
@ApiModelProperty(value = "提交绑定数据集合")
private List dtoList;
+
+ private String createBy;
+
+ private Date createTime;
+
+ private String updateBy;
+
+ private Date updateTime;
}
diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/mapper/PurchaseBindMapper.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/mapper/PurchaseBindMapper.java
index 036cc052..1b425465 100644
--- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/mapper/PurchaseBindMapper.java
+++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/mapper/PurchaseBindMapper.java
@@ -2,6 +2,7 @@ package com.bonus.material.purchase.mapper;
import com.bonus.material.purchase.dto.PurchaseDto;
import com.bonus.material.purchase.vo.PurchaseVo;
+import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -45,4 +46,31 @@ public interface PurchaseBindMapper {
* @return
*/
int add(PurchaseDto purchaseDto);
+
+ /**
+ * 查询二维码code
+ * @param genMonth
+ * @return
+ */
+ List select(String genMonth);
+
+ /**
+ * 查询状态
+ * @param purchaseDto
+ * @return
+ */
+ Integer selectStatus(PurchaseDto purchaseDto);
+
+ /**
+ * 更新状态
+ * @param id
+ * @param purchaseId
+ */
+ void updateStatus(@Param("id") String id, @Param("purchaseId") String purchaseId);
+
+ /**
+ * 二维码数据保存
+ * @param dto
+ */
+ void insert(PurchaseDto dto);
}
diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/IPurchaseBindService.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/IPurchaseBindService.java
index bbf32b58..a1886cce 100644
--- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/IPurchaseBindService.java
+++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/IPurchaseBindService.java
@@ -4,6 +4,7 @@ import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.material.purchase.dto.PurchaseDto;
import com.bonus.material.purchase.vo.PurchaseVo;
+import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@@ -39,4 +40,11 @@ public interface IPurchaseBindService {
* @return
*/
AjaxResult bind(PurchaseDto dto);
+
+ /**
+ * 下载二维码
+ * @param response
+ * @param purchaseDto
+ */
+ void downloadQrCode(HttpServletResponse response, PurchaseDto purchaseDto);
}
diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/impl/PurchaseBindServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/impl/PurchaseBindServiceImpl.java
index 3c640cfd..8cf66d18 100644
--- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/impl/PurchaseBindServiceImpl.java
+++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/service/impl/PurchaseBindServiceImpl.java
@@ -1,7 +1,11 @@
package com.bonus.material.purchase.service.impl;
+import com.bonus.common.biz.config.BackstageApplication;
+import com.bonus.common.biz.config.DateTimeHelper;
+import com.bonus.common.biz.config.QrCodeUtils;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.enums.HttpCodeEnum;
+import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
@@ -9,23 +13,36 @@ import com.bonus.material.purchase.dto.PurchaseDto;
import com.bonus.material.purchase.mapper.PurchaseBindMapper;
import com.bonus.material.purchase.service.IPurchaseBindService;
import com.bonus.material.purchase.vo.PurchaseVo;
+import com.bonus.system.api.RemoteUserService;
+import com.bonus.system.api.domain.SysUser;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.zxing.WriterException;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
-import java.util.Iterator;
-import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
/**
* @Author ma_sh
* @create 2024/10/21 18:42
*/
@Service
+@Slf4j
public class PurchaseBindServiceImpl implements IPurchaseBindService {
@Resource
private PurchaseBindMapper purchaseBindMapper;
+ @Resource
+ private RemoteUserService remoteUserService;
+
/**
* 查询所有绑定信息
* @param dto
@@ -53,10 +70,35 @@ public class PurchaseBindServiceImpl implements IPurchaseBindService {
iterator.remove();
}
}
+ extracted(list);
}
return list;
}
+ /**
+ * 远程调用方法抽取
+ * @param list
+ */
+ private void extracted(List list) {
+ for (PurchaseVo purchaseVo : list) {
+ try {
+ AjaxResult ajaxResult = remoteUserService.getInfo(Long.parseLong(purchaseVo.getCreateBy()), SecurityConstants.INNER);
+ if (ajaxResult.isSuccess()) {
+ // ajaxResult.get("data") 返回的是 LinkedHashMap
+ LinkedHashMap rawDataList = (LinkedHashMap) ajaxResult.get("data");
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ if (rawDataList != null) {
+ SysUser sysUser = objectMapper.convertValue(rawDataList, SysUser.class);
+ purchaseVo.setCreateBy(sysUser.getNickName() == null ? "" : sysUser.getNickName());
+ }
+ }
+ } catch (IllegalArgumentException e) {
+ log.error("远程调用查询失败:", e.getMessage());
+ }
+ }
+ }
+
/**
* 查询绑定信息
* @param dto
@@ -110,4 +152,176 @@ public class PurchaseBindServiceImpl implements IPurchaseBindService {
}
return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
}
+
+ /**
+ * 下载二维码
+ * @param response
+ * @param purchaseDto
+ */
+ @Override
+ public void downloadQrCode(HttpServletResponse response, PurchaseDto purchaseDto) {
+ //生成二维码
+ Set addedEntries = new HashSet<>();
+ if (purchaseDto.getPurchaseId() == null) {
+ throw new RuntimeException("内层id为空");
+ }
+ String genMonth = DateTimeHelper.getNowMonth();
+ List codeList = purchaseBindMapper.select(genMonth);
+ try (OutputStream os = response.getOutputStream();
+ ZipOutputStream zos = new ZipOutputStream(os)) {
+ Integer status = purchaseBindMapper.selectStatus(purchaseDto);
+ if (status == null) {
+ return;
+ }
+ //内层二维码下载
+ handlePurchaseId(addedEntries, purchaseDto, codeList, status, zos, genMonth);
+ zos.flush();
+ } catch (WriterException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 内层二维码下载
+ * @param purchaseDto
+ * @param codeList
+ * @param status
+ * @param zos
+ * @param genMonth
+ * @throws IOException
+ * @throws WriterException
+ */
+ private void handlePurchaseId(Set addedEntries, PurchaseDto purchaseDto, List codeList, Integer status, ZipOutputStream zos, String genMonth) throws IOException, WriterException {
+ if (status == 1) {
+ Select(addedEntries, purchaseDto, zos);
+ } else {
+ int num = getInitialNum(codeList);
+ List details = purchaseBindMapper.getDetails(purchaseDto);
+ if (CollectionUtils.isNotEmpty(details)) {
+ PurchaseVo detail = details.get(0);
+ purchaseDto.setTaskId(detail.getTaskId().toString());
+ getString(addedEntries, purchaseDto, genMonth, num, zos, detail.getMaterialModel(), detail.getMaterialName(), detail.getTypeId(), detail.getCheckNum());
+ extractedUpStatus(purchaseDto);
+ }
+ }
+ }
+
+ /**
+ * 方法抽取
+ * @param purchaseDto
+ * @param genMonth
+ * @param num
+ * @param zos
+ * @param materialModel
+ * @param materialName
+ * @param typeId
+ * @param checkNum
+ * @throws WriterException
+ * @throws IOException
+ */
+ private void getString(Set addedEntries, PurchaseDto purchaseDto, String genMonth, int num, ZipOutputStream zos, String materialModel, String materialName, Integer typeId, Integer checkNum) throws WriterException, IOException {
+ for (int j = 1; j <= checkNum; j++) {
+ genMonth = genMonth.replace("-", "");
+ String code = genMonth + "-" + String.format("%5d", num + j).replace(" ", "0");
+ // 新购管理-二维码打印-新增
+ String url = BackstageApplication.getUrl() + "backstage/machine/qrCodePage?qrcode=" + code;
+ // // 二维码的图片格式
+ String format = "jpg";
+ //设置路径
+ String mkdirsName = "images";
+ // linux 系统路径
+ String saveDirectory = "/data/imw/" + mkdirsName + "/";
+ String os = System.getProperty("os.name");
+ if (os.toLowerCase().startsWith("win")) {
+ //本地路径
+ saveDirectory = "D://files/" + mkdirsName + "/";
+ }
+ // 生成二维码
+ File files = new File(saveDirectory);
+ if (!files.exists()) {
+ files.mkdirs();
+ }
+ QrCodeUtils.generateQRImage(url, saveDirectory, code + ".jpg", format);
+ String qrUrl = saveDirectory + code + ".jpg";
+ PurchaseDto dto = PurchaseDto.builder().taskId(purchaseDto.getTaskId()).typeId(typeId).qrCode(code).qrUrl(qrUrl).createBy(SecurityUtils.getUserId().toString()).build();
+ purchaseBindMapper.insert(dto);
+ extracted( addedEntries, zos, materialModel, materialName, code, qrUrl);
+ }
+ }
+
+ /**
+ * 修改任务表方法抽取
+ * @param purchaseDto
+ */
+ private void extractedUpStatus(PurchaseDto purchaseDto) {
+ //修改任务表的是否下载状态
+ purchaseBindMapper.updateStatus(purchaseDto.getTaskId(), purchaseDto.getPurchaseId());
+ }
+
+ /**
+ * 获取初始化num
+ * @param codeList
+ * @return
+ */
+ private int getInitialNum(List codeList) {
+ if (com.alibaba.nacos.common.utils.CollectionUtils.isNotEmpty(codeList)) {
+ PurchaseVo purchaseVo = codeList.get(0);
+ return Integer.parseInt(purchaseVo.getQrCode().split("-")[1]);
+ }
+ return 0;
+ }
+
+ /**
+ * 查询方法抽取
+ * @param purchaseDto
+ * @param zos
+ * @throws IOException
+ */
+ private void Select(Set addedEntries, PurchaseDto purchaseDto, ZipOutputStream zos) throws IOException {
+ List list = purchaseBindMapper.selectPurchaseCheckInfoById(purchaseDto);
+ if (com.alibaba.nacos.common.utils.CollectionUtils.isNotEmpty(list)) {
+ for (PurchaseVo purchaseVo : list) {
+ String materialModel = purchaseVo.getMaterialModel();
+ String materialName = purchaseVo.getMaterialName();
+ String path = purchaseVo.getQrUrl();
+ String qrCode = purchaseVo.getQrCode();
+ path = path.replace("filePath", "/data/imw");
+ extracted(addedEntries, zos, materialModel, materialName, qrCode, path);
+ }
+ }
+ }
+
+ /**
+ * 二维码下载方法抽取
+ * @param zos
+ * @param materialModel
+ * @param materialName
+ * @param code
+ * @param path
+ * @throws IOException
+ */
+ private void extracted(Set addedEntries, ZipOutputStream zos, String materialModel, String materialName, String code, String path) throws IOException {
+ // 判断路径是否存在
+ File imageFile = new File(path);
+ if (!imageFile.exists()) {
+ return;
+ }
+ String entryName = "[" + materialModel + "-" + materialName + "]" + code + ".jpg";
+ if (addedEntries.contains(entryName)) {
+ System.out.println("Duplicate entry skipped: " + entryName);
+ return;
+ }
+ addedEntries.add(entryName);
+
+ zos.setLevel(0);
+ zos.putNextEntry(new ZipEntry(entryName));
+ try (InputStream fis = new FileInputStream(imageFile)) {
+ byte[] buffer = new byte[1024];
+ int r;
+ while ((r = fis.read(buffer)) != -1) {
+ zos.write(buffer, 0, r);
+ }
+ }
+ zos.closeEntry();
+ }
}
diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/vo/PurchaseVo.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/vo/PurchaseVo.java
index 99d1e42d..76bd58e0 100644
--- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/vo/PurchaseVo.java
+++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/purchase/vo/PurchaseVo.java
@@ -102,6 +102,9 @@ public class PurchaseVo {
@ApiModelProperty(value = "出厂编号")
private String outFacCode;
- @ApiModelProperty(value = "二维码")
+ @ApiModelProperty(value = "二维码code")
private String qrCode;
+
+ @ApiModelProperty(value = "二维码路径")
+ private String qrUrl;
}
diff --git a/bonus-modules/bonus-material/src/main/resources/mapper/material/purchase/PurchaseBindMapper.xml b/bonus-modules/bonus-material/src/main/resources/mapper/material/purchase/PurchaseBindMapper.xml
index 490968c2..ba191d87 100644
--- a/bonus-modules/bonus-material/src/main/resources/mapper/material/purchase/PurchaseBindMapper.xml
+++ b/bonus-modules/bonus-material/src/main/resources/mapper/material/purchase/PurchaseBindMapper.xml
@@ -44,6 +44,48 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+
+ INSERT INTO purchase_macode_info
+
+
+ qr_code,
+
+
+ type_id,
+
+
+ qr_url,
+
+
+ task_id,
+
+
+ create_by,
+
+ create_time,
+ del_flag
+
+
+
+ #{qrCode},
+
+
+ #{typeId},
+
+
+ #{qrUrl},
+
+
+ #{id},
+
+
+ #{createBy},
+
+ NOW(),
+ 0
+
+
+
UPDATE purchase_check_details
SET input_num = #{purchaseNum}
@@ -65,6 +107,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
type_id = #{typeId}
+
+ UPDATE purchase_check_details
+ SET is_download = '1'
+ WHERE del_flag = '0'
+
+ and task_id = #{id}
+
+
+ and id = #{purchaseId}
+
+
+