feat: license申请、生成和下载功能

This commit is contained in:
caiyuchao
2025-07-18 16:31:34 +08:00
parent 5140d81045
commit 8af90ae549
8 changed files with 113 additions and 0 deletions

View File

@@ -66,6 +66,14 @@ public class LicenseController {
return success(true);
}
@GetMapping("/generate")
@Operation(summary = "生成License")
@PreAuthorize("@ss.hasPermission('license:license:generate')")
public CommonResult<String> generate(@RequestParam("id") Long id) {
String url = licenseService.generate(id);
return success(url);
}
@DeleteMapping("/delete")
@Operation(summary = "删除License")
@Parameter(name = "id", description = "编号", required = true)

View File

@@ -43,6 +43,9 @@ public class LicensePageReqVO extends PageParam {
@Schema(description = "激活码")
private String activationCode;
@Schema(description = "文件URL")
private String fileUrl;
@Schema(description = "License内容")
private String licenseContent;

View File

@@ -66,6 +66,10 @@ public class LicenseRespVO implements VO {
@ExcelProperty("激活码")
private String activationCode;
@Schema(description = "文件URL")
@ExcelProperty("文件URL")
private String fileUrl;
@Schema(description = "License内容")
@ExcelProperty("License内容")
private String licenseContent;

View File

@@ -42,6 +42,9 @@ public class LicenseSaveReqVO {
@Schema(description = "激活码")
private String activationCode;
@Schema(description = "文件URL")
private String fileUrl;
@Schema(description = "License内容")
private String licenseContent;

View File

@@ -71,6 +71,10 @@ public class LicenseDO extends BaseDO {
* 激活码
*/
private String activationCode;
/**
* 文件URL
*/
private String fileUrl;
/**
* License内容
*/

View File

@@ -35,6 +35,14 @@ public interface LicenseService {
*/
void applyLicense(@Valid LicenseSaveReqVO updateReqVO);
/**
* 生成License
*
* @param id license ID
* @return 文件路径
*/
String generate(Long id);
/**
* 删除License
*

View File

@@ -1,19 +1,35 @@
package org.agt.module.license.service.license;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import org.agt.framework.common.pojo.PageResult;
import org.agt.framework.common.util.object.BeanUtils;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.framework.web.core.util.WebFrameworkUtils;
import org.agt.module.infra.api.file.FileApi;
import org.agt.module.license.controller.admin.license.vo.LicensePageReqVO;
import org.agt.module.license.controller.admin.license.vo.LicenseSaveReqVO;
import org.agt.module.license.dal.dataobject.customer.CustomerDO;
import org.agt.module.license.dal.dataobject.license.LicenseDO;
import org.agt.module.license.dal.dataobject.project.ProjectDO;
import org.agt.module.license.dal.mysql.customer.CustomerMapper;
import org.agt.module.license.dal.mysql.license.LicenseMapper;
import org.agt.module.license.dal.mysql.project.ProjectMapper;
import org.agt.module.license.enums.LicenseStatusEnum;
import org.agt.module.system.api.mail.MailSendApi;
import org.agt.module.system.api.mail.dto.MailSendSingleToUserReqDTO;
import org.agt.module.system.api.notify.NotifyMessageSendApi;
import org.agt.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_NOT_EXISTS;
@@ -31,6 +47,21 @@ public class LicenseServiceImpl implements LicenseService {
@Resource
private LicenseMapper licenseMapper;
@Resource
private CustomerMapper customerMapper;
@Resource
private ProjectMapper projectMapper;
@Resource
private FileApi fileApi;
@Resource
private MailSendApi mailSendApi;
@Resource
private NotifyMessageSendApi notifySendApi;
@Override
public Long createLicense(LicenseSaveReqVO createReqVO) {
// 校验项目Sn是否唯一
@@ -64,6 +95,51 @@ public class LicenseServiceImpl implements LicenseService {
updateReqVO.setApplicant(WebFrameworkUtils.getLoginUserId());
updateReqVO.setApplicationTime(LocalDateTime.now());
updateLicense(updateReqVO);
// 发送邮件
// 1. 准备参数
Long userId = updateReqVO.getApprover();
String templateCode = "license_apply"; // 邮件模版,记得在【邮箱管理】中配置噢
Map<String, Object> templateParams = new HashMap<>();
CustomerDO customerDO = customerMapper.selectById(updateReqVO.getCustomerId());
ProjectDO projectDO = projectMapper.selectById(updateReqVO.getProjectId());
templateParams.put("customer", customerDO.getName());
templateParams.put("project", projectDO.getName());
templateParams.put("sn", updateReqVO.getSerialNo());
templateParams.put("url", "http://192.168.9.50/license/generate?id=" + updateReqVO.getId());
// 2. 发送邮件
mailSendApi.sendSingleMailToAdmin(new MailSendSingleToUserReqDTO()
.setUserId(userId).setTemplateCode(templateCode).setTemplateParams(templateParams));
// 发送站内信
notifySendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO()
.setUserId(userId).setTemplateCode(templateCode).setTemplateParams(templateParams));
}
@Override
public String generate(Long id) {
LicenseDO licenseDO = licenseMapper.selectById(id);
List<Integer> neList = licenseDO.getNeList();
List<String> neLabels = new ArrayList<>();
for (Integer ne : neList) {
String label = DictFrameworkUtils.parseDictDataLabel("lic_ne_list", ne.toString());
neLabels.add(label);
}
String neListStr = StrUtil.join("_", neLabels);
if (StrUtil.isNotBlank(neListStr)) {
neListStr = neListStr + "_";
}
String fileName = neListStr + licenseDO.getSerialNo() + "_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+ "_system.ini";
// 上传到文件服务
byte[] fileContent = ResourceUtil.readBytes("file/MME_13750602_2024-08-02_system.ini");
String fileURL = fileApi.createFile(fileContent, fileName);
licenseDO.setFileUrl(fileURL);
licenseDO.setStatus(LicenseStatusEnum.COMPLETED.getCode());
licenseMapper.updateById(licenseDO);
return fileURL;
}
@Override

View File

@@ -0,0 +1,7 @@
[pytest]
addopts = --verbose
# Pytest requires that test files have unique names, because pytest imports
# them as top-level modules. It is silly to prefix or suffix a test file with
# the directory name that contains it. Use __init__.py for all test files.
python_files = __init__.py