فهرست منبع

Add 小程序登录功能后端实现

Yue 2 سال پیش
والد
کامیت
e8a41142ca
16فایلهای تغییر یافته به همراه314 افزوده شده و 77 حذف شده
  1. 5 0
      SERVER/YanZhongXYH/script/sql/UpdateUser20231230.sql
  2. 4 2
      SERVER/YanZhongXYH/xyh-admin/src/main/resources/application-dev.yml
  3. 3 0
      SERVER/YanZhongXYH/xyh-admin/src/main/resources/application.yml
  4. 1 0
      SERVER/YanZhongXYH/xyh-admin/src/main/resources/i18n/messages_en_US.properties
  5. 1 0
      SERVER/YanZhongXYH/xyh-admin/src/main/resources/i18n/messages_zh_CN.properties
  6. 27 0
      SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/config/WxAppConfig.java
  7. 34 0
      SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/dto/WxUserInfoDto.java
  8. 36 0
      SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/dto/XcxLoginDto.java
  9. 8 0
      SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/entity/SysUser.java
  10. 1 0
      SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/model/XcxLoginUser.java
  11. 17 8
      SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/controller/system/SysLoginController.java
  12. 8 0
      SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/mapper/SysUserMapper.java
  13. 1 0
      SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/service/ISysUserService.java
  14. 60 17
      SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/service/SysLoginService.java
  15. 5 0
      SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/service/impl/SysUserServiceImpl.java
  16. 103 50
      SERVER/YanZhongXYH/xyh-system/src/main/resources/mapper/system/SysUserMapper.xml

+ 5 - 0
SERVER/YanZhongXYH/script/sql/UpdateUser20231230.sql

@@ -0,0 +1,5 @@
+USE `YanZhongXYH`;
+ALTER TABLE sys_user
+    ADD COLUMN union_id varchar(50) DEFAULT NULL COMMENT '在WX开放平台的唯一标识符' AFTER login_date;
+ALTER TABLE sys_user
+    ADD COLUMN open_id varchar(50) DEFAULT NULL COMMENT 'WX用户唯一标识' AFTER login_date;

+ 4 - 2
SERVER/YanZhongXYH/xyh-admin/src/main/resources/application-dev.yml

@@ -181,9 +181,11 @@ spring:
 spring:
   redis:
     # 地址
-    host: 192.168.0.82
+    #host: 192.168.0.82
+    host: shvber.com
     # 端口,默认为6379
-    port: 6379
+    #port: 6379
+    port: 4502
     # 数据库索引
     database: 0
     # 密码(如没有密码请注释掉)

+ 3 - 0
SERVER/YanZhongXYH/xyh-admin/src/main/resources/application.yml

@@ -16,6 +16,9 @@ vber:
   cacheLazy: false
   shardingSphere:
     enabled: false
+wx:
+  app-id: wxf78f89c00da43b16
+  app-secret: 02663dcc6c44fcba76dc04d7de7c8c4d
 
 captcha:
   # 页面 <参数设置> 可开启关闭 验证码校验

+ 1 - 0
SERVER/YanZhongXYH/xyh-admin/src/main/resources/i18n/messages_en_US.properties

@@ -8,6 +8,7 @@ user.password.retry.limit.count=Password input error {0} times
 user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes
 user.password.delete=Sorry, your account:{0} has been deleted
 user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
+user.wx.openid.error=WeChat failed to obtain openid and unionid
 role.blocked=Role disabled,please contact administrators
 user.logout.success=Exit successful
 length.not.valid=The length must be between {min} and {max} characters

+ 1 - 0
SERVER/YanZhongXYH/xyh-admin/src/main/resources/i18n/messages_zh_CN.properties

@@ -8,6 +8,7 @@ user.password.retry.limit.count=密码输入错误{0}次
 user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
 user.password.delete=对不起,您的账号:{0} 已被删除
 user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
+user.wx.openid.error=微信获取获取openid和unionid失败
 role.blocked=角色已封禁,请联系管理员
 user.logout.success=退出成功
 length.not.valid=长度必须在{min}到{max}个字符之间

+ 27 - 0
SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/config/WxAppConfig.java

@@ -0,0 +1,27 @@
+package cn.xyh.common.config;
+
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取项目相关配置
+ *
+ * @author Yue
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "wx")
+public class WxAppConfig {
+    /**
+     * AppId
+     */
+    private String appId;
+
+    /**
+     * AppSecret
+     */
+    private String appSecret;
+
+}

+ 34 - 0
SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/dto/WxUserInfoDto.java

@@ -0,0 +1,34 @@
+package cn.xyh.common.core.domain.dto;
+
+/**
+ * 微信用户信息
+ *
+ * @Author Yue
+ */
+public class WxUserInfoDto {
+
+    /**
+     * 用户昵称
+     */
+    private String nickname;
+
+    /**
+     * 用户头像
+     */
+    private String avatarUrl;
+    /**
+     * 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回
+     */
+    private String unionid;
+
+    /**
+     * 会话密钥
+     */
+    private String session_key;
+
+    /**
+     * 用户唯一标识
+     */
+    private String openid;
+
+}

+ 36 - 0
SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/dto/XcxLoginDto.java

@@ -0,0 +1,36 @@
+package cn.xyh.common.core.domain.dto;
+
+import lombok.Data;
+
+/**
+ * 小程序登录请求结果
+ *
+ * @author Yue
+ */
+@Data
+public class XcxLoginDto {
+    /**
+     * 用户唯一标识
+     */
+    private String openid;
+
+    /**
+     * 用户在开放平台的唯一标识符
+     */
+    private String unionid;
+
+    /**
+     * 会话密钥
+     */
+    private String session_key;
+
+    /**
+     * 错误信息
+     */
+    private String errmsg;
+
+    /**
+     * 错误码
+     */
+    private Integer errcode;
+}

+ 8 - 0
SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/entity/SysUser.java

@@ -112,6 +112,14 @@ public class SysUser extends BaseEntity {
      * 最后登录时间
      */
     private Date loginDate;
+    /**
+     * 用户唯一标识
+     */
+    private String openId;
+    /**
+     * 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回
+     */
+    private String unionId;
     /**
      * 备注
      */

+ 1 - 0
SERVER/YanZhongXYH/xyh-common/src/main/java/cn/xyh/common/core/domain/model/XcxLoginUser.java

@@ -18,5 +18,6 @@ public class XcxLoginUser extends LoginUser {
      * openid
      */
     private String openid;
+    private String unionId;
 
 }

+ 17 - 8
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/controller/system/SysLoginController.java

@@ -8,6 +8,7 @@ import cn.xyh.common.core.domain.model.EmailLoginBody;
 import cn.xyh.common.core.domain.model.LoginBody;
 import cn.xyh.common.core.domain.model.LoginUser;
 import cn.xyh.common.core.domain.model.SmsLoginBody;
+import cn.xyh.common.exception.ServiceException;
 import cn.xyh.common.helper.LoginHelper;
 import cn.xyh.system.domain.vo.RouterVo;
 import cn.xyh.system.service.ISysMenuService;
@@ -15,10 +16,7 @@ import cn.xyh.system.service.ISysUserService;
 import cn.xyh.system.service.SysLoginService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.validation.constraints.NotBlank;
 import java.util.HashMap;
@@ -94,12 +92,23 @@ public class SysLoginController {
      * @return 结果
      */
     @SaIgnore
-    @PostMapping("/xcxLogin")
-    public R<Map<String, Object>> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) {
+    @PostMapping("/xcxLogin/{xcxCode}")
+    public R<Map<String, Object>> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") @PathVariable String xcxCode) {
         Map<String, Object> ajax = new HashMap<>();
         // 生成令牌
-        String token = loginService.xcxLogin(xcxCode);
-        ajax.put(Constants.TOKEN, token);
+        try {
+            String token = loginService.xcxLogin(xcxCode);
+            ajax.put(Constants.TOKEN, token);
+        } catch (ServiceException ex) {
+            if (ex.getCode() == 401) {
+                String openid = ex.getMessage();
+                ajax.put("openid", openid);
+                R<Map<String, Object>> fail = R.fail(ajax);
+                fail.setCode(401);
+                return fail;
+            }
+            return R.fail(ex.getMessage());
+        }
         return R.ok(ajax);
     }
 

+ 8 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/mapper/SysUserMapper.java

@@ -70,6 +70,14 @@ public interface SysUserMapper extends BaseMapperPlus<SysUserMapper, SysUser, Sy
      */
     SysUser selectUserByUserName(String userName);
 
+    /**
+     * 通过openId查询用户
+     *
+     * @param openId openId
+     * @return 用户对象信息
+     */
+    SysUser selectUserByOpenId(String openId);
+
     /**
      * 通过手机号查询用户
      *

+ 1 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/service/ISysUserService.java

@@ -208,4 +208,5 @@ public interface ISysUserService {
      */
     int deleteUserByIds(Long[] userIds);
 
+    SysUser selectUserByOpenid(String openid);
 }

+ 60 - 17
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/service/SysLoginService.java

@@ -5,9 +5,13 @@ import cn.dev33.satoken.secure.BCrypt;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import cn.xyh.common.config.WxAppConfig;
 import cn.xyh.common.constant.CacheConstants;
 import cn.xyh.common.constant.Constants;
 import cn.xyh.common.core.domain.dto.RoleDTO;
+import cn.xyh.common.core.domain.dto.XcxLoginDto;
 import cn.xyh.common.core.domain.entity.SysUser;
 import cn.xyh.common.core.domain.event.LogininforEvent;
 import cn.xyh.common.core.domain.model.LoginUser;
@@ -15,6 +19,7 @@ import cn.xyh.common.core.domain.model.XcxLoginUser;
 import cn.xyh.common.enums.DeviceType;
 import cn.xyh.common.enums.LoginType;
 import cn.xyh.common.enums.UserStatus;
+import cn.xyh.common.exception.ServiceException;
 import cn.xyh.common.exception.user.CaptchaException;
 import cn.xyh.common.exception.user.CaptchaExpireException;
 import cn.xyh.common.exception.user.UserException;
@@ -49,6 +54,8 @@ public class SysLoginService {
     private final SysUserMapper userMapper;
     private final ISysConfigService configService;
     private final SysPermissionService permissionService;
+    private final ISysUserService userService;
+    private final WxAppConfig wxAppConfig;
 
     @Value("${user.password.maxRetryCount}")
     private Integer maxRetryCount;
@@ -116,19 +123,19 @@ public class SysLoginService {
 
     public String xcxLogin(String xcxCode) {
         // xcxCode 为 小程序调用 wx.login 授权后获取
-        // todo 以下自行实现
         // 校验 appid + appSecret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
-        String openid = "";
+        XcxLoginDto xcxLoginDto = getOpenIdByCode(xcxCode);
 
         // 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
-        SysUser user = loadUserByOpenid(openid);
-
+        SysUser user = loadUserByOpenid(xcxLoginDto);
+        if (user == null) {
+            // 用户不存在 抛出异常 openId交给全局异常处理 返回401
+            throw new ServiceException(xcxLoginDto.getOpenid(), 401);
+        }
         // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
-        XcxLoginUser loginUser = new XcxLoginUser();
-        loginUser.setUserId(user.getUserId());
-        loginUser.setUsername(user.getUserName());
-        loginUser.setUserType(user.getUserType());
-        loginUser.setOpenid(openid);
+        XcxLoginUser loginUser = buildXcxLoginUser(user);
+        loginUser.setOpenid(xcxLoginDto.getOpenid());
+        loginUser.setUnionId(xcxLoginDto.getUnionid());
         // 生成token
         LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
 
@@ -137,6 +144,7 @@ public class SysLoginService {
         return StpUtil.getTokenValue();
     }
 
+
     /**
      * 退出登录
      */
@@ -254,20 +262,55 @@ public class SysLoginService {
         return userMapper.selectUserByEmail(email);
     }
 
-    private SysUser loadUserByOpenid(String openid) {
-        // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
-        // todo 自行实现 userService.selectUserByOpenid(openid);
-        SysUser user = new SysUser();
+    private XcxLoginDto getOpenIdByCode(String code) {
+        //通过前端给的code获取openid和unionid
+        String url = StringUtils.format("https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorizatinon_code", wxAppConfig.getAppId(), wxAppConfig.getAppSecret(), code);
+        String data = HttpUtil.get(url);
+        log.info("微信获取获取openid和unionid,返回结果:{}", data);
+        try {
+            XcxLoginDto dto = JSONUtil.toBean(data, XcxLoginDto.class);
+            if (dto.getErrcode() != null) {
+                throw new UserException("user.wx.openid.error");
+            }
+            return dto;
+
+        } catch (Exception e) {
+            log.error("微信获取获取openid和unionid异常", e);
+            throw new UserException("user.wx.openid.error");
+        }
+
+    }
+
+    private SysUser loadUserByOpenid(XcxLoginDto wxLoginDto) {
+        // 使用 openid 查询绑定用户
+        SysUser user = userService.selectUserByOpenid(wxLoginDto.getOpenid());
         if (ObjectUtil.isNull(user)) {
-            log.info("登录用户:{} 不存在.", openid);
-            // todo 用户不存在 业务逻辑自行实现
+            log.info("登录用户:{} 不存在.", wxLoginDto.getOpenid());
+            return null;
         } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("登录用户:{} 已被停用.", openid);
-            // todo 用户已被停用 业务逻辑自行实现
+            log.info("登录用户:{} 已被停用.", wxLoginDto.getOpenid());
+            throw new UserException("user.blocked", user.getUserName());
         }
         return user;
     }
 
+    /**
+     * 构建登录用户
+     */
+    private XcxLoginUser buildXcxLoginUser(SysUser user) {
+        XcxLoginUser loginUser = new XcxLoginUser();
+        loginUser.setUserId(user.getUserId());
+        loginUser.setOrgId(user.getOrgId());
+        loginUser.setUsername(user.getUserName());
+        loginUser.setUserType(user.getUserType());
+        loginUser.setMenuPermission(permissionService.getMenuPermission(user));
+        loginUser.setRolePermission(permissionService.getRolePermission(user));
+        loginUser.setOrgName(ObjectUtil.isNull(user.getOrg()) ? "" : user.getOrg().getOrgName());
+        List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
+        loginUser.setRoles(roles);
+        return loginUser;
+    }
+
     /**
      * 构建登录用户
      */

+ 5 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/system/service/impl/SysUserServiceImpl.java

@@ -474,6 +474,11 @@ public class SysUserServiceImpl implements ISysUserService, IUserService {
         return baseMapper.deleteBatchIds(ids);
     }
 
+    @Override
+    public SysUser selectUserByOpenid(String openid) {
+        return baseMapper.selectUserByOpenId(openid);
+    }
+
     @Cacheable(cacheNames = CacheNames.SYS_USER_NAME, key = "#userId")
     @Override
     public String selectUserNameById(Long userId) {

+ 103 - 50
SERVER/YanZhongXYH/xyh-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -18,6 +18,8 @@
         <result property="delFlag" column="del_flag"/>
         <result property="loginIp" column="login_ip"/>
         <result property="loginDate" column="login_date"/>
+        <result property="openId" column="open_id"/>
+        <result property="unionId" column="union_id"/>
         <result property="createBy" column="create_by"/>
         <result property="createTime" column="create_time"/>
         <result property="updateBy" column="update_by"/>
@@ -48,73 +50,119 @@
 
     <sql id="selectUserVo">
         select u.user_id,
-        u.org_id,
-        u.user_name,
-        u.nick_name,
-        u.user_type,
-        u.email,
-        u.avatar,
-        u.phonenumber,
-        u.password,
-        u.sex,
-        u.status,
-        u.del_flag,
-        u.login_ip,
-        u.login_date,
-        u.create_by,
-        u.create_time,
-        u.remark,
-        d.org_id,
-        d.parent_id,
-        d.ancestors,
-        d.org_name,
-        d.order_num,
-        d.leader,
-        d.status as org_status,
-        r.role_id,
-        r.role_name,
-        r.role_key,
-        r.role_sort,
-        r.data_scope,
-        r.status as role_status
+               u.org_id,
+               u.user_name,
+               u.nick_name,
+               u.user_type,
+               u.email,
+               u.avatar,
+               u.phonenumber,
+               u.password,
+               u.sex,
+               u.status,
+               u.del_flag,
+               u.login_ip,
+               u.login_date,
+               u.open_id,
+               u.union_id,
+               u.create_by,
+               u.create_time,
+               u.remark,
+               d.org_id,
+               d.parent_id,
+               d.ancestors,
+               d.org_name,
+               d.order_num,
+               d.leader,
+               d.status as org_status,
+               r.role_id,
+               r.role_name,
+               r.role_key,
+               r.role_sort,
+               r.data_scope,
+               r.status as role_status
         from sys_user u
-        left join sys_org d on u.org_id = d.org_id
-        left join sys_user_role sur on u.user_id = sur.user_id
-        left join sys_role r on r.role_id = sur.role_id
+                 left join sys_org d on u.org_id = d.org_id
+                 left join sys_user_role sur on u.user_id = sur.user_id
+                 left join sys_role r on r.role_id = sur.role_id
     </sql>
 
     <select id="selectPageUserList" resultMap="SysUserResult">
-        select u.user_id, u.org_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
-        u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.org_name, d.leader
+        select u.user_id,
+               u.org_id,
+               u.nick_name,
+               u.user_name,
+               u.email,
+               u.avatar,
+               u.phonenumber,
+               u.sex,
+               u.status,
+               u.del_flag,
+               u.login_ip,
+               u.login_date,
+               u.create_by,
+               u.create_time,
+               u.remark,
+               d.org_name,
+               d.leader
         from sys_user u
-        left join sys_org d on u.org_id = d.org_id
-        ${ew.getCustomSqlSegment}
+                 left join sys_org d on u.org_id = d.org_id
+            ${ew.getCustomSqlSegment}
     </select>
 
     <select id="selectUserList" resultMap="SysUserResult">
-        select u.user_id, u.org_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
-        u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.org_name, d.leader
+        select u.user_id,
+               u.org_id,
+               u.nick_name,
+               u.user_name,
+               u.email,
+               u.avatar,
+               u.phonenumber,
+               u.sex,
+               u.status,
+               u.del_flag,
+               u.login_ip,
+               u.login_date,
+               u.create_by,
+               u.create_time,
+               u.remark,
+               d.org_name,
+               d.leader
         from sys_user u
-        left join sys_org d on u.org_id = d.org_id
-        ${ew.getCustomSqlSegment}
+                 left join sys_org d on u.org_id = d.org_id
+            ${ew.getCustomSqlSegment}
     </select>
 
     <select id="selectAllocatedList" resultMap="SysUserResult">
-        select distinct u.user_id, u.org_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
+        select distinct u.user_id,
+                        u.org_id,
+                        u.user_name,
+                        u.nick_name,
+                        u.email,
+                        u.phonenumber,
+                        u.status,
+                        u.create_time
         from sys_user u
-        left join sys_org d on u.org_id = d.org_id
-        left join sys_user_role sur on u.user_id = sur.user_id
-        left join sys_role r on r.role_id = sur.role_id
-        ${ew.getCustomSqlSegment}
+                 left join sys_org d on u.org_id = d.org_id
+                 left join sys_user_role sur on u.user_id = sur.user_id
+                 left join sys_role r on r.role_id = sur.role_id
+            ${ew.getCustomSqlSegment}
     </select>
 
     <select id="selectUnallocatedList" resultMap="SysUserResult">
-        select distinct u.user_id, u.org_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
+        select distinct u.user_id,
+                        u.org_id,
+                        u.user_name,
+                        u.nick_name,
+                        u.email,
+                        u.phonenumber,
+                        u.status,
+                        u.create_time
         from sys_user u
-        left join sys_org d on u.org_id = d.org_id
-        left join sys_user_role sur on u.user_id = sur.user_id
-        left join sys_role r on r.role_id = sur.role_id
-        ${ew.getCustomSqlSegment}
+                 left join sys_org d on u.org_id = d.org_id
+                 left join sys_user_role sur on u.user_id = sur.user_id
+                 left join sys_role r on r.role_id = sur.role_id
+            ${ew.getCustomSqlSegment}
     </select>
 
     <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
@@ -122,6 +170,11 @@
         where u.del_flag = '0' and u.user_name = #{userName}
     </select>
 
+    <select id="selectUserByOpenId" parameterType="String" resultMap="SysUserResult">
+        <include refid="selectUserVo"/>
+        where u.open_id = #{openId}
+    </select>
+
     <select id="selectUserByPhonenumber" parameterType="String" resultMap="SysUserResult">
         <include refid="selectUserVo"/>
         where u.del_flag = '0' and u.phonenumber = #{phonenumber}