diff --git a/src/main/java/com/yunhai/userhome/controller/api/UserSettingsController.java b/src/main/java/com/yunhai/userhome/controller/api/UserSettingsController.java index 1a69959..57db3bb 100644 --- a/src/main/java/com/yunhai/userhome/controller/api/UserSettingsController.java +++ b/src/main/java/com/yunhai/userhome/controller/api/UserSettingsController.java @@ -292,8 +292,16 @@ public class UserSettingsController { // List appPageList = bschBaseOpenApi.getPcGrzxPage(authUserWithDept.getId(), schId); List appPageList = Collections.emptyList(); if (optional.isPresent()) model = optional.get(); + // 壁纸池一次取全:悬空自愈判定与兜底选择共用 + List wallList = userSettingsService.findWallList(authUserWithDept.getId()); + // 悬空引用自愈:自选壁纸已被删除(删除清理修复前的存量脏数据)时视为未自选,避免返回死 URL 白板 + String chosenUrl = normalizeWallpaperUrl(model.getWallpaperUrl()); + if (model.getWallpaperUrl() != null && !model.getWallpaperUrl().isEmpty() + && wallList.stream().noneMatch(w -> chosenUrl != null && chosenUrl.equals(w.getWallpaperUrl()))) { + model.setWallpaperUrl(null); + } if (model.getWallpaperUrl() == null || model.getWallpaperUrl().isEmpty()) { - model.setWallpaperUrl(resolveFallbackWallpaper(authUserWithDept, schId)); + model.setWallpaperUrl(resolveFallbackWallpaper(authUserWithDept, schId, wallList)); } List mapList = appPageList.stream().map(boaApp -> { Map map = new HashMap<>(); @@ -310,31 +318,33 @@ public class UserSettingsController { /** * 兜底壁纸(用户未自选时,壁纸三级默认轮 2026-10-09):本校默认(sch_settings.wallpaper_url,管理员选定) - * → 平台默认(schId=0 行)→ 本地学校壁纸池最新一张 → 平台池最新一张(历史兜底,两级皆未配置时保持原体验)。 - *

学校壁纸完全本地管理(wallpaper 表 type=1),不再依赖跨仓 schConfig。

+ * → 平台默认(schId=0 行)→ 本地学校壁纸池第一张 → 平台池第一张(历史兜底,两级皆未配置时保持原体验)。 + *

学校壁纸完全本地管理(wallpaper 表 type=1),不再依赖跨仓 schConfig。 + * 管理员选定默认返回前校验其仍在壁纸池中——被删池视为未配置继续下落,避免兜底本身返回死 URL(2026-10-09 白板修复)。

*/ - private String resolveFallbackWallpaper(BoaUser authUserWithDept, Integer schId) { + private String resolveFallbackWallpaper(BoaUser authUserWithDept, Integer schId, List wallList) { + Set poolUrls = new HashSet<>(); + wallList.forEach(w -> poolUrls.add(w.getWallpaperUrl())); // 1/2. 管理员选定的默认壁纸(本校 → 平台 级联,读侧 LayerValue) ISchSettingsService.LayerValue wallHit = schSettingsService.readWallpaperWithFallback(schId); - if (wallHit.getValue() != null) { + if (wallHit.getValue() != null && poolUrls.contains(normalizeWallpaperUrl(wallHit.getValue()))) { return wallHit.getValue(); } - // 3/4. 历史兜底:壁纸池最新(校 type=1 → 平台 type=0) - List wallList = userSettingsService.findWallList(authUserWithDept.getId()); + // 3/4. 历史兜底:壁纸池第一张(校 type=1 → 平台 type=0,最早上传者优先) if (schId != null) { - // 3. 本地学校壁纸第一张(type=1,取最新) + // 3. 本地学校壁纸第一张(type=1) Optional schWall = wallList.stream() .filter(w -> w.getType() != null && w.getType() == 1 && w.getSchId() != null && w.getSchId().equals(schId)) - .max(Comparator.comparing(Wallpaper::getId)); + .min(Comparator.comparing(Wallpaper::getId)); if (schWall.isPresent()) { return FILE_WEB_PATH + schWall.get().getWallpaperUrl().replace("/upload", ""); } } - // 4. 超管全局壁纸第一张(type=0,取最新) + // 4. 超管全局壁纸第一张(type=0) Optional sysWall = wallList.stream() .filter(w -> w.getType() != null && w.getType() == 0) - .max(Comparator.comparing(Wallpaper::getId)); + .min(Comparator.comparing(Wallpaper::getId)); if (sysWall.isPresent()) { return FILE_WEB_PATH + sysWall.get().getWallpaperUrl().replace("/upload", ""); } diff --git a/src/main/java/com/yunhai/userhome/repository/UserSettingsRepository.java b/src/main/java/com/yunhai/userhome/repository/UserSettingsRepository.java index 79cf4df..d6aabac 100644 --- a/src/main/java/com/yunhai/userhome/repository/UserSettingsRepository.java +++ b/src/main/java/com/yunhai/userhome/repository/UserSettingsRepository.java @@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.Collection; import java.util.Optional; public interface UserSettingsRepository extends JpaRepository, JpaSpecificationExecutor { @@ -21,8 +22,10 @@ public interface UserSettingsRepository extends JpaRepository urls); } diff --git a/src/main/java/com/yunhai/userhome/service/impl/UserSettingsServiceImpl.java b/src/main/java/com/yunhai/userhome/service/impl/UserSettingsServiceImpl.java index f39dd37..08bd653 100644 --- a/src/main/java/com/yunhai/userhome/service/impl/UserSettingsServiceImpl.java +++ b/src/main/java/com/yunhai/userhome/service/impl/UserSettingsServiceImpl.java @@ -53,6 +53,10 @@ public class UserSettingsServiceImpl implements IUserSettingsService { @Value("${FILE_PATH:./upload/}") private String FILE_PATH; + /** 与 UserSettingsController 同源:展示形态 = 该前缀 + 去掉 /upload 的池内原始路径 */ + @Value("${FILE_WEB_PATH:}") + private String FILE_WEB_PATH; + @Override public List findWallList(Integer userId) { Optional currentRoleOpt = userCurrentRoleService.findById(userId); @@ -136,8 +140,11 @@ public class UserSettingsServiceImpl implements IUserSettingsService { if (!(superAdmin || ownPersonal || schAdminOwn)) { throw new BizException(ErrorCode.FORBIDDEN); } - // 使用中清理:被删壁纸被用户设置引用时置空,避免裂图 - userSettingsRepository.clearWallpaperUrl(wallpaper.getWallpaperUrl()); + // 使用中清理:被删壁纸被用户设置引用时置空,避免裂图。 + // user_settings 存展示形态(FILE_WEB_PATH 前缀 + 去 /upload),与 wall 表原始形态不同,两种都清 + String rawUrl = wallpaper.getWallpaperUrl(); + String displayUrl = (FILE_WEB_PATH == null ? "" : FILE_WEB_PATH) + rawUrl.replace("/upload", ""); + userSettingsRepository.clearWallpaperUrl(java.util.Arrays.asList(rawUrl, displayUrl)); // 清理物理文件(非本地上传的跨仓地址静默跳过) FileUtil.deleteFile(FILE_PATH, wallpaper.getWallpaperUrl()); wallpaperRepository.delete(wallpaper);