From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsFileCenterService.java |  212 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 212 insertions(+), 0 deletions(-)

diff --git a/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsFileCenterService.java b/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsFileCenterService.java
new file mode 100644
index 0000000..ab6af1a
--- /dev/null
+++ b/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/DmsFileCenterService.java
@@ -0,0 +1,212 @@
+package jnpf.dmsService;
+
+import jnpf.base.UserInfo;
+import jnpf.dmsEntity.permission.model.DmsSubjectSet;
+import jnpf.dmsEntity.permission.vo.DmsCursorPageVO;
+import jnpf.dmsEntity.permission.vo.DmsFileCenterItemVO;
+import jnpf.dmsMapper.DmsFileCenterMapper;
+import jnpf.dmsPermission.DmsCurrentIdentity;
+import jnpf.dmsPermission.DmsFileCenterCursorCodec;
+import jnpf.dmsPermission.DmsFileCenterQuery;
+import jnpf.dmsPermission.DmsPermissionError;
+import jnpf.dmsPermission.DmsPermissionException;
+import jnpf.dmsPermission.DmsPermissionGroupMembershipResolver;
+import jnpf.dmsPermission.DmsPermissionProperties;
+import jnpf.dmsPermission.DmsSubjectResolver;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Function;
+
+@Service
+@RequiredArgsConstructor
+public class DmsFileCenterService {
+    private static final String FOLDER_CURSOR = "FOLDER";
+    private static final String CURRENT_CURSOR = "CURRENT_FOLDER";
+    private static final String HISTORICAL_CURSOR = "HISTORICAL_FOLDER";
+    private static final String DOCUMENT_VERSIONS_CURSOR = "DOCUMENT_VERSIONS";
+    private static final String SHARED_CURRENT_CURSOR = "SHARED_CURRENT";
+    private static final String SHARED_HISTORICAL_CURSOR = "SHARED_HISTORICAL";
+
+    private final DmsCurrentIdentity currentIdentity;
+    private final DmsSubjectResolver subjectResolver;
+    private final DmsPermissionGroupMembershipResolver groupMembershipResolver;
+    private final DmsPermissionProperties properties;
+    private final DmsFileCenterCursorCodec cursorCodec;
+    private final DmsFileCenterMapper mapper;
+
+    @Transactional(readOnly = true)
+    public DmsCursorPageVO<DmsFileCenterItemVO> rootFolders(String cursor, Integer pageSize) {
+        return folders(null, cursor, pageSize);
+    }
+
+    @Transactional(readOnly = true)
+    public DmsCursorPageVO<DmsFileCenterItemVO> childFolders(UUID parentId, String cursor,
+                                                             Integer pageSize) {
+        return folders(parentId, cursor, pageSize);
+    }
+
+    @Transactional(readOnly = true)
+    public DmsCursorPageVO<DmsFileCenterItemVO> currentDocuments(UUID folderId, String cursor,
+                                                                 Integer pageSize, String keyword) {
+        DmsFileCenterQuery query = query();
+        query.setFolderId(folderId);
+        query.setKeyword(normalizeKeyword(keyword));
+        int limit = pageSize(pageSize);
+        String fingerprint = cursorCodec.fingerprint(query.getKeyword());
+        applyCursor(query, cursorCodec.decode(cursor, CURRENT_CURSOR, query.getTenantId(),
+                query.getUserId(), folderId, fingerprint));
+        query.setLimit(limit + 1);
+        return page(mapper.selectCurrentDocuments(query), limit,
+                item -> cursorCodec.encode(CURRENT_CURSOR, query.getTenantId(), query.getUserId(),
+                        folderId, fingerprint, cursor(item)));
+    }
+
+    @Transactional(readOnly = true)
+    public DmsCursorPageVO<DmsFileCenterItemVO> historicalVersions(UUID folderId, String cursor,
+                                                                   Integer pageSize, String keyword) {
+        DmsFileCenterQuery query = query();
+        query.setFolderId(folderId);
+        query.setKeyword(normalizeKeyword(keyword));
+        int limit = pageSize(pageSize);
+        String fingerprint = cursorCodec.fingerprint(query.getKeyword());
+        applyCursor(query, cursorCodec.decode(cursor, HISTORICAL_CURSOR, query.getTenantId(),
+                query.getUserId(), folderId, fingerprint));
+        query.setLimit(limit + 1);
+        return page(mapper.selectHistoricalVersions(query), limit,
+                item -> cursorCodec.encode(HISTORICAL_CURSOR, query.getTenantId(), query.getUserId(),
+                        folderId, fingerprint, cursor(item)));
+    }
+
+    @Transactional(readOnly = true)
+    public DmsCursorPageVO<DmsFileCenterItemVO> documentVersions(UUID documentId, String cursor,
+                                                                 Integer pageSize) {
+        DmsFileCenterQuery query = query();
+        query.setDocumentId(documentId);
+        int limit = pageSize(pageSize);
+        String fingerprint = cursorCodec.fingerprint(null);
+        applyCursor(query, cursorCodec.decode(cursor, DOCUMENT_VERSIONS_CURSOR, query.getTenantId(),
+                query.getUserId(), documentId, fingerprint));
+        query.setLimit(limit + 1);
+        return page(mapper.selectDocumentVersions(query), limit,
+                item -> cursorCodec.encode(DOCUMENT_VERSIONS_CURSOR, query.getTenantId(), query.getUserId(),
+                        documentId, fingerprint, cursor(item)));
+    }
+
+    @Transactional(readOnly = true)
+    public DmsCursorPageVO<DmsFileCenterItemVO> sharedDocuments(String center, String cursor,
+                                                                Integer pageSize) {
+        boolean historical = normalizeCenter(center);
+        String cursorKind = historical ? SHARED_HISTORICAL_CURSOR : SHARED_CURRENT_CURSOR;
+        DmsFileCenterQuery query = query();
+        int limit = pageSize(pageSize);
+        String fingerprint = cursorCodec.fingerprint(null);
+        applyCursor(query, cursorCodec.decode(cursor, cursorKind, query.getTenantId(),
+                query.getUserId(), null, fingerprint));
+        query.setLimit(limit + 1);
+        List<DmsFileCenterItemVO> rows = historical
+                ? mapper.selectSharedHistoricalVersions(query) : mapper.selectSharedDocuments(query);
+        return page(rows, limit,
+                item -> cursorCodec.encode(cursorKind, query.getTenantId(), query.getUserId(),
+                        null, fingerprint, cursor(item)));
+    }
+
+    private DmsCursorPageVO<DmsFileCenterItemVO> folders(UUID parentId, String cursor,
+                                                         Integer pageSize) {
+        DmsFileCenterQuery query = query();
+        query.setParentId(parentId);
+        int limit = pageSize(pageSize);
+        String fingerprint = cursorCodec.fingerprint(null);
+        applyCursor(query, cursorCodec.decode(cursor, FOLDER_CURSOR, query.getTenantId(),
+                query.getUserId(), parentId, fingerprint));
+        query.setLimit(limit + 1);
+        return page(mapper.selectFolders(query), limit,
+                item -> cursorCodec.encode(FOLDER_CURSOR, query.getTenantId(), query.getUserId(),
+                        parentId, fingerprint, cursor(item)));
+    }
+
+    private DmsFileCenterQuery query() {
+        UserInfo user = currentIdentity.requireUser();
+        DmsFileCenterQuery query = new DmsFileCenterQuery();
+        query.setTenantId(currentIdentity.tenantId(user));
+        query.setUserId(user.getUserId().trim());
+        query.setAdministrator(currentIdentity.isPermissionAdministrator());
+        if (query.isAdministrator()) {
+            return query;
+        }
+        DmsSubjectSet subjects = subjectResolver.resolve(user);
+        groupMembershipResolver.resolveAll(subjects, properties.getMaxPermissionGroupScan());
+        query.setDirectOrgIds(new ArrayList<>(subjects.getDirectOrgIds()));
+        query.setAncestorOrgIds(new ArrayList<>(subjects.getAncestorOrgIds()));
+        query.setPositionIds(new ArrayList<>(subjects.getPositionIds()));
+        query.setRoleIds(new ArrayList<>(subjects.getRoleIds()));
+        query.setPermissionGroupIds(new ArrayList<>(subjects.getPermissionGroupIds()));
+        return query;
+    }
+
+    private void applyCursor(DmsFileCenterQuery query, DmsFileCenterCursorCodec.Cursor cursor) {
+        query.setCursorName(cursor.getName());
+        query.setCursorDocumentId(cursor.getDocumentId());
+        query.setCursorVersionNo(cursor.getVersionNo());
+        query.setCursorId(cursor.getId());
+    }
+
+    private DmsFileCenterCursorCodec.Cursor cursor(DmsFileCenterItemVO item) {
+        return new DmsFileCenterCursorCodec.Cursor(
+                item.getName(), item.getDocumentId(), item.getVersionNo(), item.getId());
+    }
+
+    private DmsCursorPageVO<DmsFileCenterItemVO> page(
+            List<DmsFileCenterItemVO> values, int limit, Function<DmsFileCenterItemVO, String> encoder) {
+        List<DmsFileCenterItemVO> rows = values == null
+                ? Collections.<DmsFileCenterItemVO>emptyList() : values;
+        boolean hasMore = rows.size() > limit;
+        if (hasMore) {
+            rows = new ArrayList<>(rows.subList(0, limit));
+        }
+        DmsCursorPageVO<DmsFileCenterItemVO> result = new DmsCursorPageVO<>();
+        result.setList(rows);
+        result.setHasMore(hasMore);
+        if (hasMore && !rows.isEmpty()) {
+            result.setNextCursor(encoder.apply(rows.get(rows.size() - 1)));
+        }
+        return result;
+    }
+
+    private int pageSize(Integer requested) {
+        int value = requested == null ? properties.getDefaultPageSize() : requested;
+        if (value < 1 || value > properties.getMaxPageSize()) {
+            throw DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST,
+                    "pageSize 蹇呴』鍦� 1 鍒� " + properties.getMaxPageSize() + " 涔嬮棿");
+        }
+        return value;
+    }
+
+    private String normalizeKeyword(String value) {
+        if (value == null || value.trim().isEmpty()) {
+            return null;
+        }
+        String normalized = value.trim();
+        if (normalized.length() > 200) {
+            throw DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST,
+                    "keyword 闀垮害涓嶈兘瓒呰繃 200 涓瓧绗�");
+        }
+        return normalized;
+    }
+
+    private boolean normalizeCenter(String value) {
+        if (value == null || value.trim().isEmpty() || "CURRENT".equalsIgnoreCase(value.trim())) {
+            return false;
+        }
+        if ("HISTORICAL".equalsIgnoreCase(value.trim())) {
+            return true;
+        }
+        throw DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST,
+                "center 蹇呴』鏄� CURRENT 鎴� HISTORICAL");
+    }
+}

--
Gitblit v1.8.0