4 Commits
4.1.x ... dev

12 changed files with 283 additions and 82 deletions

View File

@@ -1,7 +1,7 @@
# ContiNew Admin 多租户中后台管理框架 # ContiNew Admin 多租户中后台管理框架
<a href="https://github.com/continew-org/continew-admin" title="Release" target="_blank"> <a href="https://github.com/continew-org/continew-admin" title="Release" target="_blank">
<img src="https://img.shields.io/badge/RELEASE-v4.1.0-%23ff3f59.svg" alt="Release" /> <img src="https://img.shields.io/badge/SNAPSHOT-v4.2.0-%23ff3f59.svg" alt="Release" />
</a> </a>
<a href="https://github.com/continew-org/continew-starter" title="ContiNew Starter" target="_blank"> <a href="https://github.com/continew-org/continew-starter" title="ContiNew Starter" target="_blank">
<img src="https://img.shields.io/badge/ContiNew Starter-2.14.0-%236CB52D.svg" alt="ContiNew Starter" /> <img src="https://img.shields.io/badge/ContiNew Starter-2.14.0-%236CB52D.svg" alt="ContiNew Starter" />

View File

@@ -15,18 +15,6 @@
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<description>API 及打包部署模块</description> <description>API 及打包部署模块</description>
<properties>
<!-- ### 打包配置相关 ### -->
<!-- 启动类 -->
<main-class>top.continew.admin.ContiNewAdminApplication</main-class>
<!-- 程序 jar 输出目录 -->
<bin-path>bin/</bin-path>
<!-- 配置文件输出目录 -->
<config-path>config/</config-path>
<!-- 依赖 jar 输出目录 -->
<lib-path>lib/</lib-path>
</properties>
<dependencies> <dependencies>
<!-- 系统管理模块 --> <!-- 系统管理模块 -->
<dependency> <dependency>
@@ -86,8 +74,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration> <configuration>
<!-- 是否跳过 Spring Boot 的重新打包操作 -->
<skip>${spring-boot.repackage.skip}</skip>
<!-- 是否将系统作用域的依赖包含进去 -->
<includeSystemScope>true</includeSystemScope> <includeSystemScope>true</includeSystemScope>
<skip>${skip.boot.repackage}</skip>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
@@ -101,34 +91,35 @@
</build> </build>
<profiles> <profiles>
<!-- 默认 Spring Boot 胖包 模式 --> <!-- 胖包模式:将依赖、配置文件等打包到 jar 包之内 -->
<profile> <profile>
<id>fat_jar</id> <id>fat-jar</id>
<properties> <properties>
<skip.boot.repackage>false</skip.boot.repackage> <!-- 是否跳过 Spring Boot 的重新打包操作 -->
<spring-boot.repackage.skip>false</spring-boot.repackage.skip>
</properties> </properties>
</profile> </profile>
<!-- 瘦包 模式(可执行 JAR + lib + config --> <!-- 瘦包模式:将依赖、配置文件等打包到 jar 包之外 -->
<profile> <profile>
<id>slim_jar</id> <id>thin-jar</id>
<!--默认-->
<activation> <activation>
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<skip.boot.repackage>true</skip.boot.repackage> <!-- 是否跳过 Spring Boot 的重新打包操作 -->
<spring-boot.repackage.skip>true</spring-boot.repackage.skip>
<!-- 路径变量 -->
<lib-path>lib/</lib-path>
<config-path>config/</config-path>
<bin-path>bin/</bin-path>
<!-- 启动类 --> <!-- 启动类 -->
<main-class>top.continew.admin.ContiNewAdminApplication</main-class> <main-class>top.continew.admin.ContiNewAdminApplication</main-class>
<!-- 程序 jar 输出目录 -->
<bin-path>bin/</bin-path>
<!-- 配置文件输出目录 -->
<config-path>config/</config-path>
<!-- 依赖 jar 输出目录 -->
<lib-path>lib/</lib-path>
</properties> </properties>
<build> <build>
<plugins> <plugins>
<!-- 分离打包 JAR不包含依赖 -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
@@ -157,7 +148,6 @@
<outputDirectory>${project.build.directory}/app/${bin-path}</outputDirectory> <outputDirectory>${project.build.directory}/app/${bin-path}</outputDirectory>
</configuration> </configuration>
</plugin> </plugin>
<!-- 拷贝依赖 jar --> <!-- 拷贝依赖 jar -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@@ -175,7 +165,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- 拷贝配置文件 --> <!-- 拷贝配置文件 -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@@ -206,7 +195,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</profile> </profile>

View File

@@ -6,7 +6,7 @@ application:
# 描述 # 描述
description: 持续迭代优化的前后端分离中后台管理系统框架,开箱即用,持续提供舒适的开发体验。 description: 持续迭代优化的前后端分离中后台管理系统框架,开箱即用,持续提供舒适的开发体验。
# 版本 # 版本
version: 4.1.0 version: 4.2.0-SNAPSHOT
starter: 2.14.0 starter: 2.14.0
# 基本包 # 基本包
base-package: top.continew.admin base-package: top.continew.admin
@@ -238,17 +238,24 @@ sa-token:
token-name: Authorization token-name: Authorization
# 是否启用动态 activeTimeout 功能 # 是否启用动态 activeTimeout 功能
dynamic-active-timeout: true dynamic-active-timeout: true
## 提示:请通过页面功能 [系统管理/系统配置/客户端配置] 动态调整 timeout、active-timeout 配置项 ## 提示:请通过页面功能 [系统管理/系统配置/客户端配置] 动态调整下方注释的配置项
## 如果不需要动态配置,请将 dynamic-active-timeout 设为 false并取消下方 timeout 和 active-timeout 配置注释,最好再移除相关登录处理代码 ## 如果不需要动态配置,请取消下方配置注释,再移除相关登录处理代码
# # Token 有效期(单位:秒,默认 30 天,-1 代表永不过期) # # Token 有效期(单位:秒,默认 30 天,-1 代表永不过期)
# timeout: 86400 # timeout: 86400
# # Token 最低活跃频率(单位:秒,默认 -1代表不限制永不冻结。如果 token 超过此时间没有访问系统就会被冻结) # # Token 最低活跃频率(单位:秒,默认 -1代表不限制永不冻结。如果 token 超过此时间没有访问系统就会被冻结)
# active-timeout: 1800 # active-timeout: 1800
# 是否打开自动续签(如果此值为 true框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作) # # 是否打开自动续签(true每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
auto-renew: true # auto-renew: true
# 是否允许同一账号多地同时登录(true 时允许一起登录,为 false新登录挤掉旧登录) # # 是否允许同一账号多地同时登录true:允许;false新登录挤掉旧登录)
is-concurrent: true # is-concurrent: true
# 在多人登录同一账号时,是否共用一个 Token为 true 时所有登录共用一个 Token为 false 时每次登录新建一个 Token # # 顶人下线的范围ALL_DEVICE_TYPE所有设备类型端
# replaced-range: ALL_DEVICE_TYPE
# # 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
# max-login-count: -1
# # 溢出人数的下线方式KICKOUT踢人下线
# overflow-logout-mode: KICKOUT
# 在多人登录同一账号时,是否共用一个 Tokentrue所有登录共用一个 Tokenfalse每次登录新建一个 Token
# 使用 jwt-simple 模式后is-share 恒等于 false目前本项目使用 jwt-simple 模式,可通过 sa-token.extension.enableJwt: false 关闭并自行提供 StpLogic 配置)
is-share: false is-share: false
# 是否输出操作日志 # 是否输出操作日志
is-log: false is-log: false

View File

@@ -341,18 +341,22 @@ CREATE TABLE IF NOT EXISTS `sys_file` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件表';
CREATE TABLE IF NOT EXISTS `sys_client` ( CREATE TABLE IF NOT EXISTS `sys_client` (
`id` bigint(20) AUTO_INCREMENT COMMENT 'ID', `id` bigint(20) AUTO_INCREMENT COMMENT 'ID',
`client_id` varchar(50) NOT NULL COMMENT '客户端ID', `client_id` varchar(50) NOT NULL COMMENT '客户端ID',
`client_type` varchar(50) NOT NULL COMMENT '客户端类型', `client_type` varchar(50) NOT NULL COMMENT '客户端类型',
`auth_type` json NOT NULL COMMENT '认证类型', `auth_type` json NOT NULL COMMENT '认证类型',
`active_timeout` bigint(20) DEFAULT -1 COMMENT 'Token最低活跃频率单位-1不限制永不冻结', `active_timeout` bigint(20) NOT NULL DEFAULT -1 COMMENT 'Token最低活跃频率单位-1不限制永不冻结',
`timeout` bigint(20) DEFAULT 2592000 COMMENT 'Token有效期单位-1永不过期', `timeout` bigint(20) NOT NULL DEFAULT 2592000 COMMENT 'Token有效期单位-1永不过期',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用', `is_concurrent` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否允许同一账号多地同时登录true允许false新登录挤掉旧登录',
`create_user` bigint(20) NOT NULL COMMENT '创建人', `replaced_range` varchar(20) DEFAULT NULL COMMENT '顶人下线的范围CURR_DEVICE_TYPE当前客户端类型ALL_DEVICE_TYPE所有客户端类型',
`create_time` datetime NOT NULL COMMENT '创建时间', `max_login_count` int NOT NULL DEFAULT -1 COMMENT '同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人', `overflow_logout_mode` varchar(20) DEFAULT NULL COMMENT '溢出人数的下线方式LOGOUT注销下线KICKOUT踢人下线REPLACED顶人下线',
`update_time` datetime DEFAULT NULL COMMENT '修改时间', `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`deleted` bigint(20) NOT NULL DEFAULT 0 COMMENT '是否已删除0id', `create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`deleted` bigint(20) NOT NULL DEFAULT 0 COMMENT '是否已删除0id',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE INDEX `uk_client_id`(`client_id`, `deleted`), UNIQUE INDEX `uk_client_id`(`client_id`, `deleted`),
INDEX `idx_create_user`(`create_user`), INDEX `idx_create_user`(`create_user`),

View File

@@ -566,37 +566,45 @@ COMMENT ON COLUMN "sys_file"."deleted" IS '是否已删除0
COMMENT ON TABLE "sys_file" IS '文件表'; COMMENT ON TABLE "sys_file" IS '文件表';
CREATE TABLE IF NOT EXISTS "sys_client" ( CREATE TABLE IF NOT EXISTS "sys_client" (
"id" int8 NOT NULL, "id" int8 NOT NULL,
"client_id" varchar(50) NOT NULL, "client_id" varchar(50) NOT NULL,
"client_type" varchar(50) NOT NULL, "client_type" varchar(50) NOT NULL,
"auth_type" json NOT NULL, "auth_type" json NOT NULL,
"active_timeout" int8 NOT NULL DEFAULT -1, "active_timeout" int8 NOT NULL DEFAULT -1,
"timeout" int8 NOT NULL DEFAULT 2592000, "timeout" int8 NOT NULL DEFAULT 2592000,
"status" int2 NOT NULL DEFAULT 1, "is_concurrent" bool NOT NULL DEFAULT true,
"create_user" int8 NOT NULL, "replaced_range" varchar(20) DEFAULT NULL,
"create_time" timestamp NOT NULL, "max_login_count" int4 NOT NULL DEFAULT -1,
"update_user" int8 DEFAULT NULL, "overflow_logout_mode" varchar(20) DEFAULT NULL,
"update_time" timestamp DEFAULT NULL, "status" int2 NOT NULL DEFAULT 1,
"deleted" int8 NOT NULL DEFAULT 0, "create_user" int8 NOT NULL,
"create_time" timestamp NOT NULL,
"update_user" int8 DEFAULT NULL,
"update_time" timestamp DEFAULT NULL,
"deleted" int8 NOT NULL DEFAULT 0,
PRIMARY KEY ("id") PRIMARY KEY ("id")
); );
CREATE UNIQUE INDEX "uk_client_client_id" ON "sys_client" ("client_id"); CREATE UNIQUE INDEX "uk_client_client_id" ON "sys_client" ("client_id");
CREATE INDEX "idx_client_create_user" ON "sys_client" ("create_user"); CREATE INDEX "idx_client_create_user" ON "sys_client" ("create_user");
CREATE INDEX "idx_client_update_user" ON "sys_client" ("update_user"); CREATE INDEX "idx_client_update_user" ON "sys_client" ("update_user");
CREATE INDEX "idx_client_deleted" ON "sys_client" ("deleted"); CREATE INDEX "idx_client_deleted" ON "sys_client" ("deleted");
COMMENT ON COLUMN "sys_client"."id" IS 'ID'; COMMENT ON COLUMN "sys_client"."id" IS 'ID';
COMMENT ON COLUMN "sys_client"."client_id" IS '客户端ID'; COMMENT ON COLUMN "sys_client"."client_id" IS '客户端ID';
COMMENT ON COLUMN "sys_client"."client_type" IS '客户端类型'; COMMENT ON COLUMN "sys_client"."client_type" IS '客户端类型';
COMMENT ON COLUMN "sys_client"."auth_type" IS '认证类型'; COMMENT ON COLUMN "sys_client"."auth_type" IS '认证类型';
COMMENT ON COLUMN "sys_client"."active_timeout" IS 'Token最低活跃频率单位-1不限制永不冻结'; COMMENT ON COLUMN "sys_client"."active_timeout" IS 'Token最低活跃频率单位-1不限制永不冻结';
COMMENT ON COLUMN "sys_client"."timeout" IS 'Token有效期单位-1永不过期'; COMMENT ON COLUMN "sys_client"."timeout" IS 'Token有效期单位-1永不过期';
COMMENT ON COLUMN "sys_client"."status" IS '状态1启用2禁用'; COMMENT ON COLUMN "sys_client"."is_concurrent" IS '是否允许同一账号多地同时登录true允许false新登录挤掉旧登录';
COMMENT ON COLUMN "sys_client"."create_user" IS '创建人'; COMMENT ON COLUMN "sys_client"."replaced_range" IS '顶人下线的范围CURR_DEVICE_TYPE当前客户端类型ALL_DEVICE_TYPE所有客户端类型';
COMMENT ON COLUMN "sys_client"."create_time" IS '创建时间'; COMMENT ON COLUMN "sys_client"."max_login_count" IS '同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)';
COMMENT ON COLUMN "sys_client"."update_user" IS '修改人'; COMMENT ON COLUMN "sys_client"."overflow_logout_mode" IS '溢出人数的下线方式LOGOUT注销下线KICKOUT踢人下线REPLACED顶人下线';
COMMENT ON COLUMN "sys_client"."update_time" IS '修改时间'; COMMENT ON COLUMN "sys_client"."status" IS '状态1启用2禁用';
COMMENT ON COLUMN "sys_client"."deleted" IS '是否已删除0id'; COMMENT ON COLUMN "sys_client"."create_user" IS '创建人';
COMMENT ON TABLE "sys_client" IS '客户端表'; COMMENT ON COLUMN "sys_client"."create_time" IS '创建时间';
COMMENT ON COLUMN "sys_client"."update_user" IS '修改人';
COMMENT ON COLUMN "sys_client"."update_time" IS '修改时间';
COMMENT ON COLUMN "sys_client"."deleted" IS '是否已删除0id';
COMMENT ON TABLE "sys_client" IS '客户端表';
CREATE TABLE IF NOT EXISTS "sys_sms_config" ( CREATE TABLE IF NOT EXISTS "sys_sms_config" (
"id" int8 NOT NULL, "id" int8 NOT NULL,

View File

@@ -18,6 +18,8 @@ package top.continew.admin.auth;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter; import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.dev33.satoken.stp.parameter.enums.SaLogoutMode;
import cn.dev33.satoken.stp.parameter.enums.SaReplacedRange;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@@ -120,8 +122,17 @@ public abstract class AbstractLoginHandler<T extends LoginReq> implements LoginH
loginParameter.setActiveTimeout(client.getActiveTimeout()); loginParameter.setActiveTimeout(client.getActiveTimeout());
loginParameter.setTimeout(client.getTimeout()); loginParameter.setTimeout(client.getTimeout());
loginParameter.setDeviceType(client.getClientType()); loginParameter.setDeviceType(client.getClientType());
userContext.setClientType(client.getClientType());
loginParameter.setExtra(CLIENT_ID, client.getClientId()); loginParameter.setExtra(CLIENT_ID, client.getClientId());
// 设置并发登录配置参数
loginParameter.setIsConcurrent(client.getIsConcurrent());
if (Boolean.FALSE.equals(client.getIsConcurrent())) {
loginParameter.setReplacedRange(SaReplacedRange.valueOf(client.getReplacedRange().getValue()));
}
loginParameter.setMaxLoginCount(client.getMaxLoginCount());
if (client.getMaxLoginCount() != -1) {
loginParameter.setOverflowLogoutMode(SaLogoutMode.valueOf(client.getOverflowLogoutMode().getValue()));
}
userContext.setClientType(client.getClientType());
userContext.setClientId(client.getClientId()); userContext.setClientId(client.getClientId());
userContext.setTenantId(tenantId); userContext.setTenantId(tenantId);
// 登录并缓存用户信息 // 登录并缓存用户信息

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import top.continew.starter.core.enums.BaseEnum;
/**
* 注销模式枚举
*
* @author KAI
* @since 2025/10/28 14:04
*/
@Getter
@RequiredArgsConstructor
public enum LogoutModeEnum implements BaseEnum<String> {
/**
* 注销下线
*/
LOGOUT("LOGOUT", "注销下线"),
/**
* 踢人下线
*/
KICKOUT("KICKOUT", "踢人下线"),
/**
* 顶人下线
*/
REPLACED("REPLACED", "顶人下线");
private final String value;
private final String description;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import top.continew.starter.core.enums.BaseEnum;
/**
* 顶人下线的范围枚举
*
* @author KAI
* @since 2025/10/28 14:05
*/
@Getter
@RequiredArgsConstructor
public enum ReplacedRangeEnum implements BaseEnum<String> {
/**
* 当前客户端类型
*/
CURR_DEVICE_TYPE("CURR_DEVICE_TYPE", "当前客户端类型"),
/**
* 所有客户端类型
*/
ALL_DEVICE_TYPE("ALL_DEVICE_TYPE", "所有客户端类型");
private final String value;
private final String description;
}

View File

@@ -20,8 +20,10 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data; import lombok.Data;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.base.model.entity.BaseDO; import top.continew.admin.common.base.model.entity.BaseDO;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.system.enums.LogoutModeEnum;
import top.continew.admin.system.enums.ReplacedRangeEnum;
import java.io.Serial; import java.io.Serial;
import java.util.List; import java.util.List;
@@ -66,6 +68,26 @@ public class ClientDO extends BaseDO {
*/ */
private Long timeout; private Long timeout;
/**
* 是否允许同一账号多地同时登录true允许false新登录挤掉旧登录
*/
private Boolean isConcurrent;
/**
* 顶人下线的范围
*/
private ReplacedRangeEnum replacedRange;
/**
* 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
*/
private Integer maxLoginCount;
/**
* 溢出人数的下线方式
*/
private LogoutModeEnum overflowLogoutMode;
/** /**
* 状态 * 状态
*/ */

View File

@@ -16,12 +16,17 @@
package top.continew.admin.system.model.req; package top.continew.admin.system.model.req;
import cn.sticki.spel.validator.constrain.SpelNotNull;
import cn.sticki.spel.validator.jakarta.SpelValid;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.system.enums.LogoutModeEnum;
import top.continew.admin.system.enums.ReplacedRangeEnum;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
@@ -35,6 +40,7 @@ import java.util.List;
* @since 2024/12/03 16:04 * @since 2024/12/03 16:04
*/ */
@Data @Data
@SpelValid
@Schema(description = "客户端创建或修改请求参数") @Schema(description = "客户端创建或修改请求参数")
public class ClientReq implements Serializable { public class ClientReq implements Serializable {
@@ -60,14 +66,44 @@ public class ClientReq implements Serializable {
* Token 最低活跃频率(单位:秒,-1不限制永不冻结 * Token 最低活跃频率(单位:秒,-1不限制永不冻结
*/ */
@Schema(description = "Token 最低活跃频率(单位:秒,-1不限制永不冻结", example = "1800") @Schema(description = "Token 最低活跃频率(单位:秒,-1不限制永不冻结", example = "1800")
@NotNull(message = "Token 最低活跃频率不能为空")
private Long activeTimeout; private Long activeTimeout;
/** /**
* Token 有效期(单位:秒,-1永不过期 * Token 有效期(单位:秒,-1永不过期
*/ */
@Schema(description = "Token 有效期(单位:秒,-1永不过期", example = "86400") @Schema(description = "Token 有效期(单位:秒,-1永不过期", example = "86400")
@NotNull(message = "Token 有效期不能为空")
private Long timeout; private Long timeout;
/**
* 是否允许同一账号多地同时登录true允许false新登录挤掉旧登录
*/
@Schema(description = "是否允许同一账号多地同时登录", example = "true")
@NotNull(message = "是否允许同一账号多地同时登录不能为空")
private Boolean isConcurrent;
/**
* 顶人下线的范围
*/
@Schema(description = "顶人下线的范围", example = "ALL_DEVICE_TYPE")
@SpelNotNull(condition = "#this.isConcurrent == false", message = "顶人下线的范围无效")
private ReplacedRangeEnum replacedRange;
/**
* 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
*/
@Schema(description = "同一账号最大登录数量", example = "-1")
@NotNull(message = "同一账号最大登录数量不能为空")
private Integer maxLoginCount;
/**
* 溢出人数的下线方式
*/
@Schema(description = "溢出人数的下线方式", example = "KICKOUT")
@SpelNotNull(condition = "#this.maxLoginCount != -1", message = "溢出人数的下线方式无效")
private LogoutModeEnum overflowLogoutMode;
/** /**
* 状态 * 状态
*/ */

View File

@@ -20,10 +20,12 @@ import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import top.continew.admin.common.base.model.resp.BaseDetailResp;
import top.continew.admin.common.config.excel.DictExcelProperty; import top.continew.admin.common.config.excel.DictExcelProperty;
import top.continew.admin.common.config.excel.ExcelDictConverter; import top.continew.admin.common.config.excel.ExcelDictConverter;
import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.base.model.resp.BaseDetailResp; import top.continew.admin.system.enums.LogoutModeEnum;
import top.continew.admin.system.enums.ReplacedRangeEnum;
import top.continew.starter.excel.converter.ExcelBaseEnumConverter; import top.continew.starter.excel.converter.ExcelBaseEnumConverter;
import top.continew.starter.excel.converter.ExcelListConverter; import top.continew.starter.excel.converter.ExcelListConverter;
@@ -81,10 +83,38 @@ public class ClientResp extends BaseDetailResp {
@ExcelProperty(value = "Token 有效期", order = 7) @ExcelProperty(value = "Token 有效期", order = 7)
private Long timeout; private Long timeout;
/**
* 是否允许同一账号多地同时登录true允许false新登录挤掉旧登录
*/
@Schema(description = "是否允许同一账号多地同时登录", example = "true")
@ExcelProperty(value = "是否允许同一账号多地同时登录", order = 8)
private Boolean isConcurrent;
/**
* 顶人下线的范围
*/
@Schema(description = "顶人下线的范围", example = "ALL_DEVICE_TYPE")
@ExcelProperty(value = "顶人下线的范围", converter = ExcelBaseEnumConverter.class, order = 9)
private ReplacedRangeEnum replacedRange;
/**
* 同一账号最大登录数量(-1不限制只有在 isConcurrent=trueisShare=false 时才有效)
*/
@Schema(description = "同一账号最大登录数量", example = "-1")
@ExcelProperty(value = "同一账号最大登录数量", order = 10)
private Integer maxLoginCount;
/**
* 溢出人数的下线方式
*/
@Schema(description = "溢出人数的下线方式", example = "KICKOUT")
@ExcelProperty(value = "溢出人数的下线方式", converter = ExcelBaseEnumConverter.class, order = 11)
private LogoutModeEnum overflowLogoutMode;
/** /**
* 状态 * 状态
*/ */
@Schema(description = "状态", example = "1") @Schema(description = "状态", example = "1")
@ExcelProperty(value = "状态", converter = ExcelBaseEnumConverter.class, order = 8) @ExcelProperty(value = "状态", converter = ExcelBaseEnumConverter.class, order = 12)
private DisEnableStatusEnum status; private DisEnableStatusEnum status;
} }

View File

@@ -35,7 +35,7 @@
<properties> <properties>
<!-- 项目版本号 --> <!-- 项目版本号 -->
<revision>4.1.0</revision> <revision>4.2.0-SNAPSHOT</revision>
</properties> </properties>
<!-- 全局依赖版本管理 --> <!-- 全局依赖版本管理 -->