系统基本功能完善,用用来做SpringBoot系统的基本框架(集成mybatis/redis/腾讯云对象存储/阿里云一键登录)
2个文件已删除
2 文件已重命名
20个文件已修改
15个文件已添加
1578 ■■■■ 已修改文件
pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/aspect/SignValidateAspect.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/config/CosFilePathEnum.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/config/RedisConfig.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/config/RedisKeyEnum.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/config/TencentCosConfig.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/config/WebSecurityConfig.java 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/controller/client/user/LoginController.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/controller/client/user/UserController.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/controller/user/LoginController.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/config/SystemConfig.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/config/SystemConfigKeyEnum.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/user/User.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/entity/user/UserAuth.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/factory/user/UserAuthFactory.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/factory/user/UserFactory.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/RedisManager.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/impl/AdminUserServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/impl/EnglishWordsServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/impl/SMSServiceImpl.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/impl/config/SystemConfigServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/impl/user/UserServiceImpl.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/inter/AdminUserService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/inter/EnglishWordsService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/inter/SMSService.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/service/inter/user/UserService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/utils/AliyunOneKeyLoginUtil.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/vo/AcceptData.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/everyday/word/vo/user/UserInfoVO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-pro.yml 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/base.sql 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/SystemConfigMapper.xml 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/UserAuthMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/UserMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/everyday/word/ConfigTest.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/everyday/word/CosTest.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/everyday/word/RedisTest.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/everyday/word/WordsTest.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -230,6 +230,8 @@
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
@@ -287,6 +289,11 @@
            <version>1.9.2</version>
        </dependency>
        <!-- Redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>
src/main/java/com/everyday/word/aspect/SignValidateAspect.java
@@ -34,11 +34,9 @@
    @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;
@@ -50,7 +48,7 @@
            }
        }
        if (acceptData == null) {
            out.print(JsonUtil.loadFalseResult(-1, "签名错误"));
            servletContainer.getResponse().getWriter().print(JsonUtil.loadFalseResult(-1, "签名错误"));
            return null;
        }
@@ -65,20 +63,19 @@
                JSONObject data = new JSONObject();
                data.put("code", -2);
                data.put("msg", "时间错误");
                PrintWriter out = servletContainer.getResponse().getWriter();
                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) {
                    PrintWriter out = servletContainer.getResponse().getWriter();
                    out.print(JsonUtil.loadFalseResult(90009, "服务器内部错误"));
                } else {
                    throw e;
@@ -86,6 +83,7 @@
            }
            return obj;
        } else {
            PrintWriter out = servletContainer.getResponse().getWriter();
            out.print(JsonUtil.loadFalseResult(-1, "签名错误"));
            out.close();
            return null;
src/main/java/com/everyday/word/config/CosFilePathEnum.java
New file
@@ -0,0 +1,32 @@
package com.everyday.word.config;
/**
 * @author hxh
 * @title: CosFilePathEnum
 * @description: 腾讯云cos路径
 * @date 2025/2/13 10:21
 */
public enum CosFilePathEnum {
    // 用户相关
    userPortrait("/user/img/portrait/", "用户头像");
    private final String path;
    private final String desc;
    private CosFilePathEnum(String path, String desc) {
        this.path = path;
        this.desc = desc;
    }
    public String getDesc() {
        return desc;
    }
    public String getPath() {
        return path;
    }
    public String getWholePath(String subPath) {
        return path + subPath;
    }
}
src/main/java/com/everyday/word/config/RedisConfig.java
New file
@@ -0,0 +1,107 @@
package com.everyday.word.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
 * @author hxh
 * @title: RedisConfig
 * @description: Redis配置
 * @date 2025/2/12 16:10
 */
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Value("${spring.redis.host}")
    private String addr;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Value("${spring.redis.password}")
    private String auth;
    @Value("${spring.redis.database}")
    private int database;
    @Value("${spring.redis.lettuce.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.lettuce.pool.max-wait}")
    private int maxWait;
    @Value("${spring.redis.lettuce.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.lettuce.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.lettuce.shutdown-timeout}")
    private int shutDownTimeout;
    @Bean
    public LettuceConnectionFactory lettuceConnectionFactory() {
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        genericObjectPoolConfig.setMinIdle(minIdle);
        genericObjectPoolConfig.setMaxTotal(maxActive);
        genericObjectPoolConfig.setMaxWaitMillis(maxWait);
        genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(1000);
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setDatabase(database);
        redisStandaloneConfiguration.setHostName(addr);
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setPassword(RedisPassword.of(auth));
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(timeout))
                .shutdownTimeout(Duration.ofMillis(shutDownTimeout))
                .poolConfig(genericObjectPoolConfig)
                .build();
        LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
        //允许多个连接公用一个物理连接,默认为true
//        factory.setShareNativeConnection(true);
// 检验链接是否可用,默认为false
        factory.setValidateConnection(true);
        return factory;
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(lettuceConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}
src/main/java/com/everyday/word/config/RedisKeyEnum.java
New file
@@ -0,0 +1,34 @@
package com.everyday.word.config;
/**
 * @author hxh
 * @title: RedisKeyEnum
 * @description: Redis的键枚举
 * @date 2025/2/11 17:08
 */
public enum RedisKeyEnum {
    emptyKey("", "空值-key外部空值"),
    SMS("sms-", "短信"),
    SMSVCode("smscode-", "短信验证码");
    private final String key;
    private final String desc;
    private RedisKeyEnum(String key, String desc) {
        this.key = key;
        this.desc = desc;
    }
    public String getDesc() {
        return desc;
    }
    public String getKey() {
        return key;
    }
    public static String getRedisKey(RedisKeyEnum keyEnum, String value) {
        return keyEnum.getKey() + value;
    }
}
src/main/java/com/everyday/word/config/TencentCosConfig.java
New file
@@ -0,0 +1,62 @@
package com.everyday.word.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.yeshi.utils.tencentcloud.COSManager;
import org.yeshi.utils.tencentcloud.entity.COSInitParams;
import java.time.Duration;
/**
 * @author hxh
 * @title: RedisConfig
 * @description: 腾讯云COS配置
 * @date 2025/2/12 16:10
 */
@Configuration
public class TencentCosConfig extends CachingConfigurerSupport {
    @Value("${qcloud.cos.appid}")
    private long appId;
    @Value("${qcloud.cos.secret_id}")
    private String secretId;
    @Value("${qcloud.cos.secret_key}")
    private String secretKey;
    @Value("${qcloud.cos.bucket_name}")
    private String bucketName;
    @Value("${qcloud.cos.region}")
    private String region;
    @Value("${qcloud.cos.access_host}")
    private String accessHost;
    @Bean
    public COSManager createCosManager() {
        COSInitParams params=new COSInitParams();
        params.setAppId(appId);
        params.setSecretId(secretId);
        params.setSecretKey(secretKey);
        params.setBucketName(bucketName);
        params.setRegion(region);
        params.setAccessHost(accessHost);
        COSManager.getInstance().init(params);
        return COSManager.getInstance();
    }
}
src/main/java/com/everyday/word/config/WebSecurityConfig.java
@@ -2,7 +2,7 @@
import com.everyday.word.entity.AdminUser;
import com.everyday.word.exception.VerificationCodeException;
import com.everyday.word.service.AdminUserService;
import com.everyday.word.service.inter.AdminUserService;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
@@ -58,6 +58,10 @@
    private final static String[] STATIC_RESOURCE_PATHS = new String[]{
            "/*.html", "/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg", "/**/*.gif", "/**/*.xml", "/**/font/*", "/**/fonts/*", "/**/layui/**"
    };
    private final static String[] PERMIT_URIS = new String[]{
            "/admin/api/captcha.jpg*", "/api/**"
    };
@@ -131,6 +135,7 @@
                //非登录接口
                String url = httpServletRequest.getRequestURI();
                //不验证静态资源
                System.out.println("过滤链接:"+url);
                AntPathMatcher pathMatcher = new AntPathMatcher();
                for (String resource : STATIC_RESOURCE_PATHS) {
                    if (pathMatcher.match(resource, url)) {
@@ -199,7 +204,7 @@
        http.headers().frameOptions().disable();
        http.authorizeRequests()
                // 配置不需要鉴权的接口
                .antMatchers("/admin/api/captcha.jpg*", "/api/**", "/webapi/**","*/agentapi/**").permitAll()
                .antMatchers(PERMIT_URIS).permitAll()
                //配置需要鉴权的接口
                .antMatchers("/admin/api/**", "/admin/index.html").authenticated()
                .and()
@@ -246,10 +251,8 @@
                .csrf().disable()
                .rememberMe().userDetailsService(new MyUserDetailsService())
                .and().exceptionHandling().authenticationEntryPoint(new NotLoginAuthenticationEntryPoint());
        // TODO 暂时不验证
        http.addFilterBefore(new PreRequestVerifyFilter(), UsernamePasswordAuthenticationFilter.class);
        // http.addFilterBefore(new PreRequestVerifyFilter(), UsernamePasswordAuthenticationFilter.class);
    }
@@ -328,5 +331,12 @@
        }
    }
    public static void main(String[] args) {
      boolean match =  new AntPathMatcher().match("/api/**","/api/user/login/wx");
      System.out.println(match);
    }
}
src/main/java/com/everyday/word/controller/client/user/LoginController.java
New file
@@ -0,0 +1,202 @@
package com.everyday.word.controller.client.user;
import com.everyday.word.dto.QQUserInfo;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.config.SystemConfigKeyEnum;
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.SMSException;
import com.everyday.word.factory.user.UserFactory;
import com.everyday.word.service.inter.SMSService;
import com.everyday.word.service.inter.config.SystemConfigService;
import com.everyday.word.service.inter.user.UserService;
import com.everyday.word.utils.AliyunOneKeyLoginUtil;
import com.everyday.word.vo.AcceptData;
import com.everyday.word.vo.user.UserInfoVO;
import com.google.gson.Gson;
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 org.yeshi.utils.entity.wx.WeiXinUser;
import org.yeshi.utils.wx.WXAppLoginUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.List;
/**
 * @author hxh
 * @title: UserController
 * @description:
 * @date 2025/2/7 15:59
 */
@Controller
@RequestMapping("api/user/login")
public class LoginController {
    @Resource
    private SMSService smsService;
    @Resource
    private UserService userService;
    @Resource
    private SystemConfigService systemConfigService;
    private final Gson gson = JsonUtil.getSimpleGson();
    private UserInfoVO getUserInfoVO(Long uid) {
        User user = userService.selectUser(uid);
        if (user == null) {
            return null;
        }
        List<UserAuth> authList = userService.listUserAuth(uid);
        return UserFactory.createVO(user, authList);
    }
    private User loginByPhone(String phone, SystemEnum system) {
        User user = userService.loginByPhone(phone, system);
        if (user == null) {
            // 注册
            userService.register(UserFactory.createAuth(phone, system));
        }
        user = userService.loginByPhone(phone, system);
        return user;
    }
    /**
     * @return java.lang.String
     * @author hxh
     * @description 电话号码登录
     * @date 11:28 2025/2/13
     * @param: acceptData
     * @param: phone
     * @param: vcode
     * @param: accessToken 一键登录的Token
     * @param: session
     **/
    @ResponseBody
    @RequestMapping("phone")
    public String phoneLogin(AcceptData acceptData, String phone, String vcode, HttpSession session) {
        // 电话号码登录
        if (StringUtil.isNullOrEmpty(phone)) {
            return JsonUtil.loadFalseResult("电话号码不能为空");
        }
        if (StringUtil.isNullOrEmpty(vcode)) {
            return JsonUtil.loadFalseResult("验证码不能为空");
        }
        // 验证验证码
        String cacheCode = smsService.getVerifyCode(acceptData.getSystem(), phone, 1);
        if (!vcode.equalsIgnoreCase(cacheCode)) {
            return JsonUtil.loadFalseResult("验证码错误");
        }
        User user = loginByPhone(phone, acceptData.getSystem());
        if (user == null) {
            return JsonUtil.loadFalseResult("登录失败");
        }
        return JsonUtil.loadTrueResult(gson.toJson(getUserInfoVO(user.getId())));
    }
    @ResponseBody
    @RequestMapping("sendVerifyCode")
    public String sendSms(AcceptData acceptData, String phone, Long uid, HttpSession session) {
        try {
            if (phone.contains("**") && uid != null && uid > 0) {
                UserAuth userAuth = userService.selectUserAuth(uid, IdentityType.PHONE);
                if (userAuth == null) {
                    return JsonUtil.loadFalseResult(2, "用户不存在/未绑定手机号");
                }
                phone = userAuth.getIdentifier();
            }
            if (!StringUtil.isMobile(phone)) {
                return JsonUtil.loadFalseResult(4, "电话号码格式不正确");
            }
            smsService.sendVerifyCode(acceptData.getSystem(), phone, 6, 1);
            return JsonUtil.loadTrueResult("发送成功");
        } catch (SMSException e) {
            return JsonUtil.loadFalseResult(e.getCode(), e.getMsg());
        }
    }
    /**
     * @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("手机号获取失败");
        }
        User user = loginByPhone(phone, acceptData.getSystem());
        if (user == null) {
            return JsonUtil.loadFalseResult("登录失败");
        }
        return JsonUtil.loadTrueResult(gson.toJson(getUserInfoVO(user.getId())));
    }
    private WeiXinUser getWeiXinUserByCode(String code, SystemEnum system) {
        String wxAppId = systemConfigService.getValueCache(SystemConfigKeyEnum.wxAppId, system);
        String wxAppSecret = systemConfigService.getValueCache(SystemConfigKeyEnum.wxAppSecret, system);
        if (StringUtil.isNullOrEmpty(wxAppId) || StringUtil.isNullOrEmpty(wxAppSecret)) {
            return null;
        }
        return WXAppLoginUtil.getWeiXinUser(code, wxAppId, wxAppSecret);
    }
    @ResponseBody
    @RequestMapping("wx")
    public String wxLogin(AcceptData acceptData, String code, HttpSession session) {
        if (StringUtil.isNullOrEmpty(code)) {
            return JsonUtil.loadFalseResult("微信授权码未上传");
        }
        WeiXinUser weiXinUser = getWeiXinUserByCode(code, acceptData.getSystem());
        if (weiXinUser == null) {
            return JsonUtil.loadFalseResult("微信授权失败");
        }
        User user = userService.loginByWX(weiXinUser, acceptData.getSystem());
        if (user == null) {
            userService.register(UserFactory.createAuth(weiXinUser, acceptData.getSystem()));
            user = userService.loginByWX(weiXinUser, acceptData.getSystem());
        }
        if (user == null) {
            return JsonUtil.loadFalseResult("登录失败");
        }
        return JsonUtil.loadTrueResult(gson.toJson(getUserInfoVO(user.getId())));
    }
    @ResponseBody
    @RequestMapping("qq")
    public String qqLogin(AcceptData acceptData, QQUserInfo qqUserInfo, HttpSession session) {
        if (StringUtil.isNullOrEmpty(qqUserInfo.getOpenid())) {
            return JsonUtil.loadFalseResult("QQ授权码未上传");
        }
        UserAuth userAuth = UserFactory.createAuth(qqUserInfo, acceptData.getSystem());
        User user = userService.loginByQQ(qqUserInfo.getOpenid(), acceptData.getSystem());
        if (user == null) {
            userService.register(userAuth);
            user = userService.loginByQQ(qqUserInfo.getOpenid(), acceptData.getSystem());
        }
        if (user == null) {
            return JsonUtil.loadFalseResult("登录失败");
        }
        return JsonUtil.loadTrueResult(gson.toJson(getUserInfoVO(user.getId())));
    }
}
src/main/java/com/everyday/word/controller/client/user/UserController.java
New file
@@ -0,0 +1,157 @@
package com.everyday.word.controller.client.user;
import com.everyday.word.dto.QQUserInfo;
import com.everyday.word.entity.config.SystemConfigKeyEnum;
import com.everyday.word.entity.user.User;
import com.everyday.word.entity.user.UserAuth;
import com.everyday.word.factory.user.UserFactory;
import com.everyday.word.service.inter.SMSService;
import com.everyday.word.service.inter.config.SystemConfigService;
import com.everyday.word.service.inter.user.UserService;
import com.everyday.word.utils.AliyunOneKeyLoginUtil;
import com.everyday.word.vo.AcceptData;
import com.everyday.word.vo.user.UserInfoVO;
import com.google.gson.Gson;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.wx.WeiXinUser;
import org.yeshi.utils.wx.WXAppLoginUtil;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
/**
 * @author hxh
 * @title: UserController
 * @description:
 * @date 2025/2/7 15:59
 */
@Controller
@RequestMapping("user")
public class UserController {
    @Resource
    private SMSService smsService;
    @Resource
    private UserService userService;
    @Resource
    private SystemConfigService systemConfigService;
    private final Gson gson = JsonUtil.getSimpleGson();
    @ResponseBody
    @RequestMapping("uploadPortrait")
    public String uploadPortrait(AcceptData acceptData, MultipartFile portrait) {
        if (acceptData.getUid() == null) {
            return JsonUtil.loadFalseResult("用户未登录");
        }
        if (portrait == null) {
            return JsonUtil.loadFalseResult("上传文件不能为空");
        }
        try {
            userService.uploadPortrait(portrait, acceptData.getUid());
            return JsonUtil.loadTrueResult("");
        } catch (IOException e) {
            return JsonUtil.loadFalseResult("头像上传失败");
        }
    }
    @ResponseBody
    @RequestMapping("getUserInfo")
    public String getUserInfo(AcceptData acceptData) {
        if (acceptData.getUid() == null) {
            return JsonUtil.loadFalseResult("用户未登录");
        }
        User user = userService.selectUser(acceptData.getUid());
        if (user == null) {
            return JsonUtil.loadFalseResult("尚未获取到用户信息");
        }
        List<UserAuth> authList = userService.listUserAuth(acceptData.getUid());
        UserInfoVO vo = UserFactory.createVO(user, authList);
        return JsonUtil.loadTrueResult(gson.toJson(vo));
    }
    /**
     * @return java.lang.String
     * @author hxh
     * @description 绑定电话
     * @date 14:37 2025/2/13
     * @param: acceptData
     * @param: phone
     * @param: vcode
     * @param: token
     **/
    @ResponseBody
    @RequestMapping("bindPhone")
    public String bindPhone(AcceptData acceptData, String phone, String vcode, String token) {
        if (acceptData.getUid() == null) {
            return JsonUtil.loadFalseResult("用户未登录");
        }
        if (!StringUtil.isNullOrEmpty(token)) {
            if (StringUtil.isNullOrEmpty(phone)) {
                return JsonUtil.loadFalseResult("电话号码不能为空");
            }
            if (StringUtil.isNullOrEmpty(vcode)) {
                return JsonUtil.loadFalseResult("验证码不能为空");
            }
            // 验证验证码
            String cacheCode = smsService.getVerifyCode(acceptData.getSystem(), phone, 1);
            if (!vcode.equalsIgnoreCase(cacheCode)) {
                return JsonUtil.loadFalseResult("验证码错误");
            }
        } else {
            phone = AliyunOneKeyLoginUtil.getMobile(token, "");
            if (StringUtil.isNullOrEmpty(phone)) {
                return JsonUtil.loadFalseResult("手机号获取失败");
            }
        }
        userService.bindPhone(acceptData.getUid(), phone);
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("bindWX")
    public String bindWX(AcceptData acceptData, String code) {
        if (acceptData.getUid() == null) {
            return JsonUtil.loadFalseResult("用户未登录");
        }
        String wxAppId = systemConfigService.getValueCache(SystemConfigKeyEnum.wxAppId, acceptData.getSystem());
        String wxAppSecret = systemConfigService.getValueCache(SystemConfigKeyEnum.wxAppSecret, acceptData.getSystem());
        if (StringUtil.isNullOrEmpty(wxAppId) || StringUtil.isNullOrEmpty(wxAppSecret)) {
            return JsonUtil.loadFalseResult("获取配置信息失败");
        }
        WeiXinUser weiXinUser = WXAppLoginUtil.getWeiXinUser(code, wxAppId, wxAppSecret);
        if (weiXinUser == null) {
            return JsonUtil.loadFalseResult("获取微信授权信息失败");
        }
        userService.bindWechat(acceptData.getUid(), weiXinUser);
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("bindQQ")
    public String bindQQ(AcceptData acceptData, QQUserInfo qqUserInfo) {
        if (acceptData.getUid() == null) {
            return JsonUtil.loadFalseResult("用户未登录");
        }
        if (StringUtil.isNullOrEmpty(qqUserInfo.getOpenid())) {
            return JsonUtil.loadFalseResult("获取QQ授权信息失败");
        }
        userService.bindQQ(acceptData.getUid(), qqUserInfo);
        return JsonUtil.loadTrueResult("");
    }
}
src/main/java/com/everyday/word/controller/user/LoginController.java
File was deleted
src/main/java/com/everyday/word/entity/config/SystemConfig.java
@@ -1,7 +1,9 @@
package com.everyday.word.entity.config;
import com.everyday.word.entity.SystemEnum;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Tolerate;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
@@ -15,20 +17,23 @@
 */
@Table("table_system_config")
@Data
@Builder
public class SystemConfig {
    @Column(name = "id")
    private Long id;
    @Column(name = "key")
    @Column(name = "`key`")
    private String key;
    @Column(name = "value")
    @Column(name = "`value`")
    private String value;
    @Column(name = "name")
    @Column(name = "`name`")
    private String name;
    @Column(name = "system")
    @Column(name = "`system`")
    private SystemEnum system;
    @Column(name = "create_time")
@@ -37,21 +42,24 @@
    @Column(name = "update_time")
    private Date updateTime;
    @Tolerate
    public SystemConfig() {
    }
    @Tolerate
    public SystemConfig(Long id) {
        super();
        this.id = id;
    }
    @Tolerate
    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
@@ -11,7 +11,15 @@
    wxGZAppId("微信公众平台的appId"),
    wxGZAppSecret("微信公众平台的appSecret"),
    defaultNickNamePrefix("默认昵称前缀"),
    defaultPortrait("默认头像");
    defaultPortrait("默认头像"),
    smsAlias("短信签名"),
    smsTemplate("短信模版"),
    smsAppId("短信验证码的AppId"),
    smsAppKey("短信验证码的AppKey"),
    ;
    private String name;
src/main/java/com/everyday/word/entity/user/User.java
@@ -1,7 +1,9 @@
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;
@@ -16,7 +18,12 @@
 */
@Table("table_user")
@Data
@Builder
public class User {
    @Tolerate
    public User(){
    }
    @Id
    @Column(name ="id")
    private Long id;
src/main/java/com/everyday/word/entity/user/UserAuth.java
@@ -33,13 +33,19 @@
    private Long userId;
    @Column(name ="system")
    private SystemEnum system;
    // 使用枚举类型
    /**
     * 使用枚举类型
     */
    @Column(name ="identity_type")
    private IdentityType identityType;
    // 手机号, openid, unionid
    /**
     * 手机号, openid, unionid
     */
    @Column(name ="identifier")
    private String identifier;
    // 密码或token
    /**
     * 密码或token
     */
    @Column(name ="credential")
    private String credential;
src/main/java/com/everyday/word/factory/user/UserAuthFactory.java
File was deleted
src/main/java/com/everyday/word/factory/user/UserFactory.java
New file
@@ -0,0 +1,76 @@
package com.everyday.word.factory.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.vo.user.UserInfoVO;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.wx.WeiXinUser;
import java.util.List;
/**
 * @author hxh
 * @title: UserAuthFactory
 * @description: TODO
 * @date 2025/2/11 13:51
 */
public class UserFactory {
    public static UserAuth createAuth(WeiXinUser user, SystemEnum system) {
        return UserAuth.builder()
                .identityType(IdentityType.WECHAT)
                .identifier(user.getOpenid())
                .portrait(user.getHeadimgurl())
                .nickName(user.getNickname())
                .system(system)
                .build();
    }
    public static UserAuth createAuth(QQUserInfo user, SystemEnum system) {
        return UserAuth.builder()
                .identityType(IdentityType.QQ)
                .identifier(user.getOpenid())
                .portrait(user.getFigureurl())
                .nickName(user.getNickname())
                .system(system)
                .build();
    }
    public static UserAuth createAuth(String phone, SystemEnum system) {
        return UserAuth.builder()
                .identityType(IdentityType.PHONE)
                .identifier(phone)
                .system(system)
                .build();
    }
    public static UserInfoVO createVO(User user, List<UserAuth> authList) {
        UserInfoVO vo = UserInfoVO.builder()
                .id(user.getId())
                .nickName(user.getNickName())
                .portrait(user.getPortrait())
                .build();
        if (authList != null) {
            for (UserAuth auth : authList) {
                if (auth.getIdentityType() == IdentityType.PHONE) {
                    if (auth.getIdentifier().length() > 5) {
                        String phone = auth.getIdentifier().substring(0, 3);
                        phone += "******";
                        phone += auth.getIdentifier().substring(auth.getIdentifier().length() - 2, auth.getIdentifier().length());
                        vo.setPhone(phone);
                    } else {
                        vo.setPhone(auth.getIdentifier());
                    }
                } else if (auth.getIdentityType() == IdentityType.WECHAT) {
                    vo.setWxNickName(auth.getNickName());
                } else if (auth.getIdentityType() == IdentityType.QQ) {
                    vo.setQqNickName(auth.getNickName());
                }
            }
        }
        return vo;
    }
}
src/main/java/com/everyday/word/service/RedisManager.java
New file
@@ -0,0 +1,85 @@
package com.everyday.word.service;
/**
 * @author hxh
 * @title: RedisManager
 * @description: Redis管理器
 * @date 2025/2/11 17:13
 */
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Component
public class RedisManager {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    /**
     * 缓存字符串
     *
     * @param key
     * @param value
     */
    private void setString(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }
    /**
     * 删除某个键值
     *
     * @param key
     */
    public void removeKey(String key) {
        redisTemplate.delete(key);
    }
    /**
     * 缓存字符串
     *
     * @param key
     * @param value
     * @param seconds -缓存时间(s)
     */
    private void setString(String key, String value, int seconds) {
        redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
    }
    private String getString(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    public void increase(String key) {
        redisTemplate.opsForValue().increment(key);
    }
    public void expire(String key, int seconds) {
        redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
    }
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }
    public void cacheCommonString(String key, String value, int seconds) {
        setString(key, value, seconds);
    }
    public void cacheCommonString(String key, String value) {
        setString(key, value);
    }
    public String getCommonString(String key) {
        return getString(key);
    }
    public void removeCommonString(String key) {
        removeKey(key);
    }
}
src/main/java/com/everyday/word/service/impl/AdminUserServiceImpl.java
@@ -2,7 +2,7 @@
import com.everyday.word.dao.AdminUserMapper;
import com.everyday.word.entity.AdminUser;
import com.everyday.word.service.AdminUserService;
import com.everyday.word.service.inter.AdminUserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
src/main/java/com/everyday/word/service/impl/EnglishWordsServiceImpl.java
@@ -3,7 +3,7 @@
import com.everyday.word.dao.EnglishWordsMapper;
import com.everyday.word.entity.EnglishWords;
import com.everyday.word.exception.EnglishWordsException;
import com.everyday.word.service.EnglishWordsService;
import com.everyday.word.service.inter.EnglishWordsService;
import org.springframework.stereotype.Service;
import org.yeshi.utils.StringUtil;
src/main/java/com/everyday/word/service/impl/SMSServiceImpl.java
New file
@@ -0,0 +1,108 @@
package com.everyday.word.service.impl;
import com.everyday.word.config.RedisKeyEnum;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.entity.config.SystemConfigKeyEnum;
import com.everyday.word.exception.SMSException;
import com.everyday.word.service.RedisManager;
import com.everyday.word.service.inter.SMSService;
import com.everyday.word.service.inter.config.SystemConfigService;
import org.springframework.stereotype.Service;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.sms.TencentSMSUtil;
import javax.annotation.Resource;
import java.util.Date;
/**
 * @author hxh
 * @title: SMSServiceImpl
 * @description: 短信服务
 * @date 2025/2/11 17:04
 */
@Service
public class SMSServiceImpl implements SMSService {
    @Resource
    private RedisManager redisManager;
    @Resource
    private SystemConfigService systemConfigService;
    /**
     * @return boolean
     * @author hxh
     * @description 是否触发验证码发送频率
     * @date 17:17 2025/2/11
     * @param: phone
     * @param: sence
     **/
    private boolean isSmsFrequencyLimit(String phone, int sence) {
        String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.SMS, phone + "-" + sence);
        String value = redisManager.getCommonString(key);
        if (StringUtil.isNullOrEmpty(value)) {
            return false;
        } else {
            return true;
        }
    }
    private String getVerifyCode(int length) {
        String sts = "0123456789";
        String code = "";
        for (int i = 0; i < length; ++i) {
            int p = (int) (Math.random() * 10.0D);
            code = code + sts.charAt(p);
        }
        return code;
    }
    private void sendSmsSuccess(String phone, int type) {
        String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.SMS, phone + "-" + type);
        redisManager.cacheCommonString(key, "1", 10);
    }
    private void saveSMSVCode(String phone, int type, String code) {
        String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.SMSVCode, phone + "-" + type);
        // 保存2分钟
        redisManager.cacheCommonString(key, code, 120);
    }
    @Override
    public String sendVerifyCode(SystemEnum system, String phone, int codeLength, int sence) throws SMSException {
        boolean limit = isSmsFrequencyLimit(phone, sence);
        if (limit) {
            throw new SMSException(1001, "请过60秒再试");
        }
        String msgCode = getVerifyCode(codeLength);
        String smsAlias = systemConfigService.getValueCache(SystemConfigKeyEnum.smsAlias, system);
        if (StringUtil.isNullOrEmpty(smsAlias)) {
            throw new SMSException(1001, "短信签名为空");
        }
        String smsTemplate = systemConfigService.getValueCache(SystemConfigKeyEnum.smsAlias, system);
        if (StringUtil.isNullOrEmpty(smsTemplate)) {
            throw new SMSException(1001, "短信模版为空");
        }
        // 验证码模板
        String msg = smsTemplate.replace("[签名]", smsAlias).replace("[验证码]",
                msgCode);
        // 发送短信
        String appId = systemConfigService.getValueCache(SystemConfigKeyEnum.smsAppId, system);
        String appKey = systemConfigService.getValueCache(SystemConfigKeyEnum.smsAppKey, system);
        TencentSMSUtil.sendSingleMsg(Integer.parseInt(appId), appKey, phone, msg);
        // 缓存
        sendSmsSuccess(phone, sence);
        saveSMSVCode(phone, sence, msgCode);
        return msgCode;
    }
    @Override
    public String getVerifyCode(SystemEnum system, String phone, int sence) {
        String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.SMSVCode, phone + "-" + sence);
        return redisManager.getCommonString(key);
    }
}
src/main/java/com/everyday/word/service/impl/config/SystemConfigServiceImpl.java
@@ -16,7 +16,7 @@
/**
 * @author hxh
 * @title: SystemConfigServiceImpl
 * @description: TODO
 * @description: 系统配置服务
 * @date 2025/2/11 15:45
 */
@Service
@@ -33,8 +33,6 @@
        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();
@@ -43,6 +41,9 @@
            update.setUpdateTime(new Date());
            systemConfigMapper.updateByPrimaryKeySelective(update);
        } else {
            if (systemConfig.getCreateTime() == null) {
                systemConfig.setCreateTime(new Date());
            }
            if (systemConfig.getUpdateTime() == null) {
                systemConfig.setUpdateTime(new Date());
            }
@@ -59,7 +60,7 @@
                .count(1)
                .build();
        List<SystemConfig> mList = systemConfigMapper.list(daoQuery);
        if(mList!=null&&mList.size()>0){
        if(mList!=null&& !mList.isEmpty()){
            return mList.get(0);
        }
        return null;
src/main/java/com/everyday/word/service/impl/user/UserServiceImpl.java
@@ -1,5 +1,6 @@
package com.everyday.word.service.impl.user;
import com.everyday.word.config.CosFilePathEnum;
import com.everyday.word.dao.user.UserAuthMapper;
import com.everyday.word.dao.user.UserMapper;
import com.everyday.word.dto.QQUserInfo;
@@ -8,14 +9,17 @@
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.factory.user.UserFactory;
import com.everyday.word.service.inter.user.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.wx.WeiXinUser;
import org.yeshi.utils.tencentcloud.COSManager;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.List;
@@ -31,6 +35,8 @@
    private UserMapper userMapper;
    @Resource
    private UserAuthMapper userAuthMapper;
    @Resource
    private COSManager cosManager;
    @Override
    public User loginByWX(WeiXinUser user, SystemEnum system) {
@@ -73,6 +79,7 @@
        user.setNickName(authInfo.getNickName());
        user.setPortrait(authInfo.getPortrait());
        user.setCreateTime(new Date());
        user.setSystem(authInfo.getSystem());
        userMapper.insertSelective(user);
        authInfo.setUserId(user.getId());
        authInfo.setCreateTime(new Date());
@@ -87,7 +94,7 @@
        daoQuery.system = system;
        daoQuery.count = 1;
        List<UserAuth> authList = userAuthMapper.list(daoQuery);
        if (authList.size() < 1) {
        if (authList.isEmpty()) {
            return null;
        }
        return authList.get(0);
@@ -100,7 +107,7 @@
        daoQuery.userId = uid;
        daoQuery.count = 1;
        List<UserAuth> authList = userAuthMapper.list(daoQuery);
        if (authList.size() < 1) {
        if (authList.isEmpty()) {
            return null;
        }
        return authList.get(0);
@@ -125,7 +132,7 @@
        if (user == null) {
            throw new UserException("用户不存在");
        }
        UserAuth userAuth = UserAuthFactory.create(weiXinUser);
        UserAuth userAuth = UserFactory.createAuth(weiXinUser, user.getSystem());
        if (selectUserAuth(userAuth.getIdentityType(), userAuth.getIdentifier(), user.getSystem()) != null) {
            throw new UserException("微信已被绑定");
        }
@@ -138,7 +145,7 @@
        if (user == null) {
            throw new UserException("用户不存在");
        }
        UserAuth userAuth = UserAuthFactory.create(qqUserInfo);
        UserAuth userAuth = UserFactory.createAuth(qqUserInfo, user.getSystem());
        if (selectUserAuth(userAuth.getIdentityType(), userAuth.getIdentifier(), user.getSystem()) != null) {
            throw new UserException("QQ已被绑定");
        }
@@ -151,13 +158,24 @@
        if (user == null) {
            throw new UserException("用户不存在");
        }
        UserAuth userAuth = UserAuthFactory.create(phone);
        UserAuth userAuth = UserFactory.createAuth(phone, user.getSystem());
        if (selectUserAuth(userAuth.getIdentityType(), userAuth.getIdentifier(), user.getSystem()) != null) {
            throw new UserException("手机号已被绑定");
        }
        bind(userId, userAuth);
    }
    @Override
    public void uploadPortrait(MultipartFile file, Long uid) throws UserException, IOException {
        String fileUrl = cosManager.uploadFile(file.getInputStream(), CosFilePathEnum.userPortrait.getWholePath(uid + ".jpg")).getUrl();
        User user = User.builder()
                .id(uid)
                .portrait(fileUrl)
                .updateTime(new Date())
                .build();
        userMapper.updateByPrimaryKeySelective(user);
    }
    private void bind(Long userId, UserAuth userAuth) {
        // 查询是否为更换绑定
        UserAuth oldAuth = selectUserAuth(userId, userAuth.getIdentityType());
src/main/java/com/everyday/word/service/inter/AdminUserService.java
File was renamed from src/main/java/com/everyday/word/service/AdminUserService.java
@@ -1,4 +1,4 @@
package com.everyday.word.service;
package com.everyday.word.service.inter;
import com.everyday.word.entity.AdminUser;
src/main/java/com/everyday/word/service/inter/EnglishWordsService.java
File was renamed from src/main/java/com/everyday/word/service/EnglishWordsService.java
@@ -1,4 +1,4 @@
package com.everyday.word.service;
package com.everyday.word.service.inter;
import com.everyday.word.dao.EnglishWordsMapper;
import com.everyday.word.entity.EnglishWords;
src/main/java/com/everyday/word/service/inter/SMSService.java
New file
@@ -0,0 +1,39 @@
package com.everyday.word.service.inter;
import com.everyday.word.entity.SystemEnum;
import com.everyday.word.exception.SMSException;
import java.math.BigDecimal;
/**
 * 短信服务
 *
 * @author Administrator
 *
 */
public interface SMSService {
    /**
     * @author hxh
     * @description 发送验证短信
     * @date 17:06 2025/2/11
     * @param: system
     * @param: phone
     * @param: codeLength
     * @param: sence
     * @return java.lang.String
     **/
    public String sendVerifyCode(SystemEnum system, String phone, int codeLength, int sence) throws SMSException;
    /**
     * @author hxh
     * @description 获取验证码
     * @date 13:07 2025/2/13
     * @param: system
     * @param: phone
     * @param: sence
     * @return java.lang.String
     **/
    public String getVerifyCode(SystemEnum system, String phone, int sence);
}
src/main/java/com/everyday/word/service/inter/user/UserService.java
@@ -6,8 +6,10 @@
import com.everyday.word.entity.user.User;
import com.everyday.word.entity.user.UserAuth;
import com.everyday.word.exception.user.UserException;
import org.springframework.web.multipart.MultipartFile;
import org.yeshi.utils.entity.wx.WeiXinUser;
import java.io.IOException;
import java.util.List;
/**
@@ -129,4 +131,15 @@
    public void bindPhone(Long userId, String phone) throws UserException;
    /**
     * @author hxh
     * @description 上传头像
     * @date 11:15 2025/2/13
     * @param: file
     * @param: uid
     * @return void
     **/
    public void uploadPortrait(MultipartFile file, Long uid) throws UserException, IOException;
}
src/main/java/com/everyday/word/utils/AliyunOneKeyLoginUtil.java
@@ -28,8 +28,7 @@
            GetMobileResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
            if (response.getGetMobileResultDTO() != null) {
                String mobile = response.getGetMobileResultDTO().getMobile();
                return mobile;
                return response.getGetMobileResultDTO().getMobile();
            }
            System.out.println(new Gson().toJson(response));
        } catch (ServerException e) {
src/main/java/com/everyday/word/vo/AcceptData.java
@@ -6,7 +6,7 @@
/**
 * @author hxh
 * @title: AcceptData
 * @description: TODO
 * @description: 接口接受基础数据
 * @date 2025/2/7 16:03
 */
@Data
@@ -15,10 +15,10 @@
    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;
    private Long uid;
}
src/main/java/com/everyday/word/vo/user/UserInfoVO.java
New file
@@ -0,0 +1,22 @@
package com.everyday.word.vo.user;
import lombok.Builder;
import lombok.Data;
/**
 * @author hxh
 * @title: UserInfoVO
 * @description: 用户信息输出
 * @date 2025/2/13 13:53
 */
@Data
@Builder
public class UserInfoVO {
    private Long id;
    private String nickName;
    private String portrait;
    private String phone;
    private String wxNickName;
    private String qqNickName;
}
src/main/resources/application-dev.yml
@@ -45,8 +45,40 @@
    type: ehcache
    ehcache:
      config: classpath:ehcache.xml
  redis:
    host: 192.168.3.252
    port: 6379
    password: 123456
    database: 0
    timeout: 5000
    lettuce:
      pool:
        max-active: 200 #连接池最大连接数
        max-wait: 5000 #连接池最大阻塞等待时间
        max-idle: 50 #连接池中的最大空闲连接
        time-between-eviction-runs: 60000 #每隔多长时间运行一次空闲连接回收器(独立线程)
        min-idle: 5 #连接池中的最小空闲连接
      shutdown-timeout: 5000 #连接关闭超时时间
    jedis:
      pool:
        max-total: 1024
        max-wait: 10000ms
        max-idle: 200
        test_on_borrow: true
        min-idle: 8
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.everyday.word.entity
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 腾讯云COS设置
qcloud:
  cos:
     appid: 1255749512
     secret_id: AKIDTlpgJhLjOozvd6QI2XnpfGbgV4NQJk25
     secret_key: xhCSUHo55oHUQ6XicFcmfIgspX0EEzWo
     bucket_name: words
     region: ap-guangzhou
     access_host:
src/main/resources/application-pro.yml
@@ -16,9 +16,9 @@
    #    username: root
    #    password: Yeshi2016@
    # XCP
    url: jdbc:mysql://rm-f8z0j143g151fp995.mysql.rds.aliyuncs.com:3306/taoke_autopay?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
    url: jdbc:mysql://172.16.16.17:3306/everyday_words?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
    username: root
    password: xcp123123@
    password: Yeshi2016@
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
@@ -43,8 +43,39 @@
    type: ehcache
    ehcache:
      config: classpath:ehcache.xml
  redis:
    host: localhost
    port: 6379
    password: 123213
    database: 0
    timeout: 5000
    lettuce:
      pool:
        max-active: 200 #连接池最大连接数
        max-wait: 5000 #连接池最大阻塞等待时间
        max-idle: 50 #连接池中的最大空闲连接
        time-between-eviction-runs: 60000 #每隔多长时间运行一次空闲连接回收器(独立线程)
        min-idle: 5 #连接池中的最小空闲连接
      shutdown-timeout: 5000 #连接关闭超时时间
    jedis:
        pool:
          max-total: 1024
          max-wait: 10000ms
          max-idle: 200
          test_on_borrow: true
          min-idle: 8
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.taoke.autopay.entity
  type-aliases-package: com.everyday.word.entity
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 腾讯云COS设置
qcloud:
  cos:
    appid: 1255749512
    secret_id: AKIDTlpgJhLjOozvd6QI2XnpfGbgV4NQJk25
    secret_key: xhCSUHo55oHUQ6XicFcmfIgspX0EEzWo
    bucket_name: words
    region: ap-guangzhou
    access_host:
src/main/resources/base.sql
New file
@@ -0,0 +1,46 @@
create table table_user
(
    `id`          bigint not null primary key AUTO_INCREMENT,
    `nick_name`   varchar(128) DEFAULT NULL,
    `portrait`    varchar(256) DEFAULT NULL,
    `system`      varchar(64)  DEFAULT NULL,
    `create_time` datetime     DEFAULT NULL,
    `update_time` datetime     DEFAULT NULL
);
create table table_user_auth
(
    `id`            bigint not null primary key AUTO_INCREMENT,
    `user_id`       bigint       DEFAULT NULL,
    `system`        varchar(64)  DEFAULT NULL,
    `identity_type` varchar(128) DEFAULT NULL,
    `identifier`    varchar(128) DEFAULT NULL,
    `credential`    varchar(128) DEFAULT NULL,
    `nick_name`     varchar(128) DEFAULT NULL,
    `portrait`      varchar(256) DEFAULT NULL,
    `create_time`   datetime     DEFAULT NULL,
    `update_time`   datetime     DEFAULT NULL
);
create table table_admin
(
    `id`          bigint not null primary key AUTO_INCREMENT,
    `account`     varchar(128) DEFAULT NULL,
    `pwd`         varchar(128) DEFAULT NULL,
    `name`        varchar(128) DEFAULT NULL,
    `rule`        int          DEFAULT NULL,
    `create_time` datetime     DEFAULT NULL,
    `update_time` datetime     DEFAULT NULL
);
create table table_system_config
(
    `id`          bigint not null primary key AUTO_INCREMENT,
    `key`         varchar(128) DEFAULT NULL,
    `value`       varchar(1024) DEFAULT NULL,
    `name`        varchar(128) DEFAULT NULL,
    `system`      varchar(128) DEFAULT NULL,
    `create_time` datetime     DEFAULT NULL,
    `update_time` datetime     DEFAULT NULL
);
src/main/resources/mapper/SystemConfigMapper.xml
@@ -2,74 +2,97 @@
<!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>
    <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
@@ -1,7 +1,7 @@
<?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">
<mapper namespace="com.everyday.word.dao.user.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"/>
src/main/resources/mapper/UserMapper.xml
@@ -1,7 +1,7 @@
<?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">
<mapper namespace="com.everyday.word.dao.user.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"/>
src/test/java/com/everyday/word/ConfigTest.java
New file
@@ -0,0 +1,47 @@
package com.everyday.word;
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 com.everyday.word.service.inter.config.SystemConfigService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.yeshi.utils.tencentcloud.COSManager;
import javax.annotation.Resource;
import java.io.File;
/**
 * @author hxh
 * @title: RedisTest
 * @description: COS测试
 * @date 2025/2/13 10:11
 */
@SpringBootTest
public class ConfigTest {
    @Resource
    private SystemConfigService systemConfigService;
    @Test
    public void test() throws ParamsException {
        SystemConfig config = SystemConfig.builder()
                .system(SystemEnum.everyday_words)
                .key(SystemConfigKeyEnum.wxAppId.name())
                .value("wx82f0e543363453c6")
                .name(SystemConfigKeyEnum.wxAppId.getName())
                .build();
        systemConfigService.save(config);
        config = SystemConfig.builder()
                .system(SystemEnum.everyday_words)
                .key(SystemConfigKeyEnum.wxAppSecret.name())
                .value("8a6164408b9190d0b824f799ce0975b4")
                .name(SystemConfigKeyEnum.wxAppSecret.getName())
                .build();
        systemConfigService.save(config);
    }
}
src/test/java/com/everyday/word/CosTest.java
New file
@@ -0,0 +1,28 @@
package com.everyday.word;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.yeshi.utils.tencentcloud.COSManager;
import javax.annotation.Resource;
import java.io.File;
/**
 * @author hxh
 * @title: RedisTest
 * @description: COS测试
 * @date 2025/2/13 10:11
 */
@SpringBootTest
public class CosTest {
    @Resource
    private COSManager cosManager;
    @Test
    public void test() {
        cosManager.uploadFile(new File("D:\\项目\\单词\\源代码\\server\\src\\main\\resources\\static\\index.html"),"user/test.html");
    }
}
src/test/java/com/everyday/word/RedisTest.java
New file
@@ -0,0 +1,28 @@
package com.everyday.word;
import com.everyday.word.service.RedisManager;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
/**
 * @author hxh
 * @title: RedisTest
 * @description: TODO
 * @date 2025/2/13 10:11
 */
@SpringBootTest
public class RedisTest {
    @Resource
    private RedisManager redisManager;
    @Test
    public void test() {
//        redisManager.cacheCommonString("test","123123",10);
        System.out.println(redisManager.getCommonString("test"));
    }
}
src/test/java/com/everyday/word/WordsTest.java
@@ -2,7 +2,7 @@
import com.everyday.word.dao.EnglishWordsMapper;
import com.everyday.word.entity.EnglishWords;
import com.everyday.word.service.EnglishWordsService;
import com.everyday.word.service.inter.EnglishWordsService;
import com.everyday.word.utils.YouDaoWebApi;
import com.everyday.word.utils.YouDaoWebUtil;
import net.sf.json.JSONArray;