正在显示
16 个修改的文件
包含
355 行增加
和
25 行删除
| @@ -2,10 +2,12 @@ package com.ruoyi.quartz.task; | @@ -2,10 +2,12 @@ package com.ruoyi.quartz.task; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.http.HttpUtil; | 3 | import cn.hutool.http.HttpUtil; |
| 4 | import com.alibaba.fastjson.JSONObject; | 4 | import com.alibaba.fastjson.JSONObject; |
| 5 | +import com.google.common.io.Resources; | ||
| 5 | import com.ruoyi.common.constant.Constants; | 6 | import com.ruoyi.common.constant.Constants; |
| 6 | import com.ruoyi.common.tool.SysLogininforType; | 7 | import com.ruoyi.common.tool.SysLogininforType; |
| 7 | import com.ruoyi.common.utils.DateUtils; | 8 | import com.ruoyi.common.utils.DateUtils; |
| 8 | import com.ruoyi.common.utils.MessageUtils; | 9 | import com.ruoyi.common.utils.MessageUtils; |
| 10 | +import com.ruoyi.quartz.task.aquatic.AquaticPublicOpinionBase; | ||
| 9 | import com.ruoyi.quartz.task.aquatic.AquaticPublicOpinionService; | 11 | import com.ruoyi.quartz.task.aquatic.AquaticPublicOpinionService; |
| 10 | import com.zhonglai.luhui.dao.service.PublicService; | 12 | import com.zhonglai.luhui.dao.service.PublicService; |
| 11 | import com.zhonglai.luhui.sys.manager.AsyncManager; | 13 | import com.zhonglai.luhui.sys.manager.AsyncManager; |
| @@ -15,9 +17,17 @@ import org.slf4j.LoggerFactory; | @@ -15,9 +17,17 @@ import org.slf4j.LoggerFactory; | ||
| 15 | import org.springframework.beans.factory.annotation.Autowired; | 17 | import org.springframework.beans.factory.annotation.Autowired; |
| 16 | import org.springframework.stereotype.Component; | 18 | import org.springframework.stereotype.Component; |
| 17 | 19 | ||
| 20 | +import java.nio.file.Files; | ||
| 21 | +import java.nio.file.Path; | ||
| 22 | +import java.nio.file.Paths; | ||
| 23 | +import java.util.*; | ||
| 24 | + | ||
| 25 | +import javax.imageio.ImageIO; | ||
| 26 | +import java.awt.*; | ||
| 27 | +import java.awt.image.BufferedImage; | ||
| 28 | +import java.io.File; | ||
| 29 | +import java.io.IOException; | ||
| 18 | import java.util.List; | 30 | import java.util.List; |
| 19 | -import java.util.Map; | ||
| 20 | -import java.util.TimerTask; | ||
| 21 | 31 | ||
| 22 | /** | 32 | /** |
| 23 | * 水产舆情 | 33 | * 水产舆情 |
| @@ -31,7 +41,7 @@ public class AquaticPublicOpinionTask { | @@ -31,7 +41,7 @@ public class AquaticPublicOpinionTask { | ||
| 31 | protected PublicService publicService; | 41 | protected PublicService publicService; |
| 32 | public void run(String day) | 42 | public void run(String day) |
| 33 | { | 43 | { |
| 34 | - for (AquaticPublicOpinionService service : aquaticPublicOpinionServices) { | 44 | + for (AquaticPublicOpinionService service : aquaticPublicOpinionServices) { |
| 35 | AsyncManager.me().execute(new TimerTask() { | 45 | AsyncManager.me().execute(new TimerTask() { |
| 36 | @Override | 46 | @Override |
| 37 | public void run() { | 47 | public void run() { |
| @@ -53,6 +63,7 @@ public class AquaticPublicOpinionTask { | @@ -53,6 +63,7 @@ public class AquaticPublicOpinionTask { | ||
| 53 | 63 | ||
| 54 | if (null != lsit && lsit.size()!=0) | 64 | if (null != lsit && lsit.size()!=0) |
| 55 | { | 65 | { |
| 66 | + List<AbstractMap.SimpleEntry<String, String>> dataList = new ArrayList<>(); | ||
| 56 | for (Map<String,Object> map:lsit) | 67 | for (Map<String,Object> map:lsit) |
| 57 | { | 68 | { |
| 58 | StringBuffer content = new StringBuffer(); | 69 | StringBuffer content = new StringBuffer(); |
| @@ -71,8 +82,9 @@ public class AquaticPublicOpinionTask { | @@ -71,8 +82,9 @@ public class AquaticPublicOpinionTask { | ||
| 71 | text.put("mentioned_mobile_list",new String[]{"@all"}); | 82 | text.put("mentioned_mobile_list",new String[]{"@all"}); |
| 72 | jsonObject.put("text",text); | 83 | jsonObject.put("text",text); |
| 73 | HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=6d6b4790-d20f-4692-bc4a-e8ceb1e8cfda",jsonObject.toJSONString()); | 84 | HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=6d6b4790-d20f-4692-bc4a-e8ceb1e8cfda",jsonObject.toJSONString()); |
| 74 | - | ||
| 75 | } | 85 | } |
| 86 | + | ||
| 87 | + | ||
| 76 | } | 88 | } |
| 77 | } | 89 | } |
| 78 | } | 90 | } |
| @@ -23,11 +23,13 @@ public abstract class AquaticPublicOpinionBase implements AquaticPublicOpinionS | @@ -23,11 +23,13 @@ public abstract class AquaticPublicOpinionBase implements AquaticPublicOpinionS | ||
| 23 | protected final Logger logger = LoggerFactory.getLogger(this.getClass()); | 23 | protected final Logger logger = LoggerFactory.getLogger(this.getClass()); |
| 24 | @Autowired | 24 | @Autowired |
| 25 | protected PublicService publicService; | 25 | protected PublicService publicService; |
| 26 | + | ||
| 27 | + public static final String saveFilePath = "uploadPath/aquaticPublicOpinion/"; | ||
| 26 | public void updateSaveInfo(String text,Integer id) | 28 | public void updateSaveInfo(String text,Integer id) |
| 27 | { | 29 | { |
| 28 | if(StringUtils.isNotEmpty(text)) | 30 | if(StringUtils.isNotEmpty(text)) |
| 29 | { | 31 | { |
| 30 | - Path path = Paths.get("uploadPath/aquaticPublicOpinion/"+id+".txt"); | 32 | + Path path = Paths.get(saveFilePath+id+".txt"); |
| 31 | String filepath = saveFile(text, path); | 33 | String filepath = saveFile(text, path); |
| 32 | if(StringUtils.isNotEmpty(filepath)) | 34 | if(StringUtils.isNotEmpty(filepath)) |
| 33 | { | 35 | { |
| @@ -69,10 +69,10 @@ public class WwwCafsAcCn extends AquaticPublicOpinionBase{ | @@ -69,10 +69,10 @@ public class WwwCafsAcCn extends AquaticPublicOpinionBase{ | ||
| 69 | StringBuilder text = new StringBuilder(); | 69 | StringBuilder text = new StringBuilder(); |
| 70 | 70 | ||
| 71 | // 遍历段落,保留换行 | 71 | // 遍历段落,保留换行 |
| 72 | - for (Element p : content.select("p")) { | 72 | + for (Element p : content.children()) { |
| 73 | String line = p.text().trim(); | 73 | String line = p.text().trim(); |
| 74 | if (!line.isEmpty()) { | 74 | if (!line.isEmpty()) { |
| 75 | - text.append(line).append("\n\n"); | 75 | + text.append(line).append("\n"); |
| 76 | } | 76 | } |
| 77 | } | 77 | } |
| 78 | 78 |
| @@ -77,10 +77,10 @@ public class WwwChinaCfaOrg extends AquaticPublicOpinionBase{ | @@ -77,10 +77,10 @@ public class WwwChinaCfaOrg extends AquaticPublicOpinionBase{ | ||
| 77 | StringBuilder text = new StringBuilder(); | 77 | StringBuilder text = new StringBuilder(); |
| 78 | 78 | ||
| 79 | // 遍历段落,保留换行 | 79 | // 遍历段落,保留换行 |
| 80 | - for (Element p : content.select("p")) { | 80 | + for (Element p : content.children()) { |
| 81 | String line = p.text().trim(); | 81 | String line = p.text().trim(); |
| 82 | if (!line.isEmpty()) { | 82 | if (!line.isEmpty()) { |
| 83 | - text.append(line).append("\n\n"); | 83 | + text.append(line).append("\n"); |
| 84 | } | 84 | } |
| 85 | } | 85 | } |
| 86 | 86 |
| @@ -67,10 +67,10 @@ public class WwwCsfishOrgCn extends AquaticPublicOpinionBase{ | @@ -67,10 +67,10 @@ public class WwwCsfishOrgCn extends AquaticPublicOpinionBase{ | ||
| 67 | text.append( title); | 67 | text.append( title); |
| 68 | text.append("\n\n"); | 68 | text.append("\n\n"); |
| 69 | // 遍历段落,保留换行 | 69 | // 遍历段落,保留换行 |
| 70 | - for (Element p : content.select("p")) { | 70 | + for (Element p : content.children()) { |
| 71 | String line = p.text().trim(); | 71 | String line = p.text().trim(); |
| 72 | if (!line.isEmpty()) { | 72 | if (!line.isEmpty()) { |
| 73 | - text.append(line).append("\n\n"); | 73 | + text.append(line).append("\n"); |
| 74 | } | 74 | } |
| 75 | } | 75 | } |
| 76 | 76 |
| @@ -44,10 +44,10 @@ public class WwwMoaGovCn extends AquaticPublicOpinionBase{ | @@ -44,10 +44,10 @@ public class WwwMoaGovCn extends AquaticPublicOpinionBase{ | ||
| 44 | StringBuilder text = new StringBuilder(); | 44 | StringBuilder text = new StringBuilder(); |
| 45 | 45 | ||
| 46 | // 遍历段落,保留换行 | 46 | // 遍历段落,保留换行 |
| 47 | - for (Element p : content.select("p")) { | 47 | + for (Element p : content.children()) { |
| 48 | String line = p.text().trim(); | 48 | String line = p.text().trim(); |
| 49 | if (!line.isEmpty()) { | 49 | if (!line.isEmpty()) { |
| 50 | - text.append(line).append("\n\n"); | 50 | + text.append(line).append("\n"); |
| 51 | } | 51 | } |
| 52 | } | 52 | } |
| 53 | 53 |
| @@ -91,10 +91,10 @@ public class WwwNftecAgriCn extends AquaticPublicOpinionBase{ | @@ -91,10 +91,10 @@ public class WwwNftecAgriCn extends AquaticPublicOpinionBase{ | ||
| 91 | StringBuilder text = new StringBuilder(); | 91 | StringBuilder text = new StringBuilder(); |
| 92 | 92 | ||
| 93 | // 遍历段落,保留换行 | 93 | // 遍历段落,保留换行 |
| 94 | - for (Element p : content.select("p")) { | 94 | + for (Element p : content.children()) { |
| 95 | String line = p.text().trim(); | 95 | String line = p.text().trim(); |
| 96 | if (!line.isEmpty()) { | 96 | if (!line.isEmpty()) { |
| 97 | - text.append(line).append("\n\n"); | 97 | + text.append(line).append("\n"); |
| 98 | } | 98 | } |
| 99 | } | 99 | } |
| 100 | 100 | ||
| @@ -109,4 +109,10 @@ public class WwwNftecAgriCn extends AquaticPublicOpinionBase{ | @@ -109,4 +109,10 @@ public class WwwNftecAgriCn extends AquaticPublicOpinionBase{ | ||
| 109 | return null; | 109 | return null; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | + | ||
| 113 | + public static void main(String[] args) { | ||
| 114 | + WwwNftecAgriCn wwwNftecAgriCn = new WwwNftecAgriCn(); | ||
| 115 | + String str= wwwNftecAgriCn.getInfo("http://www.nftec.agri.cn/tzgg/202507/t20250711_8748522.htm"); | ||
| 116 | + System.out.println(str); | ||
| 117 | + } | ||
| 112 | } | 118 | } |
| 1 | +package com.ruoyi.quartz.util; | ||
| 2 | + | ||
| 3 | +import com.google.common.io.Resources; | ||
| 4 | +import com.ruoyi.common.utils.DateUtils; | ||
| 5 | + | ||
| 6 | +import javax.imageio.ImageIO; | ||
| 7 | +import java.awt.*; | ||
| 8 | +import java.awt.image.BufferedImage; | ||
| 9 | +import java.awt.AlphaComposite; | ||
| 10 | +import java.io.File; | ||
| 11 | +import java.io.IOException; | ||
| 12 | +import java.util.*; | ||
| 13 | +import java.util.List; | ||
| 14 | + | ||
| 15 | +public class MultiTextImageGenerator { | ||
| 16 | + | ||
| 17 | + private static final String savePath = "uploadPath/aquaticPublicOpinion/img/"; | ||
| 18 | + private static final String backgroundPath = "moban.png"; | ||
| 19 | + public static void main(String[] args) throws IOException { | ||
| 20 | + // 1. 示例数据 | ||
| 21 | + List<AbstractMap.SimpleEntry<String, String>> dataList = Arrays.asList( | ||
| 22 | + new AbstractMap.SimpleEntry<>("水质监测", "用于监测水体中溶氧、温度、pH 等参数,保障水产养殖环境。"), | ||
| 23 | + new AbstractMap.SimpleEntry<>("智能告警", "当监测数据异常时,可通过APP或短信方式自动告警提醒。"), | ||
| 24 | + new AbstractMap.SimpleEntry<>("移动便携", "设备小巧轻便,支持户外测量,数据实时同步上传。") | ||
| 25 | + ); | ||
| 26 | + // 2. 配置加载 | ||
| 27 | + generateImage(dataList,new StyleConfig()); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + public static String generateImage(List<AbstractMap.SimpleEntry<String, String>> dataList, StyleConfig style) throws IOException { | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + // 3. 背景图 | ||
| 34 | + BufferedImage image = ImageIO.read(new File(backgroundPath)); | ||
| 35 | + int width = image.getWidth(); | ||
| 36 | + int height = image.getHeight(); | ||
| 37 | + BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); | ||
| 38 | + Graphics2D g = newImage.createGraphics(); | ||
| 39 | + g.drawImage(image, 0, 0, null); | ||
| 40 | + | ||
| 41 | + // 抗锯齿 | ||
| 42 | + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); | ||
| 43 | + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); | ||
| 44 | + | ||
| 45 | + int maxTextWidth = width - 2 * style.startX; | ||
| 46 | + int currY = style.startY; | ||
| 47 | + | ||
| 48 | + // 4. 绘制每组内容块 | ||
| 49 | + for (int i = 0; i < dataList.size(); i++) { | ||
| 50 | + String title = (i + 1) + ". " + dataList.get(i).getKey(); | ||
| 51 | + String content = dataList.get(i).getValue(); | ||
| 52 | + | ||
| 53 | + g.setFont(style.titleFont); | ||
| 54 | + FontMetrics titleMetrics = g.getFontMetrics(); | ||
| 55 | + int titleHeight = titleMetrics.getHeight(); | ||
| 56 | + | ||
| 57 | + g.setFont(style.contentFont); | ||
| 58 | + FontMetrics contentMetrics = g.getFontMetrics(); | ||
| 59 | + List<String> lines = splitTextIntoLines(content, contentMetrics, maxTextWidth); | ||
| 60 | + int lineHeight = contentMetrics.getHeight() + style.lineSpacing; | ||
| 61 | + int contentHeight = lines.size() * lineHeight; | ||
| 62 | + int totalTextHeight = titleHeight + 10 + contentHeight; | ||
| 63 | + int blockHeight = totalTextHeight + 2 * style.padding; | ||
| 64 | + | ||
| 65 | + int blockWidth = maxTextWidth + 2 * style.padding; | ||
| 66 | + int blockX = style.startX - style.padding; | ||
| 67 | + int blockY = currY; | ||
| 68 | + | ||
| 69 | + if (style.showBackgroundBlock) | ||
| 70 | + { | ||
| 71 | + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, style.backgroundAlpha)); | ||
| 72 | + g.setColor(style.backgroundColor); | ||
| 73 | + g.fillRoundRect(blockX, blockY, blockWidth, blockHeight, style.cornerRadius, style.cornerRadius); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); | ||
| 77 | + g.setColor(style.textColor); | ||
| 78 | + | ||
| 79 | + int textStartY = blockY + style.padding + (blockHeight - 2 * style.padding - totalTextHeight) / 2; | ||
| 80 | + | ||
| 81 | + g.setFont(style.titleFont); | ||
| 82 | + int titleY = textStartY + titleHeight; | ||
| 83 | + g.drawString(title, style.startX, titleY); | ||
| 84 | + | ||
| 85 | + g.setFont(style.contentFont); | ||
| 86 | + int contentStartY = titleY + 10 + lineHeight; | ||
| 87 | + for (int j = 0; j < lines.size(); j++) { | ||
| 88 | + int y = contentStartY + j * lineHeight; | ||
| 89 | + g.drawString(lines.get(j), style.startX, y); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + currY = blockY + blockHeight + style.blockSpacing; | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + // 5. 添加文字水印 | ||
| 96 | + drawTextWatermark(g, width, height, style); | ||
| 97 | + | ||
| 98 | + // 6. 添加图片水印 | ||
| 99 | +// drawImageWatermark(g, width, height, style); | ||
| 100 | + | ||
| 101 | + g.dispose(); | ||
| 102 | + | ||
| 103 | + // 7. 保存输出 | ||
| 104 | + String saveFile = savePath + DateUtils.getDate()+ "_output.png"; | ||
| 105 | + ImageIO.write(newImage, "png", new File(saveFile)); | ||
| 106 | + return saveFile; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + // 文字自动换行 | ||
| 110 | + private static List<String> splitTextIntoLines(String text, FontMetrics metrics, int maxWidth) { | ||
| 111 | + List<String> lines = new ArrayList<>(); | ||
| 112 | + StringBuilder line = new StringBuilder(); | ||
| 113 | + for (char c : text.toCharArray()) { | ||
| 114 | + line.append(c); | ||
| 115 | + if (metrics.stringWidth(line.toString()) > maxWidth) { | ||
| 116 | + line.deleteCharAt(line.length() - 1); | ||
| 117 | + lines.add(line.toString()); | ||
| 118 | + line = new StringBuilder().append(c); | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + if (!line.toString().isEmpty()) { | ||
| 122 | + lines.add(line.toString()); | ||
| 123 | + } | ||
| 124 | + return lines; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + // 文字水印 | ||
| 128 | + private static void drawTextWatermark(Graphics2D g, int width, int height, StyleConfig style) { | ||
| 129 | + g.setFont(style.watermarkFont); | ||
| 130 | + g.setColor(style.watermarkColor); | ||
| 131 | + FontMetrics metrics = g.getFontMetrics(); | ||
| 132 | + int textWidth = metrics.stringWidth(style.watermarkText); | ||
| 133 | + int x = width - textWidth - style.watermarkTextMarginX; | ||
| 134 | + int y = height - style.watermarkTextMarginY; | ||
| 135 | + g.drawString(style.watermarkText, x, y); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + // 图片水印 | ||
| 139 | + private static void drawImageWatermark(Graphics2D g, int width, int height, StyleConfig style) { | ||
| 140 | + try { | ||
| 141 | + String watermarkImagePath = style.watermarkImagePath; | ||
| 142 | + File file = new File(watermarkImagePath); | ||
| 143 | + if (!file.exists()) { | ||
| 144 | + System.out.println("⚠️ 水印图片未找到:" + watermarkImagePath); | ||
| 145 | + return; | ||
| 146 | + } | ||
| 147 | + Image logo = ImageIO.read(file).getScaledInstance( | ||
| 148 | + style.watermarkImageWidth, | ||
| 149 | + style.watermarkImageHeight, | ||
| 150 | + Image.SCALE_SMOOTH | ||
| 151 | + ); | ||
| 152 | + int x = width - style.watermarkImageWidth - style.watermarkImageMarginX; | ||
| 153 | + int y = height - style.watermarkImageHeight - style.watermarkImageMarginY; | ||
| 154 | + g.drawImage(logo, x, y, null); | ||
| 155 | + } catch (IOException e) { | ||
| 156 | + System.err.println("❌ 加载图片水印失败:" + e.getMessage()); | ||
| 157 | + } | ||
| 158 | + } | ||
| 159 | +} | ||
| 160 | + |
| 1 | +package com.ruoyi.quartz.util; | ||
| 2 | + | ||
| 3 | +import java.awt.*; | ||
| 4 | +import java.io.File; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 样式配置类 | ||
| 8 | + */ | ||
| 9 | +public class StyleConfig { | ||
| 10 | + public StyleConfig() { | ||
| 11 | + try { | ||
| 12 | + Font baseFont = Font.createFont(Font.TRUETYPE_FONT, | ||
| 13 | + new File("NotoSansCJKsc-Black.otf")); | ||
| 14 | + | ||
| 15 | + titleFont = baseFont.deriveFont(Font.BOLD, 36f); | ||
| 16 | + contentFont = baseFont.deriveFont(Font.PLAIN, 28f); | ||
| 17 | + watermarkFont = baseFont.deriveFont(Font.PLAIN, 20f); | ||
| 18 | + | ||
| 19 | + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(baseFont); | ||
| 20 | + } catch (Exception e) { | ||
| 21 | + System.err.println("❌ 加载字体失败,使用默认字体:" + e.getMessage()); | ||
| 22 | + titleFont = new Font("Serif", Font.BOLD, 36); | ||
| 23 | + contentFont = new Font("Serif", Font.PLAIN, 28); | ||
| 24 | + } | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + // 文本样式配置 | ||
| 28 | + public Font titleFont = new Font("微软雅黑", Font.BOLD, 36); | ||
| 29 | +// 标题字体,微软雅黑,加粗,字号36 | ||
| 30 | + | ||
| 31 | + public Font contentFont = new Font("微软雅黑", Font.PLAIN, 28); | ||
| 32 | +// 正文字体,微软雅黑,常规,字号28 | ||
| 33 | + | ||
| 34 | + public Color textColor = Color.WHITE; | ||
| 35 | +// 文字颜色,默认为白色 | ||
| 36 | + | ||
| 37 | + // 是否显示遮罩背景块(默认开启) | ||
| 38 | + public boolean showBackgroundBlock = false; | ||
| 39 | + | ||
| 40 | + // 遮罩块样式(文字背景) | ||
| 41 | + public Color backgroundColor = new Color(0, 0, 0); | ||
| 42 | +// 遮罩背景颜色,默认黑色(RGB) | ||
| 43 | + | ||
| 44 | + public float backgroundAlpha = 0.4f; | ||
| 45 | +// 遮罩背景透明度(0.0f~1.0f,0是完全透明,1是不透明) | ||
| 46 | + | ||
| 47 | + public int cornerRadius = 20; | ||
| 48 | +// 遮罩背景圆角半径,单位像素 | ||
| 49 | + | ||
| 50 | + public int padding = 20; | ||
| 51 | +// 遮罩内部边距:文字距离遮罩边缘的内边距(上下左右均使用该值) | ||
| 52 | + | ||
| 53 | + public int blockSpacing = 0; | ||
| 54 | +// 每个标题+内容之间的垂直间距(块间隔),单位像素 | ||
| 55 | + | ||
| 56 | + public int startX = 97; | ||
| 57 | +// 文字区域的起始横坐标(左边距) | ||
| 58 | + | ||
| 59 | + public int startY = 245; | ||
| 60 | +// 第一段文字区域的起始纵坐标(上边距) | ||
| 61 | + | ||
| 62 | + public int lineSpacing = 5; | ||
| 63 | +// 内容段落之间的行间距(单位像素) | ||
| 64 | + | ||
| 65 | + // 文字水印配置 | ||
| 66 | + public String watermarkText = "@鱼儿乐科技"; | ||
| 67 | +// 添加的文字水印内容 | ||
| 68 | + | ||
| 69 | + public Font watermarkFont = new Font("微软雅黑", Font.PLAIN, 20); | ||
| 70 | +// 水印字体:微软雅黑,常规,字号20 | ||
| 71 | + | ||
| 72 | + public Color watermarkColor = new Color(255, 255, 255, 180); | ||
| 73 | +// 水印颜色:白色,透明度约70%(255=不透明,180≈70%透明) | ||
| 74 | + | ||
| 75 | + public int watermarkTextMarginX = 567; | ||
| 76 | +// 文字水印的横坐标偏移量,单位像素(从左上角或右下角偏移) | ||
| 77 | + | ||
| 78 | + public int watermarkTextMarginY = 1236; | ||
| 79 | +// 文字水印的纵坐标偏移量,单位像素(从左上角或右下角偏移) | ||
| 80 | + | ||
| 81 | + // 图片水印配置 | ||
| 82 | + public String watermarkImagePath = "logo.jpg"; | ||
| 83 | +// 图片水印的文件路径,支持 PNG/JPG 格式 | ||
| 84 | + | ||
| 85 | + public int watermarkImageWidth = 100; | ||
| 86 | +// 图片水印缩放后的宽度(单位像素) | ||
| 87 | + | ||
| 88 | + public int watermarkImageHeight = 100; | ||
| 89 | +// 图片水印缩放后的高度(单位像素) | ||
| 90 | + | ||
| 91 | + public int watermarkImageMarginX = 20; | ||
| 92 | +// 图片水印的横向偏移量(从右下角向内缩进的距离) | ||
| 93 | + | ||
| 94 | + public int watermarkImageMarginY = 20; | ||
| 95 | +// 图片水印的纵向偏移量(从右下角向内缩进的距离) | ||
| 96 | + | ||
| 97 | +} | ||
| 98 | + |
不能预览此文件类型
20.5 KB
812.2 KB
| 1 | package com.zhonglai.luhui.admin.controller.monitor; | 1 | package com.zhonglai.luhui.admin.controller.monitor; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | import cn.hutool.http.HttpUtil; | 3 | import cn.hutool.http.HttpUtil; |
| 5 | import com.alibaba.fastjson.JSONObject; | 4 | import com.alibaba.fastjson.JSONObject; |
| 6 | -import com.google.gson.JsonArray; | ||
| 7 | import com.google.gson.JsonObject; | 5 | import com.google.gson.JsonObject; |
| 8 | import com.ruoyi.common.core.domain.AjaxResult; | 6 | import com.ruoyi.common.core.domain.AjaxResult; |
| 9 | import com.ruoyi.common.core.page.TableDataInfo; | 7 | import com.ruoyi.common.core.page.TableDataInfo; |
| @@ -12,15 +10,17 @@ import com.ruoyi.common.utils.GsonConstructor; | @@ -12,15 +10,17 @@ import com.ruoyi.common.utils.GsonConstructor; | ||
| 12 | import com.ruoyi.common.utils.ServletUtils; | 10 | import com.ruoyi.common.utils.ServletUtils; |
| 13 | import com.ruoyi.common.utils.ip.IpUtils; | 11 | import com.ruoyi.common.utils.ip.IpUtils; |
| 14 | import com.ruoyi.framework.web.domain.Server; | 12 | import com.ruoyi.framework.web.domain.Server; |
| 13 | +import com.ruoyi.quartz.util.MultiTextImageGenerator; | ||
| 14 | +import com.ruoyi.quartz.util.StyleConfig; | ||
| 15 | import com.ruoyi.system.domain.sys.SysMonitorApplication; | 15 | import com.ruoyi.system.domain.sys.SysMonitorApplication; |
| 16 | import com.ruoyi.system.domain.sys.SysMonitorApplicationLog; | 16 | import com.ruoyi.system.domain.sys.SysMonitorApplicationLog; |
| 17 | import com.ruoyi.system.domain.sys.SysMonitorServer; | 17 | import com.ruoyi.system.domain.sys.SysMonitorServer; |
| 18 | import com.ruoyi.system.domain.sys.SysMonitorServerLog; | 18 | import com.ruoyi.system.domain.sys.SysMonitorServerLog; |
| 19 | import com.zhonglai.luhui.action.BaseController; | 19 | import com.zhonglai.luhui.action.BaseController; |
| 20 | +import com.zhonglai.luhui.admin.dto.GenerateAquaticPublicOpinionPosterDto; | ||
| 20 | import com.zhonglai.luhui.admin.dto.MonitorServerUploadApplicationDto; | 21 | import com.zhonglai.luhui.admin.dto.MonitorServerUploadApplicationDto; |
| 21 | import com.zhonglai.luhui.admin.dto.MonitorServerUploadDto; | 22 | import com.zhonglai.luhui.admin.dto.MonitorServerUploadDto; |
| 22 | import com.zhonglai.luhui.admin.qywx.AesException; | 23 | import com.zhonglai.luhui.admin.qywx.AesException; |
| 23 | -import com.zhonglai.luhui.admin.qywx.QyWxApplication; | ||
| 24 | import com.zhonglai.luhui.admin.qywx.WXBizMsgCrypt; | 24 | import com.zhonglai.luhui.admin.qywx.WXBizMsgCrypt; |
| 25 | import com.zhonglai.luhui.admin.service.SendSysMonitorServerMessge; | 25 | import com.zhonglai.luhui.admin.service.SendSysMonitorServerMessge; |
| 26 | import com.zhonglai.luhui.dao.service.PublicService; | 26 | import com.zhonglai.luhui.dao.service.PublicService; |
| @@ -28,7 +28,6 @@ import com.zhonglai.luhui.device.analysis.comm.util.StringUtils; | @@ -28,7 +28,6 @@ import com.zhonglai.luhui.device.analysis.comm.util.StringUtils; | ||
| 28 | import io.swagger.annotations.Api; | 28 | import io.swagger.annotations.Api; |
| 29 | import io.swagger.annotations.ApiOperation; | 29 | import io.swagger.annotations.ApiOperation; |
| 30 | import org.springframework.beans.factory.annotation.Autowired; | 30 | import org.springframework.beans.factory.annotation.Autowired; |
| 31 | -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
| 32 | import org.springframework.security.access.prepost.PreAuthorize; | 31 | import org.springframework.security.access.prepost.PreAuthorize; |
| 33 | import org.springframework.transaction.annotation.Transactional; | 32 | import org.springframework.transaction.annotation.Transactional; |
| 34 | import org.springframework.util.StreamUtils; | 33 | import org.springframework.util.StreamUtils; |
| @@ -44,11 +43,13 @@ import javax.servlet.http.HttpServletRequest; | @@ -44,11 +43,13 @@ import javax.servlet.http.HttpServletRequest; | ||
| 44 | import javax.xml.parsers.DocumentBuilder; | 43 | import javax.xml.parsers.DocumentBuilder; |
| 45 | import javax.xml.parsers.DocumentBuilderFactory; | 44 | import javax.xml.parsers.DocumentBuilderFactory; |
| 46 | import javax.xml.parsers.ParserConfigurationException; | 45 | import javax.xml.parsers.ParserConfigurationException; |
| 46 | +import java.io.File; | ||
| 47 | import java.io.IOException; | 47 | import java.io.IOException; |
| 48 | import java.io.StringReader; | 48 | import java.io.StringReader; |
| 49 | import java.util.*; | 49 | import java.util.*; |
| 50 | import java.util.concurrent.ScheduledExecutorService; | 50 | import java.util.concurrent.ScheduledExecutorService; |
| 51 | import java.util.concurrent.TimeUnit; | 51 | import java.util.concurrent.TimeUnit; |
| 52 | +import java.util.stream.Collectors; | ||
| 52 | 53 | ||
| 53 | 54 | ||
| 54 | /** | 55 | /** |
| @@ -176,12 +177,40 @@ public class ServerController extends BaseController | @@ -176,12 +177,40 @@ public class ServerController extends BaseController | ||
| 176 | 177 | ||
| 177 | @ApiOperation("获取当天水产新闻") | 178 | @ApiOperation("获取当天水产新闻") |
| 178 | @GetMapping("/getNowAquaticPublicOpinion") | 179 | @GetMapping("/getNowAquaticPublicOpinion") |
| 179 | - public AjaxResult getNowAquaticPublicOpinion() | 180 | + public AjaxResult getNowAquaticPublicOpinion(String day) |
| 180 | { | 181 | { |
| 181 | - List<Map<String,Object>> lsit = publicService.getObjectListBySQL("SELECT * FROM `fish_aquatic_public_opinion` WHERE release_time='"+DateUtils.getDate()+" 00:00:00'"); | 182 | + if(StringUtils.isEmpty(day)) |
| 183 | + { | ||
| 184 | + day = DateUtils.getDate(); | ||
| 185 | + } | ||
| 186 | + List<Map<String,Object>> lsit = publicService.getObjectListBySQL("SELECT * FROM `fish_aquatic_public_opinion` WHERE release_time='"+day+" 00:00:00'"); | ||
| 182 | return AjaxResult.success(lsit); | 187 | return AjaxResult.success(lsit); |
| 183 | } | 188 | } |
| 184 | 189 | ||
| 190 | + @ApiOperation("生成水产新闻海报") | ||
| 191 | + @PostMapping("/generateAquaticPublicOpinionPoster") | ||
| 192 | + public AjaxResult generateAquaticPublicOpinionPoster(@RequestBody List<GenerateAquaticPublicOpinionPosterDto> list) | ||
| 193 | + { | ||
| 194 | + if (null == list || list.size()==0) | ||
| 195 | + { | ||
| 196 | + return AjaxResult.error("参数不能为空"); | ||
| 197 | + } | ||
| 198 | + List<AbstractMap.SimpleEntry<String, String>> dataList = list.stream() | ||
| 199 | + .map(dto -> new AbstractMap.SimpleEntry<>(dto.getTitle(), dto.getContent())) | ||
| 200 | + .collect(Collectors.toList()); | ||
| 201 | + try { | ||
| 202 | + logger.info("转换数据:{}",dataList); | ||
| 203 | + String savePath = MultiTextImageGenerator.generateImage(dataList, new StyleConfig()); | ||
| 204 | + String imgurl = "https://lh.admin.yu2le.com/api/"+savePath.replace("uploadPath","profile"); | ||
| 205 | + return AjaxResult.success(imgurl); | ||
| 206 | + } catch (IOException e) { | ||
| 207 | + logger.info(new File("moban.png").getAbsolutePath()); | ||
| 208 | + logger.error("生成海报错误",e); | ||
| 209 | + return AjaxResult.error("生成海报错误"+e.getMessage()); | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + } | ||
| 213 | + | ||
| 185 | @ApiOperation("获取服务器应用列表") | 214 | @ApiOperation("获取服务器应用列表") |
| 186 | @GetMapping("/getServiceAoolicationList") | 215 | @GetMapping("/getServiceAoolicationList") |
| 187 | public Map<String,Object> getServiceAoolicationList() | 216 | public Map<String,Object> getServiceAoolicationList() |
| 1 | +package com.zhonglai.luhui.admin.dto; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 生成水产新闻海报对象 | ||
| 5 | + */ | ||
| 6 | +public class GenerateAquaticPublicOpinionPosterDto { | ||
| 7 | + private String title; | ||
| 8 | + private String content; | ||
| 9 | + | ||
| 10 | + public String getTitle() { | ||
| 11 | + return title; | ||
| 12 | + } | ||
| 13 | + | ||
| 14 | + public void setTitle(String title) { | ||
| 15 | + this.title = title; | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + public String getContent() { | ||
| 19 | + return content; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + public void setContent(String content) { | ||
| 23 | + this.content = content; | ||
| 24 | + } | ||
| 25 | +} |
| 1 | -# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 实例演示开关 demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) profile: E:/work/idea/Luhui/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 captchaType: math # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8080 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn com.zhonglai.luhui: debug # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 119.23.218.181 # 端口,默认为6379 port: 6379 # 数据库索引 database: 1 # 密码 password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-admin # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/tool/gen/generatorCodeFromDb,/data/**,/monitor/server/upload,/monitor/server/getSysMonitorServerList,/monitor/server/getSysMonitorServerLogList # NameServer地址 rocketmq: name-server: 8.129.224.117:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-mqtt-service-deviceCommand-test send-tags: 1 | ||
| 1 | +# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 实例演示开关 demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) profile: E:/work/idea/Luhui/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 captchaType: math # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8080 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn com.zhonglai.luhui: debug # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 119.23.218.181 # 端口,默认为6379 port: 6379 # 数据库索引 database: 1 # 密码 password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-admin # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/tool/gen/generatorCodeFromDb,/data/**,/monitor/server/upload,/monitor/server/getSysMonitorServerList,/monitor/server/getSysMonitorServerLogList,/monitor/server/getNowAquaticPublicOpinion # NameServer地址 rocketmq: name-server: 8.129.224.117:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-mqtt-service-deviceCommand-test send-tags: 1 |
| @@ -57,9 +57,7 @@ public class IotTerminalController extends BaseController | @@ -57,9 +57,7 @@ public class IotTerminalController extends BaseController | ||
| 57 | @GetMapping("/listByDeviceId/{deviceId}") | 57 | @GetMapping("/listByDeviceId/{deviceId}") |
| 58 | public AjaxResult listByDeviceId(@PathVariable String deviceId) | 58 | public AjaxResult listByDeviceId(@PathVariable String deviceId) |
| 59 | { | 59 | { |
| 60 | - IotTerminal iotTerminal = new IotTerminal(); | ||
| 61 | - iotTerminal.setDevice_id(deviceId); | ||
| 62 | - List<IotTerminal> list = iotTerminalService.selectIotTerminalListByUserId(iotTerminal); | 60 | + List<IotTerminal> list = iotTerminalService.selectNotUserIotTerminalListByImei(deviceId); |
| 63 | return AjaxResult.success(list); | 61 | return AjaxResult.success(list); |
| 64 | } | 62 | } |
| 65 | 63 |
-
请 注册 或 登录 后发表评论