LED显示功能增加

dev_xd
lijun 2026-03-24 23:33:37 +08:00
parent 9e66b8422a
commit ce786084bc
10 changed files with 674 additions and 270 deletions

View File

@ -28,8 +28,19 @@ public interface ProMobileAttendanceDataMapper
public List<ProMobileAttendanceData> selectProMobileAttendanceDataList(ProMobileAttendanceData proMobileAttendanceData); public List<ProMobileAttendanceData> selectProMobileAttendanceDataList(ProMobileAttendanceData proMobileAttendanceData);
/**
*
* @param proMobileAttendanceData
* @return
*/
public List<ProMobileAttendanceData> selectProMobileAttendanceDataListByWorkArea(ProMobileAttendanceData proMobileAttendanceData); public List<ProMobileAttendanceData> selectProMobileAttendanceDataListByWorkArea(ProMobileAttendanceData proMobileAttendanceData);
/**
*
* @param proMobileAttendanceData
* @return
*/
public List<ProMobileAttendanceData> selectProMobileAttendanceAllListByWorkArea(ProMobileAttendanceData proMobileAttendanceData);
/** /**
* *
* *

View File

@ -94,6 +94,43 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE rn = 1 WHERE rn = 1
</select> </select>
<select id="selectProMobileAttendanceAllListByWorkArea" parameterType="ProMobileAttendanceData" resultMap="ProMobileAttendanceDataResult">
SELECT pma.id, pma.user_id, pma.project_id, pma.cfg_id, pma.in_out, pma.longitude, pma.latitude, pma.att_date, pma.att_img, pma.is_del,
pma.remark, pma.state, pma.create_by, pma.create_time, pma.update_by, pma.update_time,
dic1.dict_label as craft_type_name, dic2.dict_label as craft_post_name, pma.att_device,
psu.user_name, psu.user_phone, psu.sub_dept_name, psu.sub_dept_group_name, psu.user_post, psu.user_sex,
pma.work_area_id
FROM pro_mobile_attendance_data pma
LEFT JOIN (
SELECT t.* FROM pro_project_info_subdepts_users t
INNER JOIN (
SELECT user_id, MAX(CONCAT(IFNULL(update_time, DATE('2099-12-31')), create_time)) AS max_time_key
FROM pro_project_info_subdepts_users
GROUP BY user_id
) t_max ON t.user_id = t_max.user_id
AND CONCAT(IFNULL(t.update_time, DATE('2099-12-31')), t.create_time) = t_max.max_time_key
) psu ON pma.user_id = psu.user_id
LEFT JOIN sys_dict_data dic1 ON psu.craft_type = dic1.dict_value AND dic1.dict_type = 'pro_craft_type'
LEFT JOIN sys_dict_data dic2 ON psu.craft_post = dic2.dict_value AND dic2.dict_type = 'pro_craft_post'
WHERE pma.is_del = 0
AND pma.work_area_id = #{workAreaId}
AND pma.project_id = #{projectId}
AND DATE(pma.att_date) = CURDATE()
AND pma.id IN (
SELECT id FROM (
SELECT id,
ROW_NUMBER() OVER (PARTITION BY user_id, in_out ORDER BY att_date DESC) as rn
FROM pro_mobile_attendance_data
WHERE is_del = 0
AND work_area_id = #{workAreaId}
AND project_id = #{projectId}
AND DATE(att_date) = CURDATE()
) ranked
WHERE rn = 1
)
ORDER BY psu.user_name, pma.att_date
</select>
<select id="selectProMobileAttendanceDataById" parameterType="Long" resultMap="ProMobileAttendanceDataResult"> <select id="selectProMobileAttendanceDataById" parameterType="Long" resultMap="ProMobileAttendanceDataResult">
<include refid="selectProMobileAttendanceDataVo"/> <include refid="selectProMobileAttendanceDataVo"/>
where pma.id = #{id} where pma.id = #{id}

View File

@ -41,5 +41,5 @@ public interface ILedScreenService {
*/ */
List<SysLedscreen> getAllLedScreensFromCacheByProjectId(Long projectId); List<SysLedscreen> getAllLedScreensFromCacheByProjectId(Long projectId);
String[] getImagePathsForScreen(SysLedscreen ledScreen); List<String> getImagePathsForScreen(SysLedscreen ledScreen);
} }

View File

@ -18,7 +18,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.awt.*; import java.awt.*;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -78,7 +80,7 @@ public class LedDrawService {
ProgramBxFile programFile = new ProgramBxFile("P000", profile); ProgramBxFile programFile = new ProgramBxFile("P000", profile);
// 根据LED屏的配置参数进行绘制 // 根据LED屏的配置参数进行绘制
String[] imagePaths = ledScreenService.getImagePathsForScreen(ledScreen); // 获取要显示的图片路径 List<String> imagePaths = ledScreenService.getImagePathsForScreen(ledScreen); // 获取要显示的图片路径
createBx6MProgram(programFile, ledScreen, imagePaths, profile); createBx6MProgram(programFile, ledScreen, imagePaths, profile);
return programFile; return programFile;
} }
@ -87,7 +89,7 @@ public class LedDrawService {
/** /**
* Bx6M * Bx6M
*/ */
private void createBx6MProgram(ProgramBxFile programFile, SysLedscreen ledScreen, String[] imagePaths, Bx6GScreenProfile profile) { private void createBx6MProgram(ProgramBxFile programFile, SysLedscreen ledScreen, List<String> imagePaths, Bx6GScreenProfile profile) {
try { try {
//绘图 头部显示屏信息 底显示时间 中间显示图片列表 //绘图 头部显示屏信息 底显示时间 中间显示图片列表
// 创建图文区 - 使用屏幕配置文件 // 创建图文区 - 使用屏幕配置文件
@ -106,8 +108,8 @@ public class LedDrawService {
area.addPage(textPage); area.addPage(textPage);
programFile.addArea(area); programFile.addArea(area);
// 添加图片页 // 添加图片页
if (imagePaths != null && imagePaths.length > 0) { if (imagePaths != null && imagePaths.size() > 0) {
logger.info("图片数量2={},sn={}x:0,y:17,w:{},h:{}",imagePaths.length,ledScreen.getDeviceSn(),ledScreen.getWidth().intValue(), logger.info("图片数量2={},sn={}x:0,y:17,w:{},h:{}",imagePaths.size(),ledScreen.getDeviceSn(),ledScreen.getWidth().intValue(),
ledScreen.getHeight().intValue()-32); ledScreen.getHeight().intValue()-32);
area = new TextCaptionBxArea(0, 17, ledScreen.getWidth().intValue(), area = new TextCaptionBxArea(0, 17, ledScreen.getWidth().intValue(),
ledScreen.getHeight().intValue()-32, profile); ledScreen.getHeight().intValue()-32, profile);

View File

@ -2,9 +2,8 @@ package com.yanzhu.led.service.impl;
import com.yanzhu.led.config.LedProperties; import com.yanzhu.led.config.LedProperties;
import com.yanzhu.led.service.ILedScreenService; import com.yanzhu.led.service.ILedScreenService;
import com.yanzhu.led.utils.LedFileUtils; import com.yanzhu.led.utils.*;
import com.yanzhu.led.utils.Uni2LedDrawer; import com.yanzhu.led.vo.UniAttendanceStartEndInfo;
import com.yanzhu.led.utils.UniLedDrawer;
import com.yanzhu.manage.domain.ProMobileAttendanceData; import com.yanzhu.manage.domain.ProMobileAttendanceData;
import com.yanzhu.manage.mapper.ProMobileAttendanceDataMapper; import com.yanzhu.manage.mapper.ProMobileAttendanceDataMapper;
import com.yanzhu.system.domain.SysLedscreen; import com.yanzhu.system.domain.SysLedscreen;
@ -17,7 +16,9 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -137,19 +138,31 @@ public class LedScreenServiceImpl implements ILedScreenService {
* LED * LED
* *
*/ */
public String[] getImagePathsForScreen(SysLedscreen ledScreen) { public List<String> getImagePathsForScreen(SysLedscreen ledScreen) {
// 这里应该根据实际业务逻辑获取图片路径 // 这里应该根据实际业务逻辑获取图片路径
//根据屏所在的工区ID获取考勤信息 //根据屏所在的工区ID获取考勤信息
//根据屏的DeviceNo为目录创建图片路径 //根据屏的DeviceNo为目录创建图片路径
if(ledScreen.getDrawType().intValue()==1){ if(ledScreen.getDrawType().intValue()==1){
//Uni考勤信息+气体监测数据
// 获取考勤数据 // 获取考勤数据
List<ProMobileAttendanceData> attendanceDataList = getAttendanceDataByWorkAreaId(ledScreen); List<ProMobileAttendanceData> attendanceDataList = getAttendanceDataByWorkAreaId(ledScreen);
return UniLedDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList); //return UniLedDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList);
List<String> imgs= UniAttendanceDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList);
return imgs;
}else if (ledScreen.getDrawType().intValue()==2){ }else if (ledScreen.getDrawType().intValue()==2){
//Uni考勤信息+环境监测数据
List<ProMobileAttendanceData> attendanceDataList = getAttendanceDataByWorkAreaId(ledScreen); List<ProMobileAttendanceData> attendanceDataList = getAttendanceDataByWorkAreaId(ledScreen);
return Uni2LedDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList); //return Uni2LedDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList);
List<String> imgs= UniAttendanceDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList);
return imgs;
}else if(ledScreen.getDrawType().intValue()==3){
List<UniAttendanceStartEndInfo> attendanceStartEndInfos=getAttendanceStartEndInfo(ledScreen);
List<String> imgs=UniAttendanceStartAndEndDrawer.drawLedScreen(ledScreen, ledProperties, attendanceStartEndInfos);
return imgs;
} }
return new String[]{}; // 实际使用时应从配置或数据库获取 return new ArrayList<>(); // 实际使用时应从配置或数据库获取
} }
// 根据工区ID获取考勤数据 // 根据工区ID获取考勤数据
@ -163,13 +176,54 @@ public class LedScreenServiceImpl implements ILedScreenService {
log.info("根据工区ID获取考勤数据: {}条, 工区ID: {}, 项目ID: {}", list.size(), ledScreen.getWorkareaId(), ledScreen.getProjectId()); log.info("根据工区ID获取考勤数据: {}条, 工区ID: {}, 项目ID: {}", list.size(), ledScreen.getWorkareaId(), ledScreen.getProjectId());
//根据屏的DeviceNo为目录创建图片路径 //根据屏的DeviceNo为目录创建图片路径
return list; return list;
// return Arrays.stream("1,2,3,4,5,6,7,8,9,10".split(",")).map(id -> {
// ProMobileAttendanceData d=new ProMobileAttendanceData();
// d.setId(Long.parseLong(id));
// return d;
// }).collect(Collectors.toList());
} }
//根据工区ID获取考勤数据 包含统计的
private List<UniAttendanceStartEndInfo> getAttendanceStartEndInfo(SysLedscreen ledScreen) {
ProMobileAttendanceData where = new ProMobileAttendanceData();
where.setWorkAreaId(ledScreen.getWorkareaId());
where.setProjectId(ledScreen.getProjectId());
List<ProMobileAttendanceData> list=proMobileAttendanceDataMapper.selectProMobileAttendanceAllListByWorkArea(where);
List<UniAttendanceStartEndInfo> datas=new ArrayList<>();
Map<Long, UniAttendanceStartEndInfo> userMap = new HashMap<>();
for (ProMobileAttendanceData data : list) {
Long userId = data.getUserId();
UniAttendanceStartEndInfo info = userMap.get(userId);
if (info == null) {
info = new UniAttendanceStartEndInfo();
info.setUserId(userId);
info.setProjectId(data.getProjectId());
info.setCfgId(data.getCfgId());
info.setUserName(data.getUserName());
info.setUserPhone(data.getUserPhone());
info.setSubDeptName(data.getSubDeptName());
info.setSubDeptGroupName(data.getSubDeptGroupName());
info.setCraftTypeName(data.getCraftTypeName());
info.setCraftPostName(data.getCraftPostName());
info.setUserPost(data.getUserPost());
userMap.put(userId, info);
}
if ("in".equals(data.getInOut())) {
info.setInDate(data.getAttDate());
} else if ("out".equals(data.getInOut())) {
info.setOutDate(data.getAttDate());
}
}
datas.addAll(userMap.values());
for (UniAttendanceStartEndInfo info : datas) {
if (info.getOutDate() != null && info.getInDate() != null && info.getOutDate().before(info.getInDate())) {
info.setOutDate(null);
}
}
return datas;
}
/** /**
* LED * LED
*/ */

View File

@ -19,134 +19,9 @@ import java.util.stream.Collectors;
public class Uni2LedDrawer extends BaseDrawer{ public class Uni2LedDrawer extends BaseDrawer{
public static String[] drawLedScreen(SysLedscreen ledScreen, LedProperties ledProperties, List<ProMobileAttendanceData> attendanceDataList) { public static List<String> drawLedScreen(SysLedscreen ledScreen, LedProperties ledProperties, List<ProMobileAttendanceData> attendanceDataList) {
String ledSavePath=ledProperties.getSavePath()+ledScreen.getDeviceSn()+"/"; return UniAttendanceDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList);
//检查目录及子目录是否已存在,不存在创建目
LedFileUtils.createDir(ledSavePath);
int screenHeight=ledScreen.getHeight().intValue();
int dataLine = Math.max(3, (screenHeight-32)/18-1); // 确保dataLine至少为1
List<String> imagePaths = new ArrayList<>();
//根据dataLine来对list进行分页调用绘制方法
if (!attendanceDataList.isEmpty() && dataLine > 0) { // 检查列表不为空且dataLine大于0
for (int i = 0; i < attendanceDataList.size(); i += dataLine) {
List<ProMobileAttendanceData> subList = attendanceDataList.subList(i, Math.min(i + dataLine, attendanceDataList.size()));
String imagePath=ledSavePath + "image" + (i / dataLine + 1) + ".bmp";
drawImage(ledScreen, subList, imagePath, dataLine);
imagePaths.add(imagePath);
} }
}
return imagePaths.toArray(new String[0]);
}
private static void drawImage(SysLedscreen ledScreen, List<ProMobileAttendanceData> subList, String imagePath, int maxRows) {
int screenWidth=ledScreen.getWidth().intValue();
int screenHeight=ledScreen.getHeight().intValue();
int lineHeight = 18;
int headerHeight = lineHeight;
int rowHeight = lineHeight;
int margin = 2;
int drawWidth = screenWidth - 2 * margin;
int imageHeight = screenHeight - 32;
int totalHeight = imageHeight - 2 * margin;
int imageWidth = screenWidth;
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = image.createGraphics();
try {
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, imageWidth, imageHeight);
Font font = new Font("宋体", Font.BOLD, 14);
g2d.setFont(font);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setColor(Color.WHITE);
String[] headers = {"姓名", "班组", "进入时间"};
int[] columnWidths = {drawWidth / 3, drawWidth / 3, drawWidth / 3};
int x = margin;
for (int i = 0; i < headers.length; i++) {
g2d.drawString(headers[i], x + 2, margin + headerHeight - 2);
x += columnWidths[i];
}
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, margin + headerHeight, margin + drawWidth, margin + headerHeight);
g2d.setColor(Color.WHITE);
for (int i = 0; i < maxRows; i++) {
int rowY = margin + headerHeight + i * rowHeight;
int lineY = rowY + rowHeight;
if (lineY > margin + totalHeight) {
lineY = margin + totalHeight;
}
if (i < subList.size()) {
ProMobileAttendanceData data = subList.get(i);
String userName = data.getUserName() != null ? data.getUserName() : "";
String subDeptGroupName = data.getSubDeptGroupName() != null ? data.getSubDeptGroupName() : "";
String attTime = "";
if (data.getAttDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
attTime = sdf.format(data.getAttDate());
}
x = margin;
g2d.drawString(userName, x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString(subDeptGroupName, x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString(attTime, x + 2, rowY + rowHeight - 4);
} else {
x = margin;
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
}
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, lineY, margin + drawWidth, lineY);
}
g2d.setColor(Color.WHITE);
int x1 = margin + columnWidths[0];
int x2 = margin + columnWidths[0] + columnWidths[1];
g2d.drawLine(x1, margin, x1, margin + totalHeight);
g2d.drawLine(x2, margin, x2, margin + totalHeight);
g2d.setColor(Color.WHITE);
g2d.drawRect(margin, margin, drawWidth, totalHeight);
File outputFile = new File(imagePath);
ImageIO.write(image, "bmp", outputFile);
} catch (IOException e) {
e.printStackTrace();
} finally {
g2d.dispose();
}
}
public static void main(String[] args) { public static void main(String[] args) {
SysLedscreen led=new SysLedscreen(); SysLedscreen led=new SysLedscreen();
led.setWidth(256l); led.setWidth(256l);

View File

@ -0,0 +1,148 @@
package com.yanzhu.led.utils;
import com.yanzhu.led.config.LedProperties;
import com.yanzhu.manage.domain.ProMobileAttendanceData;
import com.yanzhu.system.domain.SysLedscreen;
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.ArrayList;
import java.util.List;
/**
*
*
*/
public class UniAttendanceDrawer {
public static List<String> drawLedScreen(SysLedscreen ledScreen, LedProperties ledProperties, List<ProMobileAttendanceData> attendanceDataList) {
String ledSavePath=ledProperties.getSavePath()+ledScreen.getDeviceSn()+"/";
//检查目录及子目录是否已存在,不存在创建目
LedFileUtils.createDir(ledSavePath);
int screenHeight=ledScreen.getHeight().intValue();
int dataLine = Math.max(3, (screenHeight-32)/18-1); // 确保dataLine至少为1
List<String> imagePaths = new ArrayList<>();
//根据dataLine来对list进行分页调用绘制方法
if (!attendanceDataList.isEmpty() && dataLine > 0) { // 检查列表不为空且dataLine大于0
for (int i = 0; i < attendanceDataList.size(); i += dataLine) {
List<ProMobileAttendanceData> subList = attendanceDataList.subList(i, Math.min(i + dataLine, attendanceDataList.size()));
String imagePath=ledSavePath + "image" + (i / dataLine + 1) + ".bmp";
drawImage(ledScreen, subList, imagePath, dataLine);
imagePaths.add(imagePath);
}
}
return imagePaths;
}
private static void drawImage(SysLedscreen ledScreen, List<ProMobileAttendanceData> subList, String imagePath, int maxRows) {
int screenWidth=ledScreen.getWidth().intValue();
int screenHeight=ledScreen.getHeight().intValue();
int lineHeight = 18;
int headerHeight = lineHeight;
int rowHeight = lineHeight;
int margin = 2;
int drawWidth = screenWidth - 2 * margin;
int imageHeight = screenHeight - 32;
int totalHeight = imageHeight - 2 * margin;
int imageWidth = screenWidth;
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = image.createGraphics();
try {
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, imageWidth, imageHeight);
Font font = new Font("宋体", Font.BOLD, 14);
g2d.setFont(font);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setColor(Color.WHITE);
String[] headers = {"姓名", "班组", "进入时间"};
int[] columnWidths = {drawWidth / 3, drawWidth / 3, drawWidth / 3};
int x = margin;
for (int i = 0; i < headers.length; i++) {
g2d.drawString(headers[i], x + 2, margin + headerHeight - 2);
x += columnWidths[i];
}
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, margin + headerHeight, margin + drawWidth, margin + headerHeight);
g2d.setColor(Color.WHITE);
for (int i = 0; i < maxRows; i++) {
int rowY = margin + headerHeight + i * rowHeight;
int lineY = rowY + rowHeight;
if (lineY > margin + totalHeight) {
lineY = margin + totalHeight;
}
if (i < subList.size()) {
ProMobileAttendanceData data = subList.get(i);
String userName = data.getUserName() != null ? data.getUserName() : "";
String subDeptGroupName = data.getSubDeptGroupName() != null ? data.getSubDeptGroupName() : "";
String attTime = "";
if (data.getAttDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
attTime = sdf.format(data.getAttDate());
}
x = margin;
g2d.drawString(userName, x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString(subDeptGroupName, x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString(attTime, x + 2, rowY + rowHeight - 4);
} else {
x = margin;
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
}
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, lineY, margin + drawWidth, lineY);
}
g2d.setColor(Color.WHITE);
int x1 = margin + columnWidths[0];
int x2 = margin + columnWidths[0] + columnWidths[1];
g2d.drawLine(x1, margin, x1, margin + totalHeight);
g2d.drawLine(x2, margin, x2, margin + totalHeight);
g2d.setColor(Color.WHITE);
g2d.drawRect(margin, margin, drawWidth, totalHeight);
File outputFile = new File(imagePath);
ImageIO.write(image, "bmp", outputFile);
} catch (IOException e) {
e.printStackTrace();
} finally {
g2d.dispose();
}
}
}

View File

@ -0,0 +1,270 @@
package com.yanzhu.led.utils;
import com.yanzhu.led.config.LedProperties;
import com.yanzhu.led.vo.UniAttendanceStartEndInfo;
import com.yanzhu.manage.domain.ProMobileAttendanceData;
import com.yanzhu.system.domain.SysLedscreen;
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.ArrayList;
import java.util.Date;
import java.util.List;
/**
*
*
*/
public class UniAttendanceStartAndEndDrawer {
public static List<String> drawLedScreen(SysLedscreen ledScreen, LedProperties ledProperties, List<UniAttendanceStartEndInfo> attendanceDataList) {
String ledSavePath=ledProperties.getSavePath()+ledScreen.getDeviceSn()+"/";
//检查目录及子目录是否已存在,不存在创建目
LedFileUtils.createDir(ledSavePath);
//获取在场人数
long count = attendanceDataList.stream().filter(d -> d.getOutDate() == null).count();
//日志打印在场人数
//每页在表格上有一行显示:"当前在场人数count人",后面是表格,表格显示 姓名,班组,进入时间,离开时间
int screenHeight=ledScreen.getHeight().intValue();
int dataLine = Math.max(3, (screenHeight-50)/18-1); // 确保dataLine至少为1预留空间给在场人数行
List<String> imagePaths = new ArrayList<>();
//根据dataLine来对list进行分页调用绘制方法
if (!attendanceDataList.isEmpty() && dataLine > 0) { // 检查列表不为空且dataLine大于0
for (int i = 0; i < attendanceDataList.size(); i += dataLine) {
List<UniAttendanceStartEndInfo> subList = attendanceDataList.subList(i, Math.min(i + dataLine, attendanceDataList.size()));
String imagePath=ledSavePath + "image" + (i / dataLine + 1) + ".bmp";
drawImage(ledScreen, subList, imagePath, dataLine, count);
imagePaths.add(imagePath);
}
}
return imagePaths;
}
private static void drawImage(SysLedscreen ledScreen, List<UniAttendanceStartEndInfo> subList, String imagePath, int maxRows, long count) {
int screenWidth=ledScreen.getWidth().intValue();
int screenHeight=ledScreen.getHeight().intValue();
int lineHeight = 18;
int headerHeight = lineHeight;
int rowHeight = lineHeight;
int countRowHeight = lineHeight;
int margin = 2;
int drawWidth = screenWidth - 2 * margin;
int imageHeight = screenHeight - 32;
int totalHeight = imageHeight - 2 * margin;
int imageWidth = screenWidth;
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = image.createGraphics();
try {
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, imageWidth, imageHeight);
Font font = new Font("宋体", Font.PLAIN, 13);
g2d.setFont(font);
g2d.setColor(Color.WHITE);
String[] headers = {"姓名", "班组", "进入时间", "离开时间"};
int[] columnWidths = {drawWidth / 5, drawWidth * 3 / 10, drawWidth / 4, drawWidth / 4};
int currentY = margin;
g2d.drawString("当前在场人数:" + count + "人", margin + 2, currentY + countRowHeight - 4);
currentY += countRowHeight;
int x = margin;
for (int i = 0; i < headers.length; i++) {
g2d.drawString(headers[i], x + 2, currentY + headerHeight - 4);
x += columnWidths[i];
}
currentY += headerHeight;
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, currentY, margin + drawWidth, currentY);
g2d.setColor(Color.WHITE);
for (int i = 0; i < maxRows; i++) {
int rowY = currentY + i * rowHeight;
int lineY = rowY + rowHeight;
if (lineY > margin + totalHeight) {
lineY = margin + totalHeight;
}
if (i < subList.size()) {
UniAttendanceStartEndInfo data = subList.get(i);
String userName = data.getUserName() != null ? data.getUserName() : "";
String subDeptGroupName = data.getSubDeptGroupName() != null ? data.getSubDeptGroupName() : "";
String inTime = "";
if (data.getInDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
inTime = sdf.format(data.getInDate());
}
String outTime = "";
if (data.getOutDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
outTime = sdf.format(data.getOutDate());
}
x = margin;
g2d.drawString(userName, x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString(subDeptGroupName, x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString(inTime, x + 2, rowY + rowHeight - 4);
x += columnWidths[2];
g2d.drawString(outTime, x + 2, rowY + rowHeight - 4);
} else {
x = margin;
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[2];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
}
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, lineY, margin + drawWidth, lineY);
}
g2d.setColor(Color.WHITE);
int x1 = margin + columnWidths[0];
int x2 = margin + columnWidths[0] + columnWidths[1];
int x3 = margin + columnWidths[0] + columnWidths[1] + columnWidths[2];
g2d.drawLine(x1, margin + countRowHeight, x1, margin + totalHeight);
g2d.drawLine(x2, margin + countRowHeight, x2, margin + totalHeight);
g2d.drawLine(x3, margin + countRowHeight, x3, margin + totalHeight);
g2d.setColor(Color.WHITE);
g2d.drawRect(margin, margin + countRowHeight, drawWidth, totalHeight - countRowHeight);
File outputFile = new File(imagePath);
ImageIO.write(image, "bmp", outputFile);
} catch (IOException e) {
e.printStackTrace();
} finally {
g2d.dispose();
}
}
public static void main(String[] args) {
List<UniAttendanceStartEndInfo> testData = createTestData();
SysLedscreen ledScreen = new SysLedscreen();
ledScreen.setWidth(256l);
ledScreen.setHeight(160l);
ledScreen.setDeviceSn("TEST001");
LedProperties ledProperties = new LedProperties();
List<String> imagePaths = drawLedScreen(ledScreen, ledProperties, testData);
System.out.println("生成的图片路径:");
for (String path : imagePaths) {
System.out.println(path);
}
}
private static List<UniAttendanceStartEndInfo> createTestData() {
List<UniAttendanceStartEndInfo> list = new ArrayList<>();
addAttendance(list, 3548L, "侯泽芳", "18691080516", "项目总包单位", "管理班组",
parseTime("2026-03-24 11:24:12"), parseTime("2026-03-24 17:59:51"));
addAttendance(list, 3720L, "冯帆", "15667288301", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "管理班组",
parseTime("2026-03-24 08:07:26"), parseTime("2026-03-24 10:24:43"));
addAttendance(list, 3744L, "冷义德", "15641285767", "项目总包单位", "桃树湾",
parseTime("2026-03-24 17:42:41"), parseTime("2026-03-24 17:59:07"));
addAttendance(list, 3752L, "刘克龙", "13780241604", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 12:57:58"), parseTime("2026-03-24 11:55:20"));
addAttendance(list, 3736L, "刘景林", "18392474396", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 16:34:53"), parseTime("2026-03-24 17:48:33"));
addAttendance(list, 3738L, "卓子忠", "18135737705", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 16:34:18"), parseTime("2026-03-24 17:58:32"));
addAttendance(list, 3748L, "徐小龙", "18292369100", "陕西研筑信息科技有限公司", "管理班组",
parseTime("2026-03-24 17:50:46"), parseTime("2026-03-24 17:59:01"));
addAttendance(list, 3749L, "徐涛", "18161767380", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "桃树湾",
parseTime("2026-03-24 12:58:12"), parseTime("2026-03-24 17:58:10"));
addAttendance(list, 3642L, "晏云云", "17352153644", "项目总包单位", "管理班组",
parseTime("2026-03-24 09:39:05"), parseTime("2026-03-24 10:29:17"));
addAttendance(list, 3774L, "李艳丰", "18033657455", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "桃树湾",
null, parseTime("2026-03-24 11:39:41"));
addAttendance(list, 3737L, "杨国华", "13938338679", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 16:34:34"), parseTime("2026-03-24 17:59:12"));
addAttendance(list, 3742L, "杨峰", "17612910335", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "桃树湾",
parseTime("2026-03-24 16:34:37"), parseTime("2026-03-24 17:57:59"));
addAttendance(list, 3735L, "林忠", "13043537559", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 18:01:56"), parseTime("2026-03-24 18:02:59"));
addAttendance(list, 3733L, "梁春", "18220199851", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 16:34:32"), parseTime("2026-03-24 17:57:37"));
addAttendance(list, 3724L, "楚梦飞", "15769267044", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "管理班组",
parseTime("2026-03-24 17:42:56"), parseTime("2026-03-24 17:45:44"));
addAttendance(list, 3723L, "王涛", "18696809001", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "管理班组",
parseTime("2026-03-24 11:24:19"), parseTime("2026-03-24 11:39:47"));
addAttendance(list, 3727L, "王珂", "19916217559", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "管理班组",
parseTime("2026-03-24 17:45:04"), parseTime("2026-03-24 17:58:33"));
addAttendance(list, 3564L, "石岩", "18706870106", "项目总包单位", "管理班组",
parseTime("2026-03-24 17:36:22"), parseTime("2026-03-24 18:00:08"));
addAttendance(list, 3734L, "耿德毅", "15249211104", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 17:00:54"), parseTime("2026-03-24 11:53:08"));
addAttendance(list, 3732L, "董西峰", "15991497422", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 17:21:39"), parseTime("2026-03-24 17:59:22"));
addAttendance(list, 3751L, "郭炳旭", "18838989230", "项目总包单位", "桃树湾",
parseTime("2026-03-24 11:24:05"), parseTime("2026-03-24 11:40:07"));
addAttendance(list, 3731L, "陈平", "13865321999", "西安吉鑫", "桃树湾",
parseTime("2026-03-24 16:52:21"), parseTime("2026-03-24 17:33:44"));
addAttendance(list, 3750L, "陈晓东", "13835926225", "长春-石家庄天然气管道工程干线隧道工程施工三标段项目部", "桃树湾",
parseTime("2026-03-24 09:45:21"), parseTime("2026-03-24 09:47:39"));
return list;
}
private static void addAttendance(List<UniAttendanceStartEndInfo> list, Long userId, String userName, String userPhone,
String subDeptName, String subDeptGroupName, Date inDate, Date outDate) {
UniAttendanceStartEndInfo info = new UniAttendanceStartEndInfo();
info.setUserId(userId);
info.setProjectId(204L);
info.setCfgId(0L);
info.setUserName(userName);
info.setUserPhone(userPhone);
info.setSubDeptName(subDeptName);
info.setSubDeptGroupName(subDeptGroupName);
info.setInDate(inDate);
info.setOutDate(outDate);
if (outDate != null && inDate != null && outDate.before(inDate)) {
info.setOutDate(null);
}
list.add(info);
}
private static Date parseTime(String timeStr) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.parse(timeStr);
} catch (Exception e) {
return null;
}
}
}

View File

@ -20,133 +20,10 @@ import javax.imageio.ImageIO;
public class UniLedDrawer extends BaseDrawer{ public class UniLedDrawer extends BaseDrawer{
public static String[] drawLedScreen(SysLedscreen ledScreen, LedProperties ledProperties, List<ProMobileAttendanceData> attendanceDataList) { public static List<String> drawLedScreen(SysLedscreen ledScreen, LedProperties ledProperties, List<ProMobileAttendanceData> attendanceDataList) {
String ledSavePath=ledProperties.getSavePath()+ledScreen.getDeviceSn()+"/"; return UniAttendanceDrawer.drawLedScreen(ledScreen, ledProperties, attendanceDataList);
//检查目录及子目录是否已存在,不存在创建目
LedFileUtils.createDir(ledSavePath);
int screenHeight=ledScreen.getHeight().intValue();
int dataLine = Math.max(3, (screenHeight-32)/18-1); // 确保dataLine至少为1
List<String> imagePaths = new ArrayList<>();
//根据dataLine来对list进行分页调用绘制方法
if (!attendanceDataList.isEmpty() && dataLine > 0) { // 检查列表不为空且dataLine大于0
for (int i = 0; i < attendanceDataList.size(); i += dataLine) {
List<ProMobileAttendanceData> subList = attendanceDataList.subList(i, Math.min(i + dataLine, attendanceDataList.size()));
String imagePath=ledSavePath + "image" + (i / dataLine + 1) + ".bmp";
drawImage(ledScreen, subList, imagePath, dataLine);
imagePaths.add(imagePath);
}
}
return imagePaths.toArray(new String[0]);
} }
private static void drawImage(SysLedscreen ledScreen, List<ProMobileAttendanceData> subList, String imagePath, int maxRows) {
int screenWidth=ledScreen.getWidth().intValue();
int screenHeight=ledScreen.getHeight().intValue();
int lineHeight = 18;
int headerHeight = lineHeight;
int rowHeight = lineHeight;
int margin = 2;
int drawWidth = screenWidth - 2 * margin;
int imageHeight = screenHeight - 32;
int totalHeight = imageHeight - 2 * margin;
int imageWidth = screenWidth;
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = image.createGraphics();
try {
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, imageWidth, imageHeight);
Font font = new Font("宋体", Font.BOLD, 14);
g2d.setFont(font);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setColor(Color.WHITE);
String[] headers = {"姓名", "班组", "进入时间"};
int[] columnWidths = {drawWidth / 3, drawWidth / 3, drawWidth / 3};
int x = margin;
for (int i = 0; i < headers.length; i++) {
g2d.drawString(headers[i], x + 2, margin + headerHeight - 2);
x += columnWidths[i];
}
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, margin + headerHeight, margin + drawWidth, margin + headerHeight);
g2d.setColor(Color.WHITE);
for (int i = 0; i < maxRows; i++) {
int rowY = margin + headerHeight + i * rowHeight;
int lineY = rowY + rowHeight;
if (lineY > margin + totalHeight) {
lineY = margin + totalHeight;
}
if (i < subList.size()) {
ProMobileAttendanceData data = subList.get(i);
String userName = data.getUserName() != null ? data.getUserName() : "";
String subDeptGroupName = data.getSubDeptGroupName() != null ? data.getSubDeptGroupName() : "";
String attTime = "";
if (data.getAttDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
attTime = sdf.format(data.getAttDate());
}
x = margin;
g2d.drawString(userName, x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString(subDeptGroupName, x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString(attTime, x + 2, rowY + rowHeight - 4);
} else {
x = margin;
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[0];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
x += columnWidths[1];
g2d.drawString("", x + 2, rowY + rowHeight - 4);
}
g2d.setColor(Color.WHITE);
g2d.drawLine(margin, lineY, margin + drawWidth, lineY);
}
g2d.setColor(Color.WHITE);
int x1 = margin + columnWidths[0];
int x2 = margin + columnWidths[0] + columnWidths[1];
g2d.drawLine(x1, margin, x1, margin + totalHeight);
g2d.drawLine(x2, margin, x2, margin + totalHeight);
g2d.setColor(Color.WHITE);
g2d.drawRect(margin, margin, drawWidth, totalHeight);
File outputFile = new File(imagePath);
ImageIO.write(image, "bmp", outputFile);
} catch (IOException e) {
e.printStackTrace();
} finally {
g2d.dispose();
}
}
public static void main(String[] args) { public static void main(String[] args) {
SysLedscreen led=new SysLedscreen(); SysLedscreen led=new SysLedscreen();

View File

@ -0,0 +1,130 @@
package com.yanzhu.led.vo;
import java.util.Date;
/**
* Uni
*/
public class UniAttendanceStartEndInfo {
private Long userId;
private Long projectId;
private Long cfgId;
//进入时间
private Date inDate;
//出去时间
private Date outDate;
//用户名
private String userName;
//用户手机号
private String userPhone;
//子部门名称
private String subDeptName;
//子部门组别名称
private String subDeptGroupName;
//工种名称
private String craftTypeName;
//岗位名称
private String craftPostName;
//岗位名称
private String userPost;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getProjectId() {
return projectId;
}
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
public Long getCfgId() {
return cfgId;
}
public void setCfgId(Long cfgId) {
this.cfgId = cfgId;
}
public Date getInDate() {
return inDate;
}
public void setInDate(Date inDate) {
this.inDate = inDate;
}
public Date getOutDate() {
return outDate;
}
public void setOutDate(Date outDate) {
this.outDate = outDate;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPhone() {
return userPhone;
}
public void setUserPhone(String userPhone) {
this.userPhone = userPhone;
}
public String getSubDeptName() {
return subDeptName;
}
public void setSubDeptName(String subDeptName) {
this.subDeptName = subDeptName;
}
public String getSubDeptGroupName() {
return subDeptGroupName;
}
public void setSubDeptGroupName(String subDeptGroupName) {
this.subDeptGroupName = subDeptGroupName;
}
public String getCraftTypeName() {
return craftTypeName;
}
public void setCraftTypeName(String craftTypeName) {
this.craftTypeName = craftTypeName;
}
public String getCraftPostName() {
return craftPostName;
}
public void setCraftPostName(String craftPostName) {
this.craftPostName = craftPostName;
}
public String getUserPost() {
return userPost;
}
public void setUserPost(String userPost) {
this.userPost = userPost;
}
}