diff --git a/pom.xml b/pom.xml
index 58ebe62a..574bf741 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,6 +71,12 @@
1.8.2
+
+ com.microsoft.playwright
+ playwright
+ 1.40.0
+
+
com.aliyun.oss
aliyun-sdk-oss
diff --git a/src/main/java/cn/lihongjie/coal/file/service/FileService.java b/src/main/java/cn/lihongjie/coal/file/service/FileService.java
index a0eb25a2..15a6422e 100644
--- a/src/main/java/cn/lihongjie/coal/file/service/FileService.java
+++ b/src/main/java/cn/lihongjie/coal/file/service/FileService.java
@@ -130,25 +130,65 @@ public class FileService extends BaseService {
}
String objectKey = fileEntity.getDirectory() + "/" + fileEntity.getObjectId();
- String objectUrl = "";
- // PutObjectResult putObjectResult =
- // obsClient.putObject(
- // hwCloudProperty.getObs().getBucketName(),
- // objectKey,
- // file.getInputStream());
- //
- // if (putObjectResult.getStatusCode() != 200) {
- // throw new BizException("上传文件失败 %s".formatted(putObjectResult.toString()));
- // }
- // objectUrl = putObjectResult.getObjectUrl();
+ fileEntity.setPublicUrl(uploadToOSS(objectKey, file.getInputStream()));
+
+ this.save(fileEntity);
+
+ return getById(fileEntity.getId());
+ }
+
+ @SneakyThrows
+ public FileDto upload(
+ InputStream file,
+ String name,
+ String dir,
+ String sortKey,
+ String code,
+ String remarks) {
+ FileEntity fileEntity = new FileEntity();
+ fileEntity.setFileName(name);
+ fileEntity.setFileSize(Long.valueOf(file.available()));
+ fileEntity.setCode(code);
+ fileEntity.setRemarks(remarks);
+ try {
+
+ fileEntity.setSortKey(Integer.parseInt(sortKey));
+ } catch (Exception e) {
+
+ fileEntity.setSortKey(1);
+ }
+ fileEntity.setDirectory(
+ "%s/%s/%s"
+ .formatted(
+ activateProfile,
+ Ctx.currentUser().getOrganizationId(),
+ StringUtils.defaultIfBlank(dir, "public")));
+ InputStream inputStream = file;
+ fileEntity.setObjectId(
+ UUID.randomUUID() + "." + FilenameUtils.getExtension(name.replace(":", "_")));
+ try (inputStream) {
+ fileEntity.setMimeType(tika.detect(inputStream));
+ }
+
+ String objectKey = fileEntity.getDirectory() + "/" + fileEntity.getObjectId();
+
+ fileEntity.setPublicUrl(uploadToOSS(objectKey, file));
+
+ this.save(fileEntity);
+
+ return getById(fileEntity.getId());
+ }
+
+ private String uploadToOSS(String objectKey, InputStream inputStream) {
+ String objectUrl;
try {
com.aliyun.oss.model.PutObjectResult objectResult =
ossClient.putObject(
aliyunProperty.getOSS().getBucketName(),
objectKey,
- file.getInputStream());
+ inputStream);
} catch (Exception e) {
log.warn("上传文件失败", e);
@@ -171,11 +211,6 @@ public class FileService extends BaseService {
aliyunProperty.getOSS().getBucketName(),
ossRegion.getEndpoint(),
objectKey);
-
- fileEntity.setPublicUrl(objectUrl);
-
- this.save(fileEntity);
-
- return getById(fileEntity.getId());
+ return objectUrl;
}
}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/controller/PdfGeneratorController.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/controller/PdfGeneratorController.java
new file mode 100644
index 00000000..20e1fc29
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/controller/PdfGeneratorController.java
@@ -0,0 +1,61 @@
+package cn.lihongjie.coal.pdfGenerator.controller;
+
+import cn.lihongjie.coal.annotation.OrgScope;
+import cn.lihongjie.coal.annotation.SysLog;
+import cn.lihongjie.coal.base.dto.CommonQuery;
+import cn.lihongjie.coal.base.dto.IdRequest;
+import cn.lihongjie.coal.pdfGenerator.dto.CreatePdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.dto.GeneratePdfDto;
+import cn.lihongjie.coal.pdfGenerator.dto.PdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.dto.UpdatePdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.service.PdfGeneratorService;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/pdfGenerator")
+@SysLog(module = "Pdf生成器")
+@Slf4j
+@OrgScope
+public class PdfGeneratorController {
+ @Autowired private PdfGeneratorService service;
+
+ @PostMapping("/create")
+ public PdfGeneratorDto create(@RequestBody CreatePdfGeneratorDto request) {
+ return this.service.create(request);
+ }
+
+ @PostMapping("/update")
+ public PdfGeneratorDto update(@RequestBody UpdatePdfGeneratorDto request) {
+ return this.service.update(request);
+ }
+
+ @PostMapping("/delete")
+ public Object delete(@RequestBody IdRequest request) {
+ this.service.delete(request);
+ return true;
+ }
+
+ @PostMapping("/getById")
+ public PdfGeneratorDto getById(@RequestBody IdRequest request) {
+ return this.service.getById(request.getId());
+ }
+
+
+ @PostMapping("/generate")
+ public PdfGeneratorDto generate(@RequestBody GeneratePdfDto request) {
+ return this.service.generate(request);
+ }
+
+ @PostMapping("/list")
+ public Page list(@RequestBody CommonQuery request) {
+ return this.service.list(request);
+ }
+}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/CreatePdfGeneratorDto.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/CreatePdfGeneratorDto.java
new file mode 100644
index 00000000..c3ab8529
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/CreatePdfGeneratorDto.java
@@ -0,0 +1,13 @@
+package cn.lihongjie.coal.pdfGenerator.dto;
+
+import cn.lihongjie.coal.base.dto.OrgCommonDto;
+
+import lombok.Data;
+
+@Data
+public class CreatePdfGeneratorDto extends OrgCommonDto {
+
+
+
+
+}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/GeneratePdfDto.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/GeneratePdfDto.java
new file mode 100644
index 00000000..5bc118e4
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/GeneratePdfDto.java
@@ -0,0 +1,15 @@
+package cn.lihongjie.coal.pdfGenerator.dto;
+
+import cn.lihongjie.coal.base.dto.OrgCommonDto;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import lombok.Data;
+
+@Data
+public class GeneratePdfDto extends OrgCommonDto {
+ private String htmlUrl;
+ private String htmlText;
+
+ private ObjectNode options;
+}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/PdfGeneratorDto.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/PdfGeneratorDto.java
new file mode 100644
index 00000000..692c71c3
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/PdfGeneratorDto.java
@@ -0,0 +1,28 @@
+package cn.lihongjie.coal.pdfGenerator.dto;
+
+import cn.lihongjie.coal.base.dto.OrgCommonDto;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class PdfGeneratorDto extends OrgCommonDto {
+
+
+ private String htmlUrl;
+ private String htmlText;
+
+
+ private String pdfUrl;
+
+
+ private LocalDateTime startTime;
+ private LocalDateTime endTime;
+
+ private Long duration;
+
+
+ private String options;
+
+}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/UpdatePdfGeneratorDto.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/UpdatePdfGeneratorDto.java
new file mode 100644
index 00000000..a2cc6d21
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/dto/UpdatePdfGeneratorDto.java
@@ -0,0 +1,8 @@
+package cn.lihongjie.coal.pdfGenerator.dto;
+
+import cn.lihongjie.coal.base.dto.OrgCommonDto;
+
+import lombok.Data;
+
+@Data
+public class UpdatePdfGeneratorDto extends OrgCommonDto {}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/entity/PdfGeneratorEntity.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/entity/PdfGeneratorEntity.java
new file mode 100644
index 00000000..521903b7
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/entity/PdfGeneratorEntity.java
@@ -0,0 +1,46 @@
+package cn.lihongjie.coal.pdfGenerator.entity;
+
+import cn.lihongjie.coal.base.entity.OrgCommonEntity;
+
+import jakarta.persistence.Entity;
+
+import lombok.Data;
+
+import org.hibernate.annotations.Comment;
+import org.hibernate.annotations.Formula;
+
+import java.time.LocalDateTime;
+
+@Data
+@Entity
+public class PdfGeneratorEntity extends OrgCommonEntity {
+
+
+
+ private String htmlUrl;
+ private String htmlText;
+
+
+ private String pdfUrl;
+
+
+ private LocalDateTime startTime;
+ private LocalDateTime endTime;
+
+ private Long duration;
+
+
+ private String options;
+
+ @Comment("生成状态")
+ private String execStatus;
+
+ @Formula(
+ "(select i.name\n"
+ + "from t_dictionary d,\n"
+ + " t_dictionary_item i\n"
+ + "where d.id = i.dictionary_id\n"
+ + " and d.code = 'common.execStatus'\n"
+ + " and i.code = exec_status)")
+ private String execStatusName;
+}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/mapper/PdfGeneratorMapper.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/mapper/PdfGeneratorMapper.java
new file mode 100644
index 00000000..e85d1c1e
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/mapper/PdfGeneratorMapper.java
@@ -0,0 +1,25 @@
+package cn.lihongjie.coal.pdfGenerator.mapper;
+
+import cn.lihongjie.coal.base.mapper.BaseMapper;
+import cn.lihongjie.coal.base.mapper.CommonMapper;
+import cn.lihongjie.coal.pdfGenerator.dto.CreatePdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.dto.GeneratePdfDto;
+import cn.lihongjie.coal.pdfGenerator.dto.PdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.dto.UpdatePdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.entity.PdfGeneratorEntity;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.control.DeepClone;
+
+@Mapper(
+ componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING,
+ uses = {CommonMapper.class},
+ mappingControl = DeepClone.class)
+public interface PdfGeneratorMapper
+ extends BaseMapper<
+ PdfGeneratorEntity,
+ PdfGeneratorDto,
+ CreatePdfGeneratorDto,
+ UpdatePdfGeneratorDto> {
+ PdfGeneratorEntity toEntity(GeneratePdfDto request);
+}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/repository/PdfGeneratorRepository.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/repository/PdfGeneratorRepository.java
new file mode 100644
index 00000000..d0ec3ced
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/repository/PdfGeneratorRepository.java
@@ -0,0 +1,9 @@
+package cn.lihongjie.coal.pdfGenerator.repository;
+
+import cn.lihongjie.coal.base.dao.BaseRepository;
+import cn.lihongjie.coal.pdfGenerator.entity.PdfGeneratorEntity;
+
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PdfGeneratorRepository extends BaseRepository {}
diff --git a/src/main/java/cn/lihongjie/coal/pdfGenerator/service/PdfGeneratorService.java b/src/main/java/cn/lihongjie/coal/pdfGenerator/service/PdfGeneratorService.java
new file mode 100644
index 00000000..ea2714ac
--- /dev/null
+++ b/src/main/java/cn/lihongjie/coal/pdfGenerator/service/PdfGeneratorService.java
@@ -0,0 +1,188 @@
+package cn.lihongjie.coal.pdfGenerator.service;
+
+import cn.lihongjie.coal.base.dto.CommonQuery;
+import cn.lihongjie.coal.base.dto.IdRequest;
+import cn.lihongjie.coal.base.service.BaseService;
+import cn.lihongjie.coal.file.dto.FileDto;
+import cn.lihongjie.coal.file.service.FileService;
+import cn.lihongjie.coal.pdfGenerator.dto.CreatePdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.dto.GeneratePdfDto;
+import cn.lihongjie.coal.pdfGenerator.dto.PdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.dto.UpdatePdfGeneratorDto;
+import cn.lihongjie.coal.pdfGenerator.entity.PdfGeneratorEntity;
+import cn.lihongjie.coal.pdfGenerator.mapper.PdfGeneratorMapper;
+import cn.lihongjie.coal.pdfGenerator.repository.PdfGeneratorRepository;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.playwright.Browser;
+import com.microsoft.playwright.Playwright;
+import com.microsoft.playwright.Response;
+
+import jakarta.annotation.PreDestroy;
+
+import lombok.Cleanup;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.ByteArrayInputStream;
+import java.time.Duration;
+import java.time.LocalDateTime;
+
+@Service
+@Slf4j
+@Transactional
+public class PdfGeneratorService extends BaseService {
+ @Autowired FileService fileService;
+ @Autowired ObjectMapper objectMapper;
+ @Autowired private PdfGeneratorRepository repository;
+ @Autowired private PdfGeneratorMapper mapper;
+ @Autowired private ConversionService conversionService;
+ private Boolean chromeInit = false;
+ private Playwright playwright;
+ private Browser browser;
+
+ @PreDestroy
+ public void destroy() {
+ log.info("销毁chrome");
+ if (browser != null) {
+
+ browser.close();
+ }
+
+ if (playwright != null) {
+
+ playwright.close();
+ }
+ }
+
+ @SneakyThrows
+ public PdfGeneratorDto generate(GeneratePdfDto request) {
+
+ synchronized (this) {
+ LocalDateTime startTime = LocalDateTime.now();
+ if (!chromeInit) {
+ log.info("初始化chrome");
+
+ playwright = Playwright.create();
+ browser = playwright.chromium().launch();
+ chromeInit = true;
+ }
+
+ @Cleanup com.microsoft.playwright.Page page = browser.newPage();
+
+ if (StringUtils.isNotEmpty(request.getHtmlText())) {
+ page.setContent(request.getHtmlText());
+ } else if (StringUtils.isNotEmpty(request.getHtmlUrl())) {
+ Response response = page.navigate(request.getHtmlUrl());
+
+ log.info("访问{}返回{}", request.getHtmlUrl(), response.status());
+ } else {
+ throw new IllegalArgumentException("htmlText和htmlUrl不能同时为空");
+ }
+
+ com.microsoft.playwright.Page.PdfOptions pdfOptions = null;
+ if (request.getOptions() != null) {
+ pdfOptions =
+ objectMapper.treeToValue(
+ request.getOptions(),
+ com.microsoft.playwright.Page.PdfOptions.class);
+ }
+ PdfGeneratorEntity entity = mapper.toEntity(request);
+ boolean error = false;
+ String stackTrace = null;
+ byte[] pdf = null;
+ try {
+
+ pdf = page.pdf(pdfOptions);
+ } catch (Exception e) {
+
+ log.error("生成pdf失败", e);
+ stackTrace = ExceptionUtils.getStackTrace(e);
+ error = true;
+ }
+
+ if (pdf != null) {
+
+ FileDto generatePdf = null;
+ try {
+
+ generatePdf =
+ fileService.upload(
+ new ByteArrayInputStream(pdf),
+ request.getName(),
+ "generatePdf",
+ null,
+ null,
+ "");
+ } catch (Exception e) {
+ log.error("上传pdf失败", e);
+ error = true;
+ stackTrace = ExceptionUtils.getStackTrace(e);
+ }
+
+ if (!error) {
+
+ entity.setPdfUrl(generatePdf.getPublicUrl());
+ }
+ }
+
+ entity.setEndTime(LocalDateTime.now());
+
+ entity.setDuration(Duration.between(startTime, entity.getEndTime()).toMillis());
+
+ entity.setRemarks(stackTrace);
+ entity.setExecStatus(error ? "1" : "0");
+
+ this.save(entity);
+ return this.mapper.toDto(entity);
+ }
+ }
+
+ public PdfGeneratorDto create(CreatePdfGeneratorDto request) {
+ PdfGeneratorEntity entity = mapper.toEntity(request);
+
+ this.repository.save(entity);
+ return getById(entity.getId());
+ }
+
+ public PdfGeneratorDto update(UpdatePdfGeneratorDto request) {
+ PdfGeneratorEntity entity = this.repository.get(request.getId());
+ this.mapper.updateEntity(entity, request);
+
+ this.repository.save(entity);
+
+ return getById(entity.getId());
+ }
+
+ public void delete(IdRequest request) {
+ this.repository.deleteAllById(request.getIds());
+ }
+
+ public PdfGeneratorDto getById(String id) {
+ PdfGeneratorEntity entity = repository.get(id);
+
+ return mapper.toDto(entity);
+ }
+
+ public Page list(CommonQuery query) {
+ Page page =
+ repository.findAll(
+ query.specification(conversionService),
+ PageRequest.of(
+ query.getPageNo(),
+ query.getPageSize(),
+ Sort.by(query.getOrders())));
+
+ return page.map(this.mapper::toDto);
+ }
+}
diff --git a/src/main/resources/config/dictionary.json b/src/main/resources/config/dictionary.json
index 37d69669..4eb8d5e3 100644
--- a/src/main/resources/config/dictionary.json
+++ b/src/main/resources/config/dictionary.json
@@ -1703,6 +1703,20 @@
}
]
},
+ {
+ "code": "common.execStatus",
+ "name": "通用状态",
+ "item": [
+ {
+ "code": "0",
+ "name": "成功"
+ },
+ {
+ "code": "1",
+ "name": "失败"
+ }
+ ]
+ },
{
"code": "loginUserHis.loginStatus",
"name": "登录状态",