Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-csf
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-csf
Commits
506522ed
Commit
506522ed
authored
Nov 21, 2025
by
jianan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新单跟进72
parent
cd9ce964
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
560 additions
and
3 deletions
+560
-3
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiPolicyFollowController.java
+94
-3
yd-csf-service/pom.xml
+19
-0
yd-csf-service/src/main/java/com/yd/csf/service/dto/PolicyReportData.java
+39
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/PolicyReportPdfService.java
+408
-0
yd-csf-service/src/main/resources/font/DFKai-SB.ttf
+0
-0
No files found.
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiPolicyFollowController.java
View file @
506522ed
...
@@ -12,19 +12,18 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
...
@@ -12,19 +12,18 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.common.result.Result
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.csf.api.dto.CommissionExcelDTO
;
import
com.yd.csf.api.dto.CommissionExcelDTO
;
import
com.yd.csf.api.dto.PolicyExcelDTO
;
import
com.yd.csf.api.dto.PolicyExcelDTO
;
import
com.yd.csf.api.dto.PolicyFollowDTO
;
import
com.yd.csf.api.dto.PolicyFollowDTO
;
import
com.yd.csf.api.listener.PolicyDataListener
;
import
com.yd.csf.api.listener.PolicyDataListener
;
import
com.yd.csf.api.service.ApiExpectedFortuneService
;
import
com.yd.csf.service.common.ErrorCode
;
import
com.yd.csf.service.common.ErrorCode
;
import
com.yd.csf.service.dto.*
;
import
com.yd.csf.service.dto.*
;
import
com.yd.csf.service.enums.PolicyFollowStatusEnum
;
import
com.yd.csf.service.enums.PolicyFollowStatusEnum
;
import
com.yd.csf.service.model.*
;
import
com.yd.csf.service.model.*
;
import
com.yd.csf.service.service.*
;
import
com.yd.csf.service.service.*
;
import
com.yd.csf.service.utils.AsyncQueryUtil
;
import
com.yd.csf.service.vo.PolicyFollowDetailVO
;
import
com.yd.csf.service.vo.PolicyFollowDetailVO
;
import
com.yd.csf.service.vo.PolicyFollowRecordVO
;
import
com.yd.csf.service.vo.PolicyFollowRecordVO
;
import
com.yd.csf.service.vo.PolicyFollowVO
;
import
com.yd.csf.service.vo.PolicyFollowVO
;
...
@@ -35,13 +34,15 @@ import org.apache.commons.lang3.StringUtils;
...
@@ -35,13 +34,15 @@ import org.apache.commons.lang3.StringUtils;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.annotation.Resource
;
import
javax.annotation.Resource
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.math.BigDecimal
;
import
java.text.DecimalFormat
;
import
java.text.DecimalFormat
;
import
java.text.ParseException
;
import
java.text.ParseException
;
import
java.util.*
;
import
java.util.*
;
...
@@ -82,6 +83,10 @@ public class ApiPolicyFollowController {
...
@@ -82,6 +83,10 @@ public class ApiPolicyFollowController {
private
PolicyFollowFileService
policyFollowFileService
;
private
PolicyFollowFileService
policyFollowFileService
;
@Resource
private
PolicyReportPdfService
policyReportPdfService
;
@PostMapping
(
"/upload/excel"
)
@PostMapping
(
"/upload/excel"
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Result
<
Boolean
>
uploadExcel
(
@RequestParam
(
"file"
)
MultipartFile
file
)
throws
Exception
{
public
Result
<
Boolean
>
uploadExcel
(
@RequestParam
(
"file"
)
MultipartFile
file
)
throws
Exception
{
...
@@ -549,4 +554,89 @@ public class ApiPolicyFollowController {
...
@@ -549,4 +554,89 @@ public class ApiPolicyFollowController {
List
<
PolicyFollowRecord
>
policyFollowStatusList
=
policyFollowRecordService
.
list
(
queryWrapper
);
List
<
PolicyFollowRecord
>
policyFollowStatusList
=
policyFollowRecordService
.
list
(
queryWrapper
);
return
Result
.
success
(
policyFollowRecordService
.
getVOList
(
policyFollowStatusList
));
return
Result
.
success
(
policyFollowRecordService
.
getVOList
(
policyFollowStatusList
));
}
}
/**
* 生成签约单
*/
@GetMapping
(
value
=
"/report/download"
,
produces
=
"application/pdf"
)
@Operation
(
summary
=
"生成签约单"
)
public
void
previewPolicyReport
(
@RequestParam
(
"policyBizId"
)
String
policyBizId
,
HttpServletResponse
response
)
{
PolicyFollow
policyFollow
=
policyFollowService
.
getByPolicyBizId
(
policyBizId
);
if
(
policyFollow
==
null
)
{
throw
new
BusinessException
(
ErrorCode
.
NOT_FOUND_ERROR
.
getCode
(),
ErrorCode
.
NOT_FOUND_ERROR
.
getMessage
());
}
PolicyReportData
reportData
=
new
PolicyReportData
();
// 填充数据
// reportData.setStartTime("2025-10-30");
// reportData.setEndTime("2025-10-30");
// reportData.setLocation("香港");
// reportData.setServiceManager("Vickie");
// reportData.setPolicyHolder(policyFollow.getPolicyHolder());
// reportData.setPolicyNumber(policyFollow.getPolicyNo());
// reportData.setInsuranceCompany(policyFollow.getInsurer());
// reportData.setInsuredPerson(policyFollow.getInsured());
// reportData.setInsurancePlan(policyFollow.getProductName());
// reportData.setInsuredAge(0);
// reportData.setCurrency(policyFollow.getCurrency());
// reportData.setPaymentPeriod((Integer) policyFollow.getPaymentTerm());
// reportData.setAnnualAmount(policyFollow.getPaymentPremium());
// reportData.setTotalPrepayment(BigDecimal.ZERO);
// reportData.setPremiumFee(BigDecimal.ZERO);
reportData
.
setStartTime
(
"2025-10-30"
);
reportData
.
setEndTime
(
"2025-10-30"
);
reportData
.
setLocation
(
"香港"
);
reportData
.
setServiceManager
(
"Vickie"
);
reportData
.
setPolicyHolder
(
"policyHolder"
);
reportData
.
setPolicyNumber
(
"B635379588"
);
reportData
.
setInsuranceCompany
(
"友邦保险"
);
reportData
.
setInsuredPerson
(
"insuredPerson"
);
reportData
.
setInsurancePlan
(
"环宇盈活储蓄保险计划"
);
reportData
.
setInsuredAge
(
1
);
reportData
.
setCurrency
(
"HKD"
);
reportData
.
setPaymentPeriod
(
5
);
reportData
.
setAnnualAmount
(
BigDecimal
.
valueOf
(
30000.08
));
reportData
.
setTotalPrepayment
(
BigDecimal
.
valueOf
(
150064.70
));
reportData
.
setPremiumFee
(
BigDecimal
.
valueOf
(
12.86
));
try
{
log
.
info
(
"收到PDF生成请求: {}"
,
reportData
);
log
.
info
(
"PolicyReportData 内容检查:"
);
log
.
info
(
"startTime: {}"
,
reportData
.
getStartTime
());
log
.
info
(
"endTime: {}"
,
reportData
.
getEndTime
());
log
.
info
(
"location: {}"
,
reportData
.
getLocation
());
log
.
info
(
"serviceManager: {}"
,
reportData
.
getServiceManager
());
byte
[]
pdfBytes
=
policyReportPdfService
.
generatePolicyReport
(
reportData
);
if
(
pdfBytes
==
null
||
pdfBytes
.
length
==
0
)
{
log
.
error
(
"生成的PDF为空"
);
throw
new
BusinessException
(
"生成的PDF内容为空"
);
}
log
.
info
(
"PDF生成成功,大小: {} bytes"
,
pdfBytes
.
length
);
// 设置下载响应头
response
.
setContentType
(
"application/pdf"
);
response
.
setHeader
(
"Content-Disposition"
,
"attachment; filename=policy-report-"
+
reportData
.
getPolicyNumber
()
+
".pdf"
);
response
.
setContentLength
(
pdfBytes
.
length
);
// 写入响应流
ServletOutputStream
outputStream
=
response
.
getOutputStream
();
outputStream
.
write
(
pdfBytes
);
outputStream
.
flush
();
log
.
info
(
"PDF响应发送完成"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"PDF预览失败"
,
e
);
throw
new
BusinessException
(
"PDF预览失败: "
+
e
.
getMessage
());
}
}
}
}
\ No newline at end of file
yd-csf-service/pom.xml
View file @
506522ed
...
@@ -12,6 +12,20 @@
...
@@ -12,6 +12,20 @@
<artifactId>
yd-csf-service
</artifactId>
<artifactId>
yd-csf-service
</artifactId>
<dependencies>
<dependencies>
<!-- 公共工具类 -->
<dependency>
<groupId>
commons-io
</groupId>
<artifactId>
commons-io
</artifactId>
<version>
2.11.0
</version>
</dependency>
<!-- itextpdf -->
<dependency>
<groupId>
com.github.librepdf
</groupId>
<artifactId>
openpdf
</artifactId>
<version>
1.3.30
</version>
</dependency>
<dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<groupId>
com.alibaba
</groupId>
<artifactId>
easyexcel
</artifactId>
<artifactId>
easyexcel
</artifactId>
...
@@ -104,5 +118,10 @@
...
@@ -104,5 +118,10 @@
<artifactId>
yd-feign
</artifactId>
<artifactId>
yd-feign
</artifactId>
<version>
${project.version}
</version>
<version>
${project.version}
</version>
</dependency>
</dependency>
<!-- 添加AOP依赖 -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-aop
</artifactId>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
yd-csf-service/src/main/java/com/yd/csf/service/dto/PolicyReportData.java
0 → 100644
View file @
506522ed
package
com
.
yd
.
csf
.
service
.
dto
;
import
lombok.Data
;
import
java.math.BigDecimal
;
import
java.util.List
;
@Data
public
class
PolicyReportData
{
// 基本信息
private
String
startTime
;
private
String
endTime
;
private
String
location
;
private
String
serviceManager
;
// 保单详细信息
private
String
policyHolder
;
private
String
policyNumber
;
private
String
insuranceCompany
;
private
String
insuredPerson
;
private
String
insurancePlan
;
private
Integer
insuredAge
;
private
String
currency
;
private
Integer
paymentPeriod
;
private
BigDecimal
annualAmount
;
private
BigDecimal
totalPrepayment
;
private
BigDecimal
premiumFee
;
// 附加险信息
private
List
<
AdditionalInsurance
>
additionalInsurances
;
@Data
public
static
class
AdditionalInsurance
{
private
String
name
;
private
String
paymentTerm
;
private
String
currency
;
private
BigDecimal
firstYearAmount
;
}
}
yd-csf-service/src/main/java/com/yd/csf/service/service/PolicyReportPdfService.java
0 → 100644
View file @
506522ed
package
com
.
yd
.
csf
.
service
.
service
;
import
com.lowagie.text.Document
;
import
com.lowagie.text.DocumentException
;
import
com.lowagie.text.Font
;
import
com.lowagie.text.PageSize
;
import
com.lowagie.text.Paragraph
;
import
com.lowagie.text.pdf.BaseFont
;
import
com.lowagie.text.pdf.PdfContentByte
;
import
com.lowagie.text.pdf.PdfPTable
;
import
com.lowagie.text.pdf.PdfWriter
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.csf.service.dto.PolicyReportData
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Service
;
import
java.awt.*
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
@Service
@Slf4j
public
class
PolicyReportPdfService
{
private
Font
chineseFont
;
private
Font
chineseBoldFont
;
private
Font
chineseTitleFont
;
private
Font
chineseRedTitleFont
;
// 颜色定义
private
static
final
Color
RED_TITLE_COLOR
=
new
Color
(
255
,
0
,
0
);
private
static
final
Color
TEXT_COLOR
=
new
Color
(
102
,
102
,
102
);
private
static
final
Color
FOOTNOTE_COLOR
=
new
Color
(
153
,
153
,
153
);
private
static
final
Color
LINE_COLOR
=
new
Color
(
226
,
226
,
226
);
// 调整字号常量
private
static
final
float
MAIN_TITLE_FONT_SIZE
=
28
f
;
// 增大主标题字号
private
static
final
float
SECTION_TITLE_FONT_SIZE
=
16
f
;
// 调整章节标题字号
private
static
final
float
CONTENT_FONT_SIZE
=
12
f
;
// 调整内容文字字号
private
static
final
float
FOOTNOTE_FONT_SIZE
=
10
f
;
// 调整备注文字字号
// 调整间距常量
private
static
final
float
MAIN_TITLE_MARGIN_BOTTOM
=
20
f
;
// 增大主标题下方间距
private
static
final
float
LINE_MARGIN_BOTTOM
=
18
f
;
// 调整水平线间距
private
static
final
float
ROW_SPACING
=
12
f
;
// 调整行间距
public
byte
[]
generatePolicyReport
(
PolicyReportData
reportData
)
throws
DocumentException
{
ByteArrayOutputStream
outputStream
=
new
ByteArrayOutputStream
();
try
{
Document
document
=
new
Document
(
PageSize
.
A4
,
40
,
40
,
40
,
40
);
PdfWriter
writer
=
PdfWriter
.
getInstance
(
document
,
outputStream
);
document
.
open
();
initChineseFont
();
// 1. 主标题
addMainTitle
(
document
,
"簽單完成報告"
);
// 2. 主标题下方水平线
addHorizontalLine
(
document
,
writer
);
// 3. 基本信息表格
addBasicInfo
(
document
,
reportData
);
// 4. 保单详细信息标题
addPolicyDetailTitle
(
document
,
reportData
);
// 5. 保单详细信息标题下方水平线
addHorizontalLine
(
document
,
writer
);
// 6. 保单详细字段表格(包含备注和保費徵費)
addPolicyDetailFields
(
document
,
reportData
);
// 7. 附加险表头
addAdditionalInsuranceHeader
(
document
);
// 8. 详细信息下方水平线
addHorizontalLine
(
document
,
writer
);
// 移除了原来的备注说明,因为现在备注已经整合到保单详细字段中
document
.
close
();
return
outputStream
.
toByteArray
();
}
catch
(
Exception
e
)
{
log
.
error
(
"PDF生成失败"
,
e
);
throw
new
BusinessException
(
"生成报告失败: "
+
e
.
getMessage
());
}
}
/**
* 主标题 - 放大并居中
*/
private
void
addMainTitle
(
Document
document
,
String
title
)
throws
DocumentException
{
// 创建更大的红色标题字体
Font
largeTitleFont
=
new
Font
(
chineseRedTitleFont
.
getBaseFont
(),
MAIN_TITLE_FONT_SIZE
,
Font
.
BOLD
,
RED_TITLE_COLOR
);
Paragraph
titleParagraph
=
new
Paragraph
(
title
,
largeTitleFont
);
titleParagraph
.
setAlignment
(
Paragraph
.
ALIGN_CENTER
);
// 设置为居中
titleParagraph
.
setSpacingAfter
(
MAIN_TITLE_MARGIN_BOTTOM
);
document
.
add
(
titleParagraph
);
}
/**
* 水平线 - 调整位置
*/
private
void
addHorizontalLine
(
Document
document
,
PdfWriter
writer
)
throws
DocumentException
{
// 绘制直线
PdfContentByte
canvas
=
writer
.
getDirectContent
();
canvas
.
saveState
();
canvas
.
setColorStroke
(
LINE_COLOR
);
canvas
.
setLineWidth
(
1
f
);
float
y
=
writer
.
getVerticalPosition
(
false
)
-
5
f
;
canvas
.
moveTo
(
40
,
y
);
canvas
.
lineTo
(
PageSize
.
A4
.
getWidth
()
-
40
,
y
);
canvas
.
stroke
();
canvas
.
restoreState
();
// 添加额外间距
Paragraph
extraSpacing
=
new
Paragraph
(
" "
);
extraSpacing
.
setSpacingAfter
(
8
f
);
document
.
add
(
extraSpacing
);
}
/**
* 保单详细信息标题 - 调整字体大小
*/
private
void
addPolicyDetailTitle
(
Document
document
,
PolicyReportData
data
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
25
,
25
,
25
,
25
});
table
.
setSpacingBefore
(
0
f
);
table
.
setSpacingAfter
(
ROW_SPACING
);
// 使用更大的字体和红色
Font
sectionTitleFont
=
new
Font
(
chineseRedTitleFont
.
getBaseFont
(),
SECTION_TITLE_FONT_SIZE
,
Font
.
BOLD
,
RED_TITLE_COLOR
);
Paragraph
titlePara
=
new
Paragraph
(
"保單詳細信息"
,
sectionTitleFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
titleCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
titlePara
);
titleCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
titleCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
// 第二列:空
com
.
lowagie
.
text
.
pdf
.
PdfPCell
emptyCell1
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
new
Paragraph
(
" "
));
emptyCell1
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
// 第三列:保單編號标签
Paragraph
numberLabelPara
=
new
Paragraph
(
"保單編號"
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
numberLabelCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
numberLabelPara
);
numberLabelCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
numberLabelCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
// 第四列:保单编号值
Paragraph
numberValuePara
=
new
Paragraph
(
data
.
getPolicyNumber
()
!=
null
?
data
.
getPolicyNumber
()
:
""
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
numberValueCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
numberValuePara
);
numberValueCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
numberValueCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
table
.
addCell
(
titleCell
);
table
.
addCell
(
emptyCell1
);
table
.
addCell
(
numberLabelCell
);
table
.
addCell
(
numberValueCell
);
document
.
add
(
table
);
}
/**
* 保单详细字段 - 修正保費徵費位置
*/
private
void
addPolicyDetailFields
(
Document
document
,
PolicyReportData
data
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
20
,
30
,
20
,
30
});
table
.
setSpacingBefore
(
0
f
);
table
.
setSpacingAfter
(
ROW_SPACING
);
// 第一行:保單持有人 | 持有人值 | 保險公司 | 公司值
addTableHeaderCellNoBorder
(
table
,
"保單持有人"
);
addTableCellNoBorder
(
table
,
data
.
getPolicyHolder
()
!=
null
?
data
.
getPolicyHolder
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"保險公司"
);
addTableCellNoBorder
(
table
,
data
.
getInsuranceCompany
()
!=
null
?
data
.
getInsuranceCompany
()
:
""
);
// 第二行:保單受保人 | 受保人值 | 受保人年齡 | 年齡值
addTableHeaderCellNoBorder
(
table
,
"保單受保人"
);
addTableCellNoBorder
(
table
,
data
.
getInsuredPerson
()
!=
null
?
data
.
getInsuredPerson
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"受保人年齡"
);
addTableCellNoBorder
(
table
,
data
.
getInsuredAge
()
!=
null
?
String
.
valueOf
(
data
.
getInsuredAge
())
:
""
);
// 第三行:保險計劃 | 計劃值 | 繳費年期 | 年期值
addTableHeaderCellNoBorder
(
table
,
"保險計劃"
);
addTableCellNoBorder
(
table
,
data
.
getInsurancePlan
()
!=
null
?
data
.
getInsurancePlan
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"繳費年期"
);
addTableCellNoBorder
(
table
,
data
.
getPaymentPeriod
()
!=
null
?
String
.
valueOf
(
data
.
getPaymentPeriod
())
:
""
);
// 第四行:保單貨幣 | 貨幣值 | 备注 | 备注(跨列)
addTableHeaderCellNoBorder
(
table
,
"保單貨幣"
);
addTableCellNoBorder
(
table
,
data
.
getCurrency
()
!=
null
?
data
.
getCurrency
()
:
""
);
// 备注单元格 - 跨第3、4列,与保單貨幣同一行
Font
footnoteFont
=
new
Font
(
chineseFont
.
getBaseFont
(),
FOOTNOTE_FONT_SIZE
,
Font
.
NORMAL
,
FOOTNOTE_COLOR
);
Paragraph
footnotePara
=
new
Paragraph
(
"*此徵費為香港政府收取,續期時亦須繳納,但不納入本報告金額統計。澳門保單毋需繳納此費用。"
,
footnoteFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
footnoteCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
footnotePara
);
footnoteCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
footnoteCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
footnoteCell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_TOP
);
footnoteCell
.
setColspan
(
2
);
// 跨2列
footnoteCell
.
setPadding
(
2
f
);
table
.
addCell
(
footnoteCell
);
// 第五行:年繳金額 | 金額值 | 保費徵費 | 費用值
addTableHeaderCellNoBorder
(
table
,
"年繳金額"
);
addTableCellNoBorder
(
table
,
formatAmount
(
data
.
getAnnualAmount
()));
addTableHeaderCellNoBorder
(
table
,
"保費徵費"
);
addTableCellNoBorder
(
table
,
formatAmount
(
data
.
getPremiumFee
()));
// 第六行:合預繳息金額 | 金額值 | (空) | (空)
addTableHeaderCellNoBorder
(
table
,
"合預繳息金額"
);
addTableCellNoBorder
(
table
,
formatAmount
(
data
.
getTotalPrepayment
()));
addTableCellNoBorder
(
table
,
""
);
addTableCellNoBorder
(
table
,
""
);
document
.
add
(
table
);
}
/**
* 添加无边框的表头单元格
*/
private
void
addTableHeaderCellNoBorder
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
para
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
2
f
);
table
.
addCell
(
cell
);
}
/**
* 添加无边框的内容单元格
*/
private
void
addTableCellNoBorder
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
para
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
2
f
);
table
.
addCell
(
cell
);
}
/**
* 基本信息 - 调整行间距
*/
private
void
addBasicInfo
(
Document
document
,
PolicyReportData
data
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
20
,
30
,
20
,
30
});
// 调整列宽比例
table
.
setSpacingBefore
(
0
f
);
table
.
setSpacingAfter
(
ROW_SPACING
);
// 第一行
addTableHeaderCellNoBorder
(
table
,
"開始時間"
);
addTableCellNoBorder
(
table
,
data
.
getStartTime
()
!=
null
?
data
.
getStartTime
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"結束時間"
);
addTableCellNoBorder
(
table
,
data
.
getEndTime
()
!=
null
?
data
.
getEndTime
()
:
""
);
// 第二行
addTableHeaderCellNoBorder
(
table
,
"簽單地點"
);
addTableCellNoBorder
(
table
,
data
.
getLocation
()
!=
null
?
data
.
getLocation
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"服務主管"
);
addTableCellNoBorder
(
table
,
data
.
getServiceManager
()
!=
null
?
data
.
getServiceManager
()
:
""
);
document
.
add
(
table
);
}
/**
* 附加险表头 - 去掉边框
*/
private
void
addAdditionalInsuranceHeader
(
Document
document
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
25
,
25
,
25
,
25
});
table
.
setSpacingBefore
(
10
f
);
table
.
setSpacingAfter
(
10
f
);
// 创建居中对齐的无边框单元格
addTableCenterHeaderCellNoBorder
(
table
,
"附加险名称"
);
addTableCenterHeaderCellNoBorder
(
table
,
"缴费期限"
);
addTableCenterHeaderCellNoBorder
(
table
,
"幣种"
);
addTableCenterHeaderCellNoBorder
(
table
,
"首年金额"
);
document
.
add
(
table
);
}
/**
* 添加居中对齐的无边框表头单元格
*/
private
void
addTableCenterHeaderCellNoBorder
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseBoldFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
para
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_CENTER
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
2
f
);
table
.
addCell
(
cell
);
}
/**
* 备注说明
*/
private
void
addFootnote
(
Document
document
)
throws
DocumentException
{
Font
footnoteFont
=
new
Font
(
chineseFont
.
getBaseFont
(),
FOOTNOTE_FONT_SIZE
,
Font
.
NORMAL
,
FOOTNOTE_COLOR
);
Paragraph
footnote
=
new
Paragraph
(
"*此徵費為香港政府收取,續期時亦須繳納,但不納入本報告金額統計。澳門保單毋需繳納此費用。"
,
footnoteFont
);
footnote
.
setAlignment
(
Paragraph
.
ALIGN_LEFT
);
footnote
.
setSpacingBefore
(
10
f
);
document
.
add
(
footnote
);
}
/**
* 添加表格表头单元格
*/
private
void
addTableHeaderCell
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
table
.
addCell
(
createCell
(
para
,
false
));
}
/**
* 添加表格内容单元格
*/
private
void
addTableCell
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
table
.
addCell
(
createCell
(
para
,
false
));
}
/**
* 添加居中对齐的表头单元格
*/
private
void
addTableCenterHeaderCell
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseBoldFont
);
table
.
addCell
(
createCell
(
para
,
true
));
}
/**
* 创建单元格
*/
private
com
.
lowagie
.
text
.
pdf
.
PdfPCell
createCell
(
Paragraph
paragraph
,
boolean
centerAlign
)
{
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
paragraph
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
centerAlign
?
com
.
lowagie
.
text
.
Element
.
ALIGN_CENTER
:
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
5
f
);
return
cell
;
}
/**
* 初始化中文字体 - 从classpath资源加载
*/
private
void
initChineseFont
()
throws
IOException
,
DocumentException
{
try
{
BaseFont
baseFont
=
null
;
// 方法1: 使用绝对路径
String
absolutePath
=
"D:\\IdeaProjects\\yd-csf\\yd-csf-service\\src\\main\\resources\\font\\DFKai-SB.ttf"
;
// 方法2: 使用classpath相对路径(如果字体文件在resources目录下)
String
resourcePath
=
"font/DFKai-SB.ttf"
;
java
.
io
.
File
fontFile
=
new
java
.
io
.
File
(
absolutePath
);
if
(
fontFile
.
exists
())
{
try
{
baseFont
=
BaseFont
.
createFont
(
absolutePath
,
BaseFont
.
IDENTITY_H
,
BaseFont
.
EMBEDDED
);
log
.
info
(
"成功从绝对路径加载繁体楷体: {}"
,
absolutePath
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"绝对路径加载失败,尝试classpath路径"
);
// 尝试从classpath加载
try
{
baseFont
=
BaseFont
.
createFont
(
resourcePath
,
BaseFont
.
IDENTITY_H
,
BaseFont
.
EMBEDDED
);
log
.
info
(
"成功从classpath加载繁体楷体: {}"
,
resourcePath
);
}
catch
(
IOException
ioException
)
{
log
.
error
(
"classpath路径加载失败,使用备用字体"
,
ioException
);
}
}
}
// 如果还是失败,使用备用字体
if
(
baseFont
==
null
)
{
log
.
warn
(
"繁体楷体加载失败,使用STSong-Light"
);
baseFont
=
BaseFont
.
createFont
(
"STSong-Light"
,
"UniGB-UCS2-H"
,
BaseFont
.
EMBEDDED
);
}
// 创建字体样式
this
.
chineseFont
=
new
Font
(
baseFont
,
CONTENT_FONT_SIZE
,
Font
.
NORMAL
,
TEXT_COLOR
);
this
.
chineseBoldFont
=
new
Font
(
baseFont
,
CONTENT_FONT_SIZE
,
Font
.
BOLD
,
TEXT_COLOR
);
this
.
chineseTitleFont
=
new
Font
(
baseFont
,
SECTION_TITLE_FONT_SIZE
,
Font
.
BOLD
,
TEXT_COLOR
);
this
.
chineseRedTitleFont
=
new
Font
(
baseFont
,
MAIN_TITLE_FONT_SIZE
,
Font
.
BOLD
,
RED_TITLE_COLOR
);
// 使用主标题字号
}
catch
(
Exception
e
)
{
log
.
error
(
"字体初始化失败"
,
e
);
throw
new
DocumentException
(
"字体初始化失败: "
+
e
.
getMessage
());
}
}
/**
* 金额格式化
*/
private
String
formatAmount
(
BigDecimal
amount
)
{
if
(
amount
==
null
)
return
""
;
return
String
.
format
(
"%.2f"
,
amount
);
}
}
\ No newline at end of file
yd-csf-service/src/main/resources/font/DFKai-SB.ttf
0 → 100644
View file @
506522ed
File added
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