diff --git a/db/0pigxx_boot.sql b/db/0pigxx_boot.sql index bb4a2e1c4..49e64227f 100644 --- a/db/0pigxx_boot.sql +++ b/db/0pigxx_boot.sql @@ -281,8 +281,6 @@ INSERT INTO `sys_dict_item` VALUES (33, 11, '0', '正常', 'status_type', '状 INSERT INTO `sys_dict_item` VALUES (34, 11, '9', '冻结', 'status_type', '状态冻结', NULL, 1, ' ', ' ', '2019-05-15 16:31:56', '2019-05-16 22:30:50', '状态冻结', '0', 1); INSERT INTO `sys_dict_item` VALUES (35, 12, '1', '系统类', 'dict_type', '系统类字典', NULL, 0, ' ', ' ', '2019-05-16 14:20:40', '2019-05-16 14:20:40', '不能修改删除', '0', 1); INSERT INTO `sys_dict_item` VALUES (36, 12, '0', '业务类', 'dict_type', '业务类字典', NULL, 0, ' ', ' ', '2019-05-16 14:20:59', '2019-05-16 14:20:59', '可以修改', '0', 1); -INSERT INTO `sys_dict_item` VALUES (37, 2, 'GITEE', '码云', 'social_type', '码云', NULL, 2, ' ', ' ', '2019-06-28 09:59:12', '2019-06-28 09:59:12', '码云', '0', 1); -INSERT INTO `sys_dict_item` VALUES (38, 2, 'OSC', '开源中国', 'social_type', '开源中国登录', NULL, 2, ' ', ' ', '2019-06-28 10:04:32', '2019-06-28 10:04:32', '', '0', 1); INSERT INTO `sys_dict_item` VALUES (39, 14, 'password', '密码模式', 'grant_types', '支持oauth密码模式', NULL, 0, ' ', ' ', '2019-08-13 07:35:28', '2019-08-13 07:35:28', NULL, '0', 1); INSERT INTO `sys_dict_item` VALUES (40, 14, 'authorization_code', '授权码模式', 'grant_types', 'oauth2 授权码模式', NULL, 1, ' ', ' ', '2019-08-13 07:36:07', '2019-08-13 07:36:07', NULL, '0', 1); INSERT INTO `sys_dict_item` VALUES (41, 14, 'client_credentials', '客户端模式', 'grant_types', 'oauth2 客户端模式', NULL, 2, ' ', ' ', '2019-08-13 07:36:30', '2019-08-13 07:36:30', NULL, '0', 1); @@ -1420,13 +1418,6 @@ CREATE TABLE `sys_user` ( `password_expire_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '密码是否过期,0未过期,9已过期', `password_modify_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记,0未删除,1已删除', - `wx_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '微信登录openId', - `mini_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '小程序openId', - `qq_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'QQ openId', - `gitee_login` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '码云标识', - `osc_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '开源中国标识', - `wx_cp_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '企业微信唯一ID', - `wx_ding_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '钉钉唯一ID', `dept_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '主部门ID', `tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户ID', PRIMARY KEY (`user_id`) USING BTREE @@ -1436,9 +1427,24 @@ CREATE TABLE `sys_user` ( -- Records of sys_user -- ---------------------------- BEGIN; -INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '17338122125', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, '0', NULL, 'oBxPy5E-v82xWGsfzZVzkD3wEX64', NULL, 'log4j', NULL, NULL,NULL,1,1); +INSERT INTO `sys_user` (`user_id`, `username`, `password`, `salt`, `phone`, `avatar`, `nickname`, `name`, `email`, `create_by`, `update_by`, `create_time`, `update_time`, `lock_flag`, `password_expire_flag`, `password_modify_time`, `del_flag`, `dept_id`, `tenant_id`) VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '17338122125', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, '0', 1, 1); COMMIT; +-- ---------------------------- +-- Table structure for sys_user_social +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_social`; +CREATE TABLE `sys_user_social` ( + `id` bigint(20) NOT NULL COMMENT '主键ID', + `user_id` bigint(20) NOT NULL COMMENT '用户ID', + `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '社交平台类型', + `identifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '唯一凭据', + `create_time` datetime NOT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_social_identifier` (`type`,`identifier`) USING BTREE, + UNIQUE KEY `uk_user_social_type` (`user_id`,`type`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户社交登录身份表'; + -- ---------------------------- -- Table structure for sys_user_post -- ---------------------------- diff --git a/db/2pigxx.sql b/db/2pigxx.sql index cc818c8d6..1a6683b70 100644 --- a/db/2pigxx.sql +++ b/db/2pigxx.sql @@ -262,8 +262,6 @@ INSERT INTO `sys_dict_item` VALUES (33, 11, '0', '正常', 'status_type', '状 INSERT INTO `sys_dict_item` VALUES (34, 11, '9', '冻结', 'status_type', '状态冻结', NULL, 1, ' ', ' ', '2019-05-15 16:31:56', '2019-05-16 22:30:50', '状态冻结', '0', 1); INSERT INTO `sys_dict_item` VALUES (35, 12, '1', '系统类', 'dict_type', '系统类字典', NULL, 0, ' ', ' ', '2019-05-16 14:20:40', '2019-05-16 14:20:40', '不能修改删除', '0', 1); INSERT INTO `sys_dict_item` VALUES (36, 12, '0', '业务类', 'dict_type', '业务类字典', NULL, 0, ' ', ' ', '2019-05-16 14:20:59', '2019-05-16 14:20:59', '可以修改', '0', 1); -INSERT INTO `sys_dict_item` VALUES (37, 2, 'GITEE', '码云', 'social_type', '码云', NULL, 2, ' ', ' ', '2019-06-28 09:59:12', '2019-06-28 09:59:12', '码云', '0', 1); -INSERT INTO `sys_dict_item` VALUES (38, 2, 'OSC', '开源中国', 'social_type', '开源中国登录', NULL, 2, ' ', ' ', '2019-06-28 10:04:32', '2019-06-28 10:04:32', '', '0', 1); INSERT INTO `sys_dict_item` VALUES (39, 14, 'password', '密码模式', 'grant_types', '支持oauth密码模式', NULL, 0, ' ', ' ', '2019-08-13 07:35:28', '2019-08-13 07:35:28', NULL, '0', 1); INSERT INTO `sys_dict_item` VALUES (40, 14, 'authorization_code', '授权码模式', 'grant_types', 'oauth2 授权码模式', NULL, 1, ' ', ' ', '2019-08-13 07:36:07', '2019-08-13 07:36:07', NULL, '0', 1); INSERT INTO `sys_dict_item` VALUES (41, 14, 'client_credentials', '客户端模式', 'grant_types', 'oauth2 客户端模式', NULL, 2, ' ', ' ', '2019-08-13 07:36:30', '2019-08-13 07:36:30', NULL, '0', 1); @@ -1406,13 +1404,6 @@ CREATE TABLE `sys_user` ( `password_expire_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '密码是否过期,0未过期,9已过期', `password_modify_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记,0未删除,1已删除', - `wx_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '微信登录openId', - `mini_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '小程序openId', - `qq_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'QQ openId', - `gitee_login` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '码云标识', - `osc_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '开源中国标识', - `wx_cp_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '企业微信唯一ID', - `wx_ding_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '钉钉唯一ID', `dept_id` bigint(20) DEFAULT NULL COMMENT '主部门ID', `tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '所属租户ID', PRIMARY KEY (`user_id`) USING BTREE @@ -1422,9 +1413,24 @@ CREATE TABLE `sys_user` ( -- Records of sys_user -- ---------------------------- BEGIN; -INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '17338122125', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, '0', NULL, 'oBxPy5E-v82xWGsfzZVzkD3wEX64', NULL, 'log4j', NULL, NULL,NULL,1,1); +INSERT INTO `sys_user` (`user_id`, `username`, `password`, `salt`, `phone`, `avatar`, `nickname`, `name`, `email`, `create_by`, `update_by`, `create_time`, `update_time`, `lock_flag`, `password_expire_flag`, `password_modify_time`, `del_flag`, `dept_id`, `tenant_id`) VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '17338122125', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, '0', 1, 1); COMMIT; +-- ---------------------------- +-- Table structure for sys_user_social +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_social`; +CREATE TABLE `sys_user_social` ( + `id` bigint(20) NOT NULL COMMENT '主键ID', + `user_id` bigint(20) NOT NULL COMMENT '用户ID', + `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '社交平台类型', + `identifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '唯一凭据', + `create_time` datetime NOT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `uk_social_identifier` (`type`,`identifier`) USING BTREE, + UNIQUE KEY `uk_user_social_type` (`user_id`,`type`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户社交登录身份表'; + -- ---------------------------- -- Table structure for sys_user_post -- ---------------------------- diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java index 4cd648fcf..97c95b358 100644 --- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java @@ -137,32 +137,11 @@ public interface SecurityConstants { */ String MINI_APP_PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s"; - /** - * 码云获取token - */ - String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type=" - + "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s"; - - /** - * 开源中国获取token - */ - String OSC_AUTHORIZATION_CODE_URL = "https://www.oschina.net/action/openapi/token"; - /** * QQ获取用户信息 */ String QQ_USER_INFO_URL = "https://graph.qq.com/oauth2.0/me?access_token=%s"; - /** - * 码云获取用户信息 - */ - String GITEE_USER_INFO_URL = "https://gitee.com/api/v5/user?access_token=%s"; - - /** - * 开源中国用户信息 - */ - String OSC_USER_INFO_URL = "https://www.oschina.net/action/openapi/user?access_token=%s&dataType=json"; - /** * 钉钉获取 token */ diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java index 46bf392f3..7c953dc0a 100644 --- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java @@ -55,16 +55,6 @@ public enum LoginTypeEnum { */ MINI_APP("MINI", "微信小程序"), - /** - * 码云登录 - */ - GITEE("GITEE", "码云登录"), - - /** - * 开源中国登录 - */ - OSC("OSC", "开源中国登录"), - /** * 钉钉 */ diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserDTO.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserDTO.java index 797a30f16..f6d4c4e34 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserDTO.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/dto/UserDTO.java @@ -35,6 +35,36 @@ import java.util.List; @EqualsAndHashCode(callSuper = true) public class UserDTO extends SysUser { + /** + * 微信 openid + */ + @Schema(description = "微信openid") + private String wxOpenid; + + /** + * 企业微信 userid + */ + @Schema(description = "企业微信userid") + private String wxCpUserid; + + /** + * 钉钉 openid + */ + @Schema(description = "钉钉openid") + private String wxDingUserid; + + /** + * 微信小程序 openid + */ + @Schema(description = "微信小程序openid") + private String miniOpenid; + + /** + * QQ openid + */ + @Schema(description = "QQ openid") + private String qqOpenid; + /** * 角色ID */ diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java index 57cd28429..5b4fd3a3b 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java @@ -156,48 +156,6 @@ public class SysUser extends Model implements Serializable { @Schema(description = "用户主部门id") private Long deptId; - /** - * 微信openid - */ - @Schema(description = "微信openid") - private String wxOpenid; - - /** - * 企微微信 userid - */ - @Schema(description = "企微微信 userid") - private String wxCpUserid; - - /** - * 钉钉 userid - */ - @Schema(description = "钉钉 userid") - private String wxDingUserid; - - /** - * 微信小程序openId - */ - @Schema(description = "微信小程序openid") - private String miniOpenid; - - /** - * QQ openid - */ - @Schema(description = "QQ openid") - private String qqOpenid; - - /** - * 码云唯一标识 - */ - @Schema(description = "码云唯一标识") - private String giteeLogin; - - /** - * 开源中国唯一标识 - */ - @Schema(description = "开源中国唯一标识") - private String oscId; - /** * 昵称 */ diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserSocial.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserSocial.java new file mode 100644 index 000000000..457c2c0a0 --- /dev/null +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserSocial.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018-2026, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.admin.api.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +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 com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.time.LocalDateTime; + +/** + * 用户社交登录身份表 + * + * @author lengleng + * @date 2026-08-04 + */ +@Data +@TableName("sys_user_social") +@Schema(description = "用户社交登录身份") +@EqualsAndHashCode(callSuper = true) +public class SysUserSocial extends Model { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "主键") + private Long id; + + /** + * 用户ID + */ + @Schema(description = "用户ID") + private Long userId; + + /** + * 社交平台类型 + */ + @Schema(description = "社交平台类型") + private String type; + + /** + * 唯一凭据 + */ + @Schema(description = "唯一凭据") + private String identifier; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java index f420f7964..ef3421207 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/UserVO.java @@ -69,42 +69,6 @@ public class UserVO implements Serializable { @JsonIgnore private String salt; - /** - * 微信openid - */ - @Schema(description = "微信open id") - private String wxOpenid; - - /** - * QQ openid - */ - @Schema(description = "qq open id") - private String qqOpenid; - - /** - * gitee openid - */ - @Schema(description = "gitee open id") - private String giteeOpenId; - - /** - * 开源中国 openid - */ - @Schema(description = "开源中国 open id") - private String oscOpenId; - - /** - * 企微微信 userid - */ - @Schema(description = "企微微信 userid") - private String wxCpUserid; - - /** - * 钉钉 userid - */ - @Schema(description = "钉钉 userid") - private String wxDingUserid; - /** * 创建时间 */ diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java index 5a935ce1d..31d2649a9 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysUserController.java @@ -256,6 +256,16 @@ public class SysUserController { return userService.unbinding(type); } + /** + * 查询当前用户已绑定的社交平台类型 + * + * @return 已绑定的社交平台类型列表 + */ + @GetMapping("/social") + public R> socialTypes() { + return R.ok(userService.listCurrentUserSocialTypes()); + } + /** * 校验密码接口 * diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/DingTalkLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/DingTalkLoginHandler.java index 117c6ca97..43e114ce9 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/DingTalkLoginHandler.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/DingTalkLoginHandler.java @@ -22,11 +22,14 @@ import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.pig4cloud.pigx.admin.api.dto.UserDTO; import com.pig4cloud.pigx.admin.api.dto.UserInfo; import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; import com.pig4cloud.pigx.admin.api.entity.SysUser; +import com.pig4cloud.pigx.admin.api.entity.SysUserSocial; import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; +import com.pig4cloud.pigx.admin.mapper.SysUserSocialMapper; import com.pig4cloud.pigx.admin.service.SysUserService; import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; import com.pig4cloud.pigx.common.core.util.R; @@ -49,6 +52,8 @@ public class DingTalkLoginHandler extends AbstractLoginHandler { private final SysSocialDetailsMapper sysSocialDetailsMapper; + private final SysUserSocialMapper sysUserSocialMapper; + /** * QQ登录传入code *

@@ -111,17 +116,31 @@ public class DingTalkLoginHandler extends AbstractLoginHandler { } /** - * 绑定逻辑 + * 将钉钉 openId 绑定到指定用户。 + *

+ * 按用户 ID + 平台类型写入 {@code sys_user_social}:已存在则覆盖 {@code identifier}, + * 不存在则插入。同一用户同一平台仅保留一条绑定。 + *

* - * @param user 用户实体 - * @param identify 渠道返回唯一标识 - * @return + * @param user 待绑定用户,不可为 null,且 {@code userId} 必须有效 + * @param identify 钉钉 openId,渠道返回的唯一凭据 + * @return 写入成功返回 {@code true},插入或更新影响行数小于 1 时返回 {@code false} + * @throws org.springframework.dao.DuplicateKeyException 当 {@code identify} 已被其他用户占用时 */ @Override public Boolean bind(SysUser user, String identify) { - user.setWxDingUserid(identify); - sysUserService.updateById(user); - return true; + SysUserSocial existing = sysUserSocialMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysUserSocial::getUserId, user.getUserId()) + .eq(SysUserSocial::getType, LoginTypeEnum.DINGTALK.getType())); + if (existing != null) { + existing.setIdentifier(identify); + return sysUserSocialMapper.updateById(existing) > 0; + } + SysUserSocial social = new SysUserSocial(); + social.setUserId(user.getUserId()); + social.setType(LoginTypeEnum.DINGTALK.getType()); + social.setIdentifier(identify); + return sysUserSocialMapper.insert(social) > 0; } } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/GiteeLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/GiteeLoginHandler.java deleted file mode 100644 index 77cc4043a..000000000 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/GiteeLoginHandler.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2018-2026, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.admin.handler; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.URLUtil; -import cn.hutool.http.HttpUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.pig4cloud.pigx.admin.api.dto.UserDTO; -import com.pig4cloud.pigx.admin.api.dto.UserInfo; -import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; -import com.pig4cloud.pigx.admin.api.entity.SysUser; -import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; -import com.pig4cloud.pigx.admin.service.SysUserService; -import com.pig4cloud.pigx.common.core.constant.SecurityConstants; -import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; -import com.pig4cloud.pigx.common.core.util.R; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.HashMap; - -/** - * @author lengleng - * @date 2019/4/8 - *

- * 码云登录 - */ -@Slf4j -@Component("GITEE") -@AllArgsConstructor -public class GiteeLoginHandler extends AbstractLoginHandler { - - private final SysSocialDetailsMapper sysSocialDetailsMapper; - - private final SysUserService sysUserService; - - /** - * 码云登录传入code - *

- * 通过code 调用qq 获取唯一标识 - * @param code - * @return - */ - @Override - public String identify(String code) { - SysSocialDetails condition = new SysSocialDetails(); - condition.setType(LoginTypeEnum.GITEE.getType()); - SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition)); - - String url = String.format(SecurityConstants.GITEE_AUTHORIZATION_CODE_URL, code, socialDetails.getAppId(), - URLUtil.encode(socialDetails.getRedirectUrl()), socialDetails.getAppSecret()); - String result = HttpUtil.post(url, new HashMap<>(0)); - log.debug("码云响应报文:{}", result); - - String accessToken = JSONUtil.parseObj(result).getStr("access_token"); - String userUrl = String.format(SecurityConstants.GITEE_USER_INFO_URL, accessToken); - String resp = HttpUtil.get(userUrl); - log.debug("码云获取个人信息返回报文{}", resp); - - JSONObject userInfo = JSONUtil.parseObj(resp); - // 码云唯一标识 - return userInfo.getStr("login"); - } - - /** - * 根据标识获取用户信息 - * @param identify 用户标识 - * @return 用户信息,未找到时返回null - */ - @Override - public UserInfo info(String identify) { - if (StrUtil.isBlank(identify)) { - log.warn("Gitee标识为空,无法获取用户信息"); - return null; - } - - UserDTO userDTO = new UserDTO(); - userDTO.setGiteeLogin(identify); - - R userInfoR = sysUserService.getUserInfo(userDTO); - - if (userInfoR.getData() == null) { - log.info("微信 不存在用户:{}", identify); - return null; - } - - return userInfoR.getData(); - } - - /** - * 绑定逻辑 - * @param user 用户实体 - * @param identify 渠道返回唯一标识 - * @return - */ - @Override - public Boolean bind(SysUser user, String identify) { - user.setGiteeLogin(identify); - sysUserService.updateById(user); - return true; - } - -} diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/OscChinaLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/OscChinaLoginHandler.java deleted file mode 100644 index 5a796b694..000000000 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/OscChinaLoginHandler.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2018-2025, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.admin.handler; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.http.HttpUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.pig4cloud.pigx.admin.api.dto.UserDTO; -import com.pig4cloud.pigx.admin.api.dto.UserInfo; -import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; -import com.pig4cloud.pigx.admin.api.entity.SysUser; -import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; -import com.pig4cloud.pigx.admin.service.SysUserService; -import com.pig4cloud.pigx.common.core.constant.SecurityConstants; -import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; -import com.pig4cloud.pigx.common.core.util.R; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author lengleng - * @date 2019/4/8 - *

- * 开源中国登录 - */ -@Slf4j -@Component("OSC") -@AllArgsConstructor -public class OscChinaLoginHandler extends AbstractLoginHandler { - - private final SysSocialDetailsMapper sysSocialDetailsMapper; - - private final SysUserService sysUserService; - - /** - * 开源中国传入code - *

- * 通过code 调用qq 获取唯一标识 - * - * @param code - * @return - */ - @Override - public String identify(String code) { - SysSocialDetails condition = new SysSocialDetails(); - condition.setType(LoginTypeEnum.OSC.getType()); - SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition)); - - Map params = new HashMap<>(8); - - params.put("client_id", socialDetails.getAppId()); - params.put("client_secret", socialDetails.getAppSecret()); - params.put("grant_type", "authorization_code"); - params.put("redirect_uri", socialDetails.getRedirectUrl()); - params.put("code", code); - params.put("dataType", "json"); - - String result = HttpUtil.post(SecurityConstants.OSC_AUTHORIZATION_CODE_URL, params); - log.debug("开源中国响应报文:{}", result); - - String accessToken = JSONUtil.parseObj(result).getStr("access_token"); - - String url = String.format(SecurityConstants.OSC_USER_INFO_URL, accessToken); - String resp = HttpUtil.get(url); - log.debug("开源中国获取个人信息返回报文{}", resp); - - JSONObject userInfo = JSONUtil.parseObj(resp); - // 开源中国唯一标识 - return userInfo.getStr("id"); - } - - /** - * 根据开源中国标识获取用户信息 - * - * @param identify 开源中国用户标识 - * @return 用户信息对象,未找到时返回null - */ - @Override - public UserInfo info(String identify) { - if (StrUtil.isBlank(identify)) { - log.warn("开源中国标识为空,无法获取用户信息"); - return null; - } - - UserDTO userDTO = new UserDTO(); - userDTO.setOscId(identify); - - R userInfoR = sysUserService.getUserInfo(userDTO); - - if (userInfoR.getData() == null) { - log.info("开源中国 不存在用户:{}", identify); - return null; - } - - return userInfoR.getData(); - } - - /** - * 绑定逻辑 - * - * @param user 用户实体 - * @param identify 渠道返回唯一标识 - * @return - */ - @Override - public Boolean bind(SysUser user, String identify) { - user.setOscId(identify); - sysUserService.updateById(user); - return true; - } - -} diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatCPLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatCPLoginHandler.java index 5bdf80acc..158544779 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatCPLoginHandler.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatCPLoginHandler.java @@ -21,11 +21,14 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.pig4cloud.pigx.admin.api.dto.UserDTO; import com.pig4cloud.pigx.admin.api.dto.UserInfo; import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; import com.pig4cloud.pigx.admin.api.entity.SysUser; +import com.pig4cloud.pigx.admin.api.entity.SysUserSocial; import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; +import com.pig4cloud.pigx.admin.mapper.SysUserSocialMapper; import com.pig4cloud.pigx.admin.service.SysUserService; import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; import com.pig4cloud.pigx.common.core.util.R; @@ -48,6 +51,8 @@ public class WeChatCPLoginHandler extends AbstractLoginHandler { private final SysSocialDetailsMapper sysSocialDetailsMapper; + private final SysUserSocialMapper sysUserSocialMapper; + /** * 企微登录传入code *

@@ -102,17 +107,31 @@ public class WeChatCPLoginHandler extends AbstractLoginHandler { } /** - * 绑定逻辑 + * 将企业微信 userid 绑定到指定用户。 + *

+ * 按用户 ID + 平台类型写入 {@code sys_user_social}:已存在则覆盖 {@code identifier}, + * 不存在则插入。同一用户同一平台仅保留一条绑定。 + *

* - * @param user 用户实体 - * @param identify 渠道返回唯一标识 - * @return + * @param user 待绑定用户,不可为 null,且 {@code userId} 必须有效 + * @param identify 企业微信 userid,渠道返回的唯一凭据 + * @return 写入成功返回 {@code true},插入或更新影响行数小于 1 时返回 {@code false} + * @throws org.springframework.dao.DuplicateKeyException 当 {@code identify} 已被其他用户占用时 */ @Override public Boolean bind(SysUser user, String identify) { - user.setWxCpUserid(identify); - sysUserService.updateById(user); - return true; + SysUserSocial existing = sysUserSocialMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysUserSocial::getUserId, user.getUserId()) + .eq(SysUserSocial::getType, LoginTypeEnum.WEIXIN_CP.getType())); + if (existing != null) { + existing.setIdentifier(identify); + return sysUserSocialMapper.updateById(existing) > 0; + } + SysUserSocial social = new SysUserSocial(); + social.setUserId(user.getUserId()); + social.setType(LoginTypeEnum.WEIXIN_CP.getType()); + social.setIdentifier(identify); + return sysUserSocialMapper.insert(social) > 0; } } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java index f74287016..6cde5a95b 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java @@ -21,11 +21,14 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.pig4cloud.pigx.admin.api.dto.UserDTO; import com.pig4cloud.pigx.admin.api.dto.UserInfo; import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; import com.pig4cloud.pigx.admin.api.entity.SysUser; +import com.pig4cloud.pigx.admin.api.entity.SysUserSocial; import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; +import com.pig4cloud.pigx.admin.mapper.SysUserSocialMapper; import com.pig4cloud.pigx.admin.service.SysUserService; import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; @@ -47,6 +50,8 @@ public class WeChatLoginHandler extends AbstractLoginHandler { private final SysSocialDetailsMapper sysSocialDetailsMapper; + private final SysUserSocialMapper sysUserSocialMapper; + /** * 微信登录传入code *

@@ -96,17 +101,31 @@ public class WeChatLoginHandler extends AbstractLoginHandler { } /** - * 绑定逻辑 + * 将微信 openId 绑定到指定用户。 + *

+ * 按用户 ID + 平台类型写入 {@code sys_user_social}:已存在则覆盖 {@code identifier}, + * 不存在则插入。同一用户同一平台仅保留一条绑定。 + *

* - * @param user 用户实体 - * @param identify 渠道返回唯一标识 - * @return + * @param user 待绑定用户,不可为 null,且 {@code userId} 必须有效 + * @param identify 微信 openId,渠道返回的唯一凭据 + * @return 写入成功返回 {@code true},插入或更新影响行数小于 1 时返回 {@code false} + * @throws org.springframework.dao.DuplicateKeyException 当 {@code identify} 已被其他用户占用时 */ @Override public Boolean bind(SysUser user, String identify) { - user.setWxOpenid(identify); - sysUserService.updateById(user); - return true; + SysUserSocial existing = sysUserSocialMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysUserSocial::getUserId, user.getUserId()) + .eq(SysUserSocial::getType, LoginTypeEnum.WECHAT.getType())); + if (existing != null) { + existing.setIdentifier(identify); + return sysUserSocialMapper.updateById(existing) > 0; + } + SysUserSocial social = new SysUserSocial(); + social.setUserId(user.getUserId()); + social.setType(LoginTypeEnum.WECHAT.getType()); + social.setIdentifier(identify); + return sysUserSocialMapper.insert(social) > 0; } } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserSocialMapper.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserSocialMapper.java new file mode 100644 index 000000000..5632f8724 --- /dev/null +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserSocialMapper.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018-2026, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.admin.mapper; + +import com.pig4cloud.pigx.admin.api.entity.SysUserSocial; +import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 用户社交登录身份 Mapper + * + * @author lengleng + * @date 2026-08-04 + */ +@Mapper +public interface SysUserSocialMapper extends PigxBaseMapper { + + /** + * 根据用户ID查询已绑定的社交平台类型 + * + * @param userId 用户ID + * @return 已绑定的社交平台类型列表 + */ + List selectTypesByUserId(@Param("userId") Long userId); + +} diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java index d655bff5e..e8267f251 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysUserService.java @@ -155,6 +155,13 @@ public interface SysUserService extends IService { */ R unbinding(String type); + /** + * 查询当前用户已绑定的社交平台类型 + * + * @return 已绑定的社交平台类型列表 + */ + List listCurrentUserSocialTypes(); + /** * 校验密码 * diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java index 2bb24e217..0a9279dd0 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java @@ -2,16 +2,22 @@ package com.pig4cloud.pigx.admin.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.pig4cloud.pigx.admin.api.dto.UserDTO; import com.pig4cloud.pigx.admin.api.entity.SysDept; import com.pig4cloud.pigx.admin.api.entity.SysUser; +import com.pig4cloud.pigx.admin.api.entity.SysUserSocial; +import com.pig4cloud.pigx.admin.mapper.SysUserSocialMapper; import com.pig4cloud.pigx.admin.service.ConnectService; import com.pig4cloud.pigx.admin.service.SysDeptService; import com.pig4cloud.pigx.admin.service.SysUserService; +import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; +import com.pig4cloud.pigx.common.core.exception.CheckedException; import com.pig4cloud.pigx.common.core.util.R; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -52,6 +58,8 @@ public class ConnectServiceImpl implements ConnectService { */ private final SysUserService sysUserService; + private final SysUserSocialMapper sysUserSocialMapper; + /** * 导入企业微信部门 @@ -179,10 +187,11 @@ public class ConnectServiceImpl implements ConnectService { * - 新用户: 创建用户账号 * - 部门不存在: 分配到根部门(parentId=0) * - 初始密码: 手机号 + * - 社交账号冲突: 当前行回滚并记录错误,其他合法行继续导入并提交 * * @param excelVOList Excel 数据列表 * @param bindingResult 字段级别校验结果 - * @return 导入结果 + * @return 全部成功时返回成功结果;任一行校验或绑定失败时返回逐行错误,已成功行仍会保留 */ @Override @Transactional(rollbackFor = Exception.class) @@ -241,31 +250,54 @@ public class ConnectServiceImpl implements ConnectService { // 8. 判断用户是否已存在(通过手机号) SysUser existingUser = phoneUserMap.get(phone); - if (existingUser != null) { - // 用户已存在,更新用户信息(覆盖模式) - existingUser.setName(excel.getName()); - existingUser.setNickname(nickname); - existingUser.setEmail(excel.getEmail()); - existingUser.setDeptId(primaryDeptId); - existingUser.setWxCpUserid(excel.getAccount()); + try { + if (existingUser != null) { + // 用户已存在,更新用户信息(覆盖模式) + existingUser.setName(excel.getName()); + existingUser.setNickname(nickname); + existingUser.setEmail(excel.getEmail()); + existingUser.setDeptId(primaryDeptId); - sysUserService.updateById(existingUser); - updateCount++; - } else { - // 新用户,创建账号 - UserDTO userDTO = new UserDTO(); - userDTO.setUsername(phone); - userDTO.setPhone(phone); - userDTO.setName(excel.getName()); - userDTO.setNickname(nickname); - userDTO.setEmail(excel.getEmail()); - userDTO.setDeptIds(deptIds); // 设置多部门 - userDTO.setPassword(phone); - userDTO.setPasswordModifyTime(LocalDateTime.now()); - userDTO.setWxCpUserid(excel.getAccount()); + // 覆盖企微绑定:同用户同平台已存在则更新 identifier,否则插入 + SysUserSocial existingSocial = sysUserSocialMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysUserSocial::getUserId, existingUser.getUserId()) + .eq(SysUserSocial::getType, LoginTypeEnum.WEIXIN_CP.getType())); + if (existingSocial != null) { + existingSocial.setIdentifier(excel.getAccount()); + sysUserSocialMapper.updateById(existingSocial); + } else { + SysUserSocial social = new SysUserSocial(); + social.setUserId(existingUser.getUserId()); + social.setType(LoginTypeEnum.WEIXIN_CP.getType()); + social.setIdentifier(excel.getAccount()); + sysUserSocialMapper.insert(social); + } + sysUserService.updateById(existingUser); + updateCount++; + } else { + // 新用户,创建账号 + UserDTO userDTO = new UserDTO(); + userDTO.setUsername(phone); + userDTO.setPhone(phone); + userDTO.setName(excel.getName()); + userDTO.setNickname(nickname); + userDTO.setEmail(excel.getEmail()); + userDTO.setDeptIds(deptIds); // 设置多部门 + userDTO.setPassword(phone); + userDTO.setPasswordModifyTime(LocalDateTime.now()); + userDTO.setUserId(IdWorker.getId()); - sysUserService.saveUser(userDTO); - successCount++; + sysUserService.saveUser(userDTO); + SysUserSocial social = new SysUserSocial(); + social.setUserId(userDTO.getUserId()); + social.setType(LoginTypeEnum.WEIXIN_CP.getType()); + social.setIdentifier(excel.getAccount()); + sysUserSocialMapper.insert(social); + successCount++; + } + } catch (CheckedException | DuplicateKeyException ex) { + errorMsg.add(ex.getMessage()); + errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMsg)); } } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java index 84999ae4c..6e425abaf 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java @@ -21,7 +21,6 @@ package com.pig4cloud.pigx.admin.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -69,6 +68,11 @@ import java.util.*; import java.util.stream.Collectors; /** + * 用户服务实现。 + *

+ * 用户基础资料由 {@code sys_user} 维护,社交登录凭据由 {@code sys_user_social} 独立维护。 + *

+ * * @author lengleng * @date 2026-02-10 */ @@ -79,6 +83,9 @@ public class SysUserServiceImpl extends ServiceImpl impl private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder(); + private static final Set UNBIND_TYPES = Set.of(LoginTypeEnum.WECHAT.getType(), + LoginTypeEnum.WEIXIN_CP.getType(), LoginTypeEnum.DINGTALK.getType()); + private final SysMenuService sysMenuService; private final SysRoleService sysRoleService; @@ -97,6 +104,8 @@ public class SysUserServiceImpl extends ServiceImpl impl private final SysTenantUserMapper sysTenantUserMapper; + private final SysUserSocialMapper sysUserSocialMapper; + private final CacheManager cacheManager; private final SysDeptMapper sysDeptMapper; @@ -267,6 +276,8 @@ public class SysUserServiceImpl extends ServiceImpl impl // 用户降级处理,如果用户关联了其他租户,则不删除用户信息,仅删除当前租户关联关系并更新用户所属租户;如果没有关联其他租户,则删除用户信息 List removableUserIds = findRemovableUserIds(userList, currentTenantId); if (CollUtil.isNotEmpty(removableUserIds)) { + sysUserSocialMapper.delete(Wrappers.lambdaQuery() + .in(SysUserSocial::getUserId, removableUserIds)); this.removeBatchByIds(removableUserIds); } return Boolean.TRUE; @@ -682,39 +693,28 @@ public class SysUserServiceImpl extends ServiceImpl impl * @return 操作结果,成功返回R.ok(),失败返回R.failed() */ @Override + @Transactional(rollbackFor = Exception.class) public R unbinding(String type) { PigxUser user = SecurityUtils.getUser(); - LambdaUpdateWrapper wrapper = null; - - // 微信开放平台 (普通用户扫码登录) - if (type.equals(LoginTypeEnum.WECHAT.getType())) { - wrapper = Wrappers.lambdaUpdate() - .set(SysUser::getWxOpenid, null) - .eq(SysUser::getUserId, user.getId()); - // 码云登录 (方便申请) - } else if (type.equals(LoginTypeEnum.GITEE.getType())) { - wrapper = Wrappers.lambdaUpdate() - .set(SysUser::getGiteeLogin, null) - .eq(SysUser::getUserId, user.getId()); - // 企业微信登录 - } else if (type.equals(LoginTypeEnum.WEIXIN_CP.getType())) { - wrapper = Wrappers.lambdaUpdate() - .set(SysUser::getWxCpUserid, null) - .eq(SysUser::getUserId, user.getId()); - // 钉钉登录 - } else if (type.equals(LoginTypeEnum.DINGTALK.getType())) { - wrapper = Wrappers.lambdaUpdate() - .set(SysUser::getWxDingUserid, null) - .eq(SysUser::getUserId, user.getId()); - } - - if (Objects.isNull(wrapper)) { + if (Objects.isNull(type) || !UNBIND_TYPES.contains(type)) { return R.failed(MsgUtils.getMessage(UpmsErrorCodes.SYS_USER_UNBIND_TYPE_NOT_FOUND)); } - this.update(wrapper); + sysUserSocialMapper.delete(Wrappers.lambdaQuery() + .eq(SysUserSocial::getUserId, user.getId()) + .eq(SysUserSocial::getType, type)); return R.ok(); } + /** + * 查询当前用户已绑定的社交平台类型。 + * + * @return 已绑定的社交平台类型列表 + */ + @Override + public List listCurrentUserSocialTypes() { + return sysUserSocialMapper.selectTypesByUserId(SecurityUtils.getUser().getId()); + } + /** * 检查用户密码是否正确 * diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml index 49dab7241..4bcd94655 100644 --- a/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml +++ b/pigx-upms/pigx-upms-biz/src/main/resources/mapper/SysUserMapper.xml @@ -13,12 +13,6 @@ - - - - - - @@ -51,12 +45,6 @@ u.name, u.nickname, u.email, - u.wx_openid, - u.qq_openid, - u.gitee_login, - u.osc_id, - u.wx_cp_userid, - u.wx_ding_userid, u.del_flag, u.lock_flag, u.password_expire_flag, @@ -72,31 +60,29 @@ SELECT FROM sys_user u + + INNER JOIN sys_user_social wx_cp_social ON wx_cp_social.user_id = u.user_id + AND wx_cp_social.type = 'WEIXIN_CP' AND wx_cp_social.identifier = #{query.wxCpUserid} + + + INNER JOIN sys_user_social dingtalk_social ON dingtalk_social.user_id = u.user_id + AND dingtalk_social.type = 'DINGTALK' AND dingtalk_social.identifier = #{query.wxDingUserid} + + + INNER JOIN sys_user_social wx_social ON wx_social.user_id = u.user_id + AND wx_social.type = 'WX' AND wx_social.identifier = #{query.wxOpenid} + + + INNER JOIN sys_user_social mini_social ON mini_social.user_id = u.user_id + AND mini_social.type = 'MINI' AND mini_social.identifier = #{query.miniOpenid} + WHERE u.del_flag = '0' AND u.username = #{query.username} - - AND u.osc_id = #{query.oscId} - AND u.phone = #{query.phone} - - AND u.wx_cp_userid = #{query.wxCpUserid} - - - AND u.wx_ding_userid = #{query.wxDingUserid} - - - AND u.gitee_login = #{query.giteeLogin} - - - AND u.wx_openid = #{query.wxOpenid} - - - AND u.mini_openid = #{query.miniOpenid} - + SELECT social.type + FROM sys_user_social social + WHERE social.user_id = #{userId} + + +