TeamService.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. package com.izouma.walkchina.service;
  2. import cn.binarywang.wx.miniapp.api.WxMaService;
  3. import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
  4. import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
  5. import com.izouma.walkchina.constant.AppConstants;
  6. import com.izouma.walkchina.constant.Strings;
  7. import com.izouma.walkchina.domain.Message;
  8. import com.izouma.walkchina.domain.TeamMember;
  9. import com.izouma.walkchina.domain.UserInfo;
  10. import com.izouma.walkchina.domain.WalkData;
  11. import com.izouma.walkchina.dto.UserDTO;
  12. import com.izouma.walkchina.exception.ServiceException;
  13. import com.izouma.walkchina.repo.*;
  14. import com.izouma.walkchina.utils.ImageUtils;
  15. import lombok.extern.slf4j.Slf4j;
  16. import me.chanjar.weixin.common.error.WxErrorException;
  17. import org.springframework.beans.factory.annotation.Autowired;
  18. import org.springframework.stereotype.Service;
  19. import javax.imageio.ImageIO;
  20. import java.awt.*;
  21. import java.awt.image.BufferedImage;
  22. import java.io.IOException;
  23. import java.math.BigDecimal;
  24. import java.net.URL;
  25. import java.time.LocalDate;
  26. import java.time.LocalDateTime;
  27. import java.util.ArrayList;
  28. import java.util.List;
  29. import java.util.Optional;
  30. import static java.time.temporal.ChronoUnit.DAYS;
  31. @Service
  32. @Slf4j
  33. public class TeamService {
  34. @Autowired
  35. private TeamMemberRepository teamMemberRepository;
  36. @Autowired
  37. private UserInfoRepository userInfoRepository;
  38. @Autowired
  39. private MessageRepository messageRepository;
  40. @Autowired
  41. private WalkDataRepository walkDataRepository;
  42. @Autowired
  43. private FriendInfoRepository friendInfoRepository;
  44. @Autowired
  45. private CoinService coinService;
  46. @Autowired
  47. private WxMaService wxMaService;
  48. @Autowired
  49. private FormIdService formIdService;
  50. @Autowired
  51. private UserInfoService userInfoService;
  52. public void hire(Long userId, Long target) {
  53. LocalDateTime now = LocalDateTime.now();
  54. UserInfo userInfo = userInfoRepository.findById(userId).orElseThrow(new ServiceException("用户不存在"));
  55. UserInfo targetUserInfo = userInfoRepository.findById(target).orElseThrow(new ServiceException("用户不存在"));
  56. TeamMember teamMember = teamMemberRepository.findCurrent(target, now.toLocalDate());
  57. if (teamMember != null) {
  58. if (teamMember.getLeader().equals(userId)) {
  59. throw new ServiceException("Ta已经是你的队员");
  60. }
  61. if (teamMember.getStartDate().atTime(0, 0).isAfter(now)) {
  62. throw new ServiceException(Strings.GRAB_FAIL);
  63. }
  64. teamMember.setEndDate(now.toLocalDate());
  65. teamMember.setGrabbed(true);
  66. teamMemberRepository.save(teamMember);
  67. Message grabMsg = Message.builder()
  68. .userId(teamMember.getLeader())
  69. .type(AppConstants.MessageType.NORMAL)
  70. .content(String.format(Strings.MSG_MEMBER_GRABBED, targetUserInfo.getNickname(), userInfo.getNickname()))
  71. .active(true)
  72. .isRead(false)
  73. .build();
  74. messageRepository.save(grabMsg);
  75. }
  76. BigDecimal price = Optional.ofNullable(userInfo.getPrice()).orElse(AppConstants.MIN_PRICE);
  77. BigDecimal balance = Optional.ofNullable(userInfo.getCoin()).orElse(BigDecimal.ZERO);
  78. if (balance.compareTo(price) < 0) {
  79. throw new ServiceException("雇佣失败,商城币不足");
  80. }
  81. coinService.balanceChange(userInfo, price.negate(), AppConstants.CoinRecordType.HIRE, Strings.REMARK_HIRE, null);
  82. coinService.balanceChange(targetUserInfo, price, AppConstants.CoinRecordType.BE_HIRED, Strings.REMARK_BE_HIRED,
  83. String.format(Strings.MSG_HIRED, userInfo.getNickname(), price));
  84. TeamMember newTeamMember = TeamMember.builder()
  85. .userId(target)
  86. .leader(userId)
  87. .hireDate(now.toLocalDate())
  88. .startDate(now.toLocalDate())
  89. .endDate(AppConstants.FOREVER)
  90. .active(true)
  91. .build();
  92. teamMemberRepository.save(newTeamMember);
  93. userInfoService.updateUserPrice(targetUserInfo);
  94. }
  95. public boolean canHire(Long userId, Long target) {
  96. if (userId.equals(target)) {
  97. return false;
  98. }
  99. TeamMember teamMember = teamMemberRepository.findCurrent(target, LocalDate.now());
  100. if (teamMember != null) {
  101. return !teamMember.getLeader().equals(userId);
  102. }
  103. return true;
  104. }
  105. public List<UserDTO> userTeam(Long userId) {
  106. List<UserDTO> list = teamMemberRepository.findUserTeam(userId);
  107. for (UserDTO userDTO : list) {
  108. WalkData walkData = walkDataRepository.findByUserIdAndDate(userDTO.getUserId(), LocalDate.now());
  109. if (walkData != null) {
  110. userDTO.setTodaySteps(walkData.getSteps());
  111. } else {
  112. userDTO.setTodaySteps(0L);
  113. userDTO.setShouldWake(true);
  114. }
  115. }
  116. return list;
  117. }
  118. public List<UserDTO> userFriend(Long userId) {
  119. LocalDate now = LocalDate.now();
  120. List<UserDTO> list = friendInfoRepository.findUserFriend(userId);
  121. for (UserDTO userDTO : list) {
  122. WalkData walkData = walkDataRepository.findByUserIdAndDate(userDTO.getUserId(), now);
  123. if (walkData != null) {
  124. userDTO.setTodaySteps(walkData.getSteps());
  125. } else {
  126. userDTO.setTodaySteps(0L);
  127. }
  128. TeamMember teamMember = teamMemberRepository.findCurrent(userDTO.getUserId(), now);
  129. if (teamMember != null) {
  130. userDTO.setHiredBy(teamMember.getLeader());
  131. userDTO.setHireDate(teamMember.getHireDate());
  132. }
  133. }
  134. return list;
  135. }
  136. public UserDTO userLeader(Long userId) {
  137. UserDTO userDTO = teamMemberRepository.findLeader(userId, LocalDate.now());
  138. if (userDTO == null) {
  139. return null;
  140. }
  141. WalkData walkData = walkDataRepository.findByUserIdAndDate(userDTO.getUserId(), LocalDate.now());
  142. if (walkData != null) {
  143. userDTO.setTodaySteps(walkData.getSteps());
  144. } else {
  145. userDTO.setTodaySteps(0L);
  146. }
  147. return userDTO;
  148. }
  149. public BufferedImage recruitImg(Long userId) throws IOException, FontFormatException, WxErrorException {
  150. UserInfo userInfo = userInfoRepository.findById(userId).orElseThrow(new ServiceException("用户不存在"));
  151. Font pingFangRegular = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/static/PingFangRegular.ttf"));
  152. Font pingFangMedium = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/static/PingFangMedium.ttf"));
  153. Font robot = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/static/Roboto-Black.ttf"));
  154. BufferedImage shareImg = ImageIO.read(this.getClass().getResourceAsStream("/static/share_img.png"));
  155. Graphics2D g = shareImg.createGraphics();
  156. g.setComposite(AlphaComposite.Src);
  157. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  158. g.setComposite(AlphaComposite.SrcOver);
  159. BufferedImage avatarImg = ImageUtils.makeRoundedCorner(ImageUtils
  160. .scale(ImageIO.read(new URL(userInfo.getAvatar())),
  161. 46 * 3, 46 * 3,
  162. ImageUtils.Fit.COVER), 23 * 3);
  163. g.drawImage(avatarImg, 145 * 3, 177 * 3, null);
  164. BufferedImage levelImg = ImageIO.read(this.getClass().getResourceAsStream("/static/level_" + userInfo.getLevel() + ".png"));
  165. g.drawImage(levelImg, (shareImg.getWidth() - levelImg.getWidth()) / 2, 251 * 3, null);
  166. Font nicknameFont = pingFangRegular.deriveFont(14f * 3);
  167. g.setColor(Color.BLACK);
  168. ImageUtils.drawCenteredString(g, userInfo.getNickname(), new Rectangle(0, 230 * 3, shareImg.getWidth(), 20 * 3), nicknameFont);
  169. Font walkDataFont = pingFangMedium.deriveFont(17f * 3);
  170. ImageUtils.drawCenteredString(g, DAYS.between(userInfo.getCreatedAt(), LocalDateTime.now()) + 1 + "", new Rectangle(20 * 3, 295 * 3, 295 * 3 / 2, 24 * 3), walkDataFont);
  171. ImageUtils.drawCenteredString(g, String.valueOf(userInfo.getWalkCities()), new Rectangle(295 * 3 / 2 + 20 * 3, 295 * 3, 295 * 3 / 2, 24 * 3), walkDataFont);
  172. ImageUtils.drawCenteredString(g, String.valueOf(userInfo.getTotalSteps()), new Rectangle(20 * 3, 353 * 3, 295 * 3 / 2, 24 * 3), walkDataFont);
  173. ImageUtils.drawCenteredString(g, coinService.totalAward(userId).toString(), new Rectangle(295 * 3 / 2 + 20 * 3, 353 * 3, 295 * 3 / 2, 24 * 3), walkDataFont);
  174. Font labelFont = pingFangRegular.deriveFont(12f * 3);
  175. g.setColor(new Color(128, 128, 128));
  176. ImageUtils.drawCenteredString(g, "参赛天数", new Rectangle(20 * 3, 321 * 3, 295 * 3 / 2, 24 * 3), labelFont);
  177. ImageUtils.drawCenteredString(g, "途经城市", new Rectangle(295 * 3 / 2 + 20 * 3, 321 * 3, 295 * 3 / 2, 24 * 3), labelFont);
  178. ImageUtils.drawCenteredString(g, "总步数", new Rectangle(20 * 3, 376 * 3, 295 * 3 / 2, 24 * 3), labelFont);
  179. ImageUtils.drawCenteredString(g, "获得奖金", new Rectangle(295 * 3 / 2 + 20 * 3, 376 * 3, 295 * 3 / 2, 24 * 3), labelFont);
  180. String userNum = String.valueOf(userInfoRepository.count() + 10000);
  181. Font numberFont = robot.deriveFont(39f * 3);
  182. g.setColor(new Color(76, 128, 255));
  183. g.setFont(numberFont);
  184. g.drawString(userNum, 20 * 3, 505 * 3);
  185. int numberWidth = g.getFontMetrics(numberFont).stringWidth(userNum);
  186. g.setFont(pingFangRegular.deriveFont(14f * 3));
  187. g.drawString("位", 20 * 3 + numberWidth, 505 * 3);
  188. // byte[] bytes = wxMaService.getQrcodeService().createWxaCodeUnlimitBytes("recruit", "pages/home/home?from=" + userId, 72 * 3, true, new WxMaCodeLineColor("0", "0", "0"), true);
  189. // ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
  190. // BufferedImage codeImg = ImageIO.read(byteArrayInputStream);
  191. BufferedImage codeImg = ImageIO.read(this.getClass().getResourceAsStream("/static/wxaqrcode.jpg"));
  192. g.drawImage(ImageUtils.scale(codeImg, 72 * 3, 72 * 3, ImageUtils.Fit.COVER), 235 * 3, 425 * 3, null);
  193. return shareImg;
  194. }
  195. public void wake(Long userId, Long target) throws WxErrorException {
  196. UserInfo userInfo = userInfoRepository.findById(userId).orElseThrow(new ServiceException("用户不存在"));
  197. UserInfo targetUserInfo = userInfoRepository.findById(target).orElseThrow(new ServiceException("用户不存在"));
  198. String formId = formIdService.get(target);
  199. if (formId == null) {
  200. return;
  201. }
  202. List<WxMaTemplateData> templateData = new ArrayList<>();
  203. templateData.add(new WxMaTemplateData("keyword1", "你的好友" + userInfo.getNickname() + "邀请您继续比赛"));
  204. templateData.add(new WxMaTemplateData("keyword2", "点击进入小程序"));
  205. WxMaTemplateMessage msg = new WxMaTemplateMessage(targetUserInfo.getOpenId(), "dSqxPurf6VpMUwUD0bhF7Hwt4fA5y_Pa441MepRWScE",
  206. "/pages/home/home", formId, templateData, null);
  207. wxMaService.getMsgService().sendTemplateMsg(msg);
  208. }
  209. public void recruit(Long userId, Long target) {
  210. UserInfo userInfo = userInfoRepository.findById(userId).orElseThrow(new ServiceException("用户不存在"));
  211. UserInfo targetUserInfo = userInfoRepository.findById(target).orElseThrow(new ServiceException("用户不存在"));
  212. TeamMember teamMember = teamMemberRepository.findCurrent(target, LocalDate.now());
  213. if (teamMember != null) {
  214. return;
  215. }
  216. TeamMember newTeamMember = TeamMember.builder()
  217. .userId(target)
  218. .leader(userId)
  219. .hireDate(LocalDate.now())
  220. .startDate(LocalDate.now())
  221. .endDate(AppConstants.FOREVER)
  222. .active(true)
  223. .build();
  224. teamMemberRepository.save(newTeamMember);
  225. userInfoService.updateUserPrice(targetUserInfo);
  226. }
  227. }