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");
|
}
|
}
|