材料站出库--二维码下载与生成
This commit is contained in:
parent
e18052d756
commit
4a89d1bbf0
|
|
@ -12,6 +12,7 @@ import com.bonus.common.log.annotation.SysLog;
|
|||
import com.bonus.common.log.enums.OperaType;
|
||||
import com.bonus.material.back.domain.vo.MaCodeVo;
|
||||
import com.bonus.material.basic.domain.BmQrcodeInfo;
|
||||
import com.bonus.material.basic.domain.report.DownloadRequest;
|
||||
import com.bonus.material.clz.domain.lease.*;
|
||||
import com.bonus.material.common.annotation.PreventRepeatSubmit;
|
||||
import com.bonus.material.clz.domain.vo.lease.LeaseTotalInfo;
|
||||
|
|
@ -24,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -444,4 +446,10 @@ public class MaterialLeaseInfoController extends BaseController {
|
|||
public AjaxResult getLeaseDataByCode(LeaseTotalInfo info) {
|
||||
return materialLeaseInfoService.getLeaseDataByCode(info);
|
||||
}
|
||||
|
||||
@ApiOperation("二维码打包下载")
|
||||
@PostMapping("/downloadQrCode")
|
||||
public void downloadQrCode(@RequestBody MaterialLeaseApplyDetails bean, HttpServletResponse response) throws IOException {
|
||||
materialLeaseInfoService.queryQrCode(bean, response);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,4 +100,10 @@ public class MaterialMaCodeVo {
|
|||
@Excel(name = "出库时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date outTime;
|
||||
|
||||
/**
|
||||
* 二维码
|
||||
*/
|
||||
@ApiModelProperty(value = "二维码")
|
||||
private String qrCode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -498,4 +498,18 @@ public interface MaterialLeaseInfoMapper {
|
|||
* @return
|
||||
*/
|
||||
List<MaterialLeaseApplyInfo> getPublishList(MaterialLeaseApplyInfo leaseApplyInfo);
|
||||
|
||||
/**
|
||||
* 获取二维码
|
||||
* @param details
|
||||
* @return
|
||||
*/
|
||||
MaterialMaCodeVo getQrCodeByMaId(MaterialLeaseMaCodeDto details);
|
||||
|
||||
/**
|
||||
* 添加二维码信息
|
||||
* @param bmQrcodeInfo
|
||||
* @return
|
||||
*/
|
||||
int insertBmQrcodeInfo(BmQrcodeInfo bmQrcodeInfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.bonus.material.clz.mapper;
|
||||
|
||||
import com.bonus.material.back.domain.vo.MaCodeVo;
|
||||
import com.bonus.material.basic.domain.BmQrcodeInfo;
|
||||
import com.bonus.material.clz.domain.TeamVo;
|
||||
import com.bonus.material.clz.domain.machine.MaterialUseStorageInfo;
|
||||
import com.bonus.material.clz.domain.vo.*;
|
||||
|
|
@ -341,4 +342,11 @@ public interface MaterialMachineMapper {
|
|||
* @return
|
||||
*/
|
||||
List<MaterialProvideNumInfo> getSubNumList(MaterialRetainedEquipmentInfo bean);
|
||||
|
||||
/**
|
||||
* 修改ma_machine数据,二维码编号
|
||||
* @param bmQrcodeInfo
|
||||
* @return
|
||||
*/
|
||||
int updateMachine(BmQrcodeInfo bmQrcodeInfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.bonus.material.clz.domain.lease.*;
|
|||
import com.bonus.material.clz.domain.vo.lease.LeaseTotalInfo;
|
||||
import com.bonus.material.clz.domain.vo.lease.MaterialLeaseApplyRequestVo;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -171,4 +172,13 @@ public interface MaterialLeaseInfoService {
|
|||
* @return
|
||||
*/
|
||||
List<MaterialLeaseApplyDetailExport> getTotalDetailsList(MaterialLeaseApplyInfo bean);
|
||||
|
||||
/**
|
||||
* 查询二维码
|
||||
* @param bean
|
||||
* @param response
|
||||
* return
|
||||
*/
|
||||
void queryQrCode(MaterialLeaseApplyDetails bean, HttpServletResponse response);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.bonus.material.clz.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.bonus.common.biz.config.BackstageApplication;
|
||||
import com.bonus.common.biz.config.DateTimeHelper;
|
||||
import com.bonus.common.biz.config.QrCodeUtils;
|
||||
import com.bonus.common.biz.constant.MaterialConstants;
|
||||
import com.bonus.common.biz.domain.BmFileInfo;
|
||||
import com.bonus.common.biz.domain.TypeTreeBuild;
|
||||
|
|
@ -22,6 +24,7 @@ import com.bonus.material.basic.domain.BmAgreementInfo;
|
|||
import com.bonus.material.basic.domain.BmQrcodeInfo;
|
||||
import com.bonus.material.basic.mapper.BmAgreementInfoMapper;
|
||||
import com.bonus.material.basic.mapper.BmFileInfoMapper;
|
||||
import com.bonus.material.basic.mapper.BmQrcodeInfoMapper;
|
||||
import com.bonus.material.clz.domain.BmTeam;
|
||||
import com.bonus.material.clz.domain.lease.*;
|
||||
import com.bonus.material.clz.domain.vo.MaterialMaCodeVo;
|
||||
|
|
@ -42,7 +45,14 @@ import com.bonus.material.task.domain.TmTask;
|
|||
import com.bonus.material.task.domain.TmTaskAgreement;
|
||||
import com.bonus.material.task.mapper.TmTaskAgreementMapper;
|
||||
import com.bonus.material.task.mapper.TmTaskMapper;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.hibernate.validator.internal.util.StringHelper;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -50,11 +60,27 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* @Author ma_sh
|
||||
|
|
@ -94,6 +120,9 @@ public class MaterialLeaseInfoServiceImpl implements MaterialLeaseInfoService {
|
|||
@Resource
|
||||
private IwsTeamUserMapper iwsTeamUserMapper;
|
||||
|
||||
@Resource
|
||||
private BmQrcodeInfoMapper bmQrcodeInfoMapper;
|
||||
|
||||
/**
|
||||
* 查询领料任务列表
|
||||
*
|
||||
|
|
@ -508,6 +537,214 @@ public class MaterialLeaseInfoServiceImpl implements MaterialLeaseInfoService {
|
|||
return sortedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询或生成二维码
|
||||
*/
|
||||
@Override
|
||||
public void queryQrCode(MaterialLeaseApplyDetails bean, HttpServletResponse response) {
|
||||
if (bean == null || bean.getMaCodeList() == null || bean.getMaCodeList().isEmpty()) {
|
||||
throw new RuntimeException("二维码数据为空");
|
||||
}
|
||||
// 临时文件目录
|
||||
File tempDir = new File(System.getProperty("java.io.tmpdir"), "qr_temp_" + System.currentTimeMillis());
|
||||
if (!tempDir.exists()) {
|
||||
tempDir.mkdirs();
|
||||
}
|
||||
try {
|
||||
final int qrSize = 512;
|
||||
final int padding = 20;
|
||||
final int fontSize = 68;
|
||||
final int lineHeight = fontSize + 10;
|
||||
Font font = new Font("Arial", Font.PLAIN, fontSize);
|
||||
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
||||
hints.put(EncodeHintType.MARGIN, 1);
|
||||
|
||||
for (MaterialLeaseMaCodeDto details : bean.getMaCodeList()) {
|
||||
if (details.getMaId() == null) {
|
||||
continue;
|
||||
}
|
||||
String qrCode = "";
|
||||
String maCode = "";
|
||||
//查询该设备的二维码
|
||||
MaterialMaCodeVo machine = materialLeaseInfoMapper.getQrCodeByMaId(details);
|
||||
if (machine != null) {
|
||||
if (!StringHelper.isNullOrEmptyString(machine.getQrCode())) {
|
||||
qrCode = machine.getQrCode();
|
||||
} else {
|
||||
qrCode = generateQrCode(machine.getMaCode(), machine.getTypeId());
|
||||
}
|
||||
maCode = machine.getMaCode();
|
||||
}
|
||||
|
||||
// 1. 准备二维码文本
|
||||
String qrText = "http://ahjj.jypxks.com:9988/imw/backstage/machine/qrCodePage?qrcode=" + qrCode;
|
||||
|
||||
// 2. 生成二维码 BitMatrix
|
||||
BitMatrix bitMatrix = new MultiFormatWriter().encode(qrText, BarcodeFormat.QR_CODE, qrSize, qrSize, hints);
|
||||
|
||||
// 3) 转 BufferedImage
|
||||
BufferedImage qrImage = new BufferedImage(qrSize, qrSize, BufferedImage.TYPE_INT_RGB);
|
||||
for (int x = 0; x < qrSize; x++) {
|
||||
for (int y = 0; y < qrSize; y++) {
|
||||
qrImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
// 4) 在二维码下方绘制文字并换行
|
||||
BufferedImage finalImg = drawTextBelow(qrImage, maCode, font, qrSize, padding, lineHeight, fontSize);
|
||||
|
||||
// 5) 写入临时文件
|
||||
String safeFileName = sanitizeFileName(maCode) + ".png";
|
||||
File outFile = new File(tempDir, safeFileName);
|
||||
ImageIO.write(finalImg, "png", outFile);
|
||||
}
|
||||
|
||||
// 6) 把所有图片打包为 zip 并输出(使用 Commons Compress,支持设置编码)
|
||||
String zipName = "QrCode_" + LocalDate.now().toString() + ".zip";
|
||||
response.setContentType("application/zip");
|
||||
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + URLEncoder.encode(zipName, "UTF-8"));
|
||||
|
||||
try (ServletOutputStream sos = response.getOutputStream();
|
||||
java.util.zip.ZipOutputStream zos = new java.util.zip.ZipOutputStream(sos)) {
|
||||
zos.setLevel(Deflater.BEST_SPEED);
|
||||
for (File file : tempDir.listFiles()) {
|
||||
String entryName = file.getName();
|
||||
ZipEntry ze = new ZipEntry(entryName);
|
||||
zos.putNextEntry(ze);
|
||||
try (InputStream fis = new FileInputStream(file)) {
|
||||
IOUtils.copy(fis, zos);
|
||||
}
|
||||
zos.closeEntry();
|
||||
}
|
||||
zos.finish();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("生成二维码失败:" + e.getMessage());
|
||||
} finally {
|
||||
// 清理临时文件
|
||||
FileUtils.deleteQuietly(tempDir);
|
||||
}
|
||||
}
|
||||
|
||||
/** 简单的文件名清洗(避免非法字符) */
|
||||
private String sanitizeFileName(String name) {
|
||||
if (name == null) {
|
||||
return "file";
|
||||
}
|
||||
return name.replaceAll("[\\\\/:*?\"<>|]", "_");
|
||||
}
|
||||
|
||||
private BufferedImage drawTextBelow(BufferedImage qrImage, String text, Font font, int qrSize, int padding, int lineHeight, int fontSize) {
|
||||
// 1) 计算换行(以 qrSize 为最大宽度)
|
||||
FontRenderContext frc = new FontRenderContext(null, true, true);
|
||||
List<String> lines = new ArrayList<>();
|
||||
StringBuilder line = new StringBuilder();
|
||||
for (char c : text.toCharArray()) {
|
||||
String testLine = line.toString() + c;
|
||||
double width = font.getStringBounds(testLine, frc).getWidth();
|
||||
if (width > qrSize) {
|
||||
if (line.length() > 0) {
|
||||
lines.add(line.toString());
|
||||
}
|
||||
line = new StringBuilder(String.valueOf(c));
|
||||
} else {
|
||||
line.append(c);
|
||||
}
|
||||
}
|
||||
if (line.length() > 0) {
|
||||
lines.add(line.toString());
|
||||
}
|
||||
|
||||
// 2) 计算最终图片尺寸
|
||||
int totalWidth = qrSize + padding * 2;
|
||||
int totalHeight = qrSize + padding * 2 + lines.size() * lineHeight;
|
||||
|
||||
BufferedImage result = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = result.createGraphics();
|
||||
// 开启抗锯齿
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
// 背景
|
||||
g.setColor(Color.WHITE);
|
||||
g.fillRect(0, 0, totalWidth, totalHeight);
|
||||
|
||||
// 绘制二维码(居中在 padding 区域)
|
||||
g.drawImage(qrImage, padding, padding, qrSize, qrSize, null);
|
||||
|
||||
// 绘制文字
|
||||
g.setColor(Color.BLACK);
|
||||
g.setFont(font);
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String ln = lines.get(i);
|
||||
int textWidth = fm.stringWidth(ln);
|
||||
int x = (totalWidth - textWidth) / 2;
|
||||
// y 坐标:qrSize + padding + baseline 偏移(用 fontSize 进行计算)
|
||||
int y = qrSize + padding + (int)(fontSize * 0.9) + i * lineHeight;
|
||||
g.drawString(ln, x, y);
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 生成二维码编号等信息
|
||||
*/
|
||||
public String generateQrCode(String maCode,String typeId){
|
||||
BmQrcodeInfo bmQrcodeInfo = new BmQrcodeInfo();
|
||||
String genMonth = DateTimeHelper.getNowMonth();
|
||||
List<BmQrcodeInfo> list = bmQrcodeInfoMapper.selectByMonth(genMonth);
|
||||
BmQrcodeInfo bean = null;
|
||||
int num = 0;
|
||||
if (list != null && list.size() > 0) {
|
||||
bean = list.get(0);
|
||||
num = Integer.parseInt(bean.getQrCode().split("-")[1]);
|
||||
}
|
||||
genMonth = genMonth.replace("-", "");
|
||||
String code = genMonth + "-" + String.format("%5d", num + 1).replace(" ", "0");
|
||||
// 新购管理-二维码打印-新增
|
||||
String url = BackstageApplication.getUrl() + "backstage/machine/qrCodePage?qrcode=" + code;
|
||||
// // 二维码的图片格式
|
||||
String format = "jpg";
|
||||
//设置路径
|
||||
String mkdirsName = "images";
|
||||
// linux 系统路径
|
||||
String saveDirectory = "/data/imw/" + mkdirsName + "/";
|
||||
String os = System.getProperty("os.name");
|
||||
if (os.toLowerCase().startsWith("win")) {
|
||||
//本地路径
|
||||
saveDirectory = "D://files/" + mkdirsName + "/";
|
||||
}
|
||||
// 生成二维码
|
||||
File files = new File(saveDirectory);
|
||||
if (!files.exists()) {
|
||||
files.mkdirs();
|
||||
}
|
||||
QrCodeUtils.generateQRImage(url, saveDirectory, code + ".jpg", format);
|
||||
String qrUrl = saveDirectory + code + ".jpg";
|
||||
bmQrcodeInfo.setQrCode(code);
|
||||
bmQrcodeInfo.setQrUrl(qrUrl);
|
||||
bmQrcodeInfo.setCreateTime(DateUtils.getNowDate());
|
||||
bmQrcodeInfo.setCreateBy(SecurityUtils.getLoginUser().getUserid().toString());
|
||||
bmQrcodeInfo.setBindStatus("1");
|
||||
bmQrcodeInfo.setMaCode(maCode);
|
||||
bmQrcodeInfo.setTypeId(Long.valueOf(typeId));
|
||||
//新增bm_qrcode_info数据
|
||||
materialLeaseInfoMapper.insertBmQrcodeInfo(bmQrcodeInfo);
|
||||
//修改设备表
|
||||
materialMachineMapper.updateMachine(bmQrcodeInfo);
|
||||
return code;
|
||||
}
|
||||
|
||||
private List<MaterialMaCodeVo> getMachineByProIdAndTypeId(Long proId,Long typeId){
|
||||
MaterialLeaseApplyInfo dto = new MaterialLeaseApplyInfo();
|
||||
dto.setProId(proId);
|
||||
|
|
|
|||
|
|
@ -377,6 +377,39 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
NOW()
|
||||
</trim>
|
||||
</insert>
|
||||
<insert id="insertBmQrcodeInfo">
|
||||
insert into bm_qrcode_info
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="qrCode != null">qr_code,</if>
|
||||
<if test="qrUrl != null">qr_url,</if>
|
||||
<if test="typeId != null">type_id,</if>
|
||||
<if test="qrType != null">qr_type,</if>
|
||||
<if test="taskId != null">task_id,</if>
|
||||
<if test="bindStatus != null">is_bind,</if>
|
||||
<if test="maCode != null">ma_code,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="companyId != null">company_id,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="qrCode != null">#{qrCode},</if>
|
||||
<if test="qrUrl != null">#{qrUrl},</if>
|
||||
<if test="typeId != null">#{typeId},</if>
|
||||
<if test="qrType != null">#{qrType},</if>
|
||||
<if test="taskId != null">#{taskId},</if>
|
||||
<if test="bindStatus != null">#{bindStatus},</if>
|
||||
<if test="maCode != null">#{maCode},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="companyId != null">#{companyId},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateLeaseApplyInfo">
|
||||
update clz_lease_apply_info
|
||||
|
|
@ -1781,4 +1814,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
WHERE
|
||||
lpd.`code` = #{code}
|
||||
</select>
|
||||
<select id="getQrCodeByMaId" resultType="com.bonus.material.clz.domain.vo.MaterialMaCodeVo">
|
||||
SELECT
|
||||
mm.ma_id AS maId,
|
||||
mm.ma_code AS maCode,
|
||||
mm.qr_code AS qrCode,
|
||||
mm.type_id AS typeId
|
||||
FROM
|
||||
ma_machine mm
|
||||
WHERE
|
||||
mm.ma_id = #{maId}
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@
|
|||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bonus.material.clz.mapper.MaterialMachineMapper">
|
||||
<update id="updateMachine">
|
||||
UPDATE ma_machine
|
||||
SET qr_code = #{qrCode}
|
||||
WHERE ma_code = #{maCode}
|
||||
and type_id = #{typeId}
|
||||
</update>
|
||||
<select id="getMachineInfo" resultType="com.bonus.material.ma.domain.Machine">
|
||||
SELECT
|
||||
sd.dept_name AS impUnitName,
|
||||
|
|
|
|||
Loading…
Reference in New Issue