UsersService.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. package com.qxgmat.service;
  2. import com.github.pagehelper.Page;
  3. import com.nuliji.tools.AbstractService;
  4. import com.nuliji.tools.CipherHelp;
  5. import com.nuliji.tools.Tools;
  6. import com.nuliji.tools.Transform;
  7. import com.nuliji.tools.exception.AuthException;
  8. import com.nuliji.tools.exception.ParameterException;
  9. import com.nuliji.tools.exception.SystemException;
  10. import com.nuliji.tools.mybatis.Example;
  11. import com.nuliji.tools.mybatis.NativeJsonHandler;
  12. import com.nuliji.tools.third.OauthData;
  13. import com.qxgmat.data.constants.enums.status.DirectionStatus;
  14. import com.qxgmat.data.constants.enums.user.PrepareExaminationTime;
  15. import com.qxgmat.data.dao.UserMapper;
  16. import com.qxgmat.data.dao.entity.User;
  17. import com.qxgmat.data.inline.UserToken;
  18. import com.qxgmat.data.relation.UserRelationMapper;
  19. import com.qxgmat.data.relation.entity.UserPrepareRelation;
  20. import com.qxgmat.help.WechatHelp;
  21. import com.qxgmat.service.inline.UserClassService;
  22. import com.qxgmat.service.inline.UserMessageService;
  23. import com.qxgmat.service.inline.UserPayService;
  24. import com.qxgmat.service.inline.UserServiceService;
  25. import org.springframework.beans.factory.annotation.Value;
  26. import org.springframework.stereotype.Service;
  27. import org.springframework.transaction.annotation.Transactional;
  28. import javax.annotation.Resource;
  29. import java.util.*;
  30. /**
  31. * Created by GaoJie on 2017/11/1.
  32. */
  33. @Service
  34. public class UsersService extends AbstractService {
  35. final public String PLATORM_WECHAT_NATIVE = "wechat_openid_wechat";
  36. final public String PLATORM_WECHAT_PC = "wechat_openid_pc";
  37. final public String PLATORM_WECHAT = "wechat_unionid";
  38. @Value("${self.secret}")
  39. private String secret;
  40. private NativeJsonHandler<UserToken> tokenHandler = new NativeJsonHandler<UserToken>(UserToken.class);
  41. @Resource
  42. private UserMapper userMapper;
  43. @Resource
  44. private WechatHelp wechatHelp;
  45. @Resource
  46. private UserMessageService userMessageService;
  47. @Resource
  48. private UserPayService userPayService;
  49. @Resource
  50. private UserClassService userClassService;
  51. @Resource
  52. private UserServiceService userServiceService;
  53. @Resource
  54. private UserRelationMapper userRelationMapper;
  55. /**
  56. * 生成有效期token
  57. * @param user
  58. * @return
  59. */
  60. public String getTokenByUser(User user){
  61. UserToken ut = new UserToken();
  62. ut.setId(user.getId());
  63. Date expire = new Date(new Date().getTime() + 86400);
  64. ut.setExpire(expire);
  65. String info = tokenHandler.toJson(ut);
  66. return CipherHelp.encrypt(info, CipherHelp.DES, secret);
  67. }
  68. /**
  69. * 解析有效期token
  70. * @param token
  71. * @return
  72. */
  73. public User getUserByToken(String token){
  74. // 默认测试token
  75. if (token.equals("1234567890")){
  76. return get(1);
  77. }else{
  78. String info = CipherHelp.decrypt(token, CipherHelp.DES, secret);
  79. UserToken ut = tokenHandler.toObject(info);
  80. Date expire = ut.getExpire();
  81. if (expire.before(new Date())){
  82. throw new AuthException("token错误");
  83. }
  84. return get(ut.getId());
  85. }
  86. }
  87. /**
  88. * 绑定第三方账号信息
  89. * @param user 当前登录用户
  90. * @param code
  91. * @param platform
  92. * @return
  93. */
  94. @Transactional
  95. public User Oauth(User user, String code, String platform){
  96. OauthData data;
  97. switch(platform){
  98. case "wechat_pc":
  99. data = wechatHelp.oauthPc(code);
  100. break;
  101. case "wechat_native":
  102. data = wechatHelp.oauthNative(code);
  103. break;
  104. default:
  105. throw new ParameterException("第三方平台"+platform+"不支持");
  106. }
  107. // 获取已关联的账号
  108. if (user == null){
  109. user = getByOpen(data.getOpenId(), data.getUnionId(), platform);
  110. } else {
  111. // 检验是否已经绑定
  112. User openUser = getByOpen(data.getOpenId(), data.getUnionId(), platform);
  113. if(openUser != null && !openUser.getId().equals(user.getId())){
  114. // 自动合并账号
  115. // 更新消息
  116. userMessageService.mergeUser(openUser.getId(), user.getId());
  117. // 更新消费记录
  118. userPayService.mergeUser(openUser.getId(), user.getId());
  119. // 更新课程信息
  120. userClassService.mergeUser(openUser.getId(), user.getId());
  121. // 更新服务信息
  122. userServiceService.mergeUser(openUser.getId(), user.getId());
  123. // 更新实名认证
  124. if (openUser.getRealStatus() > 0){
  125. user.setRealAddress(openUser.getRealAddress());
  126. user.setRealIdentity(openUser.getRealIdentity());
  127. user.setRealName(openUser.getRealName());
  128. user.setRealPhotoFront(openUser.getRealPhotoFront());
  129. user.setRealPhotoBack(openUser.getRealPhotoBack());
  130. user.setRealStatus(openUser.getRealStatus());
  131. }
  132. // 删除旧账号
  133. delete(openUser.getId());
  134. }
  135. }
  136. if (user == null){
  137. user = new User();
  138. user.setAvatar(data.getAvatar());
  139. user.setNickname(data.getNickName());
  140. }
  141. switch(platform){
  142. case "wechat_pc":
  143. user.setWechatOpenidPc(data.getOpenId());
  144. user.setWechatUnionid(data.getUnionId());
  145. break;
  146. case "wechat_native":
  147. user.setWechatOpenidWechat(data.getOpenId());
  148. user.setWechatUnionid(data.getUnionId());
  149. user.setWechatAccessToken(data.getAccessToken());
  150. user.setWechatRefreshToken(data.getRefreshToken());
  151. user.setWechatExpireTime(data.getExpiresTime());
  152. break;
  153. }
  154. if (!user.getMobile().isEmpty()){
  155. // 直接更新数据
  156. edit(user);
  157. }
  158. return user;
  159. }
  160. /**
  161. * 通过手机号注册
  162. * @param mobile
  163. * @param inviteCode
  164. * @param openUser
  165. * @return
  166. */
  167. @Transactional
  168. public User register(String mobile, String inviteCode, User openUser){
  169. User user = getByMobile(mobile);
  170. if (user != null){
  171. throw new ParameterException("手机号已注册");
  172. }
  173. // 注册,并且绑定邀请者
  174. user = User.builder().mobile(mobile).build();
  175. if (inviteCode != null && !inviteCode.isEmpty()){
  176. User origin = getByInviteCode(inviteCode);
  177. user.setOriginId(origin.getId());
  178. // todo 按逻辑进行奖励
  179. edit(User.builder().id(origin.getId()).inviteNumber(origin.getInviteNumber() + 1).build());
  180. }
  181. // 绑定第三方登录信息
  182. if (openUser != null){
  183. user.setWechatOpenidPc(openUser.getWechatOpenidPc());
  184. user.setWechatOpenidWechat(openUser.getWechatOpenidWechat());
  185. user.setWechatExpireTime(openUser.getWechatExpireTime());
  186. user.setWechatUnionid(openUser.getWechatUnionid());
  187. user.setWechatAccessToken(openUser.getWechatAccessToken());
  188. user.setWechatRefreshToken(openUser.getWechatRefreshToken());
  189. user.setNickname(openUser.getNickname());
  190. user.setAvatar(openUser.getAvatar());
  191. }
  192. // 生成邀请码: 10位字符串
  193. user.setInviteCode(Tools.getRandomString(10));
  194. user = add(user);
  195. if(user == null)
  196. throw new SystemException("注册失败");
  197. return user;
  198. }
  199. // 获取微信快到期账号
  200. public Page<User> listByWechatExpire(int page, int size, Date expire){
  201. Example example = new Example(User.class);
  202. example.and(
  203. example.createCriteria()
  204. .andLessThan("wechatExpireTime", expire)
  205. );
  206. return page(()->select(userMapper, example), page, size);
  207. }
  208. // 通过手机号获取用户
  209. public User getByMobile(String mobile){
  210. User user = User.builder().mobile(mobile).build();
  211. return one(userMapper, user);
  212. }
  213. // 通过openid获取用户
  214. public User getByOpen(String openId, String unionId, String platform){
  215. String platformField;
  216. String unionField;
  217. switch(platform){
  218. case "wechat_pc":
  219. platformField = PLATORM_WECHAT_PC;
  220. unionField = PLATORM_WECHAT;
  221. break;
  222. case "wechat_native":
  223. platformField = PLATORM_WECHAT_NATIVE;
  224. unionField = PLATORM_WECHAT;
  225. break;
  226. default:
  227. throw new ParameterException("第三方平台"+platform+"不支持");
  228. }
  229. Example example = new Example(User.class);
  230. example.or(
  231. example.createCriteria()
  232. .andEqualTo(platformField, openId)
  233. );
  234. if (unionId != null && !unionId.isEmpty()){
  235. example.or(
  236. example.createCriteria()
  237. .andEqualTo(unionField, unionId)
  238. );
  239. }
  240. return one(userMapper, example);
  241. }
  242. /**
  243. * 通过邀请码或者手机好获取邀请人
  244. * @param inviteCode
  245. * @return
  246. */
  247. public User getByInviteCode(String inviteCode){
  248. User user = new User();
  249. Example example = new Example(User.class);
  250. // 查找手机或邀请码
  251. example.and(
  252. example.createCriteria()
  253. .orEqualTo("invite_code", inviteCode)
  254. .orEqualTo("mobile", inviteCode)
  255. );
  256. return one(userMapper, example);
  257. }
  258. /**
  259. * 获取备考统计:身份
  260. * @return
  261. */
  262. public List<UserPrepareRelation> statPrepareStatus(){
  263. return userRelationMapper.groupPrepareString("prepare_status");
  264. }
  265. /**
  266. * 获取备考统计:目标分数
  267. * @return
  268. */
  269. public List<UserPrepareRelation> statPrepareGoal(){
  270. List<UserPrepareRelation> relations = userRelationMapper.groupPrepareInteger("prepare_goal");
  271. // 按考分分组
  272. List<UserPrepareRelation> userPrepareRelationList = new ArrayList<>();
  273. Integer[] goalGroup = new Integer[]{600, 650, 700, 750};
  274. for(Integer goal : goalGroup){
  275. UserPrepareRelation real = new UserPrepareRelation();
  276. real.setI(goal);
  277. real.setNumber(0);
  278. userPrepareRelationList.add(real);
  279. }
  280. for(UserPrepareRelation relation : relations){
  281. int goal = -1;
  282. for(int i = 0; i < goalGroup.length; i++){
  283. // 根据考分判断层级
  284. if (goalGroup[i] > relation.getI()){
  285. // 属于上一层
  286. goal = i - 1;
  287. break;
  288. }
  289. }
  290. if (goal > 0){
  291. // 按层级归类
  292. UserPrepareRelation real = userPrepareRelationList.get(goal);
  293. real.setNumber(real.getNumber()+real.getNumber());
  294. }
  295. }
  296. return userPrepareRelationList;
  297. }
  298. /**
  299. * 获取备考统计:考试时间
  300. * @return
  301. */
  302. public List<UserPrepareRelation> statPrepareExaminationTime(){
  303. return userRelationMapper.groupPrepareString("prepare_examination_time");
  304. }
  305. /**
  306. * 获取备考统计:出分时间
  307. * @return
  308. */
  309. public List<UserPrepareRelation> statPrepareScoreTime(){
  310. // 直接按不同时间段统计
  311. Example example;
  312. List<UserPrepareRelation> userPrepareRelationList = new ArrayList<>();
  313. Calendar calendar = Calendar.getInstance();
  314. // 一个月内
  315. calendar.setTime(new Date());
  316. calendar.add(Calendar.MONTH, 1);
  317. example = new Example(User.class);
  318. example.and(
  319. example.createCriteria()
  320. .andLessThan("prepareScoreTime", calendar.getTime())
  321. );
  322. UserPrepareRelation oneMonth = new UserPrepareRelation();
  323. oneMonth.setS(PrepareExaminationTime.ONE_MONTH.key);
  324. oneMonth.setNumber(count(userMapper, example));
  325. userPrepareRelationList.add(oneMonth);
  326. // 两个月内
  327. calendar.setTime(new Date());
  328. calendar.add(Calendar.MONTH, 2);
  329. example = new Example(User.class);
  330. example.and(
  331. example.createCriteria()
  332. .andLessThan("prepareScoreTime", calendar.getTime())
  333. );
  334. UserPrepareRelation twoMonth = new UserPrepareRelation();
  335. twoMonth.setS(PrepareExaminationTime.TWO_MONTH.key);
  336. twoMonth.setNumber(count(userMapper, example) - oneMonth.getNumber());
  337. userPrepareRelationList.add(twoMonth);
  338. // 三个月内
  339. calendar.setTime(new Date());
  340. calendar.add(Calendar.MONTH, 3);
  341. example = new Example(User.class);
  342. example.and(
  343. example.createCriteria()
  344. .andLessThan("prepareScoreTime", calendar.getTime())
  345. );
  346. UserPrepareRelation threeMonth = new UserPrepareRelation();
  347. threeMonth.setS(PrepareExaminationTime.THREE_MONTH.key);
  348. threeMonth.setNumber(count(userMapper, example) - twoMonth.getNumber());
  349. userPrepareRelationList.add(twoMonth);
  350. // 半年
  351. calendar.setTime(new Date());
  352. calendar.add(Calendar.MONTH, 6);
  353. example = new Example(User.class);
  354. example.and(
  355. example.createCriteria()
  356. .andLessThan("prepareScoreTime", calendar.getTime())
  357. );
  358. UserPrepareRelation sixMonth = new UserPrepareRelation();
  359. sixMonth.setS(PrepareExaminationTime.SIX_MONTH.key);
  360. sixMonth.setNumber(count(userMapper, example) - threeMonth.getNumber());
  361. userPrepareRelationList.add(sixMonth);
  362. // 一年
  363. calendar.setTime(new Date());
  364. calendar.add(Calendar.MONTH, 12);
  365. example = new Example(User.class);
  366. example.and(
  367. example.createCriteria()
  368. .andLessThan("prepareScoreTime", calendar.getTime())
  369. );
  370. UserPrepareRelation oneYear = new UserPrepareRelation();
  371. oneYear.setS(PrepareExaminationTime.ONE_YEAR.key);
  372. oneYear.setNumber(count(userMapper, example) - sixMonth.getNumber());
  373. userPrepareRelationList.add(oneYear);
  374. // 其他
  375. example = new Example(User.class);
  376. example.and(
  377. example.createCriteria()
  378. // 设置过备考信息的人:mapper中做为基本条件
  379. .andGreaterThan("prepareGoal", 0)
  380. .andIsNull("prepareScoreTime")
  381. );
  382. UserPrepareRelation other = new UserPrepareRelation();
  383. other.setS(PrepareExaminationTime.ONE_YEAR.key);
  384. other.setNumber(count(userMapper, example));
  385. userPrepareRelationList.add(other);
  386. return userPrepareRelationList;
  387. }
  388. /**
  389. * 获取购买过课程的用户
  390. * @param page
  391. * @param pageSize
  392. * @param keyword
  393. * @param courseId
  394. * @return
  395. */
  396. public Page<User> listByCourse(int page, int pageSize, String keyword, Integer courseId){
  397. Page<User> p = page(()->{
  398. userRelationMapper.listByCourse(keyword, courseId);
  399. }, page, pageSize);
  400. Collection ids = Transform.getIds(p, User.class, "id");
  401. // 获取详细数据
  402. List<User> list = select(ids);
  403. Transform.replace(p, list, User.class, "id");
  404. return p;
  405. }
  406. /**
  407. * 获取总用户数
  408. * @return
  409. */
  410. public Integer count(){
  411. Example example = new Example(User.class);
  412. return count(userMapper, example);
  413. }
  414. public boolean equalsPassword(User user, String password){
  415. return Objects.equals(user.getPassword(), Tools.stringMD5(Tools.stringMD5(password)));
  416. }
  417. public boolean changePassword(User user, String password){
  418. User updateUser = User.builder().id(user.getId()).password(Tools.stringMD5(Tools.stringMD5(password))).build();
  419. int result = update(userMapper, updateUser);
  420. return result > 0;
  421. }
  422. public User add(User user){
  423. if(user.getPassword() != null) user.setPassword(Tools.stringMD5(user.getPassword()));
  424. int result = insert(userMapper, user);
  425. user = one(userMapper, user.getId());
  426. if(user == null){
  427. throw new SystemException("用户添加失败");
  428. }
  429. return user;
  430. }
  431. public User edit(User user){
  432. User in = one(userMapper, user.getId());
  433. if(in == null){
  434. throw new ParameterException("用户不存在");
  435. }
  436. if(user.getPassword() != null) user.setPassword(Tools.stringMD5(user.getPassword()));
  437. int result = update(userMapper, user);
  438. return user;
  439. }
  440. public boolean delete(Number id){
  441. User in = one(userMapper, id);
  442. if(in == null){
  443. throw new ParameterException("用户不存在");
  444. }
  445. int result = delete(userMapper, id);
  446. return result > 0;
  447. }
  448. public User get(Number id){
  449. User in = one(userMapper, id);
  450. if(in == null){
  451. throw new ParameterException("用户不存在");
  452. }
  453. return in;
  454. }
  455. public Page<User> select(int page, int pageSize){return select(userMapper, page, pageSize);
  456. }
  457. public Page<User> select(int page, int pageSize, String keyword, Boolean real, String order, DirectionStatus direction){
  458. Example example = new Example(User.class);
  459. if(keyword != null)
  460. example.and(
  461. example.createCriteria()
  462. .orLike("id", "%"+keyword+"%")
  463. .orLike("mobile", "%"+keyword+"%")
  464. );
  465. if (real != null)
  466. example.and(
  467. example.createCriteria().andEqualTo("realStatus", real?1:0)
  468. );
  469. if(order==null||order.isEmpty()) order = "id";
  470. if (direction != null){
  471. switch(direction){
  472. case ASC:
  473. example.orderBy(order).asc();
  474. break;
  475. case DESC:
  476. default:
  477. example.orderBy(order).desc();
  478. }
  479. } else {
  480. example.orderBy(order).desc();
  481. }
  482. return select(userMapper, example, page, pageSize);
  483. }
  484. public Page<User> select(Integer[] ids){
  485. return page(()->select(userMapper, ids), 1, ids.length);
  486. }
  487. public List<User> select(Collection ids){
  488. return select(userMapper, ids);
  489. }
  490. }