feat(device): add app icon management with pagination and delete functionality

新增应用图标库分页查询和图标删除接口,并完成对应的菜单与按钮权限初始化。
This commit is contained in:
TongTongStudio
2026-08-06 02:25:25 +08:00
parent e9a1773d88
commit 33fcbcff3e
4 changed files with 138 additions and 3 deletions

View File

@@ -3,7 +3,10 @@ package com.youlai.boot.device.controller;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.common.enums.ActionTypeEnum;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.result.PageResult;
import com.youlai.boot.common.result.Result;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.device.model.vo.AppIconVO;
import com.youlai.boot.device.service.AppIconService;
import io.swagger.v3.oas.annotations.Operation;
@@ -12,6 +15,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -76,4 +80,25 @@ public class AppIconController {
) {
return Result.success(appIconService.uploadIcon(packageName, appName, file, "admin"));
}
@Operation(summary = "删除应用图标版本")
@DeleteMapping("/{packageName}/{iconId}")
@Log(module = LogModuleEnum.DEVICE, value = ActionTypeEnum.DELETE)
public Result<Boolean> deleteIcon(
@Parameter(description = "应用包名") @PathVariable String packageName,
@Parameter(description = "图标记录ID") @PathVariable Long iconId
) {
return Result.judge(appIconService.deleteIcon(packageName, iconId));
}
@Operation(summary = "应用图标库分页列表")
@GetMapping("/page")
public PageResult<AppIconVO> page(
@Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Long pageNum,
@Parameter(description = "每页条数", example = "10") @RequestParam(defaultValue = "10") Long pageSize,
@Parameter(description = "应用包名(可选,不传返回全部)") @RequestParam(required = false) String packageName
) {
IPage<AppIconVO> page = new Page<>(pageNum, pageSize);
return PageResult.success(appIconService.pageAppIcons(page, packageName));
}
}

View File

@@ -1,5 +1,7 @@
package com.youlai.boot.device.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.boot.device.model.vo.AppIconVO;
import org.springframework.web.multipart.MultipartFile;
@@ -66,4 +68,22 @@ public interface AppIconService {
* @return packageName -> iconUrl
*/
Map<String, String> getActiveIconUrls(Collection<String> packageNames);
/**
* 删除应用图标版本(逻辑删除)
*
* @param packageName 应用包名
* @param iconId 图标记录ID
* @return 是否成功
*/
boolean deleteIcon(String packageName, Long iconId);
/**
* 分页查询应用图标库(支持按包名筛选,不传则返回全部)
*
* @param page 分页参数
* @param packageName 应用包名(可选)
* @return 分页结果
*/
IPage<AppIconVO> pageAppIcons(IPage<AppIconVO> page, String packageName);
}

View File

@@ -1,6 +1,8 @@
package com.youlai.boot.device.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.boot.common.config.FilePath;
import com.youlai.boot.common.exception.BusinessException;
@@ -26,6 +28,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -211,8 +215,7 @@ public class AppIconServiceImpl extends ServiceImpl<AppIconMapper, AppIcon> impl
}
@Override
public Map<String, String> getActiveIconUrls(Collection<String> packageNames) {
if (packageNames == null || packageNames.isEmpty()) {
public Map<String, String> getActiveIconUrls(Collection<String> packageNames) { if (packageNames == null || packageNames.isEmpty()) {
return Map.of();
}
List<AppIcon> activeIcons = this.lambdaQuery()
@@ -261,9 +264,41 @@ public class AppIconServiceImpl extends ServiceImpl<AppIconMapper, AppIcon> impl
return ICON_URL_PREFIX + fileName;
}
@Override
public boolean deleteIcon(String packageName, Long iconId) {
Assert.isTrue(packageName != null && packageName.matches("[A-Za-z0-9._]+"), "应用包名不合法");
Assert.notNull(iconId, "图标记录ID不能为空");
AppIcon icon = this.getById(iconId);
Assert.notNull(icon, "图标记录不存在");
Assert.isTrue(packageName.equals(icon.getPackageName()), "图标记录不属于该应用");
// 逻辑删除(由 AppIcon 实体 @TableLogic 注解处理)
return this.removeById(iconId);
}
@Override
public IPage<AppIconVO> pageAppIcons(IPage<AppIconVO> page, String packageName) {
LambdaQueryWrapper<AppIcon> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StringUtils.hasText(packageName), AppIcon::getPackageName, packageName)
.orderByDesc(AppIcon::getUpdateTime);
IPage<AppIcon> entityPage = this.page(
new Page<>(page.getCurrent(), page.getSize()), wrapper);
List<AppIconVO> voList = entityPage.getRecords().stream()
.map(this::toVo)
.collect(Collectors.toList());
IPage<AppIconVO> result = new Page<>(
entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
result.setRecords(voList);
return result;
}
private AppIconVO toVo(AppIcon entity) {
if (entity == null) {
return null;
}
AppIconVO vo = new AppIconVO();
BeanUtils.copyProperties(entity, vo);
return vo;
}
}
}