3 次代码提交 5ee4f2e8da ... 3a86580eb6

作者 SHA1 备注 提交日期
  feng_ting-ting 3a86580eb6 Merge branch 'master' of http://git.workervip.com/TenGroup/MedSmart 3 天之前
  feng_ting-ting 3025204e2b . 3 天之前
  feng_ting-ting 0a09dab3a1 微信登录 3 天之前

+ 31 - 14
pom.xml

@@ -11,43 +11,60 @@
         <java.version>1.8</java.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <spring-boot.version>2.6.13</spring-boot.version>
+        <spring-boot.version>2.7.6</spring-boot.version>
     </properties>
     <dependencies>
+        <!-- Spring Boot 基础依赖 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
+            <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <artifactId>spring-boot-starter-validation</artifactId>
         </dependency>
+
+        <!-- 数据库相关 -->
         <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-pool2</artifactId>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.3.1</version>
         </dependency>
         <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>fastjson</artifactId>
-            <version>1.2.72</version>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
         </dependency>
 
-        <!--使用hutool中对http封装工具类 调用 HTTP 请求-->
+        <!-- 工具库 -->
         <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
-            <version>5.6.5</version>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>2.0.24</version>
         </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
+            <optional>true</optional>
         </dependency>
-    </dependencies>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.15</version>
+        </dependency>
+
+        <!-- HTTP客户端 -->
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-webclient</artifactId>-->
+<!--            <version>2.7.6</version>-->
+<!--        </dependency>-->
 
+    </dependencies>
     <dependencyManagement>
         <dependencies>
             <dependency>

+ 20 - 0
src/main/java/com/zhentao/common/AppConfig.java

@@ -0,0 +1,20 @@
+package com.zhentao.common;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @date: 2025/5/20 11:10
+ * @author: ftt
+ */
+
+@Configuration
+public class AppConfig {
+
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
+}
+

+ 29 - 0
src/main/java/com/zhentao/common/RedisConfig.java

@@ -0,0 +1,29 @@
+package com.zhentao.common;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * @date: 2025/5/20 11:08
+ * @author: ftt
+ */
+
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(factory);
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
+        return template;
+    }
+}
+

+ 59 - 0
src/main/java/com/zhentao/common/Result.java

@@ -0,0 +1,59 @@
+package com.zhentao.common;
+
+/**
+ * @date: 2025/5/19 11:49
+ * @author: ftt
+ */
+
+import lombok.Data;
+
+/**
+ * 统一响应结果集
+ * @author crush
+ */
+@Data
+public class Result<T> {
+
+    //操作代码
+    Integer code;
+
+    //提示信息
+    String message;
+
+    //结果数据
+    T data;
+
+    public Result() {
+    }
+
+    public Result(ResultCode resultCode) {
+        this.code = resultCode.code();
+        this.message = resultCode.message();
+    }
+
+    public Result(ResultCode resultCode, T data) {
+        this.code = resultCode.code();
+        this.message = resultCode.message();
+        this.data = data;
+    }
+
+    public Result(String message) {
+        this.message = message;
+    }
+
+    public static Result SUCCESS() {
+        return new Result(ResultCode.SUCCESS);
+    }
+
+    public static <T> Result SUCCESS(T data) {
+        return new Result(ResultCode.SUCCESS, data);
+    }
+
+    public static Result FAIL() {
+        return new Result(ResultCode.FAIL);
+    }
+
+    public static Result FAIL(String message) {
+        return new Result(message);
+    }
+}

+ 83 - 0
src/main/java/com/zhentao/common/ResultCode.java

@@ -0,0 +1,83 @@
+package com.zhentao.common;
+
+/**
+ * @date: 2025/5/19 11:50
+ * @author: ftt
+ */
+
+/**
+ * 通用响应状态
+ */
+public enum ResultCode {
+
+    /* 成功状态码 */
+    SUCCESS(0, "操作成功!"),
+
+    /* 错误状态码 */
+    FAIL(-1, "操作失败!"),
+
+    /* 参数错误:10001-19999 */
+    PARAM_IS_INVALID(10001, "参数无效"),
+    PARAM_IS_BLANK(10002, "参数为空"),
+    PARAM_TYPE_BIND_ERROR(10003, "参数格式错误"),
+    PARAM_NOT_COMPLETE(10004, "参数缺失"),
+
+    /* 用户错误:20001-29999*/
+    USER_NOT_LOGGED_IN(20001, "用户未登录,请先登录"),
+    USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),
+    USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
+    USER_NOT_EXIST(20004, "用户不存在"),
+    USER_HAS_EXISTED(20005, "用户已存在"),
+
+    /* 系统错误:40001-49999 */
+    FILE_MAX_SIZE_OVERFLOW(40003, "上传尺寸过大"),
+    FILE_ACCEPT_NOT_SUPPORT(40004, "上传文件格式不支持"),
+
+    /* 数据错误:50001-599999 */
+    RESULT_DATA_NONE(50001, "数据未找到"),
+    DATA_IS_WRONG(50002, "数据有误"),
+    DATA_ALREADY_EXISTED(50003, "数据已存在"),
+    AUTH_CODE_ERROR(50004, "验证码错误"),
+
+
+    /* 权限错误:70001-79999 */
+    PERMISSION_UNAUTHENTICATED(70001, "此操作需要登陆系统!"),
+
+    PERMISSION_UNAUTHORISE(70002, "权限不足,无权操作!"),
+
+    PERMISSION_EXPIRE(70003, "登录状态过期!"),
+
+    PERMISSION_TOKEN_EXPIRED(70004, "token已过期"),
+
+    PERMISSION_LIMIT(70005, "访问次数受限制"),
+
+    PERMISSION_TOKEN_INVALID(70006, "无效token"),
+
+    PERMISSION_SIGNATURE_ERROR(70007, "签名失败");
+
+    //操作代码
+    int code;
+    //提示信息
+    String message;
+
+    ResultCode(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int code() {
+        return code;
+    }
+
+    public String message() {
+        return message;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+    }

+ 25 - 0
src/main/java/com/zhentao/user/controller/AuthController.java

@@ -0,0 +1,25 @@
+package com.zhentao.user.controller;
+
+import com.zhentao.user.dto.LoginResponseDTO;
+import com.zhentao.user.dto.WechatLoginDTO;
+import com.zhentao.user.service.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    private UserService userService;
+
+    @PostMapping("/wechat/login")
+    public LoginResponseDTO wechatLogin(@Valid @RequestBody WechatLoginDTO dto) {
+        return userService.wechatLogin(dto);
+    }
+}

+ 136 - 0
src/main/java/com/zhentao/user/domain/User.java

@@ -0,0 +1,136 @@
+package com.zhentao.user.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * @TableName user
+ */
+@TableName(value ="user")
+@Data
+public class User implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Integer userId;
+
+    private String username;
+
+    private String password;
+
+    private String realName;
+
+    private Integer gender;
+
+    private Date birthday;
+
+    private String mobile;
+
+    private Integer role;
+
+    private Date createTime;
+
+    private Date lastLoginTime;
+
+    private String wxOpenid;
+
+    private String wxUnionid;
+
+    private String wxNickname;
+
+    private String wxAvatarUrl;
+
+    private String wxSessionKey;
+
+    private Date wxLastLoginTime;
+
+    private Integer loginType;
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        User other = (User) that;
+        return (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
+            && (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
+            && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
+            && (this.getRealName() == null ? other.getRealName() == null : this.getRealName().equals(other.getRealName()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getBirthday() == null ? other.getBirthday() == null : this.getBirthday().equals(other.getBirthday()))
+            && (this.getMobile() == null ? other.getMobile() == null : this.getMobile().equals(other.getMobile()))
+            && (this.getRole() == null ? other.getRole() == null : this.getRole().equals(other.getRole()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getLastLoginTime() == null ? other.getLastLoginTime() == null : this.getLastLoginTime().equals(other.getLastLoginTime()))
+            && (this.getWxOpenid() == null ? other.getWxOpenid() == null : this.getWxOpenid().equals(other.getWxOpenid()))
+            && (this.getWxUnionid() == null ? other.getWxUnionid() == null : this.getWxUnionid().equals(other.getWxUnionid()))
+            && (this.getWxNickname() == null ? other.getWxNickname() == null : this.getWxNickname().equals(other.getWxNickname()))
+            && (this.getWxAvatarUrl() == null ? other.getWxAvatarUrl() == null : this.getWxAvatarUrl().equals(other.getWxAvatarUrl()))
+            && (this.getWxSessionKey() == null ? other.getWxSessionKey() == null : this.getWxSessionKey().equals(other.getWxSessionKey()))
+            && (this.getWxLastLoginTime() == null ? other.getWxLastLoginTime() == null : this.getWxLastLoginTime().equals(other.getWxLastLoginTime()))
+            && (this.getLoginType() == null ? other.getLoginType() == null : this.getLoginType().equals(other.getLoginType()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
+        result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
+        result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
+        result = prime * result + ((getRealName() == null) ? 0 : getRealName().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getBirthday() == null) ? 0 : getBirthday().hashCode());
+        result = prime * result + ((getMobile() == null) ? 0 : getMobile().hashCode());
+        result = prime * result + ((getRole() == null) ? 0 : getRole().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getLastLoginTime() == null) ? 0 : getLastLoginTime().hashCode());
+        result = prime * result + ((getWxOpenid() == null) ? 0 : getWxOpenid().hashCode());
+        result = prime * result + ((getWxUnionid() == null) ? 0 : getWxUnionid().hashCode());
+        result = prime * result + ((getWxNickname() == null) ? 0 : getWxNickname().hashCode());
+        result = prime * result + ((getWxAvatarUrl() == null) ? 0 : getWxAvatarUrl().hashCode());
+        result = prime * result + ((getWxSessionKey() == null) ? 0 : getWxSessionKey().hashCode());
+        result = prime * result + ((getWxLastLoginTime() == null) ? 0 : getWxLastLoginTime().hashCode());
+        result = prime * result + ((getLoginType() == null) ? 0 : getLoginType().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", userId=").append(userId);
+        sb.append(", username=").append(username);
+        sb.append(", password=").append(password);
+        sb.append(", realName=").append(realName);
+        sb.append(", gender=").append(gender);
+        sb.append(", birthday=").append(birthday);
+        sb.append(", mobile=").append(mobile);
+        sb.append(", role=").append(role);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", lastLoginTime=").append(lastLoginTime);
+        sb.append(", wxOpenid=").append(wxOpenid);
+        sb.append(", wxUnionid=").append(wxUnionid);
+        sb.append(", wxNickname=").append(wxNickname);
+        sb.append(", wxAvatarUrl=").append(wxAvatarUrl);
+        sb.append(", wxSessionKey=").append(wxSessionKey);
+        sb.append(", wxLastLoginTime=").append(wxLastLoginTime);
+        sb.append(", loginType=").append(loginType);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 13 - 0
src/main/java/com/zhentao/user/dto/LoginResponseDTO.java

@@ -0,0 +1,13 @@
+package com.zhentao.user.dto;
+
+import lombok.Data;
+
+@Data
+public class LoginResponseDTO {
+    private Integer userId;
+    private String token;
+    private Integer loginType;
+    private String wxNickname;
+    private String wxAvatarUrl;
+    private Boolean isNewUser;
+}

+ 15 - 0
src/main/java/com/zhentao/user/dto/WechatLoginDTO.java

@@ -0,0 +1,15 @@
+package com.zhentao.user.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class WechatLoginDTO {
+    @NotBlank(message = "code不能为空")
+    private String code;
+    private String encryptedData;
+    private String iv;
+    private String rawData;
+    private String signature;
+}

+ 20 - 0
src/main/java/com/zhentao/user/mapper/UserMapper.java

@@ -0,0 +1,20 @@
+package com.zhentao.user.mapper;
+
+import com.zhentao.user.domain.User;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author ASUS
+* @description 针对表【user(用户基本信息表)】的数据库操作Mapper
+* @createDate 2025-05-20 09:53:17
+* @Entity com.zhentao.user.domain.User
+*/
+@Mapper
+public interface UserMapper extends BaseMapper<User> {
+
+}
+
+
+
+

+ 15 - 0
src/main/java/com/zhentao/user/service/UserService.java

@@ -0,0 +1,15 @@
+package com.zhentao.user.service;
+
+import com.zhentao.user.domain.User;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.user.dto.LoginResponseDTO;
+import com.zhentao.user.dto.WechatLoginDTO;
+
+/**
+* @author ASUS
+* @description 针对表【user(用户基本信息表)】的数据库操作Service
+* @createDate 2025-05-20 09:53:17
+*/
+public interface UserService extends IService<User> {
+    LoginResponseDTO wechatLogin(WechatLoginDTO dto);
+}

+ 194 - 0
src/main/java/com/zhentao/user/service/impl/UserServiceImpl.java

@@ -0,0 +1,194 @@
+package com.zhentao.user.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.user.domain.User;
+import com.zhentao.user.service.UserService;
+import com.zhentao.user.mapper.UserMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zhentao.user.dto.LoginResponseDTO;
+import com.zhentao.user.dto.WechatLoginDTO;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+* @author ASUS
+* @description 针对表【user(用户基本信息表)】的数据库操作Service实现
+* @createDate 2025-05-20 09:53:17
+*/
+@Service
+@Slf4j
+public class UserServiceImpl extends ServiceImpl<UserMapper, User>
+    implements UserService{
+    @Value("${wx.appid}")
+    private String appId;
+
+    @Value("${wx.secret}")
+    private String appSecret;
+
+    @Value("${wx.login-url}")
+    private String loginUrl;
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @Override
+    public LoginResponseDTO wechatLogin(WechatLoginDTO dto) {
+        try {
+            // 1. 向微信服务器换取session_key和openid
+            Map<String, String> wxResult = getWxSession(dto.getCode());
+            String openid = wxResult.get("openid");
+            String sessionKey = wxResult.get("session_key");
+
+            if (openid == null || sessionKey == null) {
+                log.error("微信登录失败:获取openid或session_key失败,返回结果: {}", wxResult);
+                throw new RuntimeException("微信登录失败:获取openid或session_key失败");
+            }
+
+            // 2. 查询或创建用户
+            User user = getUserByOpenid(openid);
+            boolean isNewUser = false;
+
+            if (user == null) {
+                // 创建新用户
+                user = createWechatUser(openid, sessionKey, dto);
+                isNewUser = true;
+            } else {
+                // 更新用户信息和session_key
+                updateUserInfo(user, sessionKey, dto);
+            }
+
+            // 3. 生成JWT Token并缓存到Redis
+            String token = generateToken(user.getUserId());
+            cacheUserToken(user.getUserId(), token);
+
+            // 4. 构建响应
+            LoginResponseDTO response = new LoginResponseDTO();
+            response.setUserId(user.getUserId());
+            response.setToken(token);
+            response.setLoginType(user.getLoginType());
+            response.setWxNickname(user.getWxNickname());
+            response.setWxAvatarUrl(user.getWxAvatarUrl());
+            response.setIsNewUser(isNewUser);
+
+            return response;
+        } catch (Exception e) {
+            log.error("微信登录服务出错,请求参数: {}", dto, e);
+            throw e;
+        }
+    }
+
+    private Map<String, String> getWxSession(String code) {
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+        params.add("appid", appId);
+        params.add("secret", appSecret);
+        params.add("js_code", code);
+        params.add("grant_type", "authorization_code");
+
+        String result = restTemplate.postForObject(loginUrl, params, String.class);
+
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            Map<String, Object> resultMap = mapper.readValue(result, Map.class);
+
+            if (resultMap.containsKey("errcode")) {
+                log.error("微信登录失败,错误码:{},错误信息:{}",
+                        resultMap.get("errcode"),
+                        resultMap.get("errmsg"));
+                return new HashMap<>();
+            }
+
+            Map<String, String> sessionInfo = new HashMap<>();
+            sessionInfo.put("openid", (String) resultMap.get("openid"));
+            sessionInfo.put("session_key", (String) resultMap.get("session_key"));
+            return sessionInfo;
+        } catch (Exception e) {
+            log.error("解析微信登录结果失败", e);
+            return new HashMap<>();
+        }
+    }
+
+    private User getUserByOpenid(String openid) {
+        return this.getOne(new LambdaQueryWrapper<User>()
+                .eq(User::getWxOpenid, openid));
+    }
+
+    private User createWechatUser(String openid, String sessionKey, WechatLoginDTO dto) {
+        User user = new User();
+        user.setWxOpenid(openid);
+        user.setWxSessionKey(sessionKey);
+        user.setLoginType(1); // 1=微信登录
+    
+        // 如果有用户信息,填充到实体
+        if (dto.getRawData() != null) {
+            try {
+                ObjectMapper mapper = new ObjectMapper();
+                Map<String, Object> userInfo = mapper.readValue(dto.getRawData(), Map.class);
+                user.setWxNickname((String) userInfo.get("nickName"));
+                user.setGender(Integer.parseInt(userInfo.get("gender").toString()));
+                user.setWxAvatarUrl((String) userInfo.get("avatarUrl"));
+                log.info("成功解析用户信息,昵称: {}, 头像: {}", user.getWxNickname(), user.getWxAvatarUrl()); // 添加日志输出
+            } catch (Exception e) {
+                log.error("解析微信用户信息失败", e); // 修改为 error 级别日志
+            }
+        }
+
+        this.save(user);
+        return user;
+    }
+
+    private void updateUserInfo(User user, String sessionKey, WechatLoginDTO dto) {
+        user.setWxSessionKey(sessionKey);
+        user.setWxLastLoginTime(new java.util.Date());
+    
+        // 如果有新的用户信息,更新
+        if (dto.getRawData() != null) {
+            try {
+                ObjectMapper mapper = new ObjectMapper();
+                Map<String, Object> userInfo = mapper.readValue(dto.getRawData(), Map.class);
+                user.setWxNickname((String) userInfo.get("nickName"));
+                user.setGender(Integer.parseInt(userInfo.get("gender").toString()));
+                user.setWxAvatarUrl((String) userInfo.get("avatarUrl"));
+                log.info("成功更新用户信息,昵称: {}, 头像: {}", user.getWxNickname(), user.getWxAvatarUrl()); // 添加日志输出
+            } catch (Exception e) {
+                log.error("解析微信用户信息失败", e); // 修改为 error 级别日志
+            }
+        }
+
+        this.updateById(user);
+    }
+
+    private String generateToken(Integer userId) {
+        // 生成唯一Token
+        return UUID.randomUUID().toString().replace("-", "");
+    }
+
+    private void cacheUserToken(Integer userId, String token) {
+        // 将Token缓存到Redis,有效期24小时
+        redisTemplate.opsForValue().set(
+                "user_token:" + userId,
+                token,
+                24,
+                TimeUnit.HOURS
+        );
+    }
+}
+
+
+
+

+ 19 - 8
src/main/resources/application.yml

@@ -1,15 +1,26 @@
 server:
-  port: 8081
+  port: 8080
 spring:
-  application:
-    name: springboot-weixin
+  datasource:
+    url: jdbc:mysql://localhost:3306/medical_inquiry_system?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
+    username: root
+    password: root
+    driver-class-name: com.mysql.cj.jdbc.Driver
+
   redis:
-    database: 0
-    port: 6379
     host: localhost
+    port: 6379
     password:
-weixin:
-  appid: 'appid'
-  secret: '应用密钥'
 
+mybatis-plus:
+  mapper-locations: classpath:mapper/*.xml
+  type-aliases-package: com.zhentao.*.domain
+  configuration:
+    map-underscore-to-camel-case: true
+
+# 微信小程序配置
+wx:
+  appid: wxa2a76a594be60e4d
+  secret: 73e228a4fea627fb74d5a9de8585d880
+  login-url: https://api.weixin.qq.com/sns/jscode2session
 

+ 35 - 0
src/main/resources/mapper/UserMapper.xml

@@ -0,0 +1,35 @@
+<?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.zhentao.user.mapper.UserMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.user.domain.User">
+            <id property="userId" column="user_id" jdbcType="INTEGER"/>
+            <result property="username" column="username" jdbcType="VARCHAR"/>
+            <result property="password" column="password" jdbcType="VARCHAR"/>
+            <result property="realName" column="real_name" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="TINYINT"/>
+            <result property="birthday" column="birthday" jdbcType="DATE"/>
+            <result property="mobile" column="mobile" jdbcType="CHAR"/>
+            <result property="role" column="role" jdbcType="TINYINT"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="lastLoginTime" column="last_login_time" jdbcType="TIMESTAMP"/>
+            <result property="wxOpenid" column="wx_openid" jdbcType="VARCHAR"/>
+            <result property="wxUnionid" column="wx_unionid" jdbcType="VARCHAR"/>
+            <result property="wxNickname" column="wx_nickname" jdbcType="VARCHAR"/>
+            <result property="wxAvatarUrl" column="wx_avatar_url" jdbcType="VARCHAR"/>
+            <result property="wxSessionKey" column="wx_session_key" jdbcType="VARCHAR"/>
+            <result property="wxLastLoginTime" column="wx_last_login_time" jdbcType="TIMESTAMP"/>
+            <result property="loginType" column="login_type" jdbcType="TINYINT"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        user_id,username,password,
+        real_name,gender,birthday,
+        mobile,role,create_time,
+        last_login_time,wx_openid,wx_unionid,
+        wx_nickname,wx_avatar_url,wx_session_key,
+        wx_last_login_time,login_type
+    </sql>
+</mapper>