|
|
|
package com.ruoyi.quartz.util;
|
|
|
|
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
import com.ruoyi.common.utils.DateUtils;
|
|
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import java.awt.*;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
public class FishPriceTableWithLogo {
|
|
|
|
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
|
String json = "[{\"价格\":\"35-36元/斤\",\"品种\":\"鱼仔鳜\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"统货\"},{\"价格\":\"32-33元/斤\",\"品种\":\"饲料鳜\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"统货\"},{\"价格\":\"4元/斤\",\"品种\":\"麦鲮鱼\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"统货\"},{\"价格\":\"36元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"江苏省\",\"时间\":\"2025-07-22\",\"规格\":\"统货\"},{\"价格\":null,\"品种\":\"鳜鱼\",\"地区\":\"安徽省\",\"时间\":\"2025-07-22\",\"规格\":\"统货\"},{\"价格\":\"34元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"湖南省\",\"时间\":\"2025-07-22\",\"规格\":\"统货\"},{\"价格\":\"极36元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"湖北省\",\"时间\":\"2025-07-22\",\"规格\":\"统货\"},{\"价格\":\"17元/斤\",\"品种\":\"加州鲈\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"8两起\"},{\"价格\":\"23元/斤\",\"品种\":\"加州鲈\",\"地区\":\"四川省成都市\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"19元/斤\",\"品种\":\"加州鲈\",\"地区\":\"湖北省\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"19元/斤\",\"品种\":\"加州鲈\",\"地区\":\"湖南省华容县\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"21-22元/斤\",\"品种\":\"加州鲈\",\"地区\":\"河南省郑州市\",\"时间\":\"2025-07-22\",\"规格\":\"1斤起\"},{\"价格\":\"19.5元/斤\",\"品种\":\"加州鲈\",\"地区\":\"江苏省吴江市\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"19.5元/斤\",\"品种\":\"加州鲈\",\"地区\":\"浙江省湖州市\",\"时间\":\"2025-07-22\",\"规格\":\"8两起\"},{\"价格\":\"9.6元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"2斤以上5斤头\"},{\"价格\":\"8.8元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"4斤头\"},{\"价格\":\"6.9元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"1-2斤\"},{\"价格\":\"8元/斤\",\"品种\":\"黑鱼\",\"地区\":\"浙江省湖州市\",\"时间\":\"2025-07-22\",\"规格\":\"3斤以上占3成统货\"},{\"价格\":\"8.8元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"2斤以上占7成统货\"},{\"价格\":\"11元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"4两头\"},{\"价格\":\"12元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"5两头\"},{\"价格\":\"16元/斤\",\"品种\":\"黄颡鱼\",\"地区\":null,\"时间\":\"2025-07-22\",\"规格\":\"4两头\"},{\"价格\":\"11.5元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"四川省\",\"时间\":\"2025-07-22\",\"规格\":\"5寸起\"},{\"价格\":\"14元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"浙江省湖州市\",\"时间\":\"2025-07-22\",\"规格\":\"4两头\"},{\"价格\":\"12元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"湖北省枝江市\",\"时间\":\"2025-07-22\",\"规格\":\"6.5寸\"},{\"价格\":\"9.5-10元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"湖北省枝江市\",\"时间\":\"2025-07-22\",\"规格\":\"5寸筛\"},{\"价格\":\"11元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"湖南省常德市\",\"时间\":\"2025-07-22\",\"规格\":\"6寸筛\"},{\"价格\":\"7.4元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"1.2斤起\"},{\"价格\":\"8.5元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"江苏省扬州市\",\"时间\":\"2025-07-22\",\"规格\":\"3.2斤起\"},{\"价格\":\"8.7元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"江苏省扬州市\",\"时间\":\"2025-07-22\",\"规格\":\"2.2斤起\"},{\"价格\":\"7.6元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"河南省郑州市\",\"时间\":\"2025-07-22\",\"规格\":\"1.8斤起\"},{\"价格\":\"8.2元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"四川省成都市\",\"时间\":\"2025-07-22\",\"规格\":\"1.2-2.5斤\"}]";
|
|
|
|
String json2 = "[{\"价格\":\"35-36元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"仔鳜\"},{\"价格\":\"32-33元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"饲料鳜\"},{\"价格\":\"36元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"江苏省\",\"时间\":null,\"规格\":\"标鱼\"},{\"价格\":\"36元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"安徽省\",\"时间\":\"2025-极速-22\",\"规格\":\"标鱼\"},{\"价格\":\"34元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"湖南省\",\"时间\":\"2025-07-22\",\"规格\":\"标鱼\"},{\"价格\":\"36元/斤\",\"品种\":\"鳜鱼\",\"地区\":\"湖北省\",\"时间\":\"2025-07-22\",\"规格\":\"标鱼\"},{\"价格\":\"17元/斤\",\"品种\":\"加州鲈\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"8两起\"},{\"价格\":\"23元/斤\",\"品种\":\"加州鲈\",\"地区\":\"四川省成都市\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"19元/斤\",\"品种\":\"加州鲈\",\"地区\":\"湖北省\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"19元/斤\",\"品种\":\"加州鲈\",\"地区\":\"湖南省华容县\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"21-22元/斤\",\"品种\":\"加州鲈\",\"地区\":\"河南省郑州市\",\"时间\":\"2025-07-22\",\"规格\":\"1斤起\"},{\"价格\":\"19.5元/斤\",\"品种\":\"加州鲈\",\"地区\":\"江苏省吴江市\",\"时间\":\"2025-07-22\",\"规格\":\"9两起\"},{\"价格\":\"19.5极速/斤\",\"品种\":\"加州鲈\",\"地区\":\"浙江省湖州市\",\"时间\":\"2025-07-22\",\"规格\":\"8两起\"},{\"价格\":\"9.6元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"2斤以上5斤头\"},{\"价格\":\"8.8元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"4斤头\"},{\"价格\":\"6.9元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"1-2斤中鱼\"},{\"价格\":\"8元/斤\",\"品种\":\"黑鱼\",\"地区\":\"浙江省湖州市\",\"时间\":\"2025-07-22\",\"规格\":\"3斤以上占3成统货\"},{\"价格\":\"8.8元/斤\",\"品种\":\"黑鱼\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"2斤以上占7成统货\"},{\"价格\":\"11元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"4两头\"},{\"价格\":\"12元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"广东省佛山市\",\"时间\":\"2025-07-22\",\"规格\":\"5两头\"},{\"价格\":\"16元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"福建省漳州市\",\"时间\":\"2025-07-22\",\"规格\":\"4两头\"},{\"价格\":\"11.5元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"四川省\",\"时间\":\"2025-07-22\",\"规格\":\"5寸起\"},{\"价格\":\"14元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"浙江省湖州市\",\"时间\":\"2025-07-22\",\"规格\":\"4两头\"},{\"价格\":\"12元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"湖北省枝江市\",\"时间\":\"2025-07-22\",\"规格\":\"6.5寸\"},{\"价格\":\"9.5-10元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"湖北省枝江市\",\"时间\":\"2025-07-22\",\"规格\":\"5寸筛\"},{\"价格\":\"11元/斤\",\"品种\":\"黄颡鱼\",\"地区\":\"湖南省常德市\",\"时间\":\"2025-07-22\",\"规格\":\"6寸筛\"},{\"价格\":\"7.4元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"广东省\",\"时间\":\"2025-07-22\",\"规格\":\"1.2斤起\"},{\"价格\":\"8.5元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"江苏省扬州市\",\"时间\":\"2025-07-22\",\"规格\":\"3.2斤起\"},{\"价格\":\"8.7元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"江苏省扬州市\",\"时间\":\"2025-07-22\",\"规格\":\"2.2斤起\"},{\"价格\":\"7.6元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"河南省郑州市\",\"时间\":\"2025-07-22\",\"规格\":\"1.8斤起\"},{\"价格\":\"8.2元/斤\",\"品种\":\"鮰鱼\",\"地区\":\"四川省成都市\",\"时间\":\"2025-07-22\",\"规格\":\"1.2-2.5斤\"}]";
|
|
|
|
// 每个地区维护一个 Set 用于去重
|
|
|
|
Map<String, Set<String>> dedupMap = new HashMap<>();
|
|
|
|
// 按地区分组
|
|
|
|
Map<String, List<FishPrice>> grouped = new LinkedHashMap<>();
|
|
|
|
addFishPrice(grouped,json,dedupMap);
|
|
|
|
addFishPrice(grouped,json2,dedupMap);
|
|
|
|
draw("2025年7月23日",grouped);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static final Font baseFont;
|
|
|
|
|
|
|
|
static {
|
|
|
|
try {
|
|
|
|
baseFont = Font.createFont(Font.TRUETYPE_FONT,
|
|
|
|
new File("notosans/NotoSansCJKsc-Medium.otf"));
|
|
|
|
} catch (FontFormatException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void addFishPrice(Map<String, List<FishPrice>> grouped, String json,Map<String, Set<String>> dedupMap ) throws JsonProcessingException {
|
|
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
|
|
List<FishPrice> list = mapper.readValue(json, new TypeReference<List<FishPrice>>() {});
|
|
|
|
|
|
|
|
|
|
|
|
for (FishPrice item : list) {
|
|
|
|
String region = item.地区;
|
|
|
|
String uniqueKey = (item.品种 + "|" + item.规格 + "|" + item.价格 + "|" + item.时间).trim();
|
|
|
|
|
|
|
|
// 初始化分组和去重集合
|
|
|
|
grouped.computeIfAbsent(region, k -> new ArrayList<>());
|
|
|
|
dedupMap.computeIfAbsent(region, k -> new HashSet<>());
|
|
|
|
|
|
|
|
// 去重:只添加未出现过的记录
|
|
|
|
if (!dedupMap.get(region).contains(uniqueKey)) {
|
|
|
|
grouped.get(region).add(item);
|
|
|
|
dedupMap.get(region).add(uniqueKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String draw(String day, Map<String, List<FishPrice>> grouped) throws Exception {
|
|
|
|
// 表格参数
|
|
|
|
int rowHeight = 30;
|
|
|
|
int colWidth = 180;
|
|
|
|
int paddingTop = 140;
|
|
|
|
int paddingBottom = 120;
|
|
|
|
int tableWidth = colWidth * 5;
|
|
|
|
int tableHeight = (grouped.values().stream().mapToInt(List::size).sum() + 1) * rowHeight;
|
|
|
|
int totalHeight = paddingTop + tableHeight + paddingBottom;
|
|
|
|
|
|
|
|
// 创建画布
|
|
|
|
BufferedImage image = new BufferedImage(tableWidth, totalHeight, BufferedImage.TYPE_INT_RGB);
|
|
|
|
Graphics2D g = image.createGraphics();
|
|
|
|
|
|
|
|
// 背景色
|
|
|
|
g.setColor(new Color(235, 245, 255)); // 浅蓝
|
|
|
|
g.fillRect(0, 0, tableWidth, totalHeight);
|
|
|
|
|
|
|
|
// 抗锯齿
|
|
|
|
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
// 标题
|
|
|
|
g.setColor(Color.BLACK);
|
|
|
|
g.setFont(baseFont.deriveFont( Font.BOLD, 28));
|
|
|
|
drawCenteredString(g, day+" 全国主要鱼价行情表", new Rectangle(0, 20, tableWidth, 40), g.getFont());
|
|
|
|
|
|
|
|
// 绘制表格头
|
|
|
|
g.setFont(baseFont.deriveFont(Font.PLAIN, 16));
|
|
|
|
g.setColor(Color.BLACK);
|
|
|
|
String[] headers = {"地区", "品种", "规格", "价格", "时间"};
|
|
|
|
for (int i = 0; i < headers.length; i++) {
|
|
|
|
g.drawRect(i * colWidth, paddingTop, colWidth, rowHeight);
|
|
|
|
g.drawString(headers[i], i * colWidth + 10, paddingTop + 20);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 填充表格数据
|
|
|
|
int y = paddingTop + rowHeight;
|
|
|
|
for (Map.Entry<String, List<FishPrice>> entry : grouped.entrySet()) {
|
|
|
|
String region = entry.getKey();
|
|
|
|
List<FishPrice> fishes = entry.getValue();
|
|
|
|
|
|
|
|
// 地区合并绘制
|
|
|
|
g.drawRect(0, y, colWidth, fishes.size() * rowHeight);
|
|
|
|
drawCenteredString(g, region, new Rectangle(0, y, colWidth, fishes.size() * rowHeight), g.getFont());
|
|
|
|
|
|
|
|
for (int i = 0; i < fishes.size(); i++) {
|
|
|
|
FishPrice f = fishes.get(i);
|
|
|
|
int rowY = y + i * rowHeight;
|
|
|
|
|
|
|
|
g.drawRect(colWidth * 1, rowY, colWidth, rowHeight);
|
|
|
|
g.drawRect(colWidth * 2, rowY, colWidth, rowHeight);
|
|
|
|
g.drawRect(colWidth * 3, rowY, colWidth, rowHeight);
|
|
|
|
g.drawRect(colWidth * 4, rowY, colWidth, rowHeight);
|
|
|
|
|
|
|
|
g.drawString(null==f.品种?" ":f.品种, colWidth * 1 + 10, rowY + 20);
|
|
|
|
g.drawString(null==f.规格?" ":f.规格, colWidth * 2 + 10, rowY + 20);
|
|
|
|
g.drawString(null==f.价格?" ":f.价格, colWidth * 3 + 10, rowY + 20);
|
|
|
|
g.drawString(safeDate(f.时间), colWidth * 4 + 10, rowY + 20);
|
|
|
|
}
|
|
|
|
y += fishes.size() * rowHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 绘制下方 Logo 图片
|
|
|
|
BufferedImage logoImg = ImageIO.read(new File("logo.png"));
|
|
|
|
int logoWidth = logoImg.getWidth();
|
|
|
|
int logoHeight = logoImg.getHeight();
|
|
|
|
int logoX = (tableWidth - logoWidth) / 2;
|
|
|
|
int logoY = totalHeight - logoHeight - 40;
|
|
|
|
g.drawImage(logoImg, logoX, logoY, null);
|
|
|
|
|
|
|
|
// 上方文字 Logo
|
|
|
|
g.setFont(baseFont.deriveFont(Font.ITALIC, 16));
|
|
|
|
drawCenteredString(g, "由鱼儿乐智慧渔业出品", new Rectangle(logoX, logoY+logoHeight, 60, 20), g.getFont());
|
|
|
|
|
|
|
|
g.dispose();
|
|
|
|
|
|
|
|
// 输出图片
|
|
|
|
String saveFile = StyleConfig.savePath + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + "_jiage.png";
|
|
|
|
|
|
|
|
ImageIO.write(image, "png", new File(saveFile));
|
|
|
|
System.out.println("✅ 成功生成图片: "+saveFile);
|
|
|
|
return saveFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void drawCenteredString(Graphics2D g, String text, Rectangle rect, Font font) {
|
|
|
|
if (null == text)
|
|
|
|
{
|
|
|
|
text = "";
|
|
|
|
}
|
|
|
|
FontMetrics metrics = g.getFontMetrics(font);
|
|
|
|
try {
|
|
|
|
int x = rect.x + (rect.width - metrics.stringWidth(text)) / 2;
|
|
|
|
int y = rect.y + ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent();
|
|
|
|
g.setFont(font);
|
|
|
|
g.drawString(text, x, y);
|
|
|
|
}catch (Exception e)
|
|
|
|
{
|
|
|
|
System.out.println(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static String safeDate(String date) {
|
|
|
|
if (date == null || !date.matches("\\d{4}-\\d{2}-\\d{2}")) {
|
|
|
|
return "未知";
|
|
|
|
}
|
|
|
|
return date;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
...
|
...
|
|