🔨 tag 管理.

This commit is contained in:
lijiahangmax
2025-10-28 13:58:33 +08:00
parent 3a8addb4d2
commit 6a13d3cb22
18 changed files with 358 additions and 69 deletions

View File

@@ -22,16 +22,24 @@
*/ */
package org.dromara.visor.module.infra.controller; package org.dromara.visor.module.infra.controller;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.validator.group.Page;
import org.dromara.visor.framework.biz.operator.log.core.annotation.OperatorLog;
import org.dromara.visor.framework.log.core.annotation.IgnoreLog; import org.dromara.visor.framework.log.core.annotation.IgnoreLog;
import org.dromara.visor.framework.log.core.enums.IgnoreLogMode; import org.dromara.visor.framework.log.core.enums.IgnoreLogMode;
import org.dromara.visor.framework.web.core.annotation.DemoDisableApi;
import org.dromara.visor.framework.web.core.annotation.RestWrapper; import org.dromara.visor.framework.web.core.annotation.RestWrapper;
import org.dromara.visor.module.infra.define.operator.TagOperatorType;
import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest; import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagQueryRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagUpdateRequest;
import org.dromara.visor.module.infra.entity.vo.TagVO; import org.dromara.visor.module.infra.entity.vo.TagVO;
import org.dromara.visor.module.infra.service.TagService; import org.dromara.visor.module.infra.service.TagService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@@ -39,13 +47,13 @@ import javax.annotation.Resource;
import java.util.List; import java.util.List;
/** /**
* 标签枚举 api * 数据标签 api
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
* @since 2023-9-5 11:58 * @since 2023-9-5 11:58
*/ */
@Tag(name = "infra - 标签枚举服务") @Tag(name = "infra - 数据标签服务")
@Slf4j @Slf4j
@Validated @Validated
@RestWrapper @RestWrapper
@@ -56,12 +64,32 @@ public class TagController {
@Resource @Resource
private TagService tagService; private TagService tagService;
@DemoDisableApi
@OperatorLog(TagOperatorType.CREATE)
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建标签") @Operation(summary = "创建标签")
@PreAuthorize("@ss.hasPermission('infra:tag:create')")
public Long createTag(@Validated @RequestBody TagCreateRequest request) { public Long createTag(@Validated @RequestBody TagCreateRequest request) {
return tagService.createTag(request); return tagService.createTag(request);
} }
@DemoDisableApi
@OperatorLog(TagOperatorType.UPDATE)
@PutMapping("/update")
@Operation(summary = "修改标签")
@PreAuthorize("@ss.hasPermission('infra:tag:update')")
public Integer updateTag(@Validated @RequestBody TagUpdateRequest request) {
return tagService.updateTag(request);
}
@IgnoreLog(IgnoreLogMode.RET)
@PostMapping("/query")
@Operation(summary = "分页查询标签")
@PreAuthorize("@ss.hasPermission('infra:tag:query')")
public DataGrid<TagVO> getTagPage(@Validated(Page.class) @RequestBody TagQueryRequest request) {
return tagService.getTagPage(request);
}
@IgnoreLog(IgnoreLogMode.RET) @IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "查询标签") @Operation(summary = "查询标签")
@@ -70,12 +98,14 @@ public class TagController {
return tagService.getTagList(type); return tagService.getTagList(type);
} }
@DemoDisableApi
@OperatorLog(TagOperatorType.DELETE)
@DeleteMapping("/delete") @DeleteMapping("/delete")
@Operation(summary = "通过 id 删除标签") @Operation(summary = "通过 id 删除标签")
@Parameter(name = "id", description = "id", required = true) @Parameter(name = "id", description = "id", required = true)
@PreAuthorize("@ss.hasPermission('infra:tag:delete')")
public Integer deleteTag(@RequestParam("id") Long id) { public Integer deleteTag(@RequestParam("id") Long id) {
return tagService.deleteTagById(id); return tagService.deleteTagById(id);
} }
} }

View File

@@ -26,6 +26,7 @@ import org.dromara.visor.module.infra.entity.domain.TagDO;
import org.dromara.visor.module.infra.entity.dto.TagCacheDTO; import org.dromara.visor.module.infra.entity.dto.TagCacheDTO;
import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest; import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagQueryRequest; import org.dromara.visor.module.infra.entity.request.tag.TagQueryRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagUpdateRequest;
import org.dromara.visor.module.infra.entity.vo.TagVO; import org.dromara.visor.module.infra.entity.vo.TagVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@@ -33,7 +34,7 @@ import org.mapstruct.factory.Mappers;
import java.util.List; import java.util.List;
/** /**
* 标签枚举 内部对象转换器 * 数据标签 内部对象转换器
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -46,6 +47,8 @@ public interface TagConvert {
TagDO to(TagCreateRequest request); TagDO to(TagCreateRequest request);
TagDO to(TagUpdateRequest request);
TagDO to(TagQueryRequest request); TagDO to(TagQueryRequest request);
TagVO to(TagDO domain); TagVO to(TagDO domain);

View File

@@ -30,7 +30,7 @@ import org.mapstruct.factory.Mappers;
import java.util.List; import java.util.List;
/** /**
* 标签枚举 对外对象转换器 * 数据标签 对外对象转换器
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0

View File

@@ -30,7 +30,7 @@ import org.dromara.visor.module.infra.entity.domain.TagDO;
import java.util.List; import java.util.List;
/** /**
* 标签枚举 Mapper 接口 * 数据标签 Mapper 接口
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0

View File

@@ -24,8 +24,10 @@ package org.dromara.visor.module.infra.dao;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.dromara.visor.framework.mybatis.core.mapper.IMapper; import org.dromara.visor.framework.mybatis.core.mapper.IMapper;
import org.dromara.visor.module.infra.entity.domain.TagRelDO; import org.dromara.visor.module.infra.entity.domain.TagRelDO;
import org.dromara.visor.module.infra.entity.po.TagRelCountPO;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -72,4 +74,12 @@ public interface TagRelDAO extends IMapper<TagRelDO> {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
/**
* 查询标签引用数量
*
* @param tagIdList tagIdList
* @return count
*/
List<TagRelCountPO> selectTagRelCount(@Param("tagIdList") List<Long> tagIdList);
} }

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 - present Dromara, All rights reserved.
*
* https://visor.dromara.org
* https://visor.dromara.org.cn
* https://visor.orionsec.cn
*
* Members:
* Jiahang Li - ljh1553488six@139.com - author
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.visor.module.infra.define.operator;
import org.dromara.visor.framework.biz.operator.log.core.annotation.Module;
import org.dromara.visor.framework.biz.operator.log.core.factory.InitializingOperatorTypes;
import org.dromara.visor.framework.biz.operator.log.core.model.OperatorType;
import static org.dromara.visor.framework.biz.operator.log.core.enums.OperatorRiskLevel.L;
import static org.dromara.visor.framework.biz.operator.log.core.enums.OperatorRiskLevel.M;
/**
* 数据标签 操作日志类型
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/10 17:30
*/
@Module("infra:tag")
public class TagOperatorType extends InitializingOperatorTypes {
public static final String CREATE = "tag:create";
public static final String UPDATE = "tag:update";
public static final String DELETE = "tag:delete";
@Override
public OperatorType[] types() {
return new OperatorType[]{
new OperatorType(L, CREATE, "创建数据标签 <sb>${name}</sb>"),
new OperatorType(L, UPDATE, "修改数据标签 <sb>${name}</sb>"),
new OperatorType(M, DELETE, "删除数据标签 <sb>${name}</sb>"),
};
}
}

View File

@@ -33,7 +33,7 @@ import lombok.experimental.SuperBuilder;
import org.dromara.visor.framework.mybatis.core.domain.BaseDO; import org.dromara.visor.framework.mybatis.core.domain.BaseDO;
/** /**
* 标签枚举 实体对象 * 数据标签 实体对象
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -45,7 +45,7 @@ import org.dromara.visor.framework.mybatis.core.domain.BaseDO;
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@TableName(value = "tag", autoResultMap = true) @TableName(value = "tag", autoResultMap = true)
@Schema(name = "TagDO", description = "标签枚举 实体对象") @Schema(name = "TagDO", description = "数据标签 实体对象")
public class TagDO extends BaseDO { public class TagDO extends BaseDO {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -33,7 +33,7 @@ import javax.validation.constraints.Size;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 标签枚举 创建请求对象 * 数据标签 创建请求对象
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -43,17 +43,17 @@ import java.io.Serializable;
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Schema(name = "TagCreateRequest", description = "标签枚举 创建请求对象") @Schema(name = "TagCreateRequest", description = "数据标签 创建请求对象")
public class TagCreateRequest implements Serializable { public class TagCreateRequest implements Serializable {
@NotBlank
@Size(max = 32)
@Schema(description = "标签名称")
private String name;
@NotBlank @NotBlank
@Size(max = 12) @Size(max = 12)
@Schema(description = "标签类型") @Schema(description = "标签类型")
private String type; private String type;
@NotBlank
@Size(max = 32)
@Schema(description = "标签名称")
private String name;
} }

View File

@@ -29,7 +29,7 @@ import org.dromara.visor.common.entity.BaseQueryRequest;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
/** /**
* 标签枚举 查询请求对象 * 数据标签 查询请求对象
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -40,11 +40,15 @@ import javax.validation.constraints.Size;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Schema(name = "TagQueryRequest", description = "标签枚举 查询请求对象") @Schema(name = "TagQueryRequest", description = "数据标签 查询请求对象")
public class TagQueryRequest extends BaseQueryRequest { public class TagQueryRequest extends BaseQueryRequest {
@Size(max = 12) @Size(max = 12)
@Schema(description = "标签类型") @Schema(description = "标签类型")
private String type; private String type;
@Size(max = 32)
@Schema(description = "标签名称")
private String name;
} }

View File

@@ -64,4 +64,7 @@ public class TagRelQueryRequest extends BaseQueryRequest {
@Schema(description = "关联id") @Schema(description = "关联id")
private Collection<Long> relIdList; private Collection<Long> relIdList;
@Schema(description = "tagId")
private Collection<Long> tagIdList;
} }

View File

@@ -34,7 +34,7 @@ import javax.validation.constraints.Size;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 标签枚举 更新请求对象 * 数据标签 更新请求对象
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -44,7 +44,7 @@ import java.io.Serializable;
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Schema(name = "TagUpdateRequest", description = "标签枚举 更新请求对象") @Schema(name = "TagUpdateRequest", description = "数据标签 更新请求对象")
public class TagUpdateRequest implements Serializable { public class TagUpdateRequest implements Serializable {
@NotNull @NotNull
@@ -56,9 +56,4 @@ public class TagUpdateRequest implements Serializable {
@Schema(description = "标签名称") @Schema(description = "标签名称")
private String name; private String name;
@NotBlank
@Size(max = 12)
@Schema(description = "标签类型")
private String type;
} }

View File

@@ -29,9 +29,10 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
/** /**
* 标签枚举 视图响应对象 * 数据标签 视图响应对象
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -41,7 +42,7 @@ import java.io.Serializable;
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Schema(name = "TagVO", description = "标签枚举 视图响应对象") @Schema(name = "TagVO", description = "数据标签 视图响应对象")
public class TagVO implements Serializable { public class TagVO implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -49,7 +50,25 @@ public class TagVO implements Serializable {
@Schema(description = "id") @Schema(description = "id")
private Long id; private Long id;
@Schema(description = "标签类型")
private String type;
@Schema(description = "标签名称") @Schema(description = "标签名称")
private String name; private String name;
@Schema(description = "关联数量")
private Integer relCount;
@Schema(description = "创建时间")
private Date createTime;
@Schema(description = "修改时间")
private Date updateTime;
@Schema(description = "创建人")
private String creator;
@Schema(description = "修改人")
private String updater;
} }

View File

@@ -114,4 +114,20 @@ public interface TagRelService {
*/ */
Integer deleteRelIdList(String type, List<Long> relIdList); Integer deleteRelIdList(String type, List<Long> relIdList);
/**
* 通过 tagId 删除
*
* @param tagId tagId
* @return effect
*/
Integer deleteTagId(Long tagId);
/**
* 通过 tagId 删除
*
* @param tagIdList tagIdList
* @return effect
*/
Integer deleteTagIdList(List<Long> tagIdList);
} }

View File

@@ -22,13 +22,16 @@
*/ */
package org.dromara.visor.module.infra.service; package org.dromara.visor.module.infra.service;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest; import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagQueryRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagUpdateRequest;
import org.dromara.visor.module.infra.entity.vo.TagVO; import org.dromara.visor.module.infra.entity.vo.TagVO;
import java.util.List; import java.util.List;
/** /**
* 标签枚举 服务类 * 数据标签 服务类
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -37,7 +40,7 @@ import java.util.List;
public interface TagService { public interface TagService {
/** /**
* 创建标签枚举 * 创建数据标签
* *
* @param request request * @param request request
* @return id * @return id
@@ -45,7 +48,23 @@ public interface TagService {
Long createTag(TagCreateRequest request); Long createTag(TagCreateRequest request);
/** /**
* 查询标签枚举 * 更新数据标签
*
* @param request request
* @return effect
*/
Integer updateTag(TagUpdateRequest request);
/**
* 查询数据标签
*
* @param request request
* @return dataGrid
*/
DataGrid<TagVO> getTagPage(TagQueryRequest request);
/**
* 查询数据标签
* *
* @param type type * @param type type
* @return rows * @return rows
@@ -53,7 +72,7 @@ public interface TagService {
List<TagVO> getTagList(String type); List<TagVO> getTagList(String type);
/** /**
* 通过 id 删除标签枚举 * 通过 id 删除数据标签
* *
* @param id id * @param id id
* @return effect * @return effect
@@ -61,7 +80,7 @@ public interface TagService {
Integer deleteTagById(Long id); Integer deleteTagById(Long id);
/** /**
* 通过 id 删除标签枚举 * 通过 id 删除数据标签
* *
* @param idList idList * @param idList idList
* @return effect * @return effect
@@ -70,7 +89,9 @@ public interface TagService {
/** /**
* 清理未使用的 tag * 清理未使用的 tag
*
* @param days days
*/ */
void clearUnusedTag(); void clearUnusedTag(Integer days);
} }

View File

@@ -27,6 +27,7 @@ import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.collect.Maps; import cn.orionsec.kit.lang.utils.collect.Maps;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.dromara.visor.common.constant.Const;
import org.dromara.visor.framework.redis.core.utils.RedisStrings; import org.dromara.visor.framework.redis.core.utils.RedisStrings;
import org.dromara.visor.module.infra.convert.TagRelConvert; import org.dromara.visor.module.infra.convert.TagRelConvert;
import org.dromara.visor.module.infra.dao.TagDAO; import org.dromara.visor.module.infra.dao.TagDAO;
@@ -204,16 +205,7 @@ public class TagRelServiceImpl implements TagRelService {
@Override @Override
public Integer deleteRelId(String type, Long relId) { public Integer deleteRelId(String type, Long relId) {
// 删除数据库 return this.deleteRelIdList(type, Lists.singleton(relId));
TagRelQueryRequest queryRequest = new TagRelQueryRequest();
queryRequest.setTagType(type);
queryRequest.setRelId(relId);
LambdaQueryWrapper<TagRelDO> wrapper = this.buildQueryWrapper(queryRequest);
int effect = tagRelDAO.delete(wrapper);
// 删除缓存
String cacheKey = TagCacheKeyDefine.TAG_REL.format(type, relId);
redisTemplate.delete(cacheKey);
return effect;
} }
@Override @Override
@@ -232,6 +224,36 @@ public class TagRelServiceImpl implements TagRelService {
return effect; return effect;
} }
@Override
public Integer deleteTagId(Long tagId) {
return this.deleteTagIdList(Lists.singleton(tagId));
}
@Override
public Integer deleteTagIdList(List<Long> tagIdList) {
TagRelQueryRequest queryRequest = new TagRelQueryRequest();
queryRequest.setTagIdList(tagIdList);
LambdaQueryWrapper<TagRelDO> wrapper = this.buildQueryWrapper(queryRequest);
// 查询数据库
List<TagRelDO> tags = tagRelDAO.selectList(wrapper);
if (tags.isEmpty()) {
return Const.N_0;
}
// 删除数据库
int effect = tagRelDAO.delete(wrapper);
// 删除缓存
String tagType = tags.get(0).getTagType();
List<Long> relIdList = tags.stream()
.map(TagRelDO::getRelId)
.distinct()
.collect(Collectors.toList());
List<String> cacheKeyList = relIdList.stream()
.map(relId -> TagCacheKeyDefine.TAG_REL.format(tagType, relId))
.collect(Collectors.toList());
redisTemplate.delete(cacheKeyList);
return effect;
}
/** /**
* 构建查询 wrapper * 构建查询 wrapper
* *
@@ -242,6 +264,7 @@ public class TagRelServiceImpl implements TagRelService {
return tagRelDAO.wrapper() return tagRelDAO.wrapper()
.eq(TagRelDO::getId, request.getId()) .eq(TagRelDO::getId, request.getId())
.eq(TagRelDO::getTagId, request.getTagId()) .eq(TagRelDO::getTagId, request.getTagId())
.in(TagRelDO::getTagId, request.getTagIdList())
.eq(TagRelDO::getTagName, request.getTagName()) .eq(TagRelDO::getTagName, request.getTagName())
.eq(TagRelDO::getTagType, request.getTagType()) .eq(TagRelDO::getTagType, request.getTagType())
.eq(TagRelDO::getRelId, request.getRelId()) .eq(TagRelDO::getRelId, request.getRelId())

View File

@@ -22,29 +22,42 @@
*/ */
package org.dromara.visor.module.infra.service.impl; package org.dromara.visor.module.infra.service.impl;
import cn.orionsec.kit.lang.define.wrapper.DataGrid;
import cn.orionsec.kit.lang.utils.Objects1;
import cn.orionsec.kit.lang.utils.collect.Lists;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.constant.Const; import org.dromara.visor.common.constant.Const;
import org.dromara.visor.common.constant.ErrorMessage;
import org.dromara.visor.common.utils.Assert;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.framework.mybatis.core.query.Conditions; import org.dromara.visor.framework.mybatis.core.query.Conditions;
import org.dromara.visor.framework.redis.core.utils.RedisLists; import org.dromara.visor.framework.redis.core.utils.RedisLists;
import org.dromara.visor.framework.redis.core.utils.barrier.CacheBarriers; import org.dromara.visor.framework.redis.core.utils.barrier.CacheBarriers;
import org.dromara.visor.module.infra.convert.TagConvert; import org.dromara.visor.module.infra.convert.TagConvert;
import org.dromara.visor.module.infra.dao.TagDAO; import org.dromara.visor.module.infra.dao.TagDAO;
import org.dromara.visor.module.infra.dao.TagRelDAO;
import org.dromara.visor.module.infra.define.cache.TagCacheKeyDefine; import org.dromara.visor.module.infra.define.cache.TagCacheKeyDefine;
import org.dromara.visor.module.infra.entity.domain.TagDO; import org.dromara.visor.module.infra.entity.domain.TagDO;
import org.dromara.visor.module.infra.entity.dto.TagCacheDTO; import org.dromara.visor.module.infra.entity.dto.TagCacheDTO;
import org.dromara.visor.module.infra.entity.po.TagRelCountPO;
import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest; import org.dromara.visor.module.infra.entity.request.tag.TagCreateRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagQueryRequest;
import org.dromara.visor.module.infra.entity.request.tag.TagUpdateRequest;
import org.dromara.visor.module.infra.entity.vo.TagVO; import org.dromara.visor.module.infra.entity.vo.TagVO;
import org.dromara.visor.module.infra.service.TagRelService;
import org.dromara.visor.module.infra.service.TagService; import org.dromara.visor.module.infra.service.TagService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* 标签枚举 服务实现类 * 数据标签 服务实现类
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
@@ -54,14 +67,15 @@ import java.util.stream.Collectors;
@Service @Service
public class TagServiceImpl implements TagService { public class TagServiceImpl implements TagService {
/**
* 未使用的天数
*/
private static final Integer UN_USED_DAYS = 3;
@Resource @Resource
private TagDAO tagDAO; private TagDAO tagDAO;
@Resource
private TagRelDAO tagRelDAO;
@Resource
private TagRelService tagRelService;
@Override @Override
public Long createTag(TagCreateRequest request) { public Long createTag(TagCreateRequest request) {
// 转换 // 转换
@@ -86,6 +100,26 @@ public class TagServiceImpl implements TagService {
return record.getId(); return record.getId();
} }
@Override
@Transactional(rollbackFor = Exception.class)
public Integer updateTag(TagUpdateRequest request) {
Long id = request.getId();
log.info("TagService-updateTag id: {}, request: {}", id, JSON.toJSONString(request));
// 查询标签是否存在
TagDO record = tagDAO.selectById(id);
Assert.notNull(record, ErrorMessage.DATA_ABSENT);
// 转换
TagDO updateRecord = TagConvert.MAPPER.to(request);
// 检查数据是否存在
this.checkTagPresent(updateRecord);
// 更新
int effect = tagDAO.updateById(updateRecord);
log.info("HostProxyService-updateHostProxyById effect: {}", effect);
// 删除缓存
RedisLists.delete(TagCacheKeyDefine.TAG_NAME.format(record.getType()));
return effect;
}
@Override @Override
public List<TagVO> getTagList(String type) { public List<TagVO> getTagList(String type) {
// 查询缓存 // 查询缓存
@@ -109,41 +143,72 @@ public class TagServiceImpl implements TagService {
} }
@Override @Override
public Integer deleteTagById(Long id) { public DataGrid<TagVO> getTagPage(TagQueryRequest request) {
TagDO tag = tagDAO.selectById(id); // 查询标签
if (tag == null) { DataGrid<TagVO> dataGrid = tagDAO.of()
return Const.N_0; .createValidateWrapper()
.eq(TagDO::getType, request.getType())
.like(TagDO::getName, request.getName())
.then()
.page(request)
.order(request, TagDO::getId)
.dataGrid(TagConvert.MAPPER::to);
// 查询数量
if (!dataGrid.isEmpty()) {
List<Long> tagIdList = dataGrid.stream()
.map(TagVO::getId)
.collect(Collectors.toList());
// 查询数量
Map<Long, Integer> tagRelCountMap = tagRelDAO.selectTagRelCount(tagIdList)
.stream()
.collect(Collectors.toMap(TagRelCountPO::getTagId,
s -> Objects1.def(s.getCount(), Const.N_0)));
// 设置数量
for (TagVO tag : dataGrid) {
Integer count = tagRelCountMap.getOrDefault(tag.getId(), Const.N_0);
tag.setRelCount(count);
}
} }
// 删除数据库 return dataGrid;
int effect = tagDAO.deleteById(id);
log.info("TagService-deleteTagById id: {}, effect: {}", id, effect);
// 删除缓存
String cacheKey = TagCacheKeyDefine.TAG_NAME.format(tag.getType());
RedisLists.removeJson(cacheKey, TagConvert.MAPPER.toCache(tag));
return effect;
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public Integer deleteTagById(Long id) {
return this.deleteTagByIdList(Lists.singleton(id));
}
@Override
@Transactional(rollbackFor = Exception.class)
public Integer deleteTagByIdList(List<Long> idList) { public Integer deleteTagByIdList(List<Long> idList) {
List<TagDO> tagList = tagDAO.selectBatchIds(idList); List<TagDO> tagList = tagDAO.selectBatchIds(idList);
if (tagList.isEmpty()) { if (tagList.isEmpty()) {
return Const.N_0; return Const.N_0;
} }
// 删除数据库 // 设置日志参数
String name = tagList.stream()
.map(TagDO::getName)
.collect(Collectors.joining(Const.COMMA));
OperatorLogs.add(OperatorLogs.NAME, name);
// 删除标签
int effect = tagDAO.deleteBatchIds(idList); int effect = tagDAO.deleteBatchIds(idList);
// 删除关联
tagRelService.deleteTagIdList(idList);
log.info("TagService-deleteTagByIdList idList: {}, effect: {}", idList, effect); log.info("TagService-deleteTagByIdList idList: {}, effect: {}", idList, effect);
// 删除缓存 // 删除缓存
for (TagDO tag : tagList) { List<String> deleteKeys = tagList.stream()
String cacheKey = TagCacheKeyDefine.TAG_NAME.format(tag.getType()); .map(TagDO::getType)
RedisLists.removeJson(cacheKey, TagConvert.MAPPER.toCache(tag)); .distinct()
} .map(TagCacheKeyDefine.TAG_NAME::format)
.collect(Collectors.toList());
RedisLists.delete(deleteKeys);
return effect; return effect;
} }
@Override @Override
public void clearUnusedTag() { public void clearUnusedTag(Integer days) {
// 查询 // 查询
List<TagDO> tagList = tagDAO.selectUnusedTag(UN_USED_DAYS); List<TagDO> tagList = tagDAO.selectUnusedTag(days);
if (tagList.isEmpty()) { if (tagList.isEmpty()) {
log.info("TagService.clearUnusedTag isEmpty"); log.info("TagService.clearUnusedTag isEmpty");
return; return;
@@ -163,4 +228,22 @@ public class TagServiceImpl implements TagService {
RedisLists.delete(cacheKeys); RedisLists.delete(cacheKeys);
} }
/**
* 检查数据是否存在
*
* @param domain domain
*/
private void checkTagPresent(TagDO domain) {
// 构造条件
LambdaQueryWrapper<TagDO> wrapper = tagDAO.wrapper()
// 更新时忽略当前记录
.ne(TagDO::getId, domain.getId())
// 用其他字段做重复校验
.eq(TagDO::getType, domain.getType())
.eq(TagDO::getName, domain.getName());
// 检查是否存在
boolean present = tagDAO.of(wrapper).present();
Assert.isFalse(present, ErrorMessage.DATA_PRESENT);
}
} }

View File

@@ -26,19 +26,20 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.utils.LockerUtils; import org.dromara.visor.common.utils.LockerUtils;
import org.dromara.visor.module.infra.service.TagService; import org.dromara.visor.module.infra.service.TagService;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* tag 定时清理任务 * tag 定时清理任务
* <p>
* 提供了 web 管理删除, 所以不需要定时清理
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
* @since 2024/4/15 23:50 * @since 2024/4/15 23:50
*/ */
@Slf4j @Slf4j
@Component // @Component
public class TagAutoClearTask { public class TagAutoClearTask {
/** /**
@@ -46,6 +47,11 @@ public class TagAutoClearTask {
*/ */
private static final String LOCK_KEY = "clear:tag:lock"; private static final String LOCK_KEY = "clear:tag:lock";
/**
* 未使用的天数
*/
private static final Integer UN_USED_DAYS = 3;
@Resource @Resource
private TagService tagService; private TagService tagService;
@@ -56,7 +62,7 @@ public class TagAutoClearTask {
public void clear() { public void clear() {
log.info("TagAutoClearTask.clear start"); log.info("TagAutoClearTask.clear start");
// 获取锁并执行 // 获取锁并执行
LockerUtils.tryLockExecute(LOCK_KEY, tagService::clearUnusedTag); LockerUtils.tryLockExecute(LOCK_KEY, () -> tagService.clearUnusedTag(UN_USED_DAYS));
log.info("TagAutoClearTask.clear finish"); log.info("TagAutoClearTask.clear finish");
} }

View File

@@ -16,9 +16,28 @@
<result column="rel_id" property="relId"/> <result column="rel_id" property="relId"/>
</resultMap> </resultMap>
<!-- 数量查询映射结果 -->
<resultMap id="CountResultMap" type="org.dromara.visor.module.infra.entity.po.TagRelCountPO">
<result column="tag_id" property="tagId"/>
<result column="total_count" property="count"/>
</resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, tag_id, tag_name, tag_type, rel_id, create_time, update_time, creator, updater, deleted id, tag_id, tag_name, tag_type, rel_id, create_time, update_time, creator, updater, deleted
</sql> </sql>
<select id="selectTagRelCount" resultMap="CountResultMap">
SELECT tag_id, count(1) total_count
FROM tag_rel
WHERE deleted = 0
<if test="tagIdList != null and tagIdList.size() > 0">
AND tag_id IN
<foreach collection="tagIdList" item="item" open=" (" separator="," close=")">
#{item}
</foreach>
</if>
GROUP BY tag_id
</select>
</mapper> </mapper>