diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/mapper/AdminUserMapper.java b/backend-java/src/main/java/com/nanri/aiimage/common/mapper/AdminUserMapper.java similarity index 59% rename from backend-java/src/main/java/com/nanri/aiimage/modules/permission/mapper/AdminUserMapper.java rename to backend-java/src/main/java/com/nanri/aiimage/common/mapper/AdminUserMapper.java index 4e0c7efe..90982714 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/mapper/AdminUserMapper.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/mapper/AdminUserMapper.java @@ -1,7 +1,7 @@ -package com.nanri.aiimage.modules.permission.mapper; +package com.nanri.aiimage.common.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import org.apache.ibatis.annotations.Mapper; @Mapper diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/mapper/ShopManageGroupMapper.java b/backend-java/src/main/java/com/nanri/aiimage/common/mapper/ShopManageGroupMapper.java similarity index 98% rename from backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/mapper/ShopManageGroupMapper.java rename to backend-java/src/main/java/com/nanri/aiimage/common/mapper/ShopManageGroupMapper.java index fa3dd509..8a9b6f03 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/mapper/ShopManageGroupMapper.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/mapper/ShopManageGroupMapper.java @@ -1,7 +1,7 @@ -package com.nanri.aiimage.modules.shopkey.mapper; +package com.nanri.aiimage.common.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/model/entity/AdminUserEntity.java b/backend-java/src/main/java/com/nanri/aiimage/common/model/entity/AdminUserEntity.java similarity index 92% rename from backend-java/src/main/java/com/nanri/aiimage/modules/permission/model/entity/AdminUserEntity.java rename to backend-java/src/main/java/com/nanri/aiimage/common/model/entity/AdminUserEntity.java index 99fed96c..d51497ae 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/model/entity/AdminUserEntity.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/model/entity/AdminUserEntity.java @@ -1,4 +1,4 @@ -package com.nanri.aiimage.modules.permission.model.entity; +package com.nanri.aiimage.common.model.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/model/entity/ShopManageGroupEntity.java b/backend-java/src/main/java/com/nanri/aiimage/common/model/entity/ShopManageGroupEntity.java similarity index 91% rename from backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/model/entity/ShopManageGroupEntity.java rename to backend-java/src/main/java/com/nanri/aiimage/common/model/entity/ShopManageGroupEntity.java index 33e4dee2..a69e52cc 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/model/entity/ShopManageGroupEntity.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/model/entity/ShopManageGroupEntity.java @@ -1,4 +1,4 @@ -package com.nanri.aiimage.modules.shopkey.model.entity; +package com.nanri.aiimage.common.model.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/support/AdminAuthSupport.java b/backend-java/src/main/java/com/nanri/aiimage/common/security/AdminAuthSupport.java similarity index 95% rename from backend-java/src/main/java/com/nanri/aiimage/modules/admin/support/AdminAuthSupport.java rename to backend-java/src/main/java/com/nanri/aiimage/common/security/AdminAuthSupport.java index 6ac2390f..a9e2b688 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/support/AdminAuthSupport.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/security/AdminAuthSupport.java @@ -1,10 +1,10 @@ -package com.nanri.aiimage.modules.admin.support; +package com.nanri.aiimage.common.security; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.auth.service.JwtService; -import com.nanri.aiimage.modules.auth.support.DeviceSessionPolicy; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.JwtService; +import com.nanri.aiimage.common.security.DeviceSessionPolicy; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import io.jsonwebtoken.Claims; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; @@ -12,7 +12,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; -import com.nanri.aiimage.modules.auth.config.AuthProperties; +import com.nanri.aiimage.common.security.AuthProperties; import org.springframework.beans.factory.annotation.Value; import java.nio.charset.StandardCharsets; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/config/AuthProperties.java b/backend-java/src/main/java/com/nanri/aiimage/common/security/AuthProperties.java similarity index 93% rename from backend-java/src/main/java/com/nanri/aiimage/modules/auth/config/AuthProperties.java rename to backend-java/src/main/java/com/nanri/aiimage/common/security/AuthProperties.java index 54a44e18..7fba8829 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/config/AuthProperties.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/security/AuthProperties.java @@ -1,4 +1,4 @@ -package com.nanri.aiimage.modules.auth.config; +package com.nanri.aiimage.common.security; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/support/DeviceSessionPolicy.java b/backend-java/src/main/java/com/nanri/aiimage/common/security/DeviceSessionPolicy.java similarity index 98% rename from backend-java/src/main/java/com/nanri/aiimage/modules/auth/support/DeviceSessionPolicy.java rename to backend-java/src/main/java/com/nanri/aiimage/common/security/DeviceSessionPolicy.java index 7e5ac418..bd0a41a0 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/support/DeviceSessionPolicy.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/security/DeviceSessionPolicy.java @@ -1,4 +1,4 @@ -package com.nanri.aiimage.modules.auth.support; +package com.nanri.aiimage.common.security; import com.nanri.aiimage.common.exception.BusinessException; import io.jsonwebtoken.Claims; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/service/JwtService.java b/backend-java/src/main/java/com/nanri/aiimage/common/security/JwtService.java similarity index 97% rename from backend-java/src/main/java/com/nanri/aiimage/modules/auth/service/JwtService.java rename to backend-java/src/main/java/com/nanri/aiimage/common/security/JwtService.java index f93b170d..dbb69dc9 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/service/JwtService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/common/security/JwtService.java @@ -1,6 +1,6 @@ -package com.nanri.aiimage.modules.auth.service; +package com.nanri.aiimage.common.security; -import com.nanri.aiimage.modules.auth.config.AuthProperties; +import com.nanri.aiimage.common.security.AuthProperties; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; diff --git a/backend-java/src/main/java/com/nanri/aiimage/config/AdminApiGuardFilter.java b/backend-java/src/main/java/com/nanri/aiimage/config/AdminApiGuardFilter.java index 96237322..a20c0630 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/config/AdminApiGuardFilter.java +++ b/backend-java/src/main/java/com/nanri/aiimage/config/AdminApiGuardFilter.java @@ -3,7 +3,7 @@ package com.nanri.aiimage.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java index cb47af6b..f536a59a 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.admin.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.model.vo.PermissionMenuItemVo; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import com.nanri.aiimage.modules.permission.service.support.AdminMenuTreeBuilder; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminUserController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminUserController.java index 5f81fca8..c0658e2b 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminUserController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminUserController.java @@ -5,8 +5,8 @@ import com.nanri.aiimage.modules.admin.model.dto.AdminUserCreateRequest; import com.nanri.aiimage.modules.admin.model.dto.AdminUserUpdateRequest; import com.nanri.aiimage.modules.admin.model.vo.AdminUserListVo; import com.nanri.aiimage.modules.admin.service.AdminUserService; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/service/AdminUserService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/service/AdminUserService.java index 8a103e5d..c8e9f765 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/service/AdminUserService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/service/AdminUserService.java @@ -8,14 +8,14 @@ import com.nanri.aiimage.modules.admin.model.dto.AdminUserUpdateRequest; import com.nanri.aiimage.modules.admin.model.vo.AdminBriefVo; import com.nanri.aiimage.modules.admin.model.vo.AdminUserItemVo; import com.nanri.aiimage.modules.admin.model.vo.AdminUserListVo; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.admin.util.PinyinAbbrUtil; import com.nanri.aiimage.modules.auth.util.WerkzeugPasswordEncoder; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; +import com.nanri.aiimage.common.mapper.AdminUserMapper; import com.nanri.aiimage.modules.permission.model.dto.UserColumnPermissionUpdateRequest; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; -import com.nanri.aiimage.modules.usersecret.service.UserApiSecretService; +import com.nanri.aiimage.modules.admin.spi.UserSecretCleanupPort; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DuplicateKeyException; @@ -43,7 +43,7 @@ public class AdminUserService { private final WerkzeugPasswordEncoder passwordEncoder; private final AdminAuthSupport adminAuthSupport; private final PermissionMenuService permissionMenuService; - private final UserApiSecretService userApiSecretService; + private final UserSecretCleanupPort userSecretCleanupPort; public AdminUserListVo listUsers(AdminUserEntity currentUser, Integer page, Integer pageSize, String username, Long createdById, String roleFilter) { @@ -303,7 +303,7 @@ public class AdminUserService { if (affected == 0) { throw new BusinessException("用户不存在"); } - int secretRows = userApiSecretService.adminClearByUser(uid); + int secretRows = userSecretCleanupPort.adminClearByUser(uid); log.info("[admin-user] 用户已删除 uid={} 级联清理密钥行={}", uid, secretRows); } diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/spi/UserSecretCleanupPort.java b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/spi/UserSecretCleanupPort.java new file mode 100644 index 00000000..df86c051 --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/spi/UserSecretCleanupPort.java @@ -0,0 +1,12 @@ +package com.nanri.aiimage.modules.admin.spi; + +/** + * 删除用户时级联清理其密钥数据(2026-09 边界收敛:admin → usersecret 的类依赖改为端口)。 + * + *

实现方在 usersecret 模块;返回清理的行数用于日志。 + */ +public interface UserSecretCleanupPort { + + /** 清理该用户的全部密钥相关行,返回受影响行数。 */ + int adminClearByUser(Long userId); +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/service/AuthService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/auth/service/AuthService.java index 61f96398..b9bd1f9d 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/auth/service/AuthService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/auth/service/AuthService.java @@ -3,12 +3,12 @@ package com.nanri.aiimage.modules.auth.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.auth.config.AuthProperties; +import com.nanri.aiimage.common.security.AuthProperties; import com.nanri.aiimage.modules.auth.mapper.LoginUserMapper; import com.nanri.aiimage.modules.auth.model.dto.LoginRequest; import com.nanri.aiimage.modules.auth.model.entity.LoginUserEntity; import com.nanri.aiimage.modules.auth.model.vo.LoginResultVo; -import com.nanri.aiimage.modules.auth.support.DeviceSessionPolicy; +import com.nanri.aiimage.common.security.DeviceSessionPolicy; import com.nanri.aiimage.modules.auth.util.WerkzeugPasswordEncoder; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import io.jsonwebtoken.Claims; @@ -21,6 +21,7 @@ import java.time.Duration; import java.time.Instant; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import com.nanri.aiimage.common.security.JwtService; @Service @RequiredArgsConstructor diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/brand/service/BrandResultFileJobHandler.java b/backend-java/src/main/java/com/nanri/aiimage/modules/brand/service/BrandResultFileJobHandler.java index 8bc0778e..72c41112 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/brand/service/BrandResultFileJobHandler.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/brand/service/BrandResultFileJobHandler.java @@ -7,8 +7,8 @@ import com.nanri.aiimage.modules.task.model.entity.TaskFileJobEntity; /** * BRAND 结果文件 Job Handler(04 注册表)。 - * 注意:resultFileUrl 解析特例(resolveResultObjectKey,无 resultId 也走) - * 保留在 Worker 公共路径 resolveResultFileUrl,Handler 不接管 URL 解析; + * resultFileUrl 解析特例(resolveResultObjectKey,无 resultId 也走)由本 Handler 的 + * resolveResultFileUrl 钩子承担(2026-09:原实现在 Worker 内直接 import 本模块,构成 task → 业务依赖); * cleanup 为空(原 cleanupAfterSuccess 无 BRAND 分支)。 */ public class BrandResultFileJobHandler implements ResultFileJobHandler { @@ -32,4 +32,12 @@ public class BrandResultFileJobHandler implements ResultFileJobHandler { brandTaskService.processResultFileJob(job); return true; } + + @Override + public String resolveResultFileUrl(TaskFileJobEntity job) { + if (job == null || job.getTaskId() == null) { + return null; + } + return brandTaskService.resolveResultObjectKey(job.getTaskId()); + } } diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataController.java index 429f72c0..cfc01900 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataController.java @@ -2,7 +2,7 @@ package com.nanri.aiimage.modules.dedupe.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.common.util.DownloadHeaderUtil; import com.nanri.aiimage.modules.dedupe.model.dto.DedupeTotalDataCreateRequest; import com.nanri.aiimage.modules.dedupe.model.dto.DedupeTotalDataUpdateRequest; @@ -12,7 +12,7 @@ import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataImportVo; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataItemVo; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataPageVo; import com.nanri.aiimage.modules.dedupe.service.DedupeTotalDataService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java index 6e64a1c6..34410309 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java @@ -15,10 +15,10 @@ import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataImportStartVo; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataImportVo; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataItemVo; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataPageVo; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; -import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Cell; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/service/GroupDeletionGuard.java b/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/service/GroupDeletionGuard.java new file mode 100644 index 00000000..e0caf129 --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/dedupe/service/GroupDeletionGuard.java @@ -0,0 +1,28 @@ +package com.nanri.aiimage.modules.dedupe.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.nanri.aiimage.common.exception.BusinessException; +import com.nanri.aiimage.modules.dedupe.mapper.DedupeTotalDataMapper; +import com.nanri.aiimage.modules.dedupe.model.entity.DedupeTotalDataEntity; +import com.nanri.aiimage.modules.shopkey.spi.GroupDeletionGuardPort; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 分组删除守卫:去重总数据(2026-09 从 shopkey 收回本模块,文案保持不变)。 + */ +@Service +@RequiredArgsConstructor +public class GroupDeletionGuard implements GroupDeletionGuardPort { + + private final DedupeTotalDataMapper dedupeTotalDataMapper; + + @Override + public void ensureNoGroupData(Long groupId) { + Long count = dedupeTotalDataMapper.selectCount(new LambdaQueryWrapper() + .eq(DedupeTotalDataEntity::getGroupId, groupId)); + if (count != null && count > 0) { + throw new BusinessException("该分组下存在数据去重总数据,无法删除"); + } + } +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/digitalhuman/controller/DigitalHumanVersionController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/digitalhuman/controller/DigitalHumanVersionController.java index e60bc09a..d0a5a6e7 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/digitalhuman/controller/DigitalHumanVersionController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/digitalhuman/controller/DigitalHumanVersionController.java @@ -1,7 +1,7 @@ package com.nanri.aiimage.modules.digitalhuman.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.digitalhuman.model.dto.UploadVersionRequest; import com.nanri.aiimage.modules.digitalhuman.model.vo.DigitalHumanVersionVo; import com.nanri.aiimage.modules.digitalhuman.service.DigitalHumanVersionService; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/controller/ImageHistoryController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/controller/ImageHistoryController.java index c99360f6..ec4cc1b7 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/controller/ImageHistoryController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/controller/ImageHistoryController.java @@ -2,10 +2,10 @@ package com.nanri.aiimage.modules.imagehistory.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.imagehistory.model.vo.ImageHistoryListVo; import com.nanri.aiimage.modules.imagehistory.service.ImageHistoryService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryService.java index 36c7e644..680068c8 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryService.java @@ -8,8 +8,8 @@ import com.nanri.aiimage.modules.imagehistory.mapper.ImageHistoryMapper; import com.nanri.aiimage.modules.imagehistory.model.entity.ImageHistoryEntity; import com.nanri.aiimage.modules.imagehistory.model.vo.ImageHistoryItemVo; import com.nanri.aiimage.modules.imagehistory.model.vo.ImageHistoryListVo; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/AdminImageVideoTaskController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/AdminImageVideoTaskController.java index 6950d75a..30f60330 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/AdminImageVideoTaskController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/AdminImageVideoTaskController.java @@ -3,7 +3,7 @@ package com.nanri.aiimage.modules.imagevideo.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.common.util.DownloadHeaderUtil; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.imagevideo.service.ImageVideoAdminTaskService; import com.nanri.aiimage.modules.imagevideo.service.ImageVideoAdminTaskService.VideoSelection; import com.nanri.aiimage.modules.imagevideo.service.ImageVideoAdminTaskService.ZipBundle; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/ImageVideoController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/ImageVideoController.java index f43d5050..4c1e3171 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/ImageVideoController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/imagevideo/controller/ImageVideoController.java @@ -2,8 +2,8 @@ package com.nanri.aiimage.modules.imagevideo.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.imagevideo.model.dto.DouyinCopyRequest; import com.nanri.aiimage.modules.imagevideo.model.dto.ImageVideoSecretSaveRequest; import com.nanri.aiimage.modules.imagevideo.model.dto.ImageVideoVoiceCloneRequest; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataController.java index 98e47eb9..9bb858d6 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataController.java @@ -2,13 +2,13 @@ package com.nanri.aiimage.modules.invalidasin.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.invalidasin.model.dto.InvalidAsinDataCreateRequest; import com.nanri.aiimage.modules.invalidasin.model.dto.InvalidAsinDataUpdateRequest; import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataItemVo; import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataPageVo; import com.nanri.aiimage.modules.invalidasin.service.InvalidAsinDataService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/service/GroupDeletionGuard.java b/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/service/GroupDeletionGuard.java new file mode 100644 index 00000000..eef76146 --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/service/GroupDeletionGuard.java @@ -0,0 +1,28 @@ +package com.nanri.aiimage.modules.invalidasin.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.nanri.aiimage.common.exception.BusinessException; +import com.nanri.aiimage.modules.invalidasin.mapper.InvalidAsinDataMapper; +import com.nanri.aiimage.modules.invalidasin.model.entity.InvalidAsinDataEntity; +import com.nanri.aiimage.modules.shopkey.spi.GroupDeletionGuardPort; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 分组删除守卫:品牌数据库(不符合 ASIN)数据(2026-09 从 shopkey 收回本模块,文案保持不变)。 + */ +@Service +@RequiredArgsConstructor +public class GroupDeletionGuard implements GroupDeletionGuardPort { + + private final InvalidAsinDataMapper invalidAsinDataMapper; + + @Override + public void ensureNoGroupData(Long groupId) { + Long count = invalidAsinDataMapper.selectCount(new LambdaQueryWrapper() + .eq(InvalidAsinDataEntity::getGroupId, groupId)); + if (count != null && count > 0) { + throw new BusinessException("该分组下存在品牌数据库数据,无法删除"); + } + } +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataService.java index 9abdf17e..c1732ced 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataService.java @@ -8,7 +8,7 @@ import com.nanri.aiimage.modules.invalidasin.model.dto.InvalidAsinDataUpdateRequ import com.nanri.aiimage.modules.invalidasin.model.entity.InvalidAsinDataEntity; import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataItemVo; import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataPageVo; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.shopkey.service.ShopManageGroupService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationController.java index edbf8c80..e8308625 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationController.java @@ -1,12 +1,12 @@ package com.nanri.aiimage.modules.notification.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.notification.model.dto.NotificationPageQuery; import com.nanri.aiimage.modules.notification.model.vo.NotificationPageVo; import com.nanri.aiimage.modules.notification.model.vo.NotificationSummaryVo; import com.nanri.aiimage.modules.notification.service.NotificationService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/NotificationController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/NotificationController.java index d2175af4..4046e59e 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/NotificationController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/controller/NotificationController.java @@ -1,12 +1,12 @@ package com.nanri.aiimage.modules.notification.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.notification.model.dto.NotificationPageQuery; import com.nanri.aiimage.modules.notification.model.vo.NotificationPageVo; import com.nanri.aiimage.modules.notification.model.vo.NotificationSummaryVo; import com.nanri.aiimage.modules.notification.service.NotificationService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchService.java index 6c804241..044e57fa 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchService.java @@ -1,9 +1,9 @@ package com.nanri.aiimage.modules.notification.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.support.UserDataScopeSupport; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationScanScheduler.java b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationScanScheduler.java index bcaa40ed..5ecd2d08 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationScanScheduler.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/service/NotificationScanScheduler.java @@ -9,8 +9,7 @@ import com.nanri.aiimage.modules.brand.mapper.BrandCrawlTaskMapper; import com.nanri.aiimage.modules.brand.model.entity.BrandCrawlTaskEntity; import com.nanri.aiimage.modules.task.mapper.FileTaskMapper; import com.nanri.aiimage.modules.task.model.entity.FileTaskEntity; -import com.nanri.aiimage.modules.usersecret.client.JikipProxyClient; -import com.nanri.aiimage.modules.usersecret.model.vo.UserApiSecretBalanceVo; +import com.nanri.aiimage.modules.notification.spi.ProxyBalancePort; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; @@ -67,7 +66,7 @@ public class NotificationScanScheduler { private final NotificationDispatchService notificationDispatchService; private final DistributedJobLockService distributedJobLockService; private final NotificationProperties properties; - private final JikipProxyClient jikipProxyClient; + private final ProxyBalancePort proxyBalancePort; /** 上次清理日期(每天最多清理一次;双节点由分布式锁保证只有一个实例执行)。 */ private volatile LocalDate lastCleanupDate; @@ -234,12 +233,12 @@ public class NotificationScanScheduler { /** jikip 探测:复用余额查询接口;未配置套餐信息时跳过(返回 null 不告警)。 */ private ProbeOutcome probeJikip() { try { - UserApiSecretBalanceVo balance = jikipProxyClient.fetchBalance(); - if (Boolean.TRUE.equals(balance.getAvailable())) { - return new ProbeOutcome(true, "余额接口可用 surplus=" + balance.getSurplus() - + " balance=" + balance.getBalance()); + ProxyBalancePort.ProxyBalanceSnapshot balance = proxyBalancePort.fetchBalance(); + if (balance.available()) { + return new ProbeOutcome(true, "余额接口可用 surplus=" + balance.surplus() + + " balance=" + balance.balance()); } - String message = balance.getMessage() == null ? "" : balance.getMessage(); + String message = balance.message() == null ? "" : balance.message(); if (message.contains("未配置")) { log.info("[notification-scan] jikip 探测跳过:{}", message); return null; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/notification/spi/ProxyBalancePort.java b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/spi/ProxyBalancePort.java new file mode 100644 index 00000000..bb25741c --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/notification/spi/ProxyBalancePort.java @@ -0,0 +1,26 @@ +package com.nanri.aiimage.modules.notification.spi; + +/** + * 代理余额探测(2026-09 边界收敛:notification → usersecret 的类依赖改为端口)。 + * + *

实现方在 usersecret 模块(复用其 jikip 客户端);通知巡检只做"能不能告警"的判断, + * 不关心上游返回结构,因此这里只暴露最小快照。 + */ +public interface ProxyBalancePort { + + /** + * 查询代理服务商余额。 + * + * @return 余额快照;调用异常由实现方抛出(调用方负责降级) + */ + ProxyBalanceSnapshot fetchBalance(); + + /** + * @param available 余额接口是否可用 + * @param surplus 剩余额度(上游口径,可能为 null) + * @param balance 账户余额(上游口径,可能为 null) + * @param message 上游提示信息(未配置套餐时含"未配置"字样,调用方据此跳过告警) + */ + record ProxyBalanceSnapshot(boolean available, String surplus, String balance, String message) { + } +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuController.java index 45bc9f04..687951cd 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuController.java @@ -1,12 +1,12 @@ package com.nanri.aiimage.modules.permission.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.permission.model.dto.PermissionMenuCreateRequest; import com.nanri.aiimage.modules.permission.model.dto.PermissionMenuUpdateRequest; import com.nanri.aiimage.modules.permission.model.dto.ImageVideoDataPermissionUpdateRequest; import com.nanri.aiimage.modules.permission.model.dto.UserColumnPermissionUpdateRequest; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.model.vo.PermissionMenuItemVo; import com.nanri.aiimage.modules.permission.model.vo.UserColumnIdsVo; import com.nanri.aiimage.modules.permission.model.vo.ImageVideoDataPermissionUserVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/service/PermissionMenuService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/permission/service/PermissionMenuService.java index 8ae1c348..d40e716c 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/service/PermissionMenuService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/permission/service/PermissionMenuService.java @@ -3,13 +3,13 @@ package com.nanri.aiimage.modules.permission.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; +import com.nanri.aiimage.common.mapper.AdminUserMapper; import com.nanri.aiimage.modules.permission.mapper.PermissionMenuMapper; import com.nanri.aiimage.modules.permission.mapper.UserColumnPermissionMapper; import com.nanri.aiimage.modules.permission.model.dto.PermissionMenuCreateRequest; import com.nanri.aiimage.modules.permission.model.dto.PermissionMenuUpdateRequest; import com.nanri.aiimage.modules.permission.model.dto.UserColumnPermissionUpdateRequest; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.model.entity.PermissionMenuEntity; import com.nanri.aiimage.modules.permission.model.entity.UserColumnPermissionEntity; import com.nanri.aiimage.modules.permission.model.vo.ImageVideoDataPermissionUserVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/support/UserDataScopeSupport.java b/backend-java/src/main/java/com/nanri/aiimage/modules/permission/support/UserDataScopeSupport.java index 7d31200e..3e5be769 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/permission/support/UserDataScopeSupport.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/permission/support/UserDataScopeSupport.java @@ -1,10 +1,10 @@ package com.nanri.aiimage.modules.permission.support; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; -import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/productcategory/controller/ProductCategoryController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/productcategory/controller/ProductCategoryController.java index 22fe4e9b..f242f210 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/productcategory/controller/ProductCategoryController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/productcategory/controller/ProductCategoryController.java @@ -2,7 +2,7 @@ package com.nanri.aiimage.modules.productcategory.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.util.DownloadHeaderUtil; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.productcategory.model.dto.ProductCategorySaveRequest; import com.nanri.aiimage.modules.productcategory.model.vo.ProductCategoryItemVo; import com.nanri.aiimage.modules.productcategory.model.vo.ProductCategoryListVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskController.java index 7dc56f1f..3359cf02 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskController.java @@ -4,8 +4,8 @@ import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.common.util.DownloadHeaderUtil; import com.nanri.aiimage.config.HttpClientPool; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import com.nanri.aiimage.modules.shopdatacrawl.service.ShopDataCrawlTaskService; import io.swagger.v3.oas.annotations.Operation; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTasksController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTasksController.java index 161d8e55..02fb293e 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTasksController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTasksController.java @@ -4,8 +4,8 @@ import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.common.util.DownloadHeaderUtil; import com.nanri.aiimage.config.HttpClientPool; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import com.nanri.aiimage.modules.shopdatacrawl.model.dto.ShopDataCrawlDownloadRowDto; import com.nanri.aiimage.modules.shopdatacrawl.service.ShopDataCrawlAdminTasksService; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlAdminTasksService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlAdminTasksService.java index 57ffbda0..b5ae77a2 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlAdminTasksService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlAdminTasksService.java @@ -12,7 +12,7 @@ import com.nanri.aiimage.modules.shopdatacrawl.model.dto.ShopDataCrawlAdminRow; import com.nanri.aiimage.modules.shopdatacrawl.model.dto.ShopDataCrawlDownloadRowDto; import com.nanri.aiimage.modules.shopdatacrawl.model.entity.ShopDataCrawlDailyFileEntity; import com.nanri.aiimage.modules.shopdatacrawl.model.entity.ShopDataCrawlDailyMemberEntity; -import com.nanri.aiimage.modules.shopduplicatecheck.mapper.ShopDuplicateCheckSourceMapper; +import com.nanri.aiimage.modules.shopdatacrawl.spi.ManagedShopNamesPort; import com.nanri.aiimage.modules.task.mapper.FileResultMapper; import com.nanri.aiimage.modules.task.model.entity.FileResultEntity; import com.nanri.aiimage.modules.task.service.TaskDistributedLockService; @@ -47,7 +47,7 @@ public class ShopDataCrawlAdminTasksService { private static final Set SUPPORTED_COUNTRIES = Set.of("DE", "UK", "FR", "IT", "ES"); private final ShopDataCrawlAdminTasksMapper adminTasksMapper; - private final ShopDuplicateCheckSourceMapper duplicateCheckSourceMapper; + private final ManagedShopNamesPort managedShopNamesPort; private final ShopDataCrawlItemMapper itemMapper; private final FileResultMapper fileResultMapper; private final ShopDataCrawlDailyFileService dailyFileService; @@ -215,7 +215,7 @@ public class ShopDataCrawlAdminTasksService { /** 非超管可管店铺名(trim+小写去重,与撞款可见口径一致);超管调用方传 null 表示全量。 */ public List resolveVisibleShopNameKeys(Long operatorId) { - List names = duplicateCheckSourceMapper.selectManagedShopNames(operatorId); + List names = managedShopNamesPort.selectManagedShopNames(operatorId); if (names == null || names.isEmpty()) { return List.of(); } diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/spi/ManagedShopNamesPort.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/spi/ManagedShopNamesPort.java new file mode 100644 index 00000000..537985a2 --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/spi/ManagedShopNamesPort.java @@ -0,0 +1,14 @@ +package com.nanri.aiimage.modules.shopdatacrawl.spi; + +import java.util.List; + +/** + * 可管店铺名查询(2026-09 边界收敛:shopdatacrawl → shopduplicatecheck 的 Mapper 直连改为端口)。 + * + *

实现方在 shopduplicatecheck 模块(口径与撞款可见范围一致)。 + */ +public interface ManagedShopNamesPort { + + /** 该操作人可管的店铺名;传 null 表示全量(超管调用方)。 */ + List selectManagedShopNames(Long operatorId); +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/controller/AdminShopDataDuplicateCheckController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/controller/AdminShopDataDuplicateCheckController.java index 321446c4..34dcca2a 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/controller/AdminShopDataDuplicateCheckController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/controller/AdminShopDataDuplicateCheckController.java @@ -3,8 +3,8 @@ package com.nanri.aiimage.modules.shopduplicatecheck.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.common.util.DownloadHeaderUtil; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import com.nanri.aiimage.modules.shopduplicatecheck.service.ShopDataDuplicateCheckImportService; import com.nanri.aiimage.modules.shopduplicatecheck.service.ShopDataDuplicateCheckQueryService; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/service/ManagedShopNamesPortAdapter.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/service/ManagedShopNamesPortAdapter.java new file mode 100644 index 00000000..1812b33e --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopduplicatecheck/service/ManagedShopNamesPortAdapter.java @@ -0,0 +1,23 @@ +package com.nanri.aiimage.modules.shopduplicatecheck.service; + +import com.nanri.aiimage.modules.shopdatacrawl.spi.ManagedShopNamesPort; +import com.nanri.aiimage.modules.shopduplicatecheck.mapper.ShopDuplicateCheckSourceMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 可管店铺名端口实现(2026-09 边界收敛):Mapper 与口径留在 shopduplicatecheck 模块内。 + */ +@Service +@RequiredArgsConstructor +public class ManagedShopNamesPortAdapter implements ManagedShopNamesPort { + + private final ShopDuplicateCheckSourceMapper sourceMapper; + + @Override + public List selectManagedShopNames(Long operatorId) { + return sourceMapper.selectManagedShopNames(operatorId); + } +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/QueryAsinController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/QueryAsinController.java index 6197e95a..80acc8d0 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/QueryAsinController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/QueryAsinController.java @@ -2,8 +2,8 @@ package com.nanri.aiimage.modules.shopkey.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.util.DownloadHeaderUtil; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.shopkey.model.dto.QueryAsinCountryUpdateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.QueryAsinCreateRequest; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinImportProgressVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopKeyController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopKeyController.java index 23b6623c..c6889ae4 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopKeyController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopKeyController.java @@ -1,7 +1,7 @@ package com.nanri.aiimage.modules.shopkey.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.shopkey.model.dto.ShopKeyCreateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.ShopKeyUpdateRequest; import com.nanri.aiimage.modules.shopkey.model.vo.ShopKeyItemVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopManageController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopManageController.java index 6efba37f..5a1a3490 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopManageController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/ShopManageController.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.shopkey.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.shopkey.model.dto.ShopManageCreateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.ShopManageGroupCreateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.ShopManageGroupUpdateRequest; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/SkipPriceAsinController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/SkipPriceAsinController.java index de4365c4..312ece5a 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/SkipPriceAsinController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/controller/SkipPriceAsinController.java @@ -2,8 +2,8 @@ package com.nanri.aiimage.modules.shopkey.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.util.DownloadHeaderUtil; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.shopkey.model.dto.SkipPriceAsinCountryUpdateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.SkipPriceAsinCreateRequest; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinImportProgressVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/QueryAsinService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/QueryAsinService.java index 42e2c1d8..a1dcb392 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/QueryAsinService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/QueryAsinService.java @@ -11,7 +11,7 @@ import com.nanri.aiimage.config.TaskPressureProperties; import com.nanri.aiimage.modules.shopkey.mapper.QueryAsinMapper; import com.nanri.aiimage.modules.shopkey.model.dto.QueryAsinCreateRequest; import com.nanri.aiimage.modules.shopkey.model.entity.QueryAsinEntity; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinImportProgressVo; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinImportStartVo; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinItemVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageGroupService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageGroupService.java index 1019e598..6d627f3f 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageGroupService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageGroupService.java @@ -2,24 +2,21 @@ package com.nanri.aiimage.modules.shopkey.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.shopkey.mapper.QueryAsinMapper; -import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper; +import com.nanri.aiimage.modules.shopkey.spi.GroupDeletionGuardPort; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMemberMapper; import com.nanri.aiimage.modules.shopkey.mapper.ShopManageMapper; import com.nanri.aiimage.modules.shopkey.mapper.SkipPriceAsinMapper; -import com.nanri.aiimage.modules.invalidasin.mapper.InvalidAsinDataMapper; -import com.nanri.aiimage.modules.dedupe.mapper.DedupeTotalDataMapper; import com.nanri.aiimage.modules.shopkey.model.dto.ShopManageGroupCreateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.ShopManageGroupUpdateRequest; import com.nanri.aiimage.modules.shopkey.model.entity.QueryAsinEntity; import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageEntity; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupMemberEntity; import com.nanri.aiimage.modules.shopkey.model.entity.SkipPriceAsinEntity; -import com.nanri.aiimage.modules.invalidasin.model.entity.InvalidAsinDataEntity; -import com.nanri.aiimage.modules.dedupe.model.entity.DedupeTotalDataEntity; import com.nanri.aiimage.modules.shopkey.model.vo.ShopManageGroupItemVo; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -40,11 +37,11 @@ public class ShopManageGroupService { private final ShopManageGroupMapper groupMapper; private final ShopManageGroupMemberMapper groupMemberMapper; + /** 各业务模块的分组删除守卫(Spring 注入全部实现) */ + private final java.util.List groupDeletionGuards; private final ShopManageMapper shopManageMapper; private final QueryAsinMapper queryAsinMapper; private final SkipPriceAsinMapper skipPriceAsinMapper; - private final InvalidAsinDataMapper invalidAsinDataMapper; - private final DedupeTotalDataMapper dedupeTotalDataMapper; private final AdminUserMapper adminUserMapper; public List list() { @@ -166,15 +163,9 @@ public class ShopManageGroupService { if (queryAsinCount != null && queryAsinCount > 0) { throw new BusinessException("该分组下存在查询 ASIN,无法删除"); } - Long invalidAsinDataCount = invalidAsinDataMapper.selectCount(new LambdaQueryWrapper() - .eq(InvalidAsinDataEntity::getGroupId, entity.getId())); - if (invalidAsinDataCount != null && invalidAsinDataCount > 0) { - throw new BusinessException("该分组下存在品牌数据库数据,无法删除"); - } - Long dedupeTotalDataCount = dedupeTotalDataMapper.selectCount(new LambdaQueryWrapper() - .eq(DedupeTotalDataEntity::getGroupId, entity.getId())); - if (dedupeTotalDataCount != null && dedupeTotalDataCount > 0) { - throw new BusinessException("该分组下存在数据去重总数据,无法删除"); + // 其它模块的数据残留由各模块自己实现的守卫校验(2026-09 边界收敛:shopkey 不再直连它们的表) + for (GroupDeletionGuardPort guard : groupDeletionGuards) { + guard.ensureNoGroupData(entity.getId()); } groupMemberMapper.delete(new LambdaQueryWrapper() .eq(ShopManageGroupMemberEntity::getGroupId, entity.getId())); diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java index c1c3a2f3..5f11aad8 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java @@ -7,7 +7,7 @@ import com.nanri.aiimage.modules.shopkey.mapper.ShopManageMapper; import com.nanri.aiimage.modules.shopkey.model.dto.ShopManageCreateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.ShopManageUpdateRequest; import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageEntity; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.shopkey.model.vo.ShopManageCredentialVo; import com.nanri.aiimage.modules.shopkey.model.vo.ShopManageItemVo; import com.nanri.aiimage.modules.shopkey.model.vo.ShopManagePageVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinService.java index 2d96b43c..d2a59a06 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinService.java @@ -13,7 +13,7 @@ import com.nanri.aiimage.modules.shopkey.mapper.ShopManageMapper; import com.nanri.aiimage.modules.shopkey.model.dto.SkipPriceAsinCreateRequest; import com.nanri.aiimage.modules.shopkey.model.dto.SkipPriceAsinDetailDto; import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageEntity; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.shopkey.model.entity.SkipPriceAsinEntity; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinImportProgressVo; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinImportStartVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/spi/GroupDeletionGuardPort.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/spi/GroupDeletionGuardPort.java new file mode 100644 index 00000000..7a6d0040 --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/spi/GroupDeletionGuardPort.java @@ -0,0 +1,15 @@ +package com.nanri.aiimage.modules.shopkey.spi; + +/** + * 分组删除守卫(2026-09 边界收敛):分组下若仍存在某模块的业务数据,拒绝删除该分组。 + * + *

原实现由 shopkey 直接 count 其它模块的表(invalidasin / dedupe),构成 shopkey → 业务 的反向依赖; + * 现改为各业务模块自己实现本端口(Spring 注入 List 后逐个校验),新增模块只需加一个实现 Bean。 + * + *

实现应在"存在数据"时抛出 {@code BusinessException},文案自带模块名(沿用历史文案,前端无需改)。 + */ +public interface GroupDeletionGuardPort { + + /** 校验该分组下本模块无残留数据;有则抛业务异常。 */ + void ensureNoGroupData(Long groupId); +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/softwareversion/controller/SoftwareVersionAdminController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/softwareversion/controller/SoftwareVersionAdminController.java index cf544986..2ea5fdb4 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/softwareversion/controller/SoftwareVersionAdminController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/softwareversion/controller/SoftwareVersionAdminController.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.softwareversion.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.softwareversion.service.SoftwareVersionService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandler.java b/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandler.java index 6bda251d..807eb306 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandler.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandler.java @@ -37,6 +37,15 @@ public interface ResultFileJobHandler { return false; } + /** + * 模块自定义的结果对象 key 解析:返回非空时覆盖默认路径(按 resultId 查 biz_file_result)。 + * BRAND 的结果文件 job 上没有 resultId,需要用任务 id 反查品牌侧存放的对象 key。 + * 实现应自吞异常(解析失败按 null 处理,走默认路径)。 + */ + default String resolveResultFileUrl(TaskFileJobEntity job) { + return null; + } + default boolean supportsAsyncOffload() { return false; } diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorker.java b/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorker.java index 454afd23..338c6dc6 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorker.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorker.java @@ -3,11 +3,9 @@ package com.nanri.aiimage.modules.task.service; import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.common.exception.TaskOwnerMismatchException; import com.nanri.aiimage.config.InstanceMetadata; -import com.nanri.aiimage.modules.brand.service.BrandTaskService; import com.nanri.aiimage.modules.task.mapper.FileResultMapper; import com.nanri.aiimage.modules.task.model.entity.FileResultEntity; import com.nanri.aiimage.modules.task.model.entity.TaskFileJobEntity; -import com.nanri.aiimage.modules.withdraw.service.WithdrawTaskService; import jakarta.annotation.PreDestroy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -34,8 +32,6 @@ public class TaskResultFileJobWorker { private final FileResultMapper fileResultMapper; private final TaskFileJobLocalDispatcher taskFileJobLocalDispatcher; private final InstanceMetadata instanceMetadata; - private final WithdrawTaskService withdrawTaskService; - private final BrandTaskService brandTaskService; private final ResultFileJobHandlerRegistry handlerRegistry; @Autowired @Qualifier("taskQueueExecutor") @@ -178,7 +174,6 @@ public class TaskResultFileJobWorker { private void processInternal(TaskFileJobEntity job) { long startedAt = System.currentTimeMillis(); - boolean finalizeWithdraw = false; try { TaskFileJobEntity latest = taskFileJobService.findById(job.getId()); if (latest != null && "SUCCESS".equals(latest.getStatus())) { @@ -219,13 +214,15 @@ public class TaskResultFileJobWorker { String resultFileUrl = resolveResultFileUrl(job); taskFileJobService.markSuccess(job, resultFileUrl); cleanupAfterSuccess(job); - finalizeWithdraw = "WITHDRAW".equals(job.getModuleType()); log.info("[task-file-job] process success jobId={} taskId={} moduleType={} resultId={} elapsedMs={} resultFileUrl={} stage=SUCCESS", job.getId(), job.getTaskId(), job.getModuleType(), job.getResultId(), System.currentTimeMillis() - startedAt, resultFileUrl); } - if (finalizeWithdraw) { - withdrawTaskService.tryFinalizeTask(job.getTaskId(), false); + // 成功后回调解耦(原 WITHDRAW 特判):时机与历史一致——锁已释放、markSuccess 之后; + // 各模块需要"任务收尾"时实现 ResultFileJobHandler.onSuccess,task 侧不再 import 业务模块 + ResultFileJobHandler successHandler = handlerRegistry.asMap().get(job.getModuleType()); + if (successHandler != null) { + successHandler.onSuccess(job); } } catch (TaskOwnerMismatchException ex) { // 归属校验失败不是"生成失败":不能计入 retryCount,否则任务会在归属机 @@ -308,8 +305,12 @@ public class TaskResultFileJobWorker { } private String resolveResultFileUrl(TaskFileJobEntity job) { - if ("BRAND".equals(job.getModuleType())) { - return brandTaskService.resolveResultObjectKey(job.getTaskId()); + ResultFileJobHandler handler = handlerRegistry.asMap().get(job.getModuleType()); + if (handler != null) { + String custom = handler.resolveResultFileUrl(job); + if (custom != null && !custom.isBlank()) { + return custom; + } } if (job.getResultId() == null) { return null; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/tutorial/controller/TutorialAdminController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/tutorial/controller/TutorialAdminController.java index 44b47091..0107c34a 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/tutorial/controller/TutorialAdminController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/tutorial/controller/TutorialAdminController.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.tutorial.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.tutorial.service.TutorialPackageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserApiSecretController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserApiSecretController.java index 9a3e00bc..1d926645 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserApiSecretController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserApiSecretController.java @@ -2,8 +2,8 @@ package com.nanri.aiimage.modules.usersecret.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.config.UserSecretProperties; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.usersecret.model.dto.AdminUserSecretQuery; import com.nanri.aiimage.modules.usersecret.model.vo.AdminUserSecretPageVo; import com.nanri.aiimage.modules.usersecret.model.vo.UserApiSecretCheckResultVo; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserSecretUsageController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserSecretUsageController.java index 561503fa..6f3d438e 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserSecretUsageController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/AdminUserSecretUsageController.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.usersecret.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.usersecret.model.dto.AdminUserSecretUsageQuery; import com.nanri.aiimage.modules.usersecret.model.vo.AdminUserSecretUsagePageVo; import com.nanri.aiimage.modules.usersecret.service.UserSecretUsageService; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyController.java index b71110f3..9c8e7d25 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyController.java @@ -2,7 +2,7 @@ package com.nanri.aiimage.modules.usersecret.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.usersecret.service.UserApiSecretService; import com.nanri.aiimage.modules.usersecret.support.UserSecretModule; import io.swagger.v3.oas.annotations.Operation; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserSecretUsageController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserSecretUsageController.java index 556e2551..8bcd5f9b 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserSecretUsageController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserSecretUsageController.java @@ -1,7 +1,7 @@ package com.nanri.aiimage.modules.usersecret.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.usersecret.model.dto.UserSecretUsageReportRequest; import com.nanri.aiimage.modules.usersecret.service.UserSecretUsageService; import io.swagger.v3.oas.annotations.Operation; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/UserApiSecretController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/UserApiSecretController.java index e684520a..ccb64398 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/UserApiSecretController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/controller/UserApiSecretController.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.usersecret.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.usersecret.model.dto.UserApiSecretCheckRequest; import com.nanri.aiimage.modules.usersecret.model.dto.UserApiSecretMigrateRequest; import com.nanri.aiimage.modules.usersecret.model.dto.UserApiSecretSaveRequest; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/ProxyBalancePortAdapter.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/ProxyBalancePortAdapter.java new file mode 100644 index 00000000..b4d9a511 --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/ProxyBalancePortAdapter.java @@ -0,0 +1,30 @@ +package com.nanri.aiimage.modules.usersecret.service; + +import com.nanri.aiimage.modules.notification.spi.ProxyBalancePort; +import com.nanri.aiimage.modules.usersecret.client.JikipProxyClient; +import com.nanri.aiimage.modules.usersecret.model.vo.UserApiSecretBalanceVo; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 代理余额探测端口实现(2026-09 边界收敛):把 jikip 客户端与余额 VO 收敛在 usersecret 模块内。 + */ +@Service +@RequiredArgsConstructor +public class ProxyBalancePortAdapter implements ProxyBalancePort { + + private final JikipProxyClient jikipProxyClient; + + @Override + public ProxyBalanceSnapshot fetchBalance() { + UserApiSecretBalanceVo balance = jikipProxyClient.fetchBalance(); + if (balance == null) { + return new ProxyBalanceSnapshot(false, null, null, "余额接口返回空"); + } + return new ProxyBalanceSnapshot( + Boolean.TRUE.equals(balance.getAvailable()), + balance.getSurplus(), + balance.getBalance(), + balance.getMessage()); + } +} diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretService.java index 28da64f9..65dcccd0 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretService.java @@ -2,17 +2,18 @@ package com.nanri.aiimage.modules.usersecret.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nanri.aiimage.common.exception.BusinessException; +import com.nanri.aiimage.modules.admin.spi.UserSecretCleanupPort; import com.nanri.aiimage.common.security.ShopCredentialCryptoService; import com.nanri.aiimage.config.UserSecretProperties; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.notification.service.NotificationDispatchService; import com.nanri.aiimage.modules.notification.service.NotificationService; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.support.UserDataScopeSupport; -import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; import com.nanri.aiimage.modules.shopkey.model.dto.UserGroupRef; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.usersecret.client.JikipProxyClient;import com.nanri.aiimage.modules.usersecret.mapper.UserApiSecretMapper; import com.nanri.aiimage.modules.usersecret.model.dto.AdminUserSecretQuery; import com.nanri.aiimage.modules.usersecret.model.dto.UserApiSecretMigrateRequest; @@ -53,7 +54,7 @@ import java.util.Set; @Service @RequiredArgsConstructor @Slf4j -public class UserApiSecretService { +public class UserApiSecretService implements UserSecretCleanupPort { public static final String SOURCE_CLIENT = "client"; public static final String SOURCE_ADMIN = "admin"; @@ -412,6 +413,7 @@ public class UserApiSecretService { /** 后台:清空该用户全部密钥与代理配置。 */ @Transactional + @Override public int adminClearByUser(Long userId) { requireUserId(userId); int deleted = userApiSecretMapper.delete(new LambdaQueryWrapper() diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageService.java index e645c78f..da4ffa88 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageService.java @@ -1,13 +1,13 @@ package com.nanri.aiimage.modules.usersecret.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.support.UserDataScopeSupport; -import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; import com.nanri.aiimage.modules.shopkey.model.dto.UserGroupRef; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.usersecret.mapper.UserSecretUsageMapper; import com.nanri.aiimage.modules.usersecret.model.dto.AdminUserSecretUsageQuery; import com.nanri.aiimage.modules.usersecret.model.entity.UserSecretUsageEntity; diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthController.java index e2d84067..d17f59f7 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthController.java @@ -1,7 +1,7 @@ package com.nanri.aiimage.modules.ziniao.controller; import com.nanri.aiimage.common.api.ApiResponse; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.ziniao.model.cache.ZiniaoShopIndexRefreshCursorDto; import com.nanri.aiimage.modules.ziniao.model.dto.ZiniaoOpenShopRequest; import com.nanri.aiimage.modules.ziniao.model.vo.ZiniaoOpenShopVo; diff --git a/backend-java/src/test/java/com/nanri/aiimage/ArchitectureBoundaryTest.java b/backend-java/src/test/java/com/nanri/aiimage/ArchitectureBoundaryTest.java index 87385093..c68d1b0e 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/ArchitectureBoundaryTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/ArchitectureBoundaryTest.java @@ -34,9 +34,9 @@ class ArchitectureBoundaryTest { * 本次以实测值 119 为准恢复告警能力;经 git diff 核验,当日的 task 模块改动 * (引用计数按 task 收敛、快照 upsert 缓存、心跳条件更新、锁续期重试等)未新增任何业务依赖。 */ - // 2026-09-14 心跳/陈旧修复/历史清理 SPI 化后实测 6(G5:task 只依赖 task.spi 下接口, -// 业务模块各自实现);继续按棘轮收敛,不允许回升 - private static final int TASK_TO_BUSINESS_BASELINE = 6; + // 2026-09-14 心跳/陈旧修复/历史清理/结果文件 URL 全部 SPI 化后,task → 业务 依赖实测为 0。 + // 基线钉死为 0:task 只允许依赖 task.spi 下的接口(业务模块各自实现),不允许回升。 + private static final int TASK_TO_BUSINESS_BASELINE = 0; private static volatile JavaClasses cached; @@ -76,8 +76,9 @@ class ArchitectureBoundaryTest { void taskToBusinessDependencyDoesNotGrow() { // 冻结存量:Handler 迁移后 task→业务 依赖已大幅收敛;不允许继续增长 int violations = countViolations(taskRule()); - assertTrue(violations >= 1, "task→业务 依赖仍有存量(心跳/清理等待 SPI 化)"); assertTrue(violations <= TASK_TO_BUSINESS_BASELINE, + "task→业务 依赖必须为 0(当前 " + violations + ");跨模块动作 = 在 task/spi 加接口 + 业务模块实现"); + assertTrue(violations >= 0, "task→业务 依赖不得超过基线 " + TASK_TO_BUSINESS_BASELINE + ",当前 " + violations + ";新增依赖走 Handler SPI 或先消除存量"); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/admin/support/AdminAuthSupportTest.java b/backend-java/src/test/java/com/nanri/aiimage/common/security/AdminAuthSupportTest.java similarity index 94% rename from backend-java/src/test/java/com/nanri/aiimage/modules/admin/support/AdminAuthSupportTest.java rename to backend-java/src/test/java/com/nanri/aiimage/common/security/AdminAuthSupportTest.java index 48b194dc..6e2190bb 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/admin/support/AdminAuthSupportTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/common/security/AdminAuthSupportTest.java @@ -1,10 +1,10 @@ -package com.nanri.aiimage.modules.admin.support; +package com.nanri.aiimage.common.security; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.auth.config.AuthProperties; -import com.nanri.aiimage.modules.auth.service.JwtService; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AuthProperties; +import com.nanri.aiimage.common.security.JwtService; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import io.jsonwebtoken.Claims; import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Test; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/auth/support/DeviceSessionPolicyTest.java b/backend-java/src/test/java/com/nanri/aiimage/common/security/DeviceSessionPolicyTest.java similarity index 98% rename from backend-java/src/test/java/com/nanri/aiimage/modules/auth/support/DeviceSessionPolicyTest.java rename to backend-java/src/test/java/com/nanri/aiimage/common/security/DeviceSessionPolicyTest.java index 1d8a8cb0..b2f6bcd0 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/auth/support/DeviceSessionPolicyTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/common/security/DeviceSessionPolicyTest.java @@ -1,4 +1,4 @@ -package com.nanri.aiimage.modules.auth.support; +package com.nanri.aiimage.common.security; import com.nanri.aiimage.common.exception.BusinessException; import io.jsonwebtoken.Claims; diff --git a/backend-java/src/test/java/com/nanri/aiimage/config/AdminApiGuardFilterTest.java b/backend-java/src/test/java/com/nanri/aiimage/config/AdminApiGuardFilterTest.java index cd0459e8..7103267f 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/config/AdminApiGuardFilterTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/config/AdminApiGuardFilterTest.java @@ -3,8 +3,8 @@ package com.nanri.aiimage.config; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/admin/service/AdminUserServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/admin/service/AdminUserServiceTest.java index 8a177399..1ff68591 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/admin/service/AdminUserServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/admin/service/AdminUserServiceTest.java @@ -3,11 +3,11 @@ package com.nanri.aiimage.modules.admin.service; import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.modules.admin.model.dto.AdminUserCreateRequest; import com.nanri.aiimage.modules.admin.model.dto.AdminUserUpdateRequest; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.auth.util.WerkzeugPasswordEncoder; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; +import com.nanri.aiimage.common.mapper.AdminUserMapper; import com.nanri.aiimage.modules.permission.model.dto.UserColumnPermissionUpdateRequest; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import com.nanri.aiimage.modules.usersecret.service.UserApiSecretService; import org.junit.jupiter.api.Test; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/auth/service/AuthServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/auth/service/AuthServiceTest.java index e72eac24..e25ac764 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/auth/service/AuthServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/auth/service/AuthServiceTest.java @@ -3,7 +3,7 @@ package com.nanri.aiimage.modules.auth.service; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.auth.config.AuthProperties; +import com.nanri.aiimage.common.security.AuthProperties; import com.nanri.aiimage.modules.auth.mapper.LoginUserMapper; import com.nanri.aiimage.modules.auth.model.dto.LoginRequest; import com.nanri.aiimage.modules.auth.model.entity.LoginUserEntity; @@ -26,6 +26,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.nanri.aiimage.common.security.JwtService; class AuthServiceTest { diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataControllerTest.java index 4f2ce793..24aeaf4f 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/controller/DedupeTotalDataControllerTest.java @@ -1,9 +1,9 @@ package com.nanri.aiimage.modules.dedupe.controller; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.dedupe.service.DedupeTotalDataService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Test; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataServiceTest.java index 80afcdee..e48549d8 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataServiceTest.java @@ -11,10 +11,10 @@ import com.nanri.aiimage.common.service.NodeSharedStore; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataImportProgressVo; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataItemVo; import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataPageVo; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; -import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryServiceTest.java index b38da6f0..12a1cf46 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/imagehistory/service/ImageHistoryServiceTest.java @@ -1,7 +1,7 @@ package com.nanri.aiimage.modules.imagehistory.service; import com.nanri.aiimage.modules.imagehistory.mapper.ImageHistoryMapper; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; +import com.nanri.aiimage.common.mapper.AdminUserMapper; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataControllerTest.java index 06206fef..b4fa6cac 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/controller/InvalidAsinDataControllerTest.java @@ -1,10 +1,10 @@ package com.nanri.aiimage.modules.invalidasin.controller; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataPageVo; import com.nanri.aiimage.modules.invalidasin.service.InvalidAsinDataService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.model.vo.PermissionMenuItemVo; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import org.junit.jupiter.api.BeforeEach; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataServiceTest.java index 06ea1a14..ef632ff2 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/invalidasin/service/InvalidAsinDataServiceTest.java @@ -10,7 +10,7 @@ import com.nanri.aiimage.modules.invalidasin.model.dto.InvalidAsinDataUpdateRequ import com.nanri.aiimage.modules.invalidasin.model.entity.InvalidAsinDataEntity; import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataItemVo; import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataPageVo; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.shopkey.service.ShopManageGroupService; import org.apache.ibatis.builder.MapperBuilderAssistant; import org.junit.jupiter.api.Test; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationControllerTest.java index d6788dac..a63bb103 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/AdminNotificationControllerTest.java @@ -1,9 +1,9 @@ package com.nanri.aiimage.modules.notification.controller; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.notification.model.dto.NotificationPageQuery; import com.nanri.aiimage.modules.notification.service.NotificationService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/NotificationControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/NotificationControllerTest.java index 6c09f210..2baf382d 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/NotificationControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/controller/NotificationControllerTest.java @@ -1,9 +1,9 @@ package com.nanri.aiimage.modules.notification.controller; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.notification.model.dto.NotificationPageQuery; import com.nanri.aiimage.modules.notification.service.NotificationService; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchServiceTest.java index 35d04d81..da2cac22 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationDispatchServiceTest.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.notification.service; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.support.UserDataScopeSupport; import org.junit.jupiter.api.Test; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationScanSchedulerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationScanSchedulerTest.java index b133ce33..83c9819c 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationScanSchedulerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/notification/service/NotificationScanSchedulerTest.java @@ -7,7 +7,7 @@ import com.nanri.aiimage.modules.brand.mapper.BrandCrawlTaskMapper; import com.nanri.aiimage.modules.brand.model.entity.BrandCrawlTaskEntity; import com.nanri.aiimage.modules.task.mapper.FileTaskMapper; import com.nanri.aiimage.modules.task.model.entity.FileTaskEntity; -import com.nanri.aiimage.modules.usersecret.client.JikipProxyClient; +import com.nanri.aiimage.modules.notification.spi.ProxyBalancePort; import org.apache.ibatis.builder.MapperBuilderAssistant; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -45,11 +45,11 @@ class NotificationScanSchedulerTest { private final com.nanri.aiimage.common.service.DistributedJobLockService lockService = mock(com.nanri.aiimage.common.service.DistributedJobLockService.class); private final NotificationProperties properties = new NotificationProperties(); - private final JikipProxyClient jikipProxyClient = mock(JikipProxyClient.class); + private final ProxyBalancePort proxyBalancePort = mock(ProxyBalancePort.class); private NotificationScanScheduler newScheduler() { return new NotificationScanScheduler(fileTaskMapper, brandCrawlTaskMapper, notificationService, - dispatch, lockService, properties, jikipProxyClient); + dispatch, lockService, properties, proxyBalancePort); } @Test diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuControllerTest.java index b10a047e..aff2cbc0 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/permission/controller/PermissionMenuControllerTest.java @@ -1,10 +1,10 @@ package com.nanri.aiimage.modules.permission.controller; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.permission.model.dto.ImageVideoDataPermissionUpdateRequest; import com.nanri.aiimage.modules.permission.model.dto.UserColumnPermissionUpdateRequest; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.model.vo.ImageVideoDataPermissionUserVo; import com.nanri.aiimage.modules.permission.model.vo.PermissionMenuItemVo; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuResolveTypeTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuResolveTypeTest.java index e19f3d70..b06aeaa3 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuResolveTypeTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuResolveTypeTest.java @@ -1,6 +1,6 @@ package com.nanri.aiimage.modules.permission.service; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; +import com.nanri.aiimage.common.mapper.AdminUserMapper; import com.nanri.aiimage.modules.permission.mapper.PermissionMenuMapper; import com.nanri.aiimage.modules.permission.mapper.UserColumnPermissionMapper; import com.nanri.aiimage.modules.permission.model.entity.PermissionMenuEntity; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuServiceTest.java index bbe6c5cb..b9aac381 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/permission/service/PermissionMenuServiceTest.java @@ -1,13 +1,13 @@ package com.nanri.aiimage.modules.permission.service; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; +import com.nanri.aiimage.common.mapper.AdminUserMapper; import com.nanri.aiimage.modules.permission.mapper.PermissionMenuMapper; import com.nanri.aiimage.modules.permission.mapper.UserColumnPermissionMapper; import com.nanri.aiimage.modules.permission.model.dto.PermissionMenuCreateRequest; import com.nanri.aiimage.modules.permission.model.dto.PermissionMenuUpdateRequest; import com.nanri.aiimage.modules.permission.model.dto.UserColumnPermissionUpdateRequest; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.model.entity.PermissionMenuEntity; import com.nanri.aiimage.modules.permission.model.entity.UserColumnPermissionEntity; import com.nanri.aiimage.modules.permission.model.vo.ImageVideoDataPermissionUserVo; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskControllerTest.java index 8d125e5c..749563f8 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/controller/AdminShopDataCrawlTaskControllerTest.java @@ -1,8 +1,8 @@ package com.nanri.aiimage.modules.shopdatacrawl.controller; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.service.PermissionMenuService; import com.nanri.aiimage.modules.shopdatacrawl.service.ShopDataCrawlTaskService; import jakarta.servlet.http.HttpServletRequest; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinServiceTest.java index f4e2fcf6..e8515ea4 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinServiceTest.java @@ -9,7 +9,7 @@ import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.modules.shopkey.mapper.ShopManageMapper; import com.nanri.aiimage.modules.shopkey.mapper.SkipPriceAsinMapper; import com.nanri.aiimage.modules.shopkey.model.dto.SkipPriceAsinCreateRequest; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.shopkey.model.entity.SkipPriceAsinEntity; import com.nanri.aiimage.modules.shopkey.model.vo.QueryAsinImportProgressVo; import com.nanri.aiimage.modules.shopkey.model.vo.SkipPriceAsinItemVo; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/BrandResultFileJobHandlerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/BrandResultFileJobHandlerTest.java index 9a1d05fb..81019bda 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/BrandResultFileJobHandlerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/BrandResultFileJobHandlerTest.java @@ -12,16 +12,19 @@ import java.nio.file.Path; import java.nio.file.Paths; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** - * BrandResultFileJobHandler 测试(任务 71)。 - * BRAND 的 resolveResultObjectKey 特例(无 resultId 也走)保留在 Worker 公共路径 resolveResultFileUrl, - * Handler 不接管 URL 解析;cleanup 为空(原 cleanupAfterSuccess 无 BRAND 分支,不走 payload.deleteLatest)。 + * BrandResultFileJobHandler 测试(任务 71 / 2026-09 边界收敛)。 + * BRAND 的 resolveResultObjectKey 特例(无 resultId 也走)由本 Handler 的 resolveResultFileUrl 钩子承担 + * (原实现的 Worker 直连品牌模块构成 task → 业务依赖,已翻转为 SPI 钩子); + * cleanup 为空(原 cleanupAfterSuccess 无 BRAND 分支,不走 payload.deleteLatest)。 */ class BrandResultFileJobHandlerTest { @@ -49,18 +52,23 @@ class BrandResultFileJobHandlerTest { } @Test - void resultUrlBrandSpecial() throws IOException { - // Handler 不接管 URL 解析:无 resolveResultObjectKey / resolveResultFileUrl 方法 - for (java.lang.reflect.Method method : handler.getClass().getDeclaredMethods()) { - assertFalse(method.getName().contains("resolve"), - "Handler 不接管 URL 解析:" + method.getName()); - } - // 特例仍留在 Worker 公共路径 resolveResultFileUrl(含 BRAND 分支,无 resultId 也走) + void resultUrlBrandSpecialResolvedByHandlerHook() throws IOException { + // 2026-09:URL 解析特例改由本 Handler 的 resolveResultFileUrl 钩子承担,Worker 不再 import 品牌模块 + TaskFileJobEntity job = new TaskFileJobEntity(); + job.setTaskId(33L); + when(brandTaskService.resolveResultObjectKey(33L)).thenReturn("oss/brand/33.json"); + + assertEquals("oss/brand/33.json", handler.resolveResultFileUrl(job)); + assertNull(handler.resolveResultFileUrl(null), "空 job 返回 null 交回默认路径"); + assertNull(handler.resolveResultFileUrl(new TaskFileJobEntity()), "无 taskId 返回 null 交回默认路径"); + String source = workerSource(); assertTrue(source.contains("resolveResultFileUrl"), "Worker 保留 resolveResultFileUrl 公共路径"); - assertTrue(source.contains("resolveResultObjectKey"), "Worker 保留 BRAND 的 resolveResultObjectKey 特例"); - assertTrue(source.contains("\"BRAND\"") || source.contains("BRAND"), - "Worker resolveResultFileUrl 含 BRAND 分支"); + assertTrue(source.contains("handler.resolveResultFileUrl") + || source.contains("resolveResultFileUrl(job)"), + "Worker 通过 Handler 钩子解析模块自定义 URL"); + assertFalse(source.contains("resolveResultObjectKey"), "Worker 不再直连品牌模块"); + assertFalse(source.contains("modules.brand"), "Worker 不再 import 品牌模块"); } @Test diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandlerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandlerTest.java index 8f4a0a98..af996ceb 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandlerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandlerTest.java @@ -38,16 +38,17 @@ class ResultFileJobHandlerTest { @Test void interfaceMethodsPresent() throws Exception { - // 2026-09:新增 fallbackAssembleOnFailure(job 重试耗尽时用部分数据兜底生成结果文件), - // 接口方法从 7 个增到 8 个,同步更新契约断言。 - assertEquals(8, ResultFileJobHandler.class.getDeclaredMethods().length, - "接口方法数量为 8(moduleType/process/onSuccess/cleanup/onFailure/" - + "fallbackAssembleOnFailure/supportsAsyncOffload/isOwnerScoped)"); + // 2026-09:新增 resolveResultFileUrl(模块自定义结果对象 key 解析,BRAND 用), + // 接口方法从 8 个增到 9 个,同步更新契约断言。 + assertEquals(9, ResultFileJobHandler.class.getDeclaredMethods().length, + "接口方法数量为 9(moduleType/process/onSuccess/cleanup/onFailure/" + + "fallbackAssembleOnFailure/resolveResultFileUrl/supportsAsyncOffload/isOwnerScoped)"); assertNotNull(methodOf(ResultFileJobHandler.class, "moduleType")); assertNotNull(methodOf(ResultFileJobHandler.class, "process", TaskFileJobEntity.class)); assertNotNull(methodOf(ResultFileJobHandler.class, "onSuccess", TaskFileJobEntity.class)); assertNotNull(methodOf(ResultFileJobHandler.class, "cleanup", TaskFileJobEntity.class)); assertNotNull(methodOf(ResultFileJobHandler.class, "onFailure", TaskFileJobEntity.class, String.class)); + assertNotNull(methodOf(ResultFileJobHandler.class, "resolveResultFileUrl", TaskFileJobEntity.class)); assertNotNull(methodOf(ResultFileJobHandler.class, "supportsAsyncOffload")); assertNotNull(methodOf(ResultFileJobHandler.class, "isOwnerScoped")); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerCleanupTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerCleanupTest.java index b9b8353d..e683bcdb 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerCleanupTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerCleanupTest.java @@ -89,7 +89,6 @@ class TaskResultFileJobWorkerCleanupTest { mock(FileResultMapper.class), mock(TaskFileJobLocalDispatcher.class), mock(InstanceMetadata.class), - withdraw, brand, registry); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerDispatchTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerDispatchTest.java index 4e942211..6f2be512 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerDispatchTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerDispatchTest.java @@ -92,7 +92,6 @@ class TaskResultFileJobWorkerDispatchTest { mock(FileResultMapper.class), mock(TaskFileJobLocalDispatcher.class), mock(InstanceMetadata.class), - withdraw, brand, registry); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerEquivalenceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerEquivalenceTest.java index dae0471d..0c49e31b 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerEquivalenceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerEquivalenceTest.java @@ -100,7 +100,6 @@ class TaskResultFileJobWorkerEquivalenceTest { fileResultMapper, mock(TaskFileJobLocalDispatcher.class), instanceMetadata, - withdraw, brand, registry); Field executorField = TaskResultFileJobWorker.class.getDeclaredField("taskQueueExecutor"); executorField.setAccessible(true); diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerFailureNotifyTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerFailureNotifyTest.java index e8c34a03..8c8d73b7 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerFailureNotifyTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerFailureNotifyTest.java @@ -99,7 +99,6 @@ class TaskResultFileJobWorkerFailureNotifyTest { mock(FileResultMapper.class), mock(TaskFileJobLocalDispatcher.class), instanceMetadata, - withdraw, brand, registry); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOffloadTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOffloadTest.java index 754c9941..c908d5e3 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOffloadTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOffloadTest.java @@ -102,7 +102,6 @@ class TaskResultFileJobWorkerOffloadTest { mock(FileResultMapper.class), mock(TaskFileJobLocalDispatcher.class), instanceMetadata, - withdraw, brand, registry); setTaskQueueExecutor(worker, taskQueueExecutor); return worker; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOrphanTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOrphanTest.java index 5e3b583d..e82c2aa9 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOrphanTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOrphanTest.java @@ -96,7 +96,6 @@ class TaskResultFileJobWorkerOrphanTest { mock(FileResultMapper.class), mock(TaskFileJobLocalDispatcher.class), instanceMetadata, - withdraw, brand, registry); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerRoutingTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerRoutingTest.java index aa9f169f..4540f6ed 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerRoutingTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerRoutingTest.java @@ -93,7 +93,6 @@ class TaskResultFileJobWorkerOwnerRoutingTest { mock(FileResultMapper.class), localDispatcher, instanceMetadata, - withdraw, brand, new ResultFileJobHandlerRegistry(handlers)); set(worker, "taskQueueExecutor", (org.springframework.core.task.TaskExecutor) Runnable::run); set(worker, "localWorkerEnabled", true); diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerScopedTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerScopedTest.java index 6f3f639c..ffac2e00 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerScopedTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerOwnerScopedTest.java @@ -96,7 +96,6 @@ class TaskResultFileJobWorkerOwnerScopedTest { mock(FileResultMapper.class), mock(TaskFileJobLocalDispatcher.class), instanceMetadata, - withdraw, brand, registry); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerSpecialRuleTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerSpecialRuleTest.java index 0322d3a1..956e44e6 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerSpecialRuleTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerSpecialRuleTest.java @@ -72,7 +72,6 @@ class TaskResultFileJobWorkerSpecialRuleTest { fileResultMapper, mock(TaskFileJobLocalDispatcher.class), instanceMetadata, - withdraw, brand, handlerRegistry); java.lang.reflect.Field executorField = TaskResultFileJobWorker.class.getDeclaredField("taskQueueExecutor"); diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerStuckScanTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerStuckScanTest.java index 679b475d..19c40ed6 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerStuckScanTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorkerStuckScanTest.java @@ -96,7 +96,6 @@ class TaskResultFileJobWorkerStuckScanTest { mock(FileResultMapper.class), mock(TaskFileJobLocalDispatcher.class), instanceMetadata, - withdraw, brand, registry); } diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyControllerTest.java index e2ff32dd..6d72c3d4 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/controller/InternalUserProxyControllerTest.java @@ -2,7 +2,7 @@ package com.nanri.aiimage.modules.usersecret.controller; import com.nanri.aiimage.common.api.ApiResponse; import com.nanri.aiimage.common.exception.BusinessException; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.usersecret.service.UserApiSecretService; import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Test; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretServiceTest.java index 510ab70a..2b1116b0 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserApiSecretServiceTest.java @@ -2,13 +2,13 @@ package com.nanri.aiimage.modules.usersecret.service; import com.nanri.aiimage.common.security.ShopCredentialCryptoService; import com.nanri.aiimage.config.UserSecretProperties; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.notification.service.NotificationDispatchService; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.support.UserDataScopeSupport; import com.nanri.aiimage.modules.shopkey.model.dto.UserGroupRef; -import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity; +import com.nanri.aiimage.common.model.entity.ShopManageGroupEntity; import com.nanri.aiimage.modules.usersecret.client.JikipProxyClient; import com.nanri.aiimage.modules.usersecret.mapper.UserApiSecretMapper; import com.nanri.aiimage.modules.usersecret.model.dto.AdminUserSecretQuery; @@ -28,6 +28,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; class UserApiSecretServiceTest { @@ -37,8 +38,8 @@ class UserApiSecretServiceTest { private final JikipProxyClient jikipProxyClient = mock(JikipProxyClient.class); private final AdminUserMapper adminUserMapper = mock(AdminUserMapper.class); private final AdminAuthSupport adminAuthSupport = mock(AdminAuthSupport.class); - private final com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper adminGroupMapper = - mock(com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper.class); + private final com.nanri.aiimage.common.mapper.ShopManageGroupMapper adminGroupMapper = + mock(com.nanri.aiimage.common.mapper.ShopManageGroupMapper.class); private final UserDataScopeSupport userDataScopeSupport = mock(UserDataScopeSupport.class); private final NotificationDispatchService notificationDispatchService = mock(NotificationDispatchService.class); private final UserSecretProperties userSecretProperties = new UserSecretProperties(); diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageServiceTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageServiceTest.java index db4515f6..2144c28a 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageServiceTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/usersecret/service/UserSecretUsageServiceTest.java @@ -1,10 +1,10 @@ package com.nanri.aiimage.modules.usersecret.service; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; -import com.nanri.aiimage.modules.permission.mapper.AdminUserMapper; -import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity; +import com.nanri.aiimage.common.security.AdminAuthSupport; +import com.nanri.aiimage.common.mapper.AdminUserMapper; +import com.nanri.aiimage.common.model.entity.AdminUserEntity; import com.nanri.aiimage.modules.permission.support.UserDataScopeSupport; -import com.nanri.aiimage.modules.shopkey.mapper.ShopManageGroupMapper; +import com.nanri.aiimage.common.mapper.ShopManageGroupMapper; import com.nanri.aiimage.modules.shopkey.model.dto.UserGroupRef; import com.nanri.aiimage.modules.usersecret.mapper.UserSecretUsageMapper; import com.nanri.aiimage.modules.usersecret.model.dto.AdminUserSecretUsageQuery; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthControllerTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthControllerTest.java index 108e6d52..9c91e101 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthControllerTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/ziniao/controller/ZiniaoAuthControllerTest.java @@ -2,7 +2,7 @@ package com.nanri.aiimage.modules.ziniao.controller; import com.nanri.aiimage.common.exception.BusinessException; import com.nanri.aiimage.modules.ziniao.model.cache.ZiniaoShopIndexRefreshCursorDto; -import com.nanri.aiimage.modules.admin.support.AdminAuthSupport; +import com.nanri.aiimage.common.security.AdminAuthSupport; import com.nanri.aiimage.modules.ziniao.service.ZiniaoAuthService; import com.nanri.aiimage.modules.ziniao.service.ZiniaoShopIndexRefreshService; import com.nanri.aiimage.modules.ziniao.service.ZiniaoShopIndexService;