Initial commit

This commit is contained in:
2026-04-23 16:58:11 +08:00
commit 267eba1eca
2582 changed files with 273338 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>skins-service</artifactId>
<version>4.8.2</version>
</parent>
<artifactId>service-user</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>service-admin</artifactId>
<version>4.8.2</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>service-thirdparty</artifactId>
<version>4.8.2</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,44 @@
package com.ruoyi.user.consumer;
import com.rabbitmq.client.Channel;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.domain.other.TtNotice;
import com.ruoyi.user.service.ApiNoticeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
@Component
@Slf4j
public class NoticeConsumer {
@Autowired
private ApiNoticeService apiNoticeService;
@RabbitListener(queues = "notice_queue")
public void insertNotice(Map<String, String> noticeMap, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
String userId = noticeMap.get("userId");
String title = noticeMap.get("title");
String content = noticeMap.get("content");
String createTime = noticeMap.get("createTime");
TtNotice ttNotice = new TtNotice();
ttNotice.setUserId(Long.valueOf(userId));
ttNotice.setTitle(title);
ttNotice.setContent(content);
ttNotice.setCreateTime(DateUtils.parseDate(createTime));
apiNoticeService.addNotice(ttNotice);
try {
//手动确认消费
channel.basicAck(tag, false);
} catch (IOException e) {
log.error(e.getMessage());
}
}
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.user.contract;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class PersonalRecordRequest {
@NotNull
@Min(value = 1,message = "最小值1")
private Integer page;
@NotNull
@Min(value = 1,message = "最小值1")
@Max(value = 50, message = "最大值20")
private Integer pageSize;
// 1:今日 2昨日 3最近7天
@NotNull(message = "type不能为空")
private Integer type;
// 查询的数据源 1:充值 2:消费 3:红包
@NotNull(message = "source不能为空")
private Integer source;
// 过滤选项 筛选条件 0:支出 1:收入
private Integer filteringOptions;
}

View File

@@ -0,0 +1,24 @@
package com.ruoyi.user.contract;
import lombok.Data;
import java.util.List;
@Data
public class PersonalRecordResponse {
private long total;
private List<RecordVO> rows;
@Data
public static class RecordVO {
private String amount;
private String finalAmount;
private String remark;
private String datetime;
private Integer source;
}
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.user.contract;
import lombok.Data;
@Data
public class QueryTransferRecordRequest {
// "src": 自己转增的 "dst":转增给自己的
private String kind;
private Integer pageNum;
private Integer pageSize;
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.user.contract;
import com.ruoyi.user.model.vo.ApiTransferRecordVO;
import lombok.Data;
import java.util.List;
@Data
public class QueryTransferRecordResponse {
private long total;
private List<ApiTransferRecordVO> rows;
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.user.contract;
import com.ruoyi.domain.other.TtVipLevel;
import lombok.Data;
import java.util.List;
@Data
public class QueryVipRewardResponse {
private String todayAmount;
private String todayReward;
private String yesterdayAmount;
private String yesterdayReward;
private List<TtVipLevel> vipLevels;
}

View File

@@ -0,0 +1,30 @@
package com.ruoyi.user.controller;
import com.ruoyi.admin.service.TtAdvertisementService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.domain.other.TtAdvertisement;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "广告查询")
@RestController
@RequestMapping("/api/advertisement")
public class ApiAdvertisementController {
private final TtAdvertisementService ttAdvertisementService;
public ApiAdvertisementController(TtAdvertisementService ttAdvertisementService) {
this.ttAdvertisementService = ttAdvertisementService;
}
@GetMapping(value = "/{id}")
public R<TtAdvertisement> getInfo(@PathVariable("id") Integer id) {
TtAdvertisement ttAdvertisement = ttAdvertisementService.getById(id);
// ttBanner.setPicture("");
return R.ok(ttAdvertisement);
}
}

View File

@@ -0,0 +1,58 @@
package com.ruoyi.user.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.PageDataInfo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.domain.other.TtAnnouncement;
import com.ruoyi.user.service.ApiAnnouncementService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Objects;
@Api(tags = "公告")
@RestController
@RequestMapping("/api/announcement")
public class ApiAnnouncementController extends BaseController {
@Autowired
private ApiAnnouncementService apiAnnouncementService;
@ApiOperation("获取公告列表")
@ApiResponse(code = 200, message = "read【阅读状态0未读 1已读")
@GetMapping("/list")
public TableDataInfo list() {
startPage();
Long userId = SecurityUtils.getUserId();
List<TtAnnouncement> announcementList = apiAnnouncementService.getAnnouncementList(userId);
return getDataTable(announcementList);
}
@ApiOperation("获取公告详情")
@GetMapping("/{announcementId}")
public AjaxResult getAnnouncementByAnnouncementId(@PathVariable Integer announcementId) {
Long userId = SecurityUtils.getUserId();
TtAnnouncement ttAnnouncement = apiAnnouncementService.getAnnouncementByAnnouncementId(announcementId, userId);
if (Objects.isNull(ttAnnouncement)) {
return AjaxResult.error("公告不存在");
}
return AjaxResult.success(ttAnnouncement);
}
@ApiOperation("获取未读公告数量")
@GetMapping("/countUnreadAnnouncement")
public AjaxResult countUnreadAnnouncement() {
Long userId = SecurityUtils.getUserId();
return AjaxResult.success(apiAnnouncementService.countUnreadAnnouncement(userId));
}
}

View File

@@ -0,0 +1,53 @@
package com.ruoyi.user.controller;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.service.TtUserBlendErcashService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.domain.dto.ChildDetailByBoss;
import com.ruoyi.domain.vo.ChildDetailByBossVO;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.service.ApiShoppingService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "用户收支记录")
@RestController
@RequestMapping("/api/blendErcash")
public class ApiBlendErcashController extends BaseController {
@Autowired
private TtUserBlendErcashService blendErcashService;
@Autowired
private ISysConfigService sysConfigService;
@Autowired
private ApiShoppingService apiShoppingService;
@Autowired
private TtUserService userService;
// 下级消费明细
@ApiOperation("粉丝消费明细")
@PostMapping("/childDetailByBoss")
// @Anonymous
public R<Page<ChildDetailByBossVO>> childDetailByBoss(@RequestBody @Validated ChildDetailByBoss param){
Long userId = getUserId();
if (ObjectUtil.isEmpty(userId)) return R.fail(401,"登录过期");
param.setBossId(Integer.valueOf(userId.toString()));
return blendErcashService.childDetailByBoss(param);
}
}

View File

@@ -0,0 +1,57 @@
package com.ruoyi.user.controller;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.annotation.UpdateUserCache;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.contract.QueryVipRewardResponse;
import com.ruoyi.user.service.ApiBonusService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "福利补贴")
@RestController
@RequestMapping("/api/bonus")
public class ApiBonusController extends BaseController {
private final ISysConfigService sysConfigService;
private final ApiBonusService apiBonusService;
private final TtUserService userService;
public ApiBonusController(ISysConfigService sysConfigService,
ApiBonusService apiBonusService,
TtUserService userService) {
this.sysConfigService = sysConfigService;
this.apiBonusService = apiBonusService;
this.userService = userService;
}
@ApiOperation("领取红包")
@UpdateUserCache
@GetMapping("/receiveRedPacket/{code}")
public R receiveRedPacket(@PathVariable("code") String code) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
TtUser ttUser = userService.getById(getUserId());
return apiBonusService.receiveRedPacket(code, ttUser);
}
@ApiOperation("查询vip流水奖励")
@GetMapping("/vipreward/list")
public R<QueryVipRewardResponse> vipRewardList() {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
TtUser ttUser = userService.getById(getUserId());
return apiBonusService.vipRewardList(ttUser);
}
}

View File

@@ -0,0 +1,177 @@
package com.ruoyi.user.controller;
import com.ruoyi.admin.mapper.TtUserMapper;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.NewUserInfo;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.UserData;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.ApiLoginBody;
import com.ruoyi.domain.other.ApiVerificationCodeLoginBody;
import com.ruoyi.domain.other.ApiVerificationCodeLoginOrRegisterBody;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.service.ApiLoginService;
import com.ruoyi.user.service.ApiUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 登录Controller
*/
@Api(tags = "客户端用户认证")
@RestController
@RequestMapping("/api")
public class ApiLoginController extends BaseController {
private final ISysConfigService sysConfigService;
private final ApiLoginService loginService;
private final TokenService tokenService;
@Autowired
private TtUserMapper userMapper;
public ApiLoginController(ISysConfigService sysConfigService,
ApiLoginService loginService,
TokenService tokenService) {
this.sysConfigService = sysConfigService;
this.loginService = loginService;
this.tokenService = tokenService;
}
@Autowired
private ApiUserService apiUserService;
@Autowired
private TtUserService userService;
@ApiOperation("客户端用户登录")
@Anonymous
@PostMapping("/login")
public AjaxResult login(@RequestBody @Validated ApiLoginBody loginBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return AjaxResult.error("网站维护中......");
}
try {
if (StringUtils.isNotNull(getLoginUser())) {
String userName = getUsername();
tokenService.delLoginUser(getToken());
AsyncManager.me().execute(AsyncFactory.recordLogininfor("api_" + userName, Constants.LOGOUT, "退出成功"));
}
} catch (Exception e) {
}
AjaxResult ajax = AjaxResult.success();
Pair<String, AjaxResult> pair = loginService.login(loginBody.getUsername(), loginBody.getPassword());
if (pair.getValue() != null) {
return pair.getValue();
}
ajax.put(Constants.TOKEN, pair.getKey());
return ajax;
}
@ApiOperation("客户端用户验证码登录")
@Anonymous
@PostMapping("/verificationCodeLogin")
public AjaxResult verificationCodeLogin(@RequestBody @Validated ApiVerificationCodeLoginBody apiVerificationCodeLoginBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return AjaxResult.error("网站维护中......");
}
return loginService.verificationCodeLogin(apiVerificationCodeLoginBody.getPhoneNumber(), apiVerificationCodeLoginBody.getCode());
}
@ApiOperation("客户端用户验证码登录或注册")
@Anonymous
@PostMapping("/verificationCodeLoginOrRegister")
public AjaxResult verificationCodeLoginOrRegister(@RequestBody @Validated ApiVerificationCodeLoginOrRegisterBody req) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return AjaxResult.error("网站维护中......");
}
return loginService.verificationCodeLoginOrRegister(req.getPhoneNumber(), req.getCode(), req.getParentInvitationCode());
}
@ApiOperation("获取用户信息")
@NewUserInfo
@GetMapping("/getInfo")
public R<UserData> getInfo() {
UserData userData = getLoginUser().getUserData();
TtUser ttUser = userService.getById(getUserId());
apiUserService.authenticationOk(ttUser);
if (!"1".equals(userData.getIsRealCheck())) {
userData.setRealName("");
}
userData.setAccountAmount(ttUser.getAccountAmount());
userData.setAccountCredits(ttUser.getAccountCredits());
userData.setDeliveryAddress(ttUser.getDeliveryAddress());
// 获取下级总人数
userData.setSubordinateNumber(apiUserService.getSubordinateNumber(getUserId()));
userData.setInvitationCode(ttUser.getInvitationCode());
return R.ok(userData);
}
@ApiOperation("获取用户余额信息")
@NewUserInfo
@GetMapping("/getAccountAmount")
public R<UserData> getAccountAmount() {
UserData userData = getLoginUser().getUserData();
TtUser ttUser = userService.getById(getUserId());
userData.setAccountAmount(ttUser.getAccountAmount());
userData.setAccountCredits(ttUser.getAccountCredits());
userData.setDeliveryAddress(ttUser.getDeliveryAddress());
userData.setInvitationCode(ttUser.getInvitationCode());
userData.setVipLevel(ttUser.getVipLevel());
userData.setPassword("");
return R.ok(userData);
}
@ApiOperation("获取用户信息")
@NewUserInfo
@GetMapping("/getParentInfo")
public R<TtUser> getParentInfo() {
TtUser ttUser = userService.getById(getUserId());
if (ttUser.getParentId() == null) {
return R.ok();
}
var parent = userService.getById(ttUser.getParentId());
if (parent == null) {
return R.ok();
}
TtUser r = new TtUser();
r.setUserId(parent.getUserId());
r.setAvatar(parent.getAvatar());
r.setNickName(parent.getNickName());
r.setInvitationCode(parent.getInvitationCode());
return R.ok(r);
}
@ApiOperation("客户端用户退出")
@PostMapping("/logout")
public R<Object> logout() {
if (StringUtils.isNotNull(getLoginUser())) {
String userName = getUsername();
tokenService.delLoginUser(getToken());
AsyncManager.me().execute(AsyncFactory.recordLogininfor("api_" + userName, Constants.LOGOUT, "退出成功"));
}
return R.ok("退出成功!");
}
}

View File

@@ -0,0 +1,66 @@
package com.ruoyi.user.controller;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.admin.service.TtMessageService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.PageDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.other.TtMessage;
import com.ruoyi.user.service.ApiMessageService;
import com.ruoyi.domain.vo.ApiMessageDataVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@Api(tags = "消息")
@RestController
@RequestMapping("/api/message")
public class ApiMessageController extends BaseController {
private final ApiMessageService apiMessageService;
public ApiMessageController(ApiMessageService apiMessageService) {
this.apiMessageService = apiMessageService;
}
@Autowired
private TtMessageService ttMessageService;
@GetMapping("/list")
public PageDataInfo<TtMessage> list() {
startPage();
QueryWrapper<TtMessage> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
List<TtMessage> list = ttMessageService.list(queryWrapper);
return getPageData(list);
}
@ApiOperation("获取消息列表")
@GetMapping("/getMessageList")
public PageDataInfo<ApiMessageDataVO> getMessageList(@RequestParam(required = false) Integer id){
startPage();
List<ApiMessageDataVO> list = apiMessageService.getMessageList(getUserId(), id);
return getPageData(list);
}
@ApiOperation("已读")
@GetMapping("/view")
public R<ApiMessageDataVO> view(Integer id){
ApiMessageDataVO data = apiMessageService.view(getUserId(), id);
return R.ok(data);
}
@ApiOperation("分批操作")
@PostMapping("/batchOperation")
public R<Boolean> batchOperation(@RequestParam Integer[] ids, @RequestParam("status") String status){
String msg = apiMessageService.batchOperation(getUserId(), Arrays.asList(ids), status);
return StringUtils.isEmpty(msg) ? R.ok(true, "操作成功!") : R.fail(false, msg);
}
}

View File

@@ -0,0 +1,71 @@
package com.ruoyi.user.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.PageDataInfo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.domain.other.TtNotice;
import com.ruoyi.thirdparty.common.mapper.ApiNoticeMapper;
import com.ruoyi.user.model.vo.ApiNoticeVO;
import com.ruoyi.user.service.ApiNoticeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
@Api(tags = "通知")
@RestController
@RequestMapping("/api/notice")
public class ApiNoticeController extends BaseController {
@Autowired
private ApiNoticeService apiNoticeService;
@Autowired
private ApiNoticeMapper apiNoticeMapper;
@ApiOperation("获取通知列表")
@ApiResponse(code = 200, message = "read【阅读状态0未读 1已读")
@GetMapping("/list")
public TableDataInfo list() {
startPage();
Long userId = SecurityUtils.getUserId();
List<ApiNoticeVO> apiNoticeVOList = apiNoticeService.getNoticeList(userId);
return getDataTable(apiNoticeVOList);
}
@ApiOperation("获取通知详情")
@GetMapping("/{noticeId}")
public AjaxResult getNoticeByNoticeId(@PathVariable Integer noticeId) {
Long userId = SecurityUtils.getUserId();
ApiNoticeVO apiNoticeVO = apiNoticeService.getNoticeByNoticeId(userId, noticeId);
if (Objects.isNull(apiNoticeVO)) {
return AjaxResult.error("通知不存在");
}
return AjaxResult.success(apiNoticeVO);
}
@ApiOperation("获取未读通知数量")
@GetMapping("/countUnreadNotice")
public AjaxResult countUnreadNotice() {
Long userId = SecurityUtils.getUserId();
return AjaxResult.success(apiNoticeService.countUnreadNotice(userId));
}
// 测试添加通知
/*@ApiOperation("获取通知列表")
@GetMapping("/add")
public void addNotice() {
TtNotice ttNotice = new TtNotice();
ttNotice.setUserId(1L);
ttNotice.setTitle("测试标题");
ttNotice.setContent("测试内容");
apiNoticeMapper.addNotice(ttNotice);
}*/
}

View File

@@ -0,0 +1,31 @@
package com.ruoyi.user.controller;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.admin.service.TtOrderService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "订单信息")
@RestController
@RequestMapping("/api/order")
public class ApiOrderController extends BaseController {
@Autowired
private TtOrderService ttOrderService;
@ApiOperation("充值明细")
@GetMapping("/list")
public R list(Integer page, Integer size) {
Long userId = getUserId();
if (ObjectUtil.isNull(userId)) return R.fail("登录过期。");
return ttOrderService.clientList(page,size,userId.intValue());
}
}

View File

@@ -0,0 +1,29 @@
package com.ruoyi.user.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.page.PageDataInfo;
import com.ruoyi.domain.vo.promotion.TtPromotionRecordVo;
import com.ruoyi.user.service.ApiPromotionRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/promotionRecord")
public class ApiPromotionRecordController extends BaseController {
@Autowired
private ApiPromotionRecordService apiPromotionRecordService;
@GetMapping("/getPromotionRecord")
public PageDataInfo<TtPromotionRecordVo> getPromotionRecord(){
startPage();
Long userId = getUserId();
List<TtPromotionRecordVo> list = apiPromotionRecordService.getPromotionRecord(userId.intValue());
return getPageData(list);
}
}

View File

@@ -0,0 +1,43 @@
package com.ruoyi.user.controller;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.service.ApiRegisterService;
import com.ruoyi.domain.other.ApiRegisterBody;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "用户注册")
@RestController
@RequestMapping("/api/register")
public class ApiRegisterController extends BaseController {
private final ISysConfigService sysConfigService;
private final ApiRegisterService apiRegisterService;
public ApiRegisterController(ISysConfigService sysConfigService,
ApiRegisterService apiRegisterService) {
this.sysConfigService = sysConfigService;
this.apiRegisterService = apiRegisterService;
}
@ApiOperation("用户注册")
@PostMapping
@Anonymous
public R<Object> register(@RequestBody @Validated ApiRegisterBody registerBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
String msg = apiRegisterService.register(registerBody);
return StringUtils.isEmpty(msg) ? R.ok("注册成功!") : R.fail(msg);
}
}

View File

@@ -0,0 +1,98 @@
package com.ruoyi.user.controller;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.UpdateUserCache;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.PageDataInfo;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.service.ApiShoppingService;
import com.ruoyi.domain.other.ApiShoppingBody;
import com.ruoyi.domain.vo.ApiShoppingDataVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Api(tags = "商城")
@RestController
@RequestMapping("/api/shopping")
public class ApiShoppingController extends BaseController {
private final ISysConfigService sysConfigService;
private final ApiShoppingService apiShoppingService;
private final TtUserService userService;
public ApiShoppingController(ISysConfigService sysConfigService,
ApiShoppingService apiShoppingService,
TtUserService userService) {
this.sysConfigService = sysConfigService;
this.apiShoppingService = apiShoppingService;
this.userService = userService;
}
@ApiOperation("获取不同类型的商品")
@Anonymous
@GetMapping("/getShoppingQuery")
public R<List<Map<String, String>>> getShoppingQuery(@RequestParam("value") String value){
List<SysDictData> dictCache = null;
if ("0".equals(value)) dictCache = DictUtils.getDictCache("ornaments_type_name");
if ("1".equals(value)) dictCache = DictUtils.getDictCache("ornaments_rarity_name");
if ("2".equals(value)) dictCache = DictUtils.getDictCache("ornaments_exterior_name");
if ("3".equals(value)) dictCache = DictUtils.getDictCache("ornaments_quality_name");
if (StringUtils.isNull(dictCache)) return R.fail("数据异常!!");
List<Map<String, String>> list = dictCache.stream().map(sysDictData -> {
Map<String, String> map = new HashMap<>();
map.put(sysDictData.getDictLabel(), sysDictData.getDictValue());
return map;
}).collect(Collectors.toList());
return R.ok(list);
}
@ApiOperation("商品列表")
@GetMapping("/list")
@Anonymous
public PageDataInfo<ApiShoppingDataVO> list(@Validated ApiShoppingBody shoppingBody) {
startPage();
List<ApiShoppingDataVO> list = apiShoppingService.list(shoppingBody);
return getPageData(list);
}
@ApiOperation("商品兑换")
@PostMapping("/exchange")
@UpdateUserCache
public R exchange(Long ornamentsId) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
String shoppingMaintenance = sysConfigService.selectConfigByKey("shoppingMaintenance");
if ("1".equals(shoppingMaintenance)) {
return R.fail("商城功能正在维护中......");
}
TtUser ttUser = userService.getById(getUserId());
return apiShoppingService.exchange(ttUser, ornamentsId);
}
@ApiOperation("积分转换")
@UpdateUserCache
@PostMapping("/integratingConversion")
public R<Boolean> integratingConversion(BigDecimal credits) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) return R.fail("网站维护中......");
TtUser ttUser = userService.getById(getUserId());
String msg = apiShoppingService.integratingConversion(ttUser, credits);
return StringUtils.isEmpty(msg) ? R.ok(true, "积分转换成功!") : R.fail(msg);
}
}

View File

@@ -0,0 +1,57 @@
package com.ruoyi.user.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.user.model.TtTaskCenterUser;
import com.ruoyi.user.model.vo.ApiTaskCenterVO;
import com.ruoyi.user.service.ApiTaskCenterService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Objects;
@Api(tags = "任务中心")
@RestController
@RequestMapping("/api/taskCenter")
public class ApiTaskCenterController extends BaseController {
@Autowired
private ApiTaskCenterService apiTaskCenterService;
@ApiOperation("查询任务列表")
@ApiResponse(code = 200, message = "status【领取条件0不满足 1满足" +
"<br>claimed【是否已领取1已领取")
@PreAuthorize("isAuthenticated()")
@GetMapping("/list")
public TableDataInfo list() {
startPage();
Long userId = getUserId();
List<ApiTaskCenterVO> list = apiTaskCenterService.selectApiTaskCenterVOList(userId.intValue());
return getDataTable(list);
}
@ApiOperation("领取任务奖励")
@PreAuthorize("isAuthenticated()")
@GetMapping("/getReward/{taskId}")
public AjaxResult getReward(@PathVariable("taskId") Integer taskId) {
Long userId = getUserId();
// 判断是否具备领取条件
TtTaskCenterUser ttTaskCenterUser = apiTaskCenterService.selectTtTaskCenterUserByTaskIdAndUserId(taskId, userId.intValue());
if (Objects.isNull(ttTaskCenterUser)) {
return AjaxResult.error("不具备领取条件");
}
if ("1".equals(ttTaskCenterUser.getClaimed())) {
return AjaxResult.error("已领取过");
}
return apiTaskCenterService.getReward(taskId, userId.intValue());
}
}

View File

@@ -0,0 +1,561 @@
package com.ruoyi.user.controller;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.mapper.TtPromotionUpdateMapper;
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
import com.ruoyi.admin.mapper.TtUserMapper;
import com.ruoyi.admin.service.TtDeliveryRecordService;
import com.ruoyi.admin.service.TtOrderService;
import com.ruoyi.admin.service.TtRechargeRankingRewardService;
import com.ruoyi.admin.service.TtUserAmountRecordsService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.MoneyUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
import com.ruoyi.domain.common.constant.TtAccountRecordType;
import com.ruoyi.domain.dto.sys.TeamUsersParam;
import com.ruoyi.domain.dto.userRecord.AmountRecordsDetailCondition;
import com.ruoyi.domain.dto.userRecord.DeliveryRecordsConfition;
import com.ruoyi.domain.dto.userRecord.OrderCondition;
import com.ruoyi.domain.entity.TtUserBlendErcash;
import com.ruoyi.domain.other.TtRechargeRankingReward;
import com.ruoyi.domain.vo.TeamDetailVO;
import com.ruoyi.domain.vo.TtUserAccountRecordsRankVO;
import com.ruoyi.domain.vo.TtUserAmountRecords.UserAmountDetailVO;
import com.ruoyi.domain.vo.UserBERankVO;
import com.ruoyi.domain.vo.delivery.DeliveryRecordVO;
import com.ruoyi.domain.vo.order.TtOrderVO;
import com.ruoyi.domain.vo.sys.SimpleTtUserVO;
import com.ruoyi.user.contract.PersonalRecordRequest;
import com.ruoyi.user.contract.PersonalRecordResponse;
import com.ruoyi.user.mapper.ApiUserBlendErcashMapper;
import com.ruoyi.user.model.vo.ApiRechargeRankingVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.ruoyi.domain.common.constant.TtAccountRecordSource.RECEIVE_RED_PACKET;
import static com.ruoyi.domain.common.constant.TtAccountRecordSource.RECHARGE;
@Api(tags = "用户充值记录")
@RestController
@RequestMapping("/api/userAmountRecords")
@Slf4j
public class ApiUserAmountRecordsController extends BaseController {
@Autowired
private TtUserAmountRecordsService ttUserAmountRecordsService;
@Autowired
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
@Autowired
private TtUserAmountRecordsService userAmountRecordsService;
@Autowired
private TtUserService userService;
@Autowired
private TtUserMapper userMapper;
@Autowired
private TtOrderService orderService;
@Autowired
private TtDeliveryRecordService ttDeliveryRecordService;
@Autowired
private TtOrderService ttOrderService;
@Autowired
private TtPromotionUpdateMapper ttPromotionUpdateMapper;
@Autowired
private ApiUserBlendErcashMapper apiUserBlendErcashMapper;
@Autowired
private TtRechargeRankingRewardService ttRechargeRankingRewardService;
/**
* 充值网流水排行榜
*
* @param type 1今天 2昨天 3近一周
*/
@ApiOperation("充值网流水排行榜")
@Anonymous
@GetMapping("/amountRank/{type}/{page}/{size}")
public Page<TtUserAccountRecordsRankVO> amountRank(@PathVariable("type") Integer type,
@PathVariable("page") Integer page,
@PathVariable("size") Integer size) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
Timestamp end = null;
Timestamp begin = null;
if (type.equals(1)) {
begin = new Timestamp(c.getTimeInMillis());
end = new Timestamp(System.currentTimeMillis());
} else if (type.equals(2)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.DAY_OF_MONTH, -1);
begin = new Timestamp(c.getTimeInMillis());
} else if (type.equals(3)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.WEEK_OF_MONTH, -1);
begin = new Timestamp(c.getTimeInMillis());
}
return ttUserAmountRecordsService.rank(begin, end, page, size);
}
/**
* 充值网推广奖励明细
*/
@ApiOperation("充值网推广奖励明细")
@GetMapping("/pWelfareRecords/{page}/{size}")
public R pWelfareRecords(@PathVariable("page") Integer page,
@PathVariable("size") Integer size) {
if (page < 1) {
return R.fail("page > 0");
}
if (size > 21) {
return R.fail("size <= 20 !!!");
}
Long userId = getUserId();
return ttUserAmountRecordsService.pWelfareRecords(userId.intValue(), page, size);
}
/**
* 综合排行榜
*/
@ApiOperation("流水排行榜")
@PostMapping("/blendErcashRank")
public R<List<UserBERankVO>> blendErcashRank(@RequestBody RankParam param) {
param.setPage(1);
param.setSize(10);
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
Timestamp end = null;
Timestamp begin = null;
if (param.getType().equals(1)) {
begin = new Timestamp(c.getTimeInMillis());
end = new Timestamp(System.currentTimeMillis());
} else if (param.getType().equals(2)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.DAY_OF_MONTH, -1);
begin = new Timestamp(c.getTimeInMillis());
} else if (param.getType().equals(3)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.WEEK_OF_MONTH, -1);
begin = new Timestamp(c.getTimeInMillis());
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String beginT = dateFormat.format(begin);
String endT = dateFormat.format(end);
if (StringUtils.isBlank(beginT) || StringUtils.isBlank(beginT)) {
beginT = null;
endT = null;
}
List<Integer> source = new ArrayList<>(TtAccountRecordSource.getGameConsumeCodes());
Integer limit = (param.getPage() - 1) * param.getSize();
List<UserBERankVO> rank = ttUserBlendErcashMapper.rank(
source,
beginT,
endT,
limit,
param.getSize());
for (int i = 1; i <= rank.size(); i++) {
var item = rank.get(i - 1);
item.setBeRank(i);
item.setValue(MoneyUtil.toStr(item.getAmount().abs()));
}
return R.ok(rank);
}
@ApiOperation("获取个人综合收支明细")
@PostMapping("/userAccountDetail")
public R<List<UserAmountDetailVO>> userAccountDetail(@RequestBody @Validated AmountRecordsDetailCondition param) {
param.setUserId(null);
param.setUserId(getUserId().intValue());
List<UserAmountDetailVO> list = userAmountRecordsService.userAccountDetail(param);
return R.ok(list);
}
@ApiOperation("获取个人记录")
@PostMapping("/personalRecord")
public R<PersonalRecordResponse> queryPersonalRecord(@RequestBody @Validated PersonalRecordRequest request) {
final int TYPE_TODAY = 1;
final int TYPE_YESTERDAY = 2;
final int TYPE_LAST_7_DAYS = 3;
final int SOURCE_RECHARGE = 1;
final int SOURCE_CONSUME = 2;
final int SOURCE_RED_PACKET = 3;
final int Filtering_Options_OutPut = 0;
final int Filtering_Options_Input = 1;
if (request.getType() != TYPE_TODAY && request.getType() != TYPE_YESTERDAY && request.getType() != TYPE_LAST_7_DAYS) {
return R.fail("参数错误: type 无效");
}
if (request.getSource() != SOURCE_RECHARGE && request.getSource() != SOURCE_CONSUME && request.getSource() != SOURCE_RED_PACKET) {
return R.fail("参数错误: source 无效");
}
Integer uid = getUserId().intValue();
Page<TtUserBlendErcash> page = new Page<>(request.getPage(), request.getPageSize());
// page.setOptimizeCountSql(false);
LambdaQueryWrapper<TtUserBlendErcash> wrapper = Wrappers.lambdaQuery();
wrapper.eq(TtUserBlendErcash::getUserId, uid);
// 1:今日 2昨日 3最近7天
LocalDate today = LocalDate.now();
switch (request.getType()) {
case TYPE_TODAY:
LocalDateTime startOfToday = today.atStartOfDay();
LocalDateTime endOfToday = today.plusDays(1).atStartOfDay().minusNanos(1);
wrapper.between(TtUserBlendErcash::getCreateTime, startOfToday, endOfToday);
break;
case TYPE_YESTERDAY:
LocalDateTime startOfYesterday = today.minusDays(1).atStartOfDay();
LocalDateTime endOfYesterday = today.atStartOfDay().minusNanos(1);
wrapper.between(TtUserBlendErcash::getCreateTime, startOfYesterday, endOfYesterday);
break;
case TYPE_LAST_7_DAYS:
LocalDateTime startOf7Days = today.minusDays(6).atStartOfDay();
wrapper.ge(TtUserBlendErcash::getCreateTime, startOf7Days);
break;
default:
// 理论上不会进入,因为上面已经校验过
break;
}
// 查询的数据源 1:充值 2:全部/支出/收入 3:红包
switch (request.getSource()) {
case SOURCE_RECHARGE:
wrapper.eq(TtUserBlendErcash::getSource, RECHARGE.getCode());
break;
case SOURCE_CONSUME:
//wrapper.eq(TtUserBlendErcash::getType, TtAccountRecordType.OUTPUT);
if (request.getFilteringOptions() != null) {
if (request.getFilteringOptions() == Filtering_Options_OutPut) {
wrapper.eq(TtUserBlendErcash::getType, TtAccountRecordType.OUTPUT.getCode());
} else if (request.getFilteringOptions() == Filtering_Options_Input) {
wrapper.eq(TtUserBlendErcash::getType, TtAccountRecordType.INPUT.getCode());
}
}
break;
case SOURCE_RED_PACKET:
wrapper.eq(TtUserBlendErcash::getSource, RECEIVE_RED_PACKET.getCode());
break;
default:
break;
}
wrapper.orderByDesc(TtUserBlendErcash::getCreateTime);
IPage<TtUserBlendErcash> listPage = ttUserBlendErcashMapper.selectPage(page, wrapper);
List<TtUserBlendErcash> userList = listPage.getRecords();
var formatter = DateTimeFormatter.ofPattern("MM-dd HH:mm:ss");
var r = userList.stream().map(v -> {
PersonalRecordResponse.RecordVO item = new PersonalRecordResponse.RecordVO();
item.setAmount(MoneyUtil.toStr(v.getAmount()));
item.setFinalAmount(MoneyUtil.toStr(v.getFinalAmount()));
item.setRemark(v.getRemark());
item.setDatetime(v.getCreateTime().toLocalDateTime().format(formatter));
item.setSource(v.getSource());
return item;
}).collect(Collectors.toList());
PersonalRecordResponse response = new PersonalRecordResponse();
response.setRows(r);
response.setTotal(listPage.getTotal());
return R.ok(response);
}
@ApiOperation("获取个人提货记录")
@PostMapping("/deliveryRecords")
public R deliveryRecords(@RequestBody @Validated DeliveryRecordsConfition param) {
param.setUIdList(null);
int userId = getUserId().intValue();
if (ObjectUtil.isNull(userId)) return R.fail(401, "登录过期请重新登录。");
param.setUIdList(Arrays.asList(userId));
List<DeliveryRecordVO> list = ttDeliveryRecordService.byCondition(param);
return R.ok(list);
}
@ApiOperation("获取团队用户列表")
// @Anonymous
@PostMapping("/teamUsers")
public R<List<SimpleTtUserVO>> teamUsers(@RequestBody @Validated TeamUsersParam param) {
param.setBossIds(null);
param.setEmployeeIds(null);
param.setBossIds(Arrays.asList(getUserId().intValue()));
if (ObjectUtil.isNull(param.getOrderByFie())) param.setOrderByFie(1);
// 查询所有下级id
List<Integer> allEmployeesId = userMapper.allEmployeesByParents(param.getBossIds());
if (allEmployeesId.isEmpty()) {
return R.ok(new ArrayList<>());
}
// 解析时间
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date beginTime = null;
try {
beginTime = dateFormat.parse(param.getBeginTime());
} catch (ParseException e) {
return R.fail("日期解析异常,检查日期格式是否正确。");
}
// main
if (param.getOrderByFie().equals(1)) {
// 查询下级的最近一个绑定时间
List<TeamDetailVO> mit = ttPromotionUpdateMapper.latelyUpdate(allEmployeesId);
if (mit.size() < allEmployeesId.size()) log.warn("下级已绑定上级,但未写入更新日志,请及时检查!!!");
// 如果最近绑定时间大于本次查询的起始时间,以最近绑定时间为准
List<Integer> empIds1 = new ArrayList<>();
List<TeamDetailVO> empIds2 = new ArrayList<>();
for (TeamDetailVO item : mit) {
Timestamp latelyTime = item.getBeginTime();
if (latelyTime.compareTo(new Timestamp(beginTime.getTime())) > 0) {
empIds2.add(item);
} else {
empIds1.add(item.getEmployeeId());
}
}
List<SimpleTtUserVO> batchRechargeTotal1 = new ArrayList<>();
if (!empIds1.isEmpty()) {
// 主表充值统计
batchRechargeTotal1 = orderService.batchRechargeTotal(
empIds1,
param.getBeginTime(),
param.getEndTime(),
param.getOrderType(),
param.getPage(),
param.getSize());
System.err.println(batchRechargeTotal1);
}
List<SimpleTtUserVO> batchRechargeTotal2 = new ArrayList<>();
if (!empIds2.isEmpty()) {
for (TeamDetailVO vo : empIds2) {
String beginT = dateFormat.format(vo.getBeginTime());
List<SimpleTtUserVO> data = orderService.batchRechargeTotal(
Arrays.asList(vo.getEmployeeId()),
beginT,
param.getEndTime(),
param.getOrderType(),
param.getPage(),
param.getSize());
batchRechargeTotal2.addAll(data);
}
}
batchRechargeTotal1.addAll(batchRechargeTotal2);
return R.ok(batchRechargeTotal1);
} else if (param.getOrderByFie().equals(2) || param.getOrderByFie().equals(3) || param.getOrderByFie().equals(4)) {
if (StringUtils.isBlank(param.getBeginTime())) {
param.setBeginTime(null);
}
if (StringUtils.isBlank(param.getEndTime())) {
param.setEndTime(null);
}
if (ObjectUtil.isNull(param.getOrderType())) {
param.setOrderType(1);
}
// 查询下级的最近一个绑定时间
List<TeamDetailVO> mit = ttPromotionUpdateMapper.latelyUpdate(allEmployeesId);
if (mit.size() < allEmployeesId.size()) {
log.warn("下级已绑定上级,但未写入更新日志,请及时检查!!!");
}
// 如果最近绑定时间大于本次查询的起始时间,以最近绑定时间为准
List<Integer> empIds1 = new ArrayList<>();
List<TeamDetailVO> empIds2 = new ArrayList<>();
for (TeamDetailVO item : mit) {
Timestamp latelyTime = item.getBeginTime();
if (latelyTime.compareTo(new Timestamp(beginTime.getTime())) > 0) {
empIds2.add(item);
} else {
empIds1.add(item.getEmployeeId());
}
}
List<SimpleTtUserVO> batchConsumeTotal1 = new ArrayList<>();
if (!empIds1.isEmpty()) {
// 主表消费统计
batchConsumeTotal1 = ttUserBlendErcashMapper.batchConsumeTotal(
empIds1,
param.getBeginTime(),
param.getEndTime(),
param.getOrderByFie(),
param.getOrderType(),
(param.getPage() - 1) * param.getSize(),
param.getSize());
}
List<SimpleTtUserVO> batchConsumeTotal2 = new ArrayList<>();
if (!empIds2.isEmpty()) {
for (TeamDetailVO vo : empIds2) {
String beginT = dateFormat.format(vo.getBeginTime());
List<SimpleTtUserVO> data = ttUserBlendErcashMapper.batchConsumeTotal(
Arrays.asList(vo.getEmployeeId()),
beginT,
param.getEndTime(),
param.getOrderByFie(),
param.getOrderType(),
(param.getPage() - 1) * param.getSize(),
param.getSize()
);
batchConsumeTotal2.addAll(data);
}
}
batchConsumeTotal1.addAll(batchConsumeTotal2);
return R.ok(batchConsumeTotal1);
} else {
return R.fail("非法的排序字段");
}
// return userService.teamUsers(param);
}
@ApiOperation("获取个人充值明细")
@PostMapping("/rechargeRecords")
public R rechargeRecords(@RequestBody @Validated OrderCondition param) {
Long userId = getUserId();
if (ObjectUtil.isNull(userId)) return R.fail(401, "登录过期,请重新登录。");
param.setUserIdList(Arrays.asList(userId.intValue()));
List<TtOrderVO> list = ttOrderService.byCondition(param);
return R.ok(list);
}
@Deprecated
@ApiOperation("获取消费排行榜")
@Anonymous
@GetMapping("/rechargeRanking")
public AjaxResult getRechargeRanking() {
// 创建日期格式化对象,指定日期格式
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
// 获取今天日期
Date today = new Date();
String formattedTodayDate = formatter.format(today);
List<ApiRechargeRankingVO> todayFightRanking = apiUserBlendErcashMapper.getRechargeRankingByDate(formattedTodayDate);
// 获取昨天日期
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
Date yesterday = cal.getTime();
String formattedYesterdayDate = formatter.format(yesterday);
List<ApiRechargeRankingVO> yesterdayFightRanking = apiUserBlendErcashMapper.getRechargeRankingByDate(formattedYesterdayDate);
Map<String, List<ApiRechargeRankingVO>> map = new HashMap<>();
map.put("todayFightRanking", todayFightRanking);
map.put("yesterdayFightRanking", yesterdayFightRanking);
return AjaxResult.success(map);
}
@ApiOperation("消费排行榜奖励说明")
@GetMapping("/rechargeRankingRewardsIntroduction")
public AjaxResult rechargeRankingRewardsIntroduction() {
List<TtRechargeRankingReward> ttRechargeRankingRewards = ttRechargeRankingRewardService.selectTtRechargeRankingRewardList(null);
ttRechargeRankingRewards.forEach(r -> r.setRewardStr(MoneyUtil.toStr(r.getReward())));
return success(ttRechargeRankingRewards);
}
public R checkLogin() {
Long userId;
try {
userId = getUserId();
if (ObjectUtil.isEmpty(userId)) AjaxResult.error(401, "登录过期,请重新登录。");
return R.ok(userId);
} catch (Exception e) {
return R.fail(401, "登录过期,请重新登录。");
}
}
@NoArgsConstructor
@AllArgsConstructor
@Data
public static class RankParam {
@ApiModelProperty("类型1今天 2昨天 3近七天")
@NotEmpty(message = "时间区间不能为空")
private Integer type;
@Min(value = 1, message = "最小1")
private Integer page;
@Min(value = 1, message = "最小1")
private Integer size;
}
}

View File

@@ -0,0 +1,397 @@
package com.ruoyi.user.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.admin.mapper.TtOrderMapper;
import com.ruoyi.admin.service.TtDeliveryRecordService;
import com.ruoyi.admin.service.TtUserAmountRecordsService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.admin.service.TtVipLevelService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.UpdateUserCache;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.PageDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.entity.TtOrder;
import com.ruoyi.domain.entity.delivery.TtDeliveryRecord;
import com.ruoyi.domain.entity.recorde.TtUserAmountRecords;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.ApiForgetPasswordBody;
import com.ruoyi.domain.other.ApiUpdateUserDetailsBody;
import com.ruoyi.domain.other.RealNameAuthenticationBody;
import com.ruoyi.domain.other.TtDeliveryRecordBody;
import com.ruoyi.domain.other.TtUserAmountRecordsBody;
import com.ruoyi.domain.other.TtVipLevel;
import com.ruoyi.domain.vo.TtDeliveryRecordDataVO;
import com.ruoyi.domain.vo.TtUserPackSackDataVO;
import com.ruoyi.domain.vo.TtUserVipLevelVo;
import com.ruoyi.domain.vo.user.TtUseChildInfoVo;
import com.ruoyi.domain.vo.user.TtUserInfoVo;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.thirdparty.baidu.service.BaiduService;
import com.ruoyi.user.service.ApiUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;
@Api(tags = "用户管理")
@RestController
@RequestMapping("/api/user")
@Slf4j
public class ApiUserController extends BaseController {
private final ISysConfigService sysConfigService;
private final TtUserService userService;
private final ApiUserService apiUserService;
private final TtOrderMapper ttOrderMapper;
private final TtDeliveryRecordService ttDeliveryRecordService;
private final TtUserAmountRecordsService userAmountRecordsService;
private final TtDeliveryRecordService deliveryRecordService;
public ApiUserController(ISysConfigService sysConfigService,
TtUserService userService,
TtDeliveryRecordService ttDeliveryRecordService,
ApiUserService apiUserService, TtOrderMapper ttOrderMapper,
TtUserAmountRecordsService userAmountRecordsService,
TtDeliveryRecordService deliveryRecordService) {
this.sysConfigService = sysConfigService;
this.userService = userService;
this.ttDeliveryRecordService = ttDeliveryRecordService;
this.apiUserService = apiUserService;
this.ttOrderMapper = ttOrderMapper;
this.userAmountRecordsService = userAmountRecordsService;
this.deliveryRecordService = deliveryRecordService;
}
@Autowired
private TtVipLevelService vipLevelService;
@Autowired
private BaiduService baiduService;
@ApiOperation("头像上传")
@UpdateUserCache
@PostMapping(value = "/profilePictureUpload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Object> profilePictureUpload(@RequestPart("file") MultipartFile file) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
if (StringUtils.isNull(file)) {
return R.fail("未选择头像文件!");
}
TtUser ttUser = userService.getById(getUserId());
String msg = apiUserService.profilePictureUpload(ttUser, file);
return StringUtils.isEmpty(msg) ? R.ok("头像上传成功!") : R.fail(msg);
}
@ApiOperation("更新个人信息")
@UpdateUserCache
@PostMapping("/updateUserDetails")
public R<Object> updateUserDetails(@RequestBody ApiUpdateUserDetailsBody updateUserDetailsBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
TtUser ttUser = userService.getById(getUserId());
String msg = apiUserService.updateUserDetails(ttUser, updateUserDetailsBody);
return StringUtils.isEmpty(msg) ? R.ok("个人信息更新成功!") : R.fail(msg);
}
@ApiOperation("更新收货地址")
@UpdateUserCache
@PostMapping("/updateDeliveryAddress")
public R<Object> updateDeliveryAddress(@RequestBody ApiUpdateUserDetailsBody updateUserDetailsBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
TtUser ttUser = userService.getById(getUserId());
String msg = apiUserService.updateUserDetails(ttUser, updateUserDetailsBody);
return StringUtils.isEmpty(msg) ? R.ok("收货地址更新成功!") : R.fail(msg);
}
@ApiOperation("绑定推广人")
@UpdateUserCache
@PostMapping("/bindBoss")
public R bindBoss(@RequestBody ApiUpdateUserDetailsBody updateUserDetailsBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
TtUser ttUser = userService.getById(getUserId());
return apiUserService.bindBoss(ttUser, updateUserDetailsBody);
}
@ApiOperation("修改密码")
// @UpdateUserCache
@PostMapping("/changePW")
public R<Object> changePW(@RequestBody @Validated ApiUpdateUserDetailsBody updateUserDetailsBody, HttpServletRequest request) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
TtUser ttUser = userService.getById(getUserId());
String token = CacheConstants.LOGIN_TOKEN_KEY + getToken();
return apiUserService.changePW(ttUser, updateUserDetailsBody, token);
}
@ApiOperation("忘记密码")
@Anonymous
@PostMapping("/forgetPassword")
public R<Boolean> forgetPassword(@RequestBody ApiForgetPasswordBody apiForgetPasswordBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
String msg = apiUserService.forgetPassword(apiForgetPasswordBody);
return StringUtils.isEmpty(msg) ? R.ok(true, "密码修改成功成功!") : R.fail(msg);
}
@ApiOperation("实名认证")
@RepeatSubmit(interval = 60000, message = "操作过于频繁请60秒后重试")
@UpdateUserCache
@PostMapping("/realNameAuthentication")
public R<String> realNameAuthentication(@RequestBody RealNameAuthenticationBody realNameAuthenticationBody) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
TtUser ttUser = userService.getById(getUserId());
String msg = apiUserService.realNameAuthentication2(ttUser, realNameAuthenticationBody.getRealName(),
realNameAuthenticationBody.getIdNum(), ttUser.getPhoneNumber());
return msg.startsWith("alipays") ? R.ok(msg) : R.fail(msg);
}
@ApiOperation("认证成功")
@UpdateUserCache
@GetMapping("/authenticationOk")
public R<Boolean> authenticationOk() {
TtUser ttUser = userService.getById(getUserId());
String msg = apiUserService.authenticationOk(ttUser);
return StringUtils.isEmpty(msg) ? R.ok(true, "认证成功!") : R.fail(false, msg);
}
@ApiOperation("获取下级人数")
// @UpdateUserCache
@GetMapping("/rechargeCount")
public R<Integer> rechargeCount() {
TtUser ttUser = userService.getById(getUserId());
return R.ok((int) userService.count(new QueryWrapper<TtUser>().eq("parent_id", ttUser.getUserId())));
}
@ApiOperation("获取下级提取数")
@UpdateUserCache
@GetMapping("/getExtracts")
public R<BigDecimal> getExtracts() {
TtUser ttUser = userService.getById(getUserId());
List<TtUser> ttUsers = userService.list(new QueryWrapper<TtUser>().eq("parent_id", ttUser.getUserId()));
// 判断是否有下级用户
if (ttUsers == null || ttUsers.size() == 0) {
return R.ok(new BigDecimal(0));
}
List<Integer> collect = ttUsers.stream().map(i -> i.getUserId()).collect(Collectors.toList());
List<TtDeliveryRecord> ttDeliveryRecords = ttDeliveryRecordService.list(new QueryWrapper<TtDeliveryRecord>().in("user_id", collect).eq("status", "10"));
BigDecimal bigDecimal = new BigDecimal(0);
ttDeliveryRecords.forEach(o -> {
bigDecimal.add(o.getOrnamentsPrice());
});
return R.ok(bigDecimal);
}
@ApiOperation("获取下级充值总金额")
// @UpdateUserCache
@GetMapping("/getOrdersAmounts")
public R<BigDecimal> getOrdersAmounts() {
TtUser ttUser = userService.getById(getUserId());
List<TtUser> ttUsers = userService.list(new QueryWrapper<TtUser>().eq("parent_id", ttUser.getUserId()));
// 判断是否有下级用户
if (ttUsers == null || ttUsers.size() == 0) {
return R.ok(new BigDecimal(0));
}
List<Integer> collect = ttUsers.stream().map(i -> i.getUserId()).collect(Collectors.toList());
List<TtOrder> ttOrders = ttOrderMapper.selectList(new QueryWrapper<TtOrder>().in("user_id", collect).and(k -> k.eq("status", "3").or().eq("status", "4")));
BigDecimal bigDecimal = new BigDecimal(0);
ttOrders.forEach(o -> {
bigDecimal.add(o.getGoodsPrice());
});
return R.ok(bigDecimal);
}
@ApiOperation("获取下级流水详情")
@GetMapping("/getLsjlList")
public PageDataInfo<TtUserAmountRecords> getLsjlList(TtUserAmountRecordsBody ttUserAmountRecordsBody) {
startPage();
TtUser ttUser = userService.getById(getUserId());
List<TtUser> ttUsers = userService.list(new QueryWrapper<TtUser>().eq("parent_id", ttUser.getUserId()));
// 判断是否有下级用户
if (ttUsers == null || ttUsers.size() == 0) {
return getPageData(new ArrayList<TtUserAmountRecords>());
}
List<Integer> userIds = ttUsers.stream().map(i -> i.getUserId()).collect(Collectors.toList());
QueryWrapper<TtUserAmountRecords> ttUserAmountRecordsQueryWrapper = new QueryWrapper<>();
// 时间段筛选
if (ttUserAmountRecordsBody.getStartTime() != null) {
ttUserAmountRecordsQueryWrapper.ge("create_time", ttUserAmountRecordsBody.getStartTime());
}
if (ttUserAmountRecordsBody.getEndTime() != null) {
ttUserAmountRecordsQueryWrapper.lt("create_time", ttUserAmountRecordsBody.getEndTime());
}
if (ttUserAmountRecordsBody.getUserId() != null) {
ttUserAmountRecordsQueryWrapper.eq("user_id", ttUserAmountRecordsBody.getUserId());
}
List<TtUserAmountRecords> list = userAmountRecordsService.list(ttUserAmountRecordsQueryWrapper.in("user_id", userIds).orderByDesc("create_time"));
return getPageData(list);
}
@ApiOperation("获取出货记录")
@GetMapping("/getDeliveryRecordList")
public PageDataInfo<TtDeliveryRecordDataVO> getDeliveryRecordList(TtDeliveryRecordBody deliveryRecordBody) {
startPage();
TtUser ttUser = userService.getById(getUserId());
deliveryRecordBody.setUserId(ttUser.getUserId());
List<TtDeliveryRecordDataVO> list = deliveryRecordService.getDeliveryRecordByUserList(deliveryRecordBody);
return getPageData(list);
}
/**
* 每日出货排行榜
*
* @param type 1今天 2昨天 3近一周
*/
@ApiOperation("每日出货排行榜")
@GetMapping("/propRankOfDay/{type}/{number}")
public R propRankOfDay(@PathVariable("type") Integer type,
@PathVariable(value = "number", required = false) Integer number) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
Timestamp end = null;
Timestamp begin = null;
if (type.equals(1)) {
begin = new Timestamp(c.getTimeInMillis());
end = new Timestamp(System.currentTimeMillis());
} else if (type.equals(2)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.DAY_OF_MONTH, -1);
begin = new Timestamp(c.getTimeInMillis());
} else if (type.equals(3)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.WEEK_OF_MONTH, -1);
begin = new Timestamp(c.getTimeInMillis());
}
number = 10;
List<TtUserPackSackDataVO> list = userService.propRankOfDay(begin, end, number);
// return getPageData(list);
return R.ok(list);
}
@ApiOperation("VIP等级说明")
@GetMapping("/vipLevelIntroduction")
public AjaxResult vipLevelIntroduction() {
List<TtVipLevel> list = vipLevelService.list();
return success(list);
}
@ApiOperation("VIP等级进度")
@GetMapping("/userVipLeverRate")
public AjaxResult userVipLeverRate() {
TtUserVipLevelVo vipLevel = userService.userVipLeverRate(getUserId().intValue());
return success(vipLevel);
}
@ApiOperation("用户信息包含下级信息")
@GetMapping("/userInfo")
public AjaxResult userInfo() {
TtUserInfoVo userInfo = userService.userInfo(getUserId().intValue());
return success(userInfo);
}
@ApiOperation("用户信息包含下级用户信息")
@GetMapping("/userChildInfo")
public AjaxResult userChildInfo() {
List<TtUseChildInfoVo> userInfo = userService.userChildInfos(getUserId().intValue());
return success(userInfo);
}
@ApiOperation("用户领取VIP等级")
@UpdateUserCache
@GetMapping("/userVipLevelRechargeThreshold")
public AjaxResult userVipLevelRechargeThreshold(@RequestParam(required = true) Integer vipLevel) {
return userService.userVipLevelRechargeThreshold(getUserId().intValue(), vipLevel);
}
@ApiOperation("用户已经领取VIP等级")
@GetMapping("/userHasVipLevelRechargeThreshold")
public AjaxResult userHasVipLevelRechargeThreshold() {
return userService.userHasVipLevelRechargeThreshold(getUserId().intValue());
}
@ApiOperation("用户领取充值门槛达标奖励")
@UpdateUserCache
@GetMapping("/userRechargeBonus")
public AjaxResult userRechargeBonus(@RequestParam(required = true) Integer recharge, @RequestParam(required = true) Double bonus) {
return userService.userRechargeBonus(getUserId().intValue(), recharge, bonus);
}
@ApiOperation("用户已领取充值门槛达标奖励")
@GetMapping("/userHasRechargeBonus")
public AjaxResult userHasRechargeBonus() {
return userService.userHasRechargeBonus(getUserId().intValue());
}
@ApiOperation("用户积分兑换金币")
@UpdateUserCache
@GetMapping("/userCreditsToAmount")
public AjaxResult userCreditsToAmount(@RequestParam(required = true) BigDecimal credits) {
return userService.userCreditsToAmount(getUserId().intValue(), credits);
}
@ApiOperation("回调百度接口")
@UpdateUserCache
@GetMapping("/baidu")
public AjaxResult baidu(@RequestParam(required = true) Integer newType, @RequestParam(required = true) String bdVid) {
baiduService.upload(getUserId().intValue(), newType, bdVid);
return AjaxResult.success();
}
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.user.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.service.TtUserCreditsRecordsService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.domain.entity.recorde.TtUserCreditsRecords;
import com.ruoyi.domain.vo.TtUserCreditsRecordsRankVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Timestamp;
import java.util.Calendar;
@Api(tags = "用户信用记录")
@RestController
@RequestMapping("/api/userCreditsRecords")
@Slf4j
public class ApiUserCreditsRecordsController extends BaseController {
private final TtUserCreditsRecordsService ttUserCreditsRecordsService;
public ApiUserCreditsRecordsController(TtUserCreditsRecordsService ttUserCreditsRecordsService) {
this.ttUserCreditsRecordsService = ttUserCreditsRecordsService;
}
/**
* 积分排行榜
* @param type 1今天 2昨天 3近一周
*/
@ApiOperation("流水网流水排行榜")
@GetMapping("/creditsRank/{type}/{page}/{size}")
@Anonymous
public Page<TtUserCreditsRecordsRankVO> creditsRank(@PathVariable("type") Integer type,
@PathVariable("page") Integer page,
@PathVariable("size") Integer size) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY,0);
c.set(Calendar.MINUTE,0);
c.set(Calendar.SECOND,0);
c.set(Calendar.MILLISECOND,0);
Timestamp end = null;
Timestamp begin = null;
if (type.equals(1)) {
begin = new Timestamp(c.getTimeInMillis());
end = new Timestamp(System.currentTimeMillis());
} else if (type.equals(2)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.DAY_OF_MONTH,-1);
begin = new Timestamp(c.getTimeInMillis());
} else if (type.equals(3)) {
end = new Timestamp(c.getTimeInMillis());
c.add(Calendar.WEEK_OF_MONTH,-1);
begin = new Timestamp(c.getTimeInMillis());
}
return ttUserCreditsRecordsService.rank(begin, end, page, size);
}
/**
* 流水网推广奖励明细
* @param type 1、今天2、昨天3、近七天
*/
@ApiOperation("流水网推广奖励明细")
@GetMapping("/pWelfareRecords/{type}/{page}/{size}")
public Page<TtUserCreditsRecords> pWelfareRecords(@PathVariable("type") Integer type,
@PathVariable("page") Integer page,
@PathVariable("size") Integer size) {
Long userId = getUserId();
return ttUserCreditsRecordsService.pWelfareRecords(Integer.valueOf(String.valueOf(userId)),type,page,size);
}
}

View File

@@ -0,0 +1,218 @@
package com.ruoyi.user.controller;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.admin.mapper.TtOrnamentMapper;
import com.ruoyi.admin.mapper.TtOrnamentsLevelMapper;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.annotation.UpdateUserCache;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.PageDataInfo;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.domain.dto.packSack.DecomposeLogCondition;
import com.ruoyi.domain.dto.packSack.DecomposeParam;
import com.ruoyi.domain.dto.packSack.DeliveryParam;
import com.ruoyi.domain.dto.packSack.PackSackCondition;
import com.ruoyi.domain.entity.BoxTransferRecord;
import com.ruoyi.domain.entity.TtOrnament;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.TtOrnamentsLevel;
import com.ruoyi.domain.vo.TtBoxRecordsDataVO;
import com.ruoyi.domain.vo.UserPackSackDataVO;
import com.ruoyi.domain.vo.client.PackSackGlobalData;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.contract.QueryTransferRecordRequest;
import com.ruoyi.user.contract.QueryTransferRecordResponse;
import com.ruoyi.user.mapper.ApiBoxTransferRecordMapper;
import com.ruoyi.user.model.TransferParam;
import com.ruoyi.user.model.vo.ApiTransferRecordVO;
import com.ruoyi.user.service.ApiUserPackSackService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Api(tags = "玩家背包")
@RestController
@RequestMapping("/api/userPackSack")
public class ApiUserPackSackController extends BaseController {
private final ISysConfigService sysConfigService;
private final ApiUserPackSackService userPackSackService;
private final TtUserService userService;
@Autowired
private ApiBoxTransferRecordMapper boxTransferRecordMapper;
@Autowired
private TtOrnamentMapper ttOrnamentMapper;
@Autowired
private TtOrnamentsLevelMapper ttOrnamentsLevelMapper;
public ApiUserPackSackController(ISysConfigService sysConfigService,
ApiUserPackSackService userPackSackService,
TtUserService userService) {
this.sysConfigService = sysConfigService;
this.userPackSackService = userPackSackService;
this.userService = userService;
}
@ApiOperation("用户申请提货")
@PostMapping("/delivery")
public R delivery(@RequestBody @Validated DeliveryParam param) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
// 获取用户信息
TtUser ttUser = userService.getById(getUserId());
if ("1".equals(ttUser.getDeliveryStatus())) {
return R.fail(false, "您的帐号提货功能已被禁用,请联系管理员!");
}
return userPackSackService.delivery(param, ttUser);
}
@ApiOperation("分解饰品")
@UpdateUserCache
@PostMapping("/decompose")
public R<Object> decompose(@RequestBody @Validated DecomposeParam param) {
String websiteMaintenance = sysConfigService.selectConfigByKey("websiteMaintenance");
if ("1".equals(websiteMaintenance)) {
return R.fail("网站维护中......");
}
if (!param.getIsAll() && ObjectUtils.isEmpty(param.getPackSackIds())) {
return R.fail("请传入待分解饰品ID");
}
TtUser ttUser = userService.getById(getUserId());
int result = userPackSackService.decompose(param, ttUser);
return R.ok("成功分解" + result + "件饰品");
}
@ApiOperation("饰品分解记录")
//@UpdateUserCache
@PostMapping("/decomposeLog")
public PageDataInfo<TtBoxRecordsDataVO> decomposeLog(@RequestBody @Validated DecomposeLogCondition param) {
param.setUserId(null);
param.setUserId(getUserId().intValue());
// TtUser ttUser = userService.getById(getUserId());
List<TtBoxRecordsDataVO> ttBoxRecords = userPackSackService.decomposeLog(param);
return getPageData(ttBoxRecords);
}
@ApiOperation("玩家背包")
@PostMapping("/getPackSack")
public R<List<UserPackSackDataVO>> getPackSack(@RequestBody @Validated PackSackCondition condition) {
Long userId = getUserId();
if (ObjectUtil.isNull(userId)) {
return R.fail("登录过期。");
}
if (!Objects.isNull(condition.getOrderByType())) {
if (Objects.isNull(condition.getOrderByFie())) {
return R.fail("排序类型不能为空");
}
}
condition.setUidList(Arrays.asList(userId.intValue()));
condition.setStatusList(Arrays.asList(0));
PageUtils.clearPage();
List<UserPackSackDataVO> packSackData = userPackSackService.clientPackSack(condition);
return R.ok(packSackData);
}
@ApiOperation("玩家背包统计数据")
@GetMapping("/packSackGlobalData")
public R<PackSackGlobalData> packSackGlobalData() {
Long userId = getUserId();
if (ObjectUtil.isNull(userId)) {
return R.fail("登录过期。");
}
return userPackSackService.packSackGlobalData(userId.intValue());
}
@ApiOperation("饰品转赠")
@PostMapping({"/transfer"})
public R<Object> transfer(@RequestBody TransferParam param) {
TtUser ttUser = this.userService.getById(this.getUserId());
String result = this.userPackSackService.transfer(param, ttUser);
return StringUtils.isNotBlank(result) ? R.fail(result) : R.ok("转赠成功!");
}
@ApiOperation("饰品转赠记录")
@GetMapping({"/transfer/records"})
public R<QueryTransferRecordResponse> queryTransferRecords(QueryTransferRecordRequest param) {
if (param.getPageNum() == null) {
param.setPageNum(1);
}
if (param.getPageSize() == null) {
param.setPageSize(10);
}
var userId = this.getUserId();
Page<BoxTransferRecord> page = Page.of(param.getPageNum(), param.getPageSize());
var query = new LambdaQueryChainWrapper<>(this.boxTransferRecordMapper);
if (Objects.equals("src", param.getKind())) {
query.eq(BoxTransferRecord::getSrcUid, userId);
} else {
query.eq(BoxTransferRecord::getDstUid, userId);
}
var pageData = query.page(page);
var records = pageData.getRecords().stream().map(v -> {
ApiTransferRecordVO vo = new ApiTransferRecordVO();
BeanUtils.copyProperties(v, vo);
vo.setId(v.getId());
vo.setSrcUid(v.getSrcUid());
vo.setDstUid(v.getDstUid());
vo.setBoxRecordsId(v.getBoxRecordId());
vo.setOrnamentImg(v.getImageUrl());
// 补全:数据中饰品名称/图片/等级图片为空时,通过 ornamentId 查询再去补全
if (v.getOrnamentId() != null &&
(StringUtils.isBlank(v.getOrnamentName()) || StringUtils.isBlank(v.getImageUrl()))) {
TtOrnament ornament = new LambdaQueryChainWrapper<>(ttOrnamentMapper)
.eq(TtOrnament::getId, v.getOrnamentId())
.one();
if (ornament != null) {
if (StringUtils.isBlank(v.getOrnamentName())) {
vo.setOrnamentName(ornament.getShortName());
}
if (StringUtils.isBlank(v.getImageUrl())) {
vo.setOrnamentImg(ornament.getImageUrl());
}
if (StringUtils.isBlank(v.getMarketHashName())) {
vo.setMarketHashName(ornament.getMarketHashName());
}
// 补全等级图片tt_ornament.exterior 对应 tt_ornaments_level.id
if (StringUtils.isBlank(v.getOrnamentLevelImg()) && ornament.getQuality() != null) {
Integer levelId = Integer.valueOf(ornament.getExterior());
TtOrnamentsLevel level = new LambdaQueryChainWrapper<>(ttOrnamentsLevelMapper)
.eq(TtOrnamentsLevel::getId, levelId)
.one();
if (level != null) {
vo.setOrnamentLevelImg(level.getLevelImg());
}
}
}
}
return vo;
}).collect(Collectors.toList());
QueryTransferRecordResponse response = new QueryTransferRecordResponse();
response.setTotal(pageData.getTotal());
response.setRows(records);
return R.ok(response);
}
}

View File

@@ -0,0 +1,42 @@
package com.ruoyi.user.controller;
import com.ruoyi.domain.other.TtBanner;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.user.service.ApiWebsiteSetupService;
import com.ruoyi.domain.vo.ApiContentDataVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Api(tags = "网站设置")
@RestController
@RequestMapping("/api/websiteSetup")
public class ApiWebsiteSetupController {
private final ApiWebsiteSetupService apiWebsiteSetupService;
public ApiWebsiteSetupController(ApiWebsiteSetupService apiWebsiteSetupService) {
this.apiWebsiteSetupService = apiWebsiteSetupService;
}
@ApiOperation("获取横幅列表")
@Anonymous
@GetMapping("/getBannerList")
public R<List<TtBanner>> getBannerList() {
List<TtBanner> list = apiWebsiteSetupService.getBannerList();
return R.ok(list);
}
@ApiOperation("获取类型内容")
@GetMapping("/getContentByType")
@Anonymous
public R<ApiContentDataVO> getContentByType(String alias) {
ApiContentDataVO data = apiWebsiteSetupService.getContentByType(alias);
return R.ok(data);
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.user.mapper;
import com.ruoyi.domain.other.TtAnnouncement;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ApiAnnouncementMapper {
List<TtAnnouncement> getAnnouncementList(Long userId);
TtAnnouncement getAnnouncementByAnnouncementId(Integer announcementId);
int countUnreadAnnouncement(Long userId);
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.user.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface ApiAnnouncementReadMapper {
int countAnnouncementRead(@Param("announcementId") Integer announcementId, @Param("userId") Long userId);
int addAnnouncementRead(@Param("announcementId") Integer announcementId, @Param("userId") Long userId);
}

View File

@@ -0,0 +1,9 @@
package com.ruoyi.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.domain.entity.BoxTransferRecord;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ApiBoxTransferRecordMapper extends BaseMapper<BoxTransferRecord> {
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.user.mapper;
import com.ruoyi.domain.vo.ApiMessageDataVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ApiMessageMapper {
List<ApiMessageDataVO> getMessageList(@Param("userId") Long userId, @Param("id") Integer id);
}

View File

@@ -0,0 +1,24 @@
package com.ruoyi.user.mapper;
import com.ruoyi.domain.other.TtNotice;
import com.ruoyi.user.model.vo.ApiNoticeVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ApiNoticeMapper {
List<ApiNoticeVO> getNoticeList(Long userId);
ApiNoticeVO getNoticeByNoticeId(@Param("userId") Long userId, @Param("noticeId") Integer noticeId);
int countUnreadNotice(Long userId);
int addNotice(TtNotice ttNotice);
int editNotice(TtNotice ttNotice);
int removeNoticeByNoticeId(Integer noticeId);
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.user.mapper;
import com.ruoyi.domain.other.ApiShoppingBody;
import com.ruoyi.domain.vo.ApiShoppingDataVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ApiShoppingMapper {
List<ApiShoppingDataVO> list(@Param("shoppingBody") ApiShoppingBody shoppingBody, @Param("exchangePriceRatio") Integer exchangePriceRatio);
}

View File

@@ -0,0 +1,31 @@
package com.ruoyi.user.mapper;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.user.model.TtTaskCenterUser;
import com.ruoyi.user.model.dto.YesterdayExpenditureDTO;
import com.ruoyi.user.model.vo.ApiTaskCenterVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
@Mapper
public interface ApiTaskCenterMapper {
List<ApiTaskCenterVO> selectApiTaskCenterVOList(Integer userId);
List<YesterdayExpenditureDTO> getYesterdayExpenditure();
BigDecimal selectCreditByTaskIdAndUserId(@Param("taskId") Integer taskId, @Param("userId") Integer userId);
TtTaskCenterUser selectTtTaskCenterUserByTaskIdAndUserId(@Param("taskId") Integer taskId, @Param("userId") Integer userId);
int insertYesterdayExpenditureBonusPoints(List<TtTaskCenterUser> ttTaskCenterUserList);
int deleteYesterdayExpenditureBonusPoints(Integer taskId);
int markAsClaimedByUserIdAndType(@Param("taskId") Integer taskId, @Param("userId") Integer userId);
int insertTaskCenterRecord(TtTaskCenterUser ttTaskCenterUser);
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.user.mapper;
import com.ruoyi.user.model.vo.ApiRechargeRankingVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ApiUserBlendErcashMapper {
/**
* 获取指定日期的消费排行榜
*/
List<ApiRechargeRankingVO> getRechargeRankingByDate(String date);
}

View File

@@ -0,0 +1,26 @@
package com.ruoyi.user.mapper;
import com.ruoyi.domain.vo.UserPackSackDataVO;
import com.ruoyi.domain.vo.client.PackSackGlobalData;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ApiUserPackSackMapper {
List<UserPackSackDataVO> getPackSack(Integer userId);
List<UserPackSackDataVO> clientPackSack(
@Param("uidList") List<Integer> uidList,
@Param("statusList") List<Integer> statusList,
@Param("name") String name,
@Param("beginTime") String beginTime,
@Param("endTime") String endTime,
@Param("orderByFie") Integer orderByFie,
@Param("orderByType") Integer orderByType,
@Param("limit") Integer limit,
@Param("size") Integer size);
PackSackGlobalData packSackGlobalData(@Param("userId") Integer userId);
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.user.model;
import lombok.Data;
import java.util.List;
@Data
public class TransferParam {
private List<Long> packSackIds;
private Integer targetUid;
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.user.model;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class TtTaskCenterUser {
private Integer taskId;
private Integer userId;
private BigDecimal credit;
private String claimed;
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.user.model.dto;
import lombok.Data;
@Data
public class RealNameAuthenticationDTO {
private String realName;
private String idNum;
private String certifyId;
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.user.model.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class YesterdayExpenditureDTO {
private Integer userId;
private BigDecimal totalRecharge;
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.user.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class ApiNoticeVO {
private Integer noticeId;
private String title;
private String content;
private String read;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}

View File

@@ -0,0 +1,25 @@
package com.ruoyi.user.model.vo;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class ApiRechargeRankingVO {
private Integer ranking;
private Long userId;
private String nickName;
private String avatar;
/** 金币 */
private BigDecimal amount;
/** 积分 */
private BigDecimal credits;
private BigDecimal totalRecharge;
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.user.model.vo;
import lombok.Data;
@Data
public class ApiTaskCenterVO {
private Integer taskId;
private String taskName;
private String description;
/**
* 领取条件0不满足 1满足
*/
private String status;
/**
* 是否已领取1已领取
*/
private String claimed;
}

View File

@@ -0,0 +1,41 @@
package com.ruoyi.user.model.vo;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class ApiTransferRecordVO {
@TableId
private Long id;
private Long srcUid;
private Long dstUid;
private Long boxRecordsId;
private Long ornamentId;
private String ornamentName;
private String ornamentImg;
private String ornamentLevelImg;
private String marketHashName;
private BigDecimal ornamentsPrice;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.user.service;
import com.ruoyi.domain.other.TtAnnouncement;
import java.util.List;
public interface ApiAnnouncementService {
List<TtAnnouncement> getAnnouncementList(Long userId);
TtAnnouncement getAnnouncementByAnnouncementId(Integer announcementId, Long userId);
int countUnreadAnnouncement(Long userId);
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.user.service;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.user.contract.QueryVipRewardResponse;
import java.math.BigDecimal;
public interface ApiBonusService {
R receiveRedPacket(String code, TtUser ttUser);
R<QueryVipRewardResponse> vipRewardList(TtUser ttUser);
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.user.service;
import com.ruoyi.common.core.domain.AjaxResult;
import org.apache.commons.lang3.tuple.Pair;
public interface ApiLoginService {
Pair<String, AjaxResult> login(String username, String password);
AjaxResult verificationCodeLogin(String phoneNumber, String code);
AjaxResult verificationCodeLoginOrRegister(String phoneNumber, String code, String parentInvitationCode);
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.user.service;
import com.ruoyi.domain.vo.ApiMessageDataVO;
import java.util.List;
public interface ApiMessageService {
List<ApiMessageDataVO> getMessageList(Long userId, Integer id);
ApiMessageDataVO view(Long userId, Integer id);
String batchOperation(Long userId, List<Integer> ids, String status);
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.user.service;
import com.ruoyi.domain.other.TtNotice;
import com.ruoyi.user.model.vo.ApiNoticeVO;
import java.util.List;
public interface ApiNoticeService {
List<ApiNoticeVO> getNoticeList(Long userId);
ApiNoticeVO getNoticeByNoticeId(Long userId, Integer noticeId);
int countUnreadNotice(Long userId);
int addNotice(TtNotice ttNotice);
int editNotice(TtNotice ttNotice);
int removeNoticeByNoticeId(Integer noticeId);
}

View File

@@ -0,0 +1,10 @@
package com.ruoyi.user.service;
import com.ruoyi.domain.vo.promotion.TtPromotionRecordVo;
import java.util.List;
public interface ApiPromotionRecordService {
List<TtPromotionRecordVo> getPromotionRecord(Integer userId);
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.user.service;
import com.ruoyi.domain.other.ApiRegisterBody;
public interface ApiRegisterService {
String register(ApiRegisterBody registerBody);
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.user.service;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.ApiShoppingBody;
import com.ruoyi.domain.vo.ApiShoppingDataVO;
import java.math.BigDecimal;
import java.util.List;
public interface ApiShoppingService {
List<ApiShoppingDataVO> list(ApiShoppingBody shoppingBody);
R exchange(TtUser ttUser, Long ornamentsId);
String integratingConversion(TtUser ttUser, BigDecimal credits);
}

View File

@@ -0,0 +1,18 @@
package com.ruoyi.user.service;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.user.model.TtTaskCenterUser;
import com.ruoyi.user.model.vo.ApiTaskCenterVO;
import java.util.List;
public interface ApiTaskCenterService {
List<ApiTaskCenterVO> selectApiTaskCenterVOList(Integer userId);
TtTaskCenterUser selectTtTaskCenterUserByTaskIdAndUserId(Integer taskId, Integer userId);
void updateYesterdayBonusPoints();
AjaxResult getReward(Integer taskId, Integer userId);
}

View File

@@ -0,0 +1,33 @@
package com.ruoyi.user.service;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.domain.dto.packSack.DecomposeLogCondition;
import com.ruoyi.domain.dto.packSack.DecomposeParam;
import com.ruoyi.domain.dto.packSack.DeliveryParam;
import com.ruoyi.domain.dto.packSack.PackSackCondition;
import com.ruoyi.domain.entity.TtBoxRecords;
import com.ruoyi.domain.vo.TtBoxRecordsDataVO;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.vo.UserPackSackDataVO;
import com.ruoyi.domain.vo.client.PackSackGlobalData;
import com.ruoyi.user.model.TransferParam;
import java.util.List;
public interface ApiUserPackSackService {
R delivery(DeliveryParam param, TtUser ttUser);
int decompose(DecomposeParam param, TtUser ttUser);
List<UserPackSackDataVO> getPackSack(Integer userId);
List<TtBoxRecords> packSackHandle(List<Long> packSackIds, TtUser ttUser, Integer status);
List<TtBoxRecordsDataVO> decomposeLog(DecomposeLogCondition param);
List<UserPackSackDataVO> clientPackSack(PackSackCondition condition);
R<PackSackGlobalData> packSackGlobalData(Integer userId);
String transfer(TransferParam param, TtUser ttUser);
}

View File

@@ -0,0 +1,31 @@
package com.ruoyi.user.service;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.ApiForgetPasswordBody;
import com.ruoyi.domain.other.ApiUpdateUserDetailsBody;
import com.ruoyi.domain.other.RealNameAuthenticationBody;
import org.springframework.web.multipart.MultipartFile;
public interface ApiUserService {
String profilePictureUpload(TtUser ttUser, MultipartFile file);
String updateUserDetails(TtUser ttUser, ApiUpdateUserDetailsBody updateUserDetailsBody);
String forgetPassword(ApiForgetPasswordBody apiForgetPasswordBody);
String realNameAuthentication(TtUser ttUser, RealNameAuthenticationBody realNameAuthenticationBody);
String realNameAuthentication2(TtUser ttUser, String realName, String idNum, String phoneNum);
String authenticationOk(TtUser ttUser);
R<Object> changePW(TtUser ttUser, ApiUpdateUserDetailsBody updateUserDetailsBody,String token);
R bindBoss(TtUser ttUser, ApiUpdateUserDetailsBody updateUserDetailsBody);
Integer getSubordinateNumber(Long userId);
R<Void> checkRecharge(Integer userId);
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.user.service;
import com.ruoyi.domain.other.TtBanner;
import com.ruoyi.domain.vo.ApiContentDataVO;
import java.util.List;
public interface ApiWebsiteSetupService {
List<TtBanner> getBannerList();
ApiContentDataVO getContentByType(String alias);
}

View File

@@ -0,0 +1,40 @@
package com.ruoyi.user.service;
import com.ruoyi.admin.mapper.TtUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.security.SecureRandom;
import java.util.Objects;
@Service
public class UserIdGenerator {
@Autowired
private TtUserMapper ttUserMapper;
// 生成随机的六位数,不能与数据库中已有账号重复
public Integer generateUserId() {
SecureRandom random = new SecureRandom();
int maxRetries = 50; // 防止死循环的最大重试次数
int retryCount = 0;
while (retryCount < maxRetries) {
// 生成 100000 到 999999 之间的随机数
int candidateId = 100000 + random.nextInt(900000);
// 检查数据库中是否存在该 ID
// 假设 TtUserMapper 中有一个 checkUserIdExists 方法返回 boolean 或 count
// 如果该方法不存在,请根据实际情况调整,例如 selectById 返回 null
var exists = ttUserMapper.selectTtUserById((long)candidateId);
if (Objects.isNull(exists)) {
return candidateId;
}
retryCount++;
}
throw new RuntimeException("生成用户 ID 失败:达到最大重试次数,可能六位数 ID 已耗尽");
}
}

View File

@@ -0,0 +1,39 @@
package com.ruoyi.user.service.impl;
import com.ruoyi.domain.other.TtAnnouncement;
import com.ruoyi.user.mapper.ApiAnnouncementMapper;
import com.ruoyi.user.mapper.ApiAnnouncementReadMapper;
import com.ruoyi.user.service.ApiAnnouncementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ApiAnnouncementServiceImpl implements ApiAnnouncementService {
@Autowired
private ApiAnnouncementMapper apiAnnouncementMapper;
@Autowired
private ApiAnnouncementReadMapper apiAnnouncementReadMapper;
@Override
public List<TtAnnouncement> getAnnouncementList(Long userId) {
return apiAnnouncementMapper.getAnnouncementList(userId);
}
@Override
public TtAnnouncement getAnnouncementByAnnouncementId(Integer announcementId, Long userId) {
// 新增用户和公告关联,表示已读
if (apiAnnouncementReadMapper.countAnnouncementRead(announcementId, userId) == 0) {
apiAnnouncementReadMapper.addAnnouncementRead(announcementId, userId);
}
return apiAnnouncementMapper.getAnnouncementByAnnouncementId(announcementId);
}
@Override
public int countUnreadAnnouncement(Long userId) {
return apiAnnouncementMapper.countUnreadAnnouncement(userId);
}
}

View File

@@ -0,0 +1,265 @@
package com.ruoyi.user.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.ruoyi.admin.config.RedisConstants;
import com.ruoyi.admin.mapper.TtRedPacketMapper;
import com.ruoyi.admin.mapper.TtRedPacketRecordMapper;
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.admin.service.TtVipLevelService;
import com.ruoyi.admin.util.RandomUtils;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.redis.config.RedisLock;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MoneyUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
import com.ruoyi.domain.entity.TtUserBlendErcash;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.TtRedPacket;
import com.ruoyi.domain.other.TtRedPacketRecord;
import com.ruoyi.domain.other.TtVipLevel;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.user.contract.QueryVipRewardResponse;
import com.ruoyi.user.service.ApiBonusService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class ApiBonusServiceImpl implements ApiBonusService {
private final TtUserService userService;
private final TtRedPacketMapper redPacketMapper;
private final TtRedPacketRecordMapper redPacketRecordMapper;
private final RedisLock redisLock;
public ApiBonusServiceImpl(TtUserService userService,
TtRedPacketMapper redPacketMapper,
TtRedPacketRecordMapper redPacketRecordMapper,
RedisLock redisLock) {
this.userService = userService;
this.redPacketMapper = redPacketMapper;
this.redPacketRecordMapper = redPacketRecordMapper;
this.redisLock = redisLock;
}
@Autowired
private TtUserBlendErcashMapper userBlendErcashMapper;
@Autowired
private TtVipLevelService vipLevelService;
// 领红包检查
private R<TtRedPacket> receiveRedPacketCheck(String code, TtUser ttUser) {
if (StringUtils.isBlank(code)) return R.fail("口令错误。");
TtRedPacket ttRedPacket = new LambdaQueryChainWrapper<>(redPacketMapper)
.eq(TtRedPacket::getPassword, code)
.eq(TtRedPacket::getDelFlag, 0)
.one();
if (ObjectUtil.isNull(ttRedPacket)) return R.fail("口令错误,没有合法的红包。");
if (ttRedPacket.getStatus().equals(1)) return R.fail("红包已经抢光了。");
List<TtRedPacketRecord> allRedPackRecord = new LambdaQueryChainWrapper<>(redPacketRecordMapper)
.eq(TtRedPacketRecord::getRedPacketId, ttRedPacket.getId())
.list();
if (allRedPackRecord.size() >= ttRedPacket.getNum()) return R.fail("红包已经抢光了!");
if (Objects.isNull(ttRedPacket.getUseStatus()) || ttRedPacket.getUseStatus().equals(1))
return R.fail("该红包被禁用,请联系管理员。");
if (ObjectUtil.isNotEmpty(ttRedPacket.getUserId()) && Objects.equals(ttUser.getUserId(), ttRedPacket.getUserId()))
return R.fail("给粉丝的专属红包,您自己无法领取。");
if (ObjectUtil.isNotEmpty(ttRedPacket.getUserId())
&& ttRedPacket.getUserId() != 0
&& !Objects.equals(ttUser.getParentId(), ttRedPacket.getUserId()))
return R.fail("粉丝专属红包,您尚未关注该主播。");
Date openingTime = ttRedPacket.getOpeningTime();
if (DateUtils.getNowDate().compareTo(ttRedPacket.getOpeningTime()) < 0)
return R.fail("红包开启时间:" + DateUtil.format(openingTime, "yyyy-MM-dd HH:mm:ss") + ",敬请期待。");
Date validity = ttRedPacket.getValidity();
if (StringUtils.isNotNull(validity) && DateUtils.getNowDate().compareTo(validity) > 0) {
ttRedPacket.setStatus(1);
new LambdaUpdateChainWrapper<>(redPacketMapper)
.eq(TtRedPacket::getId, ttRedPacket.getId())
.set(TtRedPacket::getStatus, 1)
.update();
return R.fail("红包已结束");
}
for (TtRedPacketRecord record : allRedPackRecord) {
if (record.getUserId().equals(ttUser.getUserId())) return R.fail("您已领取过该红包,请勿重复领取。");
break;
}
return R.ok(ttRedPacket);
}
@Override
public R receiveRedPacket(String code, TtUser ttUser) {
R<TtRedPacket> check = receiveRedPacketCheck(code, ttUser);
if (!check.getCode().equals(200)) return check;
TtRedPacket ttRedPacket = check.getData();
Boolean lock = false;
for (int l = 0; l < 5; l++) {
lock = redisLock.tryLock(RedisConstants.RECEIVE_RED_PACKET_LOCK + ttRedPacket.getId(), 5L, 10L, TimeUnit.SECONDS);
}
if (!lock) return R.fail("没抢到红包。");
try {
List<TtRedPacketRecord> redPacketRecords = new LambdaQueryChainWrapper<>(redPacketRecordMapper)
.eq(TtRedPacketRecord::getRedPacketId, ttRedPacket.getId())
.list();
if (ttRedPacket.getNum() > redPacketRecords.size()) {
// 构建抢红包记录
BigDecimal receiveAmount = RandomUtils.getRandomPrice(ttRedPacket.getAmount());
receiveAmount = receiveAmount.setScale(2, RoundingMode.HALF_UP);
TtRedPacketRecord redPacketRecord = new TtRedPacketRecord();
redPacketRecord.setRedPacketId(ttRedPacket.getId());
redPacketRecord.setUserId(ttUser.getUserId());
redPacketRecord.setReceivePassword(code);
redPacketRecord.setReceiveAmount(receiveAmount);
redPacketRecord.setReceiveTime(DateUtils.getNowDate());
// 保存记录
redPacketRecordMapper.insert(redPacketRecord);
// 更新用户账户
userService.updateOnlyUserAccount(ttUser.getUserId(), receiveAmount, TtAccountRecordSource.RECEIVE_RED_PACKET);
// 更新红包状态
Integer count = new LambdaQueryChainWrapper<>(redPacketRecordMapper)
.eq(TtRedPacketRecord::getRedPacketId, ttRedPacket.getId())
.count().intValue();
if (ttRedPacket.getNum() <= count) {
// 抢完更新为已结束
ttRedPacket.setStatus(1);
new LambdaUpdateChainWrapper<>(redPacketMapper)
.eq(TtRedPacket::getId, ttRedPacket.getId())
.set(TtRedPacket::getStatus, 1)
.update();
}
return R.ok(receiveAmount);
} else {
new LambdaUpdateChainWrapper<>(redPacketMapper)
.eq(TtRedPacket::getId, ttRedPacket.getId())
.set(TtRedPacket::getStatus, 1)
.update();
return R.fail("红包已经抢光了!");
}
} catch (Exception e) {
log.error("任务执行发生异常", e);
return R.fail("系统繁忙,请稍后重试。");
} finally {
redisLock.unlock(RedisConstants.RECEIVE_RED_PACKET_LOCK + ttRedPacket.getId());
}
}
@Override
public R<QueryVipRewardResponse> vipRewardList(TtUser ttUser) {
var todayAmountCf = AsyncManager.me().supply(() -> {
LocalDateTime beginTime = LocalDate.now().atStartOfDay();
var records = new LambdaQueryChainWrapper<>(userBlendErcashMapper)
.eq(TtUserBlendErcash::getUserId, ttUser.getUserId())
.ge(TtUserBlendErcash::getCreateTime, beginTime)
.in(TtUserBlendErcash::getSource, TtAccountRecordSource.getGameConsumeCodes()).list();
if (CollectionUtils.isEmpty(records)) {
return BigDecimal.ZERO;
}
return records.stream()
.map(TtUserBlendErcash::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add).abs();
});
var yesterdayAmountCf = AsyncManager.me().supply(() -> {
LocalDate yesterday = LocalDate.now().minusDays(1);
LocalDateTime beginTime = yesterday.atStartOfDay();
LocalDateTime endTime = yesterday.atTime(23, 59, 59);
var records = new LambdaQueryChainWrapper<>(userBlendErcashMapper)
.eq(TtUserBlendErcash::getUserId, ttUser.getUserId())
.between(TtUserBlendErcash::getCreateTime, beginTime, endTime)
.in(TtUserBlendErcash::getSource, TtAccountRecordSource.getGameConsumeCodes()).list();
if (CollectionUtils.isEmpty(records)) {
return BigDecimal.ZERO;
}
return records.stream()
.map(TtUserBlendErcash::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add).abs();
});
var yesterdayReward = new LambdaQueryChainWrapper<>(userBlendErcashMapper)
.eq(TtUserBlendErcash::getUserId, ttUser.getUserId())
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.VIP_CONSUME_AWARD.getCode())
.gt(TtUserBlendErcash::getCreateTime, LocalDate.now().atStartOfDay())
.orderByDesc(TtUserBlendErcash::getCreateTime).one();
var todayAmount = AsyncManager.getMs(todayAmountCf, 1000);
var yesterdayAmount = AsyncManager.getMs(yesterdayAmountCf, 1000);
QueryVipRewardResponse response = new QueryVipRewardResponse();
if (todayAmount != null) {
response.setTodayAmount(MoneyUtil.toStr(todayAmount));
if (ttUser.getVipLevel() > 0) {
TtVipLevel ttVipLevel = vipLevelService.getById(ttUser.getVipLevel());
if (ttVipLevel == null) {
log.warn("用户【{}】VIP等级不存在[{}]", ttUser.getUserId(), ttUser.getVipLevel());
response.setTodayReward("0.00");
} else {
BigDecimal rebate = ttVipLevel.getCommissions().divide(BigDecimal.valueOf(100), 4,
RoundingMode.HALF_UP)
.multiply(todayAmount).setScale(2, RoundingMode.HALF_UP);
response.setTodayReward(MoneyUtil.toStr(rebate));
}
} else {
response.setTodayReward("0.00");
}
} else {
response.setTodayReward("0.00");
response.setTodayAmount("0.00");
}
if (yesterdayAmount != null) {
response.setYesterdayAmount(MoneyUtil.toStr(yesterdayAmount));
} else {
response.setYesterdayAmount("0.00");
}
if (yesterdayReward != null) {
response.setYesterdayReward(MoneyUtil.toStr(yesterdayReward.getAmount()));
} else {
response.setYesterdayReward("0.00");
}
response.setVipLevels(vipLevelService.list());
return R.ok(response);
}
}

View File

@@ -0,0 +1,263 @@
package com.ruoyi.user.service.impl;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.ruoyi.admin.mapper.TtPromotionUpdateMapper;
import com.ruoyi.admin.mapper.TtUserMapper;
import com.ruoyi.admin.service.TtUserAvatarService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.admin.util.RandomUtils;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.domain.common.constant.UserType;
import com.ruoyi.domain.entity.sys.TtPromotionUpdate;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.TtUserAvatar;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.framework.websocket.WebSocketUsers;
import com.ruoyi.framework.websocket.pojo.ResultData;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.thirdparty.common.service.ApiSmsService;
import com.ruoyi.user.service.ApiLoginService;
import com.ruoyi.user.service.UserIdGenerator;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
@Service
public class ApiLoginServiceImpl implements ApiLoginService {
@Autowired
private ApiSmsService apiSmsService;
@Autowired
private TtUserMapper userMapper;
@Autowired
private SysLoginService sysLoginService;
@Autowired
private TokenService tokenService;
@Autowired
private RedisCache redisCache;
@Autowired
private TtUserService userService;
@Autowired
private TtUserAvatarService userAvatarService;
@Autowired
private ISysConfigService configService;
@Autowired
private TtPromotionUpdateMapper ttPromotionUpdateMapper;
@Autowired
private UserIdGenerator userIdGenerator;
@Override
public Pair<String, AjaxResult> login(String username, String password) {
AjaxResult result = replicatedLogin(username);
if (result != null) {
return Pair.of(null, result);
}
sysLoginService.loginPreCheck(username, password);
LoginUser loginUser = sysLoginService.createLoginUser("api_" + username, password);
recordLoginInfo(loginUser.getUserId());
return Pair.of(tokenService.createToken(loginUser), null);
}
@Override
public AjaxResult verificationCodeLogin(String phoneNumber, String code) {
if (StringUtils.isEmpty(phoneNumber)) {
return AjaxResult.error("手机号不能为空");
}
if (!Validator.isMobile(phoneNumber)) {
return AjaxResult.error("手机号格式错误,请检查手机号是否输入正确!");
}
if (StringUtils.isEmpty(code)) {
return AjaxResult.error("验证码不能为空");
}
if (!NumberUtil.isNumber(code) || code.trim().length() != 4) {
return AjaxResult.error("验证码错误");
}
TtUser ttUser = new LambdaQueryChainWrapper<>(userMapper).eq(TtUser::getPhoneNumber, phoneNumber).one();
if (StringUtils.isNull(ttUser)) {
return AjaxResult.error("该手机号未在本站注册!");
}
String validateCaptcha = apiSmsService.validateCaptcha(code.trim(), "ApiLogin_" + phoneNumber);
if (!"success".equals(validateCaptcha)) {
return AjaxResult.error(validateCaptcha);
}
String password = ttUser.getRemark().substring(ttUser.getRemark().indexOf(":") + 1);
Pair<String, AjaxResult> pair = this.login(ttUser.getUserName(), password);
if (pair.getValue() != null) {
return pair.getValue();
}
AjaxResult ajax = AjaxResult.success();
ajax.put(Constants.TOKEN, pair.getKey());
return ajax;
}
@Override
public AjaxResult verificationCodeLoginOrRegister(String phoneNumber, String code, String parentInvitationCode) {
if (StringUtils.isEmpty(phoneNumber)) {
return AjaxResult.error("手机号不能为空");
}
if (!Validator.isMobile(phoneNumber)) {
return AjaxResult.error("手机号格式错误,请检查手机号是否输入正确!");
}
if (StringUtils.isEmpty(code)) {
return AjaxResult.error("验证码不能为空");
}
if (!NumberUtil.isNumber(code) || code.trim().length() != 4) {
return AjaxResult.error("验证码错误");
}
String validateCaptcha = apiSmsService.validateCaptcha(code.trim(), "ApiLogin_" + phoneNumber);
if (!"success".equals(validateCaptcha)) {
return AjaxResult.error(validateCaptcha);
}
TtUser ttUser = new LambdaQueryChainWrapper<>(userMapper).eq(TtUser::getPhoneNumber, phoneNumber).one();
if (StringUtils.isNull(ttUser)) {
String result = register(phoneNumber, parentInvitationCode);
if (StringUtils.isNotEmpty(result)) {
return AjaxResult.error(result);
}
ttUser = new LambdaQueryChainWrapper<>(userMapper).eq(TtUser::getPhoneNumber, phoneNumber).one();
}
String password = ttUser.getRemark().substring(ttUser.getRemark().indexOf(":") + 1);
Pair<String, AjaxResult> pair = this.login(ttUser.getUserName(), password);
if (pair.getValue() != null) {
return pair.getValue();
}
AjaxResult ajax = AjaxResult.success();
ajax.put(Constants.TOKEN, pair.getKey());
return ajax;
}
private String register(String phoneNumber, String parentInvitationCode) {
String nickName = RandomUtils.getRandomName(new Random().nextInt(2));
String password = RandomUtil.randomString(10);
if (StringUtils.isEmpty(nickName)) return "用户昵称不能为空";
if (StringUtils.isEmpty(phoneNumber)) return "手机号不能为空";
if (!Validator.isMobile(phoneNumber)) return "手机号格式错误,请检查手机号是否输入正确!";
if (StringUtils.isEmpty(password)) return "用户密码不能为空";
TtUser ttUser = TtUser.builder().build();
ttUser.setUserName(phoneNumber);
ttUser.setEmail(phoneNumber + "@qq.com");
ttUser.setPhoneNumber(phoneNumber);
ttUser.setAccountAmount(BigDecimal.ZERO);
ttUser.setAccountCredits(BigDecimal.ZERO);
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
return "密码长度必须在5到20个字符之间";
}
if (!userService.checkPhoneUnique(ttUser)) return "注册失败," + "手机号'" + phoneNumber + "'已被注册!";
if (!userService.checkUserNameUnique(ttUser))
return "注册失败," + "用户名'" + ttUser.getUserName() + "'已存在!";
ttUser.setNickName(nickName);
ttUser.setUserType(UserType.COMMON_USER.getCode());
List<TtUserAvatar> userAvatarList = new LambdaQueryChainWrapper<>(userAvatarService.getBaseMapper()).eq(TtUserAvatar::getIsDefault, "1").list();
if (!userAvatarList.isEmpty()) {
ttUser.setAvatar(userAvatarList.get(0).getAvatar());
} else ttUser.setAvatar("");
ttUser.setPassword(SecurityUtils.encryptPassword(password));
String registerRedPacketStr = configService.selectConfigByKey("registerRedPacket");
BigDecimal registerRedPacket = new BigDecimal(registerRedPacketStr);
ttUser.setAccountAmount(registerRedPacket);
ttUser.setInvitationCode(userService.getInvitationCode().toLowerCase());
if (StringUtils.isNotEmpty(parentInvitationCode) && parentInvitationCode.trim().length() == 6) {
TtUser parentUser = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
.eq(TtUser::getInvitationCode, parentInvitationCode.trim().toUpperCase())
.eq(TtUser::getDelFlag, "0").one();
if (StringUtils.isNull(parentUser)) {
return "上级邀请码填写错误!";
} else {
}
ttUser.setParentId(parentUser.getUserId());
}
ttUser.setIsRealCheck("0");
ttUser.setCreateBy("网站注册");
ttUser.setCreateTime(DateUtils.getNowDate());
ttUser.setRemark("明文密码:" + password);
var id = userIdGenerator.generateUserId();
ttUser.setUserId(id);
boolean regFlag = userService.save(ttUser);
if (!regFlag) return "注册失败,请联系系统管理人员";
// if (BigDecimal.ZERO.compareTo(registerRedPacket) < 0) {
// userService.insertUserAmountRecords(ttUser.getUserId(), TtAccountRecordType.INPUT, TtAccountRecordSource.REGIST_AWARD, registerRedPacket, ttUser.getAccountAmount());
// }
AsyncManager.me().execute(AsyncFactory
.recordLogininfor("api_" + ttUser.getUserName(), Constants.REGISTER, MessageUtils.message("user.register.success")));
// 保存推广更新记录
TtPromotionUpdate build = TtPromotionUpdate.builder()
.employeeId(ttUser.getUserId())
.bossId(ttUser.getParentId())
.createTime(new Timestamp(System.currentTimeMillis()))
.updateTime(new Timestamp(System.currentTimeMillis()))
.build();
ttPromotionUpdateMapper.insert(build);
return "";
}
/**
* 检测用户是否在其它地方登录,如果存在则发送通知给当前用户,
* 并执行相应的清理工作,例如删除已登录用户的缓存信息
*/
private AjaxResult replicatedLogin(String username) {
Collection<String> redisKeys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
List<LoginUser> loginUserList = redisKeys.stream().map(redisCache::<LoginUser>getCacheObject)
.filter(loginUser -> loginUser.getUser() == null)
.filter(loginUser -> username.equals(loginUser.getUsername()))
.collect(Collectors.toList());
if (!loginUserList.isEmpty()) {
// return AjaxResult.error("您的账号在别处已登录,请退出后再登录,如果不是本人操作,请尽快修改密码!");
ResultData<String> resultData = new ResultData<>();
resultData.setCode(10);
resultData.setTypeName("success");
resultData.setData("您的账号在别处登录,如果不是本人操作,请尽快修改密码!");
WebSocketUsers.sendMessageToUserByText(loginUserList.get(0).getUserId().intValue(),
JSON.toJSONString(resultData));
String token = loginUserList.get(0).getToken();
redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + token);
AsyncManager.me().execute(AsyncFactory.recordLogininfor("api_" + username,
Constants.LOGOUT, "退出成功,账号已换机登录!"));
}
return null;
}
/**
* 记录登录信息
*/
public void recordLoginInfo(Long userId) {
new LambdaUpdateChainWrapper<>(userMapper).eq(TtUser::getUserId, userId)
.set(TtUser::getLoginIp, IpUtils.getIpAddr())
.set(TtUser::getLoginDate, DateUtils.getNowDate()).update();
}
}

View File

@@ -0,0 +1,59 @@
package com.ruoyi.user.service.impl;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ruoyi.domain.other.TtMessageSend;
import com.ruoyi.admin.service.TtMessageSendService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.user.mapper.ApiMessageMapper;
import com.ruoyi.user.service.ApiMessageService;
import com.ruoyi.domain.vo.ApiMessageDataVO;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class ApiMessageServiceImpl implements ApiMessageService {
private final ApiMessageMapper apiMessageMapper;
private final TtMessageSendService messageSendService;
public ApiMessageServiceImpl(ApiMessageMapper apiMessageMapper,
TtMessageSendService messageSendService) {
this.apiMessageMapper = apiMessageMapper;
this.messageSendService = messageSendService;
}
@Override
public List<ApiMessageDataVO> getMessageList(Long userId, Integer id) {
return apiMessageMapper.getMessageList(userId, id);
}
@Override
public ApiMessageDataVO view(Long userId, Integer id) {
TtMessageSend ttMessageSend = messageSendService.getById(id);
ttMessageSend.setStatus("1");
ttMessageSend.setReadingTime(DateUtils.getNowDate());
messageSendService.updateById(ttMessageSend);
List<ApiMessageDataVO> messageList = apiMessageMapper.getMessageList(userId, id);
if (messageList.isEmpty()) return null;
return messageList.get(0);
}
@Override
public String batchOperation(Long userId, List<Integer> ids, String status) {
List<TtMessageSend> list = new LambdaQueryChainWrapper<>(messageSendService.getBaseMapper())
.eq(TtMessageSend::getRecId, userId)
.in(TtMessageSend::getId, ids)
.list();
list = list.stream().peek(ttMessageSend -> {
ttMessageSend.setStatus(status);
if (StringUtils.isNull(ttMessageSend.getReadingTime())) {
ttMessageSend.setReadingTime(DateUtils.getNowDate());
}
}).collect(Collectors.toList());
messageSendService.updateBatchById(list, 1);
return "";
}
}

View File

@@ -0,0 +1,58 @@
package com.ruoyi.user.service.impl;
import com.ruoyi.domain.other.TtNotice;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.user.mapper.ApiNoticeMapper;
import com.ruoyi.user.model.vo.ApiNoticeVO;
import com.ruoyi.user.service.ApiNoticeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class ApiNoticeServiceImpl implements ApiNoticeService {
@Autowired
private ApiNoticeMapper apiNoticeMapper;
@Override
public List<ApiNoticeVO> getNoticeList(Long userId) {
return apiNoticeMapper.getNoticeList(userId);
}
@Override
public ApiNoticeVO getNoticeByNoticeId(Long userId, Integer noticeId) {
// 读取详情后更新为已读状态
TtNotice ttNotice = new TtNotice();
ttNotice.setNoticeId(noticeId);
ttNotice.setRead("1");
editNotice(ttNotice);
return apiNoticeMapper.getNoticeByNoticeId(userId, noticeId);
}
@Override
public int countUnreadNotice(Long userId) {
return apiNoticeMapper.countUnreadNotice(userId);
}
@Override
public int addNotice(TtNotice ttNotice) {
ttNotice.setCreateTime(new Date());
return apiNoticeMapper.addNotice(ttNotice);
}
@Override
public int editNotice(TtNotice ttNotice) {
return apiNoticeMapper.editNotice(ttNotice);
}
@Override
public int removeNoticeByNoticeId(Integer noticeId) {
return apiNoticeMapper.removeNoticeByNoticeId(noticeId);
}
}

View File

@@ -0,0 +1,65 @@
package com.ruoyi.user.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.admin.mapper.TtPromotionRecordMapper;
import com.ruoyi.admin.mapper.TtUserMapper;
import com.ruoyi.domain.entity.TtPromotionRecord;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.vo.promotion.TtPromotionRecordVo;
import com.ruoyi.user.service.ApiPromotionRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Slf4j
public class ApiPromotionRecordServiceImpl implements ApiPromotionRecordService {
@Autowired
private TtPromotionRecordMapper ttPromotionRecordMapper;
@Autowired
private TtUserMapper ttUserMapper;
@Override
public List<TtPromotionRecordVo> getPromotionRecord(Integer userId) {
LambdaQueryWrapper<TtPromotionRecord> wrapper = Wrappers.lambdaQuery();
wrapper.eq(TtPromotionRecord::getUserId, userId);
wrapper.orderByDesc(TtPromotionRecord::getId);
List<TtPromotionRecord> list = ttPromotionRecordMapper.selectList(wrapper);
if (CollectionUtils.isEmpty(list)) {
return Collections.emptyList();
}
List<TtPromotionRecordVo> vos = new ArrayList<>();
List<Integer> userIds = new ArrayList<>();
for (TtPromotionRecord record : list) {
userIds.add(record.getSubordinateUserId());
TtPromotionRecordVo vo = new TtPromotionRecordVo();
BeanUtils.copyProperties(record, vo);
if (record.getRebate() == null || record.getRebate().compareTo(new BigDecimal(0)) <= 0) {
vo.setCommissions(new BigDecimal(0));
} else if (record.getRechargePrice().compareTo(new BigDecimal(0)) > 0) {
vo.setCommissions(record.getRebate().multiply(BigDecimal.valueOf(100))
.divide(record.getRechargePrice(), 1, RoundingMode.HALF_UP));
}
vos.add(vo);
}
List<TtUser> ttUsers = ttUserMapper.selectBatchIds(userIds);
Map<Integer, String> ttUserMap = ttUsers.stream().filter(Objects::nonNull).collect(Collectors.toMap(
TtUser::getUserId, // 使用TtUser的userId作为Map的键
TtUser::getNickName // 使用TtUser的username作为Map的值
));
for (TtPromotionRecordVo vo : vos) {
vo.setSubordinateUserName(ttUserMap.getOrDefault(vo.getSubordinateUserId(), ""));
}
return vos;
}
}

View File

@@ -0,0 +1,130 @@
package com.ruoyi.user.service.impl;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ruoyi.admin.mapper.TtPromotionUpdateMapper;
import com.ruoyi.admin.service.TtUserAvatarService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.utils.*;
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
import com.ruoyi.domain.common.constant.TtAccountRecordType;
import com.ruoyi.domain.entity.sys.TtPromotionUpdate;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.ApiRegisterBody;
import com.ruoyi.domain.other.TtUserAvatar;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.thirdparty.baidu.service.BaiduService;
import com.ruoyi.thirdparty.common.service.ApiSmsService;
import com.ruoyi.user.service.ApiRegisterService;
import com.ruoyi.user.service.UserIdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.List;
@Service
@Slf4j
public class ApiRegisterServiceImpl implements ApiRegisterService {
@Autowired
private TtUserAvatarService userAvatarService;
@Autowired
private TtUserService userService;
@Autowired
private ISysConfigService configService;
@Autowired
private ApiSmsService apiSmsService;
@Autowired
private TtPromotionUpdateMapper ttPromotionUpdateMapper;
@Autowired
private BaiduService baiduService;
@Autowired
private UserIdGenerator userIdGenerator;
@Override
public String register(ApiRegisterBody registerBody) {
String nickName = registerBody.getNickName(), phoneNumber = registerBody.getPhoneNumber(),
password = registerBody.getPassword(), parentInvitationCode = registerBody.getParentInvitationCode(),
code = registerBody.getCode();
if (StringUtils.isEmpty(nickName) || nickName.length() > UserConstants.NICKNAME_MAX_LENGTH) {
return "昵称必须在1到7个字符之间";
}
if (StringUtils.isEmpty(phoneNumber)) return "手机号不能为空";
if (!Validator.isMobile(phoneNumber)) return "手机号格式错误,请检查手机号是否输入正确!";
if (StringUtils.isEmpty(password)) return "用户密码不能为空";
if (StringUtils.isEmpty(code)) return "验证码不能为空";
if (!NumberUtil.isNumber(code) || code.trim().length() != 4) return "验证码错误";
TtUser ttUser = TtUser.builder().build();
ttUser.setUserName(phoneNumber);
ttUser.setEmail(phoneNumber + "@qq.com");
ttUser.setPhoneNumber(phoneNumber);
ttUser.setAccountAmount(BigDecimal.ZERO);
ttUser.setAccountCredits(BigDecimal.ZERO);
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
return "密码长度必须在5到20个字符之间";
}
if (!userService.checkPhoneUnique(ttUser)) return "注册失败," + "手机号'" + phoneNumber + "'已被注册!";
if (!userService.checkUserNameUnique(ttUser))
return "注册失败," + "用户名'" + ttUser.getUserName() + "'已存在!";
ttUser.setNickName(nickName);
ttUser.setUserType("02");
List<TtUserAvatar> userAvatarList = new LambdaQueryChainWrapper<>(userAvatarService.getBaseMapper()).eq(TtUserAvatar::getIsDefault, "1").list();
if (!userAvatarList.isEmpty()) {
ttUser.setAvatar(RandomUtil.choice(userAvatarList).getAvatar());
} else ttUser.setAvatar("");
ttUser.setPassword(SecurityUtils.encryptPassword(password));
String registerRedPacketStr = configService.selectConfigByKey("registerRedPacket");
BigDecimal registerRedPacket = new BigDecimal(registerRedPacketStr);
ttUser.setAccountAmount(registerRedPacket);
ttUser.setInvitationCode(userService.getInvitationCode().toLowerCase());
if (StringUtils.isNotEmpty(parentInvitationCode) && parentInvitationCode.trim().length() == 6) {
TtUser parentUser = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
.eq(TtUser::getInvitationCode, parentInvitationCode.trim().toUpperCase())
.eq(TtUser::getDelFlag, "0").one();
if (StringUtils.isNull(parentUser)) {
return "上级邀请码填写错误!";
} else {
}
ttUser.setParentId(parentUser.getUserId());
}
ttUser.setIsRealCheck("0");
ttUser.setCreateBy("网站注册");
ttUser.setCreateTime(DateUtils.getNowDate());
ttUser.setRemark("明文密码:" + password);
String validateCaptcha = apiSmsService.validateCaptcha(code.trim(), "ApiRegister_" + phoneNumber);
if (!"success".equals(validateCaptcha)) return validateCaptcha;
ttUser.setUserId(userIdGenerator.generateUserId());
boolean regFlag = userService.save(ttUser);
if (!regFlag) return "注册失败,请联系系统管理人员";
else {
if (BigDecimal.ZERO.compareTo(registerRedPacket) < 0) {
userService.insertUserAmountRecords(ttUser.getUserId(), TtAccountRecordType.INPUT, TtAccountRecordSource.REGIST_AWARD, registerRedPacket, ttUser.getAccountAmount());
}
AsyncManager.me().execute(AsyncFactory.recordLogininfor("api_" + ttUser.getUserName(), Constants.REGISTER, MessageUtils.message("user.register.success")));
// 保存推广更新记录
TtPromotionUpdate build = TtPromotionUpdate.builder()
.employeeId(ttUser.getUserId())
.bossId(ttUser.getParentId())
.createTime(new Timestamp(System.currentTimeMillis()))
.updateTime(new Timestamp(System.currentTimeMillis()))
.build();
ttPromotionUpdateMapper.insert(build);
// baiduService.upload(ttUser.getUserId(), 49, registerBody.getBdVid());
}
return "";
}
}

View File

@@ -0,0 +1,202 @@
package com.ruoyi.user.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ruoyi.admin.mapper.TtBoxRecordsMapper;
import com.ruoyi.admin.mapper.TtOrnamentMapper;
import com.ruoyi.admin.mapper.TtOrnamentsLevelMapper;
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
import com.ruoyi.admin.service.TtOrnamentService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.domain.other.TtOrnamentsLevel;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
import com.ruoyi.domain.common.constant.TtAccountRecordType;
import com.ruoyi.domain.common.constant.TtboxRecordStatus;
import com.ruoyi.domain.entity.TtBoxRecords;
import com.ruoyi.domain.entity.TtOrnament;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.ApiShoppingBody;
import com.ruoyi.domain.vo.ApiShoppingDataVO;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.mapper.ApiShoppingMapper;
import com.ruoyi.user.service.ApiShoppingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static com.ruoyi.domain.common.constant.TtboxRecordSource.MALL_EXCHANGE;
@Service
@Slf4j
public class ApiShoppingImpl implements ApiShoppingService {
private final TtUserService userService;
private final TtBoxRecordsMapper boxRecordsMapper;
private final ApiShoppingMapper shoppingMapper;
private final ISysConfigService configService;
private final TtOrnamentMapper ornamentsMapper;
private final TtOrnamentsLevelMapper ornamentsLevelMapper;
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
public ApiShoppingImpl(TtUserService userService,
TtBoxRecordsMapper boxRecordsMapper,
ApiShoppingMapper shoppingMapper,
ISysConfigService configService,
TtOrnamentMapper ornamentsMapper,
TtOrnamentsLevelMapper ornamentsLevelMapper) {
this.userService = userService;
this.boxRecordsMapper = boxRecordsMapper;
this.shoppingMapper = shoppingMapper;
this.configService = configService;
this.ornamentsMapper = ornamentsMapper;
this.ornamentsLevelMapper = ornamentsLevelMapper;
}
@Autowired
private TtOrnamentService ttOrnamentService;
@Override
public List<ApiShoppingDataVO> list(ApiShoppingBody param) {
// 商城兑换比例
String exchangePriceRatio = configService.selectConfigByKey("exchangePriceRatio");
LambdaQueryWrapper<TtOrnament> wrapper = new LambdaQueryWrapper<>();
// 名称
wrapper.like(ObjectUtil.isNotEmpty(param.getName()), TtOrnament::getShortName, param.getName());
// 类型
wrapper.eq(ObjectUtil.isNotEmpty(param.getType()), TtOrnament::getType, param.getType());
// 外观
wrapper.eq(ObjectUtil.isNotEmpty(param.getExterior()), TtOrnament::getExterior, param.getExterior());
// 品质
wrapper.eq(ObjectUtil.isNotEmpty(param.getQuality()), TtOrnament::getQuality, param.getQuality());
// 稀有程度
wrapper.eq(ObjectUtil.isNotEmpty(param.getRarity()), TtOrnament::getRarity, param.getRarity());
// 是否上架
wrapper.eq(TtOrnament::getIsPutaway, "0");
// 价格大于0
// wrapper.ge(TtOrnament::getUsePrice, 70);
// 价格区间
if (ObjectUtil.isNotNull(param.getMaxPrice())) {
if (BigDecimal.ZERO.compareTo(param.getMaxPrice()) > 0) param.setMaxPrice(null);
if (param.getMinPrice().compareTo(param.getMaxPrice()) > 0) param.setMaxPrice(null);
if (BigDecimal.ZERO.compareTo(param.getMinPrice()) > 0) param.setMinPrice(BigDecimal.ZERO);
}
if (ObjectUtil.isNotNull(param.getMaxPrice())) {
wrapper.between(TtOrnament::getUsePrice, param.getMinPrice(), param.getMaxPrice());
}
// 排序
if (ObjectUtil.isEmpty(param.getSortBy())) wrapper.orderByDesc(TtOrnament::getUsePrice);
if (ObjectUtil.isNotEmpty(param.getSortBy()) && param.getSortBy().equals(1))
wrapper.orderByAsc(TtOrnament::getUsePrice);
if (ObjectUtil.isNotEmpty(param.getSortBy()) && param.getSortBy().equals(2))
wrapper.orderByDesc(TtOrnament::getUsePrice);
if (ObjectUtil.isNotEmpty(param.getSortBy()) && param.getSortBy().equals(3))
wrapper.orderByAsc(TtOrnament::getUpdateTime);
if (ObjectUtil.isNotEmpty(param.getSortBy()) && param.getSortBy().equals(4))
wrapper.orderByDesc(TtOrnament::getUpdateTime);
List<TtOrnament> list = ttOrnamentService.list(wrapper);
List<ApiShoppingDataVO> res = list.stream().map(ornament -> {
ApiShoppingDataVO vo = new ApiShoppingDataVO();
BeanUtil.copyProperties(ornament, vo);
if (ObjectUtil.isNotEmpty(vo.getUsePrice())) {
vo.setCreditsPrice(vo.getUsePrice().multiply(new BigDecimal(exchangePriceRatio)));
}
return vo;
}).collect(Collectors.toList());
return res;
// return shoppingMapper.list(shoppingBody, Integer.parseInt(exchangePriceRatio));
}
@Override
public R exchange(TtUser ttUser, Long ornamentsId) {
TtOrnament ttOrnament = new LambdaQueryChainWrapper<>(ornamentsMapper)
.eq(TtOrnament::getId, ornamentsId)
.eq(TtOrnament::getIsPutaway, "0")
.one();
if (StringUtils.isNull(ttOrnament)) return R.fail("未查询到该饰品信息,请联系管理员!");
String exchangePriceRatio = configService.selectConfigByKey("exchangePriceRatio"); // 积分价格比例
BigDecimal exchange = ttOrnament.getUsePrice().multiply(new BigDecimal(exchangePriceRatio));
if (exchange.compareTo(ttUser.getAccountCredits()) > 0) return R.fail("您的积分不足!");
R r = userService.updateUserCredits(ttUser.getUserId(), exchange.negate(), TtAccountRecordSource.EXCHANGE);
if (R.isError(r)) {
return R.fail(r.getMsg());
}
TtBoxRecords boxRecords = TtBoxRecords.builder().build();
boxRecords.setUserId(ttUser.getUserId());
boxRecords.setOrnamentId(ornamentsId);
boxRecords.setOrnamentName(ttOrnament.getShortName());//饰品名称
boxRecords.setImageUrl(ttOrnament.getImageUrl());//饰品图片
boxRecords.setMarketHashName(ttOrnament.getMarketHashName());
boxRecords.setOrnamentsPrice(ttOrnament.getUsePrice());
// exterior 字段对应 tt_ornaments_level.id补全等级图片信息
if (ttOrnament.getExterior() != null) {
Integer levelId = Integer.valueOf(ttOrnament.getExterior());
TtOrnamentsLevel level = new LambdaQueryChainWrapper<>(ornamentsLevelMapper)
.eq(TtOrnamentsLevel::getId, levelId)
.one();
if (level != null) {
boxRecords.setOrnamentsLevelId(levelId);//饰品等级 ID
boxRecords.setOrnamentLevelImg(level.getLevelImg());//饰品等级图片
}
}
boxRecords.setStatus(TtboxRecordStatus.IN_PACKSACK_ON.getCode());
boxRecords.setCreateTime(new Date());
boxRecords.setSource(MALL_EXCHANGE.getCode());
boxRecords.setHolderUserId(ttUser.getUserId());
boxRecordsMapper.insert(boxRecords);
return R.ok();
}
// 废弃方法
public void parentAward(TtUser ttUser, BigDecimal exchange) {
BigDecimal t = exchange.multiply(new BigDecimal("0.03"));
TtUser parent = userService.getById(ttUser.getParentId());
parent.setAccountCredits(parent.getAccountCredits().add(t));
userService.updateUserById(parent);
userService.insertUserCreditsRecords(parent.getUserId(), TtAccountRecordType.INPUT, TtAccountRecordSource.P_WELFARE, t, parent.getAccountCredits());
}
@Override
public String integratingConversion(TtUser ttUser, BigDecimal credits) {
if (credits.compareTo(ttUser.getAccountCredits()) > 0) return "您的积分不足!";
ttUser.setAccountAmount(ttUser.getAccountAmount().add(credits));
ttUser.setAccountCredits(ttUser.getAccountCredits().subtract(credits));
if (userService.updateById(ttUser)) {
userService.insertUserAmountRecords(ttUser.getUserId(), TtAccountRecordType.INPUT, TtAccountRecordSource.INTEGRATING_CONVERSION, credits, ttUser.getAccountAmount());
userService.insertUserCreditsRecords(ttUser.getUserId(), TtAccountRecordType.OUTPUT, TtAccountRecordSource.INTEGRATING_CONVERSION, credits.negate(), ttUser.getAccountCredits());
return "";
}
return "积分转换异常!";
}
}

View File

@@ -0,0 +1,120 @@
package com.ruoyi.user.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.admin.mapper.*;
import com.ruoyi.admin.service.TtUserCreditsRecordsService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.domain.entity.TtUserBlendErcash;
import com.ruoyi.domain.entity.recorde.TtUserCreditsRecords;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.TtTaskCenter;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.user.mapper.ApiTaskCenterMapper;
import com.ruoyi.user.model.TtTaskCenterUser;
import com.ruoyi.user.model.dto.YesterdayExpenditureDTO;
import com.ruoyi.user.model.vo.ApiTaskCenterVO;
import com.ruoyi.user.service.ApiTaskCenterService;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@Service
public class ApiTaskCenterServiceImpl implements ApiTaskCenterService {
@Autowired
private ApiTaskCenterMapper apiTaskCenterMapper;
@Autowired
private TtTaskCenterMapper ttTaskCenterMapper;
@Autowired
private TtUserMapper ttUserMapper;
@Autowired
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
@Autowired
private ISysConfigService configService;
@Override
public List<ApiTaskCenterVO> selectApiTaskCenterVOList(Integer userId) {
return apiTaskCenterMapper.selectApiTaskCenterVOList(userId);
}
@Override
public TtTaskCenterUser selectTtTaskCenterUserByTaskIdAndUserId(Integer taskId, Integer userId) {
return apiTaskCenterMapper.selectTtTaskCenterUserByTaskIdAndUserId(taskId, userId);
}
@Transactional
@Override
public void updateYesterdayBonusPoints() {
// 根据任务标识获取任务详情
TtTaskCenter ttTaskCenter = ttTaskCenterMapper.selectTtTaskCenterByIdentify("yesterday.expenditure.task");
// 清空tt_task_center_user表中活动类型为昨日消费奖励的数据
apiTaskCenterMapper.deleteYesterdayExpenditureBonusPoints(ttTaskCenter.getTaskId());
List<YesterdayExpenditureDTO> yesterdayExpenditureDTOList = apiTaskCenterMapper.getYesterdayExpenditure();
if (yesterdayExpenditureDTOList.size() == 0) {
return;
}
// 获取参数设置中消费返积分比例
String rechargePointsRebateRatio = configService.selectConfigByKey("expenditure.points.rebate.ratio");
BigDecimal ratio = new BigDecimal(rechargePointsRebateRatio);
List<TtTaskCenterUser> ttTaskCenterUserList = new ArrayList<>();
for (YesterdayExpenditureDTO yesterdayRechargeDTO : yesterdayExpenditureDTOList) {
TtTaskCenterUser ttTaskCenterUser = new TtTaskCenterUser();
ttTaskCenterUser.setTaskId(ttTaskCenter.getTaskId());
ttTaskCenterUser.setUserId(yesterdayRechargeDTO.getUserId());
ttTaskCenterUser.setCredit(yesterdayRechargeDTO.getTotalRecharge().multiply(ratio));
ttTaskCenterUserList.add(ttTaskCenterUser);
}
// 批量增加昨日的积分奖励数据
apiTaskCenterMapper.insertYesterdayExpenditureBonusPoints(ttTaskCenterUserList);
}
@Transactional
@Override
public AjaxResult getReward(Integer taskId, Integer userId) {
// 根据ID查询奖励积分
BigDecimal credit = apiTaskCenterMapper.selectCreditByTaskIdAndUserId(taskId, userId);
// 将奖励积分写入到tt_user表
TtUser ttUser = ttUserMapper.selectById(userId);
ttUser.setAccountCredits(ttUser.getAccountCredits().add(credit));
int row = ttUserMapper.updateById(ttUser);
// 将奖励积分写入tt_user_blend_ercash表
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TtUserBlendErcash::getUserId, userId)
.orderByDesc(TtUserBlendErcash::getCreateTime)
.last("LIMIT 1");
TtUserBlendErcash lastTtUserBlendErcash = ttUserBlendErcashMapper.selectOne(queryWrapper);
TtUserBlendErcash ttUserBlendErcash = new TtUserBlendErcash();
ttUserBlendErcash.setUserId(userId);
ttUserBlendErcash.setCredits(credit);
ttUserBlendErcash.setCreateTime(new Timestamp(new Date().getTime()));
if (!Objects.isNull(lastTtUserBlendErcash) && !Objects.isNull(lastTtUserBlendErcash.getFinalCredits())) {
ttUserBlendErcash.setFinalCredits(lastTtUserBlendErcash.getFinalCredits().add(credit));
} else {
ttUserBlendErcash.setFinalCredits(credit);
}
ttUserBlendErcash.setTotal(credit);
ttUserBlendErcash.setSource(6);
ttUserBlendErcash.setType(1);
ttUserBlendErcash.setRemark("昨日消费返积分");
ttUserBlendErcashMapper.insert(ttUserBlendErcash);
// 标记为已领取
apiTaskCenterMapper.markAsClaimedByUserIdAndType(taskId, userId);
return row > 0 ? AjaxResult.success("成功领取" + credit + "积分") : AjaxResult.error("领取失败");
}
}

View File

@@ -0,0 +1,423 @@
package com.ruoyi.user.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ruoyi.admin.mapper.TtBoxRecordsMapper;
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
import com.ruoyi.admin.service.TtBoxRecordsService;
import com.ruoyi.admin.service.TtDeliveryRecordService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.domain.common.constant.*;
import com.ruoyi.domain.dto.packSack.DecomposeLogCondition;
import com.ruoyi.domain.dto.packSack.DecomposeParam;
import com.ruoyi.domain.dto.packSack.DeliveryParam;
import com.ruoyi.domain.dto.packSack.PackSackCondition;
import com.ruoyi.domain.entity.BoxTransferRecord;
import com.ruoyi.domain.entity.TtBoxRecords;
import com.ruoyi.domain.entity.delivery.TtDeliveryRecord;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.vo.TtBoxRecordsDataVO;
import com.ruoyi.domain.vo.UserPackSackDataVO;
import com.ruoyi.domain.vo.client.PackSackGlobalData;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.thirdparty.common.service.DeliverGoodsService;
import com.ruoyi.user.mapper.ApiBoxTransferRecordMapper;
import com.ruoyi.user.mapper.ApiUserPackSackMapper;
import com.ruoyi.user.model.TransferParam;
import com.ruoyi.user.service.ApiUserPackSackService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@Service
@Slf4j
public class ApiUserPackSackServiceImpl implements ApiUserPackSackService {
private final ISysConfigService configService;
private final TtUserService userService;
private final ApiUserPackSackMapper userPackSackMapper;
private final TtBoxRecordsService boxRecordsService;
private final TtBoxRecordsMapper ttBoxRecordsMapper;
private final TtDeliveryRecordService deliveryRecordService;
private final RabbitTemplate rabbitTemplate;
@Autowired
private DeliverGoodsService deliverGoodsService;
@Autowired
private Executor customThreadPoolExecutor;
@Autowired
private TtUserBlendErcashMapper TtUserBlendErcashMapper;
@Autowired
private ApiBoxTransferRecordMapper boxTransferRecordMapper;
public ApiUserPackSackServiceImpl(ISysConfigService configService, TtUserService userService,
ApiUserPackSackMapper userPackSackMapper,
TtBoxRecordsService boxRecordsService,
TtBoxRecordsMapper ttBoxRecordsMapper,
TtDeliveryRecordService deliveryRecordService,
RabbitTemplate rabbitTemplate) {
this.configService = configService;
this.userService = userService;
this.userPackSackMapper = userPackSackMapper;
this.boxRecordsService = boxRecordsService;
this.ttBoxRecordsMapper = ttBoxRecordsMapper;
this.deliveryRecordService = deliveryRecordService;
this.rabbitTemplate = rabbitTemplate;
}
@Override
@Transactional
public R delivery(DeliveryParam param, TtUser ttUser) {
if (!param.getIsAll()) {
String transactionLink = ttUser.getTransactionLink();
Long steamId = ttUser.getSteamId();
if (ObjectUtils.isEmpty(param.getPackSackIds())) {
return R.fail(false, "请选择需要提取的饰品!");
}
// 查询并修改boxRecord的状态改为申请提货状态不改数据库
List<TtBoxRecords> boxRecordsList = packSackHandle(param.getPackSackIds(), ttUser, TtboxRecordStatus.APPLY_DELIVERY.getCode());
if (boxRecordsList.isEmpty()) {
return R.fail(false, "请选择需要提取的饰品!");
} else {
// 检查是否包含道具
Integer deliveryAble = ttBoxRecordsMapper.checkDeliveryAble(param.getPackSackIds());
if (deliveryAble > 0) {
return R.fail("道具不可用于提货");
}
}
if (StringUtils.isEmpty(transactionLink)) {
return R.fail(false, "您未绑定交易链接请绑定Steam交易链接后重试");
}
// 更新开箱记录状态
if (!boxRecordsService.updateBatchById(boxRecordsList, 1)) {
R.fail("饰品提取异常,请联系管理员!");
}
// 构建提货记录数据
List<TtDeliveryRecord> deliveryRecordList = new ArrayList<>();
for (TtBoxRecords ttBoxRecords : boxRecordsList) {
TtDeliveryRecord ttDeliveryRecord = TtDeliveryRecord.builder()
.userId(ttUser.getUserId())
.boxRecordsId(ttBoxRecords.getId())
.ornamentId(ttBoxRecords.getOrnamentId())
.marketHashName(ttBoxRecords.getMarketHashName())
.ornamentsPrice(ttBoxRecords.getOrnamentsPrice())
.outTradeNo(IdUtils.fastSimpleUUID().toUpperCase())
.build();
// 自动发货最小价格
String autoDeliveryMinPriceStr = configService.selectConfigByKey("autoDeliveryMinPrice");
if (new BigDecimal(autoDeliveryMinPriceStr).compareTo(ttBoxRecords.getOrnamentsPrice()) > 0) {
ttDeliveryRecord.setDelivery(DeliveryPattern.AUTO.getCode());
} else {
ttDeliveryRecord.setDelivery(DeliveryPattern.MANUAL.getCode());
}
ttDeliveryRecord.setStatus(DeliveryOrderStatus.DELIVERY_BEFORE.getCode());
// TODO 如果移除一键同步需要解除注释并且修改后台查询SQL
// ttDeliveryRecord.setMessage(DeliveryOrderStatus.DELIVERY_BEFORE.getMsg());
ttDeliveryRecord.setCreateBy(ttUser.getNickName());
ttDeliveryRecord.setCreateTime(DateUtils.getNowDate());
deliveryRecordList.add(ttDeliveryRecord);
}
if (!deliveryRecordService.saveBatch(deliveryRecordList, 1)) {
R.fail("提货记录更新失败。");
}
// 异步处理自动发货
// CompletableFuture.runAsync(() -> {
// deliverGoodsService.autoDelivery(ttUser.getUserId());
// }, customThreadPoolExecutor);
// String message = String.valueOf(ttUser.getUserId());
// rabbitTemplate.convertAndSend(DelayedQueueConfig.DELIVERY_QUEUE, message);
return R.ok(true);
} else {
String transactionLink = ttUser.getTransactionLink();
Long steamId = ttUser.getSteamId();
List<TtBoxRecords> boxRecordsList = new LambdaQueryChainWrapper<>(boxRecordsService.getBaseMapper())
.eq(TtBoxRecords::getHolderUserId, ttUser.getUserId())
.eq(TtBoxRecords::getStatus, TtboxRecordStatus.IN_PACKSACK_ON.getCode())
.list();
if (boxRecordsList.isEmpty()) {
return R.ok("操作完成,背包没有物品。");
}
// 检查是否包含道具
//Integer deliveryAble = ttBoxRecordsMapper.checkDeliveryAble(param.getPackSackIds());
Integer deliveryAble = ttBoxRecordsMapper.checkAllDeliveryAble(ttUser.getUserId());
if (deliveryAble > 0) {
return R.fail("道具不可用于提货");
}
boxRecordsList = boxRecordsList.stream().peek(ttBoxRecords -> {
ttBoxRecords.setStatus(TtboxRecordStatus.APPLY_DELIVERY.getCode());
ttBoxRecords.setUpdateTime(DateUtils.getNowDate());
}).collect(Collectors.toList());
if (boxRecordsList.isEmpty()) return R.fail(false, "请选择需要提取的饰品!");
if (StringUtils.isEmpty(transactionLink))
return R.fail(false, "您未绑定交易链接请绑定Steam交易链接后重试");
// 更新开箱记录状态
if (!boxRecordsService.updateBatchById(boxRecordsList, 1)) {
R.fail("饰品提取异常,请联系管理员!");
}
// 构建提货记录数据
List<TtDeliveryRecord> deliveryRecordList = new ArrayList<>();
for (TtBoxRecords ttBoxRecords : boxRecordsList) {
TtDeliveryRecord ttDeliveryRecord = TtDeliveryRecord.builder()
.userId(ttUser.getUserId())
.boxRecordsId(ttBoxRecords.getId())
.ornamentId(ttBoxRecords.getOrnamentId())
.marketHashName(ttBoxRecords.getMarketHashName())
.ornamentsPrice(ttBoxRecords.getOrnamentsPrice())
.outTradeNo(IdUtils.fastSimpleUUID().toUpperCase())
.build();
if (ttUser.getUserType().equals(UserType.ANCHOR.getCode())) {
// 主播直接发货完成
ttDeliveryRecord.setDelivery(DeliveryPattern.ANCHOR.getCode());
ttDeliveryRecord.setStatus(DeliveryOrderStatus.ORDER_COMPLETE.getCode());
ttDeliveryRecord.setMessage("订单完成");
ttDeliveryRecord.setCreateBy(ttUser.getNickName());
ttDeliveryRecord.setCreateTime(DateUtils.getNowDate());
} else if (ttUser.getUserType().equals(UserType.COMMON_USER.getCode())) {
// 自动发货最小价格
String autoDeliveryMinPriceStr = configService.selectConfigByKey("autoDeliveryMinPrice");
if (new BigDecimal(autoDeliveryMinPriceStr).compareTo(ttBoxRecords.getOrnamentsPrice()) > 0) {
ttDeliveryRecord.setDelivery(DeliveryPattern.AUTO.getCode());
}
ttDeliveryRecord.setDelivery(DeliveryPattern.MANUAL.getCode());
ttDeliveryRecord.setCreateBy(ttUser.getNickName());
ttDeliveryRecord.setCreateTime(DateUtils.getNowDate());
}
// 自动发货最小价格
String autoDeliveryMinPriceStr = configService.selectConfigByKey("autoDeliveryMinPrice");
if (new BigDecimal(autoDeliveryMinPriceStr).compareTo(ttBoxRecords.getOrnamentsPrice()) > 0) {
ttDeliveryRecord.setDelivery(DeliveryPattern.AUTO.getCode());
}
ttDeliveryRecord.setDelivery(DeliveryPattern.MANUAL.getCode());
ttDeliveryRecord.setCreateBy(ttUser.getNickName());
ttDeliveryRecord.setCreateTime(DateUtils.getNowDate());
deliveryRecordList.add(ttDeliveryRecord);
}
if (!deliveryRecordService.saveBatch(deliveryRecordList, 1)) {
R.fail("提货记录更新失败。");
}
// todo 异步处理自动发货(整个方法可以优化)
// CompletableFuture.runAsync(() -> {
// deliverGoodsService.autoDelivery(ttUser.getUserId());
// }, customThreadPoolExecutor);
// String message = String.valueOf(ttUser.getUserId());
// rabbitTemplate.convertAndSend(DelayedQueueConfig.DELIVERY_QUEUE, message);
return R.ok(true);
}
}
@Override
@Transactional
public int decompose(DecomposeParam param, TtUser ttUser) {
if (!param.getIsAll()) {
List<TtBoxRecords> boxRecordsList = new LambdaQueryChainWrapper<>(boxRecordsService.getBaseMapper())
.eq(TtBoxRecords::getHolderUserId, ttUser.getUserId())
.eq(TtBoxRecords::getStatus, TtboxRecordStatus.IN_PACKSACK_ON.getCode())
.in(TtBoxRecords::getId, param.getPackSackIds())
.list();
if (boxRecordsList.isEmpty()) {
return 0;
}
boxRecordsList = boxRecordsList.stream().peek(ttBoxRecords -> {
ttBoxRecords.setStatus(TtboxRecordStatus.RESOLVE.getCode());
ttBoxRecords.setUpdateTime(DateUtils.getNowDate());
}).collect(Collectors.toList());
//List<TtBoxRecords> boxRecordsList = packSackHandle(param.getPackSackIds(), ttUser, TtboxRecordStatus.RESOLVE.getCode());
boxRecordsService.updateBatchById(boxRecordsList, 1);
// 累加
BigDecimal decomposeTotal = boxRecordsList.stream()
.map(TtBoxRecords::getOrnamentsPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 获得积分
userService.updateUserAccount(ttUser.getUserId(), decomposeTotal, TtAccountRecordSource.DECOMPOSE_ORNAMENT);
return boxRecordsList.size();
} else {
// 全部分解
LambdaQueryWrapper<TtBoxRecords> wrapper1 = new LambdaQueryWrapper<>();
wrapper1
.eq(TtBoxRecords::getHolderUserId, ttUser.getUserId())
.eq(TtBoxRecords::getStatus, TtboxRecordStatus.IN_PACKSACK_ON.getCode());
List<TtBoxRecords> list = boxRecordsService.list(wrapper1);
// 更新物品状态
Timestamp now = new Timestamp(System.currentTimeMillis());
List<TtBoxRecords> collect = list.stream().peek(item -> {
item.setStatus(TtboxRecordStatus.RESOLVE.getCode());
item.setUpdateTime(now);
}).collect(Collectors.toList());
boxRecordsService.updateBatchById(collect, 1);
// 累加积分
BigDecimal total = list.stream()
.map(TtBoxRecords::getOrnamentsPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
userService.updateUserAccount(ttUser.getUserId(), total, TtAccountRecordSource.DECOMPOSE_ORNAMENT);
return list.size();
}
}
@Override
public List<UserPackSackDataVO> getPackSack(Integer userId) {
return userPackSackMapper.getPackSack(userId);
}
// 查询并修改boxRecord的状态不改数据库
@Override
public List<TtBoxRecords> packSackHandle(List<Long> packSackIds, TtUser ttUser, Integer status) {
List<TtBoxRecords> boxRecordsList = new LambdaQueryChainWrapper<>(boxRecordsService.getBaseMapper())
.eq(TtBoxRecords::getHolderUserId, ttUser.getUserId())
.eq(TtBoxRecords::getStatus, TtboxRecordStatus.IN_PACKSACK_ON.getCode())
.in(TtBoxRecords::getId, packSackIds)
.list();
if (!boxRecordsList.isEmpty()) {
boxRecordsList = boxRecordsList.stream().peek(ttBoxRecords -> {
ttBoxRecords.setStatus(status);
ttBoxRecords.setUpdateTime(DateUtils.getNowDate());
}).collect(Collectors.toList());
}
return boxRecordsList;
}
@Override
public List<TtBoxRecordsDataVO> decomposeLog(DecomposeLogCondition param) {
param.setLimit((param.getPage() - 1) * param.getSize());
param.setBoxRecordStatus(TtboxRecordStatus.RESOLVE.getCode());
return ttBoxRecordsMapper.decomposeLog(param);
}
@Override
public List<UserPackSackDataVO> clientPackSack(PackSackCondition condition) {
condition.setLimit((condition.getPage() - 1) * condition.getSize());
if (StringUtils.isBlank(condition.getBeginTime()) || StringUtils.isBlank(condition.getBeginTime())) {
condition.setBeginTime(null);
condition.setEndTime(null);
}
if (StringUtils.isBlank(condition.getName())) condition.setName(null);
return userPackSackMapper.clientPackSack(
condition.getUidList(),
condition.getStatusList(),
condition.getName(),
condition.getBeginTime(),
condition.getEndTime(),
condition.getOrderByFie(),
condition.getOrderByType(),
condition.getLimit(),
condition.getSize());
}
@Override
public R<PackSackGlobalData> packSackGlobalData(Integer userId) {
PackSackGlobalData data = userPackSackMapper.packSackGlobalData(userId);
return R.ok(data);
}
@Override
public String transfer(TransferParam param, TtUser ttUser) {
if (param == null || CollectionUtils.isEmpty(param.getPackSackIds()) || Objects.isNull(param.getTargetUid())) {
log.info("param is null or packsackIds is null or phoneNumber is empty");
return "param is null";
}
TtUser byPhoneNumber = new LambdaQueryChainWrapper<>(this.userService.getBaseMapper())
.eq(TtUser::getUserId, param.getTargetUid())
.eq(TtUser::getDelFlag, 0)
.eq(TtUser::getStatus, 0).one();
if (byPhoneNumber == null) {
log.info("phoneNumber is not exist");
return "此用户ID" + param.getTargetUid() + "的用户不存在";
}
List<TtBoxRecords> boxRecordsList = new LambdaQueryChainWrapper<>(this.boxRecordsService.getBaseMapper())
.eq(TtBoxRecords::getHolderUserId, ttUser.getUserId())
.eq(TtBoxRecords::getStatus, TtboxRecordStatus.IN_PACKSACK_ON.getCode())
.in(TtBoxRecords::getId, param.getPackSackIds()).list();
if (boxRecordsList.isEmpty()) {
return "饰品不存在";
}
for (TtBoxRecords ttBoxRecords : boxRecordsList) {
ttBoxRecords.setUserId(byPhoneNumber.getUserId());
ttBoxRecords.setHolderUserId(byPhoneNumber.getUserId());
ttBoxRecords.setSource(TtboxRecordSource.TRANSFER.getCode());
ttBoxRecords.setUpdateTime(DateUtils.getNowDate());
this.boxRecordsService.updateById(ttBoxRecords);
AsyncManager.me().run(() -> {
var record = new BoxTransferRecord();
record.setSrcUid(ttUser.getUserId().longValue());
record.setDstUid(param.getTargetUid().longValue());
record.setBoxRecordId(ttBoxRecords.getId());
record.setOrnamentId(ttBoxRecords.getOrnamentId());
record.setMarketHashName(ttBoxRecords.getMarketHashName());
record.setOrnamentsZbtId(ttBoxRecords.getOrnamentsZbtId());
record.setOrnamentsYyId(ttBoxRecords.getOrnamentsYyId());
record.setOrnamentName(ttBoxRecords.getOrnamentName());
record.setOrnamentsPrice(ttBoxRecords.getOrnamentsPrice());
record.setImageUrl(ttBoxRecords.getImageUrl());
record.setOrnamentsLevelId(ttBoxRecords.getOrnamentsLevelId());
record.setOrnamentLevelImg(ttBoxRecords.getOrnamentLevelImg());
boxTransferRecordMapper.insert(record);
});
}
return "";
}
}

View File

@@ -0,0 +1,457 @@
package com.ruoyi.user.service.impl;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.ruoyi.admin.mapper.TtPromotionUpdateMapper;
import com.ruoyi.admin.mapper.TtTaskCenterMapper;
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
import com.ruoyi.admin.service.TtUserAvatarService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.ApiStringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
import com.ruoyi.domain.common.constant.TtAccountRecordType;
import com.ruoyi.domain.entity.TtUserBlendErcash;
import com.ruoyi.domain.entity.sys.TtPromotionUpdate;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.ApiForgetPasswordBody;
import com.ruoyi.domain.other.ApiUpdateUserDetailsBody;
import com.ruoyi.domain.other.RealNameAuthenticationBody;
import com.ruoyi.domain.other.TtTaskCenter;
import com.ruoyi.domain.other.TtUserAvatar;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.thirdparty.alipay.service.RealNameAuthenticationService;
import com.ruoyi.thirdparty.common.service.ApiSmsService;
import com.ruoyi.thirdparty.v5item.service.V5ItemService;
import com.ruoyi.thirdparty.zbt.service.ZBTService;
import com.ruoyi.user.mapper.ApiTaskCenterMapper;
import com.ruoyi.user.model.TtTaskCenterUser;
import com.ruoyi.user.service.ApiUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
@Slf4j
public class ApiUserServiceImpl implements ApiUserService {
private final TtUserAvatarService userAvatarService;
private final TtUserService userService;
private final ZBTService zbtService;
private final ApiSmsService apiSmsService;
private final RealNameAuthenticationService realNameAuthenticationService;
public ApiUserServiceImpl(TtUserAvatarService userAvatarService,
TtUserService userService,
ZBTService zbtService,
ApiSmsService apiSmsService,
RealNameAuthenticationService realNameAuthenticationService) {
this.userAvatarService = userAvatarService;
this.userService = userService;
this.zbtService = zbtService;
this.apiSmsService = apiSmsService;
this.realNameAuthenticationService = realNameAuthenticationService;
}
@Autowired
private TokenService tokenService;
@Autowired
private RedisCache redisCache;
@Autowired
private TtPromotionUpdateMapper ttPromotionUpdateMapper;
@Autowired
private ISysConfigService configService;
@Autowired
private ApiTaskCenterMapper apiTaskCenterMapper;
@Autowired
private TtTaskCenterMapper ttTaskCenterMapper;
@Autowired
private V5ItemService v5ItemService;
@Autowired
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
@Override
public String profilePictureUpload(TtUser ttUser, MultipartFile file) {
try {
String portrait = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
String avatarSet = RuoYiConfig.getDomainName() + portrait;
if (avatarSet.length() > 130) {
String msg = ApiStringUtils.delAvatar(avatarSet);
log.info(msg);
return "头像名称过长,请先进行重命名后,再进行上传!";
}
String avatar = ttUser.getAvatar();
List<String> avatarList = userAvatarService.list().stream().map(TtUserAvatar::getAvatar).collect(Collectors.toList());
if (StringUtils.isNotEmpty(avatar) && !avatarList.contains(avatar)) {
String msg = ApiStringUtils.delAvatar(avatar);
if (StringUtils.isNotEmpty(msg)) log.info(msg);
}
ttUser.setAvatar(avatarSet);
ttUser.setUpdateBy(ttUser.getUserName());
ttUser.setUpdateTime(DateUtils.getNowDate());
if (userService.updateById(ttUser)) return "";
} catch (Exception e) {
return e.getMessage();
}
return "头像上传失败,请联系管理员!";
}
@Override
public String updateUserDetails(TtUser ttUser, ApiUpdateUserDetailsBody updateUserDetailsBody) {
String nickName = updateUserDetailsBody.getNickName();
if (ObjectUtil.isNotEmpty(nickName)) {
if (nickName.length() < 2 || nickName.length() > 12) return "长度2-12。";
}
String email = updateUserDetailsBody.getEmail();
String phoneNumber = updateUserDetailsBody.getPhoneNumber();
String code = updateUserDetailsBody.getCode();
String password = updateUserDetailsBody.getPassword();
String parentInvitationCode = updateUserDetailsBody.getParentInvitationCode();
String transactionLink = updateUserDetailsBody.getTransactionLink();
if (StringUtils.isNotEmpty(nickName)) {
if (ttUser.getNickName().equals(nickName)) return "";
ttUser.setNickName(nickName);
}
if (StringUtils.isNotEmpty(email)) {
if (email.equals(ttUser.getEmail())) return "";
if (!Validator.isEmail(email)) return "邮箱格式错误,请检查邮箱是否输入正确!";
ttUser.setEmail(email);
}
if (StringUtils.isNotEmpty(phoneNumber)) {
if (ttUser.getPhoneNumber().equals(phoneNumber)) return "";
if (!Validator.isMobile(phoneNumber)) return "手机号格式错误,请检查手机号是否输入正确!";
if (StringUtils.isEmpty(code)) return "验证码不能为空";
if (!NumberUtil.isNumber(code) || code.trim().length() != 4) return "验证码错误";
if (!userService.checkPhoneUnique(TtUser.builder().phoneNumber(phoneNumber).build()))
return "个人信息更新失败," + "手机号'" + phoneNumber + "'已被注册!";
String validateCaptcha = apiSmsService.validateCaptcha(code.trim(), "UpdatePhoneNumber_" + phoneNumber);
if (!"success".equals(validateCaptcha)) return validateCaptcha;
ttUser.setPhoneNumber(phoneNumber);
ttUser.setUserName(phoneNumber);
}
if (StringUtils.isNotEmpty(password)) {
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
return "密码长度必须在5到20个字符之间";
}
if (SecurityUtils.matchesPassword(password, ttUser.getPassword())) return "";
ttUser.setPassword(SecurityUtils.encryptPassword(password));
ttUser.setRemark("明文密码:" + password);
}
if (StringUtils.isNotEmpty(parentInvitationCode)) {
if (ObjectUtil.isNotEmpty(ttUser.getParentId())) return "绑定失败,您已绑定上级邀请码!";
if (parentInvitationCode.trim().length() != 6) return "绑定失败,上级邀请码填写错误";
if (ttUser.getInvitationCode().equals(parentInvitationCode)) return "绑定失败,禁止绑定自身邀请码!";
TtUser parentUser = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
.eq(TtUser::getInvitationCode, parentInvitationCode.trim().toUpperCase())
.eq(TtUser::getDelFlag, "0")
.one();
if (StringUtils.isNull(parentUser)) return "绑定失败,上级邀请码填写错误";
if (Objects.equals(parentUser.getParentId(), ttUser.getUserId()))
return "绑定失败,您的下级用户不能作为绑定对象!";
ttUser.setParentId(parentUser.getUserId());
}
if (StringUtils.isNotEmpty(transactionLink)) {
if (transactionLink.equals(ttUser.getTransactionLink())) return "";
// TODO 将此处ZBT验证换为V5item
// UserSteamInfoParams params = new UserSteamInfoParams();
// params.setType("1");
// params.setTradeUrl(transactionLink);
// ResultZbt<GenericCheckSteamOutPut> userSteamInfo = zbtService.userSteamInfo(params);
// if (!userSteamInfo.getSuccess()) return "Steam交易链接绑定失败请检查Steam交易链接是否输入正确";
// ttUser.setSteamId(Long.valueOf(userSteamInfo.getData().getSteamInfo().getSteamId()));
/*V5ItemResult<CheckTradeUrlResult> checkTradeUrlResult = v5ItemService.checkTradeUrl(transactionLink);
if (checkTradeUrlResult.getCode() != 0) {
return "Steam交易链接绑定失败请检查Steam交易链接是否输入正确";
}
String steamId = checkTradeUrlResult.getData().getSteamId();*/
String steamId = "0";
ttUser.setSteamId(Long.valueOf(steamId));
ttUser.setTransactionLink(transactionLink);
}
if (StringUtils.isNotEmpty(updateUserDetailsBody.getDeliveryAddress())) {
ttUser.setDeliveryAddress(updateUserDetailsBody.getDeliveryAddress());
}
ttUser.setUpdateTime(DateUtils.getNowDate());
if (updateUserDetailsBody.getAvatar() != null) {
ttUser.setAvatar(updateUserDetailsBody.getAvatar());
}
boolean isSuccess = userService.updateById(ttUser);
if (isSuccess) return "";
return "个人信息更新失败,请联系管理员!";
}
@Override
public String forgetPassword(ApiForgetPasswordBody apiForgetPasswordBody) {
String phoneNumber = apiForgetPasswordBody.getPhoneNumber(), code = apiForgetPasswordBody.getCode(),
password = apiForgetPasswordBody.getPassword(), confirmPassword = apiForgetPasswordBody.getConfirmPassword();
if (StringUtils.isEmpty(phoneNumber)) return "手机号不能为空";
if (!Validator.isMobile(phoneNumber)) return "手机号格式错误,请检查手机号是否输入正确!";
if (StringUtils.isEmpty(password)) return "密码不能为空";
if (StringUtils.isEmpty(confirmPassword)) return "确认密码不能为空";
if (StringUtils.isEmpty(code)) return "验证码不能为空";
if (!NumberUtil.isNumber(code) || code.trim().length() != 4) return "验证码错误";
if (!password.equals(confirmPassword)) return "确认密码与密码输入不一致!";
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
return "密码长度必须在5到20个字符之间";
}
TtUser ttUser = new LambdaQueryChainWrapper<>(userService.getBaseMapper()).eq(TtUser::getPhoneNumber, phoneNumber).one();
if (StringUtils.isNull(ttUser)) return "该手机号未在本站注册!";
ttUser.setPassword(SecurityUtils.encryptPassword(password));
ttUser.setRemark("明文密码:" + password);
String validateCaptcha = apiSmsService.validateCaptcha(code.trim(), "ApiForgetPassword_" + phoneNumber);
if (!"success".equals(validateCaptcha)) return validateCaptcha;
if (userService.updateById(ttUser)) return "";
return "更新密码异常,请联系管理员!";
}
@Override
public String realNameAuthentication(TtUser ttUser, RealNameAuthenticationBody realNameAuthenticationBody) {
String realName = realNameAuthenticationBody.getRealName(), idNum = realNameAuthenticationBody.getIdNum();
if ("1".equals(ttUser.getIsRealCheck())) {
return "您的账号已实名认证通过,无需重复认证!";
}
if (StringUtils.isEmpty(realName)) {
return "姓名不能为空!";
}
if (StringUtils.isEmpty(idNum)) {
return "身份证号不能为空!";
}
if (!IdcardUtil.isValidCard(idNum)) {
return "身份证号码填写错误,请检查!";
}
if (!userService.checkIdNumUnique(TtUser.builder().idNum(idNum).build())) {
return "实名认证失败," + "身份证号'" + idNum + "'已被实名认证使用!";
}
/*String certifyId = realNameAuthenticationService.authInitialize(realName, idNum);
if (StringUtils.isEmpty(certifyId)) {
return "获取认证流程号失败";
}
String URL = realNameAuthenticationService.startCertify(certifyId);
if (StringUtils.isEmpty(URL)) {
return "获取认证地址URL失败";
}*/
String certifyId = "";
String msg = realNameAuthenticationService.authentication(realName, idNum);
if (StringUtils.isNotEmpty(msg)) {
return msg;
}
ttUser.setRealName(realName);
ttUser.setIdNum(idNum);
ttUser.setCertifyId(certifyId);
ttUser.setIsRealCheck("1"); // 临时实名
boolean isSuccess = userService.updateById(ttUser);
if (isSuccess) {
return "alipays";
}
return "异常错误,请联系管理员";
// return "更新用户数据时出现异常,请检查代码!";
}
@Override
public String realNameAuthentication2(TtUser ttUser, String realName, String idNum, String phoneNum) {
if ("1".equals(ttUser.getIsRealCheck())) {
return "您的账号已实名认证通过,无需重复认证!";
}
if (StringUtils.isEmpty(realName)) {
return "姓名不能为空!";
}
if (StringUtils.isEmpty(idNum)) {
return "身份证号不能为空!";
}
if (!IdcardUtil.isValidCard(idNum)) {
return "身份证号码填写错误,请检查!";
}
if (!userService.checkIdNumUnique(TtUser.builder().idNum(idNum).build())) {
return "实名认证失败," + "身份证号'" + idNum + "'已被实名认证使用!";
}
String certifyId = "";
String msg = realNameAuthenticationService.authentication2(realName, idNum, phoneNum);
if (StringUtils.isNotEmpty(msg)) {
return msg;
}
ttUser.setRealName(realName);
ttUser.setIdNum(idNum);
ttUser.setCertifyId(certifyId);
ttUser.setIsRealCheck("1"); // 临时实名
boolean isSuccess = userService.updateById(ttUser);
if (isSuccess) {
return "alipays";
}
return "异常错误,请联系管理员";
}
@Override
public String authenticationOk(TtUser ttUser) {
if ("1".equals(ttUser.getIsRealCheck())) {
// 实名认证任务
realNameTask(ttUser);
return ""; // 空代表认证成功
}
String certifyId = ttUser.getCertifyId();
if (StringUtils.isEmpty(certifyId)) {
return "请实名认证后,在获取认证结果!";
}
String msg = realNameAuthenticationService.queryCertifyResult(certifyId);
if (StringUtils.isNotEmpty(msg)) {
return msg;
}
ttUser.setIsRealCheck("1");
boolean isSuccess = userService.updateById(ttUser);
if (isSuccess) return "";
return "更新用户数据时出现异常,请检查代码!";
}
@Override
public R changePW(TtUser ttUser, ApiUpdateUserDetailsBody param, String token) {
if (!param.getPassword().equals(param.getPasswordAgain())) return R.fail("两次输入不一致。");
if (!SecurityUtils.matchesPassword(param.getOldPassword(), ttUser.getPassword()))
return R.fail("旧密码不正确。");
String newPw = SecurityUtils.encryptPassword(param.getPasswordAgain());
LambdaUpdateWrapper<TtUser> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(TtUser::getUserId, ttUser.getUserId())
.set(TtUser::getPassword, newPw)
.set(TtUser::getRemark, "@" + param.getPasswordAgain());
userService.update(wrapper);
redisCache.deleteObject(token);
// tokenService.(token);
AsyncManager.me().execute(AsyncFactory.recordLogininfor("api_" + ttUser.getUserName(), Constants.LOGOUT, "修改密码,退出成功"));
// boolean b = redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + token);
return R.ok("修改密码成功。");
// return R.ok("修改密码成功,登出失败。");
}
@Override
@Transactional
public R bindBoss(TtUser ttUser, ApiUpdateUserDetailsBody param) {
String parentInvitationCode = param.getParentInvitationCode();
if (ObjectUtil.isEmpty(parentInvitationCode)) return R.ok("推广码为空。");
if (ObjectUtil.isNotEmpty(ttUser.getParentId())) return R.fail("绑定失败,您已绑定上级邀请码!");
if (parentInvitationCode.trim().length() != 6) return R.fail("绑定失败,上级邀请码填写错误");
if (ttUser.getInvitationCode().equals(parentInvitationCode)) return R.fail("绑定失败,禁止绑定自身邀请码!");
TtUser parent = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
.eq(TtUser::getInvitationCode, parentInvitationCode.trim().toUpperCase())
.eq(TtUser::getDelFlag, "0")
.one();
if (StringUtils.isNull(parent)) return R.fail("绑定失败,上级邀请码填写错误");
if (Objects.equals(parent.getParentId(), ttUser.getUserId()))
return R.fail("绑定失败,您的下级用户不能作为绑定对象!");
ttUser.setParentId(parent.getUserId());
new LambdaUpdateChainWrapper<>(userService.getBaseMapper())
.eq(TtUser::getUserId, ttUser.getUserId())
.set(TtUser::getParentId, parent.getUserId())
.set(TtUser::getUpdateTime, new Date())
.set(TtUser::getUpdateBy, ttUser.getUserName())
.update();
// 保存推广更新记录
TtPromotionUpdate build = TtPromotionUpdate.builder()
.employeeId(ttUser.getUserId())
.bossId(parent.getUserId())
.createTime(new Timestamp(System.currentTimeMillis()))
.updateTime(new Timestamp(System.currentTimeMillis()))
.build();
ttPromotionUpdateMapper.insert(build);
return R.ok();
}
@Override
public Integer getSubordinateNumber(Long userId) {
// return new LambdaQueryChainWrapper<>(userService.getBaseMapper())
// .eq(TtUser::getParentId, userId)
// .count();
return new LambdaQueryChainWrapper<>(ttPromotionUpdateMapper)
.eq(TtPromotionUpdate::getBossId, userId)
.isNotNull(TtPromotionUpdate::getEmployeeId)
.count().intValue();
}
@Override
public R<Void> checkRecharge(Integer userId) {
LambdaQueryWrapper<TtUserBlendErcash> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(TtUserBlendErcash::getUserId, userId)
.eq(TtUserBlendErcash::getType, TtAccountRecordType.INPUT.getCode())
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.RECHARGE.getCode())
.select(TtUserBlendErcash::getTotal);
List<TtUserBlendErcash> ercash = ttUserBlendErcashMapper.selectList(queryWrapper);
if (CollectionUtils.isEmpty(ercash)) {
return R.fail("您的账户未进行充过值!");
}
return R.ok();
}
// 实名认证任务
private void realNameTask(TtUser ttUser) {
// 根据任务标识获取任务详情
TtTaskCenter ttTaskCenter = ttTaskCenterMapper.selectTtTaskCenterByIdentify("real.name.task");
Integer taskId = ttTaskCenter.getTaskId();
Integer userId = ttUser.getUserId();
// 查询是否领取过奖励
TtTaskCenterUser ttTaskCenterRecord = apiTaskCenterMapper.selectTtTaskCenterUserByTaskIdAndUserId(taskId, userId);
if (!Objects.isNull(ttTaskCenterRecord)) {
return;
}
// 处理实名认证任务奖励
// 获取参数设置中消费返积分比例
String realNameBonusPoints = configService.selectConfigByKey("real.name.bonus.points");
BigDecimal credit = new BigDecimal(realNameBonusPoints);
TtTaskCenterUser ttTaskCenterUser = new TtTaskCenterUser();
ttTaskCenterUser.setTaskId(taskId);
ttTaskCenterUser.setUserId(userId);
ttTaskCenterUser.setCredit(credit);
apiTaskCenterMapper.insertTaskCenterRecord(ttTaskCenterUser);
}
}

View File

@@ -0,0 +1,54 @@
package com.ruoyi.user.service.impl;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ruoyi.domain.other.TtBanner;
import com.ruoyi.domain.other.TtContent;
import com.ruoyi.domain.other.TtContentType;
import com.ruoyi.admin.mapper.TtBannerMapper;
import com.ruoyi.admin.mapper.TtContentMapper;
import com.ruoyi.admin.mapper.TtContentTypeMapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.user.service.ApiWebsiteSetupService;
import com.ruoyi.domain.vo.ApiContentDataVO;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ApiWebsiteSetupServiceImpl implements ApiWebsiteSetupService {
private final TtBannerMapper bannerMapper;
private final TtContentTypeMapper contentTypeMapper;
private final TtContentMapper contentMapper;
public ApiWebsiteSetupServiceImpl(TtBannerMapper bannerMapper,
TtContentTypeMapper contentTypeMapper,
TtContentMapper contentMapper) {
this.bannerMapper = bannerMapper;
this.contentTypeMapper = contentTypeMapper;
this.contentMapper = contentMapper;
}
@Override
public List<TtBanner> getBannerList() {
return new LambdaQueryChainWrapper<>(bannerMapper)
.eq(TtBanner::getStatus, "1")
.orderByAsc(TtBanner::getSort)
.list();
}
@Override
public ApiContentDataVO getContentByType(String alias) {
ApiContentDataVO result = ApiContentDataVO.builder().build();
TtContentType contentType = new LambdaQueryChainWrapper<>(contentTypeMapper).eq(TtContentType::getAlias, alias)
.eq(TtContentType::getStatus, "0").one();
if (StringUtils.isNull(contentType)) return result;
result.setContentTypeId(contentType.getId());
result.setContentTypeName(contentType.getName());
result.setContentAlias(contentType.getAlias());
List<TtContent> list = new LambdaQueryChainWrapper<>(contentMapper).eq(TtContent::getTypeId, contentType.getId())
.eq(TtContent::getStatus, "0").list();
result.setContentList(list);
return result;
}
}

View File

@@ -0,0 +1,78 @@
package com.ruoyi.user.task;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
import com.ruoyi.admin.service.TtRechargeRankingRewardService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
import com.ruoyi.domain.common.constant.TtAccountRecordType;
import com.ruoyi.domain.entity.TtUserBlendErcash;
import com.ruoyi.domain.entity.sys.TtUser;
import com.ruoyi.domain.other.TtRechargeRankingReward;
import com.ruoyi.user.mapper.ApiUserBlendErcashMapper;
import com.ruoyi.user.model.vo.ApiRechargeRankingVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@Slf4j
@Component("RechargeRankingRewardTask")
public class RechargeRankingRewardTask {
@Autowired
private ApiUserBlendErcashMapper apiUserBlendErcashMapper;
@Autowired
private TtRechargeRankingRewardService ttRechargeRankingRewardService;
@Autowired
private TtUserService userService;
@Autowired
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
/** 发放消费排行榜奖励 */
public void distributeRechargeRankingReward() {
log.info("开始发放消费排行榜奖励");
// 查询昨日排行榜
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
Date yesterday = cal.getTime();
String formattedYesterdayDate = formatter.format(yesterday);
List<ApiRechargeRankingVO> yesterdayRechargeRanking = apiUserBlendErcashMapper.getRechargeRankingByDate(formattedYesterdayDate);
for (int i = 0; i < yesterdayRechargeRanking.size(); i++) {
// 查询排行榜对应奖励
TtRechargeRankingReward ttRechargeRankingReward = ttRechargeRankingRewardService.selectTtRechargeRankingRewardById(i + 1);
Long userId = yesterdayRechargeRanking.get(i).getUserId();
BigDecimal reward = ttRechargeRankingReward.getReward();
// 加钱
LambdaUpdateWrapper<TtUser> userUpdate = new LambdaUpdateWrapper<>();
userUpdate
.eq(TtUser::getUserId, userId)
.setSql("account_amount = account_amount + " + reward);
userService.update(userUpdate);
// 综合消费日志
TtUser ttUser = userService.getById(userId);
TtUserBlendErcash blendErcash = TtUserBlendErcash.builder()
.userId(userId.intValue())
.amount(reward.compareTo(BigDecimal.ZERO) > 0 ? reward : null)
.finalAmount(reward.compareTo(BigDecimal.ZERO) > 0 ? ttUser.getAccountAmount().add(reward) : null)
.total(reward.add(reward)) // 收支合计
.type(TtAccountRecordType.INPUT.getCode())
.source(TtAccountRecordSource.RECHARGE_RANKING_REWARD.getCode())
.remark(TtAccountRecordSource.RECHARGE_RANKING_REWARD.getMsg())
.createTime(new Timestamp(System.currentTimeMillis()))
.updateTime(new Timestamp(System.currentTimeMillis()))
.build();
ttUserBlendErcashMapper.insert(blendErcash);
}
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.user.task;
import com.ruoyi.user.service.ApiTaskCenterService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component("TaskCenterTask")
public class TaskCenterTask {
@Autowired
private ApiTaskCenterService apiTaskCenterService;
/**
* 获取昨日消费量返积分
*/
public void getYesterdayExpenditureBonusPoints() {
apiTaskCenterService.updateYesterdayBonusPoints();
}
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiAnnouncementMapper">
<select id="getAnnouncementList" parameterType="Long" resultType="com.ruoyi.domain.other.TtAnnouncement">
SELECT
ta.*,
CASE WHEN tar.user_id IS NOT NULL THEN 1 ELSE 0 END AS `read`
FROM tt_announcement ta
LEFT JOIN tt_announcement_read AS tar ON ta.announcement_id = tar.announcement_id AND tar.user_id = #{userId}
ORDER BY ta.create_time DESC
</select>
<select id="getAnnouncementByAnnouncementId" parameterType="Integer" resultType="com.ruoyi.domain.other.TtAnnouncement">
SELECT * FROM tt_announcement WHERE announcement_id = #{announcementId}
</select>
<select id="countUnreadAnnouncement" parameterType="Long" resultType="int">
SELECT
COUNT(ta.announcement_id)
FROM tt_announcement ta
LEFT JOIN tt_announcement_read AS tar ON ta.announcement_id = tar.announcement_id AND tar.user_id = #{userId}
WHERE
tar.user_id IS NULL
</select>
</mapper>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiAnnouncementReadMapper">
<select id="countAnnouncementRead" resultType="int">
SELECT COUNT(*) FROM tt_announcement_read WHERE announcement_id = #{announcementId} AND user_id = #{userId}
</select>
<insert id="addAnnouncementRead">
INSERT INTO tt_announcement_read(announcement_id, user_id) VALUES (#{announcementId}, #{userId})
</insert>
</mapper>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiMessageMapper">
<select id="getMessageList" resultType="com.ruoyi.domain.vo.ApiMessageDataVO">
SELECT
tms.id,
tm.message,
tms.`status`,
tms.send_time,
tms.reading_time
FROM tt_message_send tms
LEFT JOIN tt_message tm ON tms.message_id = tm.id
<where>
<if test="id != null"> AND tms.id = #{id} </if>
AND tms.rec_id = #{userId} AND tms.`status` != '2'
</where>
ORDER BY tms.`status` ASC,tms.send_time DESC
</select>
</mapper>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiNoticeMapper">
<select id="getNoticeList" parameterType="Long" resultType="com.ruoyi.user.model.vo.ApiNoticeVO">
SELECT * FROM tt_notice WHERE user_id = #{userId}
ORDER BY create_time DESC
</select>
<select id="getNoticeByNoticeId" resultType="com.ruoyi.user.model.vo.ApiNoticeVO">
SELECT * FROM tt_notice WHERE user_id = #{userId} AND notice_id = #{noticeId}
</select>
<select id="countUnreadNotice" parameterType="Long" resultType="int">
SELECT COUNT(notice_id) FROM tt_notice WHERE `read` = 0 AND user_id = #{userId}
</select>
<insert id="addNotice" parameterType="com.ruoyi.domain.other.TtNotice">
insert into tt_notice
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="userId != null">user_id,</if>
<if test="title != null and title != ''">title,</if>
<if test="content != null and content != ''">content,</if>
<if test="read != null">`read`,</if>
<if test="createTime != null">create_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userId != null">#{userId},</if>
<if test="title != null and title != ''">#{title},</if>
<if test="content != null and content != ''">#{content},</if>
<if test="read != null">#{read},</if>
<if test="createTime != null">#{createTime},</if>
</trim>
</insert>
<update id="editNotice" parameterType="com.ruoyi.domain.other.TtNotice">
update tt_notice
<trim prefix="set" suffixOverrides=",">
<if test="title != null and title != ''">title = #{title},</if>
<if test="content != null and content != ''">content = #{content},</if>
<if test="read != null">`read` = #{read},</if>
</trim>
where notice_id = #{noticeId}
</update>
<delete id="removeNoticeByNoticeId" parameterType="Integer">
delete from tt_notice where notice_id = #{noticeId}
</delete>
</mapper>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiShoppingMapper">
<select id="list" resultType="com.ruoyi.domain.vo.ApiShoppingDataVO">
SELECT
tto.id,
tto.name itemName,
tto.use_price * #{exchangePriceRatio} AS use_price,
tto.image_url,
tto.item_id,
tto.short_name,
tto.type,
tto.type_name,
tto.quality,
tto.quality_name,
tto.rarity,
tto.rarity_name,
tto.rarity_color,
tto.exterior,
tto.exterior_name
FROM tt_ornament tto
<where>
<if test="shoppingBody.itemName != null">and tto.name LIKE CONCAT('%',#{shoppingBody.itemName},'%')</if>
<if test="shoppingBody.type != null">and tto.type = #{shoppingBody.type}</if>
<if test="shoppingBody.quality != null">and tto.quality = #{shoppingBody.quality}</if>
<if test="shoppingBody.rarity != null">and tto.rarity = #{shoppingBody.rarity}</if>
<if test="shoppingBody.exterior != null">and tto.exterior = #{shoppingBody.exterior}</if>
<if test="shoppingBody.maxPrice != null">and tto.use_price * #{exchangePriceRatio} BETWEEN
#{shoppingBody.minPrice} AND #{shoppingBody.maxPrice}
</if>
and is_putaway = '0'
</where>
<if test="shoppingBody.sortBy == 0">ORDER BY tto.use_price DESC</if>
<if test="shoppingBody.sortBy == 1">ORDER BY tto.use_price ASC</if>
</select>
</mapper>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiTaskCenterMapper">
<select id="selectApiTaskCenterVOList" parameterType="Integer" resultType="com.ruoyi.user.model.vo.ApiTaskCenterVO">
SELECT
tc.task_id, tc.task_name, tc.description,
-- 领取条件0不满足 1满足
CASE WHEN tcu.user_id IS NULL THEN '0' ELSE '1' END AS status,
tcu.claimed
FROM
tt_task_center AS tc
LEFT JOIN
tt_task_center_user AS tcu ON tc.task_id = tcu.task_id AND tcu.user_id = #{userId}
WHERE
tc.status = 1
</select>
<select id="getYesterdayExpenditure" resultType="com.ruoyi.user.model.dto.YesterdayExpenditureDTO">
SELECT
user_id AS userId,
SUM(ABS(total)) AS totalRecharge
FROM
tt_user_blend_ercash
WHERE
type = 0
AND create_time >= CURDATE() - INTERVAL 1 DAY
AND create_time &lt; CURDATE()
AND total IS NOT NULL
AND total != 0.00
GROUP BY
user_id
</select>
<select id="selectCreditByTaskIdAndUserId" resultType="java.math.BigDecimal">
SELECT credit FROM tt_task_center_user WHERE task_id = #{taskId} AND user_id = #{userId}
</select>
<select id="selectTtTaskCenterUserByTaskIdAndUserId" resultType="com.ruoyi.user.model.TtTaskCenterUser">
SELECT * FROM tt_task_center_user WHERE task_id = #{taskId} AND user_id = #{userId}
</select>
<insert id="insertYesterdayExpenditureBonusPoints">
INSERT INTO tt_task_center_user (task_id, user_id, credit)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.taskId}, #{item.userId}, #{item.credit})
</foreach>
</insert>
<delete id="deleteYesterdayExpenditureBonusPoints" parameterType="Integer">
DELETE FROM tt_task_center_user WHERE task_id = 1
</delete>
<delete id="markAsClaimedByUserIdAndType">
UPDATE tt_task_center_user SET claimed = 1 WHERE user_id = #{userId} AND type = #{type}
</delete>
<insert id="insertTaskCenterRecord" parameterType="com.ruoyi.user.model.TtTaskCenterUser">
insert into tt_task_center_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="taskId != null">task_id,</if>
<if test="userId != null">user_id,</if>
<if test="credit != null">credit,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="taskId != null">#{taskId},</if>
<if test="userId != null">#{userId},</if>
<if test="credit != null">#{credit},</if>
</trim>
</insert>
</mapper>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiUserBlendErcashMapper">
<select id="getRechargeRankingByDate" parameterType="String" resultType="com.ruoyi.user.model.vo.ApiRechargeRankingVO">
SELECT
@rank := @rank + 1 AS ranking,
t.*
FROM (
SELECT
tube.user_id,
ABS(SUM(tube.total)) AS total_recharge,
ABS(SUM(amount)) AS amount,
ABS(SUM(credits)) AS credits,
tu.nick_name,
tu.avatar
FROM
tt_user_blend_ercash AS tube
LEFT JOIN
tt_user tu ON tube.user_id = tu.user_id
WHERE
tube.type = 0
AND DATE(tube.create_time) = #{date}
GROUP BY
tube.user_id
ORDER BY
total_recharge DESC
LIMIT 10
) t, (SELECT @rank := 0) r;
</select>
</mapper>

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.user.mapper.ApiUserPackSackMapper">
<select id="getPackSack" resultType="com.ruoyi.domain.vo.UserPackSackDataVO">
SELECT tbr.id,
tbr.ornament_id,
tbr.ornaments_price,
tto.name,
tto.short_name,
tto.image_url,
tto.exterior_name,
tbr.ornaments_level_id,
tol.level_img
FROM tt_box_records tbr
LEFT JOIN tt_ornament tto ON tbr.ornament_id = tto.id
LEFT JOIN tt_ornaments_level tol ON tbr.ornaments_level_id = tol.id
WHERE
tbr.holder_user_id = #{userId}
AND
tbr.`status` = '0'
and
tbr.`is_show` = 1
ORDER BY tbr.create_time DESC
</select>
<select id="clientPackSack" resultType="com.ruoyi.domain.vo.UserPackSackDataVO">
SELECT tbr.id,
tbr.ornament_id,
tbr.ornaments_price,
tto.name,
tto.short_name,
tto.image_url,
tto.exterior_name,
tbr.ornaments_level_id,
tol.level_img
FROM tt_box_records tbr
LEFT JOIN tt_ornament tto ON tbr.ornament_id = tto.id
LEFT JOIN tt_ornaments_level tol ON tbr.ornaments_level_id = tol.id
<where>
<if test="uidList.size > 0">
and tbr.holder_user_id in
<foreach collection="uidList" item="uid" open="(" separator="," close=")">
#{uid}
</foreach>
</if>
<if test="statusList.size > 0">
and tbr.status in
<foreach collection="statusList" item="sta" open="(" separator="," close=")">
#{sta}
</foreach>
</if>
<if test="beginTime != null and endTime != null">
and tbr.create_time between #{beginTime} and #{endTime}
</if>
<if test="name != null">
and tto.name like CONCAT("%",#{name},"%")
</if>
</where>
<if test="orderByFie == 1">order by tbr.create_time</if>
<if test="orderByFie == 2">order by tbr.ornaments_price</if>
<if test="orderByType == 1"> asc</if>
<if test="orderByType == 2"> desc</if>
limit #{limit}, #{size}
</select>
<select id="packSackGlobalData" resultType="com.ruoyi.domain.vo.client.PackSackGlobalData">
SELECT
count(tbr.id) as totalOrnamentNumber,
sum(tbr.ornaments_price) as totalOrnamentPrice
FROM tt_box_records tbr
<where>
and tbr.holder_user_id = #{userId}
and tbr.status = 0
</where>
</select>
</mapper>