package com.ruoyi.im; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.im.comm.Result; import com.ruoyi.im.config.IpUtils; import com.ruoyi.im.dto.UpdateUserBusinessDto; import com.ruoyi.im.service.*; import com.ruoyi.im.dto.RegisterDto; import com.ruoyi.im.service.impl.InsurancePositionServiceImpl; import com.ruoyi.im.util.SymmetricCryptoUtil; import com.ruoyi.im.util.UserPolicyUtils; import com.ruoyi.im.util.ValidatorUtil; import com.ruoyi.system.domain.*; import com.ruoyi.system.domain.dto.SubordinateInformationDto; import com.ruoyi.system.domain.out.UserOut; import com.ruoyi.system.domain.out.UserTeamAndPositionOut; import com.ruoyi.system.domain.vo.UserAccountUpdateVo; import com.ruoyi.system.service.GroupWelcomeConfigService; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.IpBlacklistService; import com.ruoyi.system.service.UserAccountService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.*; import java.util.stream.Collectors; @RestController @RequestMapping("/im/api") @Slf4j public class ImApiController { @Autowired private ImApiServcie imApiServcie; @Autowired IpBlacklistService ipBlacklistService; @Autowired UserAccountService userAccountService; @Autowired GroupWelcomeConfigService groupWelcomeConfigService; @Autowired InsuranceProductService insuranceProductService; @Autowired MedicalInsuranceAccountService medicalInsuranceAccountService; @Autowired UserPolicyService userPolicyService; @Autowired InsurancePositionServiceImpl insurancePositionService; @Autowired UserKycService userKycService; @Autowired InsuranceFeatureService insuranceFeatureService; @Value("${file.upload-dir}") private String uploadDir; @Value("${file.upload-prefix}") private String prefix; /** * 注册 */ @PostMapping("/register") public Result register(@Validated RegisterDto dto){ try { // 验证手机号 boolean isPhoneValid = ValidatorUtil.isValidPhone(dto.getAccount()); if(!isPhoneValid){ return Result.error("手机号格式不正确"); } return imApiServcie.register(dto); } catch (RuntimeException e) { // 从异常消息中解析Result对象 return JSON.parseObject(e.getMessage(), Result.class); } } /** * 获取二维码链接和邀请码 */ @GetMapping("/getUserCodeAndUrl") public Result getUserCodeAndUrl(@RequestParam("account") String account){ try { GroupWelcomeConfig groupWelcomeConfig = groupWelcomeConfigService.getOne(new LambdaQueryWrapper<>(GroupWelcomeConfig.class) .eq(GroupWelcomeConfig::getConfigurationName, "IM-BASICS").last(" limit 1")); UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper().eq(UserAccount::getAccount, account)); Map map = new HashMap<>(); map.put("url",ObjectUtil.isNotEmpty(groupWelcomeConfig.getCodeUrl()) ? groupWelcomeConfig.getCodeUrl() : ""); map.put("code",userAccount.getInvitationCode()); return Result.success(map); } catch (RuntimeException e) { // 从异常消息中解析Result对象 return JSON.parseObject(e.getMessage(), Result.class); } } /** * 修改用户信息只有数据库 * @return */ @PostMapping("/updateUser") public Result updateUser(UserAccountUpdateVo vo){ try { UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper().eq(UserAccount::getAccount,vo.getAccountId())); if (StringUtils.isNotBlank(vo.getNickname())) { userAccount.setNickname(vo.getNickname()); } if (StringUtils.isNotBlank(vo.getSignature())) { userAccount.setSignature(vo.getSignature()); } userAccount.setUpdateTime(new Date()); userAccountService.updateById(userAccount); return Result.success(); } catch (RuntimeException e) { e.printStackTrace(); log.error("修改用户数据库信息失败"); return Result.error("修改失败!"); } } /** * 获取ip地址并判断是否在黑名单 */ @GetMapping("/blacklist") public Result blacklist(HttpServletRequest request,@RequestParam("account") String account){ try { String clientIp = IpUtils.getClientIp(request); if(StringUtils.isEmpty(clientIp)){ return Result.success(); } long count = ipBlacklistService.count(new LambdaQueryWrapper().eq(IpBlacklist::getIpAddress, clientIp)); if(count > 0){ return Result.error("账号异常,禁止登录!"); } UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<>(UserAccount.class).eq(UserAccount::getCloudMessageAccount, account)); if(ObjectUtil.isEmpty(userAccount)){ return Result.error("账号不存在!"); } userAccount.setLoginIp(clientIp); userAccount.setLoginTime(new Date()); userAccountService.updateById(userAccount); return Result.success(); }catch (Exception e){ log.error("登录错误:",e); return Result.error("登录错误,请稍后再试!"); } } @PostMapping("/upload") public Result uploadFile(@RequestParam("file") MultipartFile file,@RequestParam("accountId") String accountId) { try { // 1. 验证文件类型 String contentType = file.getContentType(); if (contentType == null || (!contentType.equals("image/jpeg") && !contentType.equals("image/png") && !contentType.equals("image/gif"))) { return Result.error("只支持JPEG、PNG和GIF格式的图片!"); } // 确保上传目录存在 File directory = new File(uploadDir); if (!directory.exists()) { directory.mkdirs(); // 设置目录权限为755 (rwxr-xr-x) setPermissions(directory, "rwxr-xr-x"); } // 生成唯一文件名 String fileName = UUID.randomUUID().toString() + "_" + file.getOriginalFilename(); Path filePath = Paths.get(uploadDir, fileName); // 保存文件 Files.write(filePath, file.getBytes()); // 设置文件权限为644 (rw-r--r--) setPermissions(filePath.toFile(), "rw-r--r--"); // 5. 调用网易云信API更新头像 fileName = prefix+"/"+fileName; UpdateUserBusinessDto dto = new UpdateUserBusinessDto(); dto.setAvatar(fileName); Map result = imApiServcie.updateUserAvatar(accountId,dto); if ((Boolean) result.get("success")) { return Result.success("文件上传成功"); } else { return Result.error("上传失败!"); } } catch (IOException e) { return Result.error("文件上传失败"); } catch (Exception e) { e.printStackTrace(); log.error("设置文件权限失败!"); } return Result.success(); } /** * 设置文件/目录权限 * @param file 文件或目录对象 * @param perm 权限字符串,如 "rw-r--r--" */ private void setPermissions(File file, String perm) throws IOException { // 获取当前操作系统 String os = System.getProperty("os.name").toLowerCase(); // 只有在Unix/Linux系统上才能设置POSIX权限 if (os.contains("nix") || os.contains("nux") || os.contains("mac")) { Set permissions = PosixFilePermissions.fromString(perm); Files.setPosixFilePermissions(file.toPath(), permissions); } else { // Windows系统不支持POSIX权限,可以设置基本权限 file.setReadable(true, false); // 所有用户可读 if (perm.startsWith("rw")) { file.setWritable(true, false); // 所有用户可写(如果权限字符串以rw开头) } else { file.setWritable(false, false); } // 如果是目录且包含执行权限,设置可执行 if (file.isDirectory() && perm.contains("x")) { file.setExecutable(true, false); } } } /** * 产品信息列表 */ @GetMapping("/list") public Result list() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(InsuranceProduct::getStatus, "ACTIVE"); // 按创建时间倒序排列 wrapper.orderByDesc(InsuranceProduct::getCreatedAt); List list = insuranceProductService.list(wrapper); return Result.success(list); } /** * 获取用户详情 */ @GetMapping("/getUserByAccount") public Result getUserByAccount(HttpServletRequest request,@RequestParam("account") String account){ try { String clientIp = IpUtils.getClientIp(request); if(StringUtils.isEmpty(clientIp)){ return Result.success(); } UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<>(UserAccount.class).eq(UserAccount::getCloudMessageAccount, account)); if(ObjectUtil.isEmpty(userAccount)){ return Result.error("账号不存在!"); } UserOut user = new UserOut(); MedicalInsuranceAccount insuranceAccount = medicalInsuranceAccountService.getOne(new LambdaQueryWrapper<>(MedicalInsuranceAccount.class) .eq(MedicalInsuranceAccount::getUserId, userAccount.getId()) .eq(MedicalInsuranceAccount::getAccountStatus, MedicalInsuranceAccount.AccountStatus.ACTIVE) ); user.setKycStatus(userAccount.getKycStatus()); if(ObjectUtil.isEmpty(insuranceAccount)){ return Result.success(user); } user.setAmountClaimed(insuranceAccount.getAmountClaimed()); user.setAlreadyReceived(insuranceAccount.getAlreadyReceived()); return Result.success(user); }catch (Exception e){ log.error("获取失败:",e); return Result.error("获取失败,请稍后再试!"); } } /** * 获取用户团队和职位 */ @GetMapping("/getUserTeamAndPosition") public Result getUserTeamAndPosition(@RequestParam("account") String account) { UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<>(UserAccount.class).eq(UserAccount::getCloudMessageAccount, account)); if(ObjectUtil.isEmpty(userAccount)){ return Result.error("账号不存在!"); } //查询当前用户的下级 List userAccountList = userAccountService.list(new LambdaQueryWrapper() .eq(UserAccount::getInvitationAccount, userAccount.getAccount()) ); UserTeamAndPositionOut userTeamAndPositionOut = new UserTeamAndPositionOut(); if(CollectionUtils.isEmpty(userAccountList)){ return Result.success(userTeamAndPositionOut); } List idList = userAccountList.stream() .map(UserAccount::getId) .collect(Collectors.toList()); List userPolicyList = userPolicyService.list(new LambdaQueryWrapper<>(UserPolicy.class) .in(UserPolicy::getUserId, idList) ); List informationDtos = new ArrayList<>(); userAccountList.forEach(f->{ userTeamAndPositionOut.setSubordinateNumber(userAccountList.size()); SubordinateInformationDto subordinateInformationDto = new SubordinateInformationDto(); subordinateInformationDto.setName(StringUtils.isEmpty(f.getNickname()) ? f.getAccount() : f.getNickname()); subordinateInformationDto.setPhone(f.getAccount()); subordinateInformationDto.setKycStatus(f.getKycStatus()); subordinateInformationDto.setIsActivate(UserPolicyUtils.hasActivePolicyForUser(userPolicyList,f.getId())); informationDtos.add(subordinateInformationDto); }); long activeNumber = UserPolicyUtils.countActivePolicies(userPolicyList); userTeamAndPositionOut.setInsureNumber(activeNumber); List positions = insurancePositionService.list(); positions.forEach(f->{ if(userPolicyList.size() >= f.getNumberPeople()){ userTeamAndPositionOut.setPosition(f.getPosition()); userTeamAndPositionOut.setSalary(f.getSalary()); } }); userTeamAndPositionOut.setInsurancePosition(positions); userTeamAndPositionOut.setSubordinateInformation(informationDtos); return Result.success(userTeamAndPositionOut); } /** * 获取用户实名认证 */ @GetMapping("/getUserKyc") public Result getUserKyc(@RequestParam("account") String account) { UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<>(UserAccount.class).eq(UserAccount::getCloudMessageAccount, account)); if(ObjectUtil.isEmpty(userAccount)){ return Result.error("账号不存在!"); } UserKyc userKyc = userKycService.getOne(new LambdaQueryWrapper<>(UserKyc.class) .eq(UserKyc::getUserId, userAccount.getId()) ); return Result.success(userKyc); } /** * 产品信息列表 */ @GetMapping("/getProduct") public Result getProduct() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); // 按创建时间倒序排列 wrapper.orderByDesc(InsuranceProduct::getCreatedAt); List list = insuranceProductService.list(wrapper); list.forEach(f->{ List features = insuranceFeatureService.list(new LambdaQueryWrapper() .eq(InsuranceFeature::getProductId, f.getId())); f.setProductFeature(features); }); return Result.success(list); } }