code review:会员标签

This commit is contained in:
YunaiV 2023-08-20 09:25:23 +08:00
parent 8191d9e141
commit 2584911d88
15 changed files with 39 additions and 207 deletions

View File

@ -1,71 +0,0 @@
create table member_tag
(
id bigint auto_increment comment '编号'
primary key,
name varchar(30) default '' not null comment '标签名称',
creator varchar(64) default '' null comment '创建者',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
updater varchar(64) default '' null comment '更新者',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
deleted bit default b'0' not null comment '是否删除',
tenant_id bigint default 0 not null comment '租户编号'
)
comment '会员标签';
alter table member_user add column tag_ids varchar(255) null comment '用户标签编号列表,以逗号分隔';
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status, component_name
)
VALUES (
'会员标签管理', '', 2, 3, 2262,
'tag', '', 'member/tag/index', 0, 'MemberTag'
);
-- 按钮父菜单ID
-- 暂时只支持 MySQL如果你是 OraclePostgreSQLSQLServer 的话需要手动修改 @parentId 的部分的代码
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'会员标签查询', 'member:tag:query', 3, 1, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'会员标签创建', 'member:tag:create', 3, 2, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'会员标签更新', 'member:tag:update', 3, 3, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'会员标签删除', 'member:tag:delete', 3, 4, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'会员标签导出', 'member:tag:export', 3, 5, @parentId,
'', '', '', 0
);

View File

@ -2,9 +2,10 @@ package cn.iocoder.yudao.module.member.controller.admin.tag;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.*;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagRespVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO;
import cn.iocoder.yudao.module.member.convert.tag.MemberTagConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import cn.iocoder.yudao.module.member.service.tag.MemberTagService;
@ -16,14 +17,11 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 会员标签")
@RestController
@ -84,16 +82,4 @@ public class MemberTagController {
return success(MemberTagConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出会员标签 Excel")
@PreAuthorize("@ss.hasPermission('member:tag:export')")
@OperateLog(type = EXPORT)
public void exportTagExcel(@Valid MemberTagExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<MemberTagDO> list = tagService.getTagList(exportReqVO);
// 导出 Excel
List<MemberTagExcelVO> datas = MemberTagConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "会员标签.xls", "数据", MemberTagExcelVO.class, datas);
}
}

View File

@ -1,25 +0,0 @@
package cn.iocoder.yudao.module.member.controller.admin.tag.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 会员标签 Excel VO
*
* @author 芋道源码
*/
@Data
public class MemberTagExcelVO {
@ExcelProperty("编号")
private Long id;
@ExcelProperty("标签名称")
private String name;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.member.controller.admin.tag.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 会员标签 Excel 导出 Request VO参数和 MemberTagPageReqVO 是一致的")
@Data
public class MemberTagExportReqVO {
@Schema(description = "标签名称", example = "李四")
private String name;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.member.controller.admin.user;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
@ -19,11 +20,13 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@Tag(name = "管理后台 - 会员用户")
@RestController
@ -58,6 +61,9 @@ public class MemberUserController {
@PreAuthorize("@ss.hasPermission('member:user:query')")
public CommonResult<PageResult<MemberUserRespVO>> getUserPage(@Valid MemberUserPageReqVO pageVO) {
PageResult<MemberUserDO> pageResult = memberUserService.getUserPage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(PageResult.empty());
}
// 处理会员标签返显
Set<Long> tagIds = pageResult.getList().stream()
@ -66,9 +72,7 @@ public class MemberUserController {
.flatMap(Collection::stream)
.collect(Collectors.toSet());
List<MemberTagDO> tags = memberTagService.getTagList(tagIds);
Map<Long, String> tagNameMap = convertMap(tags, MemberTagDO::getId, MemberTagDO::getName);
return success(MemberUserConvert.INSTANCE.convertPage(pageResult, tagNameMap));
return success(MemberUserConvert.INSTANCE.convertPage(pageResult, tags));
}
}

View File

@ -50,7 +50,7 @@ public class MemberUserBaseVO {
@Schema(description = "会员备注", example = "我是小备注")
private String mark;
@Schema(description = "会员标签")
@Schema(description = "会员标签", example = "[1, 2]")
private List<Long> tagIds;
}

View File

@ -32,7 +32,7 @@ public class MemberUserPageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "会员标签")
@Schema(description = "会员标签", example = "[1, 2]")
private List<Long> tagIds;
}

View File

@ -32,6 +32,7 @@ public class MemberUserRespVO extends MemberUserBaseVO {
// ========== 其它信息 ==========
@Schema(description = "会员标签")
@Schema(description = "会员标签", example = "[红色, 快乐]")
private List<String> tagNames;
}

View File

@ -1,13 +1,14 @@
package cn.iocoder.yudao.module.member.convert.tag;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagRespVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import java.util.List;
/**
* 会员标签 Convert
@ -29,6 +30,4 @@ public interface MemberTagConvert {
PageResult<MemberTagRespVO> convertPage(PageResult<MemberTagDO> page);
List<MemberTagExcelVO> convertList02(List<MemberTagDO> list);
}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserRespVO;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserInfoRespVO;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@ -13,6 +14,7 @@ import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@Mapper
public interface MemberUserConvert {
@ -32,8 +34,9 @@ public interface MemberUserConvert {
MemberUserRespVO convert03(MemberUserDO bean);
default PageResult<MemberUserRespVO> convertPage(PageResult<MemberUserDO> pageResult,
Map<Long, String> tagMap) {
List<MemberTagDO> tags) {
PageResult<MemberUserRespVO> result = convertPage(pageResult);
Map<Long, String> tagMap = convertMap(tags, MemberTagDO::getId, MemberTagDO::getName);
for (MemberUserRespVO vo : result.getList()) {
vo.setTagNames(convertList(vo.getTagIds(), tagMap::get));
}

View File

@ -3,13 +3,10 @@ package cn.iocoder.yudao.module.member.dal.mysql.tag;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagExportReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 会员标签 Mapper
*
@ -25,13 +22,6 @@ public interface MemberTagMapper extends BaseMapperX<MemberTagDO> {
.orderByDesc(MemberTagDO::getId));
}
default List<MemberTagDO> selectList(MemberTagExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<MemberTagDO>()
.likeIfPresent(MemberTagDO::getName, reqVO.getName())
.betweenIfPresent(MemberTagDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(MemberTagDO::getId));
}
default boolean exists(Long id, String name) {
return exists(new LambdaQueryWrapperX<MemberTagDO>()
.neIfPresent(MemberTagDO::getId, id)

View File

@ -30,13 +30,14 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
}
default PageResult<MemberUserDO> selectPage(MemberUserPageReqVO reqVO) {
// 处理 tagIds 过滤条件
String tagIdSql = "";
if (CollUtil.isNotEmpty(reqVO.getTagIds())) {
tagIdSql = reqVO.getTagIds().stream()
.map(tagId -> "FIND_IN_SET(" + tagId + ", tag_ids)")
.collect(Collectors.joining(" OR "));
}
// 分页查询
return selectPage(reqVO, new LambdaQueryWrapperX<MemberUserDO>()
.likeIfPresent(MemberUserDO::getMobile, reqVO.getMobile())
.betweenIfPresent(MemberUserDO::getLoginDate, reqVO.getLoginDate())

View File

@ -1,10 +1,14 @@
package cn.iocoder.yudao.module.member.service.tag;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* 会员标签 Service 接口
@ -59,12 +63,4 @@ public interface MemberTagService {
*/
PageResult<MemberTagDO> getTagPage(MemberTagPageReqVO pageReqVO);
/**
* 获得会员标签列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 会员标签列表
*/
List<MemberTagDO> getTagList(MemberTagExportReqVO exportReqVO);
}

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagExportReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO;
import cn.iocoder.yudao.module.member.convert.tag.MemberTagConvert;
@ -63,6 +62,8 @@ public class MemberTagServiceImpl implements MemberTagService {
tagMapper.deleteById(id);
}
// TODO @疯狂校验 tag name 不重复参考 validateMobileUnique 方法Mapper 尽量逻辑通用处理交给 Service
private void validateTagExists(Long id) {
if (tagMapper.selectById(id) == null) {
throw exception(TAG_NOT_EXISTS);
@ -94,9 +95,4 @@ public class MemberTagServiceImpl implements MemberTagService {
return tagMapper.selectPage(pageReqVO);
}
@Override
public List<MemberTagDO> getTagList(MemberTagExportReqVO exportReqVO) {
return tagMapper.selectList(exportReqVO);
}
}

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.member.service.tag;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagCreateReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagExportReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.tag.vo.MemberTagUpdateReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
@ -12,7 +11,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
@ -126,28 +124,4 @@ public class MemberTagServiceImplTest extends BaseDbUnitTest {
assertPojoEquals(dbTag, pageResult.getList().get(0));
}
@Test
public void testGetTagList() {
// mock 数据
MemberTagDO dbTag = randomPojo(MemberTagDO.class, o -> { // 等会查询到
o.setName("test");
o.setCreateTime(buildTime(2023, 2, 18));
});
tagMapper.insert(dbTag);
// 测试 name 不匹配
tagMapper.insert(cloneIgnoreId(dbTag, o -> o.setName("ne")));
// 测试 createTime 不匹配
tagMapper.insert(cloneIgnoreId(dbTag, o -> o.setCreateTime(null)));
// 准备参数
MemberTagExportReqVO reqVO = new MemberTagExportReqVO();
reqVO.setName("test");
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
List<MemberTagDO> list = tagService.getTagList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbTag, list.get(0));
}
}