【原创】Code Demo-用户管理

UserController.java

package com.cpto.dapp.api.controller;

import com.cpto.dapp.auth.annotation.Auth;
import com.cpto.dapp.auth.annotation.CurrentUser;
import com.cpto.dapp.common.simple.SimpleResponseEntity;
import com.cpto.dapp.domain.User;
import com.cpto.dapp.pojo.dto.*;
import com.cpto.dapp.pojo.vo.InviteVO;
import com.cpto.dapp.pojo.vo.LoginVO;
import com.cpto.dapp.pojo.vo.UserVO;
import com.cpto.dapp.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.constraints.NotNull;

/**
 * 用户Controller
 *
 * @author sunli
 * @date 2018/12/29
 */
@Api(tags = "用户")
@RequestMapping("/users")
@RestController
@Validated
public class UserController extends BaseController {

    @Autowired
    private UserService userService;

    @ApiOperation(value = "注册【非token认证】", notes = "注册新的用户。", tags = "非token认证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "registerDTO", value = "用户注册信息", paramType = "body", dataType = "RegisterDTO", required = true)
    })
    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity register(@RequestBody @Validated RegisterDTO registerDTO) {
        userService.register(registerDTO);
        return SimpleResponseEntity.post();
    }

    @ApiOperation(value = "登录【非token认证】", notes = "通过检查用户名和密码,完成登录。", tags = "非token认证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "loginDTO", value = "用户登录信息", paramType = "body", dataType = "LoginDTO", required = true)
    })
    @PostMapping("/token")
    public ResponseEntity<LoginVO> login(@RequestBody @Validated LoginDTO loginDTO) {
        return SimpleResponseEntity.post(userService.login(loginDTO));
    }

    @ApiOperation(value = "注销", notes = "清除缓存中当前登录账号的token。")
    @DeleteMapping("/self/token")
    @Auth
    public ResponseEntity logout(@ApiIgnore @CurrentUser User user) {
        userService.logout(user);
        return SimpleResponseEntity.delete();
    }

    @ApiOperation(value = "取得用户信息", notes = "根据用户id,取得用户信息。")
    @GetMapping("/self")
    @Auth
    public ResponseEntity<UserVO> findUser(@ApiIgnore @CurrentUser User user) {
        return SimpleResponseEntity.get(userService.findUser(user));
    }

    @ApiOperation(value = "修改登录密码", notes = "修改登录密码时,设置新的密码。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "modifyPasswordDTO", value = "修改登录密码信息", paramType = "body", dataType = "ModifyPasswordDTO", required = true)
    })
    @PutMapping("/self/password")
    @Auth
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity modifyPassword(@ApiIgnore @CurrentUser User user,
                                         @RequestBody @Validated ModifyPasswordDTO modifyPasswordDTO) {
        userService.modifyPassword(user, modifyPasswordDTO);
        return SimpleResponseEntity.put();
    }

    @ApiOperation(value = "重置登录密码【非token认证】", notes = "忘记登录密码时,设置新的密码。", tags = "非token认证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "resetPasswordDTO", value = "重置登录密码信息", paramType = "body", dataType = "ResetPasswordDTO", required = true)
    })
    @PutMapping("/password")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity resetPassword(@RequestBody @Validated ResetPasswordDTO resetPasswordDTO) {
        userService.resetPassword(resetPasswordDTO);
        return SimpleResponseEntity.put();
    }

    @ApiOperation(value = "修改支付密码", notes = "修改支付密码时,设置新的密码。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "modifyPayPasswordDTO", value = "修改支付密码信息", paramType = "body", dataType = "ModifyPayPasswordDTO", required = true)
    })
    @PutMapping("/self/pay-password")
    @Auth
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity modifyPayPassword(@ApiIgnore @CurrentUser User user,
                                            @RequestBody @Validated ModifyPayPasswordDTO modifyPayPasswordDTO) {
        userService.modifyPayPassword(user, modifyPayPasswordDTO);
        return SimpleResponseEntity.put();
    }

    @ApiOperation(value = "重置支付密码【非token认证】", notes = "忘记支付密码时,设置新的密码。", tags = "非token认证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "resetPayPasswordDTO", value = "重置支付密码信息", paramType = "body", dataType = "ResetPayPasswordDTO", required = true)
    })
    @PutMapping("/pay-password")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity resetPayPassword(@RequestBody @Validated ResetPayPasswordDTO resetPayPasswordDTO) {
        userService.resetPayPassword(resetPayPasswordDTO);
        return SimpleResponseEntity.put();
    }

    @ApiOperation(value = "绑定手机号", notes = "注册成功后,修改手机号。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "setPhoneDTO", value = "绑定手机号信息", paramType = "body", dataType = "SetPhoneDTO", required = true)
    })
    @PutMapping("/self/phone")
    @Auth
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity setPhone(@ApiIgnore @CurrentUser User user,
                                   @RequestBody @Validated SetPhoneDTO setPhoneDTO) {
        userService.setPhone(user, setPhoneDTO);
        return SimpleResponseEntity.put();
    }

    @ApiOperation(value = "绑定邮箱", notes = "注册成功后,修改邮箱。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "setEmailDTO", value = "绑定邮箱信息", paramType = "body", dataType = "SetEmailDTO", required = true)
    })
    @PutMapping("/self/email")
    @Auth
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity setEmail(@ApiIgnore @CurrentUser User user,
                                   @RequestBody @Validated SetEmailDTO setEmailDTO) {
        userService.setEmail(user, setEmailDTO);
        return SimpleResponseEntity.put();
    }

    @ApiOperation(value = "设置是否订阅邮件", notes = "打开或关闭订阅邮件功能。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "subscribeMailDTO", value = "订阅邮件信息", paramType = "body", dataType = "SubscribeMailDTO", required = true)
    })
    @PutMapping("/self/email/subscription")
    @Auth
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity subscribeMail(@ApiIgnore @CurrentUser User user,
                                        @RequestBody @Validated SubscribeMailDTO subscribeMailDTO) {
        userService.subscribeMail(user, subscribeMailDTO);
        return SimpleResponseEntity.put();
    }

    @ApiOperation(value = "取得邀请信息", notes = "取得当前用户邀请码、邀请次数和app下载地址等信息。")
    @GetMapping("/self/invite")
    @Auth
    public ResponseEntity<InviteVO> findInviteInfo(@ApiIgnore @CurrentUser User user) {
        return SimpleResponseEntity.get(userService.findInviteInfo(user));
    }

    @ApiOperation(value = "根据邀请码查询用户信息【非token认证】", notes = "根据邀请码查询用户信息", tags = "非token认证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "inviteCode", value = "邀请码", paramType = "query", defaultValue = "ABCD1111", required = true)
    })
    @GetMapping("/invites/{inviteCode}")
    public ResponseEntity<UserVO> findUserByInviteCode(@PathVariable @NotNull(message = "邀请码不能为空") String inviteCode) {
        return SimpleResponseEntity.get(userService.findUserByInviteCode(inviteCode));
    }
}

UserServiceImpl.java

package com.cpto.dapp.service.impl;

import com.cpto.dapp.auth.AuthManager;
import com.cpto.dapp.common.helper.CsvHelper;
import com.cpto.dapp.common.util.*;
import com.cpto.dapp.constant.Constant;
import com.cpto.dapp.constant.ManagerLogConstant;
import com.cpto.dapp.constant.SettingsConstant;
import com.cpto.dapp.domain.ManagerAdmin;
import com.cpto.dapp.domain.SystemSettings;
import com.cpto.dapp.domain.User;
import com.cpto.dapp.enums.ErrorEnum;
import com.cpto.dapp.enums.StatusEnum;
import com.cpto.dapp.enums.VerifyCaseEnum;
import com.cpto.dapp.enums.VerifyTypeEnum;
import com.cpto.dapp.exception.*;
import com.cpto.dapp.pojo.dto.*;
import com.cpto.dapp.pojo.vo.InviteVO;
import com.cpto.dapp.pojo.vo.LoginVO;
import com.cpto.dapp.pojo.vo.PageVO;
import com.cpto.dapp.pojo.vo.UserVO;
import com.cpto.dapp.repository.UserRepository;
import com.cpto.dapp.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 用户ServiceImpl
 *
 * @author sunli
 * @date 2018/12/29
 */
@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private SystemSettingsService systemSettingsService;

    @Autowired
    private CodeService codeService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private WalletService walletService;

    @Autowired
    private AuthManager authManager;

    @Autowired
    private CsvHelper csvHelper;

    @Value("${custom.other.invite-reward-times}")
    private Integer inviteRewardTimes;

    /**
     * 注册新的用户
     *
     * @param registerDTO 注册信息
     */
    @Override
    public void register(RegisterDTO registerDTO) {

        /* 1.检查用户输入信息 */
        checkUserInputInfo(registerDTO);

        /* 2.检查邀请码 */
        Long parentId = null;
        if (ObjectUtil.isNotEmpty(registerDTO.getInviteCode())) {
            User parent = findByInviteCode(registerDTO.getInviteCode());
            parentId = parent.getId();
        }

        /* 3.检查验证码 */
        // 设置验证信息
        User userVerifyInfo = new User();
        userVerifyInfo.setAreaCode(registerDTO.getAreaCode());
        userVerifyInfo.setPhone(registerDTO.getPhone());
        userVerifyInfo.setEmail(registerDTO.getEmail());
        codeService.verifyCode(VerifyCaseEnum.REGISTER.getCode(), getSendTo(userVerifyInfo, registerDTO.getVerifyType()), registerDTO.getCode());

        /* 4.创建用户信息 */
        User user = createUser(registerDTO, parentId);

        /* 5.初始化用户账户信息 */
        accountService.initAccount(user.getId());

        /* 6.初始化用户钱包信息 */
        walletService.initWallet(user.getId());
    }

    /**
     * 登录处理
     *
     * @param loginDTO 登录信息
     * @return 登录信息
     */
    @Override
    public LoginVO login(LoginDTO loginDTO) {

        /* 1.根据登录账号查询用户信息 */
        User user = findUserByAccount(loginDTO.getAccount());

        /* 2.通过MD5加密登录密码 */
        String md5Password = StringUtil.toMd5(loginDTO.getPassword());

        /* 3.进行登录检查 */
        // 登录失败:用户名或密码错误的场合
        if (ObjectUtil.isEmpty(user) || ObjectUtil.notEquals(md5Password, user.getPassword())) {
            throw new LoginException();
        }

        // 登录失败:账号被禁用的场合
        if (ObjectUtil.equals(user.getStatus(), StatusEnum.INVALID.getCode())) {
            throw new AuthorizedException();
        }

        /* 4.创建token,并缓存 */
        String token = authManager.createToken(user.getId());

        /* 5.登录成功,返回登录信息 */
        LoginVO loginVO = new LoginVO();
        loginVO.setToken(token);

        return loginVO;
    }

    /**
     * 注销处理
     *
     * @param user 用户
     */
    @Override
    public void logout(User user) {
        // 清除缓存中的token
        authManager.removeToken(user.getId());
    }

    /**
     * 查询满足条件的用户
     *
     * @param searchTime      查询时间
     * @param page            当前页数
     * @param pageSize        每页条数
     * @param id              用户id
     * @param userName        用户名
     * @param areaCode        手机号归属地代码
     * @param phone           手机号
     * @param email           邮箱
     * @param isSubscribeMail 是否订阅
     * @param inviteCode      邀请码
     * @param parentId        上级邀请人
     * @param status          状态
     * @param remark          备注
     * @param fromCreatedTime 创建开始时间
     * @param toCreatedTime   创建结束时间
     * @return 用户列表
     */
    @Override
    public PageVO<UserVO> searchUser(Timestamp searchTime,
                                     Integer page,
                                     Integer pageSize,
                                     Long id,
                                     String userName,
                                     String areaCode,
                                     String phone,
                                     String email,
                                     Boolean isSubscribeMail,
                                     String inviteCode,
                                     Long parentId,
                                     Integer status,
                                     String remark,
                                     String fromCreatedTime,
                                     String toCreatedTime) {

        /* 1.生成动态查询条件 */
        // 返回查询时间之前的数据
        if (ObjectUtil.isEmpty(searchTime)) {
            searchTime = DateUtil.now();
        }

        Specification<User> specification = getSQLWhere(searchTime, id, userName, areaCode, phone, email, isSubscribeMail, inviteCode, parentId, status, remark, fromCreatedTime, toCreatedTime);

        /* 2.设置分页 */
        Sort sort = new Sort(Sort.Direction.DESC, Constant.SORT_KEY_ID);
        Pageable pageable = PageRequest.of(page, pageSize, sort);

        /* 3.进行查询 */
        Page<User> userPage = userRepository.findAll(specification, pageable);

        List<UserVO> userVOList = new ArrayList<>();
        for (User user : userPage) {
            userVOList.add(editUserVO(user));
        }

        PageVO<UserVO> userPageVO = new PageVO();
        userPageVO.setRows(userVOList);
        userPageVO.setTotal(userPage.getTotalElements());
        userPageVO.setTotalPage(userPage.getTotalPages());
        userPageVO.setHasNext(userPage.hasNext());
        userPageVO.setSearchTime(searchTime);

        return userPageVO;
    }

    /**
     * 根据id取得用户信息
     *
     * @param userId 用户id
     * @return 用户信息
     */
    @Override
    public UserVO findUser(Long userId) {
        User user = findUserById(userId);
        return editUserVO(user);
    }

    /**
     * 根据id取得用户信息
     *
     * @param user 用户
     * @return 用户信息
     */
    @Override
    public UserVO findUser(User user) {
        return editUserVO(user);
    }

    /**
     * 根据id取得用户信息
     *
     * @param userId 用户id
     * @return 用户信息
     */
    @Override
    public User getUser(Long userId) {
        return findUserById(userId);
    }

    /**
     * 生成动态查询条件
     *
     * @param searchTime      查询时间
     * @param id              用户id
     * @param userName        用户名
     * @param areaCode        手机号归属地代码
     * @param phone           手机号
     * @param email           邮箱
     * @param isSubscribeMail 是否订阅
     * @param inviteCode      邀请码
     * @param parentId        上级邀请人
     * @param status          状态
     * @param remark          备注
     * @param fromCreatedTime 创建开始时间
     * @param toCreatedTime   创建结束时间
     * @return 动态查询条件
     */
    private Specification<User> getSQLWhere(Timestamp searchTime,
                                            Long id,
                                            String userName,
                                            String areaCode,
                                            String phone,
                                            String email,
                                            Boolean isSubscribeMail,
                                            String inviteCode,
                                            Long parentId,
                                            Integer status,
                                            String remark,
                                            String fromCreatedTime,
                                            String toCreatedTime) {

        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {

                List<Predicate> predicatesList = new LinkedList<>();

                // 返回查询时间之前的数据
                if (ObjectUtil.isNotEmpty(searchTime)) {
                    predicatesList.add(cb.lessThanOrEqualTo(root.get("createdTime"), searchTime));
                }

                // 精确查询用户id
                if (ObjectUtil.isNotEmpty(id)) {
                    predicatesList.add(cb.equal(root.get("id"), id));
                }

                // 模糊查询用户名
                if (ObjectUtil.isNotEmpty(userName)) {
                    predicatesList.add(cb.like(cb.lower(root.get("userName")), "%" + userName.toLowerCase() + "%"));
                }

                // 精确查询归属地
                if (ObjectUtil.isNotEmpty(areaCode)) {
                    predicatesList.add(cb.equal(root.get("areaCode"), areaCode));
                }

                // 模糊查询手机号
                if (ObjectUtil.isNotEmpty(phone)) {
                    predicatesList.add(cb.like(root.get("phone"), "%" + phone + "%"));
                }

                // 模糊查询邮箱
                if (ObjectUtil.isNotEmpty(email)) {
                    predicatesList.add(cb.like(cb.lower(root.get("email")), "%" + email + "%"));
                }

                // 精确查询是否订阅
                if (ObjectUtil.isNotEmpty(isSubscribeMail)) {
                    predicatesList.add(cb.equal(root.get("isSubscribeMail"), isSubscribeMail));
                }

                // 精确查询邀请码
                if (ObjectUtil.isNotEmpty(inviteCode)) {
                    predicatesList.add(cb.equal(cb.lower(root.get("inviteCode")), inviteCode.toLowerCase()));
                }

                // 精确查询上级邀请人id
                if (ObjectUtil.isNotEmpty(parentId)) {
                    predicatesList.add(cb.equal(root.get("parentId"), parentId));
                }

                // 精确查询用户状态
                if (ObjectUtil.isNotEmpty(status)) {
                    predicatesList.add(cb.equal(root.get("status"), status));
                }

                // 模糊查询备注
                if (ObjectUtil.isNotEmpty(remark)) {
                    predicatesList.add(cb.like(cb.lower(root.get("remark")), "%" + remark.toLowerCase() + "%"));
                }

                // 范围查询创建时间
                if (ObjectUtil.isNotEmpty(fromCreatedTime)) {
                    predicatesList.add(cb.greaterThanOrEqualTo(root.get("createdTime"), Timestamp.valueOf(DateUtil.fullFromTime(fromCreatedTime))));
                }
                if (ObjectUtil.isNotEmpty(toCreatedTime)) {
                    predicatesList.add(cb.lessThanOrEqualTo(root.get("createdTime"), Timestamp.valueOf(DateUtil.fullToTime(toCreatedTime))));
                }

                // 返回生成的条件(条件为并且的关系)
                return cb.and(predicatesList.toArray(new Predicate[predicatesList.size()]));
            }
        };

        return specification;
    }

    /**
     * 检查用户输入信息
     *
     * @param registerDTO 新建的用户信息
     */
    private void checkUserInputInfo(RegisterDTO registerDTO) {

        /* 1.检查用户名是否存在 */
        existsUserName(registerDTO.getUserName());

        // 手机验证的场合
        if (ObjectUtil.equals(registerDTO.getVerifyType(), VerifyTypeEnum.PHONE.getCode())) {
            /* 2.检查手机号是否存在 */
            existsPhone(registerDTO.getAreaCode(), registerDTO.getPhone());
        }
        // 邮箱验证的场合
        else {
            /* 3.检查邮箱是否存在 */
            existsEmail(registerDTO.getEmail());
        }
    }

    /**
     * 创建用户信息
     *
     * @param registerDTO 新建的用户信息
     * @param parentId    上级推荐人id
     * @return 用户信息
     */
    private User createUser(RegisterDTO registerDTO, Long parentId) {

        User user = new User();

        if (ObjectUtil.equals(registerDTO.getVerifyType(), VerifyTypeEnum.PHONE.getCode())) {
            user.setAreaCode(registerDTO.getAreaCode());
            user.setPhone(registerDTO.getPhone());
        } else {
            user.setEmail(registerDTO.getEmail());
        }

        user.setId(IdUtil.generateIdByCurrentTime());
        user.setUserName(registerDTO.getUserName());
        user.setPassword(StringUtil.toMd5(registerDTO.getPassword()));
        user.setParentId(parentId);
        user.setIsSubscribeMail(false);
        user.setStatus(StatusEnum.VALID.getCode());
        user.setCreatedBy(null);
        user.setCreatedTime(DateUtil.now());

        // 生成邀请码
        String inviteCode;
        boolean existsByInviteCode;
        do {
            inviteCode = IdUtil.generateCode(8);
            existsByInviteCode = userRepository.existsByInviteCode(inviteCode);
        } while (existsByInviteCode);

        user.setInviteCode(inviteCode);

        user = userRepository.save(user);

        return user;
    }

    /**
     * 修改登录密码
     *
     * @param user              用户
     * @param modifyPasswordDTO 修改登录密码信息
     */
    @Override
    public void modifyPassword(User user, ModifyPasswordDTO modifyPasswordDTO) {
        setPassword(user, modifyPasswordDTO.getVerifyType(), modifyPasswordDTO.getCode(), modifyPasswordDTO.getPassword());
    }

    /**
     * 重置登录密码
     *
     * @param resetPasswordDTO 重置登录密码信息
     */
    @Override
    public void resetPassword(ResetPasswordDTO resetPasswordDTO) {

        /* 1.取得用户信息 */
        User user = findUserByVerifyInfo(resetPasswordDTO.getVerifyType(), resetPasswordDTO.getAreaCode(), resetPasswordDTO.getPhone(), resetPasswordDTO.getEmail());

        /* 2.设置登录密码 */
        setPassword(user, resetPasswordDTO.getVerifyType(), resetPasswordDTO.getCode(), resetPasswordDTO.getPassword());
    }

    /**
     * 设置登录密码
     *
     * @param user       用户信息
     * @param verifyType 验证方式
     * @param code       验证码
     * @param password   登录密码
     */
    private void setPassword(User user, Integer verifyType, String code, String password) {

        /* 1.检查验证码 */
        codeService.verifyCode(VerifyCaseEnum.PASSWORD.getCode(), getSendTo(user, verifyType), code);

        /* 2.修改登录密码 */
        user.setPassword(StringUtil.toMd5(password));
        user.setModifiedBy(null);
        user.setModifiedTime(DateUtil.now());
        userRepository.save(user);
    }

    /**
     * 修改支付密码
     *
     * @param user                 用户
     * @param modifyPayPasswordDTO 修改支付密码信息
     */
    @Override
    public void modifyPayPassword(User user, ModifyPayPasswordDTO modifyPayPasswordDTO) {
        setPayPassword(user, modifyPayPasswordDTO.getVerifyType(), modifyPayPasswordDTO.getCode(), modifyPayPasswordDTO.getPayPassword());
    }

    /**
     * 重置支付密码
     *
     * @param resetPayPasswordDTO 重置支付密码信息
     */
    @Override
    public void resetPayPassword(ResetPayPasswordDTO resetPayPasswordDTO) {

        /* 1.取得用户信息 */
        User user = findUserByVerifyInfo(resetPayPasswordDTO.getVerifyType(), resetPayPasswordDTO.getAreaCode(), resetPayPasswordDTO.getPhone(), resetPayPasswordDTO.getEmail());

        /* 2.设置支付密码 */
        setPayPassword(user, resetPayPasswordDTO.getVerifyType(), resetPayPasswordDTO.getCode(), resetPayPasswordDTO.getPayPassword());
    }

    /**
     * 设置支付密码
     *
     * @param user        用户信息
     * @param verifyType  验证方式
     * @param code        验证码
     * @param payPassword 支付密码
     */
    private void setPayPassword(User user, Integer verifyType, String code, String payPassword) {

        /* 1.检查验证码 */
        codeService.verifyCode(VerifyCaseEnum.PAY_PASSWORD.getCode(), getSendTo(user, verifyType), code);

        /* 2.修改登录密码 */
        user.setPayPassword(StringUtil.toMd5(payPassword));
        user.setModifiedBy(null);
        user.setModifiedTime(DateUtil.now());
        userRepository.save(user);
    }

    /**
     * 绑定手机号
     *
     * @param user        用户
     * @param setPhoneDTO 绑定手机号信息
     */
    @Override
    public void setPhone(User user, SetPhoneDTO setPhoneDTO) {

        /* 1.检查手机号是否存在 */
        existsPhone(setPhoneDTO.getAreaCode(), setPhoneDTO.getPhone());

        /* 2.检查验证码 */
        codeService.verifyCode(VerifyCaseEnum.PHONE.getCode(), setPhoneDTO.getAreaCode().concat(setPhoneDTO.getPhone()), setPhoneDTO.getCode());

        /* 3.设置手机号 */
        user.setAreaCode(setPhoneDTO.getAreaCode());
        user.setPhone(setPhoneDTO.getPhone());
        user.setModifiedBy(null);
        user.setModifiedTime(DateUtil.now());
        userRepository.save(user);
    }

    /**
     * 绑定邮箱
     *
     * @param user        用户
     * @param setEmailDTO 绑定邮箱信息
     */
    @Override
    public void setEmail(User user, SetEmailDTO setEmailDTO) {

        /* 1.检查邮箱是否存在 */
        existsEmail(setEmailDTO.getEmail());

        /* 2.检查验证码 */
        codeService.verifyCode(VerifyCaseEnum.EMAIL.getCode(), setEmailDTO.getEmail(), setEmailDTO.getCode());

        /* 3.设置手机号 */
        user.setEmail(setEmailDTO.getEmail());
        user.setModifiedBy(null);
        user.setModifiedTime(DateUtil.now());
        userRepository.save(user);
    }

    /**
     * 检查用户名是否存在
     *
     * @param userName 用户名
     */
    @Override
    public void existsUserName(String userName) {
        boolean existsByUserName = userRepository.existsByUserName(userName);
        if (existsByUserName) {
            throw new BusinessException(ErrorEnum.USER_EXISTED);
        }
    }

    /**
     * 检查手机号是否存在
     *
     * @param areaCode 手机号归属地代码
     * @param phone    手机号
     */
    @Override
    public void existsPhone(String areaCode, String phone) {
        boolean existsByAreaCodeAndPhone = userRepository.existsByAreaCodeAndPhone(areaCode, phone);
        if (existsByAreaCodeAndPhone) {
            throw new BusinessException(ErrorEnum.USER_EXISTED);
        }
    }

    /**
     * 检查邮箱是否存在
     *
     * @param email 邮箱
     */
    @Override
    public void existsEmail(String email) {
        boolean existsByEmail = userRepository.existsByEmail(email);
        if (existsByEmail) {
            throw new BusinessException(ErrorEnum.USER_EXISTED);
        }
    }

    /**
     * 设置是否订阅邮件
     *
     * @param user             用户
     * @param subscribeMailDTO 订阅邮件信息
     */
    @Override
    public void subscribeMail(User user, SubscribeMailDTO subscribeMailDTO) {
        user.setIsSubscribeMail(subscribeMailDTO.getIsSubscribeMail());
        user.setModifiedBy(null);
        user.setModifiedTime(DateUtil.now());
        userRepository.save(user);
    }

    /**
     * 修改用户信息
     *
     * @param admin   管理员
     * @param userId  被修改的用户id
     * @param userDTO 用户信息
     */
    @Override
    public void modifyUser(ManagerAdmin admin, Long userId, UserDTO userDTO) {

        /* 1.取得被修改的内容 */
        User user = userRepository.findNotNullById(userId);

        /* 2.检查最后修改时间,避免查询信息被修改过 */
        if (ObjectUtil.notEquals(userDTO.getModifiedTime(), user.getModifiedTime())) {
            throw new DataExpiredException();
        }

        /* 3.设置修改内容 */
        user.setRemark(userDTO.getRemark());
        user.setStatus(userDTO.getStatus());
        user.setModifiedBy(admin);
        user.setModifiedTime(DateUtil.now());
        userRepository.save(user);

        /* 4.记录日志 */
        managerLogService.saveManagerLog(admin, ManagerLogConstant.MODIFY_USER, userId);
    }

    /**
     * 取得邀请信息
     *
     * @param user 用户
     * @return 邀请信息
     */
    @Override
    public InviteVO findInviteInfo(User user) {

        /* 1.查询邀请信息 */
        /* 1.1.计算当前用户邀请次数 */
        Integer invitationTimes = userRepository.countByParentId(user.getId());

        /* 1.2.计算当前用户剩余奖励次数(奖励次数 - 已邀请次数) */
        Integer rewardTimes = inviteRewardTimes - invitationTimes;
        if (rewardTimes < 0) {
            rewardTimes = 0;
        }

        /* 1.3.app下载页面 */
        String urlAppDownloadParamKey = LanguageUtil.getTextByLanguage(SettingsConstant.URL_APP_DOWNLOAD.concat(SettingsConstant.ZH), SettingsConstant.URL_APP_DOWNLOAD.concat(SettingsConstant.EN));
        SystemSettings urlAppDownload = systemSettingsService.findSystemSettings(urlAppDownloadParamKey);

        /* 1.4.背景图地址 */
        String urlInvitePidParamKey = LanguageUtil.getTextByLanguage(SettingsConstant.URL_INVITE_PIC.concat(SettingsConstant.ZH), SettingsConstant.URL_INVITE_PIC.concat(SettingsConstant.EN));
        SystemSettings systemSettings = systemSettingsService.findSystemSettings(urlInvitePidParamKey);

        /* 2.返回邀请信息 */
        InviteVO inviteVO = new InviteVO();

        inviteVO.setInviteCode(user.getInviteCode());
        inviteVO.setInviteTimes(invitationTimes);
        inviteVO.setRewardTimes(rewardTimes);
        inviteVO.setDownloadUrl(urlAppDownload.getParamValue());
        inviteVO.setBackgroundUrl(systemSettings.getParamValue());

        return inviteVO;
    }

    /**
     * 导出用户邮箱列表
     *
     * @return 导出数据
     */
    @Override
    public ResponseEntity downloadEmail() {

        String fileName = "email.csv";

        List<User> userList = userRepository.findByIsSubscribeMailIsTrue();
        if (ObjectUtil.isEmptyCollection(userList)) {
            throw new DataNotFoundException();
        }

        String[] title = {"id", "用户名", "邮箱地址"};
        List<String[]> dataList = new ArrayList<>();

        String[] data;
        for (User user : userList) {
            data = new String[3];
            data[0] = String.valueOf(user.getId());
            data[1] = user.getUserName();
            data[2] = user.getEmail();
            dataList.add(data);
        }

        ResponseEntity responseEntity;

        try {
            responseEntity = csvHelper.download(fileName, title, dataList);
        } catch (IOException e) {
            throw new ActionException();
        }

        return responseEntity;
    }

    /**
     * 根据邀请码查询用户信息
     *
     * @param inviteCode 邀请码
     * @return 用户信息
     */
    @Override
    public UserVO findUserByInviteCode(String inviteCode) {

        /* 1.取得用户信息 */
        User user = findByInviteCode(inviteCode);
        if (ObjectUtil.isEmpty(user)) {
            throw new DataNotFoundException();
        }

        /* 2.设置项目信息 */
        return editUserVO(user);
    }

    /**
     * 取得验证码发送地址
     *
     * @param user       用户信息
     * @param verifyType 验证方式
     * @return 验证码发送地址
     */
    private String getSendTo(User user, Integer verifyType) {
        // 手机短信验证的场合,返回手机号码
        if (ObjectUtil.equals(verifyType, VerifyTypeEnum.PHONE.getCode())) {
            return user.getAreaCode().concat(user.getPhone());
        }
        // 邮件验证的场合,返回邮箱
        else {
            return user.getEmail();
        }
    }

    /**
     * 编辑用户VO
     *
     * @param user 用户信息
     * @return 用户VO
     */
    private UserVO editUserVO(User user) {

        UserVO userVO = new UserVO();

        userVO.setId(user.getId());
        userVO.setUserName(user.getUserName());
        userVO.setHasPayPassword(ObjectUtil.isNotEmpty(user.getPayPassword()) ? true : false);
        userVO.setAreaCode(user.getAreaCode());
        userVO.setPhone(user.getPhone());
        userVO.setEmail(user.getEmail());
        userVO.setIsSubscribeMail(user.getIsSubscribeMail());
        userVO.setInviteCode(user.getInviteCode());
        userVO.setParentId(user.getParentId());
        userVO.setRemark(user.getRemark());
        userVO.setStatus(user.getStatus());
        userVO.setStatusName(StatusEnum.getNameByCode(user.getStatus()));
        userVO.setCreatedBy(ObjectUtil.isNotEmpty(user.getCreatedBy()) ? user.getCreatedBy().getName() : null);
        userVO.setCreatedTime(user.getCreatedTime());
        userVO.setModifiedBy(ObjectUtil.isNotEmpty(user.getModifiedBy()) ? user.getModifiedBy().getName() : null);
        userVO.setModifiedTime(user.getModifiedTime());

        return userVO;
    }

    /**
     * 根据用户id查询用户信息
     *
     * @param userId 用户id
     * @return 用户信息
     */
    private User findUserById(Long userId) {
        return userRepository.findNotNullById(userId);
    }


    /**
     * 根据验证信息查询用户信息
     *
     * @param verifyType 验证方式
     * @param areaCode   手机号归属地代码
     * @param phone      手机号
     * @param email      邮箱
     * @return 用户信息
     */
    private User findUserByVerifyInfo(Integer verifyType, String areaCode, String phone, String email) {

        User user;

        if (ObjectUtil.equals(verifyType, VerifyTypeEnum.PHONE.getCode())) {
            user = userRepository.findByAreaCodeAndPhone(areaCode, phone);
        } else {
            user = userRepository.findByEmail(email);
        }

        if (ObjectUtil.isEmpty(user)) {
            throw new DataNotFoundException();
        }

        return user;
    }

    /**
     * 根据登录账号查询用户信息
     *
     * @param account 登录账号
     * @return 用户信息
     */
    private User findUserByAccount(String account) {

        /* 1.用户名方式登录 */
        User user = userRepository.findByUserName(account);
        if (ObjectUtil.isNotEmpty(user)) {
            return user;
        }

        /* 2.手机号方式登录 */
        // 登录时可能输入【手机号】或者【归属地代码+手机号】两种格式
        List<User> userList = userRepository.findByPhone(account);
        if (ObjectUtil.isNotEmptyCollection(userList)) {
            // 未输入归属地代码的场合,手机号可能相同
            if (userList.size() > 1) {
                // 提示请输入归属地代码
                throw new BusinessException(ErrorEnum.AREA_CODE_NOT_SET);
            } else {
                return userList.get(0);
            }
        }

        /* 3.邮箱方式登录 */
        user = userRepository.findByEmail(account);

        return user;
    }

    /**
     * 根据邀请码查询用户信息
     *
     * @param inviteCode 邀请码
     * @return 用户信息
     */
    @Override
    public User findByInviteCode(String inviteCode) {
        User user = userRepository.findByInviteCode(inviteCode);
        if (ObjectUtil.isEmpty(user)) {
            throw new BusinessException(ErrorEnum.INVITATION_CODE_ERROR);
        }
        return user;
    }
}

UserRepository.java

package com.cpto.dapp.repository;


import com.cpto.dapp.domain.User;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

/**
 * 用户Repository
 *
 * @author sunli
 * @date 2018/12/29
 */
public interface UserRepository extends BaseRepository<User, Long>, JpaSpecificationExecutor<User> {

    /**
     * 根据用户名查询用户信息
     *
     * @param userName 用户名
     * @return 用户信息
     */
    User findByUserName(String userName);

    /**
     * 根据邀请码查询用户信息
     *
     * @param inviteCode 邀请码
     * @return 用户信息
     */
    User findByInviteCode(String inviteCode);

    /**
     * 根据手机号查询用户信息
     *
     * @param areaCode 手机号归属地代码
     * @param phone    手机号
     * @return 用户信息
     */
    User findByAreaCodeAndPhone(String areaCode, String phone);

    /**
     * 根据手机号查询用户信息
     *
     * @param phone 手机号
     * @return 用户信息
     */
    @Query(nativeQuery = true, value = "select * from user where phone = :phone or concat(area_code, phone) = :phone")
    List<User> findByPhone(String phone);

    /**
     * 根据邮箱查询用户信息
     *
     * @param email 邮箱
     * @return 用户信息
     */
    User findByEmail(String email);

    /**
     * 检查用户名是否存在
     *
     * @param userName 用户名
     * @return 是否存在
     */
    boolean existsByUserName(String userName);

    /**
     * 检查手机号是否存在
     *
     * @param areaCode 手机号归属地代码
     * @param phone    手机号
     * @return 是否存在
     */
    boolean existsByAreaCodeAndPhone(String areaCode, String phone);

    /**
     * 检查邮箱是否存在
     *
     * @param email 邮箱
     * @return 是否存在
     */
    boolean existsByEmail(String email);

    /**
     * 检查邀请码是否存在
     *
     * @param inviteCode 邀请码
     * @return 是否存在
     */
    boolean existsByInviteCode(String inviteCode);

    /**
     * 查询该用户邀请次数
     *
     * @param userId 用户id
     * @return 邀请次数
     */
    Integer countByParentId(Long userId);

    /**
     * 查询订阅邮件的用户信息
     *
     * @return 用户信息
     */
    List<User> findByIsSubscribeMailIsTrue();
}

User.java

package com.cpto.dapp.domain;


import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

/**
 * 用户
 *
 * @author sunli
 * @date 2018/12/27
 */
@Data
@Entity
@org.hibernate.annotations.Table(appliesTo = "user", comment = "用户")
public class User extends Base {

    @Id
    @Column(columnDefinition = "bigint unsigned comment 'id'", nullable = false)
    private Long id;

    @Column(columnDefinition = "varchar(16) unique comment '用户名'", nullable = false)
    private String userName;

    @Column(columnDefinition = "char(32) comment '登录密码'", nullable = false)
    private String password;

    @Column(columnDefinition = "char(32) comment '支付密码'")
    private String payPassword;

    @Column(columnDefinition = "varchar(4) comment '手机号归属地代码'")
    private String areaCode;

    @Column(columnDefinition = "varchar(32) comment '手机号'")
    private String phone;

    @Column(columnDefinition = "varchar(50) unique comment '邮箱'")
    private String email;

    @Column(columnDefinition = "tinyint unsigned default 0 comment '是否订阅邮件(0:否,1:是)'")
    private Boolean isSubscribeMail;

    @Column(columnDefinition = "char(8) unique comment '邀请码'")
    private String inviteCode;

    @Column(columnDefinition = "bigint unsigned comment '上级邀请人id'")
    private Long parentId;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。