This commit is contained in:
2025-12-04 10:35:11 +08:00
parent b0e8974d6c
commit 68def7e08b
7 changed files with 184 additions and 154 deletions

View File

@@ -270,25 +270,31 @@ func (r *DatabaseTableRenderer) safeSplitText(pdf *gofpdf.Fpdf, text string, wid
// 如果文本为空或宽度无效,返回单行
if text == "" || width <= 0 {
if text == "" {
return []string{""}
}
return []string{text}
}
// 检查文本长度,如果太短可能不需要分割
if len([]rune(text)) <= 1 {
return []string{text}
}
// 使用匿名函数和recover保护SplitText调用
var lines []string
var panicOccurred bool
func() {
defer func() {
if rec := recover(); rec != nil {
r.logger.Warn("SplitText发生panic使用估算值",
zap.Any("error", rec),
zap.String("text_preview", func() string {
if len(text) > 50 {
return text[:50] + "..."
}
return text
}()),
zap.Float64("width", width))
panicOccurred = true
// 静默处理,不记录日志
// 如果panic发生使用估算值
charCount := len([]rune(text))
if charCount == 0 {
lines = []string{""}
return
}
estimatedLines := math.Max(1, math.Ceil(float64(charCount)/20))
lines = make([]string, int(estimatedLines))
if estimatedLines == 1 {
@@ -316,12 +322,27 @@ func (r *DatabaseTableRenderer) safeSplitText(pdf *gofpdf.Fpdf, text string, wid
lines = pdf.SplitText(text, width)
}()
// 如果lines为nil或空返回单行
if lines == nil || len(lines) == 0 {
// 如果panic发生或lines为nil或空使用后备方案
if panicOccurred || lines == nil || len(lines) == 0 {
// 如果文本不为空,至少返回一行
if text != "" {
return []string{text}
}
return []string{""}
}
// 过滤掉空行(但保留至少一行)
nonEmptyLines := make([]string, 0, len(lines))
for _, line := range lines {
if strings.TrimSpace(line) != "" {
nonEmptyLines = append(nonEmptyLines, line)
}
}
if len(nonEmptyLines) == 0 {
return []string{text}
}
return lines
return nonEmptyLines
}
// renderHeader 渲染表头
@@ -450,6 +471,10 @@ func (r *DatabaseTableRenderer) renderRows(pdf *gofpdf.Fpdf, rows [][]string, co
validRowIndex++
// 计算这一行的最大高度
// 确保lineHt有效
if lineHt <= 0 {
lineHt = 5.0 // 默认行高
}
maxCellHeight := lineHt * 2.0 // 使用合理的最小高度
for j := 0; j < numCols && j < len(row); j++ {
cell := row[j]
@@ -471,12 +496,32 @@ func (r *DatabaseTableRenderer) renderRows(pdf *gofpdf.Fpdf, rows [][]string, co
lines = []string{cell}
}
cellHeight := float64(len(lines)) * lineHt
// 确保lines不为空且有效
if len(lines) == 0 || (len(lines) == 1 && lines[0] == "") {
lines = []string{cell}
if lines[0] == "" {
lines[0] = " " // 至少保留一个空格避免高度为0
}
}
// 计算单元格高度确保不会出现Inf或NaN
lineCount := float64(len(lines))
if lineCount <= 0 {
lineCount = 1
}
if lineHt <= 0 {
lineHt = 5.0 // 默认行高
}
cellHeight := lineCount * lineHt
// 添加上下内边距
cellHeight += lineHt * 0.8 // 上下各0.4倍行高的内边距
if cellHeight < lineHt*2.0 {
cellHeight = lineHt * 2.0
}
// 检查是否为有效数值
if math.IsInf(cellHeight, 0) || math.IsNaN(cellHeight) {
cellHeight = lineHt * 2.0
}
if cellHeight > maxCellHeight {
maxCellHeight = cellHeight
}
@@ -545,10 +590,7 @@ func (r *DatabaseTableRenderer) renderRows(pdf *gofpdf.Fpdf, rows [][]string, co
func() {
defer func() {
if rec := recover(); rec != nil {
r.logger.Warn("MultiCell渲染失败",
zap.Any("error", rec),
zap.Int("row_index", rowIndex),
zap.Int("col_index", j))
// 静默处理,不记录日志
}
}()
// 使用正常的行高,文本已经垂直居中
@@ -561,8 +603,20 @@ func (r *DatabaseTableRenderer) renderRows(pdf *gofpdf.Fpdf, rows [][]string, co
currentX += colW
}
// 检查maxCellHeight是否为有效数值
if math.IsInf(maxCellHeight, 0) || math.IsNaN(maxCellHeight) {
maxCellHeight = lineHt * 2.0
}
if maxCellHeight <= 0 {
maxCellHeight = lineHt * 2.0
}
// 移动到下一行
pdf.SetXY(15.0, startY+maxCellHeight)
nextY := startY + maxCellHeight
if math.IsInf(nextY, 0) || math.IsNaN(nextY) {
nextY = pdf.GetY() + lineHt*2.0
}
pdf.SetXY(15.0, nextY)
}
}