feat:新增生成二维码功能

main
HuangHuiKang 2 weeks ago
parent 6688495d0c
commit 00681c954e

@ -70,10 +70,13 @@
<netty.version>4.1.113.Final</netty.version>
<mqtt.version>1.2.5</mqtt.version>
<opc.version>0.6.9</opc.version>
<qrcode.version>3.5.3</qrcode.version>
<!-- 三方云服务相关 -->
<commons-io.version>2.17.0</commons-io.version>
<commons-compress.version>1.27.1</commons-compress.version>
<aws-java-sdk-s3.version>1.12.777</aws-java-sdk-s3.version>
<s3.version>2.41.33</s3.version>
<justauth.version>1.0.8</justauth.version>
<jimureport.version>1.7.8</jimureport.version>
<weixin-java.version>4.6.0</weixin-java.version>
@ -589,6 +592,17 @@
<version>${aws-java-sdk-s3.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>software.amazon.awssdk</groupId>-->
<!-- <artifactId>s3</artifactId>-->
<!-- <version>${s3.version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>software.amazon.awssdk</groupId>-->
<!-- <artifactId>sts</artifactId>-->
<!-- <version>${s3.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
@ -648,6 +662,16 @@
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${qrcode.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${qrcode.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.common.api.mold.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* ERP
* <p>
* erp 使 1-030-000-000
*/
public interface ErrorCodeConstants {
// ========== 二维码记录表1-030-100-000 ==========
ErrorCode RECORD_NOT_EXISTS = new ErrorCode(1_003_000_000, "通用二维码记录不存在。");
ErrorCode FAILED_TO_REGENERATE = new ErrorCode(1_003_000_001, "重新生成二维码/条形码错误。");
}

@ -16,6 +16,12 @@
<description>common 模块业务实现</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- 模块自身 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
@ -56,6 +62,14 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
</dependency>
</dependencies>
</project>

@ -16,7 +16,7 @@ public class MoldSaveReqVO {
private Long id;
@Schema(description = "模具编码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "模具编码不能为空")
// @NotEmpty(message = "模具编码不能为空")
private String code;
@Schema(description = "模具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")

@ -0,0 +1,122 @@
package cn.iocoder.yudao.module.common.controller.admin.qrcoderecord;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordPageReqVO;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordRespVO;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordSaveReqVO;
import cn.iocoder.yudao.module.common.dal.dataobject.qrcoderecord.QrcodeRecordDO;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
@Tag(name = "管理后台 - 通用二维码记录")
@RestController
@RequestMapping("/qrcode/record")
@Validated
public class QrcodeRecordController {
@Resource
private QrcodeRecordService qrcodeRecordService;
@PostMapping("/create")
@Operation(summary = "创建通用二维码记录")
@PreAuthorize("@ss.hasPermission('qrcode:record:create')")
public CommonResult<Long> createRecord(@Valid @RequestBody QrcodeRecordSaveReqVO createReqVO) {
return success(qrcodeRecordService.createRecord(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新通用二维码记录")
@PreAuthorize("@ss.hasPermission('qrcode:record:update')")
public CommonResult<Boolean> updateRecord(@Valid @RequestBody QrcodeRecordSaveReqVO updateReqVO) {
qrcodeRecordService.updateRecord(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除通用二维码记录")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('qrcode:record:delete')")
public CommonResult<Boolean> deleteRecord(@RequestParam("id") Long id) {
qrcodeRecordService.deleteRecord(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得通用二维码记录")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('qrcode:record:query')")
public CommonResult<QrcodeRecordRespVO> getRecord(@RequestParam("id") Long id) {
QrcodeRecordDO record = qrcodeRecordService.getRecord(id);
return success(BeanUtils.toBean(record, QrcodeRecordRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得通用二维码记录分页")
@PreAuthorize("@ss.hasPermission('qrcode:record:query')")
public CommonResult<PageResult<QrcodeRecordRespVO>> getRecordPage(@Valid QrcodeRecordPageReqVO pageReqVO) {
PageResult<QrcodeRecordDO> pageResult = qrcodeRecordService.getRecordPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, QrcodeRecordRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出通用二维码记录 Excel")
@PreAuthorize("@ss.hasPermission('qrcode:record:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportRecordExcel(@Valid QrcodeRecordPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<QrcodeRecordDO> list = qrcodeRecordService.getRecordPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "通用二维码记录.xls", "数据", QrcodeRecordRespVO.class,
BeanUtils.toBean(list, QrcodeRecordRespVO.class));
}
//TODO 扫二维码拉起app端,仍需app拉起连接地址。
// @GetMapping(value = "/scan", produces = "text/html;charset=UTF-8")
// @Operation(summary = "扫二维码拉起app端 ")
// @PermitAll
// public void scan(@RequestParam("type") String type,
// @RequestParam("id") Long id,
// @RequestParam(required=false) String code,
// HttpServletResponse response) throws IOException {
// String html = qrcodeRecordService.buildScanTransitHtml(type, id,code);
// response.setContentType("text/html;charset=UTF-8");
// response.getWriter().write(html);
// }
@GetMapping("/scan/resolve-id")
@Operation(summary = "扫二维码返回对应id ")
@PermitAll
public CommonResult<Map<String, Object>> resolveId(@RequestParam String type,
@RequestParam Long id,
@RequestParam String code) {
return success(qrcodeRecordService.resolveScanBizId(type, id, code));
}
}

@ -0,0 +1,59 @@
package cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 通用二维码记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class QrcodeRecordPageReqVO extends PageParam {
@Schema(description = "业务类型MOLD/PRODUCT/EQUIPMENT/PART/SPARE/WORK_ORDER", example = "2")
private String bizType;
@Schema(description = "业务ID", example = "31277")
private Long bizId;
@Schema(description = "业务编码")
private String bizCode;
@Schema(description = "二维码场景DETAIL/LABEL/TRACE")
private String qrScene;
@Schema(description = "二维码内容(扫码入口地址)")
private String qrContent;
@Schema(description = "二维码文件名", example = "芋艿")
private String fileName;
@Schema(description = "MinIO bucket名称", example = "王五")
private String bucketName;
@Schema(description = "MinIO对象路径", example = "赵六")
private String objectName;
@Schema(description = "二维码图片访问地址", example = "https://www.iocoder.cn")
private String qrcodeFileUrl;
@Schema(description = "文件MIME类型", example = "1")
private String mimeType;
@Schema(description = "文件大小(字节)")
private Long fileSize;
@Schema(description = "状态1-有效 0-失效", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "QR(二维码)/BARCODE(条形码)", example = "")
private String codeType;
}

@ -0,0 +1,73 @@
package cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 通用二维码记录 Response VO")
@Data
@ExcelIgnoreUnannotated
public class QrcodeRecordRespVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "28938")
@ExcelProperty("主键ID")
private Long id;
@Schema(description = "业务类型MOLD/PRODUCT/EQUIPMENT/PART/SPARE/WORK_ORDER", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@ExcelProperty("业务类型MOLD/PRODUCT/EQUIPMENT/PART/SPARE/WORK_ORDER")
private String bizType;
@Schema(description = "业务ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31277")
@ExcelProperty("业务ID")
private Long bizId;
@Schema(description = "业务编码")
@ExcelProperty("业务编码")
private String bizCode;
@Schema(description = "二维码场景DETAIL/LABEL/TRACE", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("二维码场景DETAIL/LABEL/TRACE")
private String qrScene;
@Schema(description = "二维码内容(扫码入口地址)", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("二维码内容(扫码入口地址)")
private String qrContent;
@Schema(description = "二维码文件名", example = "芋艿")
@ExcelProperty("二维码文件名")
private String fileName;
@Schema(description = "MinIO bucket名称", example = "王五")
@ExcelProperty("MinIO bucket名称")
private String bucketName;
@Schema(description = "MinIO对象路径", example = "赵六")
@ExcelProperty("MinIO对象路径")
private String objectName;
@Schema(description = "二维码图片访问地址", example = "https://www.iocoder.cn")
@ExcelProperty("二维码图片访问地址")
private String qrcodeFileUrl;
@Schema(description = "文件MIME类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("文件MIME类型")
private String mimeType;
@Schema(description = "文件大小(字节)")
@ExcelProperty("文件大小(字节)")
private Long fileSize;
@Schema(description = "状态1-有效 0-失效", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("状态1-有效 0-失效")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "QR(二维码)/BARCODE(条形码)", example = "")
private String codeType;
}

@ -0,0 +1,61 @@
package cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 通用二维码记录新增/修改 Request VO")
@Data
public class QrcodeRecordSaveReqVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "28938")
private Long id;
@Schema(description = "业务类型MOLD/PRODUCT/EQUIPMENT/PART/SPARE/WORK_ORDER", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotEmpty(message = "业务类型MOLD/PRODUCT/EQUIPMENT/PART/SPARE/WORK_ORDER不能为空")
private String bizType;
@Schema(description = "业务ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31277")
@NotNull(message = "业务ID不能为空")
private Long bizId;
@Schema(description = "业务编码")
private String bizCode;
@Schema(description = "二维码场景DETAIL/LABEL/TRACE", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "二维码场景DETAIL/LABEL/TRACE不能为空")
private String qrScene;
@Schema(description = "二维码内容(扫码入口地址)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "二维码内容(扫码入口地址)不能为空")
private String qrContent;
@Schema(description = "二维码文件名", example = "芋艿")
private String fileName;
@Schema(description = "MinIO bucket名称", example = "王五")
private String bucketName;
@Schema(description = "MinIO对象路径", example = "赵六")
private String objectName;
@Schema(description = "二维码图片访问地址", example = "https://www.iocoder.cn")
private String qrcodeFileUrl;
@Schema(description = "文件MIME类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotEmpty(message = "文件MIME类型不能为空")
private String mimeType;
@Schema(description = "文件大小(字节)")
private Long fileSize;
@Schema(description = "状态1-有效 0-失效", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态1-有效 0-失效不能为空")
private Integer status;
@Schema(description = "QR(二维码)/BARCODE(条形码)", example = "")
private String codeType;
}

@ -113,4 +113,10 @@ public class MoldDO extends BaseDO {
@TableField(exist = false)
private String moldType;
/**
*
*/
@TableField(exist = false)
private String qrcodeUrl;
}

@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.common.dal.dataobject.qrcoderecord;
import lombok.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* DO
*
* @author
*/
@TableName("qrcode_record")
@KeySequence("qrcode_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class QrcodeRecordDO extends BaseDO {
/**
* ID
*/
@TableId
private Long id;
/**
* MOLD/PRODUCT/EQUIPMENT/PART/SPARE/WORK_ORDER
*/
private String bizType;
/**
* ID
*/
private Long bizId;
/**
*
*/
private String bizCode;
/**
* DETAIL/LABEL/TRACE
*/
private String qrScene;
/**
*
*/
private String qrContent;
/**
*
*/
private String fileName;
/**
* MinIO bucket
*/
private String bucketName;
/**
* MinIO
*/
private String objectName;
/**
* 访
*/
private String qrcodeFileUrl;
/**
* MIME
*/
private String mimeType;
/**
*
*/
private Long fileSize;
/**
* 1- 0-
*/
private Integer status;
/**
* QR()/BARCODE()
*/
private String codeType;
}

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.common.dal.mysql.qrcoderecord;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordPageReqVO;
import cn.iocoder.yudao.module.common.dal.dataobject.qrcoderecord.QrcodeRecordDO;
import org.apache.ibatis.annotations.Mapper;
/**
* Mapper
*
* @author
*/
@Mapper
public interface QrcodeRecordMapper extends BaseMapperX<QrcodeRecordDO> {
default PageResult<QrcodeRecordDO> selectPage(QrcodeRecordPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<QrcodeRecordDO>()
.eqIfPresent(QrcodeRecordDO::getBizType, reqVO.getBizType())
.eqIfPresent(QrcodeRecordDO::getBizId, reqVO.getBizId())
.eqIfPresent(QrcodeRecordDO::getBizCode, reqVO.getBizCode())
.eqIfPresent(QrcodeRecordDO::getQrScene, reqVO.getQrScene())
.eqIfPresent(QrcodeRecordDO::getQrContent, reqVO.getQrContent())
.likeIfPresent(QrcodeRecordDO::getFileName, reqVO.getFileName())
.likeIfPresent(QrcodeRecordDO::getBucketName, reqVO.getBucketName())
.likeIfPresent(QrcodeRecordDO::getObjectName, reqVO.getObjectName())
.eqIfPresent(QrcodeRecordDO::getQrcodeFileUrl, reqVO.getQrcodeFileUrl())
.eqIfPresent(QrcodeRecordDO::getMimeType, reqVO.getMimeType())
.eqIfPresent(QrcodeRecordDO::getFileSize, reqVO.getFileSize())
.eqIfPresent(QrcodeRecordDO::getStatus, reqVO.getStatus())
.betweenIfPresent(QrcodeRecordDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(QrcodeRecordDO::getId));
}
}

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum CodeTypeEnum {
QR("QR", "二维码"),
BARCODE("BARCODE", "条形码");
private final String code;
private final String desc;
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
public static CodeTypeEnum fromBarcodeType(Integer barcodeType) {
if (barcodeType == null) {
return null;
}
return Integer.valueOf(1).equals(barcodeType) ? BARCODE : QR;
}
}

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.common.enums;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum QrcodeBizTypeEnum {
PRODUCT("PRODUCTMATERIAL", "产品物料"),
EQUIPMENT("EQUIPMENT", "设备"),
KEY_PART("KEY_PART", "关键件"),
MOLD("MOLD", "模具"),
SPARE("SPARE", "备件");
private final String code;
private final String name;
public static QrcodeBizTypeEnum of(String code) {
for (QrcodeBizTypeEnum item : values()) {
if (item.code.equalsIgnoreCase(code)) {
return item;
}
}
return null;
}
}

@ -0,0 +1,9 @@
package cn.iocoder.yudao.module.common.handler;
public interface QrcodeBizHandler {
String getBizType();
boolean exists(Long id);
String buildDeepLink(Long id);
String buildH5Path(Long id);
}

@ -0,0 +1,83 @@
package cn.iocoder.yudao.module.common.service.qrcordrecord;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordPageReqVO;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordSaveReqVO;
import cn.iocoder.yudao.module.common.dal.dataobject.qrcoderecord.QrcodeRecordDO;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* Service
*
* @author
*/
public interface QrcodeRecordService {
/**
*
*
* @param createReqVO
* @return
*/
Long createRecord(@Valid QrcodeRecordSaveReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateRecord(@Valid QrcodeRecordSaveReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteRecord(Long id);
/**
*
*
* @param id
* @return
*/
QrcodeRecordDO getRecord(Long id);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<QrcodeRecordDO> getRecordPage(QrcodeRecordPageReqVO pageReqVO);
void generateOrRefresh(QrcodeBizTypeEnum bizType, Long bizId, String bizCode, String scene) throws UnsupportedEncodingException;
void generateOrRefreshBarcode(QrcodeBizTypeEnum bizType, Long bizId, String bizCode, String scene) throws UnsupportedEncodingException;
String buildScanTransitHtml(String type, Long id,String code);
String selectQrcodeUrlByIdAndCode(String code, Long id, String code1);
Map<String, Object> resolveScanBizId(String type, Long id, String code);
void deleteByBiz(QrcodeBizTypeEnum bizType, Long bizId);
void regenerateByCodeType(QrcodeBizTypeEnum bizType, Long bizId, String bizCode, String scene, String codeType)
throws UnsupportedEncodingException;
void generateOrRefresh(
QrcodeBizTypeEnum bizType,
Long bizId,
String bizCode,
String scene,
CodeTypeEnum codeType
) throws UnsupportedEncodingException;
}

@ -0,0 +1,598 @@
package cn.iocoder.yudao.module.common.service.qrcordrecord;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordPageReqVO;
import cn.iocoder.yudao.module.common.controller.admin.qrcoderecord.vo.QrcodeRecordSaveReqVO;
import cn.iocoder.yudao.module.common.dal.dataobject.qrcoderecord.QrcodeRecordDO;
import cn.iocoder.yudao.module.common.dal.mysql.qrcoderecord.QrcodeRecordMapper;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.handler.QrcodeBizHandler;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.common.api.mold.enums.ErrorCodeConstants.RECORD_NOT_EXISTS;
/**
* Service
*
* @author
*/
@Service
@Validated
@Slf4j
public class QrcodeRecordServiceImpl implements QrcodeRecordService {
@Resource
private FileApi fileApi;
@Value("${yudao.qrcode.scan-base-url}")
private String scanBaseUrl;
@Value("${yudao.qrcode.width:300}")
private Integer width;
@Value("${yudao.qrcode.height:300}")
private Integer height;
@Value("${yudao.qrcode.default-bucket:common-qrcode}")
private String defaultBucket;
@Value("${yudao.qrcode.fail-url}")
private String failUrl;
@Value("${yudao.qrcode.scan-base-url}")
private String serverBaseUrl;
@Value("#{${yudao.qrcode.buckets:{}}}")
private Map<String, String> bucketMap = new HashMap<>();
@Resource
private QrcodeRecordMapper qrcodeRecordMapper;
private final Map<String, QrcodeBizHandler> handlerMap;
public QrcodeRecordServiceImpl(List<QrcodeBizHandler> handlers) {
this.handlerMap = handlers.stream()
.collect(Collectors.toMap(h -> h.getBizType().toUpperCase(), h -> h));
}
@Override
public Long createRecord(QrcodeRecordSaveReqVO createReqVO) {
// 插入
QrcodeRecordDO record = BeanUtils.toBean(createReqVO, QrcodeRecordDO.class);
qrcodeRecordMapper.insert(record);
// 返回
return record.getId();
}
@Override
public void updateRecord(QrcodeRecordSaveReqVO updateReqVO) {
// 校验存在
validateRecordExists(updateReqVO.getId());
// 更新
QrcodeRecordDO updateObj = BeanUtils.toBean(updateReqVO, QrcodeRecordDO.class);
qrcodeRecordMapper.updateById(updateObj);
}
@Override
public void deleteRecord(Long id) {
// 校验存在
validateRecordExists(id);
// 删除
qrcodeRecordMapper.deleteById(id);
}
private void validateRecordExists(Long id) {
if (qrcodeRecordMapper.selectById(id) == null) {
throw exception(RECORD_NOT_EXISTS);
}
}
@Override
public QrcodeRecordDO getRecord(Long id) {
return qrcodeRecordMapper.selectById(id);
}
@Override
public PageResult<QrcodeRecordDO> getRecordPage(QrcodeRecordPageReqVO pageReqVO) {
return qrcodeRecordMapper.selectPage(pageReqVO);
}
@Override
public void generateOrRefresh(QrcodeBizTypeEnum bizType, Long bizId, String bizCode, String scene) throws UnsupportedEncodingException {
if (bizType == null || bizId == null) {
throw new IllegalArgumentException("bizType 或 bizId 不能为空");
}
String qrScene = StrUtil.blankToDefault(scene, "DETAIL");
// 1. 幂等查询biz_type + biz_id + scene 唯一)
QrcodeRecordDO existed = qrcodeRecordMapper.selectOne(
new LambdaQueryWrapper<QrcodeRecordDO>()
.eq(QrcodeRecordDO::getBizType, bizType.getCode())
.eq(QrcodeRecordDO::getBizId, bizId)
.eq(QrcodeRecordDO::getBizCode,bizCode)
.eq(QrcodeRecordDO::getCodeType,"QR")
.eq(QrcodeRecordDO::getQrScene, qrScene)
.last("limit 1")
);
// 2. 组装二维码内容(统一扫码入口)
String qrContent = "{\"type\":\"" + bizType.getCode()
+ "\",\"id\":" + bizId
+ (StrUtil.isNotBlank(bizCode) ? ",\"code\":\"" + bizCode + "\"" : "")
+ "}";
// 3. 生成二维码PNG
byte[] pngBytes = buildQrPng(qrContent, width, height);
// 4. 选择bucket + objectName
String bucket = resolveBucket(bizType); // 例如 yudao.qrcode.buckets.mold
String objectName = bizType.getCode().toLowerCase() + "/qr/" + LocalDate.now() + "/" + bizId + ".png";
String fileName = bizType.getCode().toLowerCase() + "_" + bizCode + ".png";
// 5. 上传文件(按你项目 FileApi 实际签名改)
// 如果支持bucket参数用这个
// FileRespDTO file = fileApi.createFile(bucket, objectName, "image/png", pngBytes);
// 默认上传
Map<String, String> file = fileApi.createFile(fileName, objectName, pngBytes);
String fileUrl = file.get("fileUrl");
// 6. upsert 记录
QrcodeRecordDO record = new QrcodeRecordDO();
record.setBizType(bizType.getCode());
record.setBizId(bizId);
record.setBizCode(bizCode);
record.setQrScene(qrScene);
record.setQrContent(qrContent);
record.setFileName(fileName);
record.setBucketName(bucket);
record.setObjectName(objectName);
record.setQrcodeFileUrl(fileUrl);
record.setMimeType("image/png");
record.setFileSize((long) pngBytes.length);
record.setStatus(1);
if (existed == null) {
qrcodeRecordMapper.insert(record);
} else {
record.setId(existed.getId());
qrcodeRecordMapper.updateById(record);
}
}
@Override
// @Transactional(rollbackFor = Exception.class)
public void generateOrRefreshBarcode(QrcodeBizTypeEnum bizType, Long bizId, String bizCode, String scene) throws UnsupportedEncodingException {
if (bizType == null || bizId == null) {
throw new IllegalArgumentException("bizType 或 bizId 不能为空");
}
String qrScene = StrUtil.blankToDefault(scene, "DETAIL");
QrcodeRecordDO existed = qrcodeRecordMapper.selectOne(
new LambdaQueryWrapper<QrcodeRecordDO>()
.eq(QrcodeRecordDO::getBizType, bizType.getCode())
.eq(QrcodeRecordDO::getBizId, bizId)
.eq(QrcodeRecordDO::getBizCode, bizCode)
.eq(QrcodeRecordDO::getCodeType, "BARCODE")
.eq(QrcodeRecordDO::getQrScene, qrScene)
.last("limit 1")
);
String barcodeContent = "{\"type\":\"" + bizType.getCode()
+ "\",\"id\":" + bizId
+ (StrUtil.isNotBlank(bizCode) ? ",\"code\":\"" + bizCode + "\"" : "")
+ "}";
int barcodeWidth = 600;
int barcodeHeight = 180;
byte[] pngBytes = buildBarcodePng(barcodeContent, barcodeWidth, barcodeHeight);
String bucket = resolveBucket(bizType);
String objectName = bizType.getCode().toLowerCase() + "/barcode/" + LocalDate.now() + "/" + bizId + ".png";
String fileName = bizType.getCode().toLowerCase() + "_" + bizCode + "_barcode.png";
Map<String, String> file = fileApi.createFile(fileName, objectName, pngBytes);
String fileUrl = file.get("fileUrl");
QrcodeRecordDO record = new QrcodeRecordDO();
record.setBizType(bizType.getCode());
record.setBizId(bizId);
record.setBizCode(bizCode);
record.setCodeType("BARCODE");
record.setQrScene(qrScene);
record.setQrContent(barcodeContent);
record.setFileName(fileName);
record.setBucketName(bucket);
record.setObjectName(objectName);
record.setQrcodeFileUrl(fileUrl);
record.setMimeType("image/png");
record.setFileSize((long) pngBytes.length);
record.setStatus(1);
if (existed == null) {
qrcodeRecordMapper.insert(record);
} else {
record.setId(existed.getId());
qrcodeRecordMapper.updateById(record);
}
}
private byte[] buildBarcodePng(String content, int width, int height) {
try {
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.CODE_128, width, height, hints);
BufferedImage image = MatrixToImageWriter.toBufferedImage(matrix);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
return os.toByteArray();
} catch (Exception e) {
throw new RuntimeException("生成条形码失败", e);
}
}
@Override
public String buildScanTransitHtml(String type, Long id,String code) {
String fallback = normalizeUrl(StrUtil.blankToDefault(failUrl, "/"));
if (StrUtil.isBlank(type) || id == null) {
return buildRedirectHtml(fallback);
}
if (StrUtil.isBlank(code)) {
return buildRedirectHtml(fallback);
}
QrcodeRecordDO record = qrcodeRecordMapper.selectOne(
new LambdaQueryWrapper<QrcodeRecordDO>()
.eq(QrcodeRecordDO::getBizType, type.trim().toUpperCase())
.eq(QrcodeRecordDO::getBizId, id)
.eq(QrcodeRecordDO::getQrScene, "DETAIL")
.last("limit 1")
);
if (record == null || !StrUtil.equals(record.getBizCode(), code)) {
return buildRedirectHtml(fallback);
}
QrcodeBizHandler handler = handlerMap.get(type.trim().toUpperCase());
if (handler == null) {
return buildRedirectHtml(fallback);
}
try {
if (!handler.exists(id)) {
return buildRedirectHtml(fallback);
}
String target = StrUtil.blankToDefault(handler.buildDeepLink(id), handler.buildH5Path(id));
if (StrUtil.isBlank(target)) {
return buildRedirectHtml(fallback);
}
return buildRedirectHtml(normalizeUrl(target));
} catch (Exception e) {
return buildRedirectHtml(fallback);
}
}
@Override
public String selectQrcodeUrlByIdAndCode(String bizType, Long bizId, String bizCode) {
if (StrUtil.isBlank(bizType) || bizId == null || StrUtil.isBlank(bizCode)) {
return null;
}
QrcodeRecordDO record = qrcodeRecordMapper.selectOne(Wrappers.<QrcodeRecordDO>lambdaQuery()
.eq(QrcodeRecordDO::getBizType, bizType)
.eq(QrcodeRecordDO::getBizId, bizId)
.eq(QrcodeRecordDO::getBizCode, bizCode)
.eq(QrcodeRecordDO::getStatus, 1)
.last("limit 1"));
if (record == null || StrUtil.isBlank(record.getQrcodeFileUrl())) {
return null;
}
return record.getQrcodeFileUrl();
}
@Override
public Map<String, Object> resolveScanBizId(String type, Long id, String code) {
Map<String, Object> result = new HashMap<>();
if (StrUtil.isBlank(type) || id == null || StrUtil.isBlank(code)) {
return null;
}
QrcodeRecordDO record = qrcodeRecordMapper.selectOne(
new LambdaQueryWrapper<QrcodeRecordDO>()
.eq(QrcodeRecordDO::getBizType, type)
.eq(QrcodeRecordDO::getBizId, id)
.eq(QrcodeRecordDO::getBizCode,code)
.eq(QrcodeRecordDO::getQrScene, "DETAIL")
.last("limit 1")
);
if (record == null) {
return null;
}
QrcodeBizHandler handler = handlerMap.get(type.trim().toUpperCase());
if (handler == null) {
return null;
}
result.put("type", type);
result.put("id", id);
return result;
}
private String normalizeUrl(String url) {
if (StrUtil.isBlank(url)) {
return "/";
}
if (StrUtil.startWithAny(url, "http://", "https://", "besure://")) {
return url;
}
String base = StrUtil.blankToDefault(serverBaseUrl, "");
if (StrUtil.isBlank(base)) {
return url.startsWith("/") ? url : "/" + url;
}
return StrUtil.removeSuffix(base, "/") + "/" + StrUtil.removePrefix(url, "/");
}
private String buildRedirectHtml(String targetUrl) {
String safe = escapeHtml(StrUtil.blankToDefault(targetUrl, "/"));
return "<!doctype html><html><head><meta charset=\"UTF-8\">"
+ "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
+ "<meta http-equiv=\"Cache-Control\" content=\"no-store, no-cache, must-revalidate, max-age=0\">"
+ "<meta http-equiv=\"Pragma\" content=\"no-cache\">"
+ "<meta http-equiv=\"Expires\" content=\"0\">"
+ "<title>跳转中...</title></head><body>"
+ "<script>window.location.replace('" + safe + "');</script>"
+ "<noscript><a href=\"" + safe + "\">点击继续</a></noscript>"
+ "</body></html>";
}
private String escapeHtml(String s) {
return s.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;")
.replace("'", "&#39;");
}
private String resolveBucket(QrcodeBizTypeEnum bizType) {
if (bizType == null) {
return defaultBucket;
}
if (bucketMap == null || bucketMap.isEmpty()) {
return defaultBucket;
}
String bucket = bucketMap.get(bizType.getCode().toLowerCase());
return StrUtil.blankToDefault(bucket, defaultBucket);
}
private byte[] buildQrPng(String content, int width, int height) {
try {
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix matrix = new MultiFormatWriter()
.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage image = MatrixToImageWriter.toBufferedImage(matrix);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
return os.toByteArray();
} catch (Exception e) {
throw new RuntimeException("生成二维码失败", e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteByBiz(QrcodeBizTypeEnum bizType, Long bizId) {
if (bizType == null || bizId == null) {
return;
}
List<QrcodeRecordDO> records = qrcodeRecordMapper.selectList(
Wrappers.<QrcodeRecordDO>lambdaQuery()
.eq(QrcodeRecordDO::getBizType, bizType.getCode())
.eq(QrcodeRecordDO::getBizId, bizId)
);
if (records == null || records.isEmpty()) {
return;
}
for (QrcodeRecordDO record : records) {
try {
String objectName = record.getObjectName();
if (StrUtil.isBlank(objectName)) {
continue;
}
// 通过 path(objectName) 找到 infra_file
Long id = fileApi.getFileByPath(objectName);
if (id == null) {
// 可选log.warn("未找到文件记录, qrcodeId={}, path={}", record.getId(), objectName);
continue;
}
// 用文件主键删除(会删存储+删infra_file记录
fileApi.deleteFile(id);
} catch (Exception e) {
// 你可按策略选择:继续 or 抛异常回滚
// 建议先打日志
log.warn("删除文件失败, qrcodeId={}, path={}", record.getId(), record.getObjectName(), e);
}
}
qrcodeRecordMapper.delete(
Wrappers.<QrcodeRecordDO>lambdaQuery()
.eq(QrcodeRecordDO::getBizType, bizType.getCode())
.eq(QrcodeRecordDO::getBizId, bizId)
);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void regenerateByCodeType(QrcodeBizTypeEnum bizType, Long bizId, String bizCode, String scene, String codeType)
throws UnsupportedEncodingException {
if (bizType == null || bizId == null) {
throw new IllegalArgumentException("bizType 或 bizId 不能为空");
}
String qrScene = StrUtil.blankToDefault(scene, "DETAIL");
String normalizedCodeType = StrUtil.blankToDefault(codeType, "QR").trim().toUpperCase();
if (!StrUtil.equalsAny(normalizedCodeType, "QR", "BARCODE")) {
throw new IllegalArgumentException("codeType 仅支持 QR 或 BARCODE");
}
// 1. 按业务唯一键 + 码类型查询
QrcodeRecordDO existed = qrcodeRecordMapper.selectOne(
new LambdaQueryWrapper<QrcodeRecordDO>()
.eq(QrcodeRecordDO::getBizType, bizType.getCode())
.eq(QrcodeRecordDO::getBizId, bizId)
.eq(QrcodeRecordDO::getBizCode, bizCode)
// .eq(QrcodeRecordDO::getCodeType, normalizedCodeType)
.eq(QrcodeRecordDO::getQrScene, qrScene)
.last("limit 1")
);
// 2. 组装内容
String content = "{\"type\":\"" + bizType.getCode()
+ "\",\"id\":" + bizId
+ (StrUtil.isNotBlank(bizCode) ? ",\"code\":\"" + bizCode + "\"" : "")
+ "}";
// 3. 生成图片(按类型)
byte[] pngBytes;
String objectDir;
String fileNameSuffix;
if (StrUtil.equals(normalizedCodeType, "BARCODE")) {
pngBytes = buildBarcodePng(content, 600, 180);
objectDir = "barcode";
fileNameSuffix = "_barcode.png";
} else {
pngBytes = buildQrPng(content, width, height);
objectDir = "qr";
fileNameSuffix = ".png";
}
// 4. 组织文件信息
String bucket = resolveBucket(bizType);
String objectName = bizType.getCode().toLowerCase() + "/" + objectDir + "/" + LocalDate.now() + "/" + bizId + ".png";
String fileName = bizType.getCode().toLowerCase() + "_" + StrUtil.blankToDefault(bizCode, String.valueOf(bizId)) + fileNameSuffix;
// 5. 如果已存在先删旧文件MinIO + infra_file
if (existed != null && StrUtil.isNotBlank(existed.getObjectName())) {
try {
Long fileId = fileApi.getFileByPath(existed.getObjectName());
if (fileId != null) {
fileApi.deleteFile(fileId);
}
} catch (Exception e) {
log.warn("删除旧二维码/条形码文件失败, qrcodeId={}, path={}", existed.getId(), existed.getObjectName(), e);
}
}
// 6. 上传新文件
Map<String, String> file = fileApi.createFile(fileName, objectName, pngBytes);
String fileUrl = file.get("fileUrl");
// 7. upsert 记录
QrcodeRecordDO record = new QrcodeRecordDO();
record.setBizType(bizType.getCode());
record.setBizId(bizId);
record.setBizCode(bizCode);
record.setCodeType(normalizedCodeType);
record.setQrScene(qrScene);
record.setQrContent(content);
record.setFileName(fileName);
record.setBucketName(bucket);
record.setObjectName(objectName);
record.setQrcodeFileUrl(fileUrl);
record.setMimeType("image/png");
record.setFileSize((long) pngBytes.length);
record.setStatus(1);
if (existed == null) {
qrcodeRecordMapper.insert(record);
} else {
record.setId(existed.getId());
qrcodeRecordMapper.updateById(record);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void generateOrRefresh(QrcodeBizTypeEnum bizType,
Long bizId,
String bizCode,
String scene,
CodeTypeEnum codeType) throws UnsupportedEncodingException {
if (codeType == null) {
log.info("codeType为空");
return;
}
if (codeType == CodeTypeEnum.BARCODE) {
generateOrRefreshBarcode(bizType, bizId, bizCode, scene);
} else {
generateOrRefresh(bizType, bizId, bizCode, scene);
}
}
}

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.common.dal.mysql.qrcoderecord.QrcodeRecordMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

@ -133,6 +133,10 @@ public interface ErrorCodeConstants {
// ========== ERP 产品 1-030-500-000 ==========
ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在");
ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_030_500_001, "产品({})未启用");
ErrorCode PRODUCT_CODE_EXISTS = new ErrorCode(1_030_500_002, "产品编码已存在");
ErrorCode PRODUCT_NAME_AND_STANDARD_EXISTS = new ErrorCode(1_030_500_003, "名称+规格已存在且不能重复");
ErrorCode PRODUCT_CODE_NOT_EXISTS = new ErrorCode(1_030_500_004, "产品编码不存在");
// ========== ERP 产品分类 1-030-501-000 ==========
ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_501_000, "产品分类不存在");

@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.autocode;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.enums.ErpBarcodeTypeEnum;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.beans.factory.annotation.Autowired;
@ -91,6 +93,16 @@ public class AutocodeRuleController {
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<AutocodeRuleDO> list = autocodeRuleService.getAutocodeRulePage(pageReqVO).getList();
List<AutocodeRuleRespVO> autocodeRuleRespVOS = BeanUtils.toBean(list, AutocodeRuleRespVO.class);
if (CollUtil.isNotEmpty(autocodeRuleRespVOS)) {
for (AutocodeRuleRespVO respVO : autocodeRuleRespVOS) {
if (respVO.getBarcodeType()!=null){
respVO.setBarcodeTypeName(ErpBarcodeTypeEnum.getDescByType(respVO.getBarcodeType()));
}
}
}
// 导出 Excel
ExcelUtils.write(response, "编码规则.xls", "数据", AutocodeRuleRespVO.class,
BeanUtils.toBean(list, AutocodeRuleRespVO.class));

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.erp.controller.admin.autocode.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* /
*/
@Getter
@AllArgsConstructor
public enum ErpBarcodeTypeEnum {
BARCODE(1, "条形码"),
QRCODE(2, "二维码"),
BOTH(3, "条形码+二维码");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpBarcodeTypeEnum::getType).toArray();
private final Integer type;
private final String desc;
/**
*
*/
public static String getDescByType(Integer type) {
if (type == null) {
return "";
}
for (ErpBarcodeTypeEnum value : values()) {
if (value.getType().equals(type)) {
return value.getDesc();
}
}
return "未知";
}
}

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.autocode.util;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.vo.AutocodeRecordSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.autocode.AutocodePartDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.autocode.AutocodeRecordDO;
@ -184,4 +185,14 @@ public class AutoCodeUtil {
return autoCode;
}
public CodeTypeEnum queryCodeType(String ruleCode) {
AutocodeRuleDO rule = iAutoCodeRuleService.getAutocodeRuleByRuleCode(ruleCode);
if (rule == null) {
return null;
}
return CodeTypeEnum.fromBarcodeType(rule.getBarcodeType());
}
}

@ -46,4 +46,7 @@ public class AutocodeRulePageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "码类型条形码-1 二维码-2", example = "")
private Integer barcodeType;
}

@ -27,6 +27,13 @@ public class AutocodeRuleRespVO {
@ExcelProperty("规则名称")
private String ruleName;
@Schema(description = "码类型条形码-1 二维码-2", example = "")
private Integer barcodeType;
@Schema(description = "码类型", example = "")
@ExcelProperty("码类型")
private String barcodeTypeName;
@Schema(description = "描述")
@ExcelProperty("描述")
private String ruleDesc;

@ -45,4 +45,8 @@ public class AutocodeRuleSaveReqVO {
@Schema(description = "编码规则组成列表")
private List<AutocodePartDO> autocodeParts;
@Schema(description = "码类型条形码-1 二维码-2", example = "")
private Integer barcodeType;
}

@ -27,6 +27,7 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
@ -143,7 +144,7 @@ public class MoldBrandController {
@PostMapping("/mold/create")
@Operation(summary = "创建模具")
@PreAuthorize("@ss.hasPermission('erp:mold-brand:create')")
public CommonResult<Long> createMold(@Valid @RequestBody MoldSaveReqVO createReqVO) {
public CommonResult<Long> createMold(@Valid @RequestBody MoldSaveReqVO createReqVO) throws UnsupportedEncodingException {
return success(moldBrandService.createMold(createReqVO));
}
@ -186,6 +187,15 @@ public class MoldBrandController {
ExcelUtils.write(response, "模具.xls", "数据", MoldRespVO.class, list);
}
@PostMapping("/regenerate-code")
public CommonResult<Boolean> regenerateCode(@RequestParam("id") Long id,
@RequestParam("code") String code) throws UnsupportedEncodingException {
moldBrandService.regenerateCode(id, code);
return success(true);
}
// ==================== 子表(模具产品) ====================
@GetMapping("/mold-brand-product/page")

@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
@ -15,6 +16,8 @@ import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
import cn.iocoder.yudao.module.erp.framework.bean.ProductTypeEnum;
import cn.iocoder.yudao.module.erp.service.product.ErpProductCategoryService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
@ -28,14 +31,17 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.MOLD_CODE_DUPLICATE;
@Tag(name = "管理后台 - ERP 产品")
@RestController
@ -51,18 +57,22 @@ public class ErpProductController {
@PostMapping("/create")
@Operation(summary = "创建产品")
@PreAuthorize("@ss.hasPermission('erp:product:create')")
public CommonResult<Long> createProduct(@Valid @RequestBody ProductSaveReqVO createReqVO) {
ErpProductPageReqVO productPageReqVO = new ErpProductPageReqVO();
productPageReqVO.setName(createReqVO.getName());
productPageReqVO.setStandard(createReqVO.getStandard());
if (productMapper.selectProductExist(productPageReqVO)) {
return error(400,"名称+规格不能重复");
}
productPageReqVO = new ErpProductPageReqVO();
productPageReqVO.setCode(createReqVO.getBarCode());
if (!productMapper.selectProductCodeExist(productPageReqVO).getList().isEmpty()) {
return error(400,"编码不能重复");
}
public CommonResult<Long> createProduct(@Valid @RequestBody ProductSaveReqVO createReqVO) throws UnsupportedEncodingException {
// ErpProductPageReqVO productPageReqVO = new ErpProductPageReqVO();
// productPageReqVO.setName(createReqVO.getName());
// productPageReqVO.setStandard(createReqVO.getStandard());
// if (productMapper.selectProductExist(productPageReqVO)) {
// return error(400,"名称+规格不能重复");
// }
// productPageReqVO = new ErpProductPageReqVO();
// productPageReqVO.setCode(createReqVO.getBarCode());
// if (!productMapper.selectProductCodeExist(productPageReqVO).getList().isEmpty()) {
// return error(400,"编码不能重复");
// }
return success(productService.createProduct(createReqVO));
}
@ -231,4 +241,12 @@ public class ErpProductController {
return success(productService.importProductList(list, updateSupport));
}
@PostMapping("/regenerate-code")
public CommonResult<Boolean> regenerateCode(@RequestParam("id") Long id,
@RequestParam("code") String code) throws UnsupportedEncodingException {
productService.regenerateCode(id, code);
return success(true);
// s
}
}

@ -83,4 +83,7 @@ public class ErpProductRespVO {
@Schema(description = "预警库存", example = "161.87")
@ExcelProperty("预警库存")
private BigDecimal safetyNumber;
@Schema(description = "二维码地址", example = "")
private String qrcodeUrl;
}

@ -19,7 +19,7 @@ public class ProductSaveReqVO {
private String name;
@Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "X110")
@NotEmpty(message = "产品条码不能为空")
// @NotEmpty(message = "产品条码不能为空")
private String barCode;
@Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161")

@ -70,4 +70,10 @@ public class AutocodeRuleDO extends BaseDO {
*/
private Boolean isEnable;
/**
* -1 -2
*
*/
private Integer barcodeType;
}

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.product;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -100,4 +101,10 @@ public class ErpProductDO extends BaseDO {
*
*/
private BigDecimal safetyNumber;
/**
*
*/
@TableField(exist = false)
private String qrcodeUrl;
}

@ -39,16 +39,18 @@ public interface ErpProductMapper extends BaseMapperX<ErpProductDO> {
.orderByAsc(ErpProductDO::getId));
}
default Boolean selectProductExist(ErpProductPageReqVO reqVO) {
LambdaQueryWrapperX<ErpProductDO> queryWrapper = (LambdaQueryWrapperX<ErpProductDO>) new LambdaQueryWrapperX<ErpProductDO>()
.orderByAsc(ErpProductDO::getId);
if (StringUtils.hasText(reqVO.getName()) && StringUtils.hasText(reqVO.getStandard())) {
// 组合查询name 和 standard 必须同时匹配
queryWrapper.eq(ErpProductDO::getName, reqVO.getName())
.eq(ErpProductDO::getStandard, reqVO.getStandard());
return !selectPage(reqVO, queryWrapper).getList().isEmpty();
default Boolean selectProductExist(ErpProductDO reqVO) {
if (!StringUtils.hasText(reqVO.getName()) || !StringUtils.hasText(reqVO.getStandard())) {
return false;
}
return false;
// 直接使用 count 查询
Long count = selectCount(new LambdaQueryWrapper<ErpProductDO>()
.eq(ErpProductDO::getName, reqVO.getName())
.eq(ErpProductDO::getStandard, reqVO.getStandard()));
return count > 0;
}
default Long selectCountByCategoryId(Long categoryId) {

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.erp.handler;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.handler.QrcodeBizHandler;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class ProductQrcodeBizHandler implements QrcodeBizHandler {
@Resource
private ErpProductMapper productMapper;
public String getBizType() {
return QrcodeBizTypeEnum.PRODUCT.getCode();
}
public boolean exists(Long id) { return productMapper.selectById(id) != null; }
public String buildDeepLink(Long id) {
// return "besure://mold/detail?id=" + id;
//TODO 替换成app连接
return "https://www.baidu.com";
}
public String buildH5Path(Long id) {
// return "/h5/mold/view?id=" + id;
//TODO 替换成app连接不存在页面
return "https://baike.baidu.com/item/%E6%98%9F%E5%BA%A7/8072715?fr=aladdin";
}
}

@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.mold.vo.MoldBrandTreeRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@ -96,7 +97,7 @@ public interface MoldBrandService {
* @param mold
* @return
*/
Long createMold(@Valid MoldSaveReqVO createReqVO);
Long createMold(@Valid MoldSaveReqVO createReqVO) throws UnsupportedEncodingException;
/**
*
@ -184,4 +185,6 @@ public interface MoldBrandService {
}
List<MoldBrandTreeRespVO> getMoldBrandTree();
void regenerateCode(Long id, String code) throws UnsupportedEncodingException;
}

@ -15,6 +15,10 @@ import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairDO;
import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairLineDO;
import cn.iocoder.yudao.module.common.dal.dataobject.moldticketresults.MoldTicketResultsDO;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.erp.controller.admin.mold.vo.MoldBrandTreeRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
@ -29,18 +33,23 @@ import cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.common.api.mold.enums.ErrorCodeConstants.FAILED_TO_REGENERATE;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
/**
@ -50,6 +59,7 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
*/
@Service
@Validated
@Slf4j
public class MoldBrandServiceImpl implements MoldBrandService {
@Resource
@ -66,6 +76,12 @@ public class MoldBrandServiceImpl implements MoldBrandService {
private ErpProductUnitService productUnitService;
@Resource
private ErpProductService productService;
@Resource
private QrcodeRecordService qrcodeService;
@Autowired
private AutoCodeUtil autoCodeUtil;
@Override
public Long createMoldBrand(MoldBrandSaveReqVO createReqVO) {
// 插入
@ -173,19 +189,48 @@ public class MoldBrandServiceImpl implements MoldBrandService {
});
}
@Override
public Long createMold(MoldSaveReqVO createReqVO) {
public Long createMold(MoldSaveReqVO createReqVO) throws UnsupportedEncodingException {
String Code = createReqVO.getCode();
if (StrUtil.isBlank(Code)) {
throw new ServiceException(ErrorCodeConstants.MOLD_CODE_EMPTY);
}
boolean exists = moldMapper.exists(
new LambdaQueryWrapperX<MoldDO>().eq(MoldDO::getCode, Code)
);
if (exists) {
throw new ServiceException(ErrorCodeConstants.MOLD_CODE_DUPLICATE);
}
// if (StrUtil.isBlank(Code)) {
// throw new ServiceException(ErrorCodeConstants.MOLD_CODE_EMPTY);
// }
// boolean exists = moldMapper.exists(
// new LambdaQueryWrapperX<MoldDO>().eq(MoldDO::getCode, Code)
// );
// if (exists) {
// throw new ServiceException(ErrorCodeConstants.MOLD_CODE_DUPLICATE);
// }
MoldDO mold = BeanUtils.toBean(createReqVO, MoldDO.class);
if (StringUtils.isBlank(Code)) {
mold.setCode(autoCodeUtil.genSerialCode("MOLD_CODE_GENERATE",null));
} else {
if (moldMapper.selectOne(Wrappers.<MoldDO>lambdaQuery().eq(MoldDO::getCode,Code)) != null) {
throw exception(MOLD_CODE_DUPLICATE);
}
}
moldMapper.insert(mold);
CodeTypeEnum codeType = autoCodeUtil.queryCodeType("MOLD_CODE_GENERATE");
if (codeType==null){
log.warn("[创建模具]未配置码类型跳过生产ruleCode={}","MOLD_CODE_GENERATE");
return mold.getId();
}
qrcodeService.generateOrRefresh(
QrcodeBizTypeEnum.MOLD,
mold.getId(),
mold.getCode(),
"DETAIL",
codeType
);
return mold.getId();
}
@ -201,6 +246,10 @@ public class MoldBrandServiceImpl implements MoldBrandService {
public void deleteMold(Long id) {
// 校验存在
validateMoldExists(id);
// 删除二维码/条形码
qrcodeService.deleteByBiz(QrcodeBizTypeEnum.MOLD, id);
// 删除
moldMapper.deleteById(id);
}
@ -255,7 +304,8 @@ public class MoldBrandServiceImpl implements MoldBrandService {
if(CollectionUtils.isNotEmpty(moldRepairDOMap)){
moldDO.setRepairList(moldRepairDOMap);
}
String qrcodeUrl = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.MOLD.getCode(),id,moldDO.getCode());
moldDO.setQrcodeUrl(qrcodeUrl);
return moldDO;
}
@Override
@ -353,6 +403,27 @@ public class MoldBrandServiceImpl implements MoldBrandService {
return buildMoldBrandTree(allMoldBrands);
}
@Override
public void regenerateCode(Long id, String code) throws UnsupportedEncodingException {
if(moldMapper.selectById(id)==null){
throw exception(MOLD_BRAND_PRODUCT_NOT_EXISTS);
}
if(StringUtils.isBlank(code)){
throw exception(MOLD_CODE_EMPTY);
}
CodeTypeEnum codeGenerate = autoCodeUtil.queryCodeType("MOLD_CODE_GENERATE");
//
qrcodeService.regenerateByCodeType(
QrcodeBizTypeEnum.MOLD,
id,
code,
"DETAIL",
codeGenerate.getCode()
);
}
/**
*
*/

@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@ -30,7 +31,7 @@ public interface ErpProductService {
* @param createReqVO
* @return
*/
Long createProduct(@Valid ProductSaveReqVO createReqVO);
Long createProduct(@Valid ProductSaveReqVO createReqVO) throws UnsupportedEncodingException;
/**
*
@ -134,4 +135,6 @@ public interface ErpProductService {
* @return
*/
ErpProductImportRespVO importProductList(List<ErpProductImportExcelVO> importProducts, boolean isUpdateSupport);
void regenerateCode(Long id, String code) throws UnsupportedEncodingException;
}

@ -8,6 +8,11 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductImportExcelVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductImportRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO;
@ -22,7 +27,10 @@ import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
@ -32,11 +40,13 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.ConstraintViolationException;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@ -49,6 +59,7 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
*/
@Service
@Validated
@Slf4j
public class ErpProductServiceImpl implements ErpProductService {
@Resource
@ -69,13 +80,34 @@ public class ErpProductServiceImpl implements ErpProductService {
@Lazy // 延迟注入
private ErpStockService erpStockService;
@Resource
private QrcodeRecordService qrcodeService;
@Autowired
private AutoCodeUtil autoCodeUtil;
@Override
public Long createProduct(ProductSaveReqVO createReqVO) {
public Long createProduct(ProductSaveReqVO createReqVO) throws UnsupportedEncodingException {
String code = createReqVO.getBarCode();
ErpProductDO product = BeanUtils.toBean(createReqVO, ErpProductDO.class);
if (productMapper.selectProductExist(product)) {
throw exception(PRODUCT_NAME_AND_STANDARD_EXISTS);
}
if (StringUtils.isBlank(code)) {
code = autoCodeUtil.genSerialCode("PRODUCT_CODE_GENERATE", null);
} else {
if (productMapper.selectOne(Wrappers.<ErpProductDO>lambdaQuery().eq(ErpProductDO::getBarCode,code)) != null) {
throw exception(PRODUCT_CODE_EXISTS);
}
}
// TODO 芋艿:校验分类
// 插入
ErpProductDO product = BeanUtils.toBean(createReqVO, ErpProductDO.class);
ErpProductCategoryDO productCategory = productCategoryMapper.selectById(product.getCategoryId());
Long id = productCategory.getParentId();
product.setSubCategoryName(productCategory.getName());
@ -85,7 +117,39 @@ public class ErpProductServiceImpl implements ErpProductService {
product.setCategoryId(id);
id = productCategory.getParentId();
}
product.setBarCode(productCategory.getCode()+ "-" + code);
productMapper.insert(product);
// 生成二维码
// try {
// qrcodeService.generateOrRefresh(
// QrcodeBizTypeEnum.PRODUCT, // bizType
// product.getId(), // bizId
// product.getBarCode(), // bizCode
// "DETAIL" // scene
// );
// } catch (Exception e) {
// log.error("[产品物料] 生成二维码失败id={}, code={}",
// product.getId(), product.getBarCode(), e);
// }
// 生成二维码
CodeTypeEnum codeType = autoCodeUtil.queryCodeType("PRODUCT_CODE_GENERATE");
if (codeType==null){
log.warn("[创建产品物料]未配置码类型跳过生产ruleCode={}","PRODUCT_CODE_GENERATE");
return product.getId();
}
qrcodeService.generateOrRefresh(
QrcodeBizTypeEnum.PRODUCT,
product.getId(),
product.getBarCode(),
"DETAIL",
codeType
);
// 返回
return product.getId();
}
@ -154,7 +218,11 @@ public class ErpProductServiceImpl implements ErpProductService {
@Override
public ErpProductDO getProduct(Long id) {
return productMapper.selectById(id);
ErpProductDO erpProductDO = productMapper.selectById(id);
String qrcodeUrl = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.PRODUCT.getCode(),id,erpProductDO.getBarCode());
erpProductDO.setQrcodeUrl(qrcodeUrl);
return erpProductDO ;
}
@Override
@ -324,6 +392,26 @@ public class ErpProductServiceImpl implements ErpProductService {
return respVO;
}
@Override
public void regenerateCode(Long id, String code) throws UnsupportedEncodingException {
if(productMapper.selectById(id)==null){
throw exception(PRODUCT_NOT_EXISTS);
}
if(StringUtils.isBlank(code)){
throw exception(PRODUCT_CODE_NOT_EXISTS);
}
CodeTypeEnum moldCodeGenerate = autoCodeUtil.queryCodeType("PRODUCT_CODE_GENERATE");
//s
qrcodeService.regenerateByCodeType(
QrcodeBizTypeEnum.PRODUCT,
id,
code,
"DETAIL",
moldCodeGenerate.getCode()
);
}
private ErpProductDO convertToProductDO(ErpProductImportExcelVO importProduct) {
ErpProductDO productDO = BeanUtils.toBean(importProduct, ErpProductDO.class);

@ -40,4 +40,7 @@ public interface FileApi {
*/
Map<String,String> createFile(String name, String path, byte[] content);
Long getFileByPath(String path);
void deleteFile(Long id) throws Exception;
}

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.infra.api.file;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.service.file.FileService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -24,4 +25,13 @@ public class FileApiImpl implements FileApi {
return fileService.createFile(name, path, content);
}
@Override
public Long getFileByPath(String path) {
return fileService.getFileByPath(path).getId();
}
@Override
public void deleteFile(Long id) throws Exception {
fileService.deleteFile(id);
}
}

@ -65,4 +65,7 @@ public interface FileService {
*/
FilePresignedUrlRespVO getFilePresignedUrl(String path) throws Exception;
FileDO getFileByPath(String path);
}

@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
@ -121,4 +122,16 @@ public class FileServiceImpl implements FileService {
object -> object.setConfigId(fileClient.getId()));
}
@Override
public FileDO getFileByPath(String path) {
if (StrUtil.isBlank(path)) {
return null;
}
return fileMapper.selectOne(
Wrappers.<FileDO>lambdaQuery()
.eq(FileDO::getPath, path)
.orderByDesc(FileDO::getId)
.last("limit 1")
); }
}

@ -53,7 +53,7 @@ public class DeviceSaveReqVO {
private Boolean isEnable;
@Schema(description = "关联设备模型", example = "1")
@NotNull(message = "关联设备模型ID不能为空")
// @NotNull(message = "关联设备模型ID不能为空")
private Long deviceModelId;
@Schema(description = "通讯协议", example = "OPCUA")

@ -26,15 +26,15 @@ public class DeviceModelAttributeRespVO {
private String attributeName;
@Schema(description = "采集点位类型编码", example = "1")
@ExcelProperty("采集点位类型编码")
@ExcelProperty("点位类型编码")
private String attributeTypeCode;
@Schema(description = "点位类型", example = "1")
@ExcelProperty("点位类型")
// @ExcelProperty("点位类型")
private String attributeType;
@Schema(description = "类型名称", example = "1")
@ExcelProperty("类型名称")
// @ExcelProperty("类型名称")
private String typeName;
@Schema(description = "数据类型", example = "2")
@ -61,11 +61,11 @@ public class DeviceModelAttributeRespVO {
private String remark;
@Schema(description = "采集设备模型id", requiredMode = Schema.RequiredMode.REQUIRED, example = "16848")
@ExcelProperty("采集设备模型id")
// @ExcelProperty("采集设备模型id")
private Long deviceModelId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
// @ExcelProperty("创建时间")
@ColumnWidth(20) // 设置此列的宽度为 20 个字符的宽度
private LocalDateTime createTime;

@ -154,13 +154,19 @@ public class DeviceServiceImpl implements DeviceService {
device.setTenantId("1");
deviceMapper.insert(device);
if (createReqVO.getDeviceModelId()!=null){
insertTemplatePoint(createReqVO, device);
}
return device;
}
private void insertTemplatePoint(DeviceSaveReqVO createReqVO, DeviceDO device) {
//新增模板点位
LambdaQueryWrapper<DeviceModelAttributeDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DeviceModelAttributeDO::getDeviceModelId,createReqVO.getDeviceModelId()).orderByDesc(DeviceModelAttributeDO::getId);
lambdaQueryWrapper.eq(DeviceModelAttributeDO::getDeviceModelId, createReqVO.getDeviceModelId()).orderByDesc(DeviceModelAttributeDO::getId);
List<DeviceModelAttributeDO> deviceModelAttributeDOS = deviceModelAttributeMapper.selectList(lambdaQueryWrapper);
if (deviceModelAttributeDOS.isEmpty()){
if (deviceModelAttributeDOS.isEmpty()) {
throw exception(DEVICE_MODEL_ATTRIBUTE_NOT_EXISTS);
}
@ -180,10 +186,8 @@ public class DeviceServiceImpl implements DeviceService {
// createTDengine(device.getId());
//新增规则点位
addNewRulePoints(createReqVO.getDeviceModelId(),device.getId());
tdengineService.createTdengineTable(device.getId(),contactModelList);
return device;
addNewRulePoints(createReqVO.getDeviceModelId(), device.getId());
tdengineService.createTdengineTable(device.getId(), contactModelList);
}
private void addNewRulePoints(Long deviceModelId,Long deviceId) {

@ -295,7 +295,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
// 不能为空
if (StringUtils.isBlank(code)) {
respVO.getFailureCodes().put(importAttribute.getAttributeCode(), "点位类型名称不能为空");
respVO.getFailureCodes().put(importAttribute.getAttributeCode(), "点位类型编码不能为空");
return;
}
// 必须存在于数据库类型列表中(防止乱填)

@ -144,14 +144,17 @@ public interface ErrorCodeConstants {
ErrorCode DEVICE_LEDGER_EXISTS = new ErrorCode(1002000010, "设备台账编码已存在");
ErrorCode SUBJECT_EXISTS = new ErrorCode(1002000010, "项目编码已存在");
ErrorCode TASK_MANAGEMENT_NOT_EXISTS = new ErrorCode(1002000011, "设备类型不存在");
ErrorCode TASK_CORN_NOT_EXISTS = new ErrorCode(1002000011, "设备corn表达式为空");
ErrorCode TASK_CORN_NOT_LE_HOUR = new ErrorCode(1002000011, "corn表达式不能小于一小时");
ErrorCode TASK_CORN_NOT_EXISTS = new ErrorCode(1002000012, "设备corn表达式为空");
ErrorCode TASK_CORN_NOT_LE_HOUR = new ErrorCode(1002000013, "corn表达式不能小于一小时");
ErrorCode DEVICE_LEDGER_CODE_NOT_EXISTS = new ErrorCode(1002000013, "设备台账编码不存在");
ErrorCode TICKET_MANAGEMENT_NOT_EXISTS = new ErrorCode(1002000012, "工单管理不存在");
ErrorCode TICKET_RESULTS_NOT_EXISTS = new ErrorCode(1002000013, "工单检验结果不存在");
ErrorCode TICKET_RESULTS_ID_NOT_NULL = new ErrorCode(1002000014, "工单检验结果Id不存在");
ErrorCode CRITICAL_COMPONENT_NOT_EXISTS = new ErrorCode(1002000015, "设备关键件不存在");
ErrorCode CRITICAL_COMPONENT_CODE_EXISTS = new ErrorCode(1002000015, "设备关键件编码已存在");
ErrorCode CRITICAL_COMPONENT_CODE_NOT_EXISTS = new ErrorCode(1002000015, "设备关键件编码不存在");
ErrorCode CRITICAL_COMPONENT_REFERENCES= new ErrorCode(1002000015, "存在设备关键件已被引用,请先删除引用");

@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@ -48,7 +49,7 @@ public class CriticalComponentController {
@PostMapping("/create")
@Operation(summary = "创建设备关键件")
@PreAuthorize("@ss.hasPermission('mes:critical-component:create')")
public CommonResult<Long> createCriticalComponent(@Valid @RequestBody CriticalComponentSaveReqVO createReqVO) {
public CommonResult<Long> createCriticalComponent(@Valid @RequestBody CriticalComponentSaveReqVO createReqVO) throws UnsupportedEncodingException {
return success(criticalComponentService.createCriticalComponent(createReqVO));
}
@ -170,4 +171,12 @@ public class CriticalComponentController {
return success(criticalComponentService.importCriticalComponentList(list, updateSupport));
}
@PostMapping("/regenerate-code")
public CommonResult<Boolean> regenerateCode(@RequestParam("id") Long id,
@RequestParam("code") String code) throws UnsupportedEncodingException {
criticalComponentService.regenerateCode(id, code);
return success(true);
}
}

@ -41,4 +41,7 @@ public class CriticalComponentRespVO {
@Schema(description = "数量", example = "2")
private Integer count;
@Schema(description = "二维码", example = "2")
private String qrcodeUrl;
}

@ -13,7 +13,7 @@ public class CriticalComponentSaveReqVO {
private Long id;
@Schema(description = "编码(唯一标识)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "编码(唯一标识)不能为空")
// @NotEmpty(message = "编码(唯一标识)不能为空")
private String code;
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")

@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.mes.controller.admin.deviceledger;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.mes.controller.admin.deviceledger.utils.ResumeNameUtils;
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanRespVO;
@ -22,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation;
import javax.validation.*;
import javax.servlet.http.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@ -60,11 +63,14 @@ public class DeviceLedgerController {
@Resource
private AdminUserApi adminUserApi;
@Resource
private QrcodeRecordService qrcodeService;
@PostMapping("/create")
@Operation(summary = "创建设备台账")
@PreAuthorize("@ss.hasPermission('mes:device-ledger:create')")
public CommonResult<Long> createDeviceLedger(@Valid @RequestBody DeviceLedgerSaveReqVO createReqVO) {
public CommonResult<Long> createDeviceLedger(@Valid @RequestBody DeviceLedgerSaveReqVO createReqVO) throws UnsupportedEncodingException {
return success(deviceLedgerService.createDeviceLedger(createReqVO));
}
@ -99,6 +105,10 @@ public class DeviceLedgerController {
public CommonResult<DeviceLedgerRespVO> getDeviceLedger(@RequestParam("id") Long id) {
DeviceLedgerDO deviceLedger = deviceLedgerService.getDeviceLedger(id);
DeviceLedgerRespVO respVO = BeanUtils.toBean(deviceLedger, DeviceLedgerRespVO.class);
String qrcodeUrl = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.EQUIPMENT.getCode(),id,respVO.getDeviceCode());
respVO.setQrcodeUrl(qrcodeUrl);
respVO.setCreatorName(adminUserApi.getUser(Long.valueOf(deviceLedger.getCreator())).getNickname());
if (StringUtils.isNotBlank(respVO.getDeviceManager())) {
String[] userIds = respVO.getDeviceManager().split(",");
@ -250,4 +260,19 @@ public class DeviceLedgerController {
// 导出 Excel
ExcelUtils.write(response, fileName, "数据", MoldVO.class,list);
}
@PostMapping("/regenerate-code")
public CommonResult<Boolean> regenerateCode(@RequestParam("id") Long id,
@RequestParam("code") String code) throws UnsupportedEncodingException {
deviceLedgerService.regenerateCode(id, code);
return success(true);
}
}

@ -151,4 +151,7 @@ public class DeviceLedgerRespVO extends BaseDO {
@Schema(description = "关联采集设备id")
private Long dvId;
@Schema(description = "二维码")
private String qrcodeUrl;
}

@ -47,5 +47,10 @@ public class CriticalComponentDO extends BaseDO {
*
*/
private Integer count;
/**
*
*/
@TableField(exist = false)
private String qrcodeUrl;
}

@ -175,4 +175,9 @@ public class DeviceLedgerDO extends BaseDO {
*/
private Long dvId;
/**
*
*/
@TableField(exist = false)
private String qrcodeUrl;
}

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.mes.handler;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.handler.QrcodeBizHandler;
import cn.iocoder.yudao.module.mes.dal.mysql.criticalcomponent.CriticalComponentMapper;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class CriticalComponentQrcodeBizHandler implements QrcodeBizHandler {
@Resource
private CriticalComponentMapper criticalComponentMapper;
public String getBizType() {
return QrcodeBizTypeEnum.KEY_PART.getCode();
}
public boolean exists(Long id) { return criticalComponentMapper.selectById(id) != null; }
public String buildDeepLink(Long id) {
// return "besure://mold/detail?id=" + id;
//TODO 替换成app连接
return "https://www.baidu.com";
}
public String buildH5Path(Long id) {
// return "/h5/mold/view?id=" + id;
//TODO 替换成app连接不存在页面
return "https://baike.baidu.com/item/%E6%98%9F%E5%BA%A7/8072715?fr=aladdin";
}
}

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.mes.handler;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.handler.QrcodeBizHandler;
import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class DeviceLedgerQrcodeBizHandler implements QrcodeBizHandler {
@Resource
private DeviceLedgerMapper deviceLedgerMapper;
public String getBizType() {
return QrcodeBizTypeEnum.EQUIPMENT.getCode();
}
public boolean exists(Long id) { return deviceLedgerMapper.selectById(id) != null; }
public String buildDeepLink(Long id) {
// return "besure://mold/detail?id=" + id;
//TODO 替换成app连接
return "https://www.baidu.com";
}
public String buildH5Path(Long id) {
// return "/h5/mold/view?id=" + id;
//TODO 替换成app连接不存在页面
return "https://baike.baidu.com/item/%E6%98%9F%E5%BA%A7/8072715?fr=aladdin";
}
}

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.mes.handler;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.handler.QrcodeBizHandler;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class MoldQrcodeBizHandler implements QrcodeBizHandler {
@Resource
private MoldMapper moldMapper;
public String getBizType() {
return QrcodeBizTypeEnum.MOLD.getCode();
}
public boolean exists(Long id) { return moldMapper.selectById(id) != null; }
public String buildDeepLink(Long id) {
// return "besure://mold/detail?id=" + id;
//TODO 替换成app连接
return "https://www.baidu.com";
}
public String buildH5Path(Long id) {
// return "/h5/mold/view?id=" + id;
//TODO 替换成app连接不存在页面
return "https://baike.baidu.com/item/%E6%98%9F%E5%BA%A7/8072715?fr=aladdin";
}
}

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.mes.service.criticalcomponent;
import java.io.UnsupportedEncodingException;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.mes.controller.admin.criticalcomponent.vo.*;
@ -20,7 +21,7 @@ public interface CriticalComponentService {
* @param createReqVO
* @return
*/
Long createCriticalComponent(@Valid CriticalComponentSaveReqVO createReqVO);
Long createCriticalComponent(@Valid CriticalComponentSaveReqVO createReqVO) throws UnsupportedEncodingException;
/**
*
@ -61,4 +62,5 @@ public interface CriticalComponentService {
*/
CriticalComponentImportRespVO importCriticalComponentList(List<CriticalComponentImportExcelVO> importComponents, boolean isUpdateSupport);
void regenerateCode(Long id, String code) throws UnsupportedEncodingException;
}

@ -1,5 +1,10 @@
package cn.iocoder.yudao.module.mes.service.criticalcomponent;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceModelAttributeDO;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
@ -11,6 +16,8 @@ import cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.ConstraintViolationException;
@ -18,6 +25,7 @@ import javax.validation.ConstraintViolationException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@ -30,6 +38,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.mes.dal.mysql.criticalcomponent.CriticalComponentMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_MODEL_ATTRIBUTE_POTIN_CODE_EXISTS;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
@ -40,6 +49,7 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
*/
@Service
@Validated
@Slf4j
public class CriticalComponentServiceImpl implements CriticalComponentService {
@Resource
@ -51,24 +61,49 @@ public class CriticalComponentServiceImpl implements CriticalComponentService {
@Resource
private RepairTemsMapper repairTemsMapper;
@Resource
private QrcodeRecordService qrcodeService;
@Autowired
private AutoCodeUtil autoCodeUtil;
@Override
public Long createCriticalComponent(CriticalComponentSaveReqVO createReqVO) {
public Long createCriticalComponent(CriticalComponentSaveReqVO createReqVO) throws UnsupportedEncodingException {
//判断编码是否唯一
boolean exists = criticalComponentMapper.exists(
Wrappers.<CriticalComponentDO>lambdaQuery()
.eq(CriticalComponentDO::getCode, createReqVO.getCode()));
// boolean exists = criticalComponentMapper.exists(
// Wrappers.<CriticalComponentDO>lambdaQuery()
// .eq(CriticalComponentDO::getCode, createReqVO.getCode()));
//
// if (exists) {
// throw exception(CRITICAL_COMPONENT_CODE_EXISTS);
// }
CriticalComponentDO criticalComponent = BeanUtils.toBean(createReqVO, CriticalComponentDO.class);
if (exists) {
throw exception(CRITICAL_COMPONENT_CODE_EXISTS);
//判断编码是否唯一
if (StringUtils.isBlank(createReqVO.getCode())) {
criticalComponent.setCode(autoCodeUtil.genSerialCode("COMPONENT_CODE_GENERATE",null));
} else {
if (criticalComponentMapper.selectOne(Wrappers.<CriticalComponentDO>lambdaQuery().eq(CriticalComponentDO::getCode,createReqVO.getCode())) != null) {
throw exception(CRITICAL_COMPONENT_CODE_EXISTS);
}
}
// 插入
CriticalComponentDO criticalComponent = BeanUtils.toBean(createReqVO, CriticalComponentDO.class);
criticalComponentMapper.insert(criticalComponent);
CodeTypeEnum codeType = autoCodeUtil.queryCodeType("COMPONENT_CODE_GENERATE");
if (codeType==null){
log.warn("[创建设备关键件]未配置码类型跳过生产ruleCode={}","COMPONENT_CODE_GENERATE");
return criticalComponent.getId();
}
qrcodeService.generateOrRefresh(
QrcodeBizTypeEnum.KEY_PART,
criticalComponent.getId(),
criticalComponent.getCode(),
"DETAIL",
codeType
);
// 返回
return criticalComponent.getId();
}
@ -162,7 +197,11 @@ public class CriticalComponentServiceImpl implements CriticalComponentService {
@Override
public CriticalComponentDO getCriticalComponent(Long id) {
return criticalComponentMapper.selectById(id);
CriticalComponentDO criticalComponentDO = criticalComponentMapper.selectById(id);
String qrcodeUrl = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.KEY_PART.getCode(),id,criticalComponentDO.getCode());
criticalComponentDO.setQrcodeUrl(qrcodeUrl);
return criticalComponentDO;
}
@Override
@ -278,4 +317,25 @@ public class CriticalComponentServiceImpl implements CriticalComponentService {
return respVO;
}
@Override
public void regenerateCode(Long id, String code) throws UnsupportedEncodingException {
if(criticalComponentMapper.selectById(id)==null){
throw exception(CRITICAL_COMPONENT_NOT_EXISTS);
}
if(StringUtils.isBlank(code)){
throw exception(CRITICAL_COMPONENT_CODE_NOT_EXISTS);
}
CodeTypeEnum codeGenerate = autoCodeUtil.queryCodeType("COMPONENT_CODE_GENERATE");
qrcodeService.regenerateByCodeType(
QrcodeBizTypeEnum.KEY_PART,
id,
code,
"DETAIL",
codeGenerate.getCode()
);
}
}

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.mes.service.deviceledger;
import java.io.UnsupportedEncodingException;
import java.util.*;
import javax.validation.*;
@ -25,7 +26,7 @@ public interface DeviceLedgerService {
* @param createReqVO
* @return
*/
Long createDeviceLedger(@Valid DeviceLedgerSaveReqVO createReqVO);
Long createDeviceLedger(@Valid DeviceLedgerSaveReqVO createReqVO) throws UnsupportedEncodingException;
/**
*
@ -80,4 +81,6 @@ public interface DeviceLedgerService {
List<ErpProductVO> exportSpareBased(Long id);
List<MoldVO> exportMold(Long id);
void regenerateCode(Long id, String code) throws UnsupportedEncodingException;
}

@ -2,6 +2,10 @@ package cn.iocoder.yudao.module.mes.service.deviceledger;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.erp.controller.admin.mold.vo.MoldRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO;
@ -31,11 +35,14 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;
@ -48,6 +55,7 @@ import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
/**
@ -57,6 +65,7 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
*/
@Service
@Validated
@Slf4j
public class DeviceLedgerServiceImpl implements DeviceLedgerService {
@Resource
@ -90,13 +99,27 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService {
@Resource
private DeviceService deviceService;
@Resource
private QrcodeRecordService qrcodeService;
@Autowired
private AutoCodeUtil autoCodeUtil;
@Override
public Long createDeviceLedger(DeviceLedgerSaveReqVO createReqVO) {
public Long createDeviceLedger(DeviceLedgerSaveReqVO createReqVO) throws UnsupportedEncodingException {
DeviceLedgerDO deviceLedger = BeanUtils.toBean(createReqVO, DeviceLedgerDO.class);
//验证是否唯一编码
validateCodeOnly(createReqVO.getDeviceCode());
// 插入
DeviceLedgerDO deviceLedger = BeanUtils.toBean(createReqVO, DeviceLedgerDO.class);
// validateCodeOnly(createReqVO.getDeviceCode());
if (StringUtils.isBlank(createReqVO.getDeviceCode())) {
deviceLedger.setDeviceCode(autoCodeUtil.genSerialCode("DEVICE_CODE_GENERATE",null));
} else {
if (deviceLedgerMapper.selectOne(Wrappers.<DeviceLedgerDO>lambdaQuery().eq(DeviceLedgerDO::getDeviceCode,createReqVO.getDeviceCode())) != null) {
throw exception(DEVICE_LEDGER_EXISTS);
}
}
// 创建台账
deviceLedgerMapper.insert(deviceLedger);
@ -107,6 +130,23 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService {
// deviceRespVO.setOrg(Long.valueOf(deviceLedger.getWorkshop()));
// deviceService.updateDevice(BeanUtils.toBean(deviceRespVO, DeviceSaveReqVO.class));
// }
// 生成二维码
CodeTypeEnum codeType = autoCodeUtil.queryCodeType("DEVICE_CODE_GENERATE");
if (codeType==null){
log.warn("[创建设备台账]未配置码类型跳过生产ruleCode={}","DEVICE_CODE_GENERATE");
return deviceLedger.getId();
}
qrcodeService.generateOrRefresh(
QrcodeBizTypeEnum.EQUIPMENT,
deviceLedger.getId(),
deviceLedger.getDeviceCode(),
"DETAIL",
codeType
);
// 返回
return deviceLedger.getId();
}
@ -335,6 +375,25 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService {
return BeanUtils.toBean(moldList, MoldVO.class);
}
@Override
public void regenerateCode(Long id, String code) throws UnsupportedEncodingException {
if(deviceLedgerMapper.selectById(id)==null){
throw exception(DEVICE_LEDGER_NOT_EXISTS);
}
if(StringUtils.isBlank(code)){
throw exception(DEVICE_LEDGER_CODE_NOT_EXISTS);
}
CodeTypeEnum codeGenerate = autoCodeUtil.queryCodeType("DEVICE_CODE_GENERATE");
//s
qrcodeService.regenerateByCodeType(
QrcodeBizTypeEnum.EQUIPMENT,
id,
code,
"DETAIL",
codeGenerate.getCode()
);
}
}

@ -77,11 +77,11 @@ spring:
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 47.106.185.127 # 地址
port: 6379 # 端口
host: ngsk.tech # 地址
port: 36378 # 端口
database: 0 # 数据库索引
#password: bkcaydy8ydhZZnS2 # 密码,建议生产环境开启
password: BstPwd258
password: ngsk0809
--- #################### 定时任务相关配置 ####################
@ -235,6 +235,22 @@ yudao:
demo: false # 关闭演示模式
tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
qrcode:
scan-base-url: http://192.168.5.167:48081/admin-api/qrcode/record/scan/resolve-id
transit-url: http://10.10.10.20:8080/h5/qrcode/transit
fail-url: https://chat.baidu.com/search?extParams=%7B%22enter_type%22%3A%22home_operate%22%7D&isShowHello=1
width: 300
height: 300
default-bucket: common-qrcode
buckets:
mold: mold-qrcode
product: product-qrcode
equipment: equipment-qrcode
part: part-qrcode
spare: spare-qrcode
work-order: workorder-qrcode
justauth:
enabled: true
type:

@ -264,6 +264,9 @@ yudao:
- /admin-api/mp/open/** # 微信公众号开放平台,微信回调接口,无法携带租户编号
- /admin-api/iot/mqtt-server/**
- /admin-api/home/info/**
- /admin-api/qrcode/record/scan/resolve-id
# - /admin-api/qrcode/record/scan # 扫描二维码
ignore-tables:
- system_tenant
- system_tenant_package

Loading…
Cancel
Save