feat(report): 优化文档模板中数据行插入的分页处理
- 在数据行锚点后有内容时自动添加分页符,确保剩余内容另起新页 - 新增 hasContentAfterBookmark 方法判断锚点后是否存在有意义内容 - 避免锚点在文档末尾时产生多余空白页,保持存量模板兼容性 - 实现智能分页逻辑,仅对非空文本段落和表格等有效内容进行分页处理
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
package com.njcn.gather.detection.controller;
|
||||||
|
|
||||||
|
import com.njcn.common.pojo.annotation.OperateInfo;
|
||||||
|
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||||
|
import com.njcn.common.pojo.response.HttpResult;
|
||||||
|
import com.njcn.gather.detection.lock.DetectionLock;
|
||||||
|
import com.njcn.gather.detection.lock.DetectionLockManager;
|
||||||
|
import com.njcn.gather.detection.pojo.vo.DetectionLockHolderVO;
|
||||||
|
import com.njcn.web.controller.BaseController;
|
||||||
|
import com.njcn.web.utils.HttpResultUtil;
|
||||||
|
import com.njcn.web.utils.RequestUtil;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测互斥锁管理接口。
|
||||||
|
* - GET /detection/lock/current 查询当前持锁状态;空闲返回 data=null
|
||||||
|
* - POST /detection/lock/forceRelease 管理员强制释放
|
||||||
|
*
|
||||||
|
* 鉴权:默认由 AuthGlobalFilter 做 JWT 校验,登录用户均可访问;
|
||||||
|
* 强释操作通过 @OperateInfo 落审计日志,谁操作谁担责。
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Api(tags = "检测互斥锁")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/detection/lock")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LockController extends BaseController {
|
||||||
|
|
||||||
|
@GetMapping("/current")
|
||||||
|
@ApiOperation("查询当前持锁状态;空闲返回 data=null")
|
||||||
|
public HttpResult<DetectionLockHolderVO> current() {
|
||||||
|
String methodDescribe = getMethodDescribe("current");
|
||||||
|
DetectionLock cur = DetectionLockManager.getInstance().getCurrent();
|
||||||
|
DetectionLockHolderVO data = cur == null ? null : DetectionLockManager.toHolderVO(cur);
|
||||||
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, data, methodDescribe);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/forceRelease")
|
||||||
|
@OperateInfo
|
||||||
|
@ApiOperation("管理员强制释放检测锁")
|
||||||
|
public HttpResult<?> forceRelease() {
|
||||||
|
String methodDescribe = getMethodDescribe("forceRelease");
|
||||||
|
String operator = RequestUtil.getUserId();
|
||||||
|
DetectionLockManager.getInstance().forceRelease(operator, "ADMIN_FORCE");
|
||||||
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1270,6 +1270,11 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
bookmarkInfo = BookmarkUtil.getBookmarkInfo(BookmarkEnum.DATA_LINE.getKey(), bookmarks);
|
bookmarkInfo = BookmarkUtil.getBookmarkInfo(BookmarkEnum.DATA_LINE.getKey(), bookmarks);
|
||||||
todoInsertList = dealDataLine(detailDocumentPart, devReportParam, pqDevVO, resultMap);
|
todoInsertList = dealDataLine(detailDocumentPart, devReportParam, pqDevVO, resultMap);
|
||||||
if (Objects.nonNull(bookmarkInfo) && CollectionUtil.isNotEmpty(todoInsertList)) {
|
if (Objects.nonNull(bookmarkInfo) && CollectionUtil.isNotEmpty(todoInsertList)) {
|
||||||
|
// 锚点位于 base 模板中间(其后仍有有效内容)时,在数据块末尾补一个分页符,
|
||||||
|
// 让 base 剩余部分另起新页;锚点在文档末尾时不加,存量模板行为不变
|
||||||
|
if (hasContentAfterBookmark(bookmarkInfo)) {
|
||||||
|
todoInsertList.add(Docx4jUtil.getPageBreak());
|
||||||
|
}
|
||||||
BookmarkUtil.insertElement(bookmarkInfo, todoInsertList);
|
BookmarkUtil.insertElement(bookmarkInfo, todoInsertList);
|
||||||
BookmarkUtil.removeBookmark(bookmarkInfo);
|
BookmarkUtil.removeBookmark(bookmarkInfo);
|
||||||
}
|
}
|
||||||
@@ -1322,6 +1327,40 @@ public class PqReportServiceImpl extends ServiceImpl<PqReportMapper, PqReport> i
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断书签段落之后是否还有有意义的内容(非空文本段落,或表格等非段落元素)。
|
||||||
|
* <p>
|
||||||
|
* 用于数模式 DATA_LINE 锚点位于 base 模板中间时,决定是否在插入的数据块末尾追加分页符,
|
||||||
|
* 使 base 剩余部分另起新页;书签在文档末尾(其后仅剩空段落)时返回 false,不追加分页符,
|
||||||
|
* 避免末尾凭空多出一页空白,存量模板(锚点在末尾)行为保持不变。
|
||||||
|
* <p>
|
||||||
|
* 注:仅以文本判断段落是否有意义,纯图片段落不会被识别为有效内容。
|
||||||
|
*
|
||||||
|
* @param bookmarkInfo 书签信息
|
||||||
|
* @return 书签之后存在有意义内容时返回 true
|
||||||
|
*/
|
||||||
|
private boolean hasContentAfterBookmark(BookmarkUtil.BookmarkInfo bookmarkInfo) {
|
||||||
|
List<Object> parentContent = bookmarkInfo.parentContainer.getContent();
|
||||||
|
int idx = parentContent.indexOf(bookmarkInfo.parentParagraph);
|
||||||
|
if (idx < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = idx + 1; i < parentContent.size(); i++) {
|
||||||
|
Object obj = parentContent.get(i);
|
||||||
|
Object realObj = (obj instanceof JAXBElement) ? ((JAXBElement<?>) obj).getValue() : obj;
|
||||||
|
if (realObj instanceof P) {
|
||||||
|
// 非空文本段落才算有意义,纯空段落不触发分页
|
||||||
|
if (StrUtil.isNotBlank(Docx4jUtil.getTextFromP((P) realObj))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 表格等非段落元素一律视为有意义内容
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 如何处理结果性数据进文档,各省级平台的结果表格不一致,如何做到一致
|
* 如何处理结果性数据进文档,各省级平台的结果表格不一致,如何做到一致
|
||||||
|
|||||||
Reference in New Issue
Block a user