lenovo008\lenovo 4 months ago
commit fcee418cad

@ -4,6 +4,7 @@ import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID; import cn.hutool.core.lang.UUID;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.qccode.Base64Util; import cn.iocoder.yudao.framework.common.util.qccode.Base64Util;
@ -105,7 +106,6 @@ public class AppFileController {
@RequestMapping("/qrCode64Url") @RequestMapping("/qrCode64Url")
@Operation(summary = "生成Url") @Operation(summary = "生成Url")
public CommonResult<String> qrCode64Url(@Valid String type) { public CommonResult<String> qrCode64Url(@Valid String type) {
// 创建文件使用PNG扩展名因为QR码是以PNG格式生成的 // 创建文件使用PNG扩展名因为QR码是以PNG格式生成的
return success( getString(type)); return success( getString(type));

@ -0,0 +1,4 @@
package cn.iocoder.yudao.module.trade.api.order;
public interface TradeOrderItemApi {
}

@ -72,4 +72,12 @@ public interface MemberUserApi {
* @return * @return
*/ */
void updateUserUpgradesLevel(Long userId); void updateUserUpgradesLevel(Long userId);
/**
*
*
* @param orderId id
* @return
*/
void updateUserUpgradesLevelcallback(Long orderId);
} }

@ -54,5 +54,7 @@ public interface ErrorCodeConstants {
//========== 用户分组 1-004-012-000 ========== //========== 用户分组 1-004-012-000 ==========
ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_004_012_000, "用户分组不存在"); ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_004_012_000, "用户分组不存在");
ErrorCode GROUP_HAS_USER = new ErrorCode(1_004_012_001, "用户分组下存在用户,无法删除"); ErrorCode GROUP_HAS_USER = new ErrorCode(1_004_012_001, "用户分组下存在用户,无法删除");
ErrorCode DISTRIBUTION_CONFIG_NOT_EXISTS = new ErrorCode(1_004_012_002, "分销配置不存在");
ErrorCode DISTRIBUTION_LOG_NOT_EXISTS = new ErrorCode(1_004_012_003, "分销记录不存在");
ErrorCode DISTRIBUTION_STATISTICS_NOT_EXISTS = new ErrorCode(1_004_012_004, "分销统计不存在");
} }

@ -54,5 +54,10 @@ public class MemberUserApiImpl implements MemberUserApi {
userService.updateUserUpgradesLevel(userId); userService.updateUserUpgradesLevel(userId);
} }
@Override
public void updateUserUpgradesLevelcallback(Long orderId) {
userService.updateUserUpgradesLevelcallback(orderId);
}
} }

@ -0,0 +1,125 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionconfig;
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
import cn.iocoder.yudao.module.member.convert.distributionconfig.DistributionConfigConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionMebConfigDO;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.module.member.service.distributionconfig.DistributionConfigService;
@Tag(name = "管理后台 - 分销配置")
@RestController
@RequestMapping("/member/distribution-config")
@Validated
public class DistributionConfigController {
@Resource
private DistributionConfigService distributionConfigService;
@Resource
private MemberLevelApi memberLevelApi;
@Resource
private ProductSpuApi spuApi;
@PostMapping("/create")
@Operation(summary = "创建分销配置")
@PreAuthorize("@ss.hasPermission('member:distribution-config:create')")
public CommonResult<Long> createDistributionConfig(@Valid @RequestBody DistributionConfigSaveReqVO createReqVO) {
return success(distributionConfigService.createDistributionConfig(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新分销配置")
@PreAuthorize("@ss.hasPermission('member:distribution-config:update')")
public CommonResult<Boolean> updateDistributionConfig(@Valid @RequestBody DistributionConfigSaveReqVO updateReqVO) {
distributionConfigService.updateDistributionConfig(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除分销配置")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('member:distribution-config:delete')")
public CommonResult<Boolean> deleteDistributionConfig(@RequestParam("id") Long id) {
distributionConfigService.deleteDistributionConfig(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得分销配置")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('member:distribution-config:query')")
public CommonResult<DistributionConfigRespVO> getDistributionConfig(@RequestParam("id") Long id) {
DistributionConfigDO distributionConfig = distributionConfigService.getDistributionConfig(id);
return success(BeanUtils.toBean(distributionConfig, DistributionConfigRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得分销配置分页")
@PreAuthorize("@ss.hasPermission('member:distribution-config:query')")
public CommonResult<PageResult<DistributionConfigRespVO>> getDistributionConfigPage(@Valid DistributionConfigPageReqVO pageReqVO) {
PageResult<DistributionConfigDO> pageResult = distributionConfigService.getDistributionConfigPage(pageReqVO);
// 处理用户级别返显
List<MemberLevelRespDTO> levels = memberLevelApi.getLevelList(
convertSet(pageResult.getList(), DistributionConfigDO::getLevelId));
// 拼接数据
List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(pageResult.getList(), DistributionConfigDO::getProductId));
return success(DistributionConfigConvert.INSTANCE.convertPage(pageResult, levels,spuList));
// return success(BeanUtils.toBean(pageResult, DistributionConfigRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出分销配置 Excel")
@PreAuthorize("@ss.hasPermission('member:distribution-config:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportDistributionConfigExcel(@Valid DistributionConfigPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<DistributionConfigDO> list = distributionConfigService.getDistributionConfigPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "分销配置.xls", "数据", DistributionConfigRespVO.class,
BeanUtils.toBean(list, DistributionConfigRespVO.class));
}
// ==================== 子表(分销配置关联会员等级) ====================
@GetMapping("/distribution-meb-config/list-by-config-id")
@Operation(summary = "获得分销配置关联会员等级列表")
@Parameter(name = "configId", description = "分销配置id")
@PreAuthorize("@ss.hasPermission('member:distribution-config:query')")
public CommonResult<List<DistributionMebConfigDO>> getDistributionMebConfigListByConfigId(@RequestParam("configId") Long configId) {
return success(distributionConfigService.getDistributionMebConfigListByConfigId(configId));
}
}

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
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 = "管理后台 - 分销配置分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DistributionConfigPageReqVO extends PageParam {
@Schema(description = "分销商品id", example = "18678")
private Long productId;
@Schema(description = "购买人提升会员等级", example = "18678")
private Long levelId;
@Schema(description = "启用状态", example = "2")
private String status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 分销配置 Response VO")
@Data
@ExcelIgnoreUnannotated
public class DistributionConfigRespVO {
@Schema(description = "id主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "16387")
@ExcelProperty("id主键")
private Long id;
@Schema(description = "分销商品id", example = "18678")
@ExcelProperty("分销商品id")
private Long productId;
@Schema(description = "购买人提升会员等级", example = "18678")
@ExcelProperty("购买人提升会员等级")
private Long levelId;
@Schema(description = "启用状态", example = "2")
@ExcelProperty("启用状态")
private String status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "购买人提升会员等级", example = "18678")
@ExcelProperty("购买人提升会员等级")
private String levelName;
@Schema(description = "商品名称", example = "18678")
@ExcelProperty("商品名称")
private String supName;
}

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionMebConfigDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 分销配置新增/修改 Request VO")
@Data
public class DistributionConfigSaveReqVO {
@Schema(description = "id主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "16387")
private Long id;
@Schema(description = "分销商品id", example = "18678")
private Long productId;
@Schema(description = "购买人提升会员等级", example = "18678")
private Long levelId;
@Schema(description = "启用状态", example = "2")
private String status;
@Schema(description = "分销配置关联会员等级列表")
private List<DistributionMebConfigDO> distributionMebConfigs;
}

@ -0,0 +1,108 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionlog;
import cn.iocoder.yudao.module.member.convert.distributionlog.DistributionLogConvert;
import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.module.member.service.distributionlog.DistributionLogService;
@Tag(name = "管理后台 - 分销记录")
@RestController
@RequestMapping("/member/distribution-log")
@Validated
public class DistributionLogController {
@Resource
private DistributionLogService distributionLogService;
@Resource
private MemberUserService memberUserService;
@PostMapping("/create")
@Operation(summary = "创建分销记录")
@PreAuthorize("@ss.hasPermission('member:distribution-log:create')")
public CommonResult<Long> createDistributionLog(@Valid @RequestBody DistributionLogSaveReqVO createReqVO) {
return success(distributionLogService.createDistributionLog(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新分销记录")
@PreAuthorize("@ss.hasPermission('member:distribution-log:update')")
public CommonResult<Boolean> updateDistributionLog(@Valid @RequestBody DistributionLogSaveReqVO updateReqVO) {
distributionLogService.updateDistributionLog(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除分销记录")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('member:distribution-log:delete')")
public CommonResult<Boolean> deleteDistributionLog(@RequestParam("id") Long id) {
distributionLogService.deleteDistributionLog(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得分销记录")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('member:distribution-log:query')")
public CommonResult<DistributionLogRespVO> getDistributionLog(@RequestParam("id") Long id) {
DistributionLogDO distributionLog = distributionLogService.getDistributionLog(id);
return success(BeanUtils.toBean(distributionLog, DistributionLogRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得分销记录分页")
@PreAuthorize("@ss.hasPermission('member:distribution-log:query')")
public CommonResult<PageResult<DistributionLogRespVO>> getDistributionLogPage(@Valid DistributionLogPageReqVO pageReqVO) {
pageReqVO.setGameStatus("0");
PageResult<DistributionLogDO> pageResult = distributionLogService.getDistributionLogPage(pageReqVO);
// 拼接结果返回
List<MemberUserDO> users = memberUserService.getUserList(
convertSet(pageResult.getList(), DistributionLogDO::getMebId));
return success(DistributionLogConvert.INSTANCE.convertPage(pageResult, users));
}
@GetMapping("/export-excel")
@Operation(summary = "导出分销记录 Excel")
@PreAuthorize("@ss.hasPermission('member:distribution-log:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportDistributionLogExcel(@Valid DistributionLogPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<DistributionLogDO> list = distributionLogService.getDistributionLogPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "分销记录.xls", "数据", DistributionLogRespVO.class,
BeanUtils.toBean(list, DistributionLogRespVO.class));
}
}

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
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 = "管理后台 - 分销记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DistributionLogPageReqVO extends PageParam {
@Schema(description = "推荐人id", example = "5267")
private Long referrerId;
@Schema(description = "推荐人id(便于回溯)", example = "23906")
private Long oldReferrerId;
@Schema(description = "购买人id", example = "6637")
private Long mebId;
@Schema(description = "佣金")
private Integer brokerage;
@Schema(description = "分佣结算核销状态", example = "2")
private String status;
@Schema(description = "游戏状态", example = "2")
private String gameStatus;
@Schema(description = "游戏兑换状态", example = "1")
private String convertStatus;
@Schema(description = "推荐人会员等级id", example = "10242")
private Long levelId;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 分销记录 Response VO")
@Data
@ExcelIgnoreUnannotated
public class DistributionLogRespVO {
@Schema(description = "id主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "4693")
@ExcelProperty("id主键")
private Long id;
@Schema(description = "推荐人id", example = "5267")
@ExcelProperty("推荐人id")
private Long referrerId;
@Schema(description = "推荐人id(便于回溯)", example = "23906")
@ExcelProperty("推荐人id(便于回溯)")
private Long oldReferrerId;
@Schema(description = "购买人id", example = "6637")
@ExcelProperty("购买人id")
private Long mebId;
@Schema(description = "佣金")
@ExcelProperty("佣金")
private Integer brokerage;
@Schema(description = "分佣结算核销状态", example = "2")
@ExcelProperty("分佣结算核销状态")
private String status;
@Schema(description = "游戏状态", example = "2")
@ExcelProperty("游戏状态")
private String gameStatus;
@Schema(description = "游戏兑换状态", example = "1")
@ExcelProperty("游戏兑换状态")
private String convertStatus;
@Schema(description = "推荐人会员等级id", example = "10242")
@ExcelProperty("推荐人会员等级id")
private Long levelId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "用户昵称", example = "2")
@ExcelProperty("用户昵称")
private String nickname;
@Schema(description = "用户名称", example = "2")
@ExcelProperty("用户名称")
private String userName;
@Schema(description = "手机号", example = "2")
@ExcelProperty("手机号")
private String phone;
}

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 分销记录新增/修改 Request VO")
@Data
public class DistributionLogSaveReqVO {
@Schema(description = "id主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "4693")
private Long id;
@Schema(description = "推荐人id", example = "5267")
private Long referrerId;
@Schema(description = "推荐人id(便于回溯)", example = "23906")
private Long oldReferrerId;
@Schema(description = "购买人id", example = "6637")
private Long mebId;
@Schema(description = "佣金")
private Integer brokerage;
@Schema(description = "分佣结算核销状态", example = "2")
private String status;
@Schema(description = "游戏状态", example = "2")
private String gameStatus;
@Schema(description = "游戏兑换状态", example = "1")
private String convertStatus;
@Schema(description = "推荐人会员等级id", example = "10242")
private Long levelId;
}

@ -0,0 +1,124 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionstatistics;
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
import cn.iocoder.yudao.module.member.convert.distributionlog.DistributionLogConvert;
import cn.iocoder.yudao.module.member.convert.distributionstatistics.DistributionStatisticsConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics.DistributionStatisticsDO;
import cn.iocoder.yudao.module.member.service.distributionstatistics.DistributionStatisticsService;
@Tag(name = "管理后台 - 分销统计")
@RestController
@RequestMapping("/member/distribution-statistics")
@Validated
public class DistributionStatisticsController {
@Resource
private DistributionStatisticsService distributionStatisticsService;
@Resource
private MemberUserService memberUserService;
@Resource
private MemberLevelApi memberLevelApi;
@PostMapping("/create")
@Operation(summary = "创建分销统计")
@PreAuthorize("@ss.hasPermission('member:distribution-statistics:create')")
public CommonResult<Long> createDistributionStatistics(@Valid @RequestBody DistributionStatisticsSaveReqVO createReqVO) {
return success(distributionStatisticsService.createDistributionStatistics(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新分销统计")
@PreAuthorize("@ss.hasPermission('member:distribution-statistics:update')")
public CommonResult<Boolean> updateDistributionStatistics(@Valid @RequestBody DistributionStatisticsSaveReqVO updateReqVO) {
distributionStatisticsService.updateDistributionStatistics(updateReqVO);
return success(true);
}
@PutMapping("/updateAlready")
@Operation(summary = "结算分销统计")
@PreAuthorize("@ss.hasPermission('member:distribution-statistics:update')")
public CommonResult<Boolean> updateAlready(@Valid @RequestBody DistributionStatisticsSaveReqVO updateReqVO) {
distributionStatisticsService.updateAlready(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除分销统计")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('member:distribution-statistics:delete')")
public CommonResult<Boolean> deleteDistributionStatistics(@RequestParam("id") Long id) {
distributionStatisticsService.deleteDistributionStatistics(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得分销统计")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('member:distribution-statistics:query')")
public CommonResult<DistributionStatisticsRespVO> getDistributionStatistics(@RequestParam("id") Long id) {
DistributionStatisticsDO distributionStatistics = distributionStatisticsService.getDistributionStatistics(id);
return success(BeanUtils.toBean(distributionStatistics, DistributionStatisticsRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得分销统计分页")
@PreAuthorize("@ss.hasPermission('member:distribution-statistics:query')")
public CommonResult<PageResult<DistributionStatisticsRespVO>> getDistributionStatisticsPage(@Valid DistributionStatisticsPageReqVO pageReqVO) {
PageResult<DistributionStatisticsRespVO> pageResult = distributionStatisticsService.getDistributionStatisticsPage1(pageReqVO);
// 拼接结果返回
// 处理用户级别返显
List<MemberLevelRespDTO> levels = memberLevelApi.getLevelList(
convertSet(pageResult.getList(), DistributionStatisticsRespVO::getLevelId));
List<MemberUserDO> users = memberUserService.getUserList(
convertSet(pageResult.getList(), DistributionStatisticsRespVO::getMebId));
return success(DistributionStatisticsConvert.INSTANCE.convertPage(pageResult, users,levels));
}
@GetMapping("/export-excel")
@Operation(summary = "导出分销统计 Excel")
@PreAuthorize("@ss.hasPermission('member:distribution-statistics:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportDistributionStatisticsExcel(@Valid DistributionStatisticsPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<DistributionStatisticsDO> list = distributionStatisticsService.getDistributionStatisticsPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "分销统计.xls", "数据", DistributionStatisticsRespVO.class,
BeanUtils.toBean(list, DistributionStatisticsRespVO.class));
}
}

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
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 = "管理后台 - 分销统计分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DistributionStatisticsPageReqVO extends PageParam {
@Schema(description = "会员等级id", example = "19012")
private Long levelId;
@Schema(description = "会员id", example = "10495")
private Long mebId;
@Schema(description = "推荐记录id", example = "5711")
private Long logId;
@Schema(description = "推荐人id", example = "2750")
private Long referrerId;
@Schema(description = "分佣结算核销状态", example = "1")
private String status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

@ -0,0 +1,70 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 分销统计 Response VO")
@Data
@ExcelIgnoreUnannotated
public class DistributionStatisticsRespVO {
@Schema(description = "id主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "25196")
@ExcelProperty("id主键")
private Long id;
@Schema(description = "会员等级id", example = "19012")
@ExcelProperty("会员等级id")
private Long levelId;
@Schema(description = "会员id", example = "10495")
@ExcelProperty("会员id")
private Long mebId;
@Schema(description = "推荐记录id", example = "5711")
@ExcelProperty("推荐记录id")
private Long logId;
@Schema(description = "推荐人id", example = "2750")
@ExcelProperty("推荐人id")
private Long referrerId;
@Schema(description = "分佣结算核销状态", example = "1")
@ExcelProperty("分佣结算核销状态")
private String status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "用户昵称", example = "2")
@ExcelProperty("用户昵称")
private String nickname;
@Schema(description = "用户名称", example = "2")
@ExcelProperty("用户名称")
private String userName;
@Schema(description = "手机号", example = "2")
@ExcelProperty("手机号")
private String phone;
@Schema(description = "会员等级", example = "2")
@ExcelProperty("会员等级")
private String levelName;
@Schema(description = "已结算", example = "2")
@ExcelProperty("已结算")
private Integer haveAlready;
@Schema(description = "未结算", example = "2")
@ExcelProperty("未结算")
private Integer unAlready;
}

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 分销统计新增/修改 Request VO")
@Data
public class DistributionStatisticsSaveReqVO {
@Schema(description = "id主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "25196")
private Long id;
@Schema(description = "会员等级id", example = "19012")
private Long levelId;
@Schema(description = "会员id", example = "10495")
private Long mebId;
@Schema(description = "推荐记录id", example = "5711")
private Long logId;
@Schema(description = "推荐人id", example = "2750")
private Long referrerId;
@Schema(description = "分佣结算核销状态", example = "1")
private String status;
}

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.member.controller.app.user; package cn.iocoder.yudao.module.member.controller.app.user;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.module.member.controller.app.user.vo.*; import cn.iocoder.yudao.module.member.controller.app.user.vo.*;
@ -8,6 +9,7 @@ import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.service.level.MemberLevelService; import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService; import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
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;
@ -31,7 +33,8 @@ public class AppMemberUserController {
private MemberUserService userService; private MemberUserService userService;
@Resource @Resource
private MemberLevelService levelService; private MemberLevelService levelService;
@Resource
private SocialClientApi socialClientApi;
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获得基本信息") @Operation(summary = "获得基本信息")
@PreAuthenticated @PreAuthenticated
@ -40,6 +43,7 @@ public class AppMemberUserController {
MemberLevelDO level = levelService.getLevel(user.getLevelId()); MemberLevelDO level = levelService.getLevel(user.getLevelId());
AppMemberUserInfoRespVO convert = MemberUserConvert.INSTANCE.convert(user, level); AppMemberUserInfoRespVO convert = MemberUserConvert.INSTANCE.convert(user, level);
convert.setId(getLoginUserId()+""); convert.setId(getLoginUserId()+"");
convert.setUrlLink(socialClientApi.getWxUrlInfo(UserTypeEnum.MEMBER.getValue()).toString());
return success(convert); return success(convert);
} }

@ -13,6 +13,9 @@ public class AppMemberUserInfoRespVO {
@Schema(description = "id") @Schema(description = "id")
private String id; private String id;
@Schema(description = "urlLink")
private String urlLink;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String nickname; private String nickname;

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.member.convert.distributionconfig;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.DistributionConfigRespVO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
@Mapper
public interface DistributionConfigConvert {
DistributionConfigConvert INSTANCE = Mappers.getMapper(DistributionConfigConvert.class);
default PageResult<DistributionConfigRespVO> convertPage(PageResult<DistributionConfigDO> page,
List<MemberLevelRespDTO> levels
, List<ProductSpuRespDTO> spuList) {
PageResult<DistributionConfigRespVO> pageResult = convertPage(page);
Map<Long, String> levelMap = convertMap(levels, MemberLevelRespDTO::getId, MemberLevelRespDTO::getName);
// 拼接关联属性
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
// 拼接数据
pageResult.getList().forEach(record ->{
findAndThen(spuMap, record.getProductId(), spu -> {
record.setSupName(spu.getName());
});
MapUtils.findAndThen(levelMap, record.getLevelId(),
level -> record.setLevelName(levelMap.get(record.getLevelId())));
});
return pageResult;
}
PageResult<DistributionConfigRespVO> convertPage(PageResult<DistributionConfigDO> page);
}

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.member.convert.distributionlog;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.DistributionConfigRespVO;
import cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo.DistributionLogRespVO;
import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInRecordDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
@Mapper
public interface DistributionLogConvert {
DistributionLogConvert INSTANCE = Mappers.getMapper(DistributionLogConvert.class);
default PageResult<DistributionLogRespVO> convertPage(PageResult<DistributionLogDO> pageResult, List<MemberUserDO> users) {
PageResult<DistributionLogRespVO> voPageResult = convertPage(pageResult);
// user 拼接
Map<Long, MemberUserDO> userMap = convertMap(users, MemberUserDO::getId);
voPageResult.getList().forEach(record -> MapUtils.findAndThen(userMap, record.getMebId(),
memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname()).setUserName(memberUserRespDTO.getName()).setPhone(memberUserRespDTO.getMobile())));
return voPageResult;
}
PageResult<DistributionLogRespVO> convertPage(PageResult<DistributionLogDO> page);
}

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.member.convert.distributionstatistics;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.DistributionConfigRespVO;
import cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo.DistributionLogRespVO;
import cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo.DistributionStatisticsRespVO;
import cn.iocoder.yudao.module.member.convert.distributionlog.DistributionLogConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics.DistributionStatisticsDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
@Mapper
public interface DistributionStatisticsConvert {
DistributionStatisticsConvert INSTANCE = Mappers.getMapper(DistributionStatisticsConvert.class);
default PageResult<DistributionStatisticsRespVO> convertPage(PageResult<DistributionStatisticsRespVO> pageResult, List<MemberUserDO> users,List<MemberLevelRespDTO> levels) {
PageResult<DistributionStatisticsRespVO> voPageResult = convertPage(pageResult);
// user 拼接
Map<Long, MemberUserDO> userMap = convertMap(users, MemberUserDO::getId);
Map<Long, String> levelMap = convertMap(levels, MemberLevelRespDTO::getId, MemberLevelRespDTO::getName);
voPageResult.getList().forEach(record -> {
MapUtils.findAndThen(userMap, record.getMebId(),
memberUserRespDTO -> record.setNickname(memberUserRespDTO.getNickname()).setUserName(memberUserRespDTO.getName()).setPhone(memberUserRespDTO.getMobile()));
MapUtils.findAndThen(levelMap, record.getLevelId(),
level -> record.setLevelName(levelMap.get(record.getLevelId())));
});
return voPageResult;
}
PageResult<DistributionStatisticsRespVO> convertPage(PageResult<DistributionStatisticsRespVO> page);
}

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* DO
*
* @author
*/
@TableName("member_distribution_config")
@KeySequence("member_distribution_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DistributionConfigDO extends BaseDO {
/**
* id
*/
@TableId
private Long id;
/**
* id
*/
private Long productId;
/**
*
*/
private String status;
/**
*
*/
private Long levelId;
}

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* DO
*
* @author
*/
@TableName("member_distribution_meb_config")
@KeySequence("member_distribution_meb_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DistributionMebConfigDO extends BaseDO {
/**
* id
*/
@TableId
private Long id;
/**
* id
*/
private Long configId;
/**
*
*/
private Long levelId;
/**
*
*/
private Integer brokerage;
}

@ -0,0 +1,63 @@
package cn.iocoder.yudao.module.member.dal.dataobject.distributionlog;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* DO
*
* @author
*/
@TableName("member_distribution_log")
@KeySequence("member_distribution_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DistributionLogDO extends BaseDO {
/**
* id
*/
@TableId
private Long id;
/**
* id
*/
private Long referrerId;
/**
* id(便)
*/
private Long oldReferrerId;
/**
* id
*/
private Long mebId;
/**
*
*/
private Integer brokerage;
/**
*
*/
private String status;
/**
*
*/
private String gameStatus;
/**
*
*/
private String convertStatus;
/**
* id
*/
private Long levelId;
}

@ -0,0 +1,51 @@
package cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* DO
*
* @author
*/
@TableName("member_distribution_statistics")
@KeySequence("member_distribution_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DistributionStatisticsDO extends BaseDO {
/**
* id
*/
@TableId
private Long id;
/**
* id
*/
private Long levelId;
/**
* id
*/
private Long mebId;
/**
* id
*/
private Long logId;
/**
* id
*/
private Long referrerId;
/**
*
*/
private String status;
}

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.member.dal.mysql.distributionconfig;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.*;
/**
* Mapper
*
* @author
*/
@Mapper
public interface DistributionConfigMapper extends BaseMapperX<DistributionConfigDO> {
default PageResult<DistributionConfigDO> selectPage(DistributionConfigPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<DistributionConfigDO>()
.eqIfPresent(DistributionConfigDO::getProductId, reqVO.getProductId())
.eqIfPresent(DistributionConfigDO::getStatus, reqVO.getStatus())
.betweenIfPresent(DistributionConfigDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(DistributionConfigDO::getId));
}
}

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.member.dal.mysql.distributionconfig;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionMebConfigDO;
import org.apache.ibatis.annotations.Mapper;
/**
* Mapper
*
* @author
*/
@Mapper
public interface DistributionMebConfigMapper extends BaseMapperX<DistributionMebConfigDO> {
default List<DistributionMebConfigDO> selectListByConfigId(Long configId) {
return selectList(DistributionMebConfigDO::getConfigId, configId);
}
default int deleteByConfigId(Long configId) {
return delete(DistributionMebConfigDO::getConfigId, configId);
}
}

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.member.dal.mysql.distributionlog;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo.*;
/**
* Mapper
*
* @author
*/
@Mapper
public interface DistributionLogMapper extends BaseMapperX<DistributionLogDO> {
default PageResult<DistributionLogDO> selectPage(DistributionLogPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<DistributionLogDO>()
.eqIfPresent(DistributionLogDO::getReferrerId, reqVO.getReferrerId())
.eqIfPresent(DistributionLogDO::getOldReferrerId, reqVO.getOldReferrerId())
.eqIfPresent(DistributionLogDO::getMebId, reqVO.getMebId())
.eqIfPresent(DistributionLogDO::getBrokerage, reqVO.getBrokerage())
.eqIfPresent(DistributionLogDO::getStatus, reqVO.getStatus())
.eqIfPresent(DistributionLogDO::getGameStatus, reqVO.getGameStatus())
.eqIfPresent(DistributionLogDO::getConvertStatus, reqVO.getConvertStatus())
.eqIfPresent(DistributionLogDO::getLevelId, reqVO.getLevelId())
.betweenIfPresent(DistributionLogDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(DistributionLogDO::getId));
}
}

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.member.dal.mysql.distributionstatistics;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics.DistributionStatisticsDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo.*;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* Mapper
*
* @author
*/
@Mapper
public interface DistributionStatisticsMapper extends BaseMapperX<DistributionStatisticsDO> {
default PageResult<DistributionStatisticsDO> selectPage(DistributionStatisticsPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<DistributionStatisticsDO>()
.eqIfPresent(DistributionStatisticsDO::getLevelId, reqVO.getLevelId())
.eqIfPresent(DistributionStatisticsDO::getMebId, reqVO.getMebId())
.eqIfPresent(DistributionStatisticsDO::getLogId, reqVO.getLogId())
.eqIfPresent(DistributionStatisticsDO::getReferrerId, reqVO.getReferrerId())
.eqIfPresent(DistributionStatisticsDO::getStatus, reqVO.getStatus())
.betweenIfPresent(DistributionStatisticsDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(DistributionStatisticsDO::getId));
}
@Select({"<script>",
"SELECT\n" +
"\ts.meb_id,\n" +
"\ts.level_id,\n" +
"\tsum( CASE WHEN s.STATUS = 0 THEN 1 ELSE 0 END ) AS 'have_already',\n" +
"\tsum( CASE WHEN s.STATUS = 1 THEN 1 ELSE 0 END ) AS 'un_already' \n" +
"FROM\n" +
"\tmember_distribution_statistics s",
"where s.deleted = FALSE ",
"<if test='status !=null and status!=\"\" '>" ,
" and s.status = #{status}" ,
"</if> ",
"GROUP BY\n" +
"\ts.meb_id,\n" +
"\ts.level_id",
"order BY\n" +
"\ts.meb_id,\n" +
"\ts.level_id",
"</script>"})
IPage<DistributionStatisticsRespVO> selectPage1(IPage<?> page, @Param("status") String status);
}

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.service.auth;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;

@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.member.service.distributionconfig;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionMebConfigDO;
/**
* Service
*
* @author
*/
public interface DistributionConfigService {
/**
*
*
* @param createReqVO
* @return
*/
Long createDistributionConfig(@Valid DistributionConfigSaveReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateDistributionConfig(@Valid DistributionConfigSaveReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteDistributionConfig(Long id);
/**
*
*
* @param id
* @return
*/
DistributionConfigDO getDistributionConfig(Long id);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<DistributionConfigDO> getDistributionConfigPage(DistributionConfigPageReqVO pageReqVO);
// ==================== 子表(分销配置关联会员等级) ====================
/**
*
*
* @param configId id
* @return
*/
List<DistributionMebConfigDO> getDistributionMebConfigListByConfigId(Long configId);
}

@ -0,0 +1,112 @@
package cn.iocoder.yudao.module.member.service.distributionconfig;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionMebConfigDO;
import cn.iocoder.yudao.module.member.dal.mysql.distributionconfig.DistributionMebConfigMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.dal.mysql.distributionconfig.DistributionConfigMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
/**
* Service
*
* @author
*/
@Service
@Validated
public class DistributionConfigServiceImpl implements DistributionConfigService {
@Resource
private DistributionConfigMapper distributionConfigMapper;
@Resource
private DistributionMebConfigMapper distributionMebConfigMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createDistributionConfig(DistributionConfigSaveReqVO createReqVO) {
// 插入
DistributionConfigDO distributionConfig = BeanUtils.toBean(createReqVO, DistributionConfigDO.class);
distributionConfigMapper.insert(distributionConfig);
// 插入子表
createDistributionMebConfigList(distributionConfig.getId(), createReqVO.getDistributionMebConfigs());
// 返回
return distributionConfig.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateDistributionConfig(DistributionConfigSaveReqVO updateReqVO) {
// 校验存在
validateDistributionConfigExists(updateReqVO.getId());
// 更新
DistributionConfigDO updateObj = BeanUtils.toBean(updateReqVO, DistributionConfigDO.class);
distributionConfigMapper.updateById(updateObj);
// 更新子表
updateDistributionMebConfigList(updateReqVO.getId(), updateReqVO.getDistributionMebConfigs());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDistributionConfig(Long id) {
// 校验存在
validateDistributionConfigExists(id);
// 删除
distributionConfigMapper.deleteById(id);
// 删除子表
deleteDistributionMebConfigByConfigId(id);
}
private void validateDistributionConfigExists(Long id) {
if (distributionConfigMapper.selectById(id) == null) {
throw exception(DISTRIBUTION_CONFIG_NOT_EXISTS);
}
}
@Override
public DistributionConfigDO getDistributionConfig(Long id) {
return distributionConfigMapper.selectById(id);
}
@Override
public PageResult<DistributionConfigDO> getDistributionConfigPage(DistributionConfigPageReqVO pageReqVO) {
return distributionConfigMapper.selectPage(pageReqVO);
}
// ==================== 子表(分销配置关联会员等级) ====================
@Override
public List<DistributionMebConfigDO> getDistributionMebConfigListByConfigId(Long configId) {
return distributionMebConfigMapper.selectListByConfigId(configId);
}
private void createDistributionMebConfigList(Long configId, List<DistributionMebConfigDO> list) {
list.forEach(o -> o.setConfigId(configId));
distributionMebConfigMapper.insertBatch(list);
}
private void updateDistributionMebConfigList(Long configId, List<DistributionMebConfigDO> list) {
deleteDistributionMebConfigByConfigId(configId);
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下1id 冲突2updateTime 不更新
createDistributionMebConfigList(configId, list);
}
private void deleteDistributionMebConfigByConfigId(Long configId) {
distributionMebConfigMapper.deleteByConfigId(configId);
}
}

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.member.service.distributionlog;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* Service
*
* @author
*/
public interface DistributionLogService {
/**
*
*
* @param createReqVO
* @return
*/
Long createDistributionLog(@Valid DistributionLogSaveReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateDistributionLog(@Valid DistributionLogSaveReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteDistributionLog(Long id);
/**
*
*
* @param id
* @return
*/
DistributionLogDO getDistributionLog(Long id);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<DistributionLogDO> getDistributionLogPage(DistributionLogPageReqVO pageReqVO);
}

@ -0,0 +1,74 @@
package cn.iocoder.yudao.module.member.service.distributionlog;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.dal.mysql.distributionlog.DistributionLogMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
/**
* Service
*
* @author
*/
@Service
@Validated
public class DistributionLogServiceImpl implements DistributionLogService {
@Resource
private DistributionLogMapper distributionLogMapper;
@Override
public Long createDistributionLog(DistributionLogSaveReqVO createReqVO) {
// 插入
DistributionLogDO distributionLog = BeanUtils.toBean(createReqVO, DistributionLogDO.class);
distributionLogMapper.insert(distributionLog);
// 返回
return distributionLog.getId();
}
@Override
public void updateDistributionLog(DistributionLogSaveReqVO updateReqVO) {
// 校验存在
validateDistributionLogExists(updateReqVO.getId());
// 更新
DistributionLogDO updateObj = BeanUtils.toBean(updateReqVO, DistributionLogDO.class);
distributionLogMapper.updateById(updateObj);
}
@Override
public void deleteDistributionLog(Long id) {
// 校验存在
validateDistributionLogExists(id);
// 删除
distributionLogMapper.deleteById(id);
}
private void validateDistributionLogExists(Long id) {
if (distributionLogMapper.selectById(id) == null) {
throw exception(DISTRIBUTION_LOG_NOT_EXISTS);
}
}
@Override
public DistributionLogDO getDistributionLog(Long id) {
return distributionLogMapper.selectById(id);
}
@Override
public PageResult<DistributionLogDO> getDistributionLogPage(DistributionLogPageReqVO pageReqVO) {
return distributionLogMapper.selectPage(pageReqVO);
}
}

@ -0,0 +1,68 @@
package cn.iocoder.yudao.module.member.service.distributionstatistics;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics.DistributionStatisticsDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* Service
*
* @author
*/
public interface DistributionStatisticsService {
/**
*
*
* @param createReqVO
* @return
*/
Long createDistributionStatistics(@Valid DistributionStatisticsSaveReqVO createReqVO);
/**
*
*
* @param updateReqVO
*/
void updateDistributionStatistics(@Valid DistributionStatisticsSaveReqVO updateReqVO);
/**
*
*
* @param updateReqVO
*/
void updateAlready(@Valid DistributionStatisticsSaveReqVO updateReqVO);
/**
*
*
* @param id
*/
void deleteDistributionStatistics(Long id);
/**
*
*
* @param id
* @return
*/
DistributionStatisticsDO getDistributionStatistics(Long id);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<DistributionStatisticsDO> getDistributionStatisticsPage(DistributionStatisticsPageReqVO pageReqVO);
/**
*
*
* @param pageReqVO
* @return
*/
PageResult<DistributionStatisticsRespVO> getDistributionStatisticsPage1(DistributionStatisticsPageReqVO pageReqVO);
}

@ -0,0 +1,96 @@
package cn.iocoder.yudao.module.member.service.distributionstatistics;
import cn.hutool.core.util.ArrayUtil;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO;
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics.DistributionStatisticsDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.dal.mysql.distributionstatistics.DistributionStatisticsMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
/**
* Service
*
* @author
*/
@Service
@Validated
public class DistributionStatisticsServiceImpl implements DistributionStatisticsService {
@Resource
private DistributionStatisticsMapper distributionStatisticsMapper;
@Override
public Long createDistributionStatistics(DistributionStatisticsSaveReqVO createReqVO) {
// 插入
DistributionStatisticsDO distributionStatistics = BeanUtils.toBean(createReqVO, DistributionStatisticsDO.class);
distributionStatisticsMapper.insert(distributionStatistics);
// 返回
return distributionStatistics.getId();
}
@Override
public void updateDistributionStatistics(DistributionStatisticsSaveReqVO updateReqVO) {
// 校验存在
validateDistributionStatisticsExists(updateReqVO.getId());
// 更新
DistributionStatisticsDO updateObj = BeanUtils.toBean(updateReqVO, DistributionStatisticsDO.class);
distributionStatisticsMapper.updateById(updateObj);
}
@Override
public void updateAlready(DistributionStatisticsSaveReqVO updateReqVO) {
// 结算
distributionStatisticsMapper.update(new UpdateWrapper<DistributionStatisticsDO>().lambda().set(DistributionStatisticsDO::getStatus,0).eq(DistributionStatisticsDO::getMebId,updateReqVO.getMebId()).eq(DistributionStatisticsDO::getLevelId,updateReqVO.getLevelId()));
}
@Override
public void deleteDistributionStatistics(Long id) {
// 校验存在
validateDistributionStatisticsExists(id);
// 删除
distributionStatisticsMapper.deleteById(id);
}
private void validateDistributionStatisticsExists(Long id) {
if (distributionStatisticsMapper.selectById(id) == null) {
throw exception(DISTRIBUTION_STATISTICS_NOT_EXISTS);
}
}
@Override
public DistributionStatisticsDO getDistributionStatistics(Long id) {
return distributionStatisticsMapper.selectById(id);
}
@Override
public PageResult<DistributionStatisticsDO> getDistributionStatisticsPage(DistributionStatisticsPageReqVO pageReqVO) {
return distributionStatisticsMapper.selectPage(pageReqVO);
}
@Override
public PageResult<DistributionStatisticsRespVO> getDistributionStatisticsPage1(DistributionStatisticsPageReqVO pageReqVO) {
IPage<DistributionStatisticsRespVO> pageResult = distributionStatisticsMapper.selectPage1(
MyBatisUtils.buildPage(pageReqVO),
pageReqVO.getStatus());
return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
// return distributionStatisticsMapper.selectPage1(pageReqVO);
}
}

@ -200,5 +200,14 @@ public interface MemberUserService {
* @return * @return
*/ */
void updateUserUpgradesLevel(Long userId); void updateUserUpgradesLevel(Long userId);
/**
*
*
* @param userId
* @param orderId id
* @param productId id
* @return
*/
void updateUserUpgradesLevelcallback(Long orderId);
} }

@ -14,8 +14,16 @@ import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateR
import cn.iocoder.yudao.module.member.controller.app.user.vo.*; import cn.iocoder.yudao.module.member.controller.app.user.vo.*;
import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionMebConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics.DistributionStatisticsDO;
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.distributionconfig.DistributionConfigMapper;
import cn.iocoder.yudao.module.member.dal.mysql.distributionconfig.DistributionMebConfigMapper;
import cn.iocoder.yudao.module.member.dal.mysql.distributionlog.DistributionLogMapper;
import cn.iocoder.yudao.module.member.dal.mysql.distributionstatistics.DistributionStatisticsMapper;
import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper; import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper;
import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelRecordMapper; import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelRecordMapper;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
@ -25,11 +33,17 @@ import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
import cn.iocoder.yudao.module.system.api.social.SocialClientApi; import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageRecordMapper;
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper; import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -40,6 +54,7 @@ import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Date;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -79,6 +94,24 @@ public class MemberUserServiceImpl implements MemberUserService {
@Resource @Resource
private BrokerageUserMapper brokerageUserMapper; private BrokerageUserMapper brokerageUserMapper;
@Resource
private TradeOrderItemMapper tradeOrderItemMapper;
@Resource
@Lazy
private TradeOrderApi tradeOrderApi;
@Resource
private DistributionConfigMapper distributionConfigMapper;
@Resource
private BrokerageRecordMapper brokerageRecordMapper;
@Resource
private DistributionMebConfigMapper distributionMebConfigMapper;
@Resource
private DistributionLogMapper distributionLogMapper;
@Resource
private DistributionStatisticsMapper distributionStatisticsMapper;
@Override @Override
public MemberUserDO getUserByMobile(String mobile) { public MemberUserDO getUserByMobile(String mobile) {
@ -353,15 +386,140 @@ public class MemberUserServiceImpl implements MemberUserService {
} }
@Override @Override
public void updateUserUpgradesLevel(Long userId) { public void updateUserUpgradesLevel(Long userId) {
recursionMemberLevel(userId);
// if(i>0){
// return true;
// }
} }
private void recursionMemberLevel(Long userId){ @Override
public void updateUserUpgradesLevelcallback(Long orderId) {
//查询订单信息
Long productId = null;
List<TradeOrderItemDO> tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderId(orderId);
if(ObjectUtil.isNotEmpty(tradeOrderItemDOS)){
productId = tradeOrderItemDOS.get(0).getSpuId();
}
TradeOrderRespDTO order = tradeOrderApi.getOrder(orderId);
Long userId = order.getUserId();
//判断订单是否已支付
//根据商品id查询配置规则
List<DistributionConfigDO> distributionConfigDOS = distributionConfigMapper.selectList(new LambdaQueryWrapperX<DistributionConfigDO>()
.eq(DistributionConfigDO::getProductId, productId)
.eq(DistributionConfigDO::getDeleted, 0)
.eq(DistributionConfigDO::getStatus, 0)
.orderByDesc(DistributionConfigDO::getCreateTime));
if(ObjectUtil.isNotEmpty(distributionConfigDOS)){
DistributionConfigDO distributionConfigDO = distributionConfigDOS.get(0);
//查询会员当前等级
MemberUserDO user = memberUserMapper.selectById(userId);
MemberLevelDO memberLevelDO = memberLevelMapper.selectById(user.getLevelId());
//查询推广员配置信息
MemberLevelDO configLevelDO = memberLevelMapper.selectById(distributionConfigDO.getLevelId());
if(ObjectUtil.isEmpty(memberLevelDO)){
//修改购买人会员等级
int i = memberUserMapper.updateById(new MemberUserDO()
.setId(userId)
.setLevelId(distributionConfigDO.getLevelId())
);
brokerageUserMapper.updateById(new BrokerageUserDO()
.setId(userId)
.setLevel(configLevelDO.getLevel())
);
}else{
if(memberLevelDO.getLevel()<configLevelDO.getLevel()){
//修改购买人会员等级
int i = memberUserMapper.updateById(new MemberUserDO()
.setId(userId)
.setLevelId(distributionConfigDO.getLevelId())
);
brokerageUserMapper.updateById(new BrokerageUserDO()
.setId(userId)
.setLevel(configLevelDO.getLevel())
);
}
}
//查询配置中添加的等级奖励
List<DistributionMebConfigDO> distributionMebConfigDOS = distributionMebConfigMapper.selectList(new LambdaQueryWrapperX<DistributionMebConfigDO>()
.eq(DistributionMebConfigDO::getConfigId, distributionConfigDO.getId())
.eq(DistributionMebConfigDO::getDeleted, 0)
.orderByAsc(DistributionMebConfigDO::getLevelId));
//添加5占一
if(ObjectUtil.isNotEmpty(distributionMebConfigDOS)){
//添加5占一游戏
DistributionLogDO distributionLogDO = new DistributionLogDO();
distributionLogDO.setMebId(userId);
distributionLogDO.setStatus("1");
// distributionLogDO.setBrokerage();
distributionLogDO.setGameStatus("1");
distributionLogDO.setConvertStatus("1");
distributionLogMapper.insert(distributionLogDO);
//查询5占一总数
List<DistributionLogDO> distributionLogDOS = distributionLogMapper.selectList(new LambdaQueryWrapperX<DistributionLogDO>()
.orderByAsc(DistributionLogDO::getCreateTime));
int i1 = distributionLogDOS.size() % 5;
if(i1 == 0){
// DistributionLogDO vo = distributionLogDOS.get((distributionLogDOS.size()/5)-1);
// vo.setGameStatus("0");
// distributionLogMapper.updateById(vo);
List<DistributionLogDO> distributionLogDOS1 = distributionLogDOS.subList(0, (distributionLogDOS.size() / 5));
for (DistributionLogDO dt:distributionLogDOS1) {
dt.setGameStatus("0");
}
distributionLogMapper.updateBatch(distributionLogDOS1);
// distributionLogMapper.up
}
}
//发放直销奖励
//查询推广员
BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(userId);
if(ObjectUtil.isNotEmpty(brokerageUserDO)){
if(ObjectUtil.isNotEmpty(brokerageUserDO.getBindUserId())){
//查询推广员会员信息
MemberUserDO memberUserDO = memberUserMapper.selectById(brokerageUserDO.getBindUserId());
if(ObjectUtil.isNotEmpty(memberUserDO)){
if(ObjectUtil.isNotEmpty(distributionMebConfigDOS)){
for (DistributionMebConfigDO eg :distributionMebConfigDOS) {
if(eg.getLevelId() == memberUserDO.getLevelId()){
//添加佣金记录
BrokerageRecordDO brokerageRecordDO = new BrokerageRecordDO();
brokerageRecordDO.setUserId(memberUserDO.getId());
brokerageRecordDO.setBizType(1);
brokerageRecordDO.setTitle("分销直推佣金");
brokerageRecordDO.setPrice(eg.getBrokerage()*100);
//查询当前总佣金
Integer totalPrice = 0;
List<BrokerageRecordDO> brokerageRecordDOS = brokerageRecordMapper.selectList(new LambdaQueryWrapperX<BrokerageRecordDO>()
.eq(BrokerageRecordDO::getUserId, memberUserDO.getId())
.eq(BrokerageRecordDO::getDeleted, 0)
.orderByDesc(BrokerageRecordDO::getCreateTime));
if(ObjectUtil.isNotEmpty(brokerageRecordDOS)){
totalPrice = brokerageRecordDOS.get(0).getTotalPrice();
}
brokerageRecordDO.setTotalPrice(totalPrice+eg.getBrokerage()*100);//当前总佣金
brokerageRecordDO.setStatus(1);
brokerageRecordDO.setSourceUserLevel(configLevelDO.getLevel());
brokerageRecordDO.setSourceUserId(userId);
brokerageRecordMapper.insert(brokerageRecordDO);
break;
}
}
}
recursionMemberLevel(brokerageUserDO.getId(),orderId);
}
}
}
}
}
private void recursionMemberLevel(Long userId,Long orderId){
//查询会员信息 //查询会员信息
MemberUserDO memberUserDO = memberUserMapper.selectById(userId); MemberUserDO memberUserDO = memberUserMapper.selectById(userId);
DistributionStatisticsDO distributionStatisticsDO = new DistributionStatisticsDO();
distributionStatisticsDO.setLevelId(memberUserDO.getLevelId());
distributionStatisticsDO.setMebId(memberUserDO.getId());
distributionStatisticsDO.setLogId(orderId);
distributionStatisticsDO.setStatus("1");
distributionStatisticsMapper.insert(distributionStatisticsDO);
//查询会员当前等级 //查询会员当前等级
MemberLevelDO memberLevelDO = memberLevelMapper.selectById(memberUserDO.getLevelId()); MemberLevelDO memberLevelDO = memberLevelMapper.selectById(memberUserDO.getLevelId());
if(ObjectUtil.isNotEmpty(memberLevelDO)){ if(ObjectUtil.isNotEmpty(memberLevelDO)){
@ -372,28 +530,14 @@ public class MemberUserServiceImpl implements MemberUserService {
.eq(MemberLevelDO::getLevel, (memberLevelDO.getLevel()+1)) .eq(MemberLevelDO::getLevel, (memberLevelDO.getLevel()+1))
.orderByAsc(MemberLevelDO::getLevel)); .orderByAsc(MemberLevelDO::getLevel));
if(ObjectUtil.isNotEmpty(upLevelDO)){ if(ObjectUtil.isNotEmpty(upLevelDO)){
if(ObjectUtil.equal(memberLevelDO.getLevel(),1)){//帮扶人升级帮扶员 if(ObjectUtil.equal(memberLevelDO.getLevel(),1)){//帮扶人不升级
//添加分润 //添加推荐统计
//升级会员
//修改会员等级
memberUserMapper.updateById(new MemberUserDO()
.setId(userId)
.setLevelId(upLevelDO.getId())
);
//修改邀请记录等级
brokerageUserMapper.updateById(new BrokerageUserDO()
.setId(userId)
.setLevel(upLevelDO.getLevel())
);
//判断上级会员是否升级
BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(userId);
recursionMemberLevel(brokerageUserDO.getBindUserId());
} }
if(ObjectUtil.equal(memberLevelDO.getLevel(),2)){//帮扶员升级帮扶大使 if(ObjectUtil.equal(memberLevelDO.getLevel(),2)){//帮扶员升级帮扶驿站
//查询会员邀请记录下级会员 //查询会员邀请记录下级会员
List<BrokerageUserDO> brokerageUserDOS = brokerageUserMapper.selectList(new LambdaQueryWrapperX<BrokerageUserDO>() List<BrokerageUserDO> brokerageUserDOS = brokerageUserMapper.selectList(new LambdaQueryWrapperX<BrokerageUserDO>()
.eq(BrokerageUserDO::getBindUserId, userId) .eq(BrokerageUserDO::getBindUserId, userId)
.eq(BrokerageUserDO::getLevel, memberLevelDO.getLevel()) .ge(BrokerageUserDO::getLevel, memberLevelDO.getLevel())
.eq(BrokerageUserDO::getDeleted, 0) .eq(BrokerageUserDO::getDeleted, 0)
); );
if(ObjectUtil.isNotEmpty(brokerageUserDOS)){ if(ObjectUtil.isNotEmpty(brokerageUserDOS)){
@ -411,41 +555,23 @@ public class MemberUserServiceImpl implements MemberUserService {
} }
//判断上级会员是否升级 //判断上级会员是否升级
BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(userId); BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(userId);
recursionMemberLevel(brokerageUserDO.getBindUserId()); recursionMemberLevel(brokerageUserDO.getBindUserId(),orderId);
} }
if(ObjectUtil.equal(memberLevelDO.getLevel(),3)){//帮扶大使升级帮扶中心 if(ObjectUtil.equal(memberLevelDO.getLevel(),3)){//帮扶驿站升级帮扶中心
//查询会员邀请记录下级会员 //查询会员邀请记录下级会员
List<BrokerageUserDO> brokerageUserDOS = brokerageUserMapper.selectList(new LambdaQueryWrapperX<BrokerageUserDO>() List<BrokerageUserDO> brokerageUserDOS = brokerageUserMapper.selectList(new LambdaQueryWrapperX<BrokerageUserDO>()
.eq(BrokerageUserDO::getBindUserId, userId) .eq(BrokerageUserDO::getBindUserId, userId)
.eq(BrokerageUserDO::getLevel, memberLevelDO.getLevel()) .ge(BrokerageUserDO::getLevel, memberLevelDO.getLevel())
.eq(BrokerageUserDO::getDeleted, 0) .eq(BrokerageUserDO::getDeleted, 0)
); );
if(ObjectUtil.isNotEmpty(brokerageUserDOS)){
if(brokerageUserDOS.size()>=5){
//升级会员
memberUserMapper.updateById(new MemberUserDO()
.setId(userId)
.setLevelId(upLevelDO.getId())
);
brokerageUserMapper.updateById(new BrokerageUserDO()
.setId(userId)
.setLevel(upLevelDO.getLevel())
);
}
}
//判断上级会员是否升级
BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(userId);
recursionMemberLevel(brokerageUserDO.getBindUserId());
}
if(ObjectUtil.equal(memberLevelDO.getLevel(),4)){//帮扶中心升级帮扶驿站
//查询会员邀请记录下级会员 //查询会员邀请记录下级会员
List<BrokerageUserDO> brokerageUserDOS = brokerageUserMapper.selectList(new LambdaQueryWrapperX<BrokerageUserDO>() List<BrokerageUserDO> brokerageUserDOS1 = brokerageUserMapper.selectList(new LambdaQueryWrapperX<BrokerageUserDO>()
.eq(BrokerageUserDO::getBindUserId, userId) .eq(BrokerageUserDO::getBindUserId, userId)
.eq(BrokerageUserDO::getLevel, memberLevelDO.getLevel()) .ge(BrokerageUserDO::getLevel, 2)
.eq(BrokerageUserDO::getDeleted, 0) .eq(BrokerageUserDO::getDeleted, 0)
); );
if(ObjectUtil.isNotEmpty(brokerageUserDOS)){ if(ObjectUtil.isNotEmpty(brokerageUserDOS)){
if(brokerageUserDOS.size()>=10){ if(brokerageUserDOS.size()>=10 || brokerageUserDOS1.size()>=300){
//升级会员 //升级会员
memberUserMapper.updateById(new MemberUserDO() memberUserMapper.updateById(new MemberUserDO()
.setId(userId) .setId(userId)
@ -459,10 +585,9 @@ public class MemberUserServiceImpl implements MemberUserService {
} }
//判断上级会员是否升级 //判断上级会员是否升级
BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(userId); BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(userId);
recursionMemberLevel(brokerageUserDO.getBindUserId()); recursionMemberLevel(brokerageUserDO.getBindUserId(),orderId);
} }
if(ObjectUtil.equal(memberLevelDO.getLevel(),5)){//帮扶驿站---最终级别 if(ObjectUtil.equal(memberLevelDO.getLevel(),4)){//帮扶中心不做升级
} }
} }
} }

@ -0,0 +1,138 @@
package cn.iocoder.yudao.module.member.service.distributionconfig;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.member.controller.admin.distributionconfig.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionconfig.DistributionConfigDO;
import cn.iocoder.yudao.module.member.dal.mysql.distributionconfig.DistributionConfigMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link DistributionConfigServiceImpl}
*
* @author
*/
@Import(DistributionConfigServiceImpl.class)
public class DistributionConfigServiceImplTest extends BaseDbUnitTest {
@Resource
private DistributionConfigServiceImpl distributionConfigService;
@Resource
private DistributionConfigMapper distributionConfigMapper;
@Test
public void testCreateDistributionConfig_success() {
// 准备参数
DistributionConfigSaveReqVO createReqVO = randomPojo(DistributionConfigSaveReqVO.class).setId(null);
// 调用
Long distributionConfigId = distributionConfigService.createDistributionConfig(createReqVO);
// 断言
assertNotNull(distributionConfigId);
// 校验记录的属性是否正确
DistributionConfigDO distributionConfig = distributionConfigMapper.selectById(distributionConfigId);
assertPojoEquals(createReqVO, distributionConfig, "id");
}
@Test
public void testUpdateDistributionConfig_success() {
// mock 数据
DistributionConfigDO dbDistributionConfig = randomPojo(DistributionConfigDO.class);
distributionConfigMapper.insert(dbDistributionConfig);// @Sql: 先插入出一条存在的数据
// 准备参数
DistributionConfigSaveReqVO updateReqVO = randomPojo(DistributionConfigSaveReqVO.class, o -> {
o.setId(dbDistributionConfig.getId()); // 设置更新的 ID
});
// 调用
distributionConfigService.updateDistributionConfig(updateReqVO);
// 校验是否更新正确
DistributionConfigDO distributionConfig = distributionConfigMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, distributionConfig);
}
@Test
public void testUpdateDistributionConfig_notExists() {
// 准备参数
DistributionConfigSaveReqVO updateReqVO = randomPojo(DistributionConfigSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> distributionConfigService.updateDistributionConfig(updateReqVO), DISTRIBUTION_CONFIG_NOT_EXISTS);
}
@Test
public void testDeleteDistributionConfig_success() {
// mock 数据
DistributionConfigDO dbDistributionConfig = randomPojo(DistributionConfigDO.class);
distributionConfigMapper.insert(dbDistributionConfig);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbDistributionConfig.getId();
// 调用
distributionConfigService.deleteDistributionConfig(id);
// 校验数据不存在了
assertNull(distributionConfigMapper.selectById(id));
}
@Test
public void testDeleteDistributionConfig_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> distributionConfigService.deleteDistributionConfig(id), DISTRIBUTION_CONFIG_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetDistributionConfigPage() {
// mock 数据
DistributionConfigDO dbDistributionConfig = randomPojo(DistributionConfigDO.class, o -> { // 等会查询到
o.setProductId(null);
o.setStatus(null);
o.setCreateTime(null);
});
distributionConfigMapper.insert(dbDistributionConfig);
// 测试 productId 不匹配
distributionConfigMapper.insert(cloneIgnoreId(dbDistributionConfig, o -> o.setProductId(null)));
// 测试 status 不匹配
distributionConfigMapper.insert(cloneIgnoreId(dbDistributionConfig, o -> o.setStatus(null)));
// 测试 createTime 不匹配
distributionConfigMapper.insert(cloneIgnoreId(dbDistributionConfig, o -> o.setCreateTime(null)));
// 准备参数
DistributionConfigPageReqVO reqVO = new DistributionConfigPageReqVO();
reqVO.setProductId(null);
reqVO.setStatus(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<DistributionConfigDO> pageResult = distributionConfigService.getDistributionConfigPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbDistributionConfig, pageResult.getList().get(0));
}
}

@ -0,0 +1,162 @@
package cn.iocoder.yudao.module.member.service.distributionlog;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.member.controller.admin.distributionlog.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionlog.DistributionLogDO;
import cn.iocoder.yudao.module.member.dal.mysql.distributionlog.DistributionLogMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link DistributionLogServiceImpl}
*
* @author
*/
@Import(DistributionLogServiceImpl.class)
public class DistributionLogServiceImplTest extends BaseDbUnitTest {
@Resource
private DistributionLogServiceImpl distributionLogService;
@Resource
private DistributionLogMapper distributionLogMapper;
@Test
public void testCreateDistributionLog_success() {
// 准备参数
DistributionLogSaveReqVO createReqVO = randomPojo(DistributionLogSaveReqVO.class).setId(null);
// 调用
Long distributionLogId = distributionLogService.createDistributionLog(createReqVO);
// 断言
assertNotNull(distributionLogId);
// 校验记录的属性是否正确
DistributionLogDO distributionLog = distributionLogMapper.selectById(distributionLogId);
assertPojoEquals(createReqVO, distributionLog, "id");
}
@Test
public void testUpdateDistributionLog_success() {
// mock 数据
DistributionLogDO dbDistributionLog = randomPojo(DistributionLogDO.class);
distributionLogMapper.insert(dbDistributionLog);// @Sql: 先插入出一条存在的数据
// 准备参数
DistributionLogSaveReqVO updateReqVO = randomPojo(DistributionLogSaveReqVO.class, o -> {
o.setId(dbDistributionLog.getId()); // 设置更新的 ID
});
// 调用
distributionLogService.updateDistributionLog(updateReqVO);
// 校验是否更新正确
DistributionLogDO distributionLog = distributionLogMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, distributionLog);
}
@Test
public void testUpdateDistributionLog_notExists() {
// 准备参数
DistributionLogSaveReqVO updateReqVO = randomPojo(DistributionLogSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> distributionLogService.updateDistributionLog(updateReqVO), DISTRIBUTION_LOG_NOT_EXISTS);
}
@Test
public void testDeleteDistributionLog_success() {
// mock 数据
DistributionLogDO dbDistributionLog = randomPojo(DistributionLogDO.class);
distributionLogMapper.insert(dbDistributionLog);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbDistributionLog.getId();
// 调用
distributionLogService.deleteDistributionLog(id);
// 校验数据不存在了
assertNull(distributionLogMapper.selectById(id));
}
@Test
public void testDeleteDistributionLog_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> distributionLogService.deleteDistributionLog(id), DISTRIBUTION_LOG_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetDistributionLogPage() {
// mock 数据
DistributionLogDO dbDistributionLog = randomPojo(DistributionLogDO.class, o -> { // 等会查询到
o.setReferrerId(null);
o.setOldReferrerId(null);
o.setMebId(null);
o.setBrokerage(null);
o.setStatus(null);
o.setGameStatus(null);
o.setConvertStatus(null);
o.setLevelId(null);
o.setCreateTime(null);
});
distributionLogMapper.insert(dbDistributionLog);
// 测试 referrerId 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setReferrerId(null)));
// 测试 oldReferrerId 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setOldReferrerId(null)));
// 测试 mebId 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setMebId(null)));
// 测试 brokerage 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setBrokerage(null)));
// 测试 status 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setStatus(null)));
// 测试 gameStatus 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setGameStatus(null)));
// 测试 convertStatus 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setConvertStatus(null)));
// 测试 levelId 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setLevelId(null)));
// 测试 createTime 不匹配
distributionLogMapper.insert(cloneIgnoreId(dbDistributionLog, o -> o.setCreateTime(null)));
// 准备参数
DistributionLogPageReqVO reqVO = new DistributionLogPageReqVO();
reqVO.setReferrerId(null);
reqVO.setOldReferrerId(null);
reqVO.setMebId(null);
reqVO.setBrokerage(null);
reqVO.setStatus(null);
reqVO.setGameStatus(null);
reqVO.setConvertStatus(null);
reqVO.setLevelId(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<DistributionLogDO> pageResult = distributionLogService.getDistributionLogPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbDistributionLog, pageResult.getList().get(0));
}
}

@ -0,0 +1,150 @@
package cn.iocoder.yudao.module.member.service.distributionstatistics;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.member.controller.admin.distributionstatistics.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.distributionstatistics.DistributionStatisticsDO;
import cn.iocoder.yudao.module.member.dal.mysql.distributionstatistics.DistributionStatisticsMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link DistributionStatisticsServiceImpl}
*
* @author
*/
@Import(DistributionStatisticsServiceImpl.class)
public class DistributionStatisticsServiceImplTest extends BaseDbUnitTest {
@Resource
private DistributionStatisticsServiceImpl distributionStatisticsService;
@Resource
private DistributionStatisticsMapper distributionStatisticsMapper;
@Test
public void testCreateDistributionStatistics_success() {
// 准备参数
DistributionStatisticsSaveReqVO createReqVO = randomPojo(DistributionStatisticsSaveReqVO.class).setId(null);
// 调用
Long distributionStatisticsId = distributionStatisticsService.createDistributionStatistics(createReqVO);
// 断言
assertNotNull(distributionStatisticsId);
// 校验记录的属性是否正确
DistributionStatisticsDO distributionStatistics = distributionStatisticsMapper.selectById(distributionStatisticsId);
assertPojoEquals(createReqVO, distributionStatistics, "id");
}
@Test
public void testUpdateDistributionStatistics_success() {
// mock 数据
DistributionStatisticsDO dbDistributionStatistics = randomPojo(DistributionStatisticsDO.class);
distributionStatisticsMapper.insert(dbDistributionStatistics);// @Sql: 先插入出一条存在的数据
// 准备参数
DistributionStatisticsSaveReqVO updateReqVO = randomPojo(DistributionStatisticsSaveReqVO.class, o -> {
o.setId(dbDistributionStatistics.getId()); // 设置更新的 ID
});
// 调用
distributionStatisticsService.updateDistributionStatistics(updateReqVO);
// 校验是否更新正确
DistributionStatisticsDO distributionStatistics = distributionStatisticsMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, distributionStatistics);
}
@Test
public void testUpdateDistributionStatistics_notExists() {
// 准备参数
DistributionStatisticsSaveReqVO updateReqVO = randomPojo(DistributionStatisticsSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> distributionStatisticsService.updateDistributionStatistics(updateReqVO), DISTRIBUTION_STATISTICS_NOT_EXISTS);
}
@Test
public void testDeleteDistributionStatistics_success() {
// mock 数据
DistributionStatisticsDO dbDistributionStatistics = randomPojo(DistributionStatisticsDO.class);
distributionStatisticsMapper.insert(dbDistributionStatistics);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbDistributionStatistics.getId();
// 调用
distributionStatisticsService.deleteDistributionStatistics(id);
// 校验数据不存在了
assertNull(distributionStatisticsMapper.selectById(id));
}
@Test
public void testDeleteDistributionStatistics_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> distributionStatisticsService.deleteDistributionStatistics(id), DISTRIBUTION_STATISTICS_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetDistributionStatisticsPage() {
// mock 数据
DistributionStatisticsDO dbDistributionStatistics = randomPojo(DistributionStatisticsDO.class, o -> { // 等会查询到
o.setLevelId(null);
o.setMebId(null);
o.setLogId(null);
o.setReferrerId(null);
o.setStatus(null);
o.setCreateTime(null);
});
distributionStatisticsMapper.insert(dbDistributionStatistics);
// 测试 levelId 不匹配
distributionStatisticsMapper.insert(cloneIgnoreId(dbDistributionStatistics, o -> o.setLevelId(null)));
// 测试 mebId 不匹配
distributionStatisticsMapper.insert(cloneIgnoreId(dbDistributionStatistics, o -> o.setMebId(null)));
// 测试 logId 不匹配
distributionStatisticsMapper.insert(cloneIgnoreId(dbDistributionStatistics, o -> o.setLogId(null)));
// 测试 referrerId 不匹配
distributionStatisticsMapper.insert(cloneIgnoreId(dbDistributionStatistics, o -> o.setReferrerId(null)));
// 测试 status 不匹配
distributionStatisticsMapper.insert(cloneIgnoreId(dbDistributionStatistics, o -> o.setStatus(null)));
// 测试 createTime 不匹配
distributionStatisticsMapper.insert(cloneIgnoreId(dbDistributionStatistics, o -> o.setCreateTime(null)));
// 准备参数
DistributionStatisticsPageReqVO reqVO = new DistributionStatisticsPageReqVO();
reqVO.setLevelId(null);
reqVO.setMebId(null);
reqVO.setLogId(null);
reqVO.setReferrerId(null);
reqVO.setStatus(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<DistributionStatisticsDO> pageResult = distributionStatisticsService.getDistributionStatisticsPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbDistributionStatistics, pageResult.getList().get(0));
}
}

@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClient;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO;

@ -58,5 +58,8 @@ public interface PayOrderMapper extends BaseMapperX<PayOrderDO> {
.eq(PayOrderDO::getStatus, status) .eq(PayOrderDO::getStatus, status)
.lt(PayOrderDO::getExpireTime, expireTime)); .lt(PayOrderDO::getExpireTime, expireTime));
} }
default PayOrderDO selectPayOrderDOById(Long id) {
return selectById(id);
}
} }

@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO;
@ -75,6 +76,9 @@ public class PayOrderServiceImpl implements PayOrderService {
@Resource @Resource
private PayNotifyService notifyService; private PayNotifyService notifyService;
@Resource
private MemberUserApi memberUserApi;
@Override @Override
public PayOrderDO getOrder(Long id) { public PayOrderDO getOrder(Long id) {
return orderMapper.selectById(id); return orderMapper.selectById(id);
@ -268,6 +272,9 @@ public class PayOrderServiceImpl implements PayOrderService {
// 情况一:支付成功的回调 // 情况一:支付成功的回调
if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) { if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) {
notifyOrderSuccess(channel, notify); notifyOrderSuccess(channel, notify);
PayOrderExtensionDO orderExtension = updateOrderSuccess(notify);
PayOrderDO payOrderDO = orderMapper.selectPayOrderDOById(orderExtension.getOrderId());
memberUserApi.updateUserUpgradesLevelcallback(Long.valueOf(payOrderDO.getMerchantOrderId()));
return; return;
} }
// 情况二:支付失败的回调 // 情况二:支付失败的回调

@ -39,4 +39,8 @@ public interface SocialClientApi {
*/ */
SocialWxPhoneNumberInfoRespDTO getWxMaPhoneNumberInfo(Integer userType, String phoneCode); SocialWxPhoneNumberInfoRespDTO getWxMaPhoneNumberInfo(Integer userType, String phoneCode);
Object getWxUrlInfo(Integer type) ;
} }

@ -1,11 +1,13 @@
package cn.iocoder.yudao.module.system.api.social; package cn.iocoder.yudao.module.system.api.social;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
import cn.iocoder.yudao.module.system.service.social.SocialClientService; import cn.iocoder.yudao.module.system.service.social.SocialClientService;
import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -40,4 +42,9 @@ public class SocialClientApiImpl implements SocialClientApi {
return BeanUtils.toBean(info, SocialWxPhoneNumberInfoRespDTO.class); return BeanUtils.toBean(info, SocialWxPhoneNumberInfoRespDTO.class);
} }
@Override
public Object getWxUrlInfo(Integer type) {
return socialClientService.getWxUrlInfo(type);
}
} }

@ -2,12 +2,14 @@ package cn.iocoder.yudao.module.system.service.social;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import com.xingyuv.jushauth.model.AuthUser; import com.xingyuv.jushauth.model.AuthUser;
import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import javax.validation.Valid; import javax.validation.Valid;
@ -101,4 +103,5 @@ public interface SocialClientService {
*/ */
PageResult<SocialClientDO> getSocialClientPage(SocialClientPageReqVO pageReqVO); PageResult<SocialClientDO> getSocialClientPage(SocialClientPageReqVO pageReqVO);
Object getWxUrlInfo(Integer type);
} }

@ -8,11 +8,16 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.cache.CacheUtils; import cn.iocoder.yudao.framework.common.util.cache.CacheUtils;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
@ -47,6 +52,7 @@ import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/** /**
@ -336,4 +342,38 @@ public class SocialClientServiceImpl implements SocialClientService {
return socialClientMapper.selectPage(pageReqVO); return socialClientMapper.selectPage(pageReqVO);
} }
@Override
public Object getWxUrlInfo(Integer type) {
WxMaService wxMaService1 = getWxMaService(type);
String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
accessTokenUrl = String.format(accessTokenUrl, wxMaService1.getWxMaConfig().getAppid(), wxMaService1.getWxMaConfig().getSecret());
String accessToken = HttpUtil.post(accessTokenUrl, "");
JSONObject token = JSONUtil.parseObj(accessToken);
if (token.get("errcode") != null) {
throw new RuntimeException("获取微信小程序access_token失败");
}
/*
{
"path": "packageC/temporary/temporary",
"query": "'a=123'",
"env_version": "develop"
}
{"errcode":0,"errmsg":"ok","url_link":"https:\/\/wxaurl.cn\/OeiPo041PJe"}
*/
JSONObject jsonObject = new JSONObject();
jsonObject.putOnce("path", "pages/index/index");
jsonObject.putOnce("query", "r="+getLoginUserId());
jsonObject.putOnce("env_version", "develop");
String result = HttpUtil.post("https://api.weixin.qq.com/wxa/generate_urllink?access_token=ACCESS_TOKEN".replace("ACCESS_TOKEN", token.getStr("access_token")), jsonObject.toString());
JSONObject rfurl = JSONUtil.parseObj(result);
if (rfurl.get("errcode") != null&& rfurl.getInt("errcode") != 0) {
throw new RuntimeException("获取微信小程序url失败");
}
return rfurl.get("url_link");
//HttpUtil.post("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s");
// https://api.weixin.qq.com/wxa/generate_urllink?access_token=ACCESS_TOKEN
}
} }

@ -4,12 +4,12 @@ NODE_ENV=production
VITE_DEV=true VITE_DEV=true
# 请求路径 # 请求路径
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn' VITE_BASE_URL='http://localhost:48080'
# 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务 # 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务
VITE_UPLOAD_TYPE=server VITE_UPLOAD_TYPE=server
# 上传路径 # 上传路径
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload' VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
# 接口地址 # 接口地址
VITE_API_URL=/admin-api VITE_API_URL=/admin-api

File diff suppressed because it is too large Load Diff

@ -6,7 +6,7 @@
"private": false, "private": false,
"scripts": { "scripts": {
"i": "pnpm install", "i": "pnpm install",
"dev": "vite", "dev": "vite --mode dev",
"dev-server": "vite --mode dev", "dev-server": "vite --mode dev",
"ts:check": "vue-tsc --noEmit", "ts:check": "vue-tsc --noEmit",
"build:local": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build", "build:local": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build",

@ -0,0 +1,48 @@
import request from '@/config/axios'
// 分销配置 VO
export interface DistributionConfigVO {
id: number // id主键
productId: number // 分销商品id
status: string // 启用状态
}
// 分销配置 API
export const DistributionConfigApi = {
// 查询分销配置分页
getDistributionConfigPage: async (params: any) => {
return await request.get({ url: `/member/distribution-config/page`, params })
},
// 查询分销配置详情
getDistributionConfig: async (id: number) => {
return await request.get({ url: `/member/distribution-config/get?id=` + id })
},
// 新增分销配置
createDistributionConfig: async (data: DistributionConfigVO) => {
return await request.post({ url: `/member/distribution-config/create`, data })
},
// 修改分销配置
updateDistributionConfig: async (data: DistributionConfigVO) => {
return await request.put({ url: `/member/distribution-config/update`, data })
},
// 删除分销配置
deleteDistributionConfig: async (id: number) => {
return await request.delete({ url: `/member/distribution-config/delete?id=` + id })
},
// 导出分销配置 Excel
exportDistributionConfig: async (params) => {
return await request.download({ url: `/member/distribution-config/export-excel`, params })
},
// ==================== 子表(分销配置关联会员等级) ====================
// 获得分销配置关联会员等级列表
getDistributionMebConfigListByConfigId: async (configId) => {
return await request.get({ url: `/member/distribution-config/distribution-meb-config/list-by-config-id?configId=` + configId })
},
}

@ -0,0 +1,47 @@
import request from '@/config/axios'
// 分销记录 VO
export interface DistributionLogVO {
id: number // id主键
referrerId: number // 推荐人id
oldReferrerId: number // 推荐人id(便于回溯)
mebId: number // 购买人id
brokerage: number // 佣金
status: string // 分佣结算核销状态
gameStatus: string // 游戏状态
convertStatus: string // 游戏兑换状态
levelId: number // 推荐人会员等级id
}
// 分销记录 API
export const DistributionLogApi = {
// 查询分销记录分页
getDistributionLogPage: async (params: any) => {
return await request.get({ url: `/member/distribution-log/page`, params })
},
// 查询分销记录详情
getDistributionLog: async (id: number) => {
return await request.get({ url: `/member/distribution-log/get?id=` + id })
},
// 新增分销记录
createDistributionLog: async (data: DistributionLogVO) => {
return await request.post({ url: `/member/distribution-log/create`, data })
},
// 修改分销记录
updateDistributionLog: async (data: DistributionLogVO) => {
return await request.put({ url: `/member/distribution-log/update`, data })
},
// 删除分销记录
deleteDistributionLog: async (id: number) => {
return await request.delete({ url: `/member/distribution-log/delete?id=` + id })
},
// 导出分销记录 Excel
exportDistributionLog: async (params) => {
return await request.download({ url: `/member/distribution-log/export-excel`, params })
},
}

@ -0,0 +1,49 @@
import request from '@/config/axios'
// 分销统计 VO
export interface DistributionStatisticsVO {
id: number // id主键
levelId: number // 会员等级id
mebId: number // 会员id
logId: number // 推荐记录id
referrerId: number // 推荐人id
status: string // 分佣结算核销状态
}
// 分销统计 API
export const DistributionStatisticsApi = {
// 查询分销统计分页
getDistributionStatisticsPage: async (params: any) => {
return await request.get({ url: `/member/distribution-statistics/page`, params })
},
// 查询分销统计详情
getDistributionStatistics: async (id: number) => {
return await request.get({ url: `/member/distribution-statistics/get?id=` + id })
},
// 新增分销统计
createDistributionStatistics: async (data: DistributionStatisticsVO) => {
return await request.post({ url: `/member/distribution-statistics/create`, data })
},
// 修改分销统计
updateDistributionStatistics: async (data: DistributionStatisticsVO) => {
return await request.put({ url: `/member/distribution-statistics/update`, data })
},
// 结算分销统计
updateAlready: async (data: DistributionStatisticsVO) => {
return await request.put({ url: `/member/distribution-statistics/updateAlready`, data })
},
// 删除分销统计
deleteDistributionStatistics: async (id: number) => {
return await request.delete({ url: `/member/distribution-statistics/delete?id=` + id })
},
// 导出分销统计 Excel
exportDistributionStatistics: async (params) => {
return await request.download({ url: `/member/distribution-statistics/export-excel`, params })
},
}

@ -0,0 +1,52 @@
import request from '@/config/axios'
// 抽奖活动 VO
export interface PrizeDrawVO {
id: number // id主键
name: string // 活动名称
activityRule: string // 活动规则
status: string // 活动状态0开启1关闭
startTime: Date // 开始时间
endTime: Date // 截至时间
mebLevel: number // 会员等级
}
// 抽奖活动 API
export const PrizeDrawApi = {
// 查询抽奖活动分页
getPrizeDrawPage: async (params: any) => {
return await request.get({ url: `/promotion/prize-draw/page`, params })
},
// 查询抽奖活动详情
getPrizeDraw: async (id: number) => {
return await request.get({ url: `/promotion/prize-draw/get?id=` + id })
},
// 新增抽奖活动
createPrizeDraw: async (data: PrizeDrawVO) => {
return await request.post({ url: `/promotion/prize-draw/create`, data })
},
// 修改抽奖活动
updatePrizeDraw: async (data: PrizeDrawVO) => {
return await request.put({ url: `/promotion/prize-draw/update`, data })
},
// 删除抽奖活动
deletePrizeDraw: async (id: number) => {
return await request.delete({ url: `/promotion/prize-draw/delete?id=` + id })
},
// 导出抽奖活动 Excel
exportPrizeDraw: async (params) => {
return await request.download({ url: `/promotion/prize-draw/export-excel`, params })
},
// ==================== 子表(抽奖活动奖品) ====================
// 获得抽奖活动奖品列表
getActivityPrizeListByActivityId: async (activityId) => {
return await request.get({ url: `/promotion/prize-draw/activity-prize/list-by-activity-id?activityId=` + activityId })
},
}

@ -0,0 +1,47 @@
import request from '@/config/axios'
// 抽奖记录 VO
export interface PrizeLogVO {
id: number // 主键id
mebId: number // 会员id
activityId: number // 关联抽奖活动id
name: string // 奖品名称
imgUrl: string // 奖品图片路径
winNum: number // 获奖人数上限
prizeChance: string // 获奖概率
prizePoolAmount: string // 获奖金额
status: string // 兑奖状态0已兑奖1未兑奖
}
// 抽奖记录 API
export const PrizeLogApi = {
// 查询抽奖记录分页
getPrizeLogPage: async (params: any) => {
return await request.get({ url: `/promotion/prize-log/page`, params })
},
// 查询抽奖记录详情
getPrizeLog: async (id: number) => {
return await request.get({ url: `/promotion/prize-log/get?id=` + id })
},
// 新增抽奖记录
createPrizeLog: async (data: PrizeLogVO) => {
return await request.post({ url: `/promotion/prize-log/create`, data })
},
// 修改抽奖记录
updatePrizeLog: async (data: PrizeLogVO) => {
return await request.put({ url: `/promotion/prize-log/update`, data })
},
// 删除抽奖记录
deletePrizeLog: async (id: number) => {
return await request.delete({ url: `/promotion/prize-log/delete?id=` + id })
},
// 导出抽奖记录 Excel
exportPrizeLog: async (params) => {
return await request.download({ url: `/promotion/prize-log/export-excel`, params })
},
}

@ -0,0 +1,46 @@
<template>
<el-select v-model="levelId" placeholder="请选择商品" clearable class="!w-240px">
<el-option v-for="level in levelOptions" :key="level.id" :label="level.name" :value="level.id">
<span class="flex items-center gap-x-8px">
<el-avatar :src="level.picUrl" size="small" />
{{ level.name }}
</span>
</el-option>
</el-select>
</template>
<script lang="ts" setup>
// import * as ProductApi from '@/api/member/level'
// import * as ProductApi from '@/api/erp/product/product'
import * as ProductApi from '@/api/mall/product/spu'
/** 会员等级选择框 **/
defineOptions({ name: 'SkuSelect' })
const props = defineProps({
/** 下拉框选中值 **/
modelValue: {
type: Number,
default: undefined
}
})
const emit = defineEmits(['update:modelValue'])
const levelId = computed({
get() {
return props.modelValue
},
set(value: any) {
emit('update:modelValue', value)
}
})
const levelOptions = ref<ProductApi.Spu[]>([])
const getList = async () => {
levelOptions.value = await ProductApi.getSpuSimpleList()
}
/** 初始化 */
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,125 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="180px"
v-loading="formLoading"
>
<el-form-item label="分销商品" prop="productId">
<SkuSelect v-model="formData.productId" />
</el-form-item>
<el-form-item label="购买人提升至会员等级" prop="levelId">
<MemberLevelSelect v-model="formData.levelId" />
</el-form-item>
<el-form-item label="启用状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio label="0">启用</el-radio>
<el-radio label="1">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="分销配置关联会员等级" name="distributionMebConfig">
<DistributionMebConfigForm ref="distributionMebConfigFormRef" :config-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DistributionConfigApi, DistributionConfigVO } from '@/api/member/distributionconfig'
import DistributionMebConfigForm from './components/DistributionMebConfigForm.vue'
import SkuSelect from '@/views/mall/product/spu/components/SkuSelect.vue'
import MemberLevelSelect from '@/views/member/level/components/MemberLevelSelect.vue'
/** 分销配置 表单 */
defineOptions({ name: 'DistributionConfigForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
productId: undefined,
status: undefined,
levelId: undefined,
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 子表的表单 */
const subTabsName = ref('distributionMebConfig')
const distributionMebConfigFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await DistributionConfigApi.getDistributionConfig(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
try {
await distributionMebConfigFormRef.value.validate()
} catch (e) {
subTabsName.value = 'distributionMebConfig'
return
}
//
formLoading.value = true
try {
const data = formData.value as unknown as DistributionConfigVO
//
data.distributionMebConfigs = distributionMebConfigFormRef.value.getData()
if (formType.value === 'create') {
await DistributionConfigApi.createDistributionConfig(data)
message.success(t('common.createSuccess'))
} else {
await DistributionConfigApi.updateDistributionConfig(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
productId: undefined,
status: undefined,
levelId: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,97 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="会员等级" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.levelId`" :rules="formRules.levelId" class="mb-0px!">
<MemberLevelSelect v-model="row.levelId" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="佣金" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.brokerage`" :rules="formRules.brokerage" class="mb-0px!">
<el-input v-model="row.brokerage" placeholder="请输入佣金" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加分销配置关联会员等级</el-button>
</el-row>
</template>
<script setup lang="ts">
import { DistributionConfigApi } from '@/api/member/distributionconfig'
import MemberLevelSelect from '@/views/member/level/components/MemberLevelSelect.vue'
const props = defineProps<{
configId: undefined // id
}>()
const formLoading = ref(false) //
const formData = ref([])
const formRules = reactive({
})
const formRef = ref() // Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.configId,
async (val) => {
// 1.
formData.value = []
// 2. val
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await DistributionConfigApi.getDistributionMebConfigListByConfigId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
configId: undefined,
levelId: undefined,
brokerage: undefined,
}
row.configId = props.configId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

@ -0,0 +1,174 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['member:distribution-config:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['member:distribution-config:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" prop="id" />
<el-table-column label="分销商品" align="center" prop="supName" />
<el-table-column label="提升购买人会员等级" align="center" prop="levelName" />
<el-table-column label="启用状态" align="center" prop="status" >
<template #default="scope">
{{ scope.row.status==0?"启用":"禁用" }}
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['member:distribution-config:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['member:distribution-config:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DistributionConfigForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { DistributionConfigApi, DistributionConfigVO } from '@/api/member/distributionconfig'
import DistributionConfigForm from './DistributionConfigForm.vue'
/** 分销配置 列表 */
defineOptions({ name: 'DistributionConfig' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<DistributionConfigVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
productId: undefined,
status: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await DistributionConfigApi.getDistributionConfigPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DistributionConfigApi.deleteDistributionConfig(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await DistributionConfigApi.exportDistributionConfig(queryParams)
download.excel(data, '分销配置.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,108 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="兑换状态" prop="convertStatus">
<el-radio-group v-model="formData.convertStatus">
<el-radio label="0">已兑换</el-radio>
<el-radio label="1">未兑换</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DistributionLogApi, DistributionLogVO } from '@/api/member/distributionlog'
/** 分销记录 表单 */
defineOptions({ name: 'DistributionLogForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
referrerId: undefined,
oldReferrerId: undefined,
mebId: undefined,
brokerage: undefined,
status: undefined,
gameStatus: undefined,
convertStatus: undefined,
levelId: undefined,
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await DistributionLogApi.getDistributionLog(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as DistributionLogVO
if (formType.value === 'create') {
await DistributionLogApi.createDistributionLog(data)
message.success(t('common.createSuccess'))
} else {
await DistributionLogApi.updateDistributionLog(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
referrerId: undefined,
oldReferrerId: undefined,
mebId: undefined,
brokerage: undefined,
status: undefined,
gameStatus: undefined,
convertStatus: undefined,
levelId: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,187 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="兑换状态" prop="convertStatus">
<el-select
v-model="queryParams.convertStatus"
placeholder="请选择兑换状态"
clearable
class="!w-240px"
>
<el-option label="已兑换" value="0" />
<el-option label="未兑换" value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['member:distribution-log:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" prop="id" />
<el-table-column label="用户昵称" align="center" prop="nickname" />
<el-table-column label="真实姓名" align="center" prop="userName" />
<el-table-column label="手机号" align="center" prop="phone" />
<!-- <el-table-column label="佣金" align="center" prop="brokerage" /> -->
<!-- <el-table-column label="分佣结算核销状态" align="center" prop="status" /> -->
<!-- <el-table-column label="游戏状态" align="center" prop="gameStatus" /> -->
<el-table-column label="兑换状态" align="center" prop="convertStatus" >
<template #default="scope">
{{ scope.row.status==0?"已兑换":"未兑换" }}
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['member:distribution-log:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['member:distribution-log:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DistributionLogForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { DistributionLogApi, DistributionLogVO } from '@/api/member/distributionlog'
import DistributionLogForm from './DistributionLogForm.vue'
/** 分销记录 列表 */
defineOptions({ name: 'DistributionLog' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<DistributionLogVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
referrerId: undefined,
oldReferrerId: undefined,
mebId: undefined,
brokerage: undefined,
status: undefined,
gameStatus: undefined,
convertStatus: undefined,
levelId: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await DistributionLogApi.getDistributionLogPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DistributionLogApi.deleteDistributionLog(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await DistributionLogApi.exportDistributionLog(queryParams)
download.excel(data, '分销记录.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,113 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="会员等级id" prop="levelId">
<el-input v-model="formData.levelId" placeholder="请输入会员等级id" />
</el-form-item>
<el-form-item label="会员id" prop="mebId">
<el-input v-model="formData.mebId" placeholder="请输入会员id" />
</el-form-item>
<el-form-item label="推荐记录id" prop="logId">
<el-input v-model="formData.logId" placeholder="请输入推荐记录id" />
</el-form-item>
<el-form-item label="推荐人id" prop="referrerId">
<el-input v-model="formData.referrerId" placeholder="请输入推荐人id" />
</el-form-item>
<el-form-item label="分佣结算核销状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DistributionStatisticsApi, DistributionStatisticsVO } from '@/api/member/distributionstatistics'
/** 分销统计 表单 */
defineOptions({ name: 'DistributionStatisticsForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
levelId: undefined,
mebId: undefined,
logId: undefined,
referrerId: undefined,
status: undefined,
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await DistributionStatisticsApi.getDistributionStatistics(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as DistributionStatisticsVO
if (formType.value === 'create') {
await DistributionStatisticsApi.createDistributionStatistics(data)
message.success(t('common.createSuccess'))
} else {
await DistributionStatisticsApi.updateDistributionStatistics(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
levelId: undefined,
mebId: undefined,
logId: undefined,
referrerId: undefined,
status: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,175 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="分佣结算状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择分佣结算状态"
clearable
class="!w-240px"
>
<el-option label="已结算" value="0" />
<el-option label="未结算" value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['member:distribution-statistics:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" prop="id" />
<el-table-column label="用户名称" align="center" prop="nickname" />
<el-table-column label="真实姓名" align="center" prop="userName" />
<el-table-column label="手机号" align="center" prop="phone" />
<el-table-column label="会员等级" align="center" prop="levelName" />
<el-table-column label="已结算订单数量" align="center" prop="haveAlready" />
<el-table-column label="未结算订单数量" align="center" prop="unAlready" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="handleAlready(scope.row)"
v-hasPermi="['member:distribution-statistics:update']"
>
结算
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DistributionStatisticsForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { DistributionStatisticsApi, DistributionStatisticsVO } from '@/api/member/distributionstatistics'
import DistributionStatisticsForm from './DistributionStatisticsForm.vue'
/** 分销统计 列表 */
defineOptions({ name: 'DistributionStatistics' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<DistributionStatisticsVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
levelId: undefined,
mebId: undefined,
logId: undefined,
referrerId: undefined,
status: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await DistributionStatisticsApi.getDistributionStatisticsPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 结算按钮 */
const handleAlready = async (row) => {
try {
//
await message.confirm("确认结算用户"+row.nickname+"会员等级"+row.levelName+"的订单吗?")
//
await DistributionStatisticsApi.updateAlready(row)
message.success('结算完成!')
//
await getList()
} catch {}
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DistributionStatisticsApi.deleteDistributionStatistics(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await DistributionStatisticsApi.exportDistributionStatistics(queryParams)
download.excel(data, '分销统计.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,155 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="活动名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入活动名称" />
</el-form-item>
<el-form-item label="活动规则" prop="activityRule">
<Editor v-model="formData.activityRule" height="150px" />
</el-form-item>
<el-form-item label="活动状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio label="0">开启</el-radio>
<el-radio label="1">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
v-model="formData.startTime"
type="datetime"
value-format="x"
placeholder="选择开始时间"
/>
</el-form-item>
<el-form-item label="截至时间" prop="endTime">
<el-date-picker
v-model="formData.endTime"
type="datetime"
value-format="x"
placeholder="选择截至时间"
/>
</el-form-item>
<el-form-item label="会员等级" prop="mebLevel">
<MemberLevelSelect v-model="formData.mebLevel" />
<!-- <el-input v-model="formData.mebLevel" placeholder="请输入会员等级" /> -->
</el-form-item>
<el-form-item label="每人抽奖次数" prop="drawNum">
<el-input-number v-model="formData.drawNum" :min="1" placeholder="请输入单人次抽奖次数" />
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="抽奖活动奖品" name="activityPrize">
<ActivityPrizeForm ref="activityPrizeFormRef" :activity-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { PrizeDrawApi, PrizeDrawVO } from '@/api/promotion/prizedraw'
import ActivityPrizeForm from './components/ActivityPrizeForm.vue'
import MemberLevelSelect from '@/views/member/level/components/MemberLevelSelect.vue'
/** 抽奖活动 表单 */
defineOptions({ name: 'PrizeDrawForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
name: undefined,
activityRule: undefined,
status: "1",
startTime: undefined,
endTime: undefined,
mebLevel: undefined,
drawNum: undefined,
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 子表的表单 */
const subTabsName = ref('activityPrize')
const activityPrizeFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await PrizeDrawApi.getPrizeDraw(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
try {
await activityPrizeFormRef.value.validate()
} catch (e) {
subTabsName.value = 'activityPrize'
return
}
//
formLoading.value = true
try {
const data = formData.value as unknown as PrizeDrawVO
//
data.activityPrizes = activityPrizeFormRef.value.getData()
if (formType.value === 'create') {
await PrizeDrawApi.createPrizeDraw(data)
message.success(t('common.createSuccess'))
} else {
await PrizeDrawApi.updatePrizeDraw(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
activityRule: undefined,
status: "1",
startTime: undefined,
endTime: undefined,
mebLevel: undefined,
drawNum: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,121 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="奖品名称" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
<el-input v-model="row.name" placeholder="请输入奖品名称" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="奖品图片路径" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.imgUrl`" :rules="formRules.imgUrl" class="mb-0px!">
<UploadImg v-model="row.imgUrl" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="获奖人数上限" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.winNum`" :rules="formRules.winNum" class="mb-0px!">
<el-input v-model="row.winNum" placeholder="请输入获奖人数上限" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="获奖概率" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.prizeChance`" :rules="formRules.prizeChance" class="mb-0px!">
<el-input v-model="row.prizeChance" placeholder="请输入获奖概率" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="获奖金额" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.prizePoolAmount`" :rules="formRules.prizePoolAmount" class="mb-0px!">
<el-input v-model="row.prizePoolAmount" placeholder="请输入获奖金额" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加抽奖活动奖品</el-button>
</el-row>
</template>
<script setup lang="ts">
import { PrizeDrawApi } from '@/api/promotion/prizedraw'
const props = defineProps<{
activityId: undefined // id
}>()
const formLoading = ref(false) //
const formData = ref([])
const formRules = reactive({
})
const formRef = ref() // Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.activityId,
async (val) => {
// 1.
formData.value = []
// 2. val
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await PrizeDrawApi.getActivityPrizeListByActivityId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
activityId: undefined,
name: undefined,
imgUrl: undefined,
winNum: undefined,
prizeChance: undefined,
prizePoolAmount: undefined,
}
row.activityId = props.activityId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

@ -0,0 +1,244 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="活动名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入活动名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="活动状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择活动状态"
clearable
class="!w-240px"
>
<el-option label="开启" value="0" />
<el-option label="关闭" value="1" />
</el-select>
</el-form-item>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
v-model="queryParams.startTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="截至时间" prop="endTime">
<el-date-picker
v-model="queryParams.endTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="会员等级" prop="mebLevel">
<MemberLevelSelect v-model="queryParams.mebLevel" />
<!-- <el-input
v-model="queryParams.mebLevel"
placeholder="请输入会员等级"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/> -->
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['promotion:prize-draw:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['promotion:prize-draw:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="活动名称" align="center" prop="name" />
<el-table-column label="活动状态" align="center" prop="status" >
<template #default="scope">
{{ scope.row.status==0?"开启":"关闭" }}
</template>
</el-table-column>
<el-table-column label="每人抽奖次数" align="center" prop="drawNum" />
<el-table-column
label="开始时间"
align="center"
prop="startTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="截至时间"
align="center"
prop="endTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="参与会员等级" align="center" prop="levelName" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['promotion:prize-draw:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['promotion:prize-draw:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<PrizeDrawForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { PrizeDrawApi, PrizeDrawVO } from '@/api/promotion/prizedraw'
import PrizeDrawForm from './PrizeDrawForm.vue'
import MemberLevelSelect from '@/views/member/level/components/MemberLevelSelect.vue'
/** 抽奖活动 列表 */
defineOptions({ name: 'PrizeDraw' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<PrizeDrawVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: undefined,
activityRule: undefined,
status: undefined,
startTime: [],
endTime: [],
mebLevel: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await PrizeDrawApi.getPrizeDrawPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await PrizeDrawApi.deletePrizeDraw(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await PrizeDrawApi.exportPrizeDraw(queryParams)
download.excel(data, '抽奖活动.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,114 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="奖品名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入奖品名称" disabled/>
</el-form-item>
<el-form-item label="奖品图片" prop="imgUrl">
<el-image style="width: 100px; height: 100px" :src="formData.imgUrl" />
</el-form-item>
<el-form-item label="兑奖状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio label="0">已兑奖</el-radio>
<el-radio label="1">未兑奖</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { PrizeLogApi, PrizeLogVO } from '@/api/promotion/prizelog'
/** 抽奖记录 表单 */
defineOptions({ name: 'PrizeLogForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
mebId: undefined,
activityId: undefined,
name: undefined,
imgUrl: undefined,
winNum: undefined,
prizeChance: undefined,
prizePoolAmount: undefined,
status: undefined,
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await PrizeLogApi.getPrizeLog(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as PrizeLogVO
if (formType.value === 'create') {
await PrizeLogApi.createPrizeLog(data)
message.success(t('common.createSuccess'))
} else {
await PrizeLogApi.updatePrizeLog(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
mebId: undefined,
activityId: undefined,
name: undefined,
imgUrl: undefined,
winNum: undefined,
prizeChance: undefined,
prizePoolAmount: undefined,
status: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,209 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="奖品名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入奖品名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="兑奖状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择兑奖状态"
clearable
class="!w-240px"
>
<el-option label="已兑奖" value="0" />
<el-option label="未兑奖" value="1" />
</el-select>
</el-form-item>
<el-form-item label="中奖时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['promotion:prize-log:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="用户名称" align="center" prop="nickname" />
<el-table-column label="活动名称" align="center" prop="activityName" />
<el-table-column label="奖品名称" align="center" prop="name" />
<el-table-column label="奖品图片路径" align="center" prop="imgUrl" >
<template #default="scope">
<el-image style="width: 100px; height: 100px" :src="scope.row.imgUrl" />
</template>
</el-table-column>
<el-table-column label="兑奖状态" align="center" prop="status" >
<template #default="scope">
{{ scope.row.status==0?"已兑换":"未兑换" }}
</template>
</el-table-column>
<el-table-column
label="中奖时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['promotion:prize-log:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['promotion:prize-log:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<PrizeLogForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { PrizeLogApi, PrizeLogVO } from '@/api/promotion/prizelog'
import PrizeLogForm from './PrizeLogForm.vue'
/** 抽奖记录 列表 */
defineOptions({ name: 'PrizeLog' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<PrizeLogVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
nickname: undefined,
activityId: undefined,
activityName: undefined,
name: undefined,
imgUrl: undefined,
winNum: undefined,
prizeChance: undefined,
prizePoolAmount: undefined,
status: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await PrizeLogApi.getPrizeLogPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await PrizeLogApi.deletePrizeLog(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await PrizeLogApi.exportPrizeLog(queryParams)
download.excel(data, '抽奖记录.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
Loading…
Cancel
Save