Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
D
dsk-cr20g
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
dsk-cr20g
Commits
077f62f4
Commit
077f62f4
authored
Aug 22, 2024
by
fulixin
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'V20240319三方平台登录改造' into V20240805
parents
798456ab
f50c2397
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
2683 additions
and
1820 deletions
+2683
-1820
SysLoginController.java
...ava/com/dsk/web/controller/system/SysLoginController.java
+268
-262
application-prod.yml
dsk-admin/src/main/resources/application-prod.yml
+29
-6
application-test.yml
dsk-admin/src/main/resources/application-test.yml
+32
-7
application.yml
dsk-admin/src/main/resources/application.yml
+5
-1
LoginUser.java
...main/java/com/dsk/common/core/domain/model/LoginUser.java
+5
-0
ThirdPlatformLoginBody.java
.../dsk/common/core/domain/model/ThirdPlatformLoginBody.java
+19
-0
IndexController.java
...src/main/java/com/dsk/jsk/controller/IndexController.java
+279
-0
IndexService.java
...z-api/src/main/java/com/dsk/jsk/service/IndexService.java
+272
-0
package.json
dsk-operate-ui/package.json
+1
-0
login.js
dsk-operate-ui/src/api/login.js
+32
-20
Navbar.vue
dsk-operate-ui/src/layout/components/Navbar.vue
+6
-3
index.vue
dsk-operate-ui/src/layout/components/Sidebar/index.vue
+8
-1
permission.js
dsk-operate-ui/src/permission.js
+43
-12
index.js
dsk-operate-ui/src/router/index.js
+129
-131
permission.js
dsk-operate-ui/src/store/modules/permission.js
+9
-6
user.js
dsk-operate-ui/src/store/modules/user.js
+30
-2
auth.js
dsk-operate-ui/src/utils/auth.js
+39
-0
401.vue
dsk-operate-ui/src/views/error/401.vue
+69
-41
SysUser.java
dsk-system/src/main/java/com/dsk/system/domain/SysUser.java
+184
-179
SysLoginService.java
...src/main/java/com/dsk/system/service/SysLoginService.java
+705
-636
ISysTenantServiceImpl.java
...va/com/dsk/system/service/impl/ISysTenantServiceImpl.java
+519
-513
No files found.
dsk-admin/src/main/java/com/dsk/web/controller/system/SysLoginController.java
View file @
077f62f4
package
com
.
dsk
.
web
.
controller
.
system
;
import
cn.dev33.satoken.annotation.SaCheckLogin
;
import
cn.dev33.satoken.annotation.SaIgnore
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.lang.Assert
;
import
cn.hutool.core.lang.RegexPool
;
import
cn.hutool.core.map.MapUtil
;
import
cn.hutool.core.util.RandomUtil
;
import
cn.hutool.core.util.ReUtil
;
import
com.dsk.common.constant.Constants
;
import
com.dsk.common.constant.GlobalConstants
;
import
com.dsk.common.core.domain.R
;
import
com.dsk.common.exception.ServiceException
;
import
com.dsk.common.tenant.helper.TenantHelper
;
import
com.dsk.common.utils.StringUtils
;
import
com.dsk.common.utils.redis.RedisUtils
;
import
com.dsk.jsk.util.IpUtil
;
import
com.dsk.system.domain.SysMenu
;
import
com.dsk.system.domain.SysUser
;
import
com.dsk.common.core.domain.model.EmailLoginBody
;
import
com.dsk.common.core.domain.model.LoginBody
;
import
com.dsk.common.core.domain.model.LoginUser
;
import
com.dsk.common.core.domain.model.SmsLoginBody
;
import
com.dsk.common.helper.LoginHelper
;
import
com.dsk.system.domain.vo.LoginVo
;
import
com.dsk.system.domain.vo.RouterVo
;
import
com.dsk.system.domain.vo.SysTenantVo
;
import
com.dsk.system.service.ISysMenuService
;
import
com.dsk.system.service.ISysUserService
;
import
com.dsk.system.service.SysLoginService
;
import
lombok.RequiredArgsConstructor
;
import
org.dromara.sms4j.api.SmsBlend
;
import
org.dromara.sms4j.api.entity.SmsResponse
;
import
org.dromara.sms4j.core.factory.SmsFactory
;
import
org.dromara.sms4j.provider.enumerate.SupplierType
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.validation.constraints.NotBlank
;
import
java.time.Duration
;
import
java.util.*
;
/**
* 登录验证
*
* @author Lion Li
*/
@Validated
@RequiredArgsConstructor
@RestController
public
class
SysLoginController
{
private
final
SysLoginService
loginService
;
private
final
ISysMenuService
menuService
;
private
final
ISysUserService
userService
;
/**
* 登录方法
*
* @param loginBody 登录信息
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/login"
)
public
R
<
LoginVo
>
login
(
@Validated
@RequestBody
LoginBody
loginBody
,
HttpServletRequest
request
)
{
// Map<String, Object> ajax = new HashMap<>();
// 生成令牌
// LoginVo loginVo = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
// loginBody.getUuid());
// ajax.put(Constants.TOKEN, token);
// return R.ok(ajax);
String
ipAddr
=
IpUtil
.
getIpAddr
(
request
);
LoginVo
loginVo
=
loginService
.
passwordLogin
(
loginBody
,
ipAddr
);
return
R
.
ok
(
loginVo
);
}
// /**
// * 发送短信验证码
// *
// * @param phones 电话号
// * @param templateId 模板ID
// */
// @SaIgnore
// @GetMapping("/send/sms/code")
// public R<Object> sendAliyun(String phones, String templateId) {
// LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
// map.put("code", RandomUtil.randomNumbers(4));
// SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
// SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
// return R.ok(smsResponse);
// }
/**
* 短信登录
*
* @param smsLoginBody 登录信息
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/smsLogin"
)
public
R
<
LoginVo
>
smsLogin
(
@Validated
@RequestBody
SmsLoginBody
smsLoginBody
)
{
// 生成令牌
LoginVo
loginVo
=
loginService
.
smsLogin
(
smsLoginBody
.
getPhonenumber
(),
smsLoginBody
.
getSmsCode
());
return
R
.
ok
(
loginVo
);
}
/**
* 动态切换租户
*/
@SaCheckLogin
@PostMapping
(
"/switch/tenant"
)
public
R
<
LoginVo
>
switchTenant
(
String
tenantId
)
{
LoginVo
loginVo
=
loginService
.
switchTenant
(
tenantId
);
return
R
.
ok
(
loginVo
);
}
/**
* 用户租户列表:根据用户账号获取用户绑定的租户列表
*
* @return 结果
*/
@SaCheckLogin
@PostMapping
(
"/user/tenants"
)
public
R
<
List
<
SysTenantVo
>>
userTenants
()
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
List
<
SysTenantVo
>
tenantList
=
loginService
.
tenantListByAccount
(
loginUser
.
getUserPhone
());
return
R
.
ok
(
tenantList
);
}
/**
* 用户租户列表:根据用户账号获取用户绑定的租户列表
*
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/user/tenant/list"
)
public
R
<
List
<
SysTenantVo
>>
userTenantList
(
String
phone
)
{
if
(!
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
phone
))
{
return
R
.
ok
(
new
ArrayList
<>());
}
List
<
SysTenantVo
>
tenantList
=
loginService
.
tenantListByAccount
(
phone
);
if
(
CollectionUtil
.
isNotEmpty
(
tenantList
))
{
for
(
SysTenantVo
sysTenantVo
:
tenantList
)
{
sysTenantVo
.
setCompanyName
(
""
);
}
}
return
R
.
ok
(
tenantList
);
}
/**
* 获取当前用户默认租户
*
* @return
*/
@SaCheckLogin
@PostMapping
(
"/user/default/tenant"
)
public
R
<
Map
>
userDefaultTenant
()
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
Assert
.
notNull
(
loginUser
,
"用户信息不存在!"
);
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
loginUser
.
getUserPhone
();
String
defaultTenant
=
RedisUtils
.
getCacheObject
(
defaultTenantKey
);
return
R
.
ok
(
MapUtil
.
of
(
"tenantId"
,
defaultTenant
));
}
/**
* 获取当前用户默认租户
*
* @return
*/
@SaIgnore
@PostMapping
(
"/user/default/tenant/phone"
)
public
R
<
Map
>
userDefaultTenant
(
String
phone
)
{
// LoginUser loginUser = LoginHelper.getLoginUser();
// Assert.notNull(loginUser,"用户信息不存在!");
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phone
;
String
defaultTenant
=
RedisUtils
.
getCacheObject
(
defaultTenantKey
);
return
R
.
ok
(
MapUtil
.
of
(
"tenantId"
,
defaultTenant
));
}
/**
* 邮件登录
*
* @param body 登录信息
* @return 结果
*/
@PostMapping
(
"/emailLogin"
)
public
R
<
Map
<
String
,
Object
>>
emailLogin
(
@Validated
@RequestBody
EmailLoginBody
body
)
{
Map
<
String
,
Object
>
ajax
=
new
HashMap
<>();
// 生成令牌
String
token
=
loginService
.
emailLogin
(
body
.
getEmail
(),
body
.
getEmailCode
());
ajax
.
put
(
Constants
.
TOKEN
,
token
);
return
R
.
ok
(
ajax
);
}
/**
* 小程序登录(示例)
*
* @param xcxCode 小程序code
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/xcxLogin"
)
public
R
<
Map
<
String
,
Object
>>
xcxLogin
(
@NotBlank
(
message
=
"{xcx.code.not.blank}"
)
String
xcxCode
)
{
Map
<
String
,
Object
>
ajax
=
new
HashMap
<>();
// 生成令牌
String
token
=
loginService
.
xcxLogin
(
xcxCode
);
ajax
.
put
(
Constants
.
TOKEN
,
token
);
return
R
.
ok
(
ajax
);
}
/**
* 退出登录
*/
@SaIgnore
@PostMapping
(
"/logout"
)
public
R
<
Void
>
logout
()
{
loginService
.
logout
();
return
R
.
ok
(
"退出成功"
);
}
/**
* 获取用户信息
*
* @return 用户信息
*/
@GetMapping
(
"getInfo"
)
public
R
<
Map
<
String
,
Object
>>
getInfo
(
HttpServletRequest
request
)
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
//校验当前发请求的IP与登录账号的IP是否相同
// String loginUserIpaddr = loginUser.getIpaddr();
// if (StringUtils.isNotBlank(loginUserIpaddr) && !Objects.equals(IpUtil.getIpAddr(request), loginUserIpaddr)) {
// throw new ServiceException("该账号已在其他地方登录,请求失败!", 401);
// }
SysUser
user
=
userService
.
selectUserById
(
loginUser
.
getUserId
());
Map
<
String
,
Object
>
ajax
=
new
HashMap
<>();
ajax
.
put
(
"user"
,
user
);
ajax
.
put
(
"roles"
,
loginUser
.
getRolePermission
());
ajax
.
put
(
"permissions"
,
loginUser
.
getMenuPermission
());
return
R
.
ok
(
ajax
);
}
/**
* 获取路由信息
*
* @return 路由信息
*/
@GetMapping
(
"getRouters"
)
public
R
<
List
<
RouterVo
>>
getRouters
()
{
Long
userId
=
LoginHelper
.
getUserId
();
List
<
SysMenu
>
menus
=
menuService
.
selectMenuTreeByUserId
(
userId
);
return
R
.
ok
(
menuService
.
buildMenus
(
menus
));
}
}
package
com
.
dsk
.
web
.
controller
.
system
;
import
cn.dev33.satoken.annotation.SaCheckLogin
;
import
cn.dev33.satoken.annotation.SaIgnore
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.lang.Assert
;
import
cn.hutool.core.lang.RegexPool
;
import
cn.hutool.core.map.MapUtil
;
import
cn.hutool.core.util.ReUtil
;
import
com.dsk.common.constant.Constants
;
import
com.dsk.common.constant.GlobalConstants
;
import
com.dsk.common.core.domain.R
;
import
com.dsk.common.core.domain.model.*
;
import
com.dsk.common.helper.LoginHelper
;
import
com.dsk.common.utils.redis.RedisUtils
;
import
com.dsk.jsk.util.IpUtil
;
import
com.dsk.system.domain.SysMenu
;
import
com.dsk.system.domain.SysUser
;
import
com.dsk.system.domain.vo.LoginVo
;
import
com.dsk.system.domain.vo.RouterVo
;
import
com.dsk.system.domain.vo.SysTenantVo
;
import
com.dsk.system.service.ISysMenuService
;
import
com.dsk.system.service.ISysUserService
;
import
com.dsk.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
javax.servlet.http.HttpServletRequest
;
import
javax.validation.constraints.NotBlank
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* 登录验证
*
* @author Lion Li
*/
@Validated
@RequiredArgsConstructor
@RestController
public
class
SysLoginController
{
private
final
SysLoginService
loginService
;
private
final
ISysMenuService
menuService
;
private
final
ISysUserService
userService
;
/**
* 登录方法
*
* @param loginBody 登录信息
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/login"
)
public
R
<
LoginVo
>
login
(
@Validated
@RequestBody
LoginBody
loginBody
,
HttpServletRequest
request
)
{
// Map<String, Object> ajax = new HashMap<>();
// 生成令牌
// LoginVo loginVo = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
// loginBody.getUuid());
// ajax.put(Constants.TOKEN, token);
// return R.ok(ajax);
String
ipAddr
=
IpUtil
.
getIpAddr
(
request
);
LoginVo
loginVo
=
loginService
.
passwordLogin
(
loginBody
,
ipAddr
);
return
R
.
ok
(
loginVo
);
}
/**
* 三方平台跳转登录方法
*
* @param tpLoginBody 登录信息
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/thirdPlatformLogin"
)
public
R
<
LoginVo
>
thirdPlatformLogin
(
@Validated
@RequestBody
ThirdPlatformLoginBody
tpLoginBody
,
HttpServletRequest
request
)
{
String
ipAddr
=
IpUtil
.
getIpAddr
(
request
);
return
R
.
ok
(
loginService
.
thirdPlatformLogin
(
tpLoginBody
,
ipAddr
));
}
// /**
// * 发送短信验证码
// *
// * @param phones 电话号
// * @param templateId 模板ID
// */
// @SaIgnore
// @GetMapping("/send/sms/code")
// public R<Object> sendAliyun(String phones, String templateId) {
// LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
// map.put("code", RandomUtil.randomNumbers(4));
// SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
// SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
// return R.ok(smsResponse);
// }
/**
* 短信登录
*
* @param smsLoginBody 登录信息
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/smsLogin"
)
public
R
<
LoginVo
>
smsLogin
(
@Validated
@RequestBody
SmsLoginBody
smsLoginBody
)
{
// 生成令牌
LoginVo
loginVo
=
loginService
.
smsLogin
(
smsLoginBody
.
getPhonenumber
(),
smsLoginBody
.
getSmsCode
());
return
R
.
ok
(
loginVo
);
}
/**
* 动态切换租户
*/
@SaCheckLogin
@PostMapping
(
"/switch/tenant"
)
public
R
<
LoginVo
>
switchTenant
(
String
tenantId
)
{
LoginVo
loginVo
=
loginService
.
switchTenant
(
tenantId
);
return
R
.
ok
(
loginVo
);
}
/**
* 用户租户列表:根据用户账号获取用户绑定的租户列表
*
* @return 结果
*/
@SaCheckLogin
@PostMapping
(
"/user/tenants"
)
public
R
<
List
<
SysTenantVo
>>
userTenants
()
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
List
<
SysTenantVo
>
tenantList
=
loginService
.
tenantListByAccount
(
loginUser
.
getUserPhone
());
return
R
.
ok
(
tenantList
);
}
/**
* 用户租户列表:根据用户账号获取用户绑定的租户列表
*
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/user/tenant/list"
)
public
R
<
List
<
SysTenantVo
>>
userTenantList
(
String
phone
)
{
if
(!
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
phone
))
{
return
R
.
ok
(
new
ArrayList
<>());
}
List
<
SysTenantVo
>
tenantList
=
loginService
.
tenantListByAccount
(
phone
);
if
(
CollectionUtil
.
isNotEmpty
(
tenantList
))
{
for
(
SysTenantVo
sysTenantVo
:
tenantList
)
{
sysTenantVo
.
setCompanyName
(
""
);
}
}
return
R
.
ok
(
tenantList
);
}
/**
* 获取当前用户默认租户
*
* @return
*/
@SaCheckLogin
@PostMapping
(
"/user/default/tenant"
)
public
R
<
Map
>
userDefaultTenant
()
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
Assert
.
notNull
(
loginUser
,
"用户信息不存在!"
);
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
loginUser
.
getUserPhone
();
String
defaultTenant
=
RedisUtils
.
getCacheObject
(
defaultTenantKey
);
return
R
.
ok
(
MapUtil
.
of
(
"tenantId"
,
defaultTenant
));
}
/**
* 获取当前用户默认租户
*
* @return
*/
@SaIgnore
@PostMapping
(
"/user/default/tenant/phone"
)
public
R
<
Map
>
userDefaultTenant
(
String
phone
)
{
// LoginUser loginUser = LoginHelper.getLoginUser();
// Assert.notNull(loginUser,"用户信息不存在!");
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phone
;
String
defaultTenant
=
RedisUtils
.
getCacheObject
(
defaultTenantKey
);
return
R
.
ok
(
MapUtil
.
of
(
"tenantId"
,
defaultTenant
));
}
/**
* 邮件登录
*
* @param body 登录信息
* @return 结果
*/
@PostMapping
(
"/emailLogin"
)
public
R
<
Map
<
String
,
Object
>>
emailLogin
(
@Validated
@RequestBody
EmailLoginBody
body
)
{
Map
<
String
,
Object
>
ajax
=
new
HashMap
<>();
// 生成令牌
String
token
=
loginService
.
emailLogin
(
body
.
getEmail
(),
body
.
getEmailCode
());
ajax
.
put
(
Constants
.
TOKEN
,
token
);
return
R
.
ok
(
ajax
);
}
/**
* 小程序登录(示例)
*
* @param xcxCode 小程序code
* @return 结果
*/
@SaIgnore
@PostMapping
(
"/xcxLogin"
)
public
R
<
Map
<
String
,
Object
>>
xcxLogin
(
@NotBlank
(
message
=
"{xcx.code.not.blank}"
)
String
xcxCode
)
{
Map
<
String
,
Object
>
ajax
=
new
HashMap
<>();
// 生成令牌
String
token
=
loginService
.
xcxLogin
(
xcxCode
);
ajax
.
put
(
Constants
.
TOKEN
,
token
);
return
R
.
ok
(
ajax
);
}
/**
* 退出登录
*/
@SaIgnore
@PostMapping
(
"/logout"
)
public
R
<
Void
>
logout
()
{
loginService
.
logout
();
return
R
.
ok
(
"退出成功"
);
}
/**
* 获取用户信息
*
* @return 用户信息
*/
@GetMapping
(
"getInfo"
)
public
R
<
Map
<
String
,
Object
>>
getInfo
(
HttpServletRequest
request
)
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
//校验当前发请求的IP与登录账号的IP是否相同
// String loginUserIpaddr = loginUser.getIpaddr();
// if (StringUtils.isNotBlank(loginUserIpaddr) && !Objects.equals(IpUtil.getIpAddr(request), loginUserIpaddr)) {
// throw new ServiceException("该账号已在其他地方登录,请求失败!", 401);
// }
SysUser
user
=
userService
.
selectUserById
(
loginUser
.
getUserId
());
Map
<
String
,
Object
>
ajax
=
new
HashMap
<>();
ajax
.
put
(
"user"
,
user
);
ajax
.
put
(
"roles"
,
loginUser
.
getRolePermission
());
ajax
.
put
(
"permissions"
,
loginUser
.
getMenuPermission
());
ajax
.
put
(
"isThirdPlatformLogin"
,
LoginHelper
.
getLoginUser
().
getIsThirdPlatformLogin
());
return
R
.
ok
(
ajax
);
}
/**
* 获取路由信息
*
* @return 路由信息
*/
@GetMapping
(
"getRouters"
)
public
R
<
List
<
RouterVo
>>
getRouters
()
{
Long
userId
=
LoginHelper
.
getUserId
();
List
<
SysMenu
>
menus
=
menuService
.
selectMenuTreeByUserId
(
userId
);
return
R
.
ok
(
menuService
.
buildMenus
(
menus
));
}
}
dsk-admin/src/main/resources/application-prod.yml
View file @
077f62f4
...
...
@@ -52,9 +52,16 @@ spring:
# url: jdbc:mysql://192.168.0.79:3306/dsk_operate_sys?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: dev
# password: 8AXjjCHZ666!
url
:
jdbc:mysql://rds-szh.dsk.com/dos?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username
:
dsk_api_szh
password
:
j1nxbVPF0QS*B57C
# url: jdbc:mysql://rds-szh.dsk.com/dos?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: dsk_api_szh
# password: j1nxbVPF0QS*B57C
# 二十局线上数据库
url
:
jdbc:mysql://123.60.218.188:3306/dsk_operate_online?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username
:
dev
password
:
encPHwi8dbKeL!6X
# 从库数据源
# slave:
# lazy: true
...
...
@@ -104,13 +111,29 @@ spring:
---
# redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring
:
redis
:
host
:
redis-szh.dsk.com
# host: redis-szh.dsk.com
# # 端口,默认为6379
# port: 6379
# # 数据库索引
# database: 13
# # 密码
# password: Xi8$r*@d7zn5FaP2
# # 密码(如没有密码请注释掉)
# # password:
# # 连接超时时间
# timeout: 10s
# # 是否开启ssl
# ssl: false
# 二十局redis测试链接
host
:
123.60.218.188
# 端口,默认为6379
port
:
6379
# 数据库索引
database
:
13
# 密码
password
:
Xi8$r*@d7zn5FaP2
password
:
zfTFIJjaN#6xB64r
# 密码(如没有密码请注释掉)
# password:
# 连接超时时间
...
...
@@ -190,4 +213,4 @@ sms:
territory
:
ap-guangzhou
dsk
:
exportBackUrl
:
https://szhapi.jiansheku.com/export/backUrl
\ No newline at end of file
exportBackUrl
:
https://szhapi.jiansheku.com/export/backUrl
dsk-admin/src/main/resources/application-test.yml
View file @
077f62f4
...
...
@@ -49,9 +49,16 @@ spring:
driverClassName
:
com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url
:
jdbc:mysql://120.46.64.239:3306/dsk_operate?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username
:
dskdev
password
:
encPHwi8dbKeL8ZX
# url: jdbc:mysql://120.46.64.239:3306/dsk_operate?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: dskdev
# password: encPHwi8dbKeL8ZX
# 二十局数据库配置
url
:
jdbc:mysql://123.60.218.188:3306/dsk_operate?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username
:
dev
password
:
encPHwi8dbKeL!6X
# 从库数据源
# slave:
# lazy: true
...
...
@@ -101,13 +108,28 @@ spring:
---
# redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring
:
redis
:
host
:
120.46.64.239
# host: 120.46.64.239
# # 端口,默认为6379
# port: 6379
# # 数据库索引
# database: 13
# # 密码
# password: zfTFIJjaN#6xB83r
# # 密码(如没有密码请注释掉)
# # password:
# # 连接超时时间
# timeout: 10s
# # 是否开启ssl
# ssl: false
# 二十局redis测试链接
host
:
123.60.218.188
# 端口,默认为6379
port
:
6379
# 数据库索引
database
:
1
3
database
:
1
4
# 密码
password
:
zfTFIJjaN#6xB
83
r
password
:
zfTFIJjaN#6xB
64
r
# 密码(如没有密码请注释掉)
# password:
# 连接超时时间
...
...
@@ -115,6 +137,9 @@ spring:
# 是否开启ssl
ssl
:
false
redisson
:
# redis key前缀
keyPrefix
:
...
...
@@ -193,4 +218,4 @@ sa-token:
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent
:
true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share
:
true
\ No newline at end of file
is-share
:
true
dsk-admin/src/main/resources/application.yml
View file @
077f62f4
...
...
@@ -29,7 +29,9 @@ captcha:
# 开发环境配置
server
:
# 服务器的HTTP端口,默认为8080
port
:
9098
# port: 9098
# 二十局线上端口9097
port
:
9097
servlet
:
# 应用的访问路径
context-path
:
/
...
...
@@ -142,12 +144,14 @@ security:
# actuator 监控配置
-
/api/**
-
/actuator/**
# - /**
# 多租户配置
tenant
:
# 是否开启
enable
:
true
# enable: false
# 排除表
excludes
:
-
sys_menu
...
...
dsk-common/src/main/java/com/dsk/common/core/domain/model/LoginUser.java
View file @
077f62f4
...
...
@@ -113,6 +113,11 @@ public class LoginUser implements Serializable {
*/
private
Long
roleId
;
/**
* 是否三方登录
*/
private
Boolean
isThirdPlatformLogin
;
/**
* 获取登录id
*/
...
...
dsk-common/src/main/java/com/dsk/common/core/domain/model/ThirdPlatformLoginBody.java
0 → 100644
View file @
077f62f4
package
com
.
dsk
.
common
.
core
.
domain
.
model
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
/**
* 三方平台用户登录对象
*
* @author sxk
*/
@Data
public
class
ThirdPlatformLoginBody
{
/**
* 三方平台跳转本系统所需秘钥
*/
@NotBlank
(
message
=
"桑芳平台登录秘钥不能为空"
)
private
String
thirdPlatformKey
;
}
dsk-module/dsk-biz-api/src/main/java/com/dsk/jsk/controller/IndexController.java
View file @
077f62f4
...
...
@@ -43,4 +43,283 @@ public class IndexController {
public
AjaxResult
bidRank
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
bidRank
(
object
);
}
/**
*
*
* 总金额、总面积统计--刘杰那边的接口
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/statisticsOfAmountAndArea"
)
public
AjaxResult
statisticsOfAmountAndArea
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
statisticsOfAmountAndArea
(
object
);
}
/**
*
*
* 基础维度统计--刘杰那边的接口
* /nationzj/landMarket/commonStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/jcwdtj"
)
public
AjaxResult
jcwdtj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
jcwdtj
(
object
);
}
/**
*
*
* 前十企业统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/topten"
)
public
AjaxResult
topten
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
topten
(
object
);
}
/**
*
*
* 商机-拟建查询-总金额统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/njzjetj"
)
public
AjaxResult
njzjetj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
njzjetj
(
object
);
}
/**
*
*
* 商机-拟建查询-基础维度统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/njjcwdtj"
)
public
AjaxResult
njjcwdtj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
njjcwdtj
(
object
);
}
/**
*
*
* 商机-拟建查询-前十企业统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/njtopten"
)
public
AjaxResult
njtopten
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
njtopten
(
object
);
}
/**
*
*
* 商机-招标公告-总金额统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zbggzjetj"
)
public
AjaxResult
zbggzjetj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zbggzjetj
(
object
);
}
/**
*
*
* 商机-招标公告-基础维度统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zbggjcwdtj"
)
public
AjaxResult
zbggjcwdtj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zbggjcwdtj
(
object
);
}
/**
*
*
* 商机-招标公告-前十企业统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zbggtopten"
)
public
AjaxResult
zbggtopten
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zbggtopten
(
object
);
}
/**
*
*
* 招标计划查询-总金额统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zbjhcxzjetj"
)
public
AjaxResult
zbjhcxzjetj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zbjhcxzjetj
(
object
);
}
/**
*
*
* 招标计划查询-基础维度统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zbjhcxjcwdtj"
)
public
AjaxResult
zbjhcxjcwdtj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zbjhcxjcwdtj
(
object
);
}
/**
*
*
* 招标计划查询-前十企业统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zbjhcxtopten"
)
public
AjaxResult
zbjhcxtopten
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zbjhcxtopten
(
object
);
}
/**
*
*
* 重点项目清单查询-总金额统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zdxmqdzjetj"
)
public
AjaxResult
zdxmqdzjetj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zdxmqdzjetj
(
object
);
}
/**
*
*
* 重点项目清单查询-基础统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zdxmqdjctj"
)
public
AjaxResult
zdxmqdjctj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zdxmqdjctj
(
object
);
}
/**
*
*
* 重点项目清单查询-前十企业--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zdxmqdtopten"
)
public
AjaxResult
zdxmqdtopten
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zdxmqdtopten
(
object
);
}
/**
*
*
* 专项债项目-总金额统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zxzxmzjetj"
)
public
AjaxResult
zxzxmzjetj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zxzxmzjetj
(
object
);
}
/**
*
*
* 专项债项目-基础统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zxzxmjctj"
)
public
AjaxResult
zxzxmjctj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zxzxmjctj
(
object
);
}
/**
*
*
* 专项债项目查询-企业统计--刘杰那边的接口
* /nationzj/landMarket/companyStatis
* @param object
* @return {@link AjaxResult }
* @throws Exception
*/
@PostMapping
(
value
=
"/zxzxmqytj"
)
public
AjaxResult
zxzxmqytj
(
@RequestBody
JSONObject
object
)
{
return
enterpriseService
.
zxzxmqytj
(
object
);
}
}
dsk-module/dsk-biz-api/src/main/java/com/dsk/jsk/service/IndexService.java
View file @
077f62f4
...
...
@@ -33,6 +33,278 @@ public class IndexService {
@Autowired
private
DskOpenApiUtil
dskOpenApiUtil
;
public
AjaxResult
zxzxmqytj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/bondProject/companyStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zxzxmjctj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/bondProject/commonStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zxzxmzjetj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/bondProject/sumStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zdxmqdtopten
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/bondProject/importantCompanyStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zdxmqdjctj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/bondProject/importantCommonStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zdxmqdzjetj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/bondProject/importantSumStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zbjhcxtopten
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/jskBidPlan/companyStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zbjhcxjcwdtj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/jskBidPlan/commonStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zbjhcxzjetj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/jskBidPlan/sumStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zbggtopten
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/jskBid/companyStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zbggjcwdtj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/jskBid/commonStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
zbggzjetj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/jskBid/sumStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
njtopten
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/establishment/companyStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
njjcwdtj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/establishment/commonStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
njzjetj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/establishment/sumStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
topten
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/landMarket/companyStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
jcwdtj
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/landMarket/commonStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
statisticsOfAmountAndArea
(
JSONObject
object
)
{
JSONObject
page
=
object
.
getJSONObject
(
"page"
);
if
(
ObjectUtil
.
isEmpty
(
page
)){
return
AjaxResult
.
error
(
"page对象不能为空"
);
}
Integer
pageIndex
=
page
.
getInt
(
"page"
),
pageSize
=
page
.
getInt
(
"limit"
);
if
(
ObjectUtil
.
isEmpty
(
pageIndex
)
||
ObjectUtil
.
isEmpty
(
pageSize
)){
return
AjaxResult
.
error
(
"page、limit都不能为空"
);
}
Map
<
String
,
Object
>
map
=
dskOpenApiUtil
.
requestBody
(
"/nationzj/landMarket/sumStatis"
,
object
);
return
BeanUtil
.
toBean
(
map
,
AjaxResult
.
class
);
}
public
AjaxResult
bigWinningBidsPage
(
JSONObject
object
)
{
JSONArray
recentlyBidQueryDtoList
=
object
.
getJSONArray
(
"recentlyBidQueryDto"
);
Map
<
String
,
Object
>
objectMap
=
new
HashMap
<>();
...
...
dsk-operate-ui/package.json
View file @
077f62f4
...
...
@@ -6,6 +6,7 @@
"license"
:
"MIT"
,
"scripts"
:
{
"dev"
:
"vue-cli-service serve"
,
"devmac"
:
"export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve"
,
"build:prod"
:
"vue-cli-service build"
,
"build:test"
:
"vue-cli-service build --mode test"
,
"build:stage"
:
"vue-cli-service build --mode staging"
,
...
...
dsk-operate-ui/src/api/login.js
View file @
077f62f4
import
request
from
'@/utils/request'
import
request
from
'@/utils/request'
;
// 登录方法
export
function
login
(
username
,
password
,
code
,
uuid
)
{
...
...
@@ -7,7 +7,7 @@ export function login(username, password, code, uuid) {
password
,
code
,
uuid
}
}
;
return
request
({
url
:
'/login'
,
headers
:
{
...
...
@@ -15,7 +15,7 @@ export function login(username, password, code, uuid) {
},
method
:
'post'
,
data
:
data
})
})
;
}
// 注册方法
...
...
@@ -27,7 +27,7 @@ export function register(data) {
},
method
:
'post'
,
data
:
data
})
})
;
}
// 获取用户详细信息
...
...
@@ -35,7 +35,7 @@ export function getInfo() {
return
request
({
url
:
'/getInfo'
,
method
:
'get'
})
})
;
}
// 退出方法
...
...
@@ -43,7 +43,7 @@ export function logout() {
return
request
({
url
:
'/logout'
,
method
:
'post'
})
})
;
}
// 获取验证码
...
...
@@ -55,7 +55,7 @@ export function getCodeImg() {
},
method
:
'get'
,
timeout
:
20000
})
})
;
}
//获取租户企业列表
...
...
@@ -63,7 +63,7 @@ export function getTenants() {
return
request
({
url
:
'/user/tenants'
,
method
:
'post'
,
})
})
;
}
// 获取默认租户
...
...
@@ -71,15 +71,15 @@ export function defaultTenantid() {
return
request
({
url
:
'/user/default/tenant'
,
method
:
'post'
,
})
})
;
}
// 切换租户
export
function
changeTenants
(
data
)
{
return
request
({
url
:
'/switch/tenant?tenantId='
+
data
,
url
:
'/switch/tenant?tenantId='
+
data
,
method
:
'post'
,
})
})
;
}
//发送短信验证码(删除组织使用)
...
...
@@ -87,7 +87,7 @@ export function captchaSms() {
return
request
({
url
:
'/getTempSmsCode'
,
method
:
'get'
,
})
})
;
}
//验证短信验证码(删除组织使用)
...
...
@@ -95,8 +95,8 @@ export function checkSmsCode(data) {
return
request
({
url
:
'/checkSmsCode'
,
method
:
'POST'
,
params
:
data
})
params
:
data
})
;
}
//根据用户账号获取用户绑定的租户列表
...
...
@@ -104,8 +104,8 @@ export function userTenantList(data) {
return
request
({
url
:
'/user/tenant/list'
,
method
:
'POST'
,
params
:
data
})
params
:
data
})
;
}
//登录获取验证码
...
...
@@ -113,17 +113,29 @@ export function logincaptchaSms(data) {
return
request
({
url
:
'/captchaSms'
,
method
:
'get'
,
params
:
data
})
params
:
data
})
;
}
//短信登录
export
function
smsLogin
(
data
)
{
return
request
({
url
:
'/smsLogin'
,
method
:
'post'
,
data
:
data
})
data
:
data
})
;
}
/**
* 第三方植入系统
* @param {string} thirdPlatformKey
* @returns
*/
export
const
thirdPlatformLoginApi
=
(
thirdPlatformKey
)
=>
request
({
method
:
"post"
,
url
:
"/thirdPlatformLogin"
,
data
:
{
thirdPlatformKey
}
})
dsk-operate-ui/src/layout/components/Navbar.vue
View file @
077f62f4
...
...
@@ -4,7 +4,7 @@
<div
class=
"left-menu"
:style=
"
{width: scrollerWidth}">
<tags-view
/>
</div>
<div
ref=
"rightMenu"
class=
"flex-box right-menu"
>
<div
ref=
"rightMenu"
class=
"flex-box right-menu"
v-if=
"!isThirdPlatformLogin"
>
<!--
<div
class=
"menu-bells"
><img
src=
"@/assets/images/message.png"
><i
/></div>
-->
<!--
<i
class=
"menu-line"
/>
-->
<el-dropdown
class=
"avatar-container"
trigger=
"hover"
ref=
"mydrodown"
:hide-on-click=
"false"
placement=
"bottom-start"
>
...
...
@@ -40,7 +40,7 @@
<
script
>
import
store
from
"@/store"
;
import
{
mapGetters
}
from
'vuex'
import
{
mapGetters
,
mapState
}
from
'vuex'
import
elementResizeDetectorMaker
from
"element-resize-detector"
import
TagsView
from
'./TagsView'
import
{
getTenants
,
changeTenants
}
from
"@/api/login"
;
...
...
@@ -63,7 +63,10 @@ export default {
'sidebar'
,
'avatar'
,
'name'
])
]),
...
mapState
({
isThirdPlatformLogin
:
state
=>
state
.
user
.
isThirdPlatformLogin
})
},
watch
:
{
offsetWidth
(
newValue
,
oldValue
){
...
...
dsk-operate-ui/src/layout/components/Sidebar/index.vue
View file @
077f62f4
...
...
@@ -4,7 +4,7 @@
<logo
v-if=
"showLogo"
:collapse=
"isCollapse"
/>
<el-scrollbar
:class=
"settings.sideTheme"
wrap-class=
"scrollbar-wrapper"
>
<el-menu
:default-active=
"activeMenu"
:collapse=
"isCollapse"
:background-color=
"variables.menuBg"
:text-color=
"variables.menuText"
:unique-opened=
"true"
:active-text-color=
"settings.theme"
:collapse-transition=
"false"
mode=
"vertical"
>
:unique-opened=
"true"
:active-text-color=
"settings.theme"
:collapse-transition=
"false"
mode=
"vertical"
class=
"left-top-level-menu"
>
<sidebar-item
v-for=
"(route, index) in hidechildren"
:key=
"route.path + index"
:is-collapse=
"isCollapse"
:active-menu=
"activeMenu"
:item=
"route"
:base-path=
"route.path"
:class=
"route.fixed&&route.fixed.isFixed?'sideFoot':''"
:style=
"route.fixed&&route.fixed.isFixed?
{'bottom': route.fixed.number*50+'px'}: bottomMenu
&&
index==routes.length-bottomMenu-2?{'padding-bottom': bottomMenu*50+'px'}:''" />
...
...
@@ -91,3 +91,10 @@ export default {
},
};
</
script
>
<
style
lang=
"scss"
scoped
>
.left-top-level-menu
{
padding
:
20px
0px
;
box-sizing
:
border-box
;
}
</
style
>
dsk-operate-ui/src/permission.js
View file @
077f62f4
...
...
@@ -3,14 +3,17 @@ import store from './store';
import
{
Message
}
from
'element-ui'
;
import
NProgress
from
'nprogress'
;
import
'nprogress/nprogress.css'
;
import
{
getToken
}
from
'@/utils/auth'
;
import
{
getToken
,
getThirdPlatform
}
from
'@/utils/auth'
;
import
{
isRelogin
}
from
'@/utils/request'
;
NProgress
.
configure
({
showSpinner
:
false
});
const
whiteList
=
[
'/login'
,
'/register'
];
const
whiteList
=
[
'/login'
,
"/404"
,
"/401"
];
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
// 默认跳转路径 本系统跳转首页,第三方跳转宏观市场
const
platFormKey
=
getThirdPlatform
();
let
defaultRedirectPath
=
platFormKey
?
"/macro/nationalEconomies"
:
"/"
;
NProgress
.
start
();
if
(
getToken
())
{
// tab页签title
...
...
@@ -20,10 +23,10 @@ router.beforeEach((to, from, next) => {
to
.
meta
.
title
&&
store
.
dispatch
(
'settings/setTitle'
,
to
.
meta
.
title
);
/* has token*/
if
(
to
.
path
===
'/login'
)
{
next
({
path
:
'/'
});
next
({
path
:
defaultRedirectPath
});
NProgress
.
done
();
}
else
{
if
(
store
.
getters
.
roles
.
length
===
0
)
{
if
(
!
store
.
state
?.
user
?.
userId
&&
!
store
.
state
?.
user
?.
roles
?.
length
)
{
isRelogin
.
show
=
true
;
// 判断当前用户是否已拉取完user_info信息
store
.
dispatch
(
'GetInfo'
).
then
(()
=>
{
...
...
@@ -34,24 +37,52 @@ router.beforeEach((to, from, next) => {
next
({
...
to
,
replace
:
true
});
// hack方法 确保addRoutes已完成
});
}).
catch
(
err
=>
{
store
.
dispatch
(
'LogOut'
).
then
(()
=>
{
Message
.
error
(
err
);
sessionStorage
.
removeItem
(
'views'
);
next
({
path
:
'/'
});
});
if
(
platFormKey
)
{
store
.
dispatch
(
'FedLogOut'
).
then
(()
=>
{
next
({
path
:
"/401"
,
query
:
{
isSecretFreeLogin
:
true
}
});
});
}
else
{
store
.
dispatch
(
'LogOut'
).
then
(()
=>
{
Message
.
error
(
err
);
sessionStorage
.
removeItem
(
'views'
);
next
({
path
:
'/'
});
});
}
});
}
else
{
next
();
}
}
}
else
{
// 没有token
if
(
whiteList
.
indexOf
(
to
.
path
)
!==
-
1
)
{
// 在免登录白名单,直接进入
next
();
}
else
{
next
(
`/login?redirect=
${
to
.
fullPath
}
`
);
// 否则全部重定向到登录页
NProgress
.
done
();
// 非白名单 没有token 判断是否有app key 属于第三方平台
// 第三方平台 获取到 platFormKey 直接通过key 登录
if
(
platFormKey
)
{
store
.
dispatch
(
"secretFreeLogin"
,
platFormKey
).
then
((
res
)
=>
{
next
({
path
:
defaultRedirectPath
});
}).
catch
(
err
=>
{
// appkey 登陆失败 跳转到401
next
({
path
:
"/401"
,
query
:
{
isSecretFreeLogin
:
true
}
});
});
}
else
{
next
(
`/login?redirect=
${
to
.
fullPath
}
`
);
// 否则全部重定向到登录页
NProgress
.
done
();
}
}
}
});
...
...
dsk-operate-ui/src/router/index.js
View file @
077f62f4
...
...
@@ -47,11 +47,11 @@ export const constantRoutes = [
component
:
()
=>
import
(
'@/views/login'
),
hidden
:
true
},
{
path
:
'/register'
,
component
:
()
=>
import
(
'@/views/register'
),
hidden
:
true
},
//
{
//
path: '/register',
//
component: () => import('@/views/register'),
//
hidden: true
//
},
{
path
:
'/404'
,
component
:
()
=>
import
(
'@/views/error/404'
),
...
...
@@ -62,33 +62,20 @@ export const constantRoutes = [
component
:
()
=>
import
(
'@/views/error/401'
),
hidden
:
true
},
{
path
:
''
,
component
:
Layout
,
redirect
:
'index'
,
children
:
[
{
path
:
'index'
,
component
:
()
=>
import
(
'@/views/index'
),
name
:
'Index'
,
meta
:
{
title
:
'首页'
,
icon
:
'index'
,
noCache
:
true
}
}
]
},
{
path
:
''
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'urban'
,
children
:
[
{
path
:
'/macro/urban'
,
component
:
()
=>
import
(
'@/views/macro/urban'
),
name
:
'Urban'
,
meta
:
{
title
:
'城投平台'
,
icon
:
'macro'
}
}
]
},
// {
// path: '/macro',
// component: Layout,
// hidden: true,
// // redirect: 'urban',
// children: [
// {
// path: 'urban',
// component: () => import('@/views/macro/urban'),
// name: 'Urban',
// meta: { title: '城投平台', icon: 'macro' }
// }
// ]
// },
// {
// path: '',
// component: Layout,
...
...
@@ -103,20 +90,6 @@ export const constantRoutes = [
// }
// ]
// },
{
path
:
''
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'urban'
,
children
:
[
{
path
:
'/macro/urban'
,
component
:
()
=>
import
(
'@/views/macro/urban'
),
name
:
'Urban'
,
meta
:
{
title
:
'城投平台'
,
icon
:
'macro'
}
}
]
},
{
path
:
'/user'
,
component
:
Layout
,
...
...
@@ -127,7 +100,7 @@ export const constantRoutes = [
path
:
'profile'
,
component
:
()
=>
import
(
'@/views/system/user/profile/index'
),
name
:
'Profile'
,
meta
:
{
title
:
'个人中心'
,
icon
:
'user'
,
noCache
:
true
}
meta
:
{
title
:
'个人中心'
,
icon
:
'user'
,
noCache
:
true
}
}
]
},
...
...
@@ -161,26 +134,26 @@ export const constantRoutes = [
]
},
{
path
:
''
,
path
:
'
/JumpPage.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
'
/JumpPage.html
'
,
children
:
[
{
path
:
'
/JumpPage.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//乙方-企业详情
{
path
:
'/company'
,
path
:
'/company
/:id
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
name
:
'Company'
,
meta
:
{
title
:
'企业详情'
}
...
...
@@ -189,104 +162,104 @@ export const constantRoutes = [
},
//企业详情-业绩
{
path
:
''
,
path
:
'
/company/:id/performance
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id/performance
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//企业详情-人员
{
path
:
''
,
path
:
'
/company/:id/personnel
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id/personnel
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//企业详情-经营信息
{
path
:
''
,
path
:
'
/company/:id/business
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id/business
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//企业详情-良好行为
{
path
:
''
,
path
:
'
/company/:id/behavior
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id/behavior
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//企业详情-信用评价
{
path
:
''
,
path
:
'
/company/:id/evaluation
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id/evaluation
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//企业详情-信用行为
{
path
:
''
,
path
:
'
/company/:id/credit
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id/credit
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//企业详情-股权
{
path
:
''
,
path
:
'
/company/:id/lt
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/company/:id/lt
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//人员详情
{
path
:
'/personnel'
,
path
:
'/personnel
/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/personnel/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
name
:
'Personnel'
,
meta
:
{
title
:
'人员详情'
}
...
...
@@ -309,13 +282,13 @@ export const constantRoutes = [
},
//公招市场详情
{
path
:
'/gzsc'
,
path
:
'/gzsc
/:id
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/gzsc/:id
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
name
:
'detail-gzsc'
,
meta
:
{
title
:
"公招市场详情"
}
...
...
@@ -324,221 +297,221 @@ export const constantRoutes = [
},
//中标业绩详情
{
path
:
''
,
path
:
'
/performance/zb/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/zb/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//荣誉详情
{
path
:
''
,
path
:
'
/honor/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/honor/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//标讯Pro-招标公告
{
path
:
''
,
path
:
'
/bxpro/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/bxpro/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//中标候选人
{
path
:
''
,
path
:
'
/zbpro/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/zbpro/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//开标记录
{
path
:
''
,
path
:
'
/biz/tbjl/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/biz/tbjl/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//一体化详情
{
path
:
''
,
path
:
'
/performance/sjyth/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/sjyth/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//一体化详情
{
path
:
''
,
path
:
'
/performance/yth/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/yth/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//四库详情
{
path
:
''
,
path
:
'
/performance/sky/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/sky/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//公路系统详情
{
path
:
''
,
path
:
'
/performance/glxt/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/glxt/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//公路系统详情
{
path
:
''
,
path
:
'
/performance/xmzt/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/xmzt/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//水利详情
{
path
:
''
,
path
:
'
/performance/slyj/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/slyj/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//江西住建云详情
{
path
:
''
,
path
:
'
/performance/jxzjy/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/jxzjy/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//北京业绩详情
{
path
:
''
,
path
:
'
/performance/bj/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/bj/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//云南业绩详情
{
path
:
''
,
path
:
'
/performance/yn/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/performance/yn/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//商机-标讯详情
{
path
:
''
,
path
:
'
/biz/bx/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/biz/bx/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//商机-土地交易详情
{
path
:
''
,
path
:
'
/biz/tdjy/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/biz/tdjy/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
},
//商机-拟建项目详情
{
path
:
''
,
path
:
'
/biz/njxm/:id.html
'
,
component
:
Layout
,
hidden
:
true
,
redirect
:
'
noredirect
'
,
redirect
:
''
,
children
:
[
{
path
:
'
/biz/njxm/:id.html
'
,
path
:
''
,
component
:
()
=>
import
(
'@/views/detail'
),
}
]
...
...
@@ -815,6 +788,31 @@ export const dynamicRoutes = [
}
];
/**
* 第三方登录首页
*/
export
const
isThirdPlatformRoutes
=
[
{
path
:
''
,
component
:
Layout
,
redirect
:
'index'
,
children
:
[
{
path
:
'index'
,
component
:
()
=>
import
(
'@/views/index'
),
name
:
'Index'
,
meta
:
{
title
:
'首页'
,
icon
:
'index'
,
noCache
:
true
}
}
]
},
{
path
:
''
,
component
:
Layout
,
redirect
:
'/macro/nationalEconomies'
,
hidden
:
true
}
];
// 防止连续点击多次路由报错
let
routerPush
=
Router
.
prototype
.
push
;
let
routerReplace
=
Router
.
prototype
.
replace
;
...
...
dsk-operate-ui/src/store/modules/permission.js
View file @
077f62f4
import
auth
from
'@/plugins/auth'
;
import
router
,
{
constantRoutes
,
dynamicRoutes
}
from
'@/router'
;
import
router
,
{
constantRoutes
,
dynamicRoutes
,
isThirdPlatformRoutes
}
from
'@/router'
;
import
{
getRouters
}
from
'@/api/menu'
;
import
Layout
from
'@/layout/index'
;
import
ParentView
from
'@/components/ParentView'
;
...
...
@@ -19,7 +19,7 @@ const permission = {
state
.
routes
=
constantRoutes
.
concat
(
routes
);
},
SET_DEFAULT_ROUTES
:
(
state
,
routes
)
=>
{
state
.
defaultRoutes
=
constantRoutes
.
concat
(
routes
)
;
state
.
defaultRoutes
=
routes
;
},
SET_TOPBAR_ROUTES
:
(
state
,
routes
)
=>
{
state
.
topbarRouters
=
routes
;
...
...
@@ -30,21 +30,24 @@ const permission = {
},
actions
:
{
// 生成路由
GenerateRoutes
({
commit
})
{
GenerateRoutes
({
commit
,
rootState
})
{
return
new
Promise
(
resolve
=>
{
// 向后端请求路由数据
getRouters
().
then
(
res
=>
{
const
isThirdPlatformLogin
=
rootState
.
user
.
isThirdPlatformLogin
;
let
_array
=
isThirdPlatformLogin
?
[
isThirdPlatformRoutes
[
1
]]
:
[
isThirdPlatformRoutes
[
0
]];
const
sdata
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
));
const
rdata
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
));
const
sidebarRoutes
=
filterAsyncRouter
(
sdata
);
const
rewriteRoutes
=
filterAsyncRouter
(
rdata
,
false
,
true
);
const
asyncRoutes
=
filterDynamicRoutes
(
dynamicRoutes
);
rewriteRoutes
.
unshift
(...
_array
);
rewriteRoutes
.
push
({
path
:
'*'
,
redirect
:
'/404'
,
hidden
:
true
});
router
.
addRoutes
(
asyncRoutes
);
commit
(
'SET_ROUTES'
,
rewriteRoutes
);
commit
(
'SET_SIDEBAR_ROUTERS'
,
constantRoutes
.
concat
(
sidebarRoutes
));
commit
(
'SET_DEFAULT_ROUTES'
,
sidebarRoutes
);
commit
(
'SET_TOPBAR_ROUTES'
,
sidebarRoutes
);
commit
(
'SET_SIDEBAR_ROUTERS'
,
constantRoutes
.
concat
(
_array
).
concat
(
sidebarRoutes
));
commit
(
'SET_DEFAULT_ROUTES'
,
constantRoutes
.
concat
(
_array
).
concat
(
sidebarRoutes
)
);
commit
(
'SET_TOPBAR_ROUTES'
,
constantRoutes
.
concat
(
_array
).
concat
(
sidebarRoutes
)
);
resolve
(
rewriteRoutes
);
});
});
...
...
dsk-operate-ui/src/store/modules/user.js
View file @
077f62f4
import
{
login
,
logout
,
getInfo
}
from
'@/api/login'
;
import
{
getToken
,
setToken
,
removeToken
,
setTenantid
}
from
'@/utils/auth'
;
import
{
login
,
logout
,
getInfo
,
thirdPlatformLoginApi
}
from
'@/api/login'
;
import
{
getToken
,
setToken
,
removeToken
,
setTenantid
,
removeThirdPlatform
}
from
'@/utils/auth'
;
const
user
=
{
state
:
{
...
...
@@ -10,6 +10,7 @@ const user = {
permissions
:
[],
userId
:
''
,
phonenumber
:
''
,
isThirdPlatformLogin
:
false
},
mutations
:
{
...
...
@@ -33,6 +34,9 @@ const user = {
},
SET_USERPHONE
:
(
state
,
phonenumber
)
=>
{
state
.
phonenumber
=
phonenumber
;
},
SET_IS_THIRD_PLATFORM
:
(
state
,
isThirdPlatformLogin
)
=>
{
state
.
isThirdPlatformLogin
=
isThirdPlatformLogin
?
true
:
false
;
}
},
...
...
@@ -71,6 +75,7 @@ const user = {
commit
(
'SET_AVATAR'
,
avatar
);
commit
(
'SET_USERID'
,
user
.
userId
);
commit
(
'SET_USERPHONE'
,
user
.
phonenumber
);
commit
(
"SET_IS_THIRD_PLATFORM"
,
res
.
data
.
isThirdPlatformLogin
);
resolve
(
res
);
}).
catch
(
error
=>
{
reject
(
error
);
...
...
@@ -97,10 +102,33 @@ const user = {
FedLogOut
({
commit
})
{
return
new
Promise
(
resolve
=>
{
commit
(
'SET_TOKEN'
,
''
);
commit
(
'SET_USERID'
,
""
);
commit
(
'SET_ROLES'
,
[]);
removeToken
();
resolve
();
});
},
// 免密登录 通过appkey登录
async
secretFreeLogin
({
commit
,
state
},
payload
)
{
try
{
if
(
!
payload
)
throw
new
Error
(
"缺少platFormKey"
);
const
tokenInfo
=
await
thirdPlatformLoginApi
(
payload
);
console
.
log
(
tokenInfo
);
if
(
tokenInfo
.
code
==
200
)
{
setToken
(
tokenInfo
.
data
.
token
);
commit
(
'SET_TOKEN'
,
tokenInfo
.
data
.
token
);
setTenantid
(
tokenInfo
.
data
.
tenantId
);
return
true
;
}
else
{
throw
new
Error
(
"appkey登录失败"
);
}
}
catch
(
error
)
{
throw
error
;
}
}
}
};
...
...
dsk-operate-ui/src/utils/auth.js
View file @
077f62f4
import
Cookies
from
'js-cookie'
;
import
{
getUrlSearchQuery
}
from
'@/utils'
;
const
TokenKey
=
'Admin-Token'
;
const
Tenantid
=
'Tenantid'
;
...
...
@@ -30,3 +31,41 @@ export function setBiAuth(token) {
sessionStorage
.
setItem
(
"DSK_SYSTEM_AUTH_TOKEN"
,
token
);
return
true
;
}
/**
* 获取第三方app key
* @returns
*/
export
function
getThirdPlatform
()
{
const
platForm
=
sessionStorage
.
getItem
(
"PLAT_FORM"
);
if
(
platForm
)
return
platForm
;
// sessiongStorage 未获取到appkey 寻找url上的参数
const
{
platFormKey
}
=
getUrlSearchQuery
();
if
(
platFormKey
)
{
return
setThirdPlatform
(
platFormKey
)
?
platFormKey
:
""
;
}
else
{
return
""
;
};
}
/**
* 储存第三方app key
* @param {*} appkey
* @returns
*/
export
function
setThirdPlatform
(
appkey
)
{
try
{
if
(
!
appkey
)
throw
new
Error
(
""
);
sessionStorage
.
setItem
(
"PLAT_FORM"
,
appkey
);
return
true
;
}
catch
(
error
)
{
return
false
;
}
}
/**
* 移除第三方app key
*/
export
function
removeThirdPlatform
()
{
sessionStorage
.
removeItem
(
"PLAT_FORM"
);
}
dsk-operate-ui/src/views/error/401.vue
View file @
077f62f4
<
template
>
<div
class=
"errPage-container"
>
<el-button
icon=
"arrow-left"
class=
"pan-back-btn"
@
click=
"
back
"
>
返回
<el-button
icon=
"arrow-left"
class=
"pan-back-btn"
@
click=
"
isSecretFreeLogin === false ? back() : aginLogin()
"
>
{{
isSecretFreeLogin
===
false
?
"返回"
:
"重新登录"
}}
</el-button>
<el-row>
<el-col
:span=
"12"
>
...
...
@@ -9,8 +9,8 @@
401错误!
</h1>
<h2>
您没有访问权限!
</h2>
<h6>
对不起,您没有访问权限,请不要进行非法操作!
您可以返回主页面
</h6>
<ul
class=
"list-unstyled"
>
<h6>
对不起,您没有访问权限,请不要进行非法操作!
{{
isSecretFreeLogin
===
true
?
"您可以尝试使用appkey重新登录系统"
:
"您可以返回主界面"
}}
</h6>
<ul
class=
"list-unstyled"
v-if=
"isSecretFreeLogin === false"
>
<li
class=
"link-type"
>
<router-link
to=
"/"
>
回首页
...
...
@@ -26,21 +26,46 @@
</
template
>
<
script
>
import
errGif
from
'@/assets/images/401/401.gif'
import
errGif
from
'@/assets/images/401/401.gif'
;
import
{
getThirdPlatform
}
from
"@/utils/auth"
;
export
default
{
name
:
'Page401'
,
data
()
{
return
{
errGif
:
errGif
+
'?'
+
+
new
Date
()
errGif
:
errGif
+
'?'
+
+
new
Date
(),
isSecretFreeLogin
:
null
};
},
created
()
{
const
{
isSecretFreeLogin
}
=
this
.
$route
.
query
;
try
{
this
.
isSecretFreeLogin
=
JSON
.
parse
(
isSecretFreeLogin
);
}
catch
(
error
)
{
}
},
methods
:
{
back
()
{
if
(
this
.
$route
.
query
.
noGoBack
)
{
this
.
$router
.
push
({
path
:
'/'
})
this
.
$router
.
push
({
path
:
'/'
});
}
else
{
this
.
$router
.
go
(
-
1
);
}
},
aginLogin
()
{
const
platFormKey
=
getThirdPlatform
();
if
(
platFormKey
)
{
this
.
$router
.
replace
({
path
:
"/"
,
query
:
{
platFormKey
}
});
}
else
{
this
.
$router
.
go
(
-
1
)
this
.
$router
.
replace
({
path
:
"/login"
});
}
}
}
...
...
@@ -48,41 +73,44 @@ export default {
</
script
>
<
style
lang=
"scss"
scoped
>
.errPage-container
{
width
:
800px
;
max-width
:
100%
;
margin
:
100px
auto
;
.pan-back-btn
{
background
:
#008489
;
color
:
#fff
;
border
:
none
!
important
;
}
.pan-gif
{
margin
:
0
auto
;
display
:
block
;
}
.pan-img
{
display
:
block
;
margin
:
0
auto
;
width
:
100%
;
}
.text-jumbo
{
font-size
:
60px
;
font-weight
:
700
;
color
:
#484848
;
.errPage-container
{
width
:
800px
;
max-width
:
100%
;
margin
:
100px
auto
;
.pan-back-btn
{
background
:
#008489
;
color
:
#fff
;
border
:
none
!
important
;
}
.pan-gif
{
margin
:
0
auto
;
display
:
block
;
}
.pan-img
{
display
:
block
;
margin
:
0
auto
;
width
:
100%
;
}
.text-jumbo
{
font-size
:
60px
;
font-weight
:
700
;
color
:
#484848
;
}
.list-unstyled
{
font-size
:
14px
;
li
{
padding-bottom
:
5px
;
}
.list-unstyled
{
font-size
:
14px
;
li
{
padding-bottom
:
5px
;
}
a
{
color
:
#008489
;
text-decoration
:
none
;
&
:hover
{
text-decoration
:
underline
;
}
a
{
color
:
#008489
;
text-decoration
:
none
;
&
:hover
{
text-decoration
:
underline
;
}
}
}
h6
{
line-height
:
22px
;
}
}
</
style
>
dsk-system/src/main/java/com/dsk/system/domain/SysUser.java
View file @
077f62f4
package
com
.
dsk
.
system
.
domain
;
import
com.baomidou.mybatisplus.annotation.*
;
import
com.dsk.common.annotation.Sensitive
;
import
com.dsk.common.constant.UserConstants
;
import
com.dsk.common.enums.SensitiveStrategy
;
import
com.dsk.common.tenant.core.TenantEntity
;
import
com.dsk.common.xss.Xss
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.NoArgsConstructor
;
import
javax.validation.constraints.Email
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.Size
;
import
java.util.Date
;
import
java.util.List
;
/**
* 用户对象 sys_user
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode
(
callSuper
=
true
)
@TableName
(
"sys_user"
)
public
class
SysUser
extends
TenantEntity
{
/**
* 用户ID
*/
@TableId
(
value
=
"user_id"
)
private
Long
userId
;
/**
* 部门ID
*/
private
Long
deptId
;
/**
* 用户账号
*/
@Xss
(
message
=
"用户账号不能包含脚本字符"
)
@NotBlank
(
message
=
"用户账号不能为空"
)
@Size
(
min
=
0
,
max
=
30
,
message
=
"用户账号长度不能超过{max}个字符"
)
private
String
userName
;
/**
* 用户昵称
*/
@Xss
(
message
=
"用户昵称不能包含脚本字符"
)
@NotBlank
(
message
=
"用户昵称不能为空"
)
@Size
(
min
=
0
,
max
=
30
,
message
=
"用户昵称长度不能超过{max}个字符"
)
private
String
nickName
;
/**
* 用户类型(sys_user系统用户)
*/
private
String
userType
;
/**
* 用户邮箱
*/
@Sensitive
(
strategy
=
SensitiveStrategy
.
EMAIL
)
@Email
(
message
=
"邮箱格式不正确"
)
@Size
(
min
=
0
,
max
=
50
,
message
=
"邮箱长度不能超过{max}个字符"
)
private
String
email
;
/**
* 手机号码
*/
@Sensitive
(
strategy
=
SensitiveStrategy
.
PHONE
)
private
String
phonenumber
;
/**
* 用户性别
*/
private
String
sex
;
/**
* 用户头像
*/
private
String
avatar
;
/**
* 密码
*/
@TableField
(
insertStrategy
=
FieldStrategy
.
NOT_EMPTY
,
updateStrategy
=
FieldStrategy
.
NOT_EMPTY
,
whereStrategy
=
FieldStrategy
.
NOT_EMPTY
)
private
String
password
;
@JsonIgnore
@JsonProperty
public
String
getPassword
()
{
return
password
;
}
/**
* 帐号状态(0正常 1停用)
*/
private
String
status
;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private
String
delFlag
;
/**
* 最后登录IP
*/
private
String
loginIp
;
/**
* 最后登录时间
*/
private
Date
loginDate
;
/**
* 备注
*/
private
String
remark
;
/**
* 创建时间
*/
private
Date
createTime
;
/**
* 部门对象
*/
@TableField
(
exist
=
false
)
private
SysDept
dept
;
/**
* 角色对象
*/
@TableField
(
exist
=
false
)
private
List
<
SysRole
>
roles
;
/**
* 角色组
*/
@TableField
(
exist
=
false
)
private
Long
[]
roleIds
;
/**
* 岗位组
*/
@TableField
(
exist
=
false
)
private
Long
[]
postIds
;
/**
* 数据权限 当前角色ID
*/
@TableField
(
exist
=
false
)
private
Long
roleId
;
public
SysUser
(
Long
userId
)
{
this
.
userId
=
userId
;
}
public
boolean
isAdmin
()
{
return
UserConstants
.
ADMIN_ID
.
equals
(
this
.
userId
);
}
public
boolean
isSuperAdmin
()
{
return
UserConstants
.
SUPER_ADMIN_ID
.
equals
(
this
.
userId
);
}
}
package
com
.
dsk
.
system
.
domain
;
import
com.baomidou.mybatisplus.annotation.*
;
import
com.dsk.common.annotation.Sensitive
;
import
com.dsk.common.constant.UserConstants
;
import
com.dsk.common.enums.SensitiveStrategy
;
import
com.dsk.common.tenant.core.TenantEntity
;
import
com.dsk.common.xss.Xss
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.NoArgsConstructor
;
import
javax.validation.constraints.Email
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.Size
;
import
java.util.Date
;
import
java.util.List
;
/**
* 用户对象 sys_user
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode
(
callSuper
=
true
)
@TableName
(
"sys_user"
)
public
class
SysUser
extends
TenantEntity
{
/**
* 用户ID
*/
@TableId
(
value
=
"user_id"
)
private
Long
userId
;
/**
* 三方平台跳转本系统所需秘钥
*/
private
String
thirdPlatformKey
;
/**
* 部门ID
*/
private
Long
deptId
;
/**
* 用户账号
*/
@Xss
(
message
=
"用户账号不能包含脚本字符"
)
@NotBlank
(
message
=
"用户账号不能为空"
)
@Size
(
min
=
0
,
max
=
30
,
message
=
"用户账号长度不能超过{max}个字符"
)
private
String
userName
;
/**
* 用户昵称
*/
@Xss
(
message
=
"用户昵称不能包含脚本字符"
)
@NotBlank
(
message
=
"用户昵称不能为空"
)
@Size
(
min
=
0
,
max
=
30
,
message
=
"用户昵称长度不能超过{max}个字符"
)
private
String
nickName
;
/**
* 用户类型(sys_user系统用户)
*/
private
String
userType
;
/**
* 用户邮箱
*/
@Sensitive
(
strategy
=
SensitiveStrategy
.
EMAIL
)
@Email
(
message
=
"邮箱格式不正确"
)
@Size
(
min
=
0
,
max
=
50
,
message
=
"邮箱长度不能超过{max}个字符"
)
private
String
email
;
/**
* 手机号码
*/
@Sensitive
(
strategy
=
SensitiveStrategy
.
PHONE
)
private
String
phonenumber
;
/**
* 用户性别
*/
private
String
sex
;
/**
* 用户头像
*/
private
String
avatar
;
/**
* 密码
*/
@TableField
(
insertStrategy
=
FieldStrategy
.
NOT_EMPTY
,
updateStrategy
=
FieldStrategy
.
NOT_EMPTY
,
whereStrategy
=
FieldStrategy
.
NOT_EMPTY
)
private
String
password
;
@JsonIgnore
@JsonProperty
public
String
getPassword
()
{
return
password
;
}
/**
* 帐号状态(0正常 1停用)
*/
private
String
status
;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private
String
delFlag
;
/**
* 最后登录IP
*/
private
String
loginIp
;
/**
* 最后登录时间
*/
private
Date
loginDate
;
/**
* 备注
*/
private
String
remark
;
/**
* 创建时间
*/
private
Date
createTime
;
/**
* 部门对象
*/
@TableField
(
exist
=
false
)
private
SysDept
dept
;
/**
* 角色对象
*/
@TableField
(
exist
=
false
)
private
List
<
SysRole
>
roles
;
/**
* 角色组
*/
@TableField
(
exist
=
false
)
private
Long
[]
roleIds
;
/**
* 岗位组
*/
@TableField
(
exist
=
false
)
private
Long
[]
postIds
;
/**
* 数据权限 当前角色ID
*/
@TableField
(
exist
=
false
)
private
Long
roleId
;
public
SysUser
(
Long
userId
)
{
this
.
userId
=
userId
;
}
public
boolean
isAdmin
()
{
return
UserConstants
.
ADMIN_ID
.
equals
(
this
.
userId
);
}
public
boolean
isSuperAdmin
()
{
return
UserConstants
.
SUPER_ADMIN_ID
.
equals
(
this
.
userId
);
}
}
dsk-system/src/main/java/com/dsk/system/service/SysLoginService.java
View file @
077f62f4
package
com
.
dsk
.
system
.
service
;
import
cn.dev33.satoken.exception.NotLoginException
;
import
cn.dev33.satoken.secure.BCrypt
;
import
cn.dev33.satoken.secure.SaBase64Util
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.lang.Assert
;
import
cn.hutool.core.lang.RegexPool
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.ReUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.dsk.common.constant.CacheConstants
;
import
com.dsk.common.constant.Constants
;
import
com.dsk.common.constant.GlobalConstants
;
import
com.dsk.common.constant.TenantConstants
;
import
com.dsk.common.core.domain.dto.RoleDTO
;
import
com.dsk.common.core.domain.event.LogininforEvent
;
import
com.dsk.common.core.domain.model.LoginBody
;
import
com.dsk.common.core.domain.model.LoginUser
;
import
com.dsk.common.core.domain.model.XcxLoginUser
;
import
com.dsk.common.enums.DeviceType
;
import
com.dsk.common.enums.LoginType
;
import
com.dsk.common.enums.TenantStatus
;
import
com.dsk.common.enums.UserStatus
;
import
com.dsk.common.exception.user.CaptchaException
;
import
com.dsk.common.exception.user.CaptchaExpireException
;
import
com.dsk.common.exception.user.UserException
;
import
com.dsk.common.helper.LoginHelper
;
import
com.dsk.common.tenant.exception.TenantException
;
import
com.dsk.common.tenant.helper.TenantBroker
;
import
com.dsk.common.tenant.helper.TenantHelper
;
import
com.dsk.common.utils.DateUtils
;
import
com.dsk.common.utils.MessageUtils
;
import
com.dsk.common.utils.ServletUtils
;
import
com.dsk.common.utils.StringUtils
;
import
com.dsk.common.utils.redis.RedisUtils
;
import
com.dsk.common.utils.spring.SpringUtils
;
import
com.dsk.system.domain.SysTenant
;
import
com.dsk.system.domain.SysUser
;
import
com.dsk.system.domain.vo.LoginVo
;
import
com.dsk.system.domain.vo.SysTenantVo
;
import
com.dsk.system.mapper.SysTenantMapper
;
import
com.dsk.system.mapper.SysUserMapper
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
java.time.Duration
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.function.Supplier
;
/**
* 登录校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Slf4j
@Service
public
class
SysLoginService
{
private
final
SysUserMapper
userMapper
;
private
final
ISysConfigService
configService
;
private
final
SysPermissionService
permissionService
;
private
final
ISysTenantService
sysTenantService
;
@Value
(
"${captcha.enable}"
)
private
boolean
captchaEnabled
;
@Value
(
"${user.password.maxRetryCount}"
)
private
Integer
maxRetryCount
;
@Value
(
"${user.password.lockTime}"
)
private
Integer
lockTime
;
/**
* 登录验证
*
* @param loginBody 唯一标识
* @param ipAddr IP地址
* @return 结果
*/
public
LoginVo
passwordLogin
(
LoginBody
loginBody
,
String
ipAddr
)
{
String
tenantId
=
loginBody
.
getTenantId
();
String
username
=
loginBody
.
getUsername
();
String
password
=
SaBase64Util
.
decode
(
loginBody
.
getPassword
());
String
code
=
loginBody
.
getCode
();
String
uuid
=
loginBody
.
getUuid
();
// 验证码开关
if
(
captchaEnabled
)
{
validateCaptcha
(
username
,
code
,
uuid
);
}
if
(
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
username
))
{
String
defaultTenantId
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
username
);
log
.
info
(
"登录用户:{} 获取缓存默认租户:"
+
tenantId
,
username
);
if
(
StrUtil
.
isEmpty
(
tenantId
)
&&
StrUtil
.
isNotBlank
(
defaultTenantId
))
{
defaultTenantId
=
checkDefaultTenant
(
defaultTenantId
,
username
);
tenantId
=
defaultTenantId
;
}
}
//查询手机号绑定的所有用户
if
(
StrUtil
.
isEmpty
(
tenantId
))
{
List
<
SysUser
>
sysUsers
=
queryListByPhone
(
username
);
if
(
CollectionUtil
.
isEmpty
(
sysUsers
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
else
if
(
sysUsers
.
size
()
>
1
)
{
//处理存在多个用户的情况,取一个最新租户
SysUser
sysUser
=
sysUsers
.
get
(
0
);
if
(
ObjectUtil
.
isEmpty
(
sysUser
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
tenantId
=
sysUser
.
getTenantId
();
}
else
{
SysUser
sysUser
=
sysUsers
.
get
(
0
);
tenantId
=
sysUser
.
getTenantId
();
}
}
// 校验租户
if
(
tenantId
!=
null
)
{
checkTenant
(
tenantId
);
}
if
(
tenantId
==
null
||
""
.
equals
(
tenantId
))
{
tenantId
=
TenantConstants
.
DEFAULT_TENANT_ID
;
}
TenantHelper
.
setTenantId
(
tenantId
);
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// SysUser user = loadUserByUsername(username);
// return TenantBroker.applyAs(tenantId, (id -> {
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByUsername
(
username
);
checkLogin
(
LoginType
.
PASSWORD
,
username
,
()
->
!
BCrypt
.
checkpw
(
password
,
user
.
getPassword
()));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
loginUser
.
setIpaddr
(
ipAddr
);
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
// RedisUtils.setCacheObject(GlobalConstants.PHONE_DEFAULT_TENANT + username, TenantHelper.getTenantId(), Duration.ofDays(30));
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
// }));
// return StpUtil.getTokenValue();
}
/**
* 登录验证
*
* @param username 用户名
* @param password 密码
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public
String
login
(
String
username
,
String
password
,
String
code
,
String
uuid
)
{
boolean
captchaEnabled
=
configService
.
selectCaptchaEnabled
();
// 验证码开关
if
(
captchaEnabled
)
{
validateCaptcha
(
username
,
code
,
uuid
);
}
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByUsername
(
username
);
checkLogin
(
LoginType
.
PASSWORD
,
username
,
()
->
!
BCrypt
.
checkpw
(
password
,
user
.
getPassword
()));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
return
StpUtil
.
getTokenValue
();
}
public
LoginVo
smsLogin
(
String
username
,
String
smsCode
)
{
String
tenantId
=
null
;
if
(
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
username
))
{
String
defaultTenantId
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
username
);
log
.
info
(
"登录用户:{} 获取缓存默认租户:"
+
tenantId
,
username
);
if
(
StrUtil
.
isNotBlank
(
defaultTenantId
))
{
defaultTenantId
=
checkDefaultTenant
(
defaultTenantId
,
username
);
tenantId
=
defaultTenantId
;
}
}
//查询手机号绑定的所有用户
if
(
StrUtil
.
isEmpty
(
tenantId
))
{
List
<
SysUser
>
sysUsers
=
queryListByPhone
(
username
);
if
(
CollectionUtil
.
isEmpty
(
sysUsers
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
else
if
(
sysUsers
.
size
()
>
1
)
{
//处理存在多个用户的情况,取一个最新租户
SysUser
sysUser
=
sysUsers
.
get
(
0
);
if
(
ObjectUtil
.
isEmpty
(
sysUser
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
tenantId
=
sysUser
.
getTenantId
();
}
else
{
SysUser
sysUser
=
sysUsers
.
get
(
0
);
tenantId
=
sysUser
.
getTenantId
();
}
}
// 校验租户
if
(
tenantId
!=
null
)
{
checkTenant
(
tenantId
);
}
if
(
tenantId
==
null
||
""
.
equals
(
tenantId
))
{
tenantId
=
TenantConstants
.
DEFAULT_TENANT_ID
;
}
TenantHelper
.
setTenantId
(
tenantId
);
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// SysUser user = loadUserByUsername(username);
// return TenantBroker.applyAs(tenantId, (id -> {
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByUsername
(
username
);
checkLogin
(
LoginType
.
SMS
,
username
,
()
->
!
validateSmsCode
(
username
,
smsCode
));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
}
public
String
emailLogin
(
String
email
,
String
emailCode
)
{
// 通过手邮箱查找用户
SysUser
user
=
loadUserByEmail
(
email
);
checkLogin
(
LoginType
.
EMAIL
,
user
.
getUserName
(),
()
->
!
validateEmailCode
(
email
,
emailCode
));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
APP
);
recordLogininfor
(
user
.
getUserName
(),
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
user
.
getUserName
());
return
StpUtil
.
getTokenValue
();
}
public
String
xcxLogin
(
String
xcxCode
)
{
// xcxCode 为 小程序调用 wx.login 授权后获取
// todo 以下自行实现
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
String
openid
=
""
;
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByOpenid
(
openid
);
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
XcxLoginUser
loginUser
=
new
XcxLoginUser
();
loginUser
.
setUserId
(
user
.
getUserId
());
loginUser
.
setUsername
(
user
.
getUserName
());
loginUser
.
setUserType
(
user
.
getUserType
());
loginUser
.
setOpenid
(
openid
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
XCX
);
recordLogininfor
(
user
.
getUserName
(),
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
user
.
getUserName
());
return
StpUtil
.
getTokenValue
();
}
/**
* 退出登录
*/
public
void
logout
()
{
try
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
if
(
TenantHelper
.
isEnable
()
&&
LoginHelper
.
isSuperAdmin
())
{
// 超级管理员 登出清除动态租户
TenantHelper
.
clearDynamic
();
}
recordLogininfor
(
loginUser
.
getUsername
(),
Constants
.
LOGOUT
,
MessageUtils
.
message
(
"user.logout.success"
));
}
catch
(
NotLoginException
ignored
)
{
}
finally
{
try
{
StpUtil
.
logout
();
}
catch
(
NotLoginException
ignored
)
{
}
}
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
*/
private
void
recordLogininfor
(
String
username
,
String
status
,
String
message
)
{
LogininforEvent
logininforEvent
=
new
LogininforEvent
();
logininforEvent
.
setUsername
(
username
);
logininforEvent
.
setStatus
(
status
);
logininforEvent
.
setMessage
(
message
);
logininforEvent
.
setRequest
(
ServletUtils
.
getRequest
());
SpringUtils
.
context
().
publishEvent
(
logininforEvent
);
}
/**
* 校验短信验证码
*/
private
boolean
validateSmsCode
(
String
phonenumber
,
String
smsCode
)
{
String
code
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
CAPTCHA_CODE_KEY
+
phonenumber
);
if
(
StringUtils
.
isBlank
(
code
))
{
recordLogininfor
(
phonenumber
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.expire"
));
throw
new
CaptchaExpireException
();
}
return
code
.
equals
(
smsCode
);
}
/**
* 校验邮箱验证码
*/
private
boolean
validateEmailCode
(
String
email
,
String
emailCode
)
{
String
code
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
CAPTCHA_CODE_KEY
+
email
);
if
(
StringUtils
.
isBlank
(
code
))
{
recordLogininfor
(
email
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.expire"
));
throw
new
CaptchaExpireException
();
}
return
code
.
equals
(
emailCode
);
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
*/
public
void
validateCaptcha
(
String
username
,
String
code
,
String
uuid
)
{
String
verifyKey
=
GlobalConstants
.
CAPTCHA_CODE_KEY
+
StringUtils
.
defaultString
(
uuid
,
""
);
String
captcha
=
RedisUtils
.
getCacheObject
(
verifyKey
);
RedisUtils
.
deleteObject
(
verifyKey
);
if
(
captcha
==
null
)
{
recordLogininfor
(
username
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.expire"
));
throw
new
CaptchaExpireException
();
}
if
(!
code
.
equalsIgnoreCase
(
captcha
))
{
recordLogininfor
(
username
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.error"
));
throw
new
CaptchaException
();
}
}
private
SysUser
loadUserByUsername
(
String
username
)
{
SysUser
user
=
userMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getUserName
,
SysUser:
:
getStatus
)
.
eq
(
SysUser:
:
getUserName
,
username
)
.
or
().
eq
(
SysUser:
:
getPhonenumber
,
username
));
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
username
);
throw
new
UserException
(
"user.blocked"
,
username
);
}
return
userMapper
.
selectUserByUserName
(
user
.
getUserName
());
}
private
SysUser
loadUserByPhonenumber
(
String
phonenumber
)
{
SysUser
user
=
userMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getPhonenumber
,
SysUser:
:
getStatus
)
.
eq
(
SysUser:
:
getPhonenumber
,
phonenumber
));
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
phonenumber
);
throw
new
UserException
(
"user.not.exists"
,
phonenumber
);
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
phonenumber
);
throw
new
UserException
(
"user.blocked"
,
phonenumber
);
}
return
userMapper
.
selectUserByPhonenumber
(
phonenumber
);
}
private
SysUser
loadUserByEmail
(
String
email
)
{
SysUser
user
=
userMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getPhonenumber
,
SysUser:
:
getStatus
)
.
eq
(
SysUser:
:
getEmail
,
email
));
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
email
);
throw
new
UserException
(
"user.not.exists"
,
email
);
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
email
);
throw
new
UserException
(
"user.blocked"
,
email
);
}
return
userMapper
.
selectUserByEmail
(
email
);
}
private
SysUser
loadUserByOpenid
(
String
openid
)
{
// 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
// todo 自行实现 userService.selectUserByOpenid(openid);
SysUser
user
=
new
SysUser
();
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
openid
);
// todo 用户不存在 业务逻辑自行实现
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
openid
);
// todo 用户已被停用 业务逻辑自行实现
}
return
user
;
}
/**
* 构建登录用户
*/
public
LoginUser
buildLoginUser
(
SysUser
user
)
{
LoginUser
loginUser
=
new
LoginUser
();
loginUser
.
setTenantId
(
user
.
getTenantId
());
loginUser
.
setUserId
(
user
.
getUserId
());
loginUser
.
setDeptId
(
user
.
getDeptId
());
loginUser
.
setUsername
(
user
.
getUserName
());
loginUser
.
setNickname
(
user
.
getNickName
());
loginUser
.
setUserType
(
user
.
getUserType
());
loginUser
.
setUserPhone
(
user
.
getPhonenumber
());
loginUser
.
setMenuPermission
(
permissionService
.
getMenuPermission
(
user
.
getUserId
()));
loginUser
.
setRolePermission
(
permissionService
.
getRolePermission
(
user
.
getUserId
()));
loginUser
.
setDeptName
(
ObjectUtil
.
isNull
(
user
.
getDept
())
?
""
:
user
.
getDept
().
getDeptName
());
List
<
RoleDTO
>
roles
=
BeanUtil
.
copyToList
(
user
.
getRoles
(),
RoleDTO
.
class
);
loginUser
.
setRoles
(
roles
);
return
loginUser
;
}
/**
* 记录登录信息
*
* @param userId 用户ID
*/
public
void
recordLoginInfo
(
Long
userId
,
String
username
)
{
SysUser
sysUser
=
new
SysUser
();
sysUser
.
setUserId
(
userId
);
sysUser
.
setLoginIp
(
ServletUtils
.
getClientIP
());
sysUser
.
setLoginDate
(
DateUtils
.
getNowDate
());
sysUser
.
setUpdateBy
(
username
);
userMapper
.
updateById
(
sysUser
);
}
/**
* 登录校验
*/
private
void
checkLogin
(
LoginType
loginType
,
String
username
,
Supplier
<
Boolean
>
supplier
)
{
String
errorKey
=
GlobalConstants
.
PWD_ERR_CNT_KEY
+
username
;
String
loginFail
=
Constants
.
LOGIN_FAIL
;
// 获取用户登录错误次数,默认为0 (可自定义限制策略 例如: key + username + ip)
int
errorNumber
=
ObjectUtil
.
defaultIfNull
(
RedisUtils
.
getCacheObject
(
errorKey
),
0
);
// 锁定时间内登录 则踢出
if
(
errorNumber
>=
maxRetryCount
)
{
recordLogininfor
(
username
,
loginFail
,
MessageUtils
.
message
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
));
throw
new
UserException
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
);
}
if
(
supplier
.
get
())
{
// 错误次数递增
errorNumber
++;
RedisUtils
.
setCacheObject
(
errorKey
,
errorNumber
,
Duration
.
ofMinutes
(
lockTime
));
// 达到规定错误次数 则锁定登录
if
(
errorNumber
>=
maxRetryCount
)
{
recordLogininfor
(
username
,
loginFail
,
MessageUtils
.
message
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
));
throw
new
UserException
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
);
}
else
{
// 未达到规定错误次数
recordLogininfor
(
username
,
loginFail
,
MessageUtils
.
message
(
loginType
.
getRetryLimitCount
(),
errorNumber
));
throw
new
UserException
(
loginType
.
getRetryLimitCount
(),
errorNumber
);
}
}
// 登录成功 清空错误次数
RedisUtils
.
deleteObject
(
errorKey
);
}
public
void
checkTenant
(
String
tenantId
)
{
if
(!
TenantHelper
.
isEnable
())
{
return
;
}
if
(
TenantConstants
.
DEFAULT_TENANT_ID
.
equals
(
tenantId
))
{
return
;
}
SysTenantVo
tenant
=
sysTenantService
.
queryByTenantId
(
tenantId
);
if
(
ObjectUtil
.
isNull
(
tenant
))
{
log
.
info
(
"登录企业:{} 不存在."
,
tenantId
);
throw
new
TenantException
(
"company.not.exists"
);
}
else
if
(
TenantStatus
.
DISABLE
.
getCode
().
equals
(
tenant
.
getStatus
()))
{
log
.
info
(
"登录企业:{} 已被停用."
,
tenant
.
getCompanyName
());
throw
new
TenantException
(
"company.blocked"
);
}
else
if
(
ObjectUtil
.
isNotNull
(
tenant
.
getExpireTime
())
&&
new
Date
().
after
(
tenant
.
getExpireTime
()))
{
log
.
info
(
"登录企业:{} 已超过有效期."
,
tenant
.
getCompanyName
());
throw
new
TenantException
(
"company.expired"
);
}
}
public
String
checkDefaultTenant
(
String
tenantId
,
String
phoneNumber
)
{
if
(!
TenantHelper
.
isEnable
())
{
return
null
;
}
if
(
TenantConstants
.
DEFAULT_TENANT_ID
.
equals
(
tenantId
))
{
return
null
;
}
SysTenantVo
tenant
=
sysTenantService
.
queryByTenantId
(
tenantId
);
if
(
ObjectUtil
.
isNull
(
tenant
))
{
log
.
info
(
"登录企业:{} 不存在."
,
tenantId
);
RedisUtils
.
deleteObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phoneNumber
);
return
null
;
}
else
if
(
TenantStatus
.
DISABLE
.
getCode
().
equals
(
tenant
.
getStatus
()))
{
log
.
info
(
"登录企业:{} 已被停用."
,
tenant
.
getCompanyName
());
RedisUtils
.
deleteObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phoneNumber
);
return
null
;
}
else
if
(
ObjectUtil
.
isNotNull
(
tenant
.
getExpireTime
())
&&
new
Date
().
after
(
tenant
.
getExpireTime
()))
{
log
.
info
(
"登录企业:{} 已超过有效期."
,
tenant
.
getCompanyName
());
RedisUtils
.
deleteObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phoneNumber
);
return
null
;
}
return
tenantId
;
}
public
List
<
SysTenantVo
>
tenantListByAccount
(
String
username
)
{
return
TenantHelper
.
ignore
(()
->
sysTenantService
.
selectTenantList
(
username
));
}
// public List<SysTenantVo> selectTenantList(String username){
//
// }
public
List
<
SysUser
>
queryListByPhone
(
String
username
)
{
return
TenantHelper
.
ignore
(()
->
{
List
<
SysUser
>
sysUsers
=
null
;
if
(
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
username
))
{
LambdaQueryWrapper
<
SysUser
>
lqw
=
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getUserName
,
SysUser:
:
getStatus
,
SysUser:
:
getTenantId
,
SysUser:
:
getDelFlag
)
.
eq
(
SysUser:
:
getPhonenumber
,
username
)
.
orderByDesc
(
SysUser:
:
getUserId
);
// sysUsers = userMapper.selectUserByTenantPhone(username);
sysUsers
=
userMapper
.
selectList
(
lqw
);
}
else
{
LambdaQueryWrapper
<
SysUser
>
lqw
=
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getUserName
,
SysUser:
:
getStatus
,
SysUser:
:
getTenantId
)
.
eq
(
SysUser:
:
getUserName
,
username
)
.
orderByDesc
(
SysUser:
:
getUserId
);
// sysUsers = userMapper.selectUserByTenantUsername(username);
sysUsers
=
userMapper
.
selectList
(
lqw
);
}
return
sysUsers
;
});
}
public
LoginVo
switchTenant
(
String
tenantId
)
{
//获取当前登录信息
Long
userId
=
LoginHelper
.
getUserId
();
Assert
.
notNull
(
userId
,
"企业切换失败!"
);
// 如果 切换租户和当前登录租户一致,仅保存默认租户
LoginUser
loginUserVo
=
LoginHelper
.
getLoginUser
();
if
(
tenantId
.
equals
(
loginUserVo
.
getTenantId
()))
{
//保存当前账号的默认租户
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
loginUserVo
.
getUserPhone
();
RedisUtils
.
setCacheObject
(
defaultTenantKey
,
tenantId
,
Duration
.
ofDays
(
90
));
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
}
SysUser
sysUser
=
TenantHelper
.
ignore
(()
->
{
return
userMapper
.
selectUserById
(
userId
);
});
Assert
.
notNull
(
sysUser
,
"用户信息为空,企业切换失败!"
);
if
(
StrUtil
.
isEmpty
(
sysUser
.
getPhonenumber
()))
{
Assert
.
notNull
(
sysUser
,
"用户手机号为空,企业切换失败!"
);
}
//退出登录
StpUtil
.
logout
();
String
tokenValue
=
StpUtil
.
getTokenValueByLoginId
(
userId
);
StpUtil
.
logoutByTokenValue
(
tokenValue
);
StpUtil
.
kickoutByTokenValue
(
tokenValue
);
// RedisUtils.deleteKeys("*"+tokenValue+"*");
//重新登录
TenantHelper
.
setTenantId
(
tenantId
);
String
username
=
sysUser
.
getPhonenumber
();
SysUser
user
=
loadUserByUsername
(
sysUser
.
getPhonenumber
());
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
log
.
info
(
"当前租户由"
+
sysUser
.
getTenantId
()
+
"切换为"
+
tenantId
);
//保存当前账号的默认租户
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
loginUser
.
getUserPhone
();
RedisUtils
.
setCacheObject
(
defaultTenantKey
,
tenantId
,
Duration
.
ofDays
(
90
));
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
}
}
package
com
.
dsk
.
system
.
service
;
import
cn.dev33.satoken.exception.NotLoginException
;
import
cn.dev33.satoken.secure.BCrypt
;
import
cn.dev33.satoken.secure.SaBase64Util
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.lang.Assert
;
import
cn.hutool.core.lang.RegexPool
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.ReUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.dsk.common.constant.Constants
;
import
com.dsk.common.constant.GlobalConstants
;
import
com.dsk.common.constant.TenantConstants
;
import
com.dsk.common.core.domain.dto.RoleDTO
;
import
com.dsk.common.core.domain.event.LogininforEvent
;
import
com.dsk.common.core.domain.model.LoginBody
;
import
com.dsk.common.core.domain.model.LoginUser
;
import
com.dsk.common.core.domain.model.ThirdPlatformLoginBody
;
import
com.dsk.common.core.domain.model.XcxLoginUser
;
import
com.dsk.common.enums.DeviceType
;
import
com.dsk.common.enums.LoginType
;
import
com.dsk.common.enums.TenantStatus
;
import
com.dsk.common.enums.UserStatus
;
import
com.dsk.common.exception.user.CaptchaException
;
import
com.dsk.common.exception.user.CaptchaExpireException
;
import
com.dsk.common.exception.user.UserException
;
import
com.dsk.common.helper.LoginHelper
;
import
com.dsk.common.tenant.exception.TenantException
;
import
com.dsk.common.tenant.helper.TenantHelper
;
import
com.dsk.common.utils.DateUtils
;
import
com.dsk.common.utils.MessageUtils
;
import
com.dsk.common.utils.ServletUtils
;
import
com.dsk.common.utils.StringUtils
;
import
com.dsk.common.utils.redis.RedisUtils
;
import
com.dsk.common.utils.spring.SpringUtils
;
import
com.dsk.system.domain.SysUser
;
import
com.dsk.system.domain.vo.LoginVo
;
import
com.dsk.system.domain.vo.SysTenantVo
;
import
com.dsk.system.mapper.SysUserMapper
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
java.time.Duration
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.function.Supplier
;
/**
* 登录校验方法
*
* @author Lion Li
*/
@RequiredArgsConstructor
@Slf4j
@Service
public
class
SysLoginService
{
private
final
SysUserMapper
userMapper
;
private
final
ISysConfigService
configService
;
private
final
SysPermissionService
permissionService
;
private
final
ISysTenantService
sysTenantService
;
@Value
(
"${captcha.enable}"
)
private
boolean
captchaEnabled
;
@Value
(
"${user.password.maxRetryCount}"
)
private
Integer
maxRetryCount
;
@Value
(
"${user.password.lockTime}"
)
private
Integer
lockTime
;
/**
* 登录验证
*
* @param loginBody 唯一标识
* @param ipAddr IP地址
* @return 结果
*/
public
LoginVo
passwordLogin
(
LoginBody
loginBody
,
String
ipAddr
)
{
String
tenantId
=
loginBody
.
getTenantId
();
String
username
=
loginBody
.
getUsername
();
String
password
=
SaBase64Util
.
decode
(
loginBody
.
getPassword
());
String
code
=
loginBody
.
getCode
();
String
uuid
=
loginBody
.
getUuid
();
// 验证码开关
if
(
captchaEnabled
)
{
validateCaptcha
(
username
,
code
,
uuid
);
}
if
(
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
username
))
{
String
defaultTenantId
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
username
);
log
.
info
(
"登录用户:{} 获取缓存默认租户:"
+
tenantId
,
username
);
if
(
StrUtil
.
isEmpty
(
tenantId
)
&&
StrUtil
.
isNotBlank
(
defaultTenantId
))
{
defaultTenantId
=
checkDefaultTenant
(
defaultTenantId
,
username
);
tenantId
=
defaultTenantId
;
}
}
//查询手机号绑定的所有用户
if
(
StrUtil
.
isEmpty
(
tenantId
))
{
List
<
SysUser
>
sysUsers
=
queryListByPhone
(
username
);
if
(
CollectionUtil
.
isEmpty
(
sysUsers
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
else
if
(
sysUsers
.
size
()
>
1
)
{
//处理存在多个用户的情况,取一个最新租户
SysUser
sysUser
=
sysUsers
.
get
(
0
);
if
(
ObjectUtil
.
isEmpty
(
sysUser
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
tenantId
=
sysUser
.
getTenantId
();
}
else
{
SysUser
sysUser
=
sysUsers
.
get
(
0
);
tenantId
=
sysUser
.
getTenantId
();
}
}
// 校验租户
if
(
tenantId
!=
null
)
{
checkTenant
(
tenantId
);
}
if
(
tenantId
==
null
||
""
.
equals
(
tenantId
))
{
tenantId
=
TenantConstants
.
DEFAULT_TENANT_ID
;
}
TenantHelper
.
setTenantId
(
tenantId
);
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// SysUser user = loadUserByUsername(username);
// return TenantBroker.applyAs(tenantId, (id -> {
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByUsername
(
username
);
checkLogin
(
LoginType
.
PASSWORD
,
username
,
()
->
!
BCrypt
.
checkpw
(
password
,
user
.
getPassword
()));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
loginUser
.
setIpaddr
(
ipAddr
);
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
// RedisUtils.setCacheObject(GlobalConstants.PHONE_DEFAULT_TENANT + username, TenantHelper.getTenantId(), Duration.ofDays(30));
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
// }));
// return StpUtil.getTokenValue();
}
/**
* 三方平台跳转登录方法
*
* @param tpLoginBody 登录信息
* @return 结果
*/
public
LoginVo
thirdPlatformLogin
(
ThirdPlatformLoginBody
tpLoginBody
,
String
ipAddr
)
{
return
TenantHelper
.
ignore
(()
->
{
SysUser
sysUser
=
userMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysUser
>()
.
eq
(
SysUser:
:
getThirdPlatformKey
,
tpLoginBody
.
getThirdPlatformKey
()));
String
tenantId
=
sysUser
.
getTenantId
();
String
username
=
sysUser
.
getUserName
();
String
password
=
sysUser
.
getPassword
();
if
(
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
username
))
{
String
defaultTenantId
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
username
);
log
.
info
(
"登录用户:{} 获取缓存默认租户:"
+
tenantId
,
username
);
if
(
StrUtil
.
isEmpty
(
tenantId
)
&&
StrUtil
.
isNotBlank
(
defaultTenantId
))
{
defaultTenantId
=
checkDefaultTenant
(
defaultTenantId
,
username
);
tenantId
=
defaultTenantId
;
}
}
//查询手机号绑定的所有用户
if
(
StrUtil
.
isEmpty
(
tenantId
))
{
List
<
SysUser
>
sysUsers
=
queryListByPhone
(
username
);
if
(
CollectionUtil
.
isEmpty
(
sysUsers
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
else
if
(
sysUsers
.
size
()
>
1
)
{
//处理存在多个用户的情况,取一个最新租户
SysUser
sysUser1
=
sysUsers
.
get
(
0
);
if
(
ObjectUtil
.
isEmpty
(
sysUser
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
tenantId
=
sysUser1
.
getTenantId
();
}
else
{
SysUser
sysUser2
=
sysUsers
.
get
(
0
);
tenantId
=
sysUser2
.
getTenantId
();
}
}
// 校验租户
if
(
tenantId
!=
null
)
{
checkTenant
(
tenantId
);
}
if
(
tenantId
==
null
||
""
.
equals
(
tenantId
))
{
tenantId
=
TenantConstants
.
DEFAULT_TENANT_ID
;
}
TenantHelper
.
setTenantId
(
tenantId
);
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByUsername
(
username
);
//checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, user.getPassword()));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
loginUser
.
setIpaddr
(
ipAddr
);
loginUser
.
setIsThirdPlatformLogin
(
true
);
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
});
}
/**
* 登录验证
*
* @param username 用户名
* @param password 密码
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public
String
login
(
String
username
,
String
password
,
String
code
,
String
uuid
)
{
boolean
captchaEnabled
=
configService
.
selectCaptchaEnabled
();
// 验证码开关
if
(
captchaEnabled
)
{
validateCaptcha
(
username
,
code
,
uuid
);
}
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByUsername
(
username
);
checkLogin
(
LoginType
.
PASSWORD
,
username
,
()
->
!
BCrypt
.
checkpw
(
password
,
user
.
getPassword
()));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
return
StpUtil
.
getTokenValue
();
}
public
LoginVo
smsLogin
(
String
username
,
String
smsCode
)
{
String
tenantId
=
null
;
if
(
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
username
))
{
String
defaultTenantId
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
username
);
log
.
info
(
"登录用户:{} 获取缓存默认租户:"
+
tenantId
,
username
);
if
(
StrUtil
.
isNotBlank
(
defaultTenantId
))
{
defaultTenantId
=
checkDefaultTenant
(
defaultTenantId
,
username
);
tenantId
=
defaultTenantId
;
}
}
//查询手机号绑定的所有用户
if
(
StrUtil
.
isEmpty
(
tenantId
))
{
List
<
SysUser
>
sysUsers
=
queryListByPhone
(
username
);
if
(
CollectionUtil
.
isEmpty
(
sysUsers
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
else
if
(
sysUsers
.
size
()
>
1
)
{
//处理存在多个用户的情况,取一个最新租户
SysUser
sysUser
=
sysUsers
.
get
(
0
);
if
(
ObjectUtil
.
isEmpty
(
sysUser
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
tenantId
=
sysUser
.
getTenantId
();
}
else
{
SysUser
sysUser
=
sysUsers
.
get
(
0
);
tenantId
=
sysUser
.
getTenantId
();
}
}
// 校验租户
if
(
tenantId
!=
null
)
{
checkTenant
(
tenantId
);
}
if
(
tenantId
==
null
||
""
.
equals
(
tenantId
))
{
tenantId
=
TenantConstants
.
DEFAULT_TENANT_ID
;
}
TenantHelper
.
setTenantId
(
tenantId
);
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
// SysUser user = loadUserByUsername(username);
// return TenantBroker.applyAs(tenantId, (id -> {
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByUsername
(
username
);
checkLogin
(
LoginType
.
SMS
,
username
,
()
->
!
validateSmsCode
(
username
,
smsCode
));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
}
public
String
emailLogin
(
String
email
,
String
emailCode
)
{
// 通过手邮箱查找用户
SysUser
user
=
loadUserByEmail
(
email
);
checkLogin
(
LoginType
.
EMAIL
,
user
.
getUserName
(),
()
->
!
validateEmailCode
(
email
,
emailCode
));
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
APP
);
recordLogininfor
(
user
.
getUserName
(),
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
user
.
getUserName
());
return
StpUtil
.
getTokenValue
();
}
public
String
xcxLogin
(
String
xcxCode
)
{
// xcxCode 为 小程序调用 wx.login 授权后获取
// todo 以下自行实现
// 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
String
openid
=
""
;
// 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
SysUser
user
=
loadUserByOpenid
(
openid
);
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
XcxLoginUser
loginUser
=
new
XcxLoginUser
();
loginUser
.
setUserId
(
user
.
getUserId
());
loginUser
.
setUsername
(
user
.
getUserName
());
loginUser
.
setUserType
(
user
.
getUserType
());
loginUser
.
setOpenid
(
openid
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
XCX
);
recordLogininfor
(
user
.
getUserName
(),
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
user
.
getUserName
());
return
StpUtil
.
getTokenValue
();
}
/**
* 退出登录
*/
public
void
logout
()
{
try
{
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
if
(
TenantHelper
.
isEnable
()
&&
LoginHelper
.
isSuperAdmin
())
{
// 超级管理员 登出清除动态租户
TenantHelper
.
clearDynamic
();
}
recordLogininfor
(
loginUser
.
getUsername
(),
Constants
.
LOGOUT
,
MessageUtils
.
message
(
"user.logout.success"
));
}
catch
(
NotLoginException
ignored
)
{
}
finally
{
try
{
StpUtil
.
logout
();
}
catch
(
NotLoginException
ignored
)
{
}
}
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
*/
private
void
recordLogininfor
(
String
username
,
String
status
,
String
message
)
{
LogininforEvent
logininforEvent
=
new
LogininforEvent
();
logininforEvent
.
setUsername
(
username
);
logininforEvent
.
setStatus
(
status
);
logininforEvent
.
setMessage
(
message
);
logininforEvent
.
setRequest
(
ServletUtils
.
getRequest
());
SpringUtils
.
context
().
publishEvent
(
logininforEvent
);
}
/**
* 校验短信验证码
*/
private
boolean
validateSmsCode
(
String
phonenumber
,
String
smsCode
)
{
String
code
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
CAPTCHA_CODE_KEY
+
phonenumber
);
if
(
StringUtils
.
isBlank
(
code
))
{
recordLogininfor
(
phonenumber
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.expire"
));
throw
new
CaptchaExpireException
();
}
return
code
.
equals
(
smsCode
);
}
/**
* 校验邮箱验证码
*/
private
boolean
validateEmailCode
(
String
email
,
String
emailCode
)
{
String
code
=
RedisUtils
.
getCacheObject
(
GlobalConstants
.
CAPTCHA_CODE_KEY
+
email
);
if
(
StringUtils
.
isBlank
(
code
))
{
recordLogininfor
(
email
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.expire"
));
throw
new
CaptchaExpireException
();
}
return
code
.
equals
(
emailCode
);
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
*/
public
void
validateCaptcha
(
String
username
,
String
code
,
String
uuid
)
{
String
verifyKey
=
GlobalConstants
.
CAPTCHA_CODE_KEY
+
StringUtils
.
defaultString
(
uuid
,
""
);
String
captcha
=
RedisUtils
.
getCacheObject
(
verifyKey
);
RedisUtils
.
deleteObject
(
verifyKey
);
if
(
captcha
==
null
)
{
recordLogininfor
(
username
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.expire"
));
throw
new
CaptchaExpireException
();
}
if
(!
code
.
equalsIgnoreCase
(
captcha
))
{
recordLogininfor
(
username
,
Constants
.
LOGIN_FAIL
,
MessageUtils
.
message
(
"user.jcaptcha.error"
));
throw
new
CaptchaException
();
}
}
private
SysUser
loadUserByUsername
(
String
username
)
{
SysUser
user
=
userMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getUserName
,
SysUser:
:
getStatus
)
.
eq
(
SysUser:
:
getUserName
,
username
)
.
or
().
eq
(
SysUser:
:
getPhonenumber
,
username
));
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
username
);
throw
new
UserException
(
"user.not.exists"
,
username
);
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
username
);
throw
new
UserException
(
"user.blocked"
,
username
);
}
return
userMapper
.
selectUserByUserName
(
user
.
getUserName
());
}
private
SysUser
loadUserByPhonenumber
(
String
phonenumber
)
{
SysUser
user
=
userMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getPhonenumber
,
SysUser:
:
getStatus
)
.
eq
(
SysUser:
:
getPhonenumber
,
phonenumber
));
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
phonenumber
);
throw
new
UserException
(
"user.not.exists"
,
phonenumber
);
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
phonenumber
);
throw
new
UserException
(
"user.blocked"
,
phonenumber
);
}
return
userMapper
.
selectUserByPhonenumber
(
phonenumber
);
}
private
SysUser
loadUserByEmail
(
String
email
)
{
SysUser
user
=
userMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getPhonenumber
,
SysUser:
:
getStatus
)
.
eq
(
SysUser:
:
getEmail
,
email
));
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
email
);
throw
new
UserException
(
"user.not.exists"
,
email
);
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
email
);
throw
new
UserException
(
"user.blocked"
,
email
);
}
return
userMapper
.
selectUserByEmail
(
email
);
}
private
SysUser
loadUserByOpenid
(
String
openid
)
{
// 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
// todo 自行实现 userService.selectUserByOpenid(openid);
SysUser
user
=
new
SysUser
();
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
openid
);
// todo 用户不存在 业务逻辑自行实现
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
openid
);
// todo 用户已被停用 业务逻辑自行实现
}
return
user
;
}
/**
* 构建登录用户
*/
public
LoginUser
buildLoginUser
(
SysUser
user
)
{
LoginUser
loginUser
=
new
LoginUser
();
loginUser
.
setTenantId
(
user
.
getTenantId
());
loginUser
.
setUserId
(
user
.
getUserId
());
loginUser
.
setDeptId
(
user
.
getDeptId
());
loginUser
.
setUsername
(
user
.
getUserName
());
loginUser
.
setNickname
(
user
.
getNickName
());
loginUser
.
setUserType
(
user
.
getUserType
());
loginUser
.
setUserPhone
(
user
.
getPhonenumber
());
loginUser
.
setMenuPermission
(
permissionService
.
getMenuPermission
(
user
.
getUserId
()));
loginUser
.
setRolePermission
(
permissionService
.
getRolePermission
(
user
.
getUserId
()));
loginUser
.
setDeptName
(
ObjectUtil
.
isNull
(
user
.
getDept
())
?
""
:
user
.
getDept
().
getDeptName
());
List
<
RoleDTO
>
roles
=
BeanUtil
.
copyToList
(
user
.
getRoles
(),
RoleDTO
.
class
);
loginUser
.
setRoles
(
roles
);
return
loginUser
;
}
/**
* 记录登录信息
*
* @param userId 用户ID
*/
public
void
recordLoginInfo
(
Long
userId
,
String
username
)
{
SysUser
sysUser
=
new
SysUser
();
sysUser
.
setUserId
(
userId
);
sysUser
.
setLoginIp
(
ServletUtils
.
getClientIP
());
sysUser
.
setLoginDate
(
DateUtils
.
getNowDate
());
sysUser
.
setUpdateBy
(
username
);
userMapper
.
updateById
(
sysUser
);
}
/**
* 登录校验
*/
private
void
checkLogin
(
LoginType
loginType
,
String
username
,
Supplier
<
Boolean
>
supplier
)
{
String
errorKey
=
GlobalConstants
.
PWD_ERR_CNT_KEY
+
username
;
String
loginFail
=
Constants
.
LOGIN_FAIL
;
// 获取用户登录错误次数,默认为0 (可自定义限制策略 例如: key + username + ip)
int
errorNumber
=
ObjectUtil
.
defaultIfNull
(
RedisUtils
.
getCacheObject
(
errorKey
),
0
);
// 锁定时间内登录 则踢出
if
(
errorNumber
>=
maxRetryCount
)
{
recordLogininfor
(
username
,
loginFail
,
MessageUtils
.
message
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
));
throw
new
UserException
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
);
}
if
(
supplier
.
get
())
{
// 错误次数递增
errorNumber
++;
RedisUtils
.
setCacheObject
(
errorKey
,
errorNumber
,
Duration
.
ofMinutes
(
lockTime
));
// 达到规定错误次数 则锁定登录
if
(
errorNumber
>=
maxRetryCount
)
{
recordLogininfor
(
username
,
loginFail
,
MessageUtils
.
message
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
));
throw
new
UserException
(
loginType
.
getRetryLimitExceed
(),
maxRetryCount
,
lockTime
);
}
else
{
// 未达到规定错误次数
recordLogininfor
(
username
,
loginFail
,
MessageUtils
.
message
(
loginType
.
getRetryLimitCount
(),
errorNumber
));
throw
new
UserException
(
loginType
.
getRetryLimitCount
(),
errorNumber
);
}
}
// 登录成功 清空错误次数
RedisUtils
.
deleteObject
(
errorKey
);
}
public
void
checkTenant
(
String
tenantId
)
{
if
(!
TenantHelper
.
isEnable
())
{
return
;
}
if
(
TenantConstants
.
DEFAULT_TENANT_ID
.
equals
(
tenantId
))
{
return
;
}
SysTenantVo
tenant
=
sysTenantService
.
queryByTenantId
(
tenantId
);
if
(
ObjectUtil
.
isNull
(
tenant
))
{
log
.
info
(
"登录企业:{} 不存在."
,
tenantId
);
throw
new
TenantException
(
"company.not.exists"
);
}
else
if
(
TenantStatus
.
DISABLE
.
getCode
().
equals
(
tenant
.
getStatus
()))
{
log
.
info
(
"登录企业:{} 已被停用."
,
tenant
.
getCompanyName
());
throw
new
TenantException
(
"company.blocked"
);
}
else
if
(
ObjectUtil
.
isNotNull
(
tenant
.
getExpireTime
())
&&
new
Date
().
after
(
tenant
.
getExpireTime
()))
{
log
.
info
(
"登录企业:{} 已超过有效期."
,
tenant
.
getCompanyName
());
throw
new
TenantException
(
"company.expired"
);
}
}
public
String
checkDefaultTenant
(
String
tenantId
,
String
phoneNumber
)
{
if
(!
TenantHelper
.
isEnable
())
{
return
null
;
}
if
(
TenantConstants
.
DEFAULT_TENANT_ID
.
equals
(
tenantId
))
{
return
null
;
}
SysTenantVo
tenant
=
sysTenantService
.
queryByTenantId
(
tenantId
);
if
(
ObjectUtil
.
isNull
(
tenant
))
{
log
.
info
(
"登录企业:{} 不存在."
,
tenantId
);
RedisUtils
.
deleteObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phoneNumber
);
return
null
;
}
else
if
(
TenantStatus
.
DISABLE
.
getCode
().
equals
(
tenant
.
getStatus
()))
{
log
.
info
(
"登录企业:{} 已被停用."
,
tenant
.
getCompanyName
());
RedisUtils
.
deleteObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phoneNumber
);
return
null
;
}
else
if
(
ObjectUtil
.
isNotNull
(
tenant
.
getExpireTime
())
&&
new
Date
().
after
(
tenant
.
getExpireTime
()))
{
log
.
info
(
"登录企业:{} 已超过有效期."
,
tenant
.
getCompanyName
());
RedisUtils
.
deleteObject
(
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
phoneNumber
);
return
null
;
}
return
tenantId
;
}
public
List
<
SysTenantVo
>
tenantListByAccount
(
String
username
)
{
return
TenantHelper
.
ignore
(()
->
sysTenantService
.
selectTenantList
(
username
));
}
// public List<SysTenantVo> selectTenantList(String username){
//
// }
public
List
<
SysUser
>
queryListByPhone
(
String
username
)
{
return
TenantHelper
.
ignore
(()
->
{
List
<
SysUser
>
sysUsers
=
null
;
if
(
ReUtil
.
isMatch
(
RegexPool
.
MOBILE
,
username
))
{
LambdaQueryWrapper
<
SysUser
>
lqw
=
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getUserName
,
SysUser:
:
getStatus
,
SysUser:
:
getTenantId
,
SysUser:
:
getDelFlag
)
.
eq
(
SysUser:
:
getPhonenumber
,
username
)
.
orderByDesc
(
SysUser:
:
getUserId
);
// sysUsers = userMapper.selectUserByTenantPhone(username);
sysUsers
=
userMapper
.
selectList
(
lqw
);
}
else
{
LambdaQueryWrapper
<
SysUser
>
lqw
=
new
LambdaQueryWrapper
<
SysUser
>()
.
select
(
SysUser:
:
getUserName
,
SysUser:
:
getStatus
,
SysUser:
:
getTenantId
)
.
eq
(
SysUser:
:
getUserName
,
username
)
.
orderByDesc
(
SysUser:
:
getUserId
);
// sysUsers = userMapper.selectUserByTenantUsername(username);
sysUsers
=
userMapper
.
selectList
(
lqw
);
}
return
sysUsers
;
});
}
public
LoginVo
switchTenant
(
String
tenantId
)
{
//获取当前登录信息
Long
userId
=
LoginHelper
.
getUserId
();
Assert
.
notNull
(
userId
,
"企业切换失败!"
);
// 如果 切换租户和当前登录租户一致,仅保存默认租户
LoginUser
loginUserVo
=
LoginHelper
.
getLoginUser
();
if
(
tenantId
.
equals
(
loginUserVo
.
getTenantId
()))
{
//保存当前账号的默认租户
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
loginUserVo
.
getUserPhone
();
RedisUtils
.
setCacheObject
(
defaultTenantKey
,
tenantId
,
Duration
.
ofDays
(
90
));
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
}
SysUser
sysUser
=
TenantHelper
.
ignore
(()
->
{
return
userMapper
.
selectUserById
(
userId
);
});
Assert
.
notNull
(
sysUser
,
"用户信息为空,企业切换失败!"
);
if
(
StrUtil
.
isEmpty
(
sysUser
.
getPhonenumber
()))
{
Assert
.
notNull
(
sysUser
,
"用户手机号为空,企业切换失败!"
);
}
//退出登录
StpUtil
.
logout
();
String
tokenValue
=
StpUtil
.
getTokenValueByLoginId
(
userId
);
StpUtil
.
logoutByTokenValue
(
tokenValue
);
StpUtil
.
kickoutByTokenValue
(
tokenValue
);
// RedisUtils.deleteKeys("*"+tokenValue+"*");
//重新登录
TenantHelper
.
setTenantId
(
tenantId
);
String
username
=
sysUser
.
getPhonenumber
();
SysUser
user
=
loadUserByUsername
(
sysUser
.
getPhonenumber
());
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
LoginUser
loginUser
=
buildLoginUser
(
user
);
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
PC
);
log
.
info
(
"当前租户由"
+
sysUser
.
getTenantId
()
+
"切换为"
+
tenantId
);
//保存当前账号的默认租户
String
defaultTenantKey
=
GlobalConstants
.
PHONE_DEFAULT_TENANT
+
loginUser
.
getUserPhone
();
RedisUtils
.
setCacheObject
(
defaultTenantKey
,
tenantId
,
Duration
.
ofDays
(
90
));
recordLogininfor
(
username
,
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
username
);
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setTenantId
(
TenantHelper
.
getTenantId
());
loginVo
.
setAccessToken
(
StpUtil
.
getTokenValue
());
loginVo
.
setExpireIn
(
StpUtil
.
getTokenTimeout
());
return
loginVo
;
}
}
dsk-system/src/main/java/com/dsk/system/service/impl/ISysTenantServiceImpl.java
View file @
077f62f4
package
com
.
dsk
.
system
.
service
.
impl
;
import
cn.dev33.satoken.secure.BCrypt
;
import
cn.dev33.satoken.session.SaSession
;
import
cn.dev33.satoken.session.TokenSign
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.date.DateTime
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.RandomUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.CollectionUtils
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.dsk.common.constant.CacheNames
;
import
com.dsk.common.constant.Constants
;
import
com.dsk.common.constant.TenantConstants
;
import
com.dsk.common.constant.UserConstants
;
import
com.dsk.common.core.domain.PageQuery
;
import
com.dsk.common.core.domain.entity.SysDictData
;
import
com.dsk.common.core.domain.entity.SysDictType
;
import
com.dsk.common.core.page.TableDataInfo
;
import
com.dsk.common.enums.UserStatus
;
import
com.dsk.common.exception.ServiceException
;
import
com.dsk.common.utils.PasswordUtils
;
import
com.dsk.common.utils.StringUtils
;
import
com.dsk.common.utils.redis.RedisUtils
;
import
com.dsk.system.domain.*
;
import
com.dsk.system.domain.bo.SysTenantAdminBo
;
import
com.dsk.system.domain.bo.SysTenantBo
;
import
com.dsk.system.domain.vo.SysTenantVo
;
import
com.dsk.system.mapper.*
;
import
com.dsk.system.service.ISysTenantService
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.dromara.sms4j.api.SmsBlend
;
import
org.dromara.sms4j.api.entity.SmsResponse
;
import
org.dromara.sms4j.core.factory.SmsFactory
;
import
org.dromara.sms4j.provider.enumerate.SupplierType
;
import
org.springframework.cache.annotation.CacheEvict
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.*
;
/**
* 企业Service业务层处理
*
* @author sxk
* @date 2023.08.22
*/
@RequiredArgsConstructor
@Service
@Slf4j
public
class
ISysTenantServiceImpl
implements
ISysTenantService
{
private
final
SysTenantMapper
baseMapper
;
private
final
SysTenantPackageMapper
tenantPackageMapper
;
private
final
SysRoleMapper
roleMapper
;
private
final
SysRoleMenuMapper
roleMenuMapper
;
private
final
SysDeptMapper
deptMapper
;
private
final
SysRoleDeptMapper
roleDeptMapper
;
private
final
SysUserMapper
userMapper
;
private
final
SysUserRoleMapper
userRoleMapper
;
private
final
SysDictTypeMapper
dictTypeMapper
;
private
final
SysDictDataMapper
dictDataMapper
;
private
final
SysConfigMapper
configMapper
;
/**
* 查询租户列表
*/
@Override
public
TableDataInfo
<
SysTenantVo
>
queryPageList
(
SysTenantBo
bo
,
PageQuery
pageQuery
)
{
LambdaQueryWrapper
<
SysTenant
>
lqw
=
buildQueryWrapper
(
bo
);
pageQuery
.
setIsAsc
(
"desc"
);
pageQuery
.
setOrderByColumn
(
"createTime"
);
Page
<
SysTenantVo
>
result
=
baseMapper
.
selectVoPage
(
pageQuery
.
build
(),
lqw
);
for
(
SysTenantVo
sysTenantVo
:
result
.
getRecords
())
{
SysTenantPackage
sysTenantPackage
=
tenantPackageMapper
.
selectById
(
sysTenantVo
.
getPackageId
());
sysTenantVo
.
setPackageName
(
sysTenantPackage
.
getPackageName
());
}
return
TableDataInfo
.
build
(
result
);
}
/**
* 禁用所有已过期租户
*/
@Override
public
void
handleExpiredTenant
()
{
Date
now
=
new
Date
();
//查询所有已过期租户
List
<
SysTenant
>
tenantList
=
baseMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysTenant
>()
.
eq
(
SysTenant:
:
getStatus
,
TenantConstants
.
NORMAL
)
.
gt
(
SysTenant:
:
getStartTime
,
now
)
.
or
()
.
lt
(
SysTenant:
:
getExpireTime
,
now
));
//批量禁用已过期租户
if
(!
tenantList
.
isEmpty
())
{
tenantList
.
forEach
(
sysTenant
->
sysTenant
.
setStatus
(
TenantConstants
.
DISABLE
));
baseMapper
.
updateBatchById
(
tenantList
);
}
}
// /**
// * 查询租户列表
// */
// @Override
// public List<SysTenantVo> queryList(SysTenantBo bo) {
// LambdaQueryWrapper<SysTenant> lqw = buildQueryWrapper(bo);
// return baseMapper.selectVoList(lqw);
// }
/**
* 基于租户ID查询租户
*/
@Cacheable
(
cacheNames
=
CacheNames
.
SYS_TENANT
,
key
=
"#tenantId"
)
@Override
public
SysTenantVo
queryByTenantId
(
String
tenantId
)
{
return
baseMapper
.
selectVoOne
(
new
LambdaQueryWrapper
<
SysTenant
>().
eq
(
SysTenant:
:
getTenantId
,
tenantId
));
}
@Override
public
List
<
SysTenantVo
>
selectTenantList
(
String
username
)
{
return
baseMapper
.
selectTenantList
(
username
);
}
private
LambdaQueryWrapper
<
SysTenant
>
buildQueryWrapper
(
SysTenantBo
bo
)
{
LambdaQueryWrapper
<
SysTenant
>
lqw
=
Wrappers
.
lambdaQuery
();
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getTenantId
()),
SysTenant:
:
getTenantId
,
bo
.
getTenantId
());
lqw
.
like
(
StringUtils
.
isNotBlank
(
bo
.
getContactUserName
()),
SysTenant:
:
getContactUserName
,
bo
.
getContactUserName
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getContactPhone
()),
SysTenant:
:
getContactPhone
,
bo
.
getContactPhone
());
lqw
.
like
(
StringUtils
.
isNotBlank
(
bo
.
getCompanyName
()),
SysTenant:
:
getCompanyName
,
bo
.
getCompanyName
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getLicenseNumber
()),
SysTenant:
:
getLicenseNumber
,
bo
.
getLicenseNumber
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getAddress
()),
SysTenant:
:
getAddress
,
bo
.
getAddress
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getIntro
()),
SysTenant:
:
getIntro
,
bo
.
getIntro
());
lqw
.
like
(
StringUtils
.
isNotBlank
(
bo
.
getDomain
()),
SysTenant:
:
getDomain
,
bo
.
getDomain
());
lqw
.
eq
(
bo
.
getPackageId
()
!=
null
,
SysTenant:
:
getPackageId
,
bo
.
getPackageId
());
lqw
.
eq
(
bo
.
getExpireTime
()
!=
null
,
SysTenant:
:
getExpireTime
,
bo
.
getExpireTime
());
lqw
.
eq
(
bo
.
getAccountCount
()
!=
null
,
SysTenant:
:
getAccountCount
,
bo
.
getAccountCount
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getStatus
()),
SysTenant:
:
getStatus
,
bo
.
getStatus
());
return
lqw
;
}
/**
* 查询租户
*/
@Override
public
SysTenantVo
queryById
(
Long
id
)
{
return
baseMapper
.
selectVoById
(
id
);
}
/**
* 校验企业名称是否唯一
*/
@Override
public
boolean
checkCompanyNameUnique
(
SysTenantBo
bo
)
{
boolean
exist
=
baseMapper
.
exists
(
new
LambdaQueryWrapper
<
SysTenant
>()
.
eq
(
SysTenant:
:
getCompanyName
,
bo
.
getCompanyName
())
.
ne
(
ObjectUtil
.
isNotNull
(
bo
.
getTenantId
()),
SysTenant:
:
getTenantId
,
bo
.
getTenantId
()));
return
!
exist
;
}
/**
* 新增租户
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
insertByBo
(
SysTenantBo
bo
)
{
SysTenant
add
=
BeanUtil
.
toBean
(
bo
,
SysTenant
.
class
);
// 获取所有租户编号
List
<
String
>
tenantIds
=
baseMapper
.
selectObjs
(
new
LambdaQueryWrapper
<
SysTenant
>().
select
(
SysTenant:
:
getTenantId
),
Convert:
:
toStr
);
String
tenantId
=
generateTenantId
(
tenantIds
);
add
.
setTenantId
(
tenantId
);
boolean
flag
=
baseMapper
.
insert
(
add
)
>
0
;
if
(!
flag
)
{
throw
new
ServiceException
(
"创建租户失败"
);
}
bo
.
setId
(
add
.
getId
());
// 根据套餐创建角色
Long
roleId
=
createTenantRole
(
tenantId
,
bo
.
getPackageId
(),
TenantConstants
.
TENANT_SUPER_ADMIN_ROLE_NAME
,
TenantConstants
.
TENANT_SUPER_ADMIN_ROLE_KEY
);
// 创建部门: 公司名是部门名称
SysDept
dept
=
new
SysDept
();
dept
.
setTenantId
(
tenantId
);
dept
.
setDeptName
(
bo
.
getCompanyName
());
dept
.
setParentId
(
Constants
.
TOP_PARENT_ID
);
dept
.
setAncestors
(
Constants
.
TOP_PARENT_ID
.
toString
());
deptMapper
.
insert
(
dept
);
Long
deptId
=
dept
.
getDeptId
();
// 角色和部门关联表
SysRoleDept
roleDept
=
new
SysRoleDept
();
roleDept
.
setRoleId
(
roleId
);
roleDept
.
setDeptId
(
deptId
);
roleDeptMapper
.
insert
(
roleDept
);
// 创建系统用户
SysUser
user
=
new
SysUser
();
user
.
setTenantId
(
tenantId
);
user
.
setPhonenumber
(
bo
.
getContactPhone
());
//默认新增用户名为手机号
user
.
setUserName
(
bo
.
getContactPhone
());
user
.
setNickName
(
bo
.
getContactUserName
());
//生成8位随机密码
String
password
=
PasswordUtils
.
generatePwd
(
8
);
user
.
setPassword
(
BCrypt
.
hashpw
(
password
));
user
.
setDeptId
(
deptId
);
user
.
setCreateTime
(
new
DateTime
());
userMapper
.
insert
(
user
);
//新增系统用户后,默认当前用户为部门的负责人
SysDept
sd
=
new
SysDept
();
sd
.
setLeader
(
String
.
valueOf
(
user
.
getUserId
()));
sd
.
setDeptId
(
deptId
);
deptMapper
.
updateById
(
sd
);
// 用户和角色关联表
SysUserRole
userRole
=
new
SysUserRole
();
userRole
.
setUserId
(
user
.
getUserId
());
userRole
.
setRoleId
(
roleId
);
userRoleMapper
.
insert
(
userRole
);
String
defaultTenantId
=
TenantConstants
.
DEFAULT_TENANT_ID
;
List
<
SysDictType
>
dictTypeList
=
dictTypeMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysDictType
>().
eq
(
SysDictType:
:
getTenantId
,
defaultTenantId
));
List
<
SysDictData
>
dictDataList
=
dictDataMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysDictData
>().
eq
(
SysDictData:
:
getTenantId
,
defaultTenantId
));
for
(
SysDictType
dictType
:
dictTypeList
)
{
dictType
.
setDictId
(
null
);
dictType
.
setTenantId
(
tenantId
);
}
for
(
SysDictData
dictData
:
dictDataList
)
{
dictData
.
setDictCode
(
null
);
dictData
.
setTenantId
(
tenantId
);
}
dictTypeMapper
.
insertBatch
(
dictTypeList
);
dictDataMapper
.
insertBatch
(
dictDataList
);
List
<
SysConfig
>
sysConfigList
=
configMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysConfig
>()
.
eq
(
SysConfig:
:
getTenantId
,
defaultTenantId
)
.
eq
(
SysConfig:
:
getConfigType
,
"Y"
));
for
(
SysConfig
config
:
sysConfigList
)
{
config
.
setConfigId
(
null
);
config
.
setTenantId
(
tenantId
);
}
configMapper
.
insertBatch
(
sysConfigList
);
////此处暂用钉钉机器人模拟发送短信
//String content = "【短信通知】:"
// + bo.getContactUserName()
// + ",您好,您已经成功开通数字化经营管理系统,请使用手机号码登录,初始密码为"
// + password
// + "。友情提示:为了您的账号安全,请勿泄露密码。";
//DingTalkUtil.sendDingTalkMsg(content);
//租户新增成功,发送短信通知租户
LinkedHashMap
<
String
,
String
>
map
=
new
LinkedHashMap
<>(
1
);
map
.
put
(
"company"
,
bo
.
getContactUserName
());
map
.
put
(
"pwd"
,
password
);
SmsBlend
smsBlend
=
SmsFactory
.
createSmsBlend
(
SupplierType
.
ALIBABA
);
SmsResponse
smsResponse
=
smsBlend
.
sendMessage
(
bo
.
getContactPhone
(),
"SMS_463175230"
,
map
);
if
(!
"OK"
.
equals
(
smsResponse
.
getCode
()))
{
log
.
error
(
"新增租户通知短信发送异常 => {}"
,
smsResponse
);
}
return
true
;
}
/**
* 新增企业普通管理员账号
*
* @param tenantAdminBo 用户信息
* @return 结果
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
addTenantAdmin
(
SysTenantAdminBo
tenantAdminBo
)
{
String
tenantId
=
tenantAdminBo
.
getTenantId
();
//获取部门ID
Long
deptId
=
deptMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysDept
>()
.
eq
(
SysDept:
:
getTenantId
,
tenantId
)).
getDeptId
();
SysRole
sysRole
=
roleMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysRole
>()
.
eq
(
SysRole:
:
getStatus
,
UserConstants
.
ROLE_NORMAL
)
.
eq
(
SysRole:
:
getDelFlag
,
UserConstants
.
ROLE_NORMAL
)
.
eq
(
SysRole:
:
getTenantId
,
tenantId
)
.
eq
(
SysRole:
:
getRoleKey
,
TenantConstants
.
TENANT_ADMIN_ROLE_KEY
));
Long
roleId
=
null
;
//校验当前企业是否已存在普通管理员角色
if
(
ObjectUtil
.
isNull
(
sysRole
))
{
//不存在,则根据套餐创建角色
roleId
=
createTenantRole
(
tenantId
,
tenantAdminBo
.
getPackageId
(),
TenantConstants
.
TENANT_ADMIN_ROLE_NAME
,
TenantConstants
.
TENANT_ADMIN_ROLE_KEY
);
// 角色和部门关联表
SysRoleDept
roleDept
=
new
SysRoleDept
();
roleDept
.
setRoleId
(
roleId
);
roleDept
.
setDeptId
(
deptId
);
roleDeptMapper
.
insert
(
roleDept
);
}
else
{
roleId
=
sysRole
.
getRoleId
();
}
// 创建系统用户
SysUser
user
=
new
SysUser
();
user
.
setTenantId
(
tenantId
);
user
.
setPhonenumber
(
tenantAdminBo
.
getPhonenumber
());
//默认新增用户名为手机号
user
.
setUserName
(
tenantAdminBo
.
getPhonenumber
());
user
.
setNickName
(
tenantAdminBo
.
getNickName
());
//生成8位随机密码
String
password
=
PasswordUtils
.
generatePwd
(
8
);
user
.
setPassword
(
BCrypt
.
hashpw
(
password
));
user
.
setDeptId
(
deptId
);
user
.
setCreateTime
(
new
DateTime
());
userMapper
.
insert
(
user
);
// 用户和角色关联表
SysUserRole
userRole
=
new
SysUserRole
();
userRole
.
setUserId
(
user
.
getUserId
());
userRole
.
setRoleId
(
roleId
);
userRoleMapper
.
insert
(
userRole
);
List
<
SysConfig
>
sysConfigList
=
configMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysConfig
>()
.
eq
(
SysConfig:
:
getTenantId
,
TenantConstants
.
DEFAULT_TENANT_ID
)
.
eq
(
SysConfig:
:
getConfigType
,
"Y"
));
for
(
SysConfig
config
:
sysConfigList
)
{
config
.
setConfigId
(
null
);
config
.
setTenantId
(
tenantId
);
}
configMapper
.
insertBatch
(
sysConfigList
);
//管理员新增成功,发送短信通知用户
LinkedHashMap
<
String
,
String
>
map
=
new
LinkedHashMap
<>(
1
);
map
.
put
(
"company"
,
tenantAdminBo
.
getNickName
());
map
.
put
(
"pwd"
,
password
);
SmsBlend
smsBlend
=
SmsFactory
.
createSmsBlend
(
SupplierType
.
ALIBABA
);
SmsResponse
smsResponse
=
smsBlend
.
sendMessage
(
tenantAdminBo
.
getPhonenumber
(),
"SMS_463175230"
,
map
);
if
(!
"OK"
.
equals
(
smsResponse
.
getCode
()))
{
log
.
error
(
"新增租户通知短信发送异常 => {}"
,
smsResponse
);
}
return
true
;
}
/**
* 生成租户id
*
* @param tenantIds 已有租户id列表
* @return 租户id
*/
private
String
generateTenantId
(
List
<
String
>
tenantIds
)
{
// 随机生成6位
String
numbers
=
RandomUtil
.
randomNumbers
(
6
);
// 判断是否存在,如果存在则重新生成
if
(
tenantIds
.
contains
(
numbers
))
{
generateTenantId
(
tenantIds
);
}
return
numbers
;
}
/**
* 根据租户菜单创建租户角色
*
* @param tenantId 租户编号
* @param packageId 租户套餐id
* @return 角色id
*/
private
Long
createTenantRole
(
String
tenantId
,
Long
packageId
,
String
roleName
,
String
roleKey
)
{
// 获取租户套餐
SysTenantPackage
tenantPackage
=
tenantPackageMapper
.
selectById
(
packageId
);
if
(
ObjectUtil
.
isNull
(
tenantPackage
))
{
throw
new
ServiceException
(
"套餐不存在"
);
}
// 获取套餐菜单id
List
<
Long
>
menuIds
=
StringUtils
.
splitTo
(
tenantPackage
.
getMenuIds
(),
Convert:
:
toLong
);
// 创建角色
SysRole
role
=
new
SysRole
();
role
.
setTenantId
(
tenantId
);
role
.
setRoleName
(
roleName
);
role
.
setRoleKey
(
roleKey
);
role
.
setRoleSort
(
1
);
role
.
setStatus
(
TenantConstants
.
NORMAL
);
roleMapper
.
insert
(
role
);
Long
roleId
=
role
.
getRoleId
();
// 创建角色菜单
List
<
SysRoleMenu
>
roleMenus
=
new
ArrayList
<>(
menuIds
.
size
());
menuIds
.
forEach
(
menuId
->
{
SysRoleMenu
roleMenu
=
new
SysRoleMenu
();
roleMenu
.
setRoleId
(
roleId
);
roleMenu
.
setMenuId
(
menuId
);
roleMenus
.
add
(
roleMenu
);
});
roleMenuMapper
.
insertBatch
(
roleMenus
);
return
roleId
;
}
/**
* 校验租户是否允许操作
*
* @param tenantId 租户ID
*/
@Override
public
void
checkTenantAllowed
(
String
tenantId
)
{
if
(
ObjectUtil
.
isNotNull
(
tenantId
)
&&
TenantConstants
.
DEFAULT_TENANT_ID
.
equals
(
tenantId
))
{
throw
new
ServiceException
(
"不允许操作管理租户"
);
}
}
/**
* 修改租户
*/
@Override
@CacheEvict
(
cacheNames
=
CacheNames
.
SYS_TENANT
,
key
=
"#bo.tenantId"
)
public
Boolean
updateByBo
(
SysTenantBo
bo
)
{
SysTenant
tenant
=
BeanUtil
.
toBean
(
bo
,
SysTenant
.
class
);
if
(
TenantConstants
.
DISABLE
.
equals
(
bo
.
getStatus
()))
{
tenant
.
setExpireTime
(
new
DateTime
());
}
tenant
.
setTenantId
(
null
);
return
baseMapper
.
updateById
(
tenant
)
>
0
;
}
// /**
// * 修改租户状态
// *
// * @param bo 租户信息
// * @return 结果
// */
// @Override
// @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#bo.tenantId")
// public int updateTenantStatus(SysTenantBo bo) {
// SysTenant tenant = MapStructUtils.convert(bo, SysTenant.class);
// return baseMapper.updateById(tenant);
// }
/**
* 校验并批量删除租户信息
*/
@Override
@CacheEvict
(
cacheNames
=
CacheNames
.
SYS_TENANT
,
allEntries
=
true
)
public
Boolean
deleteWithValidByIds
(
Collection
<
Long
>
ids
,
Boolean
isValid
)
{
if
(
isValid
)
{
// 做一些业务上的校验,判断是否需要校验
if
(
ids
.
contains
(
TenantConstants
.
SUPER_ADMIN_ID
))
{
throw
new
ServiceException
(
"超管租户不能删除"
);
}
}
return
baseMapper
.
deleteBatchIds
(
ids
)
>
0
;
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
syncTenantPackage
(
String
tenantId
,
Long
packageId
)
{
SysTenantPackage
tenantPackage
=
tenantPackageMapper
.
selectById
(
packageId
);
List
<
SysRole
>
roles
=
roleMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysRole
>().
eq
(
SysRole:
:
getTenantId
,
tenantId
));
List
<
Long
>
roleIds
=
new
ArrayList
<>(
roles
.
size
()
-
1
);
List
<
Long
>
menuIds
=
StringUtils
.
splitTo
(
tenantPackage
.
getMenuIds
(),
Convert:
:
toLong
);
roles
.
forEach
(
item
->
{
if
(
TenantConstants
.
TENANT_SUPER_ADMIN_ROLE_KEY
.
equals
(
item
.
getRoleKey
()))
{
List
<
SysRoleMenu
>
roleMenus
=
new
ArrayList
<>(
menuIds
.
size
());
menuIds
.
forEach
(
menuId
->
{
SysRoleMenu
roleMenu
=
new
SysRoleMenu
();
roleMenu
.
setRoleId
(
item
.
getRoleId
());
roleMenu
.
setMenuId
(
menuId
);
roleMenus
.
add
(
roleMenu
);
});
roleMenuMapper
.
delete
(
new
LambdaQueryWrapper
<
SysRoleMenu
>().
eq
(
SysRoleMenu:
:
getRoleId
,
item
.
getRoleId
()));
roleMenuMapper
.
insertBatch
(
roleMenus
);
}
else
{
roleIds
.
add
(
item
.
getRoleId
());
}
});
if
(!
roleIds
.
isEmpty
())
{
roleMenuMapper
.
delete
(
new
LambdaQueryWrapper
<
SysRoleMenu
>().
in
(
SysRoleMenu:
:
getRoleId
,
roleIds
).
notIn
(!
menuIds
.
isEmpty
(),
SysRoleMenu:
:
getMenuId
,
menuIds
));
}
try
{
//清除企业用户登录信息
List
<
SysUser
>
tenantUsers
=
userMapper
.
selectList
(
Wrappers
.<
SysUser
>
lambdaQuery
()
.
eq
(
SysUser:
:
getTenantId
,
tenantId
).
eq
(
SysUser:
:
getStatus
,
UserStatus
.
OK
.
getCode
()));
if
(!
CollectionUtils
.
isEmpty
(
tenantUsers
))
{
for
(
SysUser
tenantUser
:
tenantUsers
)
{
String
key
=
"global:Authorization:login:session:00:"
+
tenantUser
.
getUserId
();
if
(
RedisUtils
.
hasKey
(
key
))
{
SaSession
session
=
RedisUtils
.
getCacheObject
(
key
);
List
<
TokenSign
>
tokenSignList
=
session
.
getTokenSignList
();
tokenSignList
.
forEach
(
sign
->
StpUtil
.
kickoutByTokenValue
(
sign
.
getValue
()));
}
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"清除企业用户登录信息操作失败!error={}"
,
e
.
getMessage
());
}
return
true
;
}
}
package
com
.
dsk
.
system
.
service
.
impl
;
import
cn.dev33.satoken.secure.BCrypt
;
import
cn.dev33.satoken.session.SaSession
;
import
cn.dev33.satoken.session.TokenSign
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.date.DateTime
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.RandomUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.CollectionUtils
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.dsk.common.constant.CacheNames
;
import
com.dsk.common.constant.Constants
;
import
com.dsk.common.constant.TenantConstants
;
import
com.dsk.common.constant.UserConstants
;
import
com.dsk.common.core.domain.PageQuery
;
import
com.dsk.common.core.domain.entity.SysDictData
;
import
com.dsk.common.core.domain.entity.SysDictType
;
import
com.dsk.common.core.page.TableDataInfo
;
import
com.dsk.common.enums.UserStatus
;
import
com.dsk.common.exception.ServiceException
;
import
com.dsk.common.utils.DingTalkUtil
;
import
com.dsk.common.utils.PasswordUtils
;
import
com.dsk.common.utils.StringUtils
;
import
com.dsk.common.utils.redis.RedisUtils
;
import
com.dsk.system.domain.*
;
import
com.dsk.system.domain.bo.SysTenantAdminBo
;
import
com.dsk.system.domain.bo.SysTenantBo
;
import
com.dsk.system.domain.vo.SysTenantVo
;
import
com.dsk.system.mapper.*
;
import
com.dsk.system.service.ISysTenantService
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.dromara.sms4j.api.SmsBlend
;
import
org.dromara.sms4j.api.entity.SmsResponse
;
import
org.dromara.sms4j.core.factory.SmsFactory
;
import
org.dromara.sms4j.provider.enumerate.SupplierType
;
import
org.springframework.cache.annotation.CacheEvict
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.*
;
/**
* 企业Service业务层处理
*
* @author sxk
* @date 2023.08.22
*/
@RequiredArgsConstructor
@Service
@Slf4j
public
class
ISysTenantServiceImpl
implements
ISysTenantService
{
private
final
SysTenantMapper
baseMapper
;
private
final
SysTenantPackageMapper
tenantPackageMapper
;
private
final
SysRoleMapper
roleMapper
;
private
final
SysRoleMenuMapper
roleMenuMapper
;
private
final
SysDeptMapper
deptMapper
;
private
final
SysRoleDeptMapper
roleDeptMapper
;
private
final
SysUserMapper
userMapper
;
private
final
SysUserRoleMapper
userRoleMapper
;
private
final
SysDictTypeMapper
dictTypeMapper
;
private
final
SysDictDataMapper
dictDataMapper
;
private
final
SysConfigMapper
configMapper
;
/**
* 查询租户列表
*/
@Override
public
TableDataInfo
<
SysTenantVo
>
queryPageList
(
SysTenantBo
bo
,
PageQuery
pageQuery
)
{
LambdaQueryWrapper
<
SysTenant
>
lqw
=
buildQueryWrapper
(
bo
);
pageQuery
.
setIsAsc
(
"desc"
);
pageQuery
.
setOrderByColumn
(
"createTime"
);
Page
<
SysTenantVo
>
result
=
baseMapper
.
selectVoPage
(
pageQuery
.
build
(),
lqw
);
for
(
SysTenantVo
sysTenantVo
:
result
.
getRecords
())
{
SysTenantPackage
sysTenantPackage
=
tenantPackageMapper
.
selectById
(
sysTenantVo
.
getPackageId
());
sysTenantVo
.
setPackageName
(
sysTenantPackage
.
getPackageName
());
}
return
TableDataInfo
.
build
(
result
);
}
/**
* 禁用所有已过期租户
*/
@Override
public
void
handleExpiredTenant
()
{
Date
now
=
new
Date
();
//查询所有已过期租户
List
<
SysTenant
>
tenantList
=
baseMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysTenant
>()
.
eq
(
SysTenant:
:
getStatus
,
TenantConstants
.
NORMAL
)
.
gt
(
SysTenant:
:
getStartTime
,
now
)
.
or
()
.
lt
(
SysTenant:
:
getExpireTime
,
now
));
//批量禁用已过期租户
if
(!
tenantList
.
isEmpty
())
{
tenantList
.
forEach
(
sysTenant
->
sysTenant
.
setStatus
(
TenantConstants
.
DISABLE
));
baseMapper
.
updateBatchById
(
tenantList
);
}
}
// /**
// * 查询租户列表
// */
// @Override
// public List<SysTenantVo> queryList(SysTenantBo bo) {
// LambdaQueryWrapper<SysTenant> lqw = buildQueryWrapper(bo);
// return baseMapper.selectVoList(lqw);
// }
/**
* 基于租户ID查询租户
*/
@Cacheable
(
cacheNames
=
CacheNames
.
SYS_TENANT
,
key
=
"#tenantId"
)
@Override
public
SysTenantVo
queryByTenantId
(
String
tenantId
)
{
return
baseMapper
.
selectVoOne
(
new
LambdaQueryWrapper
<
SysTenant
>().
eq
(
SysTenant:
:
getTenantId
,
tenantId
));
}
@Override
public
List
<
SysTenantVo
>
selectTenantList
(
String
username
)
{
return
baseMapper
.
selectTenantList
(
username
);
}
private
LambdaQueryWrapper
<
SysTenant
>
buildQueryWrapper
(
SysTenantBo
bo
)
{
LambdaQueryWrapper
<
SysTenant
>
lqw
=
Wrappers
.
lambdaQuery
();
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getTenantId
()),
SysTenant:
:
getTenantId
,
bo
.
getTenantId
());
lqw
.
like
(
StringUtils
.
isNotBlank
(
bo
.
getContactUserName
()),
SysTenant:
:
getContactUserName
,
bo
.
getContactUserName
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getContactPhone
()),
SysTenant:
:
getContactPhone
,
bo
.
getContactPhone
());
lqw
.
like
(
StringUtils
.
isNotBlank
(
bo
.
getCompanyName
()),
SysTenant:
:
getCompanyName
,
bo
.
getCompanyName
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getLicenseNumber
()),
SysTenant:
:
getLicenseNumber
,
bo
.
getLicenseNumber
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getAddress
()),
SysTenant:
:
getAddress
,
bo
.
getAddress
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getIntro
()),
SysTenant:
:
getIntro
,
bo
.
getIntro
());
lqw
.
like
(
StringUtils
.
isNotBlank
(
bo
.
getDomain
()),
SysTenant:
:
getDomain
,
bo
.
getDomain
());
lqw
.
eq
(
bo
.
getPackageId
()
!=
null
,
SysTenant:
:
getPackageId
,
bo
.
getPackageId
());
lqw
.
eq
(
bo
.
getExpireTime
()
!=
null
,
SysTenant:
:
getExpireTime
,
bo
.
getExpireTime
());
lqw
.
eq
(
bo
.
getAccountCount
()
!=
null
,
SysTenant:
:
getAccountCount
,
bo
.
getAccountCount
());
lqw
.
eq
(
StringUtils
.
isNotBlank
(
bo
.
getStatus
()),
SysTenant:
:
getStatus
,
bo
.
getStatus
());
return
lqw
;
}
/**
* 查询租户
*/
@Override
public
SysTenantVo
queryById
(
Long
id
)
{
return
baseMapper
.
selectVoById
(
id
);
}
/**
* 校验企业名称是否唯一
*/
@Override
public
boolean
checkCompanyNameUnique
(
SysTenantBo
bo
)
{
boolean
exist
=
baseMapper
.
exists
(
new
LambdaQueryWrapper
<
SysTenant
>()
.
eq
(
SysTenant:
:
getCompanyName
,
bo
.
getCompanyName
())
.
ne
(
ObjectUtil
.
isNotNull
(
bo
.
getTenantId
()),
SysTenant:
:
getTenantId
,
bo
.
getTenantId
()));
return
!
exist
;
}
/**
* 新增租户
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
insertByBo
(
SysTenantBo
bo
)
{
SysTenant
add
=
BeanUtil
.
toBean
(
bo
,
SysTenant
.
class
);
// 获取所有租户编号
List
<
String
>
tenantIds
=
baseMapper
.
selectObjs
(
new
LambdaQueryWrapper
<
SysTenant
>().
select
(
SysTenant:
:
getTenantId
),
Convert:
:
toStr
);
String
tenantId
=
generateTenantId
(
tenantIds
);
add
.
setTenantId
(
tenantId
);
boolean
flag
=
baseMapper
.
insert
(
add
)
>
0
;
if
(!
flag
)
{
throw
new
ServiceException
(
"创建租户失败"
);
}
bo
.
setId
(
add
.
getId
());
// 根据套餐创建角色
Long
roleId
=
createTenantRole
(
tenantId
,
bo
.
getPackageId
(),
TenantConstants
.
TENANT_SUPER_ADMIN_ROLE_NAME
,
TenantConstants
.
TENANT_SUPER_ADMIN_ROLE_KEY
);
// 创建部门: 公司名是部门名称
SysDept
dept
=
new
SysDept
();
dept
.
setTenantId
(
tenantId
);
dept
.
setDeptName
(
bo
.
getCompanyName
());
dept
.
setParentId
(
Constants
.
TOP_PARENT_ID
);
dept
.
setAncestors
(
Constants
.
TOP_PARENT_ID
.
toString
());
deptMapper
.
insert
(
dept
);
Long
deptId
=
dept
.
getDeptId
();
// 角色和部门关联表
SysRoleDept
roleDept
=
new
SysRoleDept
();
roleDept
.
setRoleId
(
roleId
);
roleDept
.
setDeptId
(
deptId
);
roleDeptMapper
.
insert
(
roleDept
);
// 创建系统用户
SysUser
user
=
new
SysUser
();
user
.
setTenantId
(
tenantId
);
String
thirdPlatformKey
=
UUID
.
randomUUID
().
toString
();
user
.
setThirdPlatformKey
(
thirdPlatformKey
);
user
.
setPhonenumber
(
bo
.
getContactPhone
());
//默认新增用户名为手机号
user
.
setUserName
(
bo
.
getContactPhone
());
user
.
setNickName
(
bo
.
getContactUserName
());
//生成8位随机密码
String
password
=
PasswordUtils
.
generatePwd
(
8
);
user
.
setPassword
(
BCrypt
.
hashpw
(
password
));
user
.
setDeptId
(
deptId
);
user
.
setCreateTime
(
new
DateTime
());
userMapper
.
insert
(
user
);
//新增系统用户后,默认当前用户为部门的负责人
SysDept
sd
=
new
SysDept
();
sd
.
setLeader
(
String
.
valueOf
(
user
.
getUserId
()));
sd
.
setDeptId
(
deptId
);
deptMapper
.
updateById
(
sd
);
// 用户和角色关联表
SysUserRole
userRole
=
new
SysUserRole
();
userRole
.
setUserId
(
user
.
getUserId
());
userRole
.
setRoleId
(
roleId
);
userRoleMapper
.
insert
(
userRole
);
String
defaultTenantId
=
TenantConstants
.
DEFAULT_TENANT_ID
;
List
<
SysDictType
>
dictTypeList
=
dictTypeMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysDictType
>().
eq
(
SysDictType:
:
getTenantId
,
defaultTenantId
));
List
<
SysDictData
>
dictDataList
=
dictDataMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysDictData
>().
eq
(
SysDictData:
:
getTenantId
,
defaultTenantId
));
for
(
SysDictType
dictType
:
dictTypeList
)
{
dictType
.
setDictId
(
null
);
dictType
.
setTenantId
(
tenantId
);
}
for
(
SysDictData
dictData
:
dictDataList
)
{
dictData
.
setDictCode
(
null
);
dictData
.
setTenantId
(
tenantId
);
}
dictTypeMapper
.
insertBatch
(
dictTypeList
);
dictDataMapper
.
insertBatch
(
dictDataList
);
List
<
SysConfig
>
sysConfigList
=
configMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysConfig
>()
.
eq
(
SysConfig:
:
getTenantId
,
defaultTenantId
)
.
eq
(
SysConfig:
:
getConfigType
,
"Y"
));
for
(
SysConfig
config
:
sysConfigList
)
{
config
.
setConfigId
(
null
);
config
.
setTenantId
(
tenantId
);
}
configMapper
.
insertBatch
(
sysConfigList
);
//此处暂用钉钉机器人模拟发送短信
String
content
=
"【短信通知】:"
+
bo
.
getContactUserName
()
+
",您好,您已经成功开通数字化经营管理系统,请使用手机号码登录,初始密码为"
+
password
+
",三方平台登录秘钥为"
+
thirdPlatformKey
+
"。友情提示:为了您的账号安全,请勿泄露密码。"
;
DingTalkUtil
.
sendDingTalkMsg
(
content
);
//租户新增成功,发送短信通知租户
LinkedHashMap
<
String
,
String
>
map
=
new
LinkedHashMap
<>(
1
);
map
.
put
(
"company"
,
bo
.
getContactUserName
());
map
.
put
(
"pwd"
,
password
);
SmsBlend
smsBlend
=
SmsFactory
.
createSmsBlend
(
SupplierType
.
ALIBABA
);
SmsResponse
smsResponse
=
smsBlend
.
sendMessage
(
bo
.
getContactPhone
(),
"SMS_463175230"
,
map
);
if
(!
"OK"
.
equals
(
smsResponse
.
getCode
()))
{
log
.
error
(
"新增租户通知短信发送异常 => {}"
,
smsResponse
);
}
return
true
;
}
/**
* 新增企业普通管理员账号
*
* @param tenantAdminBo 用户信息
* @return 结果
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
addTenantAdmin
(
SysTenantAdminBo
tenantAdminBo
)
{
String
tenantId
=
tenantAdminBo
.
getTenantId
();
//获取部门ID
Long
deptId
=
deptMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysDept
>()
.
eq
(
SysDept:
:
getTenantId
,
tenantId
)).
getDeptId
();
SysRole
sysRole
=
roleMapper
.
selectOne
(
new
LambdaQueryWrapper
<
SysRole
>()
.
eq
(
SysRole:
:
getStatus
,
UserConstants
.
ROLE_NORMAL
)
.
eq
(
SysRole:
:
getDelFlag
,
UserConstants
.
ROLE_NORMAL
)
.
eq
(
SysRole:
:
getTenantId
,
tenantId
)
.
eq
(
SysRole:
:
getRoleKey
,
TenantConstants
.
TENANT_ADMIN_ROLE_KEY
));
Long
roleId
=
null
;
//校验当前企业是否已存在普通管理员角色
if
(
ObjectUtil
.
isNull
(
sysRole
))
{
//不存在,则根据套餐创建角色
roleId
=
createTenantRole
(
tenantId
,
tenantAdminBo
.
getPackageId
(),
TenantConstants
.
TENANT_ADMIN_ROLE_NAME
,
TenantConstants
.
TENANT_ADMIN_ROLE_KEY
);
// 角色和部门关联表
SysRoleDept
roleDept
=
new
SysRoleDept
();
roleDept
.
setRoleId
(
roleId
);
roleDept
.
setDeptId
(
deptId
);
roleDeptMapper
.
insert
(
roleDept
);
}
else
{
roleId
=
sysRole
.
getRoleId
();
}
// 创建系统用户
SysUser
user
=
new
SysUser
();
user
.
setTenantId
(
tenantId
);
user
.
setPhonenumber
(
tenantAdminBo
.
getPhonenumber
());
//默认新增用户名为手机号
user
.
setUserName
(
tenantAdminBo
.
getPhonenumber
());
user
.
setNickName
(
tenantAdminBo
.
getNickName
());
//生成8位随机密码
String
password
=
PasswordUtils
.
generatePwd
(
8
);
user
.
setPassword
(
BCrypt
.
hashpw
(
password
));
user
.
setDeptId
(
deptId
);
user
.
setCreateTime
(
new
DateTime
());
userMapper
.
insert
(
user
);
// 用户和角色关联表
SysUserRole
userRole
=
new
SysUserRole
();
userRole
.
setUserId
(
user
.
getUserId
());
userRole
.
setRoleId
(
roleId
);
userRoleMapper
.
insert
(
userRole
);
List
<
SysConfig
>
sysConfigList
=
configMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysConfig
>()
.
eq
(
SysConfig:
:
getTenantId
,
TenantConstants
.
DEFAULT_TENANT_ID
)
.
eq
(
SysConfig:
:
getConfigType
,
"Y"
));
for
(
SysConfig
config
:
sysConfigList
)
{
config
.
setConfigId
(
null
);
config
.
setTenantId
(
tenantId
);
}
configMapper
.
insertBatch
(
sysConfigList
);
//管理员新增成功,发送短信通知用户
LinkedHashMap
<
String
,
String
>
map
=
new
LinkedHashMap
<>(
1
);
map
.
put
(
"company"
,
tenantAdminBo
.
getNickName
());
map
.
put
(
"pwd"
,
password
);
SmsBlend
smsBlend
=
SmsFactory
.
createSmsBlend
(
SupplierType
.
ALIBABA
);
SmsResponse
smsResponse
=
smsBlend
.
sendMessage
(
tenantAdminBo
.
getPhonenumber
(),
"SMS_463175230"
,
map
);
if
(!
"OK"
.
equals
(
smsResponse
.
getCode
()))
{
log
.
error
(
"新增租户通知短信发送异常 => {}"
,
smsResponse
);
}
return
true
;
}
/**
* 生成租户id
*
* @param tenantIds 已有租户id列表
* @return 租户id
*/
private
String
generateTenantId
(
List
<
String
>
tenantIds
)
{
// 随机生成6位
String
numbers
=
RandomUtil
.
randomNumbers
(
6
);
// 判断是否存在,如果存在则重新生成
if
(
tenantIds
.
contains
(
numbers
))
{
generateTenantId
(
tenantIds
);
}
return
numbers
;
}
/**
* 根据租户菜单创建租户角色
*
* @param tenantId 租户编号
* @param packageId 租户套餐id
* @return 角色id
*/
private
Long
createTenantRole
(
String
tenantId
,
Long
packageId
,
String
roleName
,
String
roleKey
)
{
// 获取租户套餐
SysTenantPackage
tenantPackage
=
tenantPackageMapper
.
selectById
(
packageId
);
if
(
ObjectUtil
.
isNull
(
tenantPackage
))
{
throw
new
ServiceException
(
"套餐不存在"
);
}
// 获取套餐菜单id
List
<
Long
>
menuIds
=
StringUtils
.
splitTo
(
tenantPackage
.
getMenuIds
(),
Convert:
:
toLong
);
// 创建角色
SysRole
role
=
new
SysRole
();
role
.
setTenantId
(
tenantId
);
role
.
setRoleName
(
roleName
);
role
.
setRoleKey
(
roleKey
);
role
.
setRoleSort
(
1
);
role
.
setStatus
(
TenantConstants
.
NORMAL
);
roleMapper
.
insert
(
role
);
Long
roleId
=
role
.
getRoleId
();
// 创建角色菜单
List
<
SysRoleMenu
>
roleMenus
=
new
ArrayList
<>(
menuIds
.
size
());
menuIds
.
forEach
(
menuId
->
{
SysRoleMenu
roleMenu
=
new
SysRoleMenu
();
roleMenu
.
setRoleId
(
roleId
);
roleMenu
.
setMenuId
(
menuId
);
roleMenus
.
add
(
roleMenu
);
});
roleMenuMapper
.
insertBatch
(
roleMenus
);
return
roleId
;
}
/**
* 校验租户是否允许操作
*
* @param tenantId 租户ID
*/
@Override
public
void
checkTenantAllowed
(
String
tenantId
)
{
if
(
ObjectUtil
.
isNotNull
(
tenantId
)
&&
TenantConstants
.
DEFAULT_TENANT_ID
.
equals
(
tenantId
))
{
throw
new
ServiceException
(
"不允许操作管理租户"
);
}
}
/**
* 修改租户
*/
@Override
@CacheEvict
(
cacheNames
=
CacheNames
.
SYS_TENANT
,
key
=
"#bo.tenantId"
)
public
Boolean
updateByBo
(
SysTenantBo
bo
)
{
SysTenant
tenant
=
BeanUtil
.
toBean
(
bo
,
SysTenant
.
class
);
if
(
TenantConstants
.
DISABLE
.
equals
(
bo
.
getStatus
()))
{
tenant
.
setExpireTime
(
new
DateTime
());
}
tenant
.
setTenantId
(
null
);
return
baseMapper
.
updateById
(
tenant
)
>
0
;
}
// /**
// * 修改租户状态
// *
// * @param bo 租户信息
// * @return 结果
// */
// @Override
// @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#bo.tenantId")
// public int updateTenantStatus(SysTenantBo bo) {
// SysTenant tenant = MapStructUtils.convert(bo, SysTenant.class);
// return baseMapper.updateById(tenant);
// }
/**
* 校验并批量删除租户信息
*/
@Override
@CacheEvict
(
cacheNames
=
CacheNames
.
SYS_TENANT
,
allEntries
=
true
)
public
Boolean
deleteWithValidByIds
(
Collection
<
Long
>
ids
,
Boolean
isValid
)
{
if
(
isValid
)
{
// 做一些业务上的校验,判断是否需要校验
if
(
ids
.
contains
(
TenantConstants
.
SUPER_ADMIN_ID
))
{
throw
new
ServiceException
(
"超管租户不能删除"
);
}
}
return
baseMapper
.
deleteBatchIds
(
ids
)
>
0
;
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
syncTenantPackage
(
String
tenantId
,
Long
packageId
)
{
SysTenantPackage
tenantPackage
=
tenantPackageMapper
.
selectById
(
packageId
);
List
<
SysRole
>
roles
=
roleMapper
.
selectList
(
new
LambdaQueryWrapper
<
SysRole
>().
eq
(
SysRole:
:
getTenantId
,
tenantId
));
List
<
Long
>
roleIds
=
new
ArrayList
<>(
roles
.
size
()
-
1
);
List
<
Long
>
menuIds
=
StringUtils
.
splitTo
(
tenantPackage
.
getMenuIds
(),
Convert:
:
toLong
);
roles
.
forEach
(
item
->
{
if
(
TenantConstants
.
TENANT_SUPER_ADMIN_ROLE_KEY
.
equals
(
item
.
getRoleKey
()))
{
List
<
SysRoleMenu
>
roleMenus
=
new
ArrayList
<>(
menuIds
.
size
());
menuIds
.
forEach
(
menuId
->
{
SysRoleMenu
roleMenu
=
new
SysRoleMenu
();
roleMenu
.
setRoleId
(
item
.
getRoleId
());
roleMenu
.
setMenuId
(
menuId
);
roleMenus
.
add
(
roleMenu
);
});
roleMenuMapper
.
delete
(
new
LambdaQueryWrapper
<
SysRoleMenu
>().
eq
(
SysRoleMenu:
:
getRoleId
,
item
.
getRoleId
()));
roleMenuMapper
.
insertBatch
(
roleMenus
);
}
else
{
roleIds
.
add
(
item
.
getRoleId
());
}
});
if
(!
roleIds
.
isEmpty
())
{
roleMenuMapper
.
delete
(
new
LambdaQueryWrapper
<
SysRoleMenu
>().
in
(
SysRoleMenu:
:
getRoleId
,
roleIds
).
notIn
(!
menuIds
.
isEmpty
(),
SysRoleMenu:
:
getMenuId
,
menuIds
));
}
try
{
//清除企业用户登录信息
List
<
SysUser
>
tenantUsers
=
userMapper
.
selectList
(
Wrappers
.<
SysUser
>
lambdaQuery
()
.
eq
(
SysUser:
:
getTenantId
,
tenantId
).
eq
(
SysUser:
:
getStatus
,
UserStatus
.
OK
.
getCode
()));
if
(!
CollectionUtils
.
isEmpty
(
tenantUsers
))
{
for
(
SysUser
tenantUser
:
tenantUsers
)
{
String
key
=
"global:Authorization:login:session:00:"
+
tenantUser
.
getUserId
();
if
(
RedisUtils
.
hasKey
(
key
))
{
SaSession
session
=
RedisUtils
.
getCacheObject
(
key
);
List
<
TokenSign
>
tokenSignList
=
session
.
getTokenSignList
();
tokenSignList
.
forEach
(
sign
->
StpUtil
.
kickoutByTokenValue
(
sign
.
getValue
()));
}
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"清除企业用户登录信息操作失败!error={}"
,
e
.
getMessage
());
}
return
true
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment