admin
2025-02-11 8cc47cfe4c6d6b48e62cf00f6cbd0951ec57c264
整体系统结构完善
3个文件已修改
29个文件已添加
1639 ■■■■■ 已修改文件
pom.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/aspect/SignValidateAspect.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/controller/user/LoginController.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/dao/config/SystemConfigMapper.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/dao/user/UserAuthMapper.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/dao/user/UserMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/dto/QQUserInfo.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/SystemEnum.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/config/SystemConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/config/SystemConfigKeyEnum.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/user/IdentityType.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/user/User.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/user/UserAuth.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/exception/BaseException.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/exception/ParamsException.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/exception/SMSException.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/exception/user/UserException.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/factory/user/UserAuthFactory.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/impl/config/SystemConfigServiceImpl.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/impl/user/UserServiceImpl.java 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/inter/config/SystemConfigService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/inter/user/UserService.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/utils/AliyunOneKeyLoginUtil.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/utils/Constant.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/utils/SystemInfoUtil.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/utils/TencentSMSUtil.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/vo/AcceptData.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/SystemConfigMapper.xml 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/UserAuthMapper.xml 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/UserMapper.xml 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/everyday/word/MapperTest.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/everyday/word/WordsTest.java 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -230,6 +230,41 @@
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.5.2</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dypnsapi</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.qcloud</groupId>
            <artifactId>cmq-http-client</artifactId>
            <version>1.0.7</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.qcloud</groupId>
            <artifactId>cos_api</artifactId>
            <version>5.2.4</version>
        </dependency>
        <!-- 腾讯云短信 -->
        <dependency>
            <groupId>com.github.qcloudsms</groupId>
            <artifactId>qcloudsms</artifactId>
            <version>1.0.2</version>
        </dependency>
src/main/java/com/everyday/word/aspect/SignValidateAspect.java
New file
@@ -0,0 +1,133 @@
package com.everyday.word.aspect;
import com.everyday.word.utils.Constant;
import com.everyday.word.utils.SystemInfoUtil;
import com.everyday.word.vo.AcceptData;
import net.sf.json.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.util.*;
/**
 * @author hxh
 * @description 客户端签名验证
 * @date 16:33 2025/2/11
 * @return
 **/
@Component
@Aspect
@Order(2)
public class SignValidateAspect {
    public static final String EDP = "execution(* com.everyday.word.controller.client.*.*.*(..))";
    @Around(EDP)
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        PrintWriter out = null;
        ServletRequestAttributes servletContainer = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        out = servletContainer.getResponse().getWriter();
        HttpServletRequest request = servletContainer.getRequest();
        AcceptData acceptData = null;
        for (Object obj : args) {
            if (obj instanceof AcceptData) {
                acceptData = (AcceptData) obj;
            } else if (obj instanceof HttpServletRequest) {
                request = (HttpServletRequest) obj;
            }
        }
        if (acceptData == null) {
            out.print(JsonUtil.loadFalseResult(-1, "签名错误"));
            return null;
        }
        if (acceptData != null) {
            acceptData.setSystem(SystemInfoUtil.getSystem(acceptData));
        }
        boolean isRight = signIsRight(request, acceptData.getSystem().getApiSignKey());
        // 签名是否正确
        if (isRight) {
            // 判断签名超时
            if (Math.abs((acceptData.getTimestamp() - System.currentTimeMillis())) > 1000 * 60 * 10) {
                JSONObject data = new JSONObject();
                data.put("code", -2);
                data.put("msg", "时间错误");
                out.print(data);
                out.close();
                return null;
            }
            final String url = request.getRequestURI();
            Object obj = null;
            try {
                long startTime = System.currentTimeMillis();
                obj = joinPoint.proceed(args);
                final long responseTime = System.currentTimeMillis() - startTime;
                // 记录大于2s的请求
            } catch (Throwable e) {
                if (!Constant.IS_TEST) {
                    out.print(JsonUtil.loadFalseResult(90009, "服务器内部错误"));
                } else {
                    throw e;
                }
            }
            return obj;
        } else {
            out.print(JsonUtil.loadFalseResult(-1, "签名错误"));
            out.close();
            return null;
        }
    }
    /**
     * 判断签名的正确性
     *
     * @param request
     * @return
     */
    private boolean signIsRight(HttpServletRequest request, String signKey) {
        Map<String, String[]> map = request.getParameterMap();
        Iterator<String> its = map.keySet().iterator();
        List<String> list = new ArrayList<>();
        boolean fromWEB = false;
        while (its.hasNext()) {
            String key = its.next();
            if (key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("callback") || key.equalsIgnoreCase("_")) {
                continue;
            }
            String[] values = map.get(key);
            list.add(key + "=" + values[0]);
        }
        Collections.sort(list);
        String str = "";
        for (String st : list) {
            str += st + "&";
        }
        String sign;
        if (!fromWEB) {
            sign = StringUtil.Md5(str + signKey);
        } else {
            sign = StringUtil.Md5(str + signKey);
        }
        if (sign.equalsIgnoreCase(request.getParameter("sign") + "")) {
            return true;
        } else {
            return false;
        }
    }
}
src/main/java/com/everyday/word/controller/user/LoginController.java
New file
@@ -0,0 +1,71 @@
package com.everyday.word.controller.user;
import com.everyday.word.utils.AliyunOneKeyLoginUtil;
import com.everyday.word.vo.AcceptData;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.servlet.http.HttpSession;
/**
 * @author hxh
 * @title: UserController
 * @description:
 * @date 2025/2/7 15:59
 */
@Controller
@RequestMapping("user/login")
public class LoginController {
    /**
     * @return java.lang.String
     * @author hxh
     * @description 电话号码登录
     * @date 16:08 2025/2/7
     * @param: acceptData
     * @param: session
     **/
    @ResponseBody
    @RequestMapping("phone")
    public String phoneLogin(AcceptData acceptData, HttpSession session) {
        return JsonUtil.loadTrueResult("");
    }
    /**
     * @return java.lang.String
     * @author hxh
     * @description 一键登录
     * @date 16:09 2025/2/7
     * @param: acceptData
     * @param: token
     * @param: session
     **/
    @ResponseBody
    @RequestMapping("one_key")
    public String oneKeyLogin(AcceptData acceptData, String token, HttpSession session) {
        String phone = AliyunOneKeyLoginUtil.getMobile(token, "");
        if (StringUtil.isNullOrEmpty(phone)) {
            return JsonUtil.loadFalseResult("手机号获取失败");
        }
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("wx")
    public String wxLogin(AcceptData acceptData, String token, HttpSession session) {
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("qq")
    public String qqLogin(AcceptData acceptData, String token, HttpSession session) {
        return JsonUtil.loadTrueResult("");
    }
}
src/main/java/com/everyday/word/dao/config/SystemConfigMapper.java
New file
@@ -0,0 +1,37 @@
package com.everyday.word.dao.config;
import java.lang.String;
import java.util.Date;
import java.lang.Long;
import java.util.List;
import com.everyday.word.entity.SystemEnum;
import lombok.Builder;
import org.apache.ibatis.annotations.Param;
import com.everyday.word.entity.config.SystemConfig;
import org.yeshi.utils.mybatis.BaseMapper;
public interface SystemConfigMapper extends BaseMapper<SystemConfig> {
    SystemConfig selectByPrimaryKeyForUpdate(@Param("id") Long id);
    List<SystemConfig> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    @Builder
    public static class DaoQuery{
        public Long id;
        public String key;
        public String value;
        public String name;
        public SystemEnum system;
        public Date minCreateTime;
        public Date maxCreateTime;
        public Date minUpdateTime;
        public Date maxUpdateTime;
        public long start;
        public int count;
        public List<String> sortList;
    }
}
src/main/java/com/everyday/word/dao/user/UserAuthMapper.java
New file
@@ -0,0 +1,37 @@
package com.everyday.word.dao.user;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.user.IdentityType;
import com.everyday.word.entity.user.UserAuth;
import org.apache.ibatis.annotations.Param;
import org.yeshi.utils.mybatis.BaseMapper;
import java.util.Date;
import java.util.List;
public interface UserAuthMapper extends BaseMapper<UserAuth> {
    UserAuth selectByPrimaryKeyForUpdate(@Param("id") Long id);
    List<UserAuth> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    public static class DaoQuery{
        public Long id;
        public Long userId;
        public SystemEnum system;
        public IdentityType identityType;
        public String identifier;
        public String credential;
        public String nickName;
        public String portrait;
        public Date minCreateTime;
        public Date maxCreateTime;
        public Date minUpdateTime;
        public Date maxUpdateTime;
        public long start;
        public int count;
        public List<String> sortList;
    }
}
src/main/java/com/everyday/word/dao/user/UserMapper.java
New file
@@ -0,0 +1,32 @@
package com.everyday.word.dao.user;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.user.User;
import org.apache.ibatis.annotations.Param;
import org.yeshi.utils.mybatis.BaseMapper;
import java.util.Date;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
    User selectByPrimaryKeyForUpdate(@Param("id") Long id);
    List<User> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    public static class DaoQuery{
        public Long id;
        public String nickName;
        public String portrait;
        public SystemEnum system;
        public Date minCreateTime;
        public Date maxCreateTime;
        public Date minUpdateTime;
        public Date maxUpdateTime;
        public long start;
        public int count;
        public List<String> sortList;
    }
}
src/main/java/com/everyday/word/dto/QQUserInfo.java
New file
@@ -0,0 +1,25 @@
package com.everyday.word.dto;
import lombok.Data;
/**
 * @author hxh
 * @title: QQUserInfo
 * @description: TODO
 * @date 2025/2/11 13:43
 */
@Data
public class QQUserInfo {
    private String openid;
    private String nickname;
    private String gender;
    private int gender_type;
    private String province;
    private String city;
    private String year;
    private String figureurl;
    private String figureurl_1;
    private String figureurl_2;
}
src/main/java/com/everyday/word/entity/SystemEnum.java
New file
@@ -0,0 +1,40 @@
package com.everyday.word.entity;
/**
 * @author hxh
 * @title: SystemEnum
 * @description: 系统
 * @date 2025/2/11 15:33
 */
public enum SystemEnum {
    everyday_words("com.word.everyday.android", "com.word.everyday.ios", "天天背单词","&!@#123123");
    private String packageName;
    private String bundleId;
    private String name;
    private String apiSignKey;
    private SystemEnum(String packageName, String bundleId, String name,String apiSignKey) {
        this.bundleId = bundleId;
        this.name = name;
        this.packageName = packageName;
        this.apiSignKey =apiSignKey;
    }
    public String getPackageName() {
        return packageName;
    }
    public String getBundleId() {
        return bundleId;
    }
    public String getName() {
        return name;
    }
    public String getApiSignKey() {
        return apiSignKey;
    }
}
src/main/java/com/everyday/word/entity/config/SystemConfig.java
New file
@@ -0,0 +1,57 @@
package com.everyday.word.entity.config;
import com.everyday.word.entity.SystemEnum;
import lombok.Data;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.util.Date;
/**
 * @author hxh
 * @title: SystemConfig
 * @description: 系统配置
 * @date 2025/2/11 15:30
 */
@Table("table_system_config")
@Data
public class SystemConfig {
    @Column(name = "id")
    private Long id;
    @Column(name = "key")
    private String key;
    @Column(name = "value")
    private String value;
    @Column(name = "name")
    private String name;
    @Column(name = "system")
    private SystemEnum system;
    @Column(name = "create_time")
    private Date createTime;
    @Column(name = "update_time")
    private Date updateTime;
    public SystemConfig() {
    }
    public SystemConfig(Long id) {
        super();
        this.id = id;
    }
    public SystemConfig(String key, String value, String name, SystemEnum system) {
        this.key = key;
        this.value = value;
        this.name = name;
        this.system = system;
    }
}
src/main/java/com/everyday/word/entity/config/SystemConfigKeyEnum.java
New file
@@ -0,0 +1,27 @@
package com.everyday.word.entity.config;
public enum SystemConfigKeyEnum {
    appName("应用名称"),
    wxAppId("微信开放平台的appId"),
    wxAppSecret("微信开放平台的appSecret"),
    androidPackageNames("Android包名"),
    androidBaseActivityName("Android activity的基础路径"),
    iosPushCertPwd("ios推送密码"),
    iosBundleIds("IOS的BundleId"),
    wxGZAppId("微信公众平台的appId"),
    wxGZAppSecret("微信公众平台的appSecret"),
    defaultNickNamePrefix("默认昵称前缀"),
    defaultPortrait("默认头像");
    private String name;
    public String getName() {
        return name;
    }
    private SystemConfigKeyEnum(String name) {
        this.name = name;
    }
}
src/main/java/com/everyday/word/entity/user/IdentityType.java
New file
@@ -0,0 +1,35 @@
package com.everyday.word.entity.user;
/**
 * @author hxh
 * @title: IdentityType
 * @description: 表示类型
 * @date 2025/2/11 10:40
 */
public enum IdentityType {
    // 手机号登录
    PHONE("phone"),
    // 微信登录
    WECHAT("wechat"),
    // QQ登录
    QQ("qq");
    private final String value;
    IdentityType(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;
    }
    // 根据字符串值获取枚举
    public static IdentityType fromValue(String value) {
        for (IdentityType type : IdentityType.values()) {
            if (type.getValue().equals(value)) {
                return type;
            }
        }
        throw new IllegalArgumentException("Unknown identity type: " + value);
    }
}
src/main/java/com/everyday/word/entity/user/User.java
New file
@@ -0,0 +1,33 @@
package com.everyday.word.entity.user;
import com.everyday.word.entity.SystemEnum;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.util.Date;
/**
 * @author hxh
 * @title: UserInfo
 * @description: 用户信息
 * @date 2025/2/10 17:34
 */
@Table("table_user")
@Data
public class User {
    @Id
    @Column(name ="id")
    private Long id;
    @Column(name ="nick_name")
    private String nickName;
    @Column(name ="portrait")
    private String portrait;
    @Column(name ="system")
    private SystemEnum system;
    @Column(name ="create_time")
    private Date createTime;
    @Column(name ="update_time")
    private Date updateTime;
}
src/main/java/com/everyday/word/entity/user/UserAuth.java
New file
@@ -0,0 +1,56 @@
package com.everyday.word.entity.user;
import com.everyday.word.entity.SystemEnum;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Tolerate;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.util.Date;
/**
 * @author hxh
 * @title: UserAuth
 * @description: 用户授权信息
 * @date 2025/2/11 10:42
 */
@Data
@Table("table_user_auth")
@Builder
public class UserAuth {
    @Tolerate
    public UserAuth(){
    }
    @Id
    @Column(name ="id")
    private Long id;
    @Column(name ="user_id")
    private Long userId;
    @Column(name ="system")
    private SystemEnum system;
    // 使用枚举类型
    @Column(name ="identity_type")
    private IdentityType identityType;
    // 手机号, openid, unionid
    @Column(name ="identifier")
    private String identifier;
    // 密码或token
    @Column(name ="credential")
    private String credential;
    @Column(name ="nick_name")
    private String nickName;
    @Column(name ="portrait")
    private  String portrait;
    @Column(name ="create_time")
    private Date createTime;
    @Column(name ="update_time")
    private Date updateTime;
}
src/main/java/com/everyday/word/exception/BaseException.java
New file
@@ -0,0 +1,32 @@
package com.everyday.word.exception;
public class BaseException extends Exception {
    private static final long serialVersionUID = 1L;
    private int code;
    private String msg;
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    public BaseException(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public BaseException(String msg) {
        this.msg = msg;
    }
    public BaseException() {
    }
    @Override
    public String getMessage() {
        return this.msg;
    }
}
src/main/java/com/everyday/word/exception/ParamsException.java
New file
@@ -0,0 +1,13 @@
package com.everyday.word.exception;
/**
 * @author hxh
 * @title: ParamsException
 * @description: 参数异常
 * @date 2025/2/11 15:44
 */
public class ParamsException extends BaseException {
    public ParamsException(int code, String message) {
        super(code, message);
    }
}
src/main/java/com/everyday/word/exception/SMSException.java
New file
@@ -0,0 +1,15 @@
package com.everyday.word.exception;
public class SMSException extends BaseException {
    private static final long serialVersionUID = 1L;
    public SMSException(int code, String msg) {
        super(code, msg);
    }
    public SMSException() {
        super();
    }
}
src/main/java/com/everyday/word/exception/user/UserException.java
New file
@@ -0,0 +1,20 @@
package com.everyday.word.exception.user;
import org.springframework.security.core.AuthenticationException;
/**
 * @author hxh
 * @description 用户登录异常
 * @date 13:41 2024/9/14
 * @return
 **/
public class UserException extends AuthenticationException{
    // 尚未注册
    public final static int CODE_NOT_REGISTER=10;
    public UserException(String msg){
        super(msg);
    }
}
src/main/java/com/everyday/word/factory/user/UserAuthFactory.java
New file
@@ -0,0 +1,41 @@
package com.everyday.word.factory.user;
import com.everyday.word.dto.QQUserInfo;
import com.everyday.word.entity.user.IdentityType;
import com.everyday.word.entity.user.UserAuth;
import org.yeshi.utils.entity.wx.WeiXinUser;
/**
 * @author hxh
 * @title: UserAuthFactory
 * @description: TODO
 * @date 2025/2/11 13:51
 */
public class UserAuthFactory {
    public static UserAuth create(WeiXinUser user){
        return UserAuth.builder()
                .identityType(IdentityType.WECHAT)
                .identifier(user.getOpenid())
                .portrait(user.getHeadimgurl())
                .nickName(user.getNickname())
                .build();
    }
    public static UserAuth create(QQUserInfo user){
        return UserAuth.builder()
                .identityType(IdentityType.QQ)
                .identifier(user.getOpenid())
                .portrait(user.getFigureurl())
                .nickName(user.getNickname())
                .build();
    }
    public static UserAuth create(String phone){
        return UserAuth.builder()
                .identityType(IdentityType.PHONE)
                .identifier(phone)
                .build();
    }
}
src/main/java/com/everyday/word/service/impl/config/SystemConfigServiceImpl.java
New file
@@ -0,0 +1,84 @@
package com.everyday.word.service.impl.config;
import com.everyday.word.dao.config.SystemConfigMapper;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.config.SystemConfig;
import com.everyday.word.entity.config.SystemConfigKeyEnum;
import com.everyday.word.exception.ParamsException;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.everyday.word.service.inter.config.*;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
 * @author hxh
 * @title: SystemConfigServiceImpl
 * @description: TODO
 * @date 2025/2/11 15:45
 */
@Service
public class SystemConfigServiceImpl implements SystemConfigService{
    @Resource
    private SystemConfigMapper systemConfigMapper;
    @Override
    public void save(SystemConfig systemConfig) throws ParamsException {
        if (systemConfig == null || systemConfig.getSystem() == null || systemConfig.getKey() == null) {
            throw new ParamsException(1, "参数不完整");
        }
        SystemConfig old = getConfig(SystemConfigKeyEnum.valueOf(systemConfig.getKey()), systemConfig.getSystem());
        if (old != null) {
            SystemConfig update = new SystemConfig();
            update.setId(old.getId());
            update.setValue(systemConfig.getValue());
            update.setUpdateTime(new Date());
            systemConfigMapper.updateByPrimaryKeySelective(update);
        } else {
            if (systemConfig.getUpdateTime() == null) {
                systemConfig.setUpdateTime(new Date());
            }
            systemConfigMapper.insertSelective(systemConfig);
        }
    }
    @Override
    public SystemConfig getConfig(SystemConfigKeyEnum key, SystemEnum system) {
        SystemConfigMapper.DaoQuery daoQuery =  SystemConfigMapper.DaoQuery.builder()
                .key(key.name())
                .system(system)
                .count(1)
                .build();
        List<SystemConfig> mList = systemConfigMapper.list(daoQuery);
        if(mList!=null&&mList.size()>0){
            return mList.get(0);
        }
        return null;
    }
    @Cacheable(value = "systemConfig", key = "'getConfig-'+#key+'-'+#system")
    @Override
    public SystemConfig getConfigCache(SystemConfigKeyEnum key, SystemEnum system) {
        return getConfig(key, system);
    }
    @Cacheable(value = "systemConfig", key = "'getValue-'+#key+'-'+#system")
    @Override
    public String getValueCache(SystemConfigKeyEnum key, SystemEnum system) {
        SystemConfig config = getConfig(key, system);
        if (config == null) {
            return null;
        }
        return config.getValue();
    }
}
src/main/java/com/everyday/word/service/impl/user/UserServiceImpl.java
New file
@@ -0,0 +1,179 @@
package com.everyday.word.service.impl.user;
import com.everyday.word.dao.user.UserAuthMapper;
import com.everyday.word.dao.user.UserMapper;
import com.everyday.word.dto.QQUserInfo;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.user.IdentityType;
import com.everyday.word.entity.user.User;
import com.everyday.word.entity.user.UserAuth;
import com.everyday.word.exception.user.UserException;
import com.everyday.word.factory.user.UserAuthFactory;
import com.everyday.word.service.inter.user.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.wx.WeiXinUser;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
 * @author hxh
 * @title: UserServiceImpl
 * @description: 用户服务实现
 * @date 2025/2/11 13:14
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserAuthMapper userAuthMapper;
    @Override
    public User loginByWX(WeiXinUser user, SystemEnum system) {
        UserAuth userAuth = selectUserAuth(IdentityType.WECHAT, user.getOpenid(), system);
        if (userAuth != null) {
            return selectUser(userAuth.getUserId());
        }
        return null;
    }
    @Override
    public User loginByQQ(String openId, SystemEnum system) {
        UserAuth userAuth = selectUserAuth(IdentityType.QQ, openId, system);
        if (userAuth != null) {
            return selectUser(userAuth.getUserId());
        }
        return null;
    }
    @Override
    public User loginByPhone(String phone, SystemEnum system) {
        UserAuth userAuth = selectUserAuth(IdentityType.PHONE, phone, system);
        if (userAuth != null) {
            return selectUser(userAuth.getUserId());
        }
        return null;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void register(UserAuth authInfo) throws UserException {
        if (authInfo.getIdentityType() == null || StringUtil.isNullOrEmpty(authInfo.getIdentifier())) {
            throw new UserException("数据缺失");
        }
        if (selectUserAuth(authInfo.getIdentityType(), authInfo.getIdentifier(), authInfo.getSystem()) != null) {
            throw new UserException("授权数据已存在");
        }
        // 新增用户
        User user = new User();
        user.setNickName(authInfo.getNickName());
        user.setPortrait(authInfo.getPortrait());
        user.setCreateTime(new Date());
        userMapper.insertSelective(user);
        authInfo.setUserId(user.getId());
        authInfo.setCreateTime(new Date());
        userAuthMapper.insertSelective(authInfo);
    }
    @Override
    public UserAuth selectUserAuth(IdentityType type, String identifier, SystemEnum system) {
        UserAuthMapper.DaoQuery daoQuery = new UserAuthMapper.DaoQuery();
        daoQuery.identityType = type;
        daoQuery.identifier = identifier;
        daoQuery.system = system;
        daoQuery.count = 1;
        List<UserAuth> authList = userAuthMapper.list(daoQuery);
        if (authList.size() < 1) {
            return null;
        }
        return authList.get(0);
    }
    @Override
    public UserAuth selectUserAuth(Long uid, IdentityType type) {
        UserAuthMapper.DaoQuery daoQuery = new UserAuthMapper.DaoQuery();
        daoQuery.identityType = type;
        daoQuery.userId = uid;
        daoQuery.count = 1;
        List<UserAuth> authList = userAuthMapper.list(daoQuery);
        if (authList.size() < 1) {
            return null;
        }
        return authList.get(0);
    }
    @Override
    public List<UserAuth> listUserAuth(Long uid) {
        UserAuthMapper.DaoQuery daoQuery = new UserAuthMapper.DaoQuery();
        daoQuery.userId = uid;
        daoQuery.count = Integer.MAX_VALUE;
        return userAuthMapper.list(daoQuery);
    }
    @Override
    public User selectUser(Long id) {
        return userMapper.selectByPrimaryKey(id);
    }
    @Override
    public void bindWechat(Long userId, WeiXinUser weiXinUser) throws UserException {
        User user = selectUser(userId);
        if (user == null) {
            throw new UserException("用户不存在");
        }
        UserAuth userAuth = UserAuthFactory.create(weiXinUser);
        if (selectUserAuth(userAuth.getIdentityType(), userAuth.getIdentifier(), user.getSystem()) != null) {
            throw new UserException("微信已被绑定");
        }
        bind(userId, userAuth);
    }
    @Override
    public void bindQQ(Long userId, QQUserInfo qqUserInfo) throws UserException {
        User user = selectUser(userId);
        if (user == null) {
            throw new UserException("用户不存在");
        }
        UserAuth userAuth = UserAuthFactory.create(qqUserInfo);
        if (selectUserAuth(userAuth.getIdentityType(), userAuth.getIdentifier(), user.getSystem()) != null) {
            throw new UserException("QQ已被绑定");
        }
        bind(userId, userAuth);
    }
    @Override
    public void bindPhone(Long userId, String phone) throws UserException {
        User user = selectUser(userId);
        if (user == null) {
            throw new UserException("用户不存在");
        }
        UserAuth userAuth = UserAuthFactory.create(phone);
        if (selectUserAuth(userAuth.getIdentityType(), userAuth.getIdentifier(), user.getSystem()) != null) {
            throw new UserException("手机号已被绑定");
        }
        bind(userId, userAuth);
    }
    private void bind(Long userId, UserAuth userAuth) {
        // 查询是否为更换绑定
        UserAuth oldAuth = selectUserAuth(userId, userAuth.getIdentityType());
        if (oldAuth != null) {
            // 更换绑定
            userAuth.setId(oldAuth.getId());
            userAuth.setCreateTime(oldAuth.getCreateTime());
            userAuth.setUpdateTime(new Date());
            userAuthMapper.updateByPrimaryKeySelective(userAuth);
        } else {
            // 添加绑定
            userAuth.setUserId(userId);
            userAuth.setCreateTime(new Date());
            userAuthMapper.insertSelective(userAuth);
        }
    }
}
src/main/java/com/everyday/word/service/inter/config/SystemConfigService.java
New file
@@ -0,0 +1,21 @@
package com.everyday.word.service.inter.config;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.config.SystemConfig;
import com.everyday.word.entity.config.SystemConfigKeyEnum;
import com.everyday.word.exception.ParamsException;
/**
 * 系统配置信息(后台可见,不输出给前端)
 */
public interface SystemConfigService {
    public void save(SystemConfig systemConfig) throws ParamsException;
    public SystemConfig getConfig(SystemConfigKeyEnum key, SystemEnum system);
    public SystemConfig getConfigCache(SystemConfigKeyEnum key, SystemEnum system);
    public String getValueCache(SystemConfigKeyEnum key, SystemEnum system);
}
src/main/java/com/everyday/word/service/inter/user/UserService.java
New file
@@ -0,0 +1,132 @@
package com.everyday.word.service.inter.user;
import com.everyday.word.dto.QQUserInfo;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.user.IdentityType;
import com.everyday.word.entity.user.User;
import com.everyday.word.entity.user.UserAuth;
import com.everyday.word.exception.user.UserException;
import org.yeshi.utils.entity.wx.WeiXinUser;
import java.util.List;
/**
 * @author hxh
 * @title: UserService
 * @description: 用户服务
 * @date 2025/2/11 11:13
 */
public interface UserService {
    /**
     * @return void
     * @author hxh
     * @description 微信登录
     * @date 11:21 2025/2/11
     * @param: user
     **/
    public User loginByWX(WeiXinUser user, SystemEnum system);
    /**
     * @return void
     * @author hxh
     * @description QQ登录
     * @date 11:22 2025/2/11
     * @param: openId
     **/
    public User loginByQQ(String openId, SystemEnum system);
    /**
     * @return void
     * @author hxh
     * @description 电话号码登录
     * @date 11:23 2025/2/11
     * @param: phone
     **/
    public User loginByPhone(String phone, SystemEnum system);
    /**
     * @return void
     * @author hxh
     * @description 用户注册
     * @date 13:06 2025/2/11
     * @param: authInfo
     **/
    public void register(UserAuth authInfo) throws UserException;
    /**
     * @return com.everyday.word.entity.user.UserAuth
     * @author hxh
     * @description 授权查询
     * @date 13:27 2025/2/11
     * @param: type
     * @param: identifier
     **/
    public UserAuth selectUserAuth(IdentityType type, String identifier, SystemEnum system);
    /**
     * @return com.everyday.word.entity.user.UserAuth
     * @author hxh
     * @description 根据用户ID查询
     * @date 13:48 2025/2/11
     * @param: uid
     * @param: type
     **/
    public UserAuth selectUserAuth(Long uid, IdentityType type);
    /**
     * @return java.util.List<com.everyday.word.entity.user.UserAuth>
     * @author hxh
     * @description 获取用户所有授权信息
     * @date 13:33 2025/2/11
     * @param: uid
     **/
    public List<UserAuth> listUserAuth(Long uid);
    /**
     * @return com.everyday.word.entity.user.User
     * @author hxh
     * @description 查询用户基本信息
     * @date 13:34 2025/2/11
     * @param: id
     **/
    public User selectUser(Long id);
    /**
     * @author hxh
     * @description 绑定微信
     * @date 14:04 2025/2/11
     * @param: userId
     * @param: weiXinUser
     * @return void
     **/
    public void bindWechat(Long userId, WeiXinUser weiXinUser) throws UserException;
    /**
     * @author hxh
     * @description 绑定QQ
     * @date 14:04 2025/2/11
     * @param: userId
     * @param: qqUserInfo
     * @return void
     **/
    public void bindQQ(Long userId, QQUserInfo qqUserInfo) throws UserException;
    /**
     * @author hxh
     * @description 绑定电话
     * @date 14:04 2025/2/11
     * @param: userId
     * @param: phone
     * @return void
     **/
    public void bindPhone(Long userId, String phone) throws UserException;
}
src/main/java/com/everyday/word/utils/AliyunOneKeyLoginUtil.java
New file
@@ -0,0 +1,44 @@
package com.everyday.word.utils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileRequest;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import org.yeshi.utils.StringUtil;
public class AliyunOneKeyLoginUtil {
    private final static String ACCESS_KEY = "LTAI4FwmTxVCuzTaoZtDiV8z";
    private final static String ACESS_SCRET = "ixWg90QbYFKP6ae5xpAo2P1qwIyll5";
    public static String getMobile(String accessToken, String outId) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY, ACESS_SCRET);
        IAcsClient client = new DefaultAcsClient(profile);
        GetMobileRequest request = new GetMobileRequest();
        request.setAccessToken(accessToken);
        if (!StringUtil.isNullOrEmpty(outId))
            request.setOutId(outId);
        try {
            GetMobileResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
            if (response.getGetMobileResultDTO() != null) {
                String mobile = response.getGetMobileResultDTO().getMobile();
                return mobile;
            }
            System.out.println(new Gson().toJson(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
        return null;
    }
}
src/main/java/com/everyday/word/utils/Constant.java
New file
@@ -0,0 +1,13 @@
package com.everyday.word.utils;
/**
 * @author hxh
 * @title: Constant
 * @description: 常量
 * @date 2025/2/11 15:18
 */
public class Constant {
    public final static boolean IS_TEST = false;
    public final static String PLATEFORM_ANDROID = "android";
    public final static String PLATEFORM_IOS = "ios";
}
src/main/java/com/everyday/word/utils/SystemInfoUtil.java
New file
@@ -0,0 +1,25 @@
package com.everyday.word.utils;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.vo.AcceptData;
public class SystemInfoUtil {
    public static SystemEnum getSystem(String platform, String packageName) {
        for (SystemEnum s : SystemEnum.values()) {
            if ("android".equalsIgnoreCase(platform) && s.getPackageName().equalsIgnoreCase(packageName)) {
                return s;
            } else if (s.getBundleId().equalsIgnoreCase(packageName)) {
                return s;
            }
        }
        return null;
    }
    public static SystemEnum getSystem(AcceptData acceptData) {
        if (acceptData == null)
            return null;
        return getSystem(acceptData.getPlatform(), acceptData.getPackages());
    }
}
src/main/java/com/everyday/word/utils/TencentSMSUtil.java
New file
@@ -0,0 +1,55 @@
package com.everyday.word.utils;
import com.everyday.word.exception.SMSException;
import com.github.qcloudsms.SmsSingleSender;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.github.qcloudsms.httpclient.HTTPException;
import org.json.JSONException;
import java.io.IOException;
/**
 * @author hxh
 * @description 腾讯云短信发送工具
 * @date 15:22 2025/2/11
 * @return
 **/
public class TencentSMSUtil {
    /**
     * @return void
     * @author hxh
     * @description 发送单条短信
     * @date 15:23 2025/2/11
     * @param: phone
     * @param: msg
     * @param: smsAppId
     * @param: smsAppKey
     **/
    public static void sendSingleMsg(String phone, String msg, String smsAppId, String smsAppKey) throws SMSException {
        SmsSingleSender ssender = new SmsSingleSender(Integer.parseInt(smsAppId),
                smsAppKey);
        SmsSingleSenderResult result = null;
        try {
            result = ssender.send(0, "86", phone, msg, "", "");
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (HTTPException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (result == null) {
            throw new SMSException(2, "短信发送失败");
        }
        if (result.result == 1025) {
            throw new SMSException(result.result, "今日验证码发送超限,请明日再试");
        } else if (result.result != 0) {
            // 发送失败
            throw new SMSException(result.result, "短信发送失败");
        }
    }
}
src/main/java/com/everyday/word/vo/AcceptData.java
New file
@@ -0,0 +1,24 @@
package com.everyday.word.vo;
import com.everyday.word.entity.SystemEnum;
import lombok.Data;
/**
 * @author hxh
 * @title: AcceptData
 * @description: TODO
 * @date 2025/2/7 16:03
 */
@Data
public class AcceptData {
    private String device;
    private String packages;
    private long timestamp;
    private String sign;
    private int versionCode;
    private String platform;
    private String channel;
    private int version;
    private String osVersion;
    private SystemEnum system;
}
src/main/resources/mapper/SystemConfigMapper.xml
New file
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.everyday.word.dao.config.SystemConfigMapper">
  <resultMap id="BaseResultMap" type="com.everyday.word.entity.config.SystemConfig">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="key" property="key" jdbcType="VARCHAR"/>
    <result column="value" property="value" jdbcType="VARCHAR"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <result column="system" property="system" jdbcType="VARCHAR"/>
    <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
    <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
  </resultMap>
  <sql id="Base_Column_List">id,key,value,name,system,create_time,update_time</sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_system_config where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_system_config where id = #{id,jdbcType=BIGINT} for update
  </select>
  <sql id="listWhereSQL">
    <if test="query.id!=null">AND id = #{query.id}</if>
    <if test="query.key!=null">AND key = #{query.key}</if>
    <if test="query.value!=null">AND value = #{query.value}</if>
    <if test="query.name!=null">AND name = #{query.name}</if>
    <if test="query.system!=null">AND system = #{query.system}</if>
    <if test="query.minCreateTime!=null">AND create_time >= #{query.minCreateTime}</if>
    <if test="query.maxCreateTime!=null">AND #{query.maxCreateTime} > create_time</if>
    <if test="query.minUpdateTime!=null">AND update_time >= #{query.minUpdateTime}</if>
    <if test="query.maxUpdateTime!=null">AND #{query.maxUpdateTime} > update_time</if>
  </sql>
  <select id="list" resultMap="BaseResultMap">select
    <include refid="Base_Column_List"/> from table_system_config where 1=1
    <include refid="listWhereSQL"/>
    <if test="query.sortList!=null">
      <foreach collection="query.sortList" item="item" open=" order by " separator=",">#{item}</foreach>
    </if>limit #{query.start},#{query.count}
  </select>
  <select id="count" resultType="java.lang.Long">select count(*) from table_system_config where 1=1
    <include refid="listWhereSQL"/>
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">delete from table_system_config where id = #{id,jdbcType=BIGINT}</delete>
  <insert id="insert" parameterType="com.everyday.word.entity.config.SystemConfig" useGeneratedKeys="true" keyProperty="id">insert into table_system_config (id,key,value,name,system,create_time,update_time) values (#{id,jdbcType=BIGINT},#{key,jdbcType=VARCHAR},#{value,jdbcType=VARCHAR},#{name,jdbcType=VARCHAR},#{system,jdbcType=VARCHAR},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert>
  <insert id="insertSelective" parameterType="com.everyday.word.entity.config.SystemConfig" useGeneratedKeys="true" keyProperty="id">insert into table_system_config
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">id,</if>
      <if test="key != null">key,</if>
      <if test="value != null">value,</if>
      <if test="name != null">name,</if>
      <if test="system != null">system,</if>
      <if test="createTime != null">create_time,</if>
      <if test="updateTime != null">update_time,</if>
    </trim>values
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">#{id,jdbcType=BIGINT},</if>
      <if test="key != null">#{key,jdbcType=VARCHAR},</if>
      <if test="value != null">#{value,jdbcType=VARCHAR},</if>
      <if test="name != null">#{name,jdbcType=VARCHAR},</if>
      <if test="system != null">#{system,jdbcType=VARCHAR},</if>
      <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
    </trim>
  </insert>
  <update id="updateByPrimaryKey" parameterType="com.everyday.word.entity.config.SystemConfig">update table_system_config set key = #{key,jdbcType=VARCHAR},value = #{value,jdbcType=VARCHAR},name = #{name,jdbcType=VARCHAR},system = #{system,jdbcType=VARCHAR},create_time = #{createTime,jdbcType=TIMESTAMP},update_time = #{updateTime,jdbcType=TIMESTAMP} where id = #{id,jdbcType=BIGINT}</update>
  <update id="updateByPrimaryKeySelective" parameterType="com.everyday.word.entity.config.SystemConfig">update table_system_config
    <set>
      <if test="key != null">key=#{key,jdbcType=VARCHAR},</if>
      <if test="value != null">value=#{value,jdbcType=VARCHAR},</if>
      <if test="name != null">name=#{name,jdbcType=VARCHAR},</if>
      <if test="system != null">system=#{system,jdbcType=VARCHAR},</if>
      <if test="createTime != null">create_time=#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">update_time=#{updateTime,jdbcType=TIMESTAMP},</if>
    </set> where id = #{id,jdbcType=BIGINT}
  </update>
</mapper>
src/main/resources/mapper/UserAuthMapper.xml
New file
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.everyday.word.entity.dao.UserAuthMapper">
  <resultMap id="BaseResultMap" type="com.everyday.word.entity.user.UserAuth">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="user_id" property="userId" jdbcType="BIGINT"/>
    <result column="system" property="system" jdbcType="VARCHAR"/>
    <result column="identity_type" property="identityType" jdbcType="VARCHAR"/>
    <result column="identifier" property="identifier" jdbcType="VARCHAR"/>
    <result column="credential" property="credential" jdbcType="VARCHAR"/>
    <result column="nick_name" property="nickName" jdbcType="VARCHAR"/>
    <result column="portrait" property="portrait" jdbcType="VARCHAR"/>
    <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
    <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
  </resultMap>
  <sql id="Base_Column_List">id,user_id,system,identity_type,identifier,credential,nick_name,portrait,create_time,update_time</sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_user_auth where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_user_auth where id = #{id,jdbcType=BIGINT} for update
  </select>
  <sql id="listWhereSQL">
    <if test="query.id!=null">AND id = #{query.id}</if>
    <if test="query.userId!=null">AND user_id = #{query.userId}</if>
    <if test="query.system!=null">AND system = #{query.system}</if>
    <if test="query.identityType!=null">AND identity_type = #{query.identityType}</if>
    <if test="query.identifier!=null">AND identifier = #{query.identifier}</if>
    <if test="query.credential!=null">AND credential = #{query.credential}</if>
    <if test="query.nickName!=null">AND nick_name = #{query.nickName}</if>
    <if test="query.portrait!=null">AND portrait = #{query.portrait}</if>
    <if test="query.minCreateTime!=null">AND create_time >= #{query.minCreateTime}</if>
    <if test="query.maxCreateTime!=null">AND #{query.maxCreateTime} > create_time</if>
    <if test="query.minUpdateTime!=null">AND update_time >= #{query.minUpdateTime}</if>
    <if test="query.maxUpdateTime!=null">AND #{query.maxUpdateTime} > update_time</if>
  </sql>
  <select id="list" resultMap="BaseResultMap">select
    <include refid="Base_Column_List"/> from table_user_auth where 1=1
    <include refid="listWhereSQL"/>
    <if test="query.sortList!=null">
      <foreach collection="query.sortList" item="item" open=" order by " separator=",">#{item}</foreach>
    </if>limit #{query.start},#{query.count}
  </select>
  <select id="count" resultType="java.lang.Long">select count(*) from table_user_auth where 1=1
    <include refid="listWhereSQL"/>
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">delete from table_user_auth where id = #{id,jdbcType=BIGINT}</delete>
  <insert id="insert" parameterType="com.everyday.word.entity.user.UserAuth" useGeneratedKeys="true" keyProperty="id">insert into table_user_auth (id,user_id,system,identity_type,identifier,credential,nick_name,portrait,create_time,update_time) values (#{id,jdbcType=BIGINT},#{userId,jdbcType=BIGINT},#{system,jdbcType=VARCHAR},#{identityType,jdbcType=VARCHAR},#{identifier,jdbcType=VARCHAR},#{credential,jdbcType=VARCHAR},#{nickName,jdbcType=VARCHAR},#{portrait,jdbcType=VARCHAR},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert>
  <insert id="insertSelective" parameterType="com.everyday.word.entity.user.UserAuth" useGeneratedKeys="true" keyProperty="id">insert into table_user_auth
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">id,</if>
      <if test="userId != null">user_id,</if>
      <if test="system != null">system,</if>
      <if test="identityType != null">identity_type,</if>
      <if test="identifier != null">identifier,</if>
      <if test="credential != null">credential,</if>
      <if test="nickName != null">nick_name,</if>
      <if test="portrait != null">portrait,</if>
      <if test="createTime != null">create_time,</if>
      <if test="updateTime != null">update_time,</if>
    </trim>values
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">#{id,jdbcType=BIGINT},</if>
      <if test="userId != null">#{userId,jdbcType=BIGINT},</if>
      <if test="system != null">#{system,jdbcType=VARCHAR},</if>
      <if test="identityType != null">#{identityType,jdbcType=VARCHAR},</if>
      <if test="identifier != null">#{identifier,jdbcType=VARCHAR},</if>
      <if test="credential != null">#{credential,jdbcType=VARCHAR},</if>
      <if test="nickName != null">#{nickName,jdbcType=VARCHAR},</if>
      <if test="portrait != null">#{portrait,jdbcType=VARCHAR},</if>
      <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
    </trim>
  </insert>
  <update id="updateByPrimaryKey" parameterType="com.everyday.word.entity.user.UserAuth">update table_user_auth set user_id = #{userId,jdbcType=BIGINT},system = #{system,jdbcType=VARCHAR},identity_type = #{identityType,jdbcType=VARCHAR},identifier = #{identifier,jdbcType=VARCHAR},credential = #{credential,jdbcType=VARCHAR},nick_name = #{nickName,jdbcType=VARCHAR},portrait = #{portrait,jdbcType=VARCHAR},create_time = #{createTime,jdbcType=TIMESTAMP},update_time = #{updateTime,jdbcType=TIMESTAMP} where id = #{id,jdbcType=BIGINT}</update>
  <update id="updateByPrimaryKeySelective" parameterType="com.everyday.word.entity.user.UserAuth">update table_user_auth
    <set>
      <if test="userId != null">user_id=#{userId,jdbcType=BIGINT},</if>
      <if test="system != null">system=#{system,jdbcType=VARCHAR},</if>
      <if test="identityType != null">identity_type=#{identityType,jdbcType=VARCHAR},</if>
      <if test="identifier != null">identifier=#{identifier,jdbcType=VARCHAR},</if>
      <if test="credential != null">credential=#{credential,jdbcType=VARCHAR},</if>
      <if test="nickName != null">nick_name=#{nickName,jdbcType=VARCHAR},</if>
      <if test="portrait != null">portrait=#{portrait,jdbcType=VARCHAR},</if>
      <if test="createTime != null">create_time=#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">update_time=#{updateTime,jdbcType=TIMESTAMP},</if>
    </set> where id = #{id,jdbcType=BIGINT}
  </update>
</mapper>
src/main/resources/mapper/UserMapper.xml
New file
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.everyday.word.entity.dao.UserMapper">
  <resultMap id="BaseResultMap" type="com.everyday.word.entity.user.User">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="nick_name" property="nickName" jdbcType="VARCHAR"/>
    <result column="portrait" property="portrait" jdbcType="VARCHAR"/>
    <result column="system" property="system" jdbcType="VARCHAR"/>
    <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
    <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
  </resultMap>
  <sql id="Base_Column_List">id,nick_name,portrait,system,create_time,update_time</sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_user where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_user where id = #{id,jdbcType=BIGINT} for update
  </select>
  <sql id="listWhereSQL">
    <if test="query.id!=null">AND id = #{query.id}</if>
    <if test="query.nickName!=null">AND nick_name = #{query.nickName}</if>
    <if test="query.portrait!=null">AND portrait = #{query.portrait}</if>
    <if test="query.system!=null">AND system = #{query.system}</if>
    <if test="query.minCreateTime!=null">AND create_time >= #{query.minCreateTime}</if>
    <if test="query.maxCreateTime!=null">AND #{query.maxCreateTime} > create_time</if>
    <if test="query.minUpdateTime!=null">AND update_time >= #{query.minUpdateTime}</if>
    <if test="query.maxUpdateTime!=null">AND #{query.maxUpdateTime} > update_time</if>
  </sql>
  <select id="list" resultMap="BaseResultMap">select
    <include refid="Base_Column_List"/> from table_user where 1=1
    <include refid="listWhereSQL"/>
    <if test="query.sortList!=null">
      <foreach collection="query.sortList" item="item" open=" order by " separator=",">#{item}</foreach>
    </if>limit #{query.start},#{query.count}
  </select>
  <select id="count" resultType="java.lang.Long">select count(*) from table_user where 1=1
    <include refid="listWhereSQL"/>
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">delete from table_user where id = #{id,jdbcType=BIGINT}</delete>
  <insert id="insert" parameterType="com.everyday.word.entity.user.User" useGeneratedKeys="true" keyProperty="id">insert into table_user (id,nick_name,portrait,system,create_time,update_time) values (#{id,jdbcType=BIGINT},#{nickName,jdbcType=VARCHAR},#{portrait,jdbcType=VARCHAR},#{system,jdbcType=VARCHAR},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert>
  <insert id="insertSelective" parameterType="com.everyday.word.entity.user.User" useGeneratedKeys="true" keyProperty="id">insert into table_user
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">id,</if>
      <if test="nickName != null">nick_name,</if>
      <if test="portrait != null">portrait,</if>
      <if test="system != null">system,</if>
      <if test="createTime != null">create_time,</if>
      <if test="updateTime != null">update_time,</if>
    </trim>values
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">#{id,jdbcType=BIGINT},</if>
      <if test="nickName != null">#{nickName,jdbcType=VARCHAR},</if>
      <if test="portrait != null">#{portrait,jdbcType=VARCHAR},</if>
      <if test="system != null">#{system,jdbcType=VARCHAR},</if>
      <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
    </trim>
  </insert>
  <update id="updateByPrimaryKey" parameterType="com.everyday.word.entity.user.User">update table_user set nick_name = #{nickName,jdbcType=VARCHAR},portrait = #{portrait,jdbcType=VARCHAR},system = #{system,jdbcType=VARCHAR},create_time = #{createTime,jdbcType=TIMESTAMP},update_time = #{updateTime,jdbcType=TIMESTAMP} where id = #{id,jdbcType=BIGINT}</update>
  <update id="updateByPrimaryKeySelective" parameterType="com.everyday.word.entity.user.User">update table_user
    <set>
      <if test="nickName != null">nick_name=#{nickName,jdbcType=VARCHAR},</if>
      <if test="portrait != null">portrait=#{portrait,jdbcType=VARCHAR},</if>
      <if test="system != null">system=#{system,jdbcType=VARCHAR},</if>
      <if test="createTime != null">create_time=#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">update_time=#{updateTime,jdbcType=TIMESTAMP},</if>
    </set> where id = #{id,jdbcType=BIGINT}
  </update>
</mapper>
src/test/java/com/everyday/word/MapperTest.java
@@ -1,6 +1,7 @@
package com.everyday.word;
import com.everyday.word.entity.EnglishWords;
import com.everyday.word.entity.user.User;
import com.everyday.word.entity.user.UserAuth;
import org.junit.jupiter.api.Test;
import org.yeshi.utils.generater.mybatis.MyBatisMapperUtil;
@@ -15,7 +16,8 @@
    @Test
    public void createMapper(){
        MyBatisMapperUtil.createMapper(EnglishWords.class);
        MyBatisMapperUtil.createMapper(User.class);
        MyBatisMapperUtil.createMapper(UserAuth.class);
    }
src/test/java/com/everyday/word/WordsTest.java
@@ -72,55 +72,55 @@
    @Test
    public void pullDataFromYouDaoWeb() throws InterruptedException {
        EnglishWordsMapper.DaoQuery daoQuery=new EnglishWordsMapper.DaoQuery();
        int page=5;
        int pageSize = 100;
        List<EnglishWords> list = englishWordsService.list(daoQuery,page, pageSize);
        Set<String> oSpellings=new HashSet<>();
        for(EnglishWords e:list){
            oSpellings.add(e.getSpelling());
        }
        Set<String> spellings=new HashSet<>();
        spellings.addAll(oSpellings);
        Set<String>  infoSellings =   YouDaoWebUtil.getBaseInfoSpellings();
        spellings.removeAll(infoSellings);
        for(String s:spellings){
            try {
                String result = YouDaoWebApi.getInfoBySpelling(s);
                if (!StringUtil.isNullOrEmpty(result) && result.length() > 100) {
                    YouDaoWebUtil.saveBaseInfo(s,result);
                }
            }catch(Exception e){
                e.printStackTrace();
                break;
        EnglishWordsMapper.DaoQuery daoQuery = new EnglishWordsMapper.DaoQuery();
        for (int page = 200; page < 300; page++) {
            int pageSize = 100;
            List<EnglishWords> list = englishWordsService.list(daoQuery, page, pageSize);
            Set<String> oSpellings = new HashSet<>();
            for (EnglishWords e : list) {
                oSpellings.add(e.getSpelling());
            }
            Thread.sleep(1000 + (int) (Math.random()*1000));
        }
            Set<String> spellings = new HashSet<>();
            spellings.addAll(oSpellings);
        Set<String>  ljSellings =   YouDaoWebUtil.getLJSpellings();
        spellings=new HashSet<>();
        spellings.addAll(oSpellings);
        spellings.removeAll(ljSellings);
        for(String s:spellings){
            try {
                String result = YouDaoWebApi.getLJBySpelling(s);
                if (!StringUtil.isNullOrEmpty(result) && result.length() > 100) {
                    YouDaoWebUtil.saveLJ(s,result);
            Set<String> infoSellings = YouDaoWebUtil.getBaseInfoSpellings();
            spellings.removeAll(infoSellings);
            for (String s : spellings) {
                try {
                    String result = YouDaoWebApi.getInfoBySpelling(s);
                    if (!StringUtil.isNullOrEmpty(result) && result.length() > 100) {
                        System.out.println("info:"+s);
                        YouDaoWebUtil.saveBaseInfo(s, result);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    break;
                }
            }catch(Exception e){
                e.printStackTrace();
                break;
                Thread.sleep(1000 + (int) (Math.random() * 1000));
            }
            Thread.sleep(1000 + (int) (Math.random()*1000));
            Set<String> ljSellings = YouDaoWebUtil.getLJSpellings();
            spellings = new HashSet<>();
            spellings.addAll(oSpellings);
            spellings.removeAll(ljSellings);
            for (String s : spellings) {
                try {
                    String result = YouDaoWebApi.getLJBySpelling(s);
                    if (!StringUtil.isNullOrEmpty(result) && result.length() > 100) {
                        System.out.println("lj:"+s);
                        YouDaoWebUtil.saveLJ(s, result);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    break;
                }
                Thread.sleep(1000 + (int) (Math.random() * 1000));
            }
        }
    }