无关风月
2024-10-14 b60e601d62c0e2d5c4fd1df9f12fa09f2bf99987
xinquan-modules/xinquan-user/src/main/java/com/xinquan/user/controller/client/ClientAppUserController.java
@@ -1,22 +1,65 @@
package com.xinquan.user.controller.client;
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.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.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.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.user.api.domain.dto.AppUserManagementDTO;
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.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.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
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.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 static com.xinquan.common.core.enums.TreeLevelEnum.TOWERING_TREES;
/**
 * <p>
@@ -34,17 +77,861 @@
public class ClientAppUserController {
    private final AppUserService appUserService;
    @Resource
    private AppUserViewingHistoryService appUserViewingHistoryService;
    @Resource
    private AppUserEnergyRecordService appUserEnergyRecordService;
    @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");
            }
        });
        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 = "管理后台-用户管理")
    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);
        }
        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();
        }
        // 根据等级查询疗愈名称和图标
        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 = "用户详情-查看报告", notes = "管理后台-用户管理")
    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();
        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(list);
        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);
        byId.setFreezingTime(LocalDateTime.now());
        byId.setFreezingReason(freezingReason);
        byId.setUserStatus(2);
        byId.setFreezingOperator(SecurityUtils.getUserId()+"");
        appUserService.updateById(byId);
        return R.ok();
    }
    @GetMapping("/detail")
    @ApiOperation(value = "用户详情", notes = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "uid", dataType = "String", required = true),
    })
    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());
        }
        return R.ok();
    }
    @GetMapping("/unFreezing")
    @ApiOperation(value = "解冻用户", notes = "管理后台-用户管理")
    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 = "设置梵文权限", notes = "管理后台-用户管理")
    @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 = "能量值修改", notes = "管理后台-用户管理")
    @ApiImplicitParams({
            @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),
    })
    public R setTotalEnergyValue(String uid,Integer energyValue,String remark) {
        AppUser byId = appUserService.getById(uid);
        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.setReason(remark);
        appUserEnergyRecord.setCreateBy(SecurityUtils.getUsername());
        appUserEnergyRecord.setCreateTime(LocalDateTime.now());
        appUserEnergyRecordService.save(appUserEnergyRecord);
        return R.ok();
    }
    @GetMapping("/setVip")
    @ApiOperation(value = "设置会员", notes = "管理后台-用户管理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "uid", dataType = "String", required = true),
            @ApiImplicitParam(name = "vipType", value = "会员类型 1非 2月 3季 4年", dataType = "Integer", required = true),
    })
    public R setVip(String uid, Integer vipType) {
        LambdaUpdateWrapper<AppUser> appUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        AppUser byId = appUserService.getById(uid);
        switch (vipType){
            case 1:
                appUserLambdaUpdateWrapper.set(AppUser::getVipExpireTime,null);
                appUserLambdaUpdateWrapper.set(AppUser::getVipLevel,null);
                appUserService.update(appUserLambdaUpdateWrapper);
                break;
            case 2:
                if (byId.getVipExpireTime() == null){
                    byId.setVipLevel(1);
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(30));
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(30));
                }else{
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(30));
                }
                break;
            case 3:
                if (byId.getVipExpireTime() == null){
                    byId.setVipLevel(2);
                    byId.setVipExpireTime(LocalDateTime.now().plusMonths(90));
                }else if (byId.getVipExpireTime().isAfter(LocalDateTime.now())){
                    // 如果当前用户的会员等级大于设置的会员等级那么不管
                    if (byId.getVipLevel()<2){
                        byId.setVipLevel(2);
                    }
                    byId.setVipExpireTime(byId.getVipExpireTime().plusDays(90));
                }else{
                    if (byId.getVipLevel()<2){
                        byId.setVipLevel(2);
                    }
                    byId.setVipExpireTime(LocalDateTime.now().plusDays(90));
                }
                break;
            case 4:
                byId.setVipLevel(3);
                if (byId.getVipExpireTime() == null){
                    byId.setVipExpireTime(LocalDateTime.now().plusMonths(365));
                }else if (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("/freezingDetail")
    @ApiOperation(value = "冻结详情", notes = "管理后台-用户管理")
    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);
    }
    @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())
                .isNotNull(AppUser::getVipExpireTime)
                .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);
        }
        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()) {
            // 判断是不是会员
            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) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        return R.ok();
    }
    @PostMapping("/deleteUser")
    @ApiOperation(value = "注销账号", tags = {"设置"})
    public R deleteUser() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        return R.ok();
    }
    @PostMapping("/wallet")
    @ApiOperation(value = "我的钱包", tags = {"个人中心"})
    public R<WalletVO> wallet(UpdateAppUserDTO dto) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        AppUser byId = appUserService.getById(userId);
        WalletVO walletVO = new WalletVO();
        walletVO.setId(userId);
        walletVO.setBalance(byId.getBalance());
        walletVO.setIncome(byId.getIncome());
        // 查询用户充值
        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) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        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));
    }
    @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> 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("登录失效");
        AppUserInfoVO appUserInfoVO = new 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());
        // 查询用户今日学习多少分钟
        int temp = appUserViewingHistoryService.today(userId);
        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.setToday(consecutiveDays);
        List<AppUserTree> list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, userId)
                .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();
        }
        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() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        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);
        }
        return R.ok(appUser);
    }
    @PostMapping("/healingLevel")
    @ApiOperation(value = "冥想等级", tags = {"个人中心"})
    public R<HealingLevelVO> healingLevel() {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        List<AppUserTree> list1 = appUserTreeService.lambdaQuery().eq(AppUserTree::getAppUserId, userId)
                .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();
        }
        HealingLevelVO healingLevelVO = new HealingLevelVO();
        healingLevelVO.setLevel(level);
        // 根据等级查询疗愈名称和图标
        UserLevelSetting data = remoteBannerService.getIconNameByLevel(level).getData();
        healingLevelVO.setLevelName(data.getLevelName());
        healingLevelVO.setLevelIcon(data.getLevelIcon());
        if (level==10){
            healingLevelVO.setNextLevel(2400);
        }else{
            switch (level){
                case 1:
                    healingLevelVO.setNextLevel(1000);
                    healingLevelVO.setDifferenceLevel(1000-tree.getGrowthValue());
                    break;
                case 2:
                    healingLevelVO.setNextLevel(1000);
                    healingLevelVO.setDifferenceLevel(1000-tree.getGrowthValue());
                    break;
                case 3:
                    healingLevelVO.setNextLevel(1000);
                    healingLevelVO.setDifferenceLevel(1000-tree.getGrowthValue());
                    break;
                case 4:
                    healingLevelVO.setNextLevel(1000);
                    healingLevelVO.setDifferenceLevel(1000-tree.getGrowthValue());
                    break;
                case 5:
                    healingLevelVO.setNextLevel(2000);
                    healingLevelVO.setDifferenceLevel(2000-tree.getGrowthValue());
                    break;
                case 6:
                    healingLevelVO.setNextLevel(2000);
                    healingLevelVO.setDifferenceLevel(2000-tree.getGrowthValue());
                    break;
                case 7:
                    healingLevelVO.setNextLevel(2000);
                    healingLevelVO.setDifferenceLevel(2000-tree.getGrowthValue());
                    break;
                case 8:
                    healingLevelVO.setNextLevel(2000);
                    healingLevelVO.setDifferenceLevel(2000-tree.getGrowthValue());
                    break;
                case 9:
                    healingLevelVO.setNextLevel(2400);
                    healingLevelVO.setDifferenceLevel(2400-tree.getGrowthValue());
                    break;
                case 10:
                    healingLevelVO.setNextLevel(2400);
                    healingLevelVO.setDifferenceLevel(2400-tree.getGrowthValue());
                    break;
            }
        }
        healingLevelVO.setGrowthValue(tree.getGrowthValue());
        String data1 = remoteUserService.getCourseList(7).getData();
        healingLevelVO.setContent(data1);
        return R.ok(healingLevelVO);
    }
    @PostMapping("/getTotalEnergyValue")
    @ApiOperation(value = "获取用户当前累计能量值",tags = "树苗打卡站")
    public R getTotalEnergyValue() {
        Long userId = SecurityUtils.getUserId();
        if (userId==0)return R.tokenError("登录失效");
        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("登录失效");
        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.getEducation());
        appUserService.update(byId, updateWrapper);
        return R.ok();
    }
    @PostMapping("/updateUserAvatar")
    @ApiOperation(value = "修改头像", tags = {"个人中心"})
    public R updateUserDetail(String avatar) {
        Long userId = SecurityUtils.getUserId();
        if (userId == 0)return R.tokenError("登录失效");
        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) {
        AppUser one = appUserService.lambdaQuery().eq(AppUser::getCellPhone, phone).one();
        AppUserDetailVO appUserDetailVO = new AppUserDetailVO();
        appUserDetailVO.setId(one.getId());
        appUserDetailVO.setCellPhone(one.getCellPhone());
        appUserDetailVO.setAvatar(one.getAvatar());
        appUserDetailVO.setNickname(one.getNickname());
        return R.ok(appUserDetailVO);
    }
    @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();
        return R.ok(one.getBalance().toString());
    }
    /**
@@ -71,6 +958,42 @@
        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);
    }
}