From b2cff4c97aea0ecfd7b4b971a70f1f54b5896d97 Mon Sep 17 00:00:00 2001
From: sjm <2431685932@qq.com>
Date: Fri, 22 Dec 2023 17:05:37 +0800
Subject: [PATCH] update
---
pom.xml | 16 +
.../lovenav/controller/CommentController.java | 6 +
.../lovenav/controller/QRCodeController.java | 27 ++
.../com/lovenav/dao/CollectIconListDao.java | 19 +
src/main/java/com/lovenav/dao/CommentDao.java | 2 +
.../com/lovenav/entity/CollectIconList.java | 34 ++
.../com/lovenav/service/CommentService.java | 2 +
.../serviceImpl/CommentServiceImpl.java | 6 +
.../java/com/lovenav/utils/QRCodeUtil.java | 374 ++++++++++++++++++
.../resources/mybatis/CollectIconListDao.xml | 65 +++
src/main/resources/mybatis/CommentDao.xml | 7 +-
src/main/resources/static/logo/NAV.png | Bin 0 -> 12299 bytes
12 files changed, 557 insertions(+), 1 deletion(-)
create mode 100644 src/main/java/com/lovenav/controller/QRCodeController.java
create mode 100644 src/main/java/com/lovenav/dao/CollectIconListDao.java
create mode 100644 src/main/java/com/lovenav/entity/CollectIconList.java
create mode 100644 src/main/java/com/lovenav/utils/QRCodeUtil.java
create mode 100644 src/main/resources/mybatis/CollectIconListDao.xml
create mode 100644 src/main/resources/static/logo/NAV.png
diff --git a/pom.xml b/pom.xml
index 2905927..17aa7d9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,7 +95,23 @@
test
+
+
+ com.google.zxing
+ core
+ 3.3.0
+
+
+ com.google.zxing
+ javase
+ 3.3.0
+
+
+ org.apache.ws.commons.axiom
+ base64-utils
+ 1.4.0
+
diff --git a/src/main/java/com/lovenav/controller/CommentController.java b/src/main/java/com/lovenav/controller/CommentController.java
index b37c606..5675743 100644
--- a/src/main/java/com/lovenav/controller/CommentController.java
+++ b/src/main/java/com/lovenav/controller/CommentController.java
@@ -46,4 +46,10 @@ public class CommentController {
public String View_comment(){
return commentService.View_comment();
}
+
+// 显示回复
+@RequestMapping(method = RequestMethod.GET, value = "/view_reply")
+ public String View_reply(int id){
+ return commentService.View_Reply(id);
+ }
}
diff --git a/src/main/java/com/lovenav/controller/QRCodeController.java b/src/main/java/com/lovenav/controller/QRCodeController.java
new file mode 100644
index 0000000..5c4e0a7
--- /dev/null
+++ b/src/main/java/com/lovenav/controller/QRCodeController.java
@@ -0,0 +1,27 @@
+package com.lovenav.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.lovenav.utils.QRCodeUtil;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+
+public class QRCodeController {
+ private QRCodeUtil qrCodeUtil;
+@RequestMapping(method = RequestMethod.GET, value = "/qrc")
+ public String QRCode(String url){
+ String text = url;
+ String logoPath ="src/main/resources/static/logo/NAV.png";
+ String destPath = "src/main/resources/static/qr";
+ try {
+ String url2 = qrCodeUtil.encode(text, logoPath, destPath, true);
+ String base64 = qrCodeUtil.getBase64(url2);
+ return JSON.toJSONString(base64);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/java/com/lovenav/dao/CollectIconListDao.java b/src/main/java/com/lovenav/dao/CollectIconListDao.java
new file mode 100644
index 0000000..c9bc5ff
--- /dev/null
+++ b/src/main/java/com/lovenav/dao/CollectIconListDao.java
@@ -0,0 +1,19 @@
+package com.lovenav.dao;
+
+import com.lovenav.entity.CollectIconList;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface CollectIconListDao {
+ int deleteByPrimaryKey(Long id);
+
+ int insert(CollectIconList record);
+
+ int insertSelective(CollectIconList record);
+
+ CollectIconList selectByPrimaryKey(Long id);
+
+ int updateByPrimaryKeySelective(CollectIconList record);
+
+ int updateByPrimaryKey(CollectIconList record);
+}
\ No newline at end of file
diff --git a/src/main/java/com/lovenav/dao/CommentDao.java b/src/main/java/com/lovenav/dao/CommentDao.java
index f0fba2e..0c3cfe6 100644
--- a/src/main/java/com/lovenav/dao/CommentDao.java
+++ b/src/main/java/com/lovenav/dao/CommentDao.java
@@ -23,4 +23,6 @@ public interface CommentDao {
int updateByPrimaryKey(Comment record);
List selectByAllComment();
+
+ List selectByAllReply(int id);
}
\ No newline at end of file
diff --git a/src/main/java/com/lovenav/entity/CollectIconList.java b/src/main/java/com/lovenav/entity/CollectIconList.java
new file mode 100644
index 0000000..3d999a7
--- /dev/null
+++ b/src/main/java/com/lovenav/entity/CollectIconList.java
@@ -0,0 +1,34 @@
+package com.lovenav.entity;
+
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ * 图标表
+ * ln_collect_icon_list
+ */
+@Data
+public class CollectIconList implements Serializable {
+ private Long id;
+
+ /**
+ * 网址id
+ */
+ private String urlid;
+
+ /**
+ * 图片地址
+ */
+ private String iconUrl;
+
+ /**
+ * 二维码地址
+ */
+ private String qrUrl;
+ /**
+ * 状态
+ */
+ private int status;
+
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/com/lovenav/service/CommentService.java b/src/main/java/com/lovenav/service/CommentService.java
index e29e2c3..5d5d04b 100644
--- a/src/main/java/com/lovenav/service/CommentService.java
+++ b/src/main/java/com/lovenav/service/CommentService.java
@@ -15,4 +15,6 @@ public interface CommentService {
String Delete(int id);
// 显示评论
String View_comment();
+// 显示回复
+ String View_Reply(int id);
}
diff --git a/src/main/java/com/lovenav/service/serviceImpl/CommentServiceImpl.java b/src/main/java/com/lovenav/service/serviceImpl/CommentServiceImpl.java
index bd16ca4..9b07f99 100644
--- a/src/main/java/com/lovenav/service/serviceImpl/CommentServiceImpl.java
+++ b/src/main/java/com/lovenav/service/serviceImpl/CommentServiceImpl.java
@@ -72,4 +72,10 @@ public class CommentServiceImpl implements CommentService {
List list = commentDao.selectByAllComment();
return JSON.toJSONString(list);
}
+
+// 显示回复
+ public String View_Reply(int id){
+ List list = commentDao.selectByAllReply(id);
+ return JSON.toJSONString(list);
+ }
}
diff --git a/src/main/java/com/lovenav/utils/QRCodeUtil.java b/src/main/java/com/lovenav/utils/QRCodeUtil.java
new file mode 100644
index 0000000..05e9330
--- /dev/null
+++ b/src/main/java/com/lovenav/utils/QRCodeUtil.java
@@ -0,0 +1,374 @@
+package com.lovenav.utils;
+
+import com.google.zxing.*;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import org.apache.tomcat.util.codec.binary.Base64;
+
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Random;
+
+
+public class QRCodeUtil {
+ private static final String CHARSET = "utf-8";
+ private static final String FORMAT_NAME = "JPG";
+ // 二维码尺寸
+ private static final int QRCODE_SIZE = 300;
+ // LOGO宽度
+ private static final int WIDTH = 60;
+ // LOGO高度
+ private static final int HEIGHT = 60;
+
+ private static BufferedImage createImage(String content, String imgPath,
+ boolean needCompress) throws Exception {
+ Hashtable hints = new Hashtable();
+ hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+ hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
+ hints.put(EncodeHintType.MARGIN, 1);
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
+ BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
+ int width = bitMatrix.getWidth();
+ int height = bitMatrix.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, bitMatrix.get(x, y) ? 0xFF000000
+ : 0xFFFFFFFF);
+ }
+ }
+ if (imgPath == null || "".equals(imgPath)) {
+ return image;
+ }
+ // 插入图片
+ QRCodeUtil.insertImage(image, imgPath, needCompress);
+ return image;
+ }
+
+ /**
+ * 插入LOGO
+ *
+ * @param source
+ * 二维码图片
+ * @param imgPath
+ * LOGO图片地址
+ * @param needCompress
+ * 是否压缩
+ * @throws Exception
+ */
+ private static void insertImage(BufferedImage source, String imgPath,
+ boolean needCompress) throws Exception {
+ File file = new File(imgPath);
+ if (!file.exists()) {
+ System.err.println(""+imgPath+" 该文件不存在!");
+ return;
+ }
+ Image src = ImageIO.read(new File(imgPath));
+ int width = src.getWidth(null);
+ int height = src.getHeight(null);
+ if (needCompress) { // 压缩LOGO
+ if (width > WIDTH) {
+ width = WIDTH;
+ }
+ if (height > HEIGHT) {
+ height = HEIGHT;
+ }
+ Image image = src.getScaledInstance(width, height,
+ Image.SCALE_SMOOTH);
+ BufferedImage tag = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ Graphics g = tag.getGraphics();
+ g.drawImage(image, 0, 0, null); // 绘制缩小后的图
+ g.dispose();
+ src = image;
+ }
+ // 插入LOGO
+ Graphics2D graph = source.createGraphics();
+ int x = (QRCODE_SIZE - width) / 2;
+ int y = (QRCODE_SIZE - height) / 2;
+ graph.drawImage(src, x, y, width, height, null);
+ Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
+ graph.setStroke(new BasicStroke(3f));
+ graph.draw(shape);
+ graph.dispose();
+ }
+
+ /**
+ * 生成二维码(内嵌LOGO)
+ *
+ * @param content
+ * 内容
+ * @param imgPath
+ * LOGO地址
+ * @param destPath
+ * 存放目录
+ * @param needCompress
+ * 是否压缩LOGO
+ * @throws Exception
+ */
+ public static String encode(String content, String imgPath, String destPath,
+ boolean needCompress) throws Exception {
+ BufferedImage image = QRCodeUtil.createImage(content, imgPath,
+ needCompress);
+ mkdirs(destPath);
+ String file = new Random().nextInt(99999999)+".jpg";
+ ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
+ return destPath+"/"+file;
+ }
+
+ /**
+ * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
+ * @param destPath 存放目录
+ */
+ public static void mkdirs(String destPath) {
+ File file =new File(destPath);
+ //当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
+ if (!file.exists() && !file.isDirectory()) {
+ file.mkdirs();
+ }
+ }
+
+ /**
+ * 生成二维码(内嵌LOGO)
+ *
+ * @param content
+ * 内容
+ * @param imgPath
+ * LOGO地址
+ * @param destPath
+ * 存储地址
+ * @throws Exception
+ */
+ public static void encode(String content, String imgPath, String destPath)
+ throws Exception {
+ QRCodeUtil.encode(content, imgPath, destPath, false);
+ }
+
+ /**
+ * 生成二维码
+ *
+ * @param content
+ * 内容
+ * @param destPath
+ * 存储地址
+ * @param needCompress
+ * 是否压缩LOGO
+ * @throws Exception
+ */
+ public static void encode(String content, String destPath,
+ boolean needCompress) throws Exception {
+ QRCodeUtil.encode(content, null, destPath, needCompress);
+ }
+
+ /**
+ * 生成二维码
+ *
+ * @param content
+ * 内容
+ * @param destPath
+ * 存储地址
+ * @throws Exception
+ */
+ public static void encode(String content, String destPath) throws Exception {
+ QRCodeUtil.encode(content, null, destPath, false);
+ }
+
+ /**
+ * 生成二维码(内嵌LOGO)
+ *
+ * @param content
+ * 内容
+ * @param imgPath
+ * LOGO地址
+ * @param output
+ * 输出流
+ * @param needCompress
+ * 是否压缩LOGO
+ * @throws Exception
+ */
+ public static void encode(String content, String imgPath,
+ OutputStream output, boolean needCompress) throws Exception {
+ BufferedImage image = QRCodeUtil.createImage(content, imgPath,
+ needCompress);
+ ImageIO.write(image, FORMAT_NAME, output);
+ }
+
+ /**
+ * 生成二维码
+ *
+ * @param content
+ * 内容
+ * @param output
+ * 输出流
+ * @throws Exception
+ */
+ public static void encode(String content, OutputStream output)
+ throws Exception {
+ QRCodeUtil.encode(content, null, output, false);
+ }
+
+ /**
+ * 解析二维码
+ *
+ * @param file
+ * 二维码图片
+ * @return
+ * @throws Exception
+ */
+ public static String decode(File file) throws Exception {
+ BufferedImage image;
+ image = ImageIO.read(file);
+ if (image == null) {
+ return null;
+ }
+ BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(
+ image);
+ BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+ Result result;
+ Hashtable hints = new Hashtable();
+ hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
+ result = new MultiFormatReader().decode(bitmap, hints);
+ String resultStr = result.getText();
+ return resultStr;
+ }
+
+ /**
+ * 解析二维码
+ *
+ * @param path
+ * 二维码图片地址
+ * @return
+ * @throws Exception
+ */
+ public static String decode(String path) throws Exception {
+ return QRCodeUtil.decode(new File(path));
+ }
+
+ /**
+ *
+ * @param content
+ * @param imgPath
+ * @param destPath
+ * @param localUrl 当前环境的域名或者ip地址
+ * @param needCompress
+ * @return
+ * @throws Exception
+ */
+ public static String encode(String content, String imgPath, String destPath,String localUrl,
+ boolean needCompress) throws Exception {
+ BufferedImage image = QRCodeUtil.createImage(content, imgPath,
+ needCompress);
+ mkdirs(destPath);
+ String file = new Random().nextInt(99999999)+".jpg";
+ ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
+ return localUrl+file;
+ }
+
+ public static String encodeDZ(String content, String imgPath, String destPath,String localUrl,int length,int width,
+ boolean needCompress) throws Exception {
+ BufferedImage image = QRCodeUtil.createImageDZ(content, imgPath,length,width,
+ needCompress);
+ mkdirs(destPath);
+ String file = new Random().nextInt(99999999)+".jpg";
+ ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
+ return localUrl+file;
+ }
+
+ private static BufferedImage createImageDZ(String content, String imgPath,int newlength,int newWidth,
+ boolean needCompress) throws Exception {
+ Hashtable hints = new Hashtable();
+ hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+ hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
+ hints.put(EncodeHintType.MARGIN, 1);
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
+ BarcodeFormat.QR_CODE, newlength, newWidth, hints);
+ int width = bitMatrix.getWidth();
+ int height = bitMatrix.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, bitMatrix.get(x, y) ? 0xFF000000
+ : 0xFFFFFFFF);
+ }
+ }
+ if (imgPath == null || "".equals(imgPath)) {
+ return image;
+ }
+ // 插入图片
+ QRCodeUtil.insertImage(image, imgPath, needCompress);
+ return image;
+ }
+
+ public static void main(String[] args) throws Exception {
+ String text = "https://www.baidu.com"; //这里设置自定义网站url
+ String logoPath ="src/main/resources/static/logo/NAV.png";
+ String destPath = "src/main/resources/static/qr";
+ String url=QRCodeUtil.encode(text, logoPath, destPath, true);
+ System.out.println(url);
+
+ /* String file="D:\\11.jpg";
+ String info=QRCodeUtil.decode(file);
+ System.out.println(info);*/
+ }
+
+ /**
+ * 将图片url转换成base64流
+ * @param url
+ * @return
+ */
+ public String getBase64(String url){
+ MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
+ Map hints = new HashMap();
+ hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); //设置字符集编码类型
+ hints.put(EncodeHintType.MARGIN, 1); //设置白边
+ BitMatrix bitMatrix = null;
+ try {
+ bitMatrix = multiFormatWriter.encode(url, BarcodeFormat.QR_CODE, 300, 300,hints);
+ BufferedImage image = toBufferedImage(bitMatrix);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ //输出二维码图片流
+ try {
+ ImageIO.write(image, "jpg",outputStream);
+ String base = new Base64().encodeAsString(outputStream.toByteArray());
+// new Base64().encode(outputStream.toByteArray());
+ return base;
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } catch (WriterException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ return null;
+ }
+
+
+ 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) ? 0xFF000000 : 0xFFFFFFFF);//0xFF000000黑;0xFFFFFFFF白
+ }
+ }
+ return image;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/mybatis/CollectIconListDao.xml b/src/main/resources/mybatis/CollectIconListDao.xml
new file mode 100644
index 0000000..310dd14
--- /dev/null
+++ b/src/main/resources/mybatis/CollectIconListDao.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+ id, url_id, icon_url,qrUrl,status
+
+
+
+ delete from ln_collect_icon_list
+ where id = #{id,jdbcType=BIGINT}
+
+
+ insert into ln_collect_icon_list (url_md5, icon_url)
+ values (#{urlMd5,jdbcType=VARCHAR}, #{iconUrl,jdbcType=VARCHAR})
+
+
+ insert into ln_collect_icon_list
+
+
+ url_md5,
+
+
+ icon_url,
+
+
+
+
+ #{urlMd5,jdbcType=VARCHAR},
+
+
+ #{iconUrl,jdbcType=VARCHAR},
+
+
+
+
+ update ln_collect_icon_list
+
+
+ url_md5 = #{urlMd5,jdbcType=VARCHAR},
+
+
+ icon_url = #{iconUrl,jdbcType=VARCHAR},
+
+
+ where id = #{id,jdbcType=BIGINT}
+
+
+ update ln_collect_icon_list
+ set url_md5 = #{urlMd5,jdbcType=VARCHAR},
+ icon_url = #{iconUrl,jdbcType=VARCHAR}
+ where id = #{id,jdbcType=BIGINT}
+
+
\ No newline at end of file
diff --git a/src/main/resources/mybatis/CommentDao.xml b/src/main/resources/mybatis/CommentDao.xml
index 9c7cd13..e1a4fbf 100644
--- a/src/main/resources/mybatis/CommentDao.xml
+++ b/src/main/resources/mybatis/CommentDao.xml
@@ -153,5 +153,10 @@
where root_comment_id = 0 and comment_status = 0
-
+
\ No newline at end of file
diff --git a/src/main/resources/static/logo/NAV.png b/src/main/resources/static/logo/NAV.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9385116e2035704b1835b5a90af203f311a35ae
GIT binary patch
literal 12299
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
l{{RMZ>48xO;Y