Administrator
2025-05-27 53f83462c6b0b5cbf366a1a8eb2243d2927b300b
feat(mall): 添加会员标识设置功能

- 新增会员标识设置相关接口和页面
- 实现会员标识与会员的关联逻辑
- 添加穿梭框组件用于选择会员
- 优化会员标识列表页面,增加设置按钮
6 files modified
5 files added
321 ■■■■■ changed files
src/main/java/cc/mrbird/febs/mall/controller/memberLevel/AdminHappyMemberLevelController.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/memberLevel/ViewHappyMemberLevelController.java 55 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/HappyMemberLabelRecord.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/HappyMemberLabelRecordMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/AdminMemberLevelService.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/AdminMemberLevelServiceImpl.java 39 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallTeamLeaderServiceImpl.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/AdminLabelSetVo.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/memberLevel/AdminMemberLabelSetDto.java 15 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/levelView/labelList.html 20 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/levelView/labelSet.html 135 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/memberLevel/AdminHappyMemberLevelController.java
@@ -16,6 +16,7 @@
import cc.mrbird.febs.mall.entity.HappyActivityOption;
import cc.mrbird.febs.mall.service.AdminMemberLevelService;
import cc.mrbird.febs.mall.service.IAdminHappyActivityService;
import cc.mrbird.febs.mall.vo.memberLevel.AdminMemberLabelSetDto;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
@@ -75,6 +76,17 @@
        return adminMemberLevelService.labelUpdate(dto);
    }
    /**
     * 会员标识-设置
     */
    @PostMapping("labelMemberSet")
    @ControllerEndpoint(operation = "会员标识-设置", exceptionMessage = "操作失败")
    public FebsResponse labelMemberSet(@RequestBody @Valid AdminMemberLabelSetDto dto) {
        return adminMemberLevelService.labelMemberSet(dto);
    }
    /**
     * 会员等级-列表
     * @return
src/main/java/cc/mrbird/febs/mall/controller/memberLevel/ViewHappyMemberLevelController.java
@@ -5,13 +5,12 @@
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.mapper.HappyActivityCategoryMapper;
import cc.mrbird.febs.mall.mapper.HappyActivityOptionMapper;
import cc.mrbird.febs.mall.mapper.HappyMemberLabelMapper;
import cc.mrbird.febs.mall.mapper.HappySaleLevelMapper;
import cc.mrbird.febs.mall.mapper.*;
import cc.mrbird.febs.mall.service.AdminMemberLevelService;
import cc.mrbird.febs.mall.service.IAdminHappyActivityService;
import cc.mrbird.febs.mall.vo.AdminLabelSetVo;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
@@ -19,6 +18,10 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Controller("levelView")
@RequestMapping(FebsConstant.VIEW_PREFIX + "modules/levelView")
@@ -28,6 +31,8 @@
    private final AdminMemberLevelService adminMemberLevelService;
    private final HappySaleLevelMapper happySaleLevelMapper;
    private final HappyMemberLabelMapper happyMemberLabelMapper;
    private final HappyMemberLabelRecordMapper happyMemberLabelRecordMapper;
    private final MallMemberMapper  mallMemberMapper;
    /**
     * 会员标识列表
@@ -63,6 +68,48 @@
    }
    /**
     * 设置会员标识
     * @param id
     * @param model
     * @return
     */
    @GetMapping("labelSet/{id}")
    @RequiresPermissions("labelSet:view")
    public String labelSet(@PathVariable long id, Model model) {
        HappyMemberLabel happyMemberLabel = happyMemberLabelMapper.selectById(id);
        //右侧数据
        List<HappyMemberLabelRecord> happyMemberLabelRecords = happyMemberLabelRecordMapper.selectList(
                new LambdaQueryWrapper<HappyMemberLabelRecord>()
                        .eq(HappyMemberLabelRecord::getLabelId, id)
        );
        //stream流操作happyMemberLabelRecords,获取memberId的set集合
        Set<Long> memberIds = happyMemberLabelRecords.stream().map(HappyMemberLabelRecord::getMemberId).collect(Collectors.toSet());
        //左侧数据
        List<MallMember> mallMembers = mallMemberMapper.selectList(
                new LambdaQueryWrapper<MallMember>()
                        .select(MallMember::getId, MallMember::getName,MallMember::getRealName, MallMember::getPhone)
                        .isNotNull(MallMember::getPhone)
                        .eq(MallMember::getAccountStatus, MallMember.ACCOUNT_STATUS_ENABLE)
        );
        //stream流操作mallMembers,生成一个新的List<MallMemberVo>
        List<AdminLabelSetVo> adminLabelSetVos = mallMembers.stream().map(mallMember -> {
            AdminLabelSetVo adminLabelSetVo = new AdminLabelSetVo();
            adminLabelSetVo.setId(mallMember.getId());
            adminLabelSetVo.setLabelName(mallMember.getName()+"("+mallMember.getRealName()+")"+mallMember.getPhone());
            return adminLabelSetVo;
        }).collect(Collectors.toList());
        model.addAttribute("adminLabelSetVos", adminLabelSetVos);
        model.addAttribute("memberIds", memberIds);
        model.addAttribute("labelId", id);
        return FebsUtil.view("modules/levelView/labelSet");
    }
    /**
     * 会员等级列表
     */
    @GetMapping("levelList")
src/main/java/cc/mrbird/febs/mall/entity/HappyMemberLabelRecord.java
New file
@@ -0,0 +1,20 @@
package cc.mrbird.febs.mall.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("happy_member_label_record")
public class HappyMemberLabelRecord extends BaseEntity {
    /**
     *
     `member_id` bigint(20) DEFAULT NULL COMMENT '名称',
     `label_id` bigint(20) DEFAULT NULL,
     */
    private Long memberId;
    private Long labelId;
}
src/main/java/cc/mrbird/febs/mall/mapper/HappyMemberLabelRecordMapper.java
New file
@@ -0,0 +1,7 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.HappyMemberLabelRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface HappyMemberLabelRecordMapper extends BaseMapper<HappyMemberLabelRecord> {
}
src/main/java/cc/mrbird/febs/mall/service/AdminMemberLevelService.java
@@ -6,6 +6,7 @@
import cc.mrbird.febs.mall.entity.HappyMemberLabel;
import cc.mrbird.febs.mall.entity.HappyMemberLevel;
import cc.mrbird.febs.mall.entity.HappySaleLevel;
import cc.mrbird.febs.mall.vo.memberLevel.AdminMemberLabelSetDto;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -23,6 +24,8 @@
    FebsResponse labelUpdate(AdminMemberLabelUpdateDto dto);
    FebsResponse labelMemberSet(AdminMemberLabelSetDto dto);
    FebsResponse levelAll();
    IPage<HappySaleLevel> getSaleLevelListInPage(AdminSaleLevelDto dto, QueryRequest request);
src/main/java/cc/mrbird/febs/mall/service/impl/AdminMemberLevelServiceImpl.java
@@ -4,15 +4,15 @@
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.enumerates.StateUpDownEnum;
import cc.mrbird.febs.mall.dto.memberLevel.*;
import cc.mrbird.febs.mall.entity.HappyActivityCategory;
import cc.mrbird.febs.mall.entity.HappyMemberLabel;
import cc.mrbird.febs.mall.entity.HappyMemberLevel;
import cc.mrbird.febs.mall.entity.HappySaleLevel;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.mapper.HappyMemberLabelMapper;
import cc.mrbird.febs.mall.mapper.HappyMemberLabelRecordMapper;
import cc.mrbird.febs.mall.mapper.HappyMemberLevelMapper;
import cc.mrbird.febs.mall.mapper.HappySaleLevelMapper;
import cc.mrbird.febs.mall.service.AdminMemberLevelService;
import cc.mrbird.febs.mall.vo.memberLevel.AdminMemberLabelSetDto;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -30,11 +30,13 @@
@Service
@RequiredArgsConstructor
@Transactional
public class AdminMemberLevelServiceImpl extends ServiceImpl<HappyMemberLevelMapper, HappyMemberLevel> implements AdminMemberLevelService {
public class
AdminMemberLevelServiceImpl extends ServiceImpl<HappyMemberLevelMapper, HappyMemberLevel> implements AdminMemberLevelService {
    private final HappyMemberLevelMapper happyMemberLevelMapper;
    private final HappySaleLevelMapper happySaleLevelMapper;
    private final HappyMemberLabelMapper happyMemberLabelMapper;
    private final HappyMemberLabelRecordMapper happyMemberLabelRecordMapper;
    @Override
    public IPage<HappyMemberLevel> getLevelListInPage(AdminMemberLevelDto dto, QueryRequest request) {
@@ -92,6 +94,33 @@
    }
    @Override
    public FebsResponse labelMemberSet(AdminMemberLabelSetDto dto) {
        Long labelId = dto.getLabelId();
        List<Long> memberIdList = dto.getMemberIdList();
        HappyMemberLabel happyMemberLabel = happyMemberLabelMapper.selectById(labelId);
        if (ObjectUtil.isNotEmpty(happyMemberLabel)) {
            if(CollUtil.isNotEmpty(memberIdList)){
                LambdaQueryWrapper<HappyMemberLabelRecord> happyMemberLabelRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
                happyMemberLabelRecordLambdaQueryWrapper.eq(HappyMemberLabelRecord::getLabelId,labelId);
                happyMemberLabelRecordLambdaQueryWrapper.in(HappyMemberLabelRecord::getMemberId,memberIdList);
                happyMemberLabelRecordMapper.delete(happyMemberLabelRecordLambdaQueryWrapper);
                for (Long memberId:memberIdList){
                    HappyMemberLabelRecord happyMemberLabelRecord = new HappyMemberLabelRecord();
                    happyMemberLabelRecord.setMemberId(memberId);
                    happyMemberLabelRecord.setLabelId(labelId);
                    happyMemberLabelRecordMapper.insert(happyMemberLabelRecord);
                }
            }else{
                LambdaQueryWrapper<HappyMemberLabelRecord> happyMemberLabelRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
                happyMemberLabelRecordLambdaQueryWrapper.eq(HappyMemberLabelRecord::getLabelId,labelId);
                happyMemberLabelRecordMapper.delete(happyMemberLabelRecordLambdaQueryWrapper);
            }
        }
        return new FebsResponse().success().message("操作成功");
    }
    @Override
    public FebsResponse levelAll() {
        List<HappyMemberLevel> happyMemberLevels = happyMemberLevelMapper.selectList(
                new LambdaQueryWrapper<HappyMemberLevel>()
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallTeamLeaderServiceImpl.java
@@ -752,6 +752,10 @@
        if(mallOrderInfo == null){
            throw new FebsException("订单不存在!");
        }
        if(mallOrderInfo.getStatus() != OrderStatusEnum.WAIT_FINISH.getValue()){
            throw new FebsException("订单不是待收货状态!");
        }
        MallTeamLeader mallTeamLeader = mallTeamLeaderMapper.selectLeaderByUniqueCode(mallOrderInfo.getTakeUniqueCode());
        if(mallTeamLeader==null){
src/main/java/cc/mrbird/febs/mall/vo/AdminLabelSetVo.java
New file
@@ -0,0 +1,11 @@
package cc.mrbird.febs.mall.vo;
import lombok.Data;
@Data
public class AdminLabelSetVo {
    private Long id;
    private String labelName;
}
src/main/java/cc/mrbird/febs/mall/vo/memberLevel/AdminMemberLabelSetDto.java
New file
@@ -0,0 +1,15 @@
package cc.mrbird.febs.mall.vo.memberLevel;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.List;
@Data
public class AdminMemberLabelSetDto {
    private  Long labelId;
    private List<Long> memberIdList;
}
src/main/resources/templates/febs/views/modules/levelView/labelList.html
@@ -37,6 +37,7 @@
<script type="text/html" id="memberLabelToolbar">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="labelAdd:add" lay-event="labelAdd">新增</button>
        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="labelSet:view" lay-event="labelSet">设置会员标识</button>
    </div>
</script>
@@ -137,6 +138,24 @@
                    }
                });
            }
            if (layEvent === 'labelSet') {
                var checkData = table.checkStatus('memberLabelTable').data;
                if (checkData.length > 1 || checkData.length === 0) {
                    febs.alert.warn('每次操作一个会员标识');
                    return;
                }
                febs.modal.open('设置会员标识', 'modules/levelView/labelSet/' + checkData[0].id, {
                    btn: ['提交', '取消'],
                    area:['100%','100%'],
                    yes: function (index, layero) {
                        $('#label-set').find('#submit').trigger('click');
                    },
                    btn2: function () {
                        layer.closeAll();
                    }
                });
            }
        });
        function initmemberLabelTable() {
@@ -147,6 +166,7 @@
                toolbar:"#memberLabelToolbar",
                defaultToolbar:[],
                cols: [[
                    {type: 'checkbox'},
                    {type: 'numbers', title: '', width: 80},
                    {title: '操作', toolbar: '#memberLabelOption', minWidth: 200, align: 'center'},
                    {field: 'name', title: '名称', minWidth: 150,align:'center'},
src/main/resources/templates/febs/views/modules/levelView/labelSet.html
New file
@@ -0,0 +1,135 @@
<div class="layui-fluid layui-anim febs-anim" id="label-set" lay-title="设置">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-fluid" id="memberLabel-set">
                <form class="layui-form" action="" lay-filter="memberLabel-set-form">
                    <div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
                        <ul class="layui-tab-title">
                            <li class="layui-this">基础信息</li>
                        </ul>
                        <div class="layui-tab-content">
                            <input type="text" name="labelId"
                                   placeholder="" autoComplete="off" class="layui-input">
                            <div class="layui-tab-item layui-show">
                                <div class="layui-form-item">
                                    <div id="memberSetMove"></div>
                                </div>
                            </div>
                            <div class="layui-tab-item layui-show">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="memberSetMoveQuery">
                                    <i class="layui-icon">获取右侧数据</i>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item febs-hide">
                        <button class="layui-btn" lay-submit="" lay-filter="memberLabel-set-form-submit" id="submit">保存</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
<script data-th-inline="javascript">
    layui.use(['febs','form', 'transfer'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            layer = layui.layer,
            form = layui.form,
            transfer = layui.transfer,
            adminLabelSetVos = [[${adminLabelSetVos}]],
            memberIds = [[${memberIds}]],
            labelId = [[${labelId}]],
            $view = $('#label-set'),
            $memberSetMoveQuery = $view.find('#memberSetMoveQuery')
        ;
        // var getData = transfer.getData('demo1');
        // $("button").click(function(){
        //     alert(getData)
        // });
        // 查询按钮
        $memberSetMoveQuery.on('click', function () {
            console.log(transfer.getData('memberSetMove-set'))
            let data1 = transfer.getData('memberSetMove-set');
            //获取data1中的value,返回一个数组
            let memberIdList = data1.map(function(item){
                return item.value;
            });
            console.log(memberIdList)
        });
        form.render();
        inithappyMemberLabelSet();
        function inithappyMemberLabelSet() {
            console.log("adminLabelSetVos:", adminLabelSetVos); // 调试信息
            console.log("memberIds:", memberIds); // 调试信息
            console.log("labelId:", labelId); // 调试信息
            form.val("memberLabel-set-form", {
                "labelId": labelId,
            });
            // 转换数据格式(假设接口返回的数据结构需要处理)
            var dataLeft = adminLabelSetVos.map(function(item){
                return {
                    value: item.id,  // 值字段
                    title: item.labelName // 显示文本
                }
            });
            var dataRight = memberIds.map(function(item){
                return {
                    value: item,  // 值字段
                }
            });
            // 渲染穿梭框
            transfer.render({
                elem: '#memberSetMove',
                data: dataLeft,
                id: 'memberSetMove-set', // 唯一标识
                title: ['待设置列表', '已设置列表'],
                width: 300,
                height: 400,
                showSearch: true,
                value: memberIds,
            });
        }
        form.on('submit(memberLabel-set-form-submit)', function (data) {
            let data1 = transfer.getData('memberSetMove-set');
            //获取data1中的value,返回一个数组
            let memberIdList = data1.map(function(item){
                return item.value;
            });
            data.field.memberIdList = memberIdList;
            data.field.labelId = labelId;
            $.ajax({
                'url':ctx + 'admin/level/labelMemberSet',
                'type':'post',
                'dataType':'json',
                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
                'traditional': true,//ajax传递数组必须添加属性
                'data':JSON.stringify(data.field),
                'success':function (data) {
                    if(data.code==200){
                        layer.closeAll();
                        febs.alert.success(data.message);
                        $('#febs-label').find('#query').click();
                    }else{
                        febs.alert.warn(data.message);
                    }
                },
                'error':function () {
                    febs.alert.warn('服务器繁忙');
                }
            })
            return false;
        });
    });
</script>