无关风月
2024-11-04 64f7ccb9ef8b5a0618e65cddc14b981c1f108ba3
xinquan-modules/xinquan-user/src/main/java/com/xinquan/user/controller/client/ClientAppUserController.java
@@ -1,15 +1,19 @@
package com.xinquan.user.controller.client;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xinquan.common.core.domain.R;
import com.xinquan.common.core.utils.WebUtils;
import com.xinquan.common.core.utils.page.BeanUtils;
import com.xinquan.common.core.utils.page.CollUtils;
import com.xinquan.common.core.utils.page.PageDTO;
import com.xinquan.common.core.web.domain.BaseModel;
import com.xinquan.common.security.service.TokenService;
import com.xinquan.common.security.utils.SecurityUtils;
import com.xinquan.course.api.domain.Course;
import com.xinquan.course.api.domain.CourseCategory;
@@ -19,10 +23,17 @@
import com.xinquan.system.api.RemoteUserService;
import com.xinquan.system.api.domain.*;
import com.xinquan.system.api.domain.vo.*;
import com.xinquan.system.api.model.LoginUser;
import com.xinquan.user.api.domain.dto.AppUserManagementDTO;
import com.xinquan.user.api.domain.dto.OrderListDTO;
import com.xinquan.user.api.domain.dto.UserChildDTO;
import com.xinquan.user.api.domain.vo.FreezingVO;
import com.xinquan.user.api.domain.vo.ViewReport;
import com.xinquan.user.domain.dto.UserAnswerDTO;
import com.xinquan.user.domain.dto.UserFreezingDTO;
import com.xinquan.user.domain.export.UserExport;
import com.xinquan.user.domain.export.UserInfoExport;
import com.xinquan.user.domain.export.WithdrawExport;
import com.xinquan.user.domain.vo.TagVO;
import com.xinquan.user.service.*;
import com.xinquan.user.utils.MailUtils;
@@ -35,10 +46,13 @@
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
@@ -47,6 +61,8 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -58,6 +74,8 @@
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import static com.xinquan.common.core.enums.TreeLevelEnum.TOWERING_TREES;
@@ -69,8 +87,6 @@
 * @author mitao
 * @since 2024-08-21
 */
@Api(tags = {"用户相关接口"})
@Slf4j
@RestController
@RequestMapping("/client/app-user")
@RequiredArgsConstructor
@@ -81,121 +97,274 @@
    private AppUserViewingHistoryService appUserViewingHistoryService;
    @Resource
    private AppUserEnergyRecordService appUserEnergyRecordService;
    @Resource
    private AppUserTagService appUserTagService;
    @Resource
    private TagService tagService;
    @Resource
    private AppUserTreeService appUserTreeService;
    @Resource
    private AppUserQuestionService appUserQuestionService;
    @Resource
    private TagService tagService;
    @Resource
    private RemoteBannerService remoteBannerService;
    @Resource
    private RemoteOrderService remoteOrderService;
    @Resource
    private RemoteUserService remoteUserService;
    public static void main(String[] args) {
        // 收件人电子邮箱,TODO 换成自己的收件箱
        String to = "443237572@qq.com";
        // 发件人电子邮箱,TODO 换成自己的发件箱
        String from = "13281306557@163.com";
        // 指定发送邮件的主机为
        String host = "smtp.163.com";
        Properties properties = new Properties();
        // 设置邮件服务器
        properties.setProperty("mail.smtp.host", host);
        // 邮件发送协议
        properties.setProperty("mail.transport.protocol", "smtp");
        //是否启用调试模式(启用调试模式可打印客户端与服务器交互过程时一问一答的响应消息)
        properties.setProperty("mail.debug","true");
        properties.setProperty("mail.smtp.auth", "true");
        // 获取默认session对象
        Session session = Session.getDefaultInstance(properties,new Authenticator(){
            @Override
            public PasswordAuthentication getPasswordAuthentication()
            {
                //发件人邮件用户名、授权码,换成自己的发件箱及授权码
                return new PasswordAuthentication("13281306557@163.com", "NUSdxDQqadYvVek2");
            }
        });
        // 获取当前年份
        int currentYear = LocalDate.now().getYear();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 获取1月份的第一天
        LocalDate firstDayOfMonth = LocalDate.of(currentYear, 2, 1);
        LocalDateTime firstDayOfMonthDateTime = firstDayOfMonth.atStartOfDay();
        try{
            // 创建默认的 MimeMessage 对象
            MimeMessage message = new MimeMessage(session);
            // Set From,设置发件人
            InternetAddress fromMail = new InternetAddress(from);
            //设置发件人名称,TODO 换成自己的发件箱
            fromMail.setPersonal(MimeUtility.encodeText("明星电力<13281306557@163.com>"));
            message.setFrom(fromMail);
            // Set To: 设置收件人
            InternetAddress toMail = new InternetAddress(to);
            // TODO 换成自己的收件箱
            InternetAddress toMail2 = new InternetAddress("443237572@qq.com");
            //发一个邮箱
//            message.setRecipient(Message.RecipientType.TO, toMail);
            //发多个邮箱
            Address[] allRecipients = {toMail, toMail2};
            message.setRecipients(Message.RecipientType.TO, allRecipients);
            // Set Subject: 邮件主体
            message.setSubject("明星电力");
            // 设置消息体
            message.setSentDate(new Date());
            // 指定为混合关系
            MimeMultipart msgMultipart = new MimeMultipart("mixed");
            message.setContent(msgMultipart);
            // 邮件信息组装
            //组装的顺序非常重要,一定要先组装文本域,再组装文件
            MimeBodyPart htmlPart = new MimeBodyPart();
            // 组装内容
            htmlPart.setContent("This is message content", "text/html;charset=UTF-8");
            msgMultipart.addBodyPart(htmlPart);
            // 组装附件
            MimeBodyPart filePart = new MimeBodyPart();
            String imageUrl = "https://xqgwzh.obs.cn-south-1.myhuaweicloud.com/xinquan/b176cf9af35d4773a276e55b7afe3b63.mp4";
            try {
                // 下载数据
                URL url = new URL(imageUrl);
                InputStream inputStream = url.openStream();
                byte[] imageBytes = IOUtils.toByteArray(inputStream);
                // 创建临时文件
                // 截取imageUrl后缀名
                String fileExtension = imageUrl.substring(imageUrl.lastIndexOf("."));
                File tempFile = File.createTempFile("tempImage", fileExtension);
                try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                    fos.write(imageBytes);
                }
                // 创建 FileDataSource
                FileDataSource fileDataSource = new FileDataSource(tempFile);
                System.out.println("FileDataSource created: " + fileDataSource.getName());
                // 如果需要,可以使用 DataHandler 进行进一步处理
                DataHandler dh = new DataHandler(fileDataSource);
                // 清理:删除临时文件(如果不再需要)
                 tempFile.deleteOnExit(); // 可根据需要保留或删除
//                DataHandler dh = new DataHandler(dataSource);
                filePart.setDataHandler(dh);
                // 附件区别内嵌内容的一个特点是有文件名,为防止中文乱码要编码
                filePart.setFileName(MimeUtility.encodeText(dh.getName()));
                msgMultipart.addBodyPart(filePart);
        // 获取1月份的最后一天
        LocalDate lastDayOfMonth = LocalDate.of(currentYear, 2, 12).with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime lastDayOfMonthDateTime = lastDayOfMonth.atTime(23, 59, 59);
                message.saveChanges();
                //发送
                //Transport.send(message, message.getAllRecipients());
                Transport.send(message);
                System.out.println("Sent mail successfully....");
            } catch (Exception e) {
                e.printStackTrace();
            }
            //TODO 换成自己的附件地址
        }catch (MessagingException | UnsupportedEncodingException mex) {
            mex.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException(e);
        // 格式化日期时间
        String firstDayOfMonthString = firstDayOfMonthDateTime.format(formatter);
        String lastDayOfMonthString = lastDayOfMonthDateTime.format(formatter);
        System.out.println("1月份的第一天: " + firstDayOfMonthString);
        System.out.println("1月份的最后一天: " + lastDayOfMonthString);
    }
    @GetMapping("/addVipExpireTime/{id}/{type}")
    public R addVipExpireTime(@PathVariable("id")Long id,@PathVariable("type")Integer type) {
        AppUser byId = appUserService.getById(id);
        byId.setVipLevel(type);
        switch (type){
            case 1:
                if (byId.getVipExpireTime()!=null&&byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(30));
                }else{
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(30));
                }
                break;
            case 2:
                if (byId.getVipExpireTime()!=null&&byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(90));
                }else{
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(90));
                }
                break;
            case 3:
                if (byId.getVipExpireTime()!=null&&byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(365));
                }else{
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(365));
                }
                break;
        }
    appUserService.updateById(byId);
        return R.ok();
    }
    @GetMapping("/addBalance/{id}/{money}")
    public R addBalance(@PathVariable("id")Long id,@PathVariable("money")BigDecimal money) {
        AppUser byId = appUserService.getById(id);
        byId.setBalance(byId.getBalance().add(money));
    appUserService.updateById(byId);
        return R.ok();
    }
    /**
     * 远程调用 获取用户总数上升趋势
     */
    @ApiOperation(value = "首页统计测试接口", tags = "首页统计测试接口")
    @PostMapping("/getUserListCount")
    public R<Map<String,Object>> getUserListCount() {
        Map<String, Object> res = new HashMap<>();
        // 获取当前年份
        int currentYear = LocalDate.now().getYear();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        for (int i = 1; i <= 12; i++) {
            // 获取1月份的第一天
            LocalDate firstDayOfMonth = LocalDate.of(currentYear, i, 1);
            LocalDateTime firstDayOfMonthDateTime = firstDayOfMonth.atStartOfDay();
            // 获取1月份的最后一天
            LocalDate lastDayOfMonth = LocalDate.of(currentYear, i, 12).with(TemporalAdjusters.lastDayOfMonth());
            LocalDateTime lastDayOfMonthDateTime = lastDayOfMonth.atTime(23, 59, 59);
            // 格式化日期时间
            String firstDayOfMonthString = firstDayOfMonthDateTime.format(formatter);
            String lastDayOfMonthString = lastDayOfMonthDateTime.format(formatter);
            List<AppUser> list = appUserService.lambdaQuery().eq(BaseModel::getDelFlag, 0)
                    .ne(AppUser::getUserStatus, 3)
                    .between(BaseModel::getCreateTime, firstDayOfMonthString, lastDayOfMonthString)
                    .list();
            res.put(i+"月",list.size());
        }
        // 定义月份的排序顺序
        List<String> monthsOrder = Arrays.asList("1月", "2月", "3月", "4月", "5月",
                "6月", "7月", "8月", "9月",
                "10月", "11月", "12月");
        // 创建一个 LinkedHashMap 来保持插入顺序
        Map<String, Object> sortedData = new LinkedHashMap<>();
        // 按照定义的顺序将数据放入 LinkedHashMap
        for (String month : monthsOrder) {
            if (res.containsKey(month)) {
                sortedData.put(month, res.get(month));
        }
    }
        return R.ok(sortedData);
    }
    /**
     * 远程调用 获取用户总数 非会员数 会员数
     * @return
     */
    @PostMapping("/getUserCount")
    public R<String> getUserCount() {
        StringBuilder stringBuilder = new StringBuilder();
        List<AppUser> list = appUserService.lambdaQuery()
                .eq(BaseModel::getDelFlag, 0)
                .ne(AppUser::getUserStatus, 3).list();
        stringBuilder.append(list.size()).append(",");
        List<AppUser> memberList = list.stream().filter(appUser ->
                appUser.getVipExpireTime() == null ||
                        appUser.getVipExpireTime()
                                .isBefore(LocalDateTime.now())).collect(Collectors.toList());
        int month=0;
        int quarter=0;
        int year=0;
        // 获取当前时间的单例
        LocalDateTime now = LocalDateTime.now();
        stringBuilder.append(memberList.size()).append(",");
        for (AppUser appUser : list) {
            if (appUser.getVipExpireTime()!=null){
                if (appUser.getVipExpireTime().isAfter(now)){
                    if (appUser.getVipLevel()!=null){
                        switch (appUser.getVipLevel()){
                            case 1:
                                month++;
                                break;
                            case 2:
                                quarter++;
                                break;
                            case 3:
                                year++;
                                break;
                        }
                    }
                }
            }
        }
        stringBuilder.append(month).append(",");
        stringBuilder.append(quarter).append(",");
        stringBuilder.append(year);
        return R.ok(stringBuilder.toString());
    }
//    public static void main(String[] args) {
//        // 收件人电子邮箱,TODO 换成自己的收件箱
//        String to = "443237572@qq.com";
//        // 发件人电子邮箱,TODO 换成自己的发件箱
//        String from = "13281306557@163.com";
//        // 指定发送邮件的主机为
//        String host = "smtp.163.com";
//        Properties properties = new Properties();
//        // 设置邮件服务器
//        properties.setProperty("mail.smtp.host", host);
//        // 邮件发送协议
//        properties.setProperty("mail.transport.protocol", "smtp");
//        //是否启用调试模式(启用调试模式可打印客户端与服务器交互过程时一问一答的响应消息)
//        properties.setProperty("mail.debug","true");
//        properties.setProperty("mail.smtp.auth", "true");
//        // 获取默认session对象
//        Session session = Session.getDefaultInstance(properties,new Authenticator(){
//            @Override
//            public PasswordAuthentication getPasswordAuthentication()
//            {
//                //发件人邮件用户名、授权码,换成自己的发件箱及授权码
//                return new PasswordAuthentication("13281306557@163.com", "NUSdxDQqadYvVek2");
//            }
//        });
//
//        try{
//            // 创建默认的 MimeMessage 对象
//            MimeMessage message = new MimeMessage(session);
//            // Set From,设置发件人
//            InternetAddress fromMail = new InternetAddress(from);
//            //设置发件人名称,TODO 换成自己的发件箱
//            fromMail.setPersonal(MimeUtility.encodeText("明星电力<13281306557@163.com>"));
//            message.setFrom(fromMail);
//            // Set To: 设置收件人
//            InternetAddress toMail = new InternetAddress(to);
//            // TODO 换成自己的收件箱
//            InternetAddress toMail2 = new InternetAddress("443237572@qq.com");
//            //发一个邮箱
////            message.setRecipient(Message.RecipientType.TO, toMail);
//            //发多个邮箱
//            Address[] allRecipients = {toMail, toMail2};
//            message.setRecipients(Message.RecipientType.TO, allRecipients);
//            // Set Subject: 邮件主体
//            message.setSubject("明星电力");
//            // 设置消息体
//            message.setSentDate(new Date());
//            // 指定为混合关系
//            MimeMultipart msgMultipart = new MimeMultipart("mixed");
//            message.setContent(msgMultipart);
//            // 邮件信息组装
//            //组装的顺序非常重要,一定要先组装文本域,再组装文件
//            MimeBodyPart htmlPart = new MimeBodyPart();
//            // 组装内容
//            htmlPart.setContent("This is message content", "text/html;charset=UTF-8");
//            msgMultipart.addBodyPart(htmlPart);
//            // 组装附件
//            MimeBodyPart filePart = new MimeBodyPart();
//            String imageUrl = "https://xqgwzh.obs.cn-south-1.myhuaweicloud.com/xinquan/b176cf9af35d4773a276e55b7afe3b63.mp4";
//            try {
//                // 下载数据
//                URL url = new URL(imageUrl);
//                InputStream inputStream = url.openStream();
//                byte[] imageBytes = IOUtils.toByteArray(inputStream);
//                // 创建临时文件
//                // 截取imageUrl后缀名
//                String fileExtension = imageUrl.substring(imageUrl.lastIndexOf("."));
//                File tempFile = File.createTempFile("tempImage", fileExtension);
//                try (FileOutputStream fos = new FileOutputStream(tempFile)) {
//                    fos.write(imageBytes);
//                }
//                // 创建 FileDataSource
//                FileDataSource fileDataSource = new FileDataSource(tempFile);
//                System.out.println("FileDataSource created: " + fileDataSource.getName());
//                // 如果需要,可以使用 DataHandler 进行进一步处理
//                DataHandler dh = new DataHandler(fileDataSource);
//                // 清理:删除临时文件(如果不再需要)
//                 tempFile.deleteOnExit(); // 可根据需要保留或删除
////                DataHandler dh = new DataHandler(dataSource);
//                filePart.setDataHandler(dh);
//                // 附件区别内嵌内容的一个特点是有文件名,为防止中文乱码要编码
//                filePart.setFileName(MimeUtility.encodeText(dh.getName()));
//                msgMultipart.addBodyPart(filePart);
//
//                message.saveChanges();
//                //发送
//                //Transport.send(message, message.getAllRecipients());
//                Transport.send(message);
//                System.out.println("Sent mail successfully....");
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            //TODO 换成自己的附件地址
//
//        }catch (MessagingException | UnsupportedEncodingException mex) {
//            mex.printStackTrace();
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//    }
    @PostMapping("/userDetail")
    @ApiOperation(value = "用户详情-基础信息", notes = "管理后台-用户管理")
    @ApiOperation(value = "用户详情-基础信息", tags = "管理后台-用户管理")
    public R userDetail(String uid) {
        AppUser byId = appUserService.getById(uid);
        // 判断是不是会员
@@ -238,12 +407,23 @@
        return R.ok();
    }
    @GetMapping("/viewReport")
    @ApiOperation(value = "用户详情-查看报告", notes = "管理后台-用户管理")
    @ApiOperation(value = "用户详情-查看报告", tags = "管理后台-用户管理")
    public R<ViewReport> viewReport(String uid) {
        ViewReport viewReport = new ViewReport();
        String tagId = appUserService.getById(uid).getTagId();
        List<AppUserQuestion> list = appUserQuestionService.lambdaQuery().eq(AppUserQuestion::getAppUserId, uid).list();
        List<Tag> list1 = tagService.lambdaQuery().list();
        List<AppUserQuestion> appUserQuestions = new ArrayList<>();
        List<AppUserQuestion> list = appUserQuestionService.lambdaQuery().eq(AppUserQuestion::getAppUserId, uid).orderByAsc(AppUserQuestion::getType).list();
        for (int i = 0; i < 6; i++) {
            AppUserQuestion appUserQuestion = new AppUserQuestion();
            appUserQuestion.setType(i+1);
            if (!list.isEmpty()){
                appUserQuestion.setAnswer(list.get(i)!=null?list.get(i).getAnswer():"");
            }else{
                appUserQuestion.setAnswer(null);
            }
            appUserQuestions.add(appUserQuestion);
        }
        List<Tag> list1 = tagService.lambdaQuery().eq(Tag::getTagType,2).list();
        String[] split = tagId.split(",");
        List<String> list2 = Arrays.asList(split);
        if (!list2.isEmpty()){
@@ -257,27 +437,26 @@
                    tag.setIsCheck(2);
            }
        }
        viewReport.setQuestions(list);
        viewReport.setQuestions(appUserQuestions);
        viewReport.setTags(list1);
        return R.ok(viewReport);
    }
    @GetMapping("/freezing")
    @ApiOperation(value = "冻结用户", notes = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "uid", dataType = "String", required = true),
            @ApiImplicitParam(name = "freezingReason", value = "冻结原因", dataType = "String", required = true),
    })
    public R freezingDetail(String uid,String freezingReason) {
        AppUser byId = appUserService.getById(uid);
    @Autowired
    private TokenService tokenService;
    @PostMapping("/freezing")
    @ApiOperation(value = "冻结用户", tags = "管理后台-用户管理")
    public R freezingDetail(@RequestBody UserFreezingDTO dto) {
        AppUser byId = appUserService.getById(dto.getUid());
        byId.setFreezingTime(LocalDateTime.now());
        byId.setFreezingReason(freezingReason);
        byId.setFreezingReason(dto.getFreezingReason());
        byId.setUserStatus(2);
        byId.setFreezingOperator(SecurityUtils.getUserId()+"");
        byId.setFreezingOperator(tokenService.getLoginUser().getUserid()+"");
        appUserService.updateById(byId);
        return R.ok();
    }
    @GetMapping("/detail")
    @ApiOperation(value = "用户详情", notes = "管理后台-用户管理")
    @ApiOperation(value = "用户详情", tags = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "uid", dataType = "String", required = true),
    })
@@ -307,11 +486,10 @@
            byId.setLevelName(data.getLevelName());
            byId.setLevelIcon(data.getLevelIcon());
        }
        return R.ok();
        return R.ok(byId);
    }
    @GetMapping("/unFreezing")
    @ApiOperation(value = "解冻用户", notes = "管理后台-用户管理")
    @ApiOperation(value = "解冻用户", tags = "管理后台-用户管理")
    public R unFreezing(String uid) {
        AppUser byId = appUserService.getById(uid);
        byId.setUserStatus(1);
@@ -319,7 +497,7 @@
        return R.ok(byId.getFreezingReason());
    }
    @GetMapping("/setSanskritFlag")
    @ApiOperation(value = "设置梵文权限", notes = "管理后台-用户管理")
    @ApiOperation(value = "设置梵文权限", tags = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "用户uid 多个逗号拼接", dataType = "String", required = true),
            @ApiImplicitParam(name = "setSanskritFlag", value = "梵文权限 1是2否", dataType = "int", required = true),
@@ -334,15 +512,16 @@
        return R.ok();
    }
    @GetMapping("/setTotalEnergyValue")
    @ApiOperation(value = "能量值修改", notes = "管理后台-用户管理")
    @ApiOperation(value = "能量值修改", tags = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "用户uid 多个逗号拼接", dataType = "String", required = true),
            @ApiImplicitParam(name = "uid", value = "用户uid", dataType = "String", required = true),
            @ApiImplicitParam(name = "energyValue", value = "能量值", dataType = "int", required = true),
            @ApiImplicitParam(name = "reason", value = "备注", dataType = "int", required = true),
            @ApiImplicitParam(name = "reason", value = "备注", dataType = "String", required = true)
    })
    public R setTotalEnergyValue(String uid,Integer energyValue,String remark) {
    public R setTotalEnergyValue(String uid,Integer energyValue,String reason) {
        AppUser byId = appUserService.getById(uid);
        byId.setTotalEnergyValue(byId.getTotalEnergyValue()+energyValue);
        byId.setEnergyValue(byId.getEnergyValue()+energyValue);
        appUserService.updateById(byId);
        AppUserEnergyRecord appUserEnergyRecord = new AppUserEnergyRecord();
        appUserEnergyRecord.setAppUserId(byId.getId());
@@ -353,66 +532,70 @@
            appUserEnergyRecord.setChangeType(1);
            appUserEnergyRecord.setEnergyValue(energyValue);
        }
        appUserEnergyRecord.setReason(remark);
        appUserEnergyRecord.setUpdateId(tokenService.getLoginUser().getUserid());
        appUserEnergyRecord.setReason(reason);
        appUserEnergyRecord.setCreateBy(SecurityUtils.getUsername());
        appUserEnergyRecord.setCreateTime(LocalDateTime.now());
        appUserEnergyRecordService.save(appUserEnergyRecord);
        return R.ok();
    }
    @GetMapping("/setVip")
    @ApiOperation(value = "设置会员", notes = "管理后台-用户管理")
    @ApiOperation(value = "设置会员", tags = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "uid", dataType = "String", required = true),
            @ApiImplicitParam(name = "vipType", value = "会员类型 1非 2月 3季 4年", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "vipExpireTime", value = "会员到期时间 yyyy-MM-dd HH:mm", dataType = "String", required = true),
    })
    public R setVip(String uid, Integer vipType) {
    public R setVip(String uid, Integer vipType,String vipExpireTime) {
        // 将其转化为LocalDateTime格式
        LocalDateTime parse = LocalDateTime.parse(vipExpireTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LambdaUpdateWrapper<AppUser> appUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        AppUser byId = appUserService.getById(uid);
        switch (vipType){
            case 1:
                appUserLambdaUpdateWrapper.set(AppUser::getVipExpireTime,null);
                appUserLambdaUpdateWrapper.set(AppUser::getVipLevel,null);
                appUserLambdaUpdateWrapper.eq(AppUser::getId,byId.getUserId());
                appUserService.update(appUserLambdaUpdateWrapper);
                break;
            case 2:
                if (byId.getVipExpireTime() == null){
                    byId.setVipLevel(1);
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(30));
                    byId.setVipExpireTime(parse);
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(30));
                    byId.setVipExpireTime(parse);
                }else{
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(30));
                    byId.setVipExpireTime(parse);
                }
                break;
            case 3:
                if (byId.getVipExpireTime() == null){
                    byId.setVipLevel(2);
                    byId.setVipExpireTime(LocalDateTime.now().plusMonths(90));
                    byId.setVipExpireTime(parse);
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    // 如果当前用户的会员等级大于设置的会员等级那么不管
                    if (byId.getVipLevel()<2){
                        byId.setVipLevel(2);
                    }
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(90));
                    byId.setVipExpireTime(parse);
                }else{
                    if (byId.getVipLevel()<2){
                        byId.setVipLevel(2);
                    }
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(90));
                    byId.setVipExpireTime(parse);
                }
                break;
            case 4:
                byId.setVipLevel(3);
                if (byId.getVipExpireTime() == null){
                    byId.setVipExpireTime(LocalDateTime.now().plusMonths(365));
                    byId.setVipExpireTime(parse);
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(365));
                    byId.setVipExpireTime(parse);
                }else{
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(365));
                    byId.setVipExpireTime(parse);
                }
                break;
        }
@@ -420,7 +603,7 @@
        return R.ok();
    }
    @GetMapping("/freezingDetail")
    @ApiOperation(value = "冻结详情", notes = "管理后台-用户管理")
    @ApiOperation(value = "冻结详情", tags = "管理后台-用户管理")
    public R<FreezingVO> freezingDetail(String uid) {
        AppUser byId = appUserService.getById(uid);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -431,6 +614,283 @@
        SysUser data = remoteUserService.getSysUserById(byId.getFreezingOperator()).getData();
        freezingVO.setFreezingOperator(data.getNickName()+"("+data.getUserName()+")");
        return R.ok(freezingVO);
    }
    @ApiOperation(value = "用户列表-下级用户管理导出", tags = {"管理后台-用户管理"})
    @PutMapping("/exportUser")
    public void export(@RequestBody UserChildDTO dto)
    {
        String startTime = null;
        String endTime = null;
        if (org.springframework.util.StringUtils.hasLength(dto.getTime())){
            String[] split = dto.getTime().split(" - ");
            startTime = split[0]+"00:00:00";
            endTime = split[1]+"23:59:59";
        }
        String userId = dto.getUid();
        LambdaQueryWrapper<AppUser> appUserWalletRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        appUserWalletRecordLambdaQueryWrapper.between(startTime!=null,BaseModel::getCreateTime,startTime,endTime);
        appUserWalletRecordLambdaQueryWrapper.eq(AppUser::getInviteUserId, userId);
        appUserWalletRecordLambdaQueryWrapper.like(org.springframework.util.StringUtils.hasLength(dto.getCellPhone()),AppUser::getCellPhone,dto.getCellPhone());
        appUserWalletRecordLambdaQueryWrapper.like(org.springframework.util.StringUtils.hasLength(dto.getNickName()),AppUser::getNickname,dto.getNickName());
        appUserWalletRecordLambdaQueryWrapper.orderByDesc(BaseModel::getCreateTime);
        List<AppUser> page = appUserService
                .list(appUserWalletRecordLambdaQueryWrapper);
        List<UserInfoExport> userInfoExports = new ArrayList<>();
        for (AppUser record : page) {
            // 查询该用户带来收益
            List<AppUserWalletRecord> list = appUserWalletRecordService.lambdaQuery().eq(AppUserWalletRecord::getAppUserId, record.getId())
                    .eq(AppUserWalletRecord::getChildAppUserId, record.getUserId()).list();
            BigDecimal bigDecimal = new BigDecimal("0");
            for (AppUserWalletRecord appUserWalletRecord : list) {
                if (appUserWalletRecord.getAmount()!=null && appUserWalletRecord.getChangeType() == 1){
                    bigDecimal = bigDecimal.add(appUserWalletRecord.getAmount());
                }
                record.setMoney(bigDecimal);
            }
            UserInfoExport userInfoExport = new UserInfoExport();
            userInfoExport.setCode(record.getCode());
            userInfoExport.setUserName(record.getNickname());
            userInfoExport.setCellphone(record.getCellPhone());
            userInfoExport.setIncome("¥"+record.getMoney());
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String format = df.format(record.getInviteUserTime());
            userInfoExport.setInviteUserTime(format);
            userInfoExport.setUserStatus(record.getUserStatus()+"");
            userInfoExports.add(userInfoExport);
        }
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), UserInfoExport.class, userInfoExports);
        HttpServletResponse response = WebUtils.response();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("用户管理导出.xls", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @ApiOperation(value = "用户列表管理导出", tags = {"管理后台-用户管理"})
    @PutMapping("/export")
    public void export(@RequestBody AppUserManagementDTO courseDTO)
    {
        String startTime = null;
        String endTime = null;
        if (org.springframework.util.StringUtils.hasLength(courseDTO.getVipExpireTime())){
            String[] split = courseDTO.getVipExpireTime().split(" - ");
            startTime = split[0]+"00:00:00";
            endTime = split[1]+"23:59:59";
        }
        String startTime1 = null;
        String endTime1 = null;
        if (org.springframework.util.StringUtils.hasLength(courseDTO.getRegisterTime())){
            String[] split = courseDTO.getRegisterTime().split(" - ");
            startTime1 = split[0]+"00:00:00";
            endTime1 = split[1]+"23:59:59";
        }
        List<Long> longs = new ArrayList<>();
        LambdaQueryWrapper<AppUser> courseLambdaQueryWrapper = new LambdaQueryWrapper<>();
        courseLambdaQueryWrapper
                .like(StringUtils.isNotBlank(courseDTO.getNickname()), AppUser::getNickname, courseDTO.getNickname())
                .like(StringUtils.isNotBlank(courseDTO.getCellPhone()), AppUser::getCellPhone, courseDTO.getCellPhone())
                .eq(Objects.nonNull(courseDTO.getGender()), AppUser::getGender, courseDTO.getGender())
                .eq(Objects.nonNull(courseDTO.getUserStatus()), AppUser::getUserStatus, courseDTO.getUserStatus())
                .between(Objects.nonNull(startTime),AppUser::getVipExpireTime,startTime,endTime)
                .between(Objects.nonNull(startTime1),AppUser::getRegisterTime,startTime1,endTime1)
                .orderByDesc(AppUser::getRegisterTime);
        if (org.springframework.util.StringUtils.hasLength(courseDTO.getVipType())){
            String[] split = courseDTO.getVipType().split(",");
            List<String> list1 = Arrays.asList(split);
            List<AppUser> appUsers = new ArrayList<>();
            List<AppUser> list = appUserService.lambdaQuery().gt(AppUser::getVipExpireTime, LocalDateTime.now()).list();
            for (AppUser appUser : list) {
                if(appUser.getVipLevel()!=null){
                    if (list1.contains(appUser.getVipLevel().toString())){
                        appUsers.add(appUser);
                    }
                }
            }
            List<Long> collect = appUsers.stream().map(AppUser::getId).collect(Collectors.toList());
            if (collect.isEmpty()){
                collect.add(-1L);
            }
            courseLambdaQueryWrapper.in(AppUser::getId, longs);
        }
        if (org.springframework.util.StringUtils.hasLength(courseDTO.getLevel())){
            List<String> list2 = Arrays.asList(courseDTO.getLevel().split(","));
            List<AppUser> list = appUserService.lambdaQuery().list();
            List<AppUser> appUsers = new ArrayList<>();
            for (AppUser appUser : list) {
                List<AppUserTree> list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, appUser.getId())
                        .list();
                // 查询用户等级最高的那颗树苗
                AppUserTree tree = list1.stream().max((o1, o2) -> {
                    if (o1.getTreeLevelType() > o2.getTreeLevelType()) {
                        return 1;
                    } else if (o1.getTreeLevelType() < o2.getTreeLevelType()) {
                        return -1;
                    } else {
                        return 0;
                    }
                }).orElse(null);
                // 查询疗愈等级 名称 图标
                int level = 1;
                if (tree != null){
                    level = tree.getTreeLevelType();
                }
                if (list2.contains(level+"")){
                    appUsers.add(appUser);
                }
            }
            List<Long> collect = appUsers.stream().map(AppUser::getId).collect(Collectors.toList());
            if (collect.isEmpty()){
                collect.add(-1L);
            }
            courseLambdaQueryWrapper.in(AppUser::getId, collect);
        }
        List<AppUser> page = appUserService.list(courseLambdaQueryWrapper);
        List<UserExport> userExports = new ArrayList<>();
        for (AppUser record : page) {
            record.setUid(record.getId()+"");
            // 判断是不是会员
            if (record.getVipExpireTime() == null){
                record.setIsVip(2);
            }else if (record.getVipExpireTime().isBefore(LocalDateTime.now())){
                record.setIsVip(2);
            }else{
                record.setIsVip(1);
            }
            List<AppUserTree> list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, record.getId())
                    .list();
            // 查询用户等级最高的那颗树苗
            AppUserTree tree = list1.stream().max((o1, o2) -> {
                if (o1.getTreeLevelType() > o2.getTreeLevelType()) {
                    return 1;
                } else if (o1.getTreeLevelType() < o2.getTreeLevelType()) {
                    return -1;
                } else {
                    return 0;
                }
            }).orElse(null);
            // 查询疗愈等级 名称 图标
            int level = 1;
            if (tree != null){
                level = tree.getTreeLevelType();
            }
            // 根据等级查询疗愈名称和图标
            UserLevelSetting data = remoteBannerService.getIconNameByLevel(level).getData();
            record.setLevel(level);
            record.setLevelIcon(data.getLevelIcon());
            record.setLevelName(data.getLevelName());
            record.setUid(record.getId().toString());
            UserExport userExport = new UserExport();
            userExport.setCode(record.getCode());
            userExport.setUserName(record.getNickname());
            userExport.setRealname(record.getRealname());
            userExport.setCellphone(record.getCellPhone());
            userExport.setGender(record.getGender()+"");
            userExport.setBirthday(record.getBirthday());
            userExport.setEducation(record.getEducation());
            userExport.setLocation(record.getLocation());
            userExport.setHometown(record.getHometown());
            userExport.setEmail(record.getEmail());
            userExport.setIndustry(record.getIndustry());
            userExport.setCompany(record.getCompany());
            userExport.setOccupation(record.getOccupation());
            if (record.getVipExpireTime()!=null){
                if (record.getVipExpireTime().isAfter(LocalDateTime.now())){
                    userExport.setIsVip(1+"");
                }else{
                    userExport.setIsVip(2+"");
                }
            }else{
                userExport.setIsVip(2+"");
            }
            userExport.setMeditationLevel(record.getLevelName());
            userExport.setTotalEnergyValue(record.getTotalEnergyValue()+"");
            userExport.setBalance(record.getBalance()+"");
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String format = df.format(record.getRegisterTime());
            userExport.setRegisterTime(format);
            userExport.setUserStatus(record.getUserStatus()+"");
            List<AppUserQuestion> list = appUserQuestionService.lambdaQuery()
                    .eq(AppUserQuestion::getAppUserId, record.getId()).list();
            for (AppUserQuestion appUserQuestion : list) {
                switch (appUserQuestion.getType()){
                    case 1:
                        userExport.setType1(appUserQuestion.getAnswer());
                        break;
                    case 2:
                        userExport.setType2(appUserQuestion.getAnswer());
                        break;
                    case 3:
                        userExport.setType3(appUserQuestion.getAnswer());
                        break;
                    case 4:
                        userExport.setType4(appUserQuestion.getAnswer());
                        break;
                    case 5:
                        userExport.setType5(appUserQuestion.getAnswer());
                        break;
                    case 6:
                        userExport.setType6(appUserQuestion.getAnswer());
                        break;
                }
            }
            List<Integer> collect = appUserTagService.lambdaQuery()
                    .eq(AppUserTag::getAppUserId, record.getId()).list().stream()
                    .map(AppUserTag::getTagId)
                    .collect(Collectors.toList());
            if (collect.isEmpty()){
                collect.add(-1);
            }
            List<Tag> list2 = tagService.lambdaQuery().in(Tag::getId, collect).list();
            StringBuilder stringBuilder = new StringBuilder();
            for (Tag tag : list2) {
                stringBuilder.append(tag.getTagName()).append(";");
            }
            userExport.setType7(stringBuilder+"");
            userExport.setSanskritFlag(record.getSanskritFlag()+"");
            int size = appUserService.lambdaQuery().eq(AppUser::getInviteUserId, record.getId()).list()
                    .size();
            userExport.setUserCount(size+"");
            userExports.add(userExport);
        }
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), UserExport.class, userExports);
        HttpServletResponse response = WebUtils.response();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("用户管理导出.xls", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @PostMapping("/userManagementList")
    @ApiOperation(value = "用户管理列表-分页", tags = {"管理后台-用户管理"})
@@ -456,7 +916,6 @@
                .like(StringUtils.isNotBlank(courseDTO.getCellPhone()), AppUser::getCellPhone, courseDTO.getCellPhone())
                .eq(Objects.nonNull(courseDTO.getGender()), AppUser::getGender, courseDTO.getGender())
                .eq(Objects.nonNull(courseDTO.getUserStatus()), AppUser::getUserStatus, courseDTO.getUserStatus())
                .isNotNull(AppUser::getVipExpireTime)
                .between(Objects.nonNull(startTime),AppUser::getVipExpireTime,startTime,endTime)
                .between(Objects.nonNull(startTime1),AppUser::getRegisterTime,startTime1,endTime1)
                .orderByDesc(AppUser::getRegisterTime);
@@ -515,6 +974,7 @@
            return R.ok(PageDTO.empty(page));
        }
        for (AppUser record : page.getRecords()) {
            record.setUid(record.getId()+"");
            // 判断是不是会员
            if (record.getVipExpireTime() == null){
                record.setIsVip(2);
@@ -577,24 +1037,33 @@
    @PostMapping("/changePhone")
    @ApiOperation(value = "更换绑定手机号", tags = {"设置"})
    public R changePhone(String phone,String code) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        return R.ok();
    }
    @PostMapping("/deleteUser")
    @ApiOperation(value = "注销账号", tags = {"设置"})
    public R deleteUser() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        return R.ok();
    }
    @PostMapping("/wallet")
    @ApiOperation(value = "我的钱包", tags = {"个人中心"})
    public R<WalletVO> wallet(UpdateAppUserDTO dto) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
    public R<WalletVO> wallet() {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUser byId = appUserService.getById(userId);
        WalletVO walletVO = new WalletVO();
        walletVO.setId(userId);
@@ -622,8 +1091,49 @@
    public R<PageDTO<InviteRankListVO>> myInviteRankList(
            @RequestParam(value = "pageCurr", defaultValue = "1") Integer pageCurr,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        Page<AppUser> page = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                .eq(AppUser::getInviteUserId, userId)
                .page(new Page<>(pageCurr, pageSize));
        if (page.getRecords().isEmpty()){
            return R.ok(PageDTO.empty(page));
        }
        // 查询登录用户邀请了哪些人
        List<Long> collect = page.getRecords().stream().map(AppUser::getId).collect(Collectors.toList());
        if (collect.isEmpty())return R.ok(PageDTO.empty(page));
        for (int i = 0; i < page.getRecords().size(); i++) {
            AppUser appUser = page.getRecords().get(i);
            // 查询该给用户带来收益
            List<AppUserWalletRecord> list = appUserWalletRecordService.lambdaQuery().eq(AppUserWalletRecord::getAppUserId, userId)
                    .eq(AppUserWalletRecord::getChildAppUserId,appUser.getUserId()).list();
            BigDecimal bigDecimal = new BigDecimal("0");
            for (AppUserWalletRecord appUserWalletRecord : list) {
                if (appUserWalletRecord.getAmount()!=null && appUserWalletRecord.getChangeType() == 1){
                    bigDecimal = bigDecimal.add(appUserWalletRecord.getAmount());
                }
            }
            appUser.setMoney(bigDecimal);
        }
        // 根据佣金金额 从大到小排序
        page.getRecords().sort((o1, o2) -> o2.getMoney().compareTo(o1.getMoney()));
        return R.ok(PageDTO.of(page, InviteRankListVO.class));
    }
    @PostMapping("/myInviteRankListShare")
    @ApiOperation(value = "我的助力-分页", tags = {"H5分享"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "分页参数,当前页码", name = "pageCurr", required = true, dataType = "Integer"),
            @ApiImplicitParam(value = "分页参数,每页数量", name = "pageSize", required = true, dataType = "Integer"),
            @ApiImplicitParam(value = "用户id", name = "userId", required = true, dataType = "String"),
    })
    public R<PageDTO<InviteRankListVO>> myInviteRankListShare(
            @RequestParam(value = "pageCurr", defaultValue = "1") Integer pageCurr,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(value = "userId") String userId) {
        Page<AppUser> page = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                .eq(AppUser::getInviteUserId, userId)
                .page(new Page<>(pageCurr, pageSize));
@@ -681,12 +1191,38 @@
        page.getRecords().sort((o1, o2) -> o2.getCount() - o1.getCount());
        return R.ok(PageDTO.of(page, InviteRankListVO.class)) ;
    }
    @PostMapping("/inviteRankListShare")
    @ApiOperation(value = "爱心助力榜单-分页", tags = {"H5分享"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "分页参数,当前页码", name = "pageCurr", required = true, dataType = "Integer"),
            @ApiImplicitParam(value = "分页参数,每页数量", name = "pageSize", required = true, dataType = "Integer")
    })
    public R<PageDTO<InviteRankListVO>> inviteRankListShare(
            @RequestParam(value = "pageCurr", defaultValue = "1") Integer pageCurr,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        Page<AppUser> page = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                .page(new Page<>(pageCurr, pageSize));
        for (AppUser appUser : page.getRecords()) {
            int size = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                    .eq(AppUser::getInviteUserId, appUser.getId())
                    .list().size();
            appUser.setCount(size);
        }
        // 根据帮助人数 从大到小排序
        page.getRecords().sort((o1, o2) -> o2.getCount() - o1.getCount());
        return R.ok(PageDTO.of(page, InviteRankListVO.class)) ;
    }
    @PostMapping("/getUserInfo")
    @ApiOperation(value = "获取用户信息", tags = {"个人中心"})
    public R<AppUserInfoVO> getUserInfo() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUserInfoVO appUserInfoVO = new AppUserInfoVO();
        AppUser byId = appUserService.getById(userId);
        BeanUtils.copyProperties(byId, appUserInfoVO);
        AppUserVO currentUser = appUserService.getCurrentUser();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        if (currentUser.getVipExpireTime() == null){
@@ -704,7 +1240,10 @@
        List<AppUserViewingHistory> com = appUserViewingHistoryService.cumulative(userId);
        appUserInfoVO.setCumulative(com.size());
        // 查询用户今日学习多少分钟
        int temp = appUserViewingHistoryService.today(userId);
        Integer temp = appUserViewingHistoryService.today(userId);
        if (temp == null){
            temp =0;
        }
        if (temp == 0){
            appUserInfoVO.setToday(0);
        }else if (temp<60){
@@ -763,8 +1302,11 @@
    @PostMapping("/getUserDetail")
    @ApiOperation(value = "获取个人资料", tags = {"个人中心"})
    public R<AppUser> getUserDetail() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUser appUser = appUserService.lambdaQuery().eq(AppUser::getId, userId).one();
        if (appUser.getVipExpireTime() == null){
            appUser.setIsVip(2);
@@ -778,10 +1320,23 @@
    @PostMapping("/healingLevel")
    @ApiOperation(value = "冥想等级", tags = {"个人中心"})
    public R<HealingLevelVO> healingLevel() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        List<AppUserTree> list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, userId)
                .list();
        if (list1.isEmpty()){
            AppUserTree appUserTree = new AppUserTree();
            appUserTree.setAppUserId(userId);
            appUserTree.setTreeLevelType(1);
            appUserTree.setGrowthValue(0);
            appUserTree.setSowAgain(2);
            appUserTree.setStatus(2);
            appUserTree.setCreateTime(LocalDateTime.now());
            appUserTreeService.save(appUserTree);
        }
        // 查询用户等级最高的那颗树苗
        AppUserTree tree = list1.stream().max((o1, o2) -> {
            if (o1.getTreeLevelType() > o2.getTreeLevelType()) {
@@ -859,16 +1414,22 @@
    @PostMapping("/getTotalEnergyValue")
    @ApiOperation(value = "获取用户当前累计能量值",tags = "树苗打卡站")
    public R getTotalEnergyValue() {
        Long userId = SecurityUtils.getUserId();
        if (userId==0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUser byId = appUserService.getById(userId);
        return R.ok(byId.getTotalEnergyValue());
    }
    @PostMapping("/updateUserDetail")
    @ApiOperation(value = "修改个人资料", tags = {"个人中心"})
    public R<AppUser> updateUserDetail(UpdateAppUserDTO dto) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
    public R<AppUser> updateUserDetail(@RequestBody UpdateAppUserDTO dto) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUser byId = appUserService.getById(userId);
        LambdaUpdateWrapper<AppUser> updateWrapper = new LambdaUpdateWrapper<>(AppUser.class);
        updateWrapper.set(AppUser::getNickname, dto.getNickname());
@@ -883,14 +1444,18 @@
        updateWrapper.set(AppUser::getLocation, dto.getLocation());
        updateWrapper.set(AppUser::getHometown, dto.getHometown());
        updateWrapper.set(AppUser::getEmail, dto.getEducation());
        updateWrapper.eq(AppUser::getId,userId);
        appUserService.update(byId, updateWrapper);
        return R.ok();
        return R.ok(byId);
    }
    @PostMapping("/updateUserAvatar")
    @ApiOperation(value = "修改头像", tags = {"个人中心"})
    public R updateUserDetail(String avatar) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUser byId = appUserService.getById(userId);
        byId.setAvatar(avatar);
        appUserService.updateById(byId);
@@ -928,9 +1493,12 @@
    @PostMapping("/getUserBalance")
    @ApiOperation(value = "查询当前用户余额")
    public R<String> getUserBalance() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        AppUser one = appUserService.lambdaQuery().eq(AppUser::getUserId, userId).one();
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUser one = appUserService.lambdaQuery().eq(AppUser::getId, userId).one();
        return R.ok(one.getBalance().toString());
    }
@@ -955,6 +1523,11 @@
    @PostMapping("/saveUserAnswers")
    @ApiOperation(value = "保存计划引导页用户的答案", tags = {"用户端-计划引导相关接口"})
    public R<?> saveUserAnswers(@Validated @RequestBody UserAnswerDTO dto) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        appUserService.saveUserAnswers(dto);
        return R.ok();
    }