Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
张文彪
/
employmentBusinessPc
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
9f11a3de
authored
Dec 01, 2025
by
zwb
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
新增根据html生成pdf文件
parent
18fa217a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
171 additions
and
4 deletions
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/config/AiConfigProperties.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/controller/NewEditionResumeController.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/NewEditionResumeService.java
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/impl/NewEditionResumeServiceImpl.java
employmentBusiness-pc-common/employmentBusiness-pc-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java
View file @
9f11a3de
...
...
@@ -70,4 +70,19 @@ public interface CacheConstants {
* 下载使用简历对应模版缓存
*/
String
RESUME_TEMPLATE_ID
=
"template:resume:download:%s"
;
/**
* 简历下载数据缓存数据pdf
*/
String
CREATE_RESUME_HTML_PDF_DATA
=
"create:resume:html:pdf:data:%s"
;
/**
* 简历下载数据缓存pdf
*/
String
CREATE_RESUME_PDF_HTML
=
"create:resume:pdf:html:%s"
;
/**
* 下载使用简历对应模版缓存pdf
*/
String
RESUME_TEMPLATE_PDF_ID
=
"template:resume:pdf:download:%s"
;
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/config/AiConfigProperties.java
View file @
9f11a3de
...
...
@@ -33,9 +33,9 @@ public class AiConfigProperties {
//
// public String avatarImages = "https://xzt-dev.jinsehuaqin.com/avatar_images/";
//
// public String pdfDownZs = "https://xzt-dev.jinsehuaqin.com/pdf_down_zs/"
;
//
// public String htmlDownZs = "https://xzt-dev.jinsehuaqin.com/html_down_zs/"
;
public
String
pdfDownZs
;
public
String
htmlDownZs
;
//
// public String imagesDownZs = "https://xzt-dev.jinsehuaqin.com/images_down_zs/";
//
...
...
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/controller/NewEditionResumeController.java
View file @
9f11a3de
...
...
@@ -7,6 +7,7 @@ import com.bkty.system.domain.dto.ModuleOptimizationDto;
import
com.bkty.system.domain.dto.ResumeByPdfDto
;
import
com.bkty.system.domain.dto.ResumeListItemCache
;
import
com.bkty.system.domain.dto.ResumeMakeDto
;
import
com.bkty.system.domain.vo.ResumeByPdfVo
;
import
com.bkty.system.domain.vo.ResumeModelVo
;
import
com.bkty.system.domain.vo.ResumeVo
;
import
com.bkty.system.service.resume.NewEditionResumeService
;
...
...
@@ -139,11 +140,26 @@ public class NewEditionResumeController {
*/
@PostMapping
(
"/create-resume-by-html"
)
public
R
createResumeHtml
(
@RequestBody
ResumeByPdfDto
dto
){
if
(
dto
.
getResumeId
()==
null
){
throw
new
WarnException
(
"简历ID不能为空"
);
}
return
new
R
<>(
this
.
newEditionResumeService
.
createResumeHtml
(
dto
.
getResumeId
(),
dto
.
getTemplateName
()));
}
/**
* 根据html生成pdf文件
* @param dto
* @return
*/
@PostMapping
(
"/create-resume-pdf"
)
public
R
<
ResumeByPdfVo
>
createResumePdf
(
@RequestBody
ResumeByPdfDto
dto
){
ResumeByPdfVo
vo
=
this
.
newEditionResumeService
.
createResumePdf
(
dto
);
return
new
R
<>(
vo
);
}
/**
* 简历模块优化
* @param dto
* @return
...
...
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/NewEditionResumeService.java
View file @
9f11a3de
package
com
.
bkty
.
system
.
service
.
resume
;
import
com.bkty.system.domain.dto.ModuleOptimizationDto
;
import
com.bkty.system.domain.dto.ResumeByPdfDto
;
import
com.bkty.system.domain.dto.ResumeListItemCache
;
import
com.bkty.system.domain.dto.ResumeMakeDto
;
import
com.bkty.system.domain.vo.ResumeByPdfVo
;
import
com.bkty.system.domain.vo.ResumeModelVo
;
import
com.bkty.system.domain.vo.ResumeVo
;
import
org.springframework.web.multipart.MultipartFile
;
...
...
@@ -90,4 +92,12 @@ public interface NewEditionResumeService {
* @param dto
*/
void
resumeModelSort
(
ResumeMakeDto
dto
);
/**
* 根据html生成pdf文件
* @param dto
* @return
*/
ResumeByPdfVo
createResumePdf
(
ResumeByPdfDto
dto
);
}
employmentBusiness-pc-modules/employmentBusiness-pc-system/src/main/java/com/bkty/system/service/resume/impl/NewEditionResumeServiceImpl.java
View file @
9f11a3de
...
...
@@ -13,6 +13,7 @@ import com.bkty.system.api.model.LoginUser;
import
com.bkty.system.config.AiConfigProperties
;
import
com.bkty.system.config.CommonAsyncThreadPool
;
import
com.bkty.system.domain.dto.ModuleOptimizationDto
;
import
com.bkty.system.domain.dto.ResumeByPdfDto
;
import
com.bkty.system.domain.dto.ResumeListItemCache
;
import
com.bkty.system.domain.dto.ResumeMakeDto
;
import
com.bkty.system.domain.entity.*
;
...
...
@@ -29,12 +30,14 @@ import lombok.extern.slf4j.Slf4j;
import
org.dromara.common.core.constant.CacheConstants
;
import
org.dromara.common.core.constant.Constants
;
import
org.dromara.common.core.constant.CozeConstsnts
;
import
org.dromara.common.core.constant.SecurityConstants
;
import
org.dromara.common.core.domain.UserLoginInfo
;
import
org.dromara.common.core.enums.ResumeEnum
;
import
org.dromara.common.core.exception.WarnException
;
import
org.dromara.common.core.utils.SecurityUtils
;
import
org.dromara.common.core.utils.SnowFlakeUtil
;
import
org.dromara.common.core.utils.StringUtils
;
import
org.dromara.common.core.utils.WebUtils
;
import
org.dromara.common.satoken.utils.LoginHelper
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.data.redis.core.RedisTemplate
;
...
...
@@ -43,6 +46,9 @@ import org.springframework.scheduling.annotation.Async;
import
org.springframework.stereotype.Service
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.time.LocalDate
;
import
java.time.format.DateTimeFormatter
;
import
java.time.temporal.ChronoUnit
;
...
...
@@ -818,6 +824,126 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
}
}
@Override
public
ResumeByPdfVo
createResumePdf
(
ResumeByPdfDto
dto
)
{
String
templateName
=
dto
.
getTemplateName
();
if
(
StringUtils
.
isBlank
(
templateName
)){
templateName
=
"tpl21.ejs"
;
}
if
(
com
.
alibaba
.
excel
.
util
.
StringUtils
.
isBlank
(
dto
.
getResumeId
())){
throw
new
WarnException
(
"简历ID不能为空"
);
}
ResumeByPdfVo
vo
=
new
ResumeByPdfVo
();
/**是否展示0.显示 1.不显示*/
Map
<
String
,
Object
>
objectMap
=
newEditionResumeUtil
.
queryAllModelData
(
dto
.
getResumeId
(),
"0"
);
Object
baseInfo
=
objectMap
.
get
(
"base"
);
if
(
baseInfo
!=
null
)
{
JSONObject
jsonObject
=
(
JSONObject
)
JSON
.
toJSON
(
baseInfo
);
String
age
=
jsonObject
.
getString
(
"birthday"
);
// 计算年龄
String
calculatedAge
=
calculationAge
(
age
);
// 放回 JSON 对象中
jsonObject
.
put
(
"birthday"
,
calculatedAge
);
jsonObject
.
put
(
"workTime"
,
""
);
// 更新 base_info
objectMap
.
put
(
"base"
,
jsonObject
);
}
log
.
info
(
"========导出简历数据1=========:{}"
,
objectMap
);
String
jsonString
=
JSON
.
toJSONString
(
objectMap
);
log
.
info
(
"========导出简历数据2=========:{}"
,
jsonString
);
if
(
objectMap
.
get
(
"base"
)
!=
null
){
Map
<
String
,
Object
>
map
=
JSON
.
parseObject
(
String
.
valueOf
(
objectMap
.
get
(
"base"
)),
Map
.
class
);
if
(
map
.
get
(
"resumeName"
)
!=
null
){
vo
.
setResumeName
(
map
!=
null
?
String
.
valueOf
(
map
.
get
(
"resumeName"
))
:
""
);
}
else
{
FunctionResumeBase
resumeBase
=
this
.
functionResumeBaseMapper
.
selectById
(
dto
.
getResumeId
());
vo
.
setResumeName
(
resumeBase
.
getResumeName
());
this
.
resumeCacheService
.
saveResumeModelDataCache
(
Long
.
valueOf
(
dto
.
getResumeId
()),
Long
.
valueOf
(
dto
.
getResumeId
()),
JSON
.
toJSONString
(
resumeBase
));
}
vo
.
setUserName
(
map
!=
null
?
String
.
valueOf
(
map
.
get
(
"username"
))
:
""
);
}
String
data
=
redisTemplate
.
opsForValue
().
get
(
CacheConstants
.
CREATE_RESUME_HTML_PDF_DATA
.
formatted
(
dto
.
getResumeId
()));
if
(
com
.
alibaba
.
excel
.
util
.
StringUtils
.
isNotBlank
(
data
)){
if
(
jsonString
.
equals
(
data
)){
String
template
=
redisTemplate
.
opsForValue
().
get
(
CacheConstants
.
RESUME_TEMPLATE_PDF_ID
.
formatted
(
dto
.
getResumeId
()));
if
(
com
.
alibaba
.
excel
.
util
.
StringUtils
.
isNotBlank
(
template
)
&&
template
.
equals
(
templateName
)){
String
json
=
redisTemplate
.
opsForValue
().
get
(
CacheConstants
.
CREATE_RESUME_PDF_HTML
.
formatted
(
dto
.
getResumeId
()));
if
(
com
.
alibaba
.
excel
.
util
.
StringUtils
.
isNotBlank
(
json
)){
ResumeByPdfVo
resume
=
JSON
.
parseObject
(
json
,
ResumeByPdfVo
.
class
);
return
resume
;
}
}
}
}
log
.
info
(
"简历预览数据: {}"
,
jsonString
);
String
htmlName
=
dto
.
getResumeId
()
+
".html"
;
FileProcessor
.
processFile
(
properties
.
getPath
()
+
"template/"
+
templateName
,
properties
.
getPath
()
+
"output/"
+
htmlName
,
"<%- data %>"
,
jsonString
);
// Node.js 命令及参数
String
nodeExecutable
=
"node"
;
// 如果环境变量已配置 Node.js,可直接用 "node"
String
scriptPath
=
properties
.
getPath
()
+
"output"
;
String
inputFile
=
"file:///"
+
properties
.
getPath
()+
"output/"
+
dto
.
getResumeId
()
+
".html"
;
String
pdfName
=
sanitizeFileName
(
vo
.
getResumeName
())
+
".pdf"
;
try
{
// 构建 ProcessBuilder 并传递参数
ProcessBuilder
processBuilder
=
new
ProcessBuilder
(
nodeExecutable
,
scriptPath
,
inputFile
,
properties
.
getPath
()
+
"pdf/"
+
pdfName
);
// 合并标准输出和错误输出
processBuilder
.
redirectErrorStream
(
true
);
// 启动进程
Process
process
=
processBuilder
.
start
();
// 读取 Node.js 命令行输出
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
process
.
getInputStream
()));
String
line
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
log
.
info
(
"Node.js 输出pdf: {}"
,
line
);
}
// 等待命令执行完成
int
exitCode
=
process
.
waitFor
();
log
.
info
(
"Node.js 命令执行完成,退出码: {}"
,
exitCode
);
}
catch
(
IOException
|
InterruptedException
e
)
{
e
.
printStackTrace
();
}
String
header
=
WebUtils
.
getRequest
().
getHeader
(
SecurityConstants
.
QQXB_FROM
);
if
(
com
.
alibaba
.
excel
.
util
.
StringUtils
.
isNotBlank
(
header
)
&&
!
SecurityConstants
.
QQXB_OUT
.
equals
(
header
)
&&
!
SecurityConstants
.
JYXZ_OUT
.
equals
(
header
)){
vo
.
setPdfName
(
properties
.
getPdfDown
()
+
pdfName
);
vo
.
setHtmlName
(
properties
.
getHtmlDown
()
+
htmlName
);
}
else
{
vo
.
setPdfName
(
properties
.
getPdfDownZs
()
+
pdfName
);
vo
.
setHtmlName
(
properties
.
getHtmlDownZs
()
+
htmlName
);
}
redisTemplate
.
opsForValue
().
set
(
CacheConstants
.
CREATE_RESUME_HTML_PDF_DATA
.
formatted
(
dto
.
getResumeId
()),
jsonString
);
redisTemplate
.
opsForValue
().
set
(
CacheConstants
.
CREATE_RESUME_PDF_HTML
.
formatted
(
dto
.
getResumeId
()),
JSON
.
toJSONString
(
vo
));
redisTemplate
.
opsForValue
().
set
(
CacheConstants
.
RESUME_TEMPLATE_PDF_ID
.
formatted
(
dto
.
getResumeId
()),
templateName
);
return
vo
;
}
public
String
sanitizeFileName
(
String
fileName
)
{
if
(
fileName
==
null
)
return
null
;
// [^a-zA-Z0-9\u4e00-\u9fa5.-] 表示不是字母、数字、中文、点、短横线的字符都替换成 _
String
sanitized
=
fileName
.
replaceAll
(
"[^a-zA-Z0-9\\u4e00-\\u9fa5.-]"
,
"_"
);
// 可选:去掉开头和结尾多余的 _
sanitized
=
sanitized
.
replaceAll
(
"^_+"
,
""
).
replaceAll
(
"_+$"
,
""
);
// 可选:连续多个特殊字符替换成一个 _
sanitized
=
sanitized
.
replaceAll
(
"_+"
,
"_"
);
return
sanitized
;
}
private
ResumeModelVo
initModelVo
(
FunctionResumeModel
m
)
{
ResumeModelVo
modelVo
=
new
ResumeModelVo
();
modelVo
.
setModelId
(
m
.
getId
());
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment