无关风月
2025-02-28 dd663d0ac783755d889e270eee57ee58630c88c8
xinquan-modules/xinquan-user/src/main/java/com/xinquan/user/controller/client/ClientAppUserController.java
@@ -1,22 +1,94 @@
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.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xinquan.common.core.constant.CacheConstants;
import com.xinquan.common.core.domain.R;
import com.xinquan.common.core.exception.ServiceException;
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.log.annotation.Log;
import com.xinquan.common.log.enums.BusinessType;
import com.xinquan.common.redis.service.RedisService;
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;
import com.xinquan.course.api.domain.CourseDTO;
import com.xinquan.course.api.domain.OrderCourseVO;
import com.xinquan.meditation.api.domain.Meditation;
import com.xinquan.order.api.feign.RemoteOrderService;
import com.xinquan.system.api.RemoteBannerService;
import com.xinquan.system.api.RemoteUserService;
import com.xinquan.system.api.domain.*;
import com.xinquan.system.api.domain.vo.*;
import com.xinquan.system.api.feignClient.SysUserClient;
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.vo.AppUserVO;
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.AppUserService;
import com.xinquan.user.service.*;
import com.xinquan.user.utils.MailUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import java.awt.image.BufferedImage;
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.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
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.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;
import org.springframework.web.bind.annotation.*;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
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;
/**
 * <p>
@@ -26,25 +98,1637 @@
 * @author mitao
 * @since 2024-08-21
 */
@Api(tags = {"用户相关接口"})
@Slf4j
@RestController
@RequestMapping("/client/app-user")
@RequiredArgsConstructor
public class ClientAppUserController {
    private final AppUserService appUserService;
    @Resource
    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 RemoteBannerService remoteBannerService;
    @Resource
    private RemoteOrderService remoteOrderService;
    @Resource
    private RemoteUserService remoteUserService;
    @Resource
    private NoticeRecordService noticeRecordService;
    @Resource
    private AppUserBlackService appUserBlackService;
    /**
     * 远程调用 查询当前登陆人拉黑列表
     * @param appUserId
     */
    @PostMapping("/getUserBlackList/{appUserId}")
    public R<List<Long>> getUserBlackList(@PathVariable("appUserId") Long appUserId){
        List<Long> collect = appUserBlackService.lambdaQuery().eq(AppUserBlack::getAppUserId, appUserId).list()
                .stream().map(AppUserBlack::getBlackId).collect(Collectors.toList());
        return R.ok(collect);
    }
    @PostMapping("/blackUser")
    @ApiOperation(value = "取消拉黑功能", tags = "IOS拉黑列表--用于上架")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "被拉黑用户id", name = "appUserId", required = true, dataType = "Long"),
    })
    public R blackUser(Long appUserId) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        AppUserBlack one = appUserBlackService.lambdaQuery().eq(AppUserBlack::getAppUserId, loginUser.getAppUserId())
                .eq(AppUserBlack::getBlackId, appUserId).one();
        if (one==null){
            // 拉黑
            AppUserBlack appUserBlack = new AppUserBlack();
            appUserBlack.setAppUserId(loginUser.getAppUserId());
            appUserBlack.setBlackId(appUserId);
            appUserBlackService.save(appUserBlack);
        }else {
            // 取消拉黑
            appUserBlackService.removeById(one.getId());
        }
        return R.ok();
    }
    @GetMapping("/blackList")
    @ApiOperation(value = "IOS拉黑列表", tags = "IOS拉黑列表--用于上架")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "分页参数,当前页码", name = "pageCurr", required = true, dataType = "Integer"),
            @ApiImplicitParam(value = "分页参数,每页数量", name = "pageSize", required = true, dataType = "Integer")
    })
    public R<PageDTO<AppUser>> blackList(Integer pageCurr, Integer pageSize) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        List<Long> collect = appUserBlackService.lambdaQuery().eq(AppUserBlack::getAppUserId, loginUser.getAppUserId()).list()
                .stream().map(AppUserBlack::getBlackId).collect(Collectors.toList());
        if (collect.isEmpty()){
            collect.add(-1L);
        }
        Page<AppUser> page = appUserService.lambdaQuery().in(AppUser::getId, collect).page(new Page<>(pageCurr, pageSize));
        if (CollUtils.isEmpty(page.getRecords())){
            PageDTO<AppUser> empty = PageDTO.empty(page);
            return R.ok(empty);
        }
        return R.ok(PageDTO.of(page, AppUser.class));
    }
    @PostMapping("/subVipExpireTime/{appUserId}/{type}")
    public void subVipExpireTime(@PathVariable("appUserId") Long appUserId,@PathVariable("type") Integer type){
        AppUser byId = appUserService.getById(appUserId);
        switch (type){
            case 1:
                LocalDateTime localDateTime = byId.getVipExpireTime().minusDays(30);
                byId.setVipExpireTime(localDateTime);
                break;
            case 2:
                LocalDateTime localDateTime1 = byId.getVipExpireTime().minusDays(90);
                byId.setVipExpireTime(localDateTime1);
                break;
            case 3:
                LocalDateTime localDateTime2 = byId.getVipExpireTime().minusDays(365);
                byId.setVipExpireTime(localDateTime2);
                break;
        }
        appUserService.updateById(byId);
    }
    @ApiOperation(value = "会员临期", tags = "会员临期")
    @PostMapping("/testVip")
    public void testVip() {
        LocalDateTime now = LocalDateTime.now();
        List<AppUser> list = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3).list();
        for (AppUser appUser : list) {
            if (appUser.getVipExpireTime()!=null && appUser.getVipExpireTime().isAfter(now)){
                // 计算两个now和time的天数差
                long between = ChronoUnit.DAYS.between(now,appUser.getVipExpireTime());
                if (between<=7 &&between>=0){
                    NoticeRecord noticeRecord = new NoticeRecord();
                    noticeRecord.setAppUserId(appUser.getId());
                    noticeRecord.setReadStatus(1);
                    noticeRecord.setNoticeType(1);
                    noticeRecord.setTitle("【会员临期通知】");
                    noticeRecord.setContent("尊敬的泉疗愈会员你好,你的会员即将在"
                            +appUser.getVipExpireTime().toLocalDate()+"到期,到期后将不再享受会员权益,请及时续费");
                    noticeRecordService.save(noticeRecord);
                }
            }
        }
    }
    @GetMapping("/deleteBalance/{id}/{amount}")
    public R deleteBalance(@PathVariable("id")String id,@PathVariable("amount")String amount) {
        AppUser byId = appUserService.getById(id);
        if (byId!=null){
            BigDecimal subtract = byId.getBalance().subtract(new BigDecimal(amount));
            if (subtract.compareTo(BigDecimal.ZERO)<0){
                byId.setBalance(BigDecimal.ZERO);
            }
        }
        return R.ok();
    }
    @GetMapping("/testNotice")
    @ApiOperation(value = "测试通知", tags = "测试通知")
    public R testNotice() {
        LocalDateTime now = LocalDateTime.now();
        List<AppUser> list = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3).list();
        for (AppUser appUser : list) {
            if (appUser.getVipExpireTime()!=null && appUser.getVipExpireTime().isAfter(now)){
                // 计算两个now和time的天数差
                long between = Math.abs(ChronoUnit.DAYS.between(appUser.getVipExpireTime(), now));
                if (between<=7){
                    NoticeRecord noticeRecord = new NoticeRecord();
                    noticeRecord.setAppUserId(appUser.getId());
                    noticeRecord.setReadStatus(1);
                    noticeRecord.setNoticeType(1);
                    noticeRecord.setTitle("【会员临期通知】");
                    noticeRecord.setContent("尊敬的泉疗愈会员你好,你的会员即将在"
                            +appUser.getVipExpireTime().toLocalDate()+"到期,到期后将不再享受会员权益,请及时续费");
                    noticeRecordService.save(noticeRecord);
                }
            }
            AppUserTree one = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, appUser.getId())
                    .eq(AppUserTree::getSowAgain, 2).one();
            if(one!=null && (one.getTaskOne()==2||one.getTaskTwo()==2)){
                NoticeRecord noticeRecord = new NoticeRecord();
                noticeRecord.setAppUserId(appUser.getId());
                noticeRecord.setReadStatus(1);
                noticeRecord.setNoticeType(1);
                noticeRecord.setTitle("【冥想通知】");
                noticeRecord.setContent("你今天的冥想任务还未完成,完成冥想后可获得能量值奖励,快去冥想吧!");
                noticeRecordService.save(noticeRecord);
            }
        }
        return R.ok();
    }
    @GetMapping("/getUserByPhone/{phone}")
    public R<AppUser> getUserByPhone(@PathVariable("phone")String phone) {
        AppUser one = appUserService.lambdaQuery().eq(AppUser::getCellPhone, phone).ne(AppUser::getUserStatus, 3)
                .one();
        return R.ok(one);
    }
    @GetMapping("/getAllUserList")
    public R<List<AppUser>> getAllUserList() {
        List<AppUser> list = appUserService.list();
        return R.ok(list);
    }
    @PostMapping("/bindVx")
    @ApiOperation(value = "绑定微信号", tags = "个人中心")
    public R bindVx(String openId,String wxName) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        AppUser byId = appUserService.getById(loginUser.getUserid());
        AppUser one = appUserService.lambdaQuery().eq(AppUser::getWxOpenId, openId)
                .isNotNull(AppUser::getCellPhone)
                .ne(AppUser::getUserStatus, 3).one();
        if (one!=null){
            return R.fail("当前微信号已绑定其他账号");
        }
        byId.setWxOpenId(openId);
        byId.setWxName(wxName);
        appUserService.updateById(byId);
        return R.ok();
    }
    public static void main(String[] args) {
        // 获取当前年份
        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();
        // 获取1月份的最后一天
        LocalDate lastDayOfMonth = LocalDate.of(currentYear, 2, 12).with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime lastDayOfMonthDateTime = lastDayOfMonth.atTime(23, 59, 59);
        // 格式化日期时间
        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)
                .isNotNull(AppUser::getCellPhone)
                .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());
    }
    @PostMapping("/userDetail")
    @ApiOperation(value = "用户详情-基础信息", tags = "管理后台-用户管理")
    public R userDetail(String uid) {
        AppUser byId = appUserService.getById(uid);
        // 判断是不是会员
        if (byId.getVipExpireTime() == null){
            byId.setIsVip(2);
        }else if (byId.getVipExpireTime().isBefore(LocalDateTime.now())){
            byId.setIsVip(2);
        }else{
            byId.setIsVip(1);
        }
        AppUserTree list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, uid)
                .eq(AppUserTree::getSowAgain,2)
                .one();
        // 查询疗愈等级 名称 图标
        int level = list1.getTreeLevelType();
        // 根据等级查询疗愈名称和图标
        UserLevelSetting data = remoteBannerService.getIconNameByLevel(level).getData();
        byId.setLevel(level);
        byId.setLevelIcon(data.getLevelIcon());
        byId.setLevelName(data.getLevelName());
        byId.setUid(byId.getId().toString());
        if (org.springframework.util.StringUtils.hasLength(byId.getTagId())){
            List<String> list = Arrays.asList(byId.getTagId().split(","));
            List<String> collect = tagService.lambdaQuery().in(Tag::getId, list).list().stream()
                    .map(Tag::getTagName).collect(Collectors.toList());
            byId.setTags(collect);
        }
        return R.ok();
    }
    @GetMapping("/viewReport")
    @ApiOperation(value = "用户详情-查看报告", tags = "管理后台-用户管理")
    public R<ViewReport> viewReport(String uid) {
        ViewReport viewReport = new ViewReport();
        String tagId = appUserService.getById(uid).getTagId();
        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();
        if (org.springframework.util.StringUtils.hasLength(tagId)){
            String[] split = tagId.split(",");
            List<String> list2 = Arrays.asList(split);
            if (!list2.isEmpty()){
                for (Tag tag : list1) {
                    if (list2.contains(tag.getId().toString())){
                        tag.setIsCheck(1);
                    }
                }
            }
        }else{
            for (Tag tag : list1) {
                tag.setIsCheck(2);
            }
        }
        viewReport.setQuestions(appUserQuestions);
        viewReport.setTags(list1);
        return R.ok(viewReport);
    }
    @Autowired
    private TokenService tokenService;
    @PostMapping("/freezing")
    @ApiOperation(value = "冻结用户", tags = "管理后台-用户管理")
    @Log(title = "【用户管理】冻结用户", businessType = BusinessType.UPDATE)
    public R freezingDetail(@RequestBody UserFreezingDTO dto) {
        AppUser byId = appUserService.getById(dto.getUid());
        byId.setFreezingTime(LocalDateTime.now());
        byId.setFreezingReason(dto.getFreezingReason());
        byId.setUserStatus(2);
        Long userid = tokenService.getLoginUser().getUserid();
        SysUser data = remoteUserService.getSysUserById(userid + "").getData();
        byId.setFreezingOperator(data.getNickName()+"("+data.getUserName()+")");
        appUserService.updateById(byId);
        String cacheList = redisService.getCacheObject(byId.getId() + "");
        redisService.deleteObject(cacheList);
        return R.ok();
    }
    @GetMapping("/detail")
    @ApiOperation(value = "用户详情", tags = "管理后台-用户管理")
    public R<AppUser> detail(String uid) {
        AppUser byId = appUserService.getById(uid);
        List<AppUserTree> list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, byId.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();
        }
        byId.setLevel(level);
        // 根据等级查询疗愈名称和图标
        UserLevelSetting data = remoteBannerService.getIconNameByLevel(level).getData();
        if (data!=null){
            byId.setLevelName(data.getLevelName());
            byId.setLevelIcon(data.getLevelIcon());
        }
        if (org.springframework.util.StringUtils.hasLength(byId.getTagId())){
            List<String> list = Arrays.asList(byId.getTagId().split(","));
            List<String> collect = tagService.lambdaQuery().in(Tag::getId, list).list().stream()
                    .map(Tag::getTagName).collect(Collectors.toList());
            byId.setTags(collect);
        }
        return R.ok(byId);
    }
    @GetMapping("/unFreezing")
    @ApiOperation(value = "解冻用户", tags = "管理后台-用户管理")
    @Log(title = "【用户管理】解冻用户", businessType = BusinessType.UPDATE)
    public R unFreezing(String uid) {
        AppUser byId = appUserService.getById(uid);
        byId.setUserStatus(1);
        appUserService.updateById(byId);
        return R.ok(byId.getFreezingReason());
    }
    @GetMapping("/setSanskritFlag")
    @ApiOperation(value = "设置梵文权限", tags = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "用户uid 多个逗号拼接", dataType = "String", required = true),
            @ApiImplicitParam(name = "setSanskritFlag", value = "梵文权限 1是2否", dataType = "int", required = true),
    })
    public R setSanskritFlag(String uid,Integer setSanskritFlag) {
        List<String> list = Arrays.asList(uid.split(","));
        List<AppUser> list1 = appUserService.lambdaQuery().in(AppUser::getId, list).list();
        for (AppUser appUser : list1) {
            appUser.setSanskritFlag(setSanskritFlag);
        }
        appUserService.updateBatchById(list1);
        return R.ok();
    }
    @GetMapping("/setTotalEnergyValue")
    @ApiOperation(value = "能量值修改", tags = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "用户uid", dataType = "String", required = true),
            @ApiImplicitParam(name = "energyValue", value = "能量值", dataType = "int", required = true),
            @ApiImplicitParam(name = "reason", value = "备注", dataType = "String", required = true)
    })
    @Log(title = "【用户管理】能量值修改", businessType = BusinessType.UPDATE)
    public R setTotalEnergyValue(String uid,Integer energyValue,String reason) {
        AppUser byId = appUserService.getById(uid);
        if (energyValue<0){
            if (byId.getTotalEnergyValue()<Math.abs(energyValue)){
                return R.fail("扣除能量值应小于当前能量值");
            }
        }
        byId.setTotalEnergyValue(byId.getTotalEnergyValue()+energyValue);
        appUserService.updateById(byId);
        AppUserEnergyRecord appUserEnergyRecord = new AppUserEnergyRecord();
        appUserEnergyRecord.setAppUserId(byId.getId());
        if (energyValue<0){
            appUserEnergyRecord.setChangeType(2);
            appUserEnergyRecord.setEnergyValue(-energyValue);
        }else{
            appUserEnergyRecord.setChangeType(1);
            appUserEnergyRecord.setEnergyValue(energyValue);
        }
        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 = "设置会员", 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),
    })
    @Log(title = "【用户管理】设置会员", businessType = BusinessType.UPDATE)
    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:
                byId.setVipExpireTime(null);
                byId.setVipLevel(null);
                appUserService.updateById(byId);
                break;
            case 2:
                if (byId.getVipExpireTime() == null){
                    byId.setVipLevel(1);
                    byId.setVipExpireTime(parse);
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(parse);
                }else{
                    byId.setVipExpireTime(parse);
                }
                break;
            case 3:
                if (byId.getVipExpireTime() == null){
                    byId.setVipLevel(2);
                    byId.setVipExpireTime(parse);
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    // 如果当前用户的会员等级大于设置的会员等级那么不管
                    if (byId.getVipLevel()<2){
                        byId.setVipLevel(2);
                    }
                    byId.setVipExpireTime(parse);
                }else{
                    if (byId.getVipLevel()<2){
                        byId.setVipLevel(2);
                    }
                    byId.setVipExpireTime(parse);
                }
                break;
            case 4:
                byId.setVipLevel(3);
                if (byId.getVipExpireTime() == null){
                    byId.setVipExpireTime(parse);
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(parse);
                }else{
                    byId.setVipExpireTime(parse);
                }
                break;
        }
        appUserService.updateById(byId);
        return R.ok();
    }
    @GetMapping("/freezingDetail")
    @ApiOperation(value = "冻结详情", tags = "管理后台-用户管理")
    public R<FreezingVO> freezingDetail(String uid) {
        AppUser byId = appUserService.getById(uid);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(byId.getFreezingTime());
        FreezingVO freezingVO = new FreezingVO();
        freezingVO.setFreezingTime(format);
        freezingVO.setFreezingReason(byId.getFreezingReason());
        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);
        appUserWalletRecordLambdaQueryWrapper.isNotNull(AppUser::getCellPhone);
        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);
        courseLambdaQueryWrapper.isNotNull(AppUser::getCellPhone)
                .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) {
                AppUserTree list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, appUser.getId())
                        .eq(AppUserTree::getSowAgain,2)
                        .one();
                // 查询疗愈等级 名称 图标
                int level = list1.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);
        }
        courseLambdaQueryWrapper.isNotNull(AppUser::getCellPhone);
        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);
            }
            AppUserTree list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, record.getId())
                    .eq(AppUserTree::getSowAgain,2)
                    .one();
            // 查询疗愈等级 名称 图标
            int level = list1.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();
                userExport.setType1("");
                userExport.setType2("");
                userExport.setType3("");
                userExport.setType4("");
                userExport.setType5("");
                userExport.setType6("");
                userExport.setType6("");
            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<String> collect = new ArrayList<>();
            if (org.springframework.util.StringUtils.hasLength(record.getTagId())) {
                collect = tagService.lambdaQuery()
                        .in(Tag::getId, Arrays.stream(record.getTagId().split(",")).map(Long::parseLong).collect(Collectors.toList())).list().stream()
                                .map(Tag::getTagName).collect(Collectors.toList());
            }
            StringBuilder stringBuilder = new StringBuilder();
            for (String tag : collect) {
                stringBuilder.append(tag).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 = {"管理后台-用户管理"})
    public R<PageDTO<AppUser>> userManagementList(@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<Integer> objects = new ArrayList<>();
            for (String s : split) {
                objects.add(Integer.parseInt(s)-1);
            }
            List<AppUser> appUsers = new ArrayList<>();
            List<AppUser> list = appUserService.lambdaQuery().list();
            for (AppUser appUser : list) {
               if (objects.contains(0)){
                   if (appUser.getVipExpireTime()==null){
                       appUsers.add(appUser);
                   }else if (appUser.getVipExpireTime().isBefore(LocalDateTime.now())){
                       appUsers.add(appUser);
                   }
                }
                if (objects.contains(1)){
                    if (appUser.getVipExpireTime()!=null&&appUser.getVipExpireTime().isAfter(LocalDateTime.now())&&appUser.getVipLevel()==1){
                        appUsers.add(appUser);
                    }
                }
                if (objects.contains(2)){
                    if (appUser.getVipExpireTime()!=null&&appUser.getVipExpireTime().isAfter(LocalDateTime.now())&&appUser.getVipLevel()==2){
                        appUsers.add(appUser);
                    }
                }
                if (objects.contains(3)){
                    if (appUser.getVipExpireTime()!=null&&appUser.getVipExpireTime().isAfter(LocalDateTime.now())&&appUser.getVipLevel()==3){
                        appUsers.add(appUser);
                    }
                }
            }
            List<Long> collect = appUsers.stream().distinct().map(AppUser::getId).collect(Collectors.toList());
            if (collect.isEmpty()){
                collect.add(-1L);
            }
            courseLambdaQueryWrapper.in(AppUser::getId, collect);
        }
        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) {
                AppUserTree list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, appUser.getId())
                        .eq(AppUserTree::getSowAgain,2)
                        .one();
                // 查询疗愈等级 名称 图标
                int level = 1;
                if (list1 != null){
                    level = list1.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);
        }
        courseLambdaQueryWrapper.isNotNull(AppUser::getCellPhone);
        Page<AppUser> page = appUserService.page(new Page<>(courseDTO.getPageCurr(), courseDTO.getPageSize()), courseLambdaQueryWrapper);
        if (CollUtils.isEmpty(page.getRecords())) {
            return R.ok(PageDTO.empty(page));
        }
        for (AppUser record : page.getRecords()) {
            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());
        }
        return R.ok(PageDTO.of(page, AppUser.class));
    }
    private static String getImageFormat(String url) {
        String extension = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
        switch (extension) {
            case "png":
                return "image/png";
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "gif":
                return "image/gif";
            default:
                return "unknown format";
        }
    }
    public static DataSource convertImageToDataSource(String imageUrl) throws Exception {
        URL url = new URL(imageUrl);
        try (InputStream inputStream = url.openStream()) {
            byte[] imageBytes = IOUtils.toByteArray(inputStream);
            // 使用 ImageIO 读取图片,以检测格式
            BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
            String formatName = ImageIO.getImageReaders(image).next().getFormatName();
            return new ByteArrayDataSource(imageBytes, "image/" + formatName);
        }
    }
    @PostMapping("/changePhone")
    @ApiOperation(value = "更换绑定手机号", tags = {"设置"})
    public R changePhone(String phone,String code) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        // 校验验证码
        if (!verifyCaptcha(phone, code,
                CacheConstants.APP_CHANGE_PHONE_CODE_PREFIX)) {
            throw new ServiceException("验证码不正确");
        }
        AppUser byId = appUserService.getById(userId);
        AppUser one = appUserService.lambdaQuery().eq(AppUser::getCellPhone, phone)
                .ne(AppUser::getId, userId)
                .ne(AppUser::getUserStatus, 3).one();
        if (one!=null){
            return R.fail("当前手机号已被绑定");
        }
        byId.setCellPhone(phone);
        boolean b = appUserService.updateById(byId);
        return R.ok();
    }
    @Autowired
    private RedisService redisService;
    private boolean verifyCaptcha(String cellPhone, String captcha, String keyPrefix) {
        if (com.xinquan.common.core.utils.StringUtils.isNotBlank(cellPhone) && com.xinquan.common.core.utils.StringUtils.isNotBlank(captcha)) {
            String key = keyPrefix + cellPhone;
            String code = redisService.getCacheObject(key);
            // 万能验证码
            if (captcha.equals("220125") || (com.xinquan.common.core.utils.StringUtils.isNotBlank(code) && code.equals(
                    captcha))) {
                redisService.deleteObject(key);
                return true;
            }
        }
        return false;
    }
    @PostMapping("/deleteUser")
    @ApiOperation(value = "注销账号", tags = {"设置"})
    public R deleteUser() {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        AppUser byId = appUserService.getById(userId);
        byId.setUserStatus(3);
        byId.setLogoutTime(LocalDateTime.now());
        appUserService.updateById(byId);
        appUserService.removeById(byId);
        remoteUserService.removeByAppUserId(byId.getUserId());
        return R.ok();
    }
    @PostMapping("/wallet")
    @ApiOperation(value = "我的钱包", tags = {"个人中心"})
    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);
        walletVO.setBalance(byId.getBalance());
        List<AppUser> page = appUserService.lambdaQuery()
                .eq(AppUser::getInviteUserId, userId)
                .list();
        // 查询登录用户邀请了哪些人
        List<Long> collect = page.stream().map(AppUser::getId).collect(Collectors.toList());
        BigDecimal bigDecimal1 = new BigDecimal("0");
        for (AppUser record : page) {
            List<AppUserWalletRecord> list = appUserWalletRecordService.lambdaQuery().eq(AppUserWalletRecord::getAppUserId, userId)
                    .like(AppUserWalletRecord::getReason,"分佣").eq(AppUserWalletRecord::getChildAppUserId, record.getId()).list();
            BigDecimal reduce = list.stream().map(AppUserWalletRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            bigDecimal1 = bigDecimal1.add(reduce);
            record.setMoney(reduce);
        }
        walletVO.setIncome(bigDecimal1);
        // 查询用户充值
        String data = remoteOrderService.queryChargeByUserId(userId).getData();
        BigDecimal bigDecimal = new BigDecimal(data);
        walletVO.setRecharge(bigDecimal);
        return R.ok(walletVO);
    }
    /**
     * 爱心助力榜单-分页
     *
     * @param pageCurr    分页参数,当前页码
     * @param pageSize    分页参数,每页数量
     * @return 课程分页列表
     */
    @PostMapping("/myInviteRankList")
    @ApiOperation(value = "我的助力-分页", tags = {"个人中心"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "分页参数,当前页码", name = "pageCurr", required = true, dataType = "Integer"),
            @ApiImplicitParam(value = "分页参数,每页数量", name = "pageSize", required = true, dataType = "Integer")
    })
    public R<PageDTO<InviteRankListVO>> myInviteRankList(
            @RequestParam(value = "pageCurr", defaultValue = "1") Integer pageCurr,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Page<AppUser> objectPage = new Page<>(pageCurr, pageSize);
        Long userId = loginUser.getUserid();
        List<AppUser> page = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                .eq(AppUser::getInviteUserId, userId)
                .list();
        // 查询登录用户邀请了哪些人
        List<Long> collect = page.stream().map(AppUser::getId).collect(Collectors.toList());
        for (AppUser record : page) {
            List<AppUserWalletRecord> list = appUserWalletRecordService.lambdaQuery().eq(AppUserWalletRecord::getAppUserId, userId)
                    .like(AppUserWalletRecord::getReason,"分佣").eq(AppUserWalletRecord::getChildAppUserId, record.getId()).list();
            BigDecimal reduce = list.stream().map(AppUserWalletRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            record.setMoney(reduce);
        }
        // 根据佣金金额 从大到小排序
        page.sort((o1, o2) -> o2.getMoney().compareTo(o1.getMoney()));
        List<AppUser> testing = testing(page.size(), pageCurr, pageSize, page);
        objectPage.setTotal(testing.size());
        objectPage.setRecords(testing);
        return R.ok(PageDTO.of(objectPage, 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> objectPage = new Page<>(pageCurr, pageSize);
        List<AppUser> page = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                .eq(AppUser::getInviteUserId, userId)
                .list();
        // 查询登录用户邀请了哪些人
        List<Long> collect = page.stream().map(AppUser::getId).collect(Collectors.toList());
        for (AppUser record : page) {
            List<AppUserWalletRecord> list = appUserWalletRecordService.lambdaQuery().eq(AppUserWalletRecord::getAppUserId, userId)
                    .like(AppUserWalletRecord::getReason,"分佣").eq(AppUserWalletRecord::getChildAppUserId, record.getId()).list();
            BigDecimal reduce = list.stream().map(AppUserWalletRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            record.setMoney(reduce);
        }
        // 根据佣金金额 从大到小排序
        page.sort((o1, o2) -> o2.getMoney().compareTo(o1.getMoney()));
        List<AppUser> testing = testing(page.size(), pageCurr, pageSize, page);
        objectPage.setTotal(page.size());
        objectPage.setRecords(testing);
        return R.ok(PageDTO.of(objectPage, InviteRankListVO.class));
    }
    @Resource
    private AppUserWalletRecordService appUserWalletRecordService;
    /**
     * 爱心助力榜单-分页
     *
     * @param pageCurr    分页参数,当前页码
     * @param pageSize    分页参数,每页数量
     * @return 课程分页列表
     */
    @PostMapping("/inviteRankList")
    @ApiOperation(value = "爱心助力榜单-分页", tags = {"个人中心"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "分页参数,当前页码", name = "pageCurr", required = true, dataType = "Integer"),
            @ApiImplicitParam(value = "分页参数,每页数量", name = "pageSize", required = true, dataType = "Integer")
    })
    public R<PageDTO<InviteRankListVO>> inviteRankList(
            @RequestParam(value = "pageCurr", defaultValue = "1") Integer pageCurr,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        Page<AppUser> objectPage = new Page<>(pageCurr, pageSize);
        List<AppUser> page = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                .list();
        List<AppUser> res = new ArrayList<>();
        for (AppUser appUser : page) {
            int size = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                    .eq(AppUser::getInviteUserId, appUser.getId())
                    .list().size();
            appUser.setCount(size);
            if (size>0){
                res.add(appUser);
            }
        }
        // 根据帮助人数 从大到小排序
        res.sort((o1, o2) -> o2.getCount() - o1.getCount());
        List<AppUser> testing = testing(res.size(), pageCurr, pageSize, res);
        objectPage.setRecords(testing);
        objectPage.setTotal(res.size());
        return R.ok(PageDTO.of(objectPage, InviteRankListVO.class)) ;
    }
    public static List<AppUser> testing(long total, long current, long size, List<AppUser> str){
        List<AppUser> result = new ArrayList<>();
        //获取初始化分页结构
        Page<AppUser> page = new Page<>(current - 1, size, total);
        //获取集合下标初始值
        long startIndex = (current - 1) * size;
        //获取集合下标结束值
        long endInddex = 0;
        if(startIndex + page.getCurrent() >= total || size > total){
            endInddex = total;
        }else {
            endInddex = Math.min(startIndex + page.getSize(), total);
        }
        //如果输入的开始查询下标大于集合大小,则查询为空值
        if(startIndex > total){
            result = Collections.emptyList();
        }else{
            result = str.subList((int)startIndex,(int)endInddex);
        }
        return result;
    }
    @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> objectPage = new Page<>(pageCurr, pageSize);
        List<AppUser> page = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                .list();
        List<AppUser> res = new ArrayList<>();
        for (AppUser appUser : page) {
            int size = appUserService.lambdaQuery().ne(AppUser::getUserStatus, 3)
                    .eq(AppUser::getInviteUserId, appUser.getId())
                    .list().size();
            appUser.setCount(size);
            if (size>0){
                res.add(appUser);
            }
        }
        // 根据帮助人数 从大到小排序
        res.sort((o1, o2) -> o2.getCount() - o1.getCount());
        List<AppUser> testing = testing(res.size(), pageCurr, pageSize, res);
        objectPage.setRecords(testing);
        objectPage.setTotal(res.size());
        return R.ok(PageDTO.of(objectPage, InviteRankListVO.class)) ;
    }
    @PostMapping("/inviteRankListShareInfo")
    @ApiOperation(value = "爱心助力榜单详情-分页", tags = {"H5分享"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "id", name = "id", required = true, dataType = "Long"),
            @ApiImplicitParam(value = "分页参数,当前页码", name = "pageCurr", required = true, dataType = "Integer"),
            @ApiImplicitParam(value = "分页参数,每页数量", name = "pageSize", required = true, dataType = "Integer")
    })
    public R<PageDTO<InviteRankListVO>> inviteRankListShareInfo(
            @RequestParam(value = "id") Long id,
            @RequestParam(value = "pageCurr", defaultValue = "1") Integer pageCurr,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        LambdaQueryWrapper<AppUser> appUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        appUserLambdaQueryWrapper.eq(AppUser::getInviteUserId,id);
        appUserLambdaQueryWrapper.ne(AppUser::getUserStatus,3);
        Page<AppUser> page = appUserService.page(new Page<>(pageCurr, pageSize), appUserLambdaQueryWrapper);
        return R.ok(PageDTO.of(page, InviteRankListVO.class)) ;
    }
    @PostMapping("/getUserInfo")
    @ApiOperation(value = "获取用户信息", tags = {"个人中心"})
    public R<AppUserInfoVO> getUserInfo() {
        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){
            appUserInfoVO.setIsVip(2);
        }else if (currentUser.getVipExpireTime().isAfter(LocalDateTime.now())){
            appUserInfoVO.setIsVip(1);
            String formattedDateTime =currentUser.getVipExpireTime().format(formatter);
            appUserInfoVO.setVipExpireTime(formattedDateTime);
        }else{
            String formattedDateTime =currentUser.getVipExpireTime().format(formatter);
            appUserInfoVO.setVipExpireTime(formattedDateTime);
            appUserInfoVO.setIsVip(2);
        }
        // 查询用户累计学习天数
        List<AppUserViewingHistory> com = appUserViewingHistoryService.cumulative(userId);
        appUserInfoVO.setCumulative(com.size());
        // 查询用户今日学习多少分钟
        Integer temp = appUserViewingHistoryService.today(userId);
        if (temp == null){
            temp =0;
        }
        if (temp == 0){
            appUserInfoVO.setToday(0);
        }else if (temp<60){
            // 不足一分钟按一分钟计算
            appUserInfoVO.setToday(1);
        }else{
            appUserInfoVO.setToday(temp/60);
        }
        // 查询用户连续观看天数
        List<AppUserViewingHistory> list = appUserViewingHistoryService.lambdaQuery().eq(AppUserViewingHistory::getAppUserId, userId)
                .eq(AppUserViewingHistory::getViewingType, 1)
                .orderByDesc(BaseModel::getCreateTime).list();
        Set<LocalDate> viewingDates = list.stream()
                .map(record -> LocalDate.parse(record.getCreateTime().toLocalDate().toString(), formatter))
                .collect(Collectors.toCollection(HashSet::new));
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 计算连续观看天数
        int consecutiveDays = 0;
        LocalDate currentDate = today;
        // 如果今天没有观看 也进入循环判断
        while (viewingDates.contains(currentDate)||LocalDate.parse(currentDate.toString(), formatter).equals(today)) {
            if (!viewingDates.contains(currentDate)){
                // 如果今天没有观看
                currentDate = currentDate.minusDays(1);
                continue;
            }
            consecutiveDays++;
            currentDate = currentDate.minusDays(1);
        }
        appUserInfoVO.setContinuity(consecutiveDays);
        AppUserTree list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, userId)
                .eq(AppUserTree::getSowAgain,2)
                .one();
        // 查询疗愈等级 名称 图标
        int level = 1;
        if (list1 != null){
            level = list1.getTreeLevelType();
        }
        appUserInfoVO.setLevel(level);
        // 根据等级查询疗愈名称和图标
        UserLevelSetting data = remoteBannerService.getIconNameByLevel(level).getData();
        appUserInfoVO.setLevelName(data.getLevelName());
        appUserInfoVO.setLevelIcon(data.getLevelIcon());
        return R.ok(appUserInfoVO);
    }
    @PostMapping("/getUserDetail")
    @ApiOperation(value = "获取个人资料", tags = {"个人中心"})
    public R<AppUser> getUserDetail() {
        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);
        }else if (appUser.getVipExpireTime().isAfter(LocalDateTime.now())){
            appUser.setIsVip(1);
        }else{
            appUser.setIsVip(2);
        }
        AppUserTree list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, userId)
                .eq(AppUserTree::getSowAgain,2)
                .one();
        // 查询疗愈等级 名称 图标
        int level = list1.getTreeLevelType();
        appUser.setLevel(level);
        // 查询用户累计学习天数
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List<AppUserViewingHistory> com = appUserViewingHistoryService.cumulative(userId);
        appUser.setCumulative(com.size());
        // 查询用户今日学习多少分钟
        Integer temp = appUserViewingHistoryService.today(userId);
        if (temp == null){
            temp =0;
        }
        if (temp == 0){
            appUser.setToday(0);
        }else if (temp<60){
            // 不足一分钟按一分钟计算
            appUser.setToday(1);
        }else{
            appUser.setToday(temp/60);
        }
        // 查询用户连续观看天数
        List<AppUserViewingHistory> list = appUserViewingHistoryService.lambdaQuery().eq(AppUserViewingHistory::getAppUserId, userId)
                .eq(AppUserViewingHistory::getViewingType, 1)
                .orderByDesc(BaseModel::getCreateTime).list();
        Set<LocalDate> viewingDates = list.stream()
                .map(record -> LocalDate.parse(record.getCreateTime().toLocalDate().toString(), formatter))
                .collect(Collectors.toCollection(HashSet::new));
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 计算连续观看天数
        int consecutiveDays = 0;
        LocalDate currentDate = today;
        // 如果今天没有观看 也进入循环判断
        while (viewingDates.contains(currentDate)||LocalDate.parse(currentDate.toString(), formatter).equals(today)) {
            if (!viewingDates.contains(currentDate)){
                // 如果今天没有观看
                currentDate = currentDate.minusDays(1);
                continue;
            }
            consecutiveDays++;
            currentDate = currentDate.minusDays(1);
        }
        appUser.setContinuity(consecutiveDays);
        // 根据等级查询疗愈名称和图标
        UserLevelSetting data = remoteBannerService.getIconNameByLevel(level).getData();
        appUser.setLevelName(data.getLevelName());
        appUser.setLevelIcon(data.getLevelIcon());
        return R.ok(appUser);
    }
    @Resource
    private SysUserClient sysUserClient;
    @PostMapping("/healingLevel")
    @ApiOperation(value = "冥想等级", tags = {"个人中心"})
    public R<HealingLevelVO> healingLevel() {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        Long userId = loginUser.getUserid();
        HealingLevelVO healingLevelVO = new HealingLevelVO();
        AppUser one = appUserService.getById(userId);
        AppUserTree list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, userId)
                .eq(AppUserTree::getSowAgain,2)
                .one();
        // 查询疗愈等级 名称 图标
        int level = list1.getTreeLevelType();
        healingLevelVO.setLevel(level);
        // 查询疗愈等级 名称 图标
        if (list1 != null){
            level = list1.getTreeLevelType();
        }
        healingLevelVO.setLevel(level);
        // 根据等级查询疗愈名称和图标
        UserLevelSetting data = remoteBannerService.getIconNameByLevel(level).getData();
        healingLevelVO.setLevelName(data.getLevelName());
        healingLevelVO.setLevelIcon(data.getLevelIcon());
        List<TreeLevelSetting> data3 = sysUserClient.getTreeGroup().getData();
        Integer total1 = list1.getTotal();
        // 根据总能量值 确定他在哪一等级
        int x = 1;
        int tem = 0;
        for (TreeLevelSetting datum : data3) {
            if (total1 == 0){
                Integer growthValue = data3.get(1).getGrowthValue();
                tem = growthValue;
                break;
            }else if (total1>=datum.getGrowthValue()){
                x = datum.getTreeLevelType();
            }
        }
        if (x == 10){
            // 如果等级为10那么成长阈值是10级减去9级
            int ten=0;
            int nine = 0;
            for (TreeLevelSetting datum : data3) {
                if (datum.getTreeLevelType()==10){
                    ten = datum.getGrowthValue();
                }
                if (datum.getTreeLevelType()==9){
                    nine = datum.getGrowthValue();
                }
            }
            tem = ten-nine;
            total1 = tem;
        }else{
            // 根据当前所在等级查询成长值
            int a = data3.get(x).getGrowthValue()-data3.get(x-1).getGrowthValue();
            tem = a;
            total1 = Math.abs(total1-data3.get(x-1).getGrowthValue());
        }
        if (x==10){
            healingLevelVO.setDifferenceLevel(0);
            healingLevelVO.setGrowthValue(tem);
        }else{
            healingLevelVO.setDifferenceLevel(tem-total1);
            healingLevelVO.setGrowthValue(total1);
        }
        healingLevelVO.setNextLevel(tem);
        healingLevelVO.setLevel(x);
        // 将当前成长值更新
        String data1 = remoteUserService.getCourseList(7).getData();
        healingLevelVO.setContent(data1);
        return R.ok(healingLevelVO);
    }
    @PostMapping("/getTotalEnergyValue")
    @ApiOperation(value = "获取用户当前累计能量值",tags = "树苗打卡站")
    public R getTotalEnergyValue() {
        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(@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());
        updateWrapper.set(AppUser::getRealname, dto.getRealname());
        updateWrapper.set(AppUser::getSignature, dto.getSignature());
        updateWrapper.set(AppUser::getGender, dto.getGender());
        updateWrapper.set(AppUser::getBirthday, dto.getBirthday());
        updateWrapper.set(AppUser::getEducation, dto.getEducation());
        updateWrapper.set(AppUser::getIndustry, dto.getIndustry());
        updateWrapper.set(AppUser::getCompany, dto.getCompany());
        updateWrapper.set(AppUser::getOccupation, dto.getOccupation());
        updateWrapper.set(AppUser::getLocation, dto.getLocation());
        updateWrapper.set(AppUser::getHometown, dto.getHometown());
        updateWrapper.set(AppUser::getEmail, dto.getEmail());
        updateWrapper.eq(AppUser::getId,userId);
        appUserService.update(byId, updateWrapper);
        return R.ok(byId);
    }
    @PostMapping("/updateUserAvatar")
    @ApiOperation(value = "修改头像", tags = {"个人中心"})
    public R updateUserDetail(String avatar) {
        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);
        return R.ok();
    }
    /**
     * 获取当前登录用户信息
     *
     * @return 用户信息
     * @see com.xinquan.user.domain.vo.AppUserVO
     * @see AppUserVO
     */
    @PostMapping("/getCurrentUser")
    @ApiOperation(value = "获取当前用户信息", tags = {"用户端-用户信息相关接口"})
    public R<AppUserVO> getCurrentUser() {
        return R.ok(appUserService.getCurrentUser());
    }
    /**
     * 通过手机号查询用户端用户信息
     *
     * @return 用户信息
     * @see AppUserVO
     */
    @PostMapping("/getUserByPhone")
    @ApiOperation(value = "根据用户手机号查询用户信息")
    public R<AppUserDetailVO> getCurrentUser(String phone) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (loginUser==null){
            return R.tokenError("登录失效");
        }
        AppUser one = appUserService.lambdaQuery().eq(AppUser::getCellPhone, phone)
                .ne(AppUser::getUserStatus,3).one();
        if (one!=null){
            if (one.getId().equals(loginUser.getUserid())){
                return R.giveError("不能赠送给自己");
            }
            AppUserDetailVO appUserDetailVO = new AppUserDetailVO();
            appUserDetailVO.setId(one.getId());
            appUserDetailVO.setCellPhone(one.getCellPhone());
            appUserDetailVO.setAvatar(one.getAvatar());
            appUserDetailVO.setNickname(one.getNickname());
            return R.ok(appUserDetailVO);
        }else {
            return R.fail("未查询到账户信息");
        }
    }
    @PostMapping("/getUserBalance")
    @ApiOperation(value = "查询当前用户余额")
    public R<String> getUserBalance() {
        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());
    }
    /**
@@ -68,9 +1752,46 @@
    @PostMapping("/saveUserAnswers")
    @ApiOperation(value = "保存计划引导页用户的答案", tags = {"用户端-计划引导相关接口"})
    public R<?> saveUserAnswers(@Validated @RequestBody UserAnswerDTO dto) {
        appUserService.saveUserAnswers(dto);
        return R.ok();
    }
    /**
     * 远程调用根据用户id 查询用户
     */
    @PostMapping("/getAppUserById/{id}")
    public R<AppUser> getAppUserById(@PathVariable("id")String id) {
        AppUser byId = appUserService.getById(id);
        return R.ok(byId);
    }
    /**
     * 远程调用根据用户名称 查询用户
     */
    @PostMapping("/getAppUserByName/{name}")
    public R<List<Long>> getAppUserByName(@PathVariable("name")String name) {
        List<Long> collect = appUserService.lambdaQuery()
                .like(AppUser::getNickname, name)
                .list()
                .stream().map(AppUser::getId).collect(Collectors.toList());
        return R.ok(collect);
    }
    /**
     * 远程调用根据用户名称 查询用户
     */
    @PostMapping("/getAppUserByNameOrPhone/{name}")
    public R<List<Long>> getAppUserByNameOrPhone(@PathVariable("name")String name) {
        List<Long> collect = appUserService.lambdaQuery()
                .like(AppUser::getNickname, name)
                .list()
                .stream().map(AppUser::getId).collect(Collectors.toList());
        List<Long> collect1 = appUserService.lambdaQuery()
                .like(AppUser::getCellPhone, name)
                .list()
                .stream().map(AppUser::getId).collect(Collectors.toList());
        collect1.addAll(collect);
        List<Long> collect2 = collect1.stream().distinct().collect(Collectors.toList());
        return R.ok(collect2);
    }
}