v3.14.0 更新;【新增】EasyExcel重磅升级为FastExcel;【新增】使用最强Argon2算法作为密码存储;【新增】大家吐槽的数据字典改为可重复;【新增】前端布局再增加多种样式;

This commit is contained in:
zhuoda
2025-03-12 21:30:24 +08:00
parent e74f179a91
commit fecb3a9d81
207 changed files with 4260 additions and 2019 deletions

View File

@@ -21,6 +21,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<springboot.version>3.3.1</springboot.version> <springboot.version>3.3.1</springboot.version>
<spring-mock.version>2.0.8</spring-mock.version> <spring-mock.version>2.0.8</spring-mock.version>
<spring-security-crypto.version>6.4.3</spring-security-crypto.version>
<mybatis-plus.version>3.5.7</mybatis-plus.version> <mybatis-plus.version>3.5.7</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version> <p6spy.version>3.9.1</p6spy.version>
<knife4j.version>4.4.0</knife4j.version> <knife4j.version>4.4.0</knife4j.version>
@@ -33,10 +34,11 @@
<commons-io.version>2.15.0</commons-io.version> <commons-io.version>2.15.0</commons-io.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<commons-collections4.version>4.4</commons-collections4.version> <commons-collections4.version>4.4</commons-collections4.version>
<commons-compress.version>1.26.0</commons-compress.version>
<commons-codec.version>1.13</commons-codec.version> <commons-codec.version>1.13</commons-codec.version>
<commons-text.version>1.9</commons-text.version> <commons-text.version>1.9</commons-text.version>
<xerces.version>2.12.0</xerces.version> <xerces.version>2.12.0</xerces.version>
<easy-excel.version>3.3.2</easy-excel.version> <fast-excel.version>1.0.0</fast-excel.version>
<poi.version>5.2.4</poi.version> <poi.version>5.2.4</poi.version>
<ooxml-schemas.version>1.4</ooxml-schemas.version> <ooxml-schemas.version>1.4</ooxml-schemas.version>
<aws-java-sdk.version>1.11.842</aws-java-sdk.version> <aws-java-sdk.version>1.11.842</aws-java-sdk.version>
@@ -48,7 +50,7 @@
<velocity-tools.version>3.1</velocity-tools.version> <velocity-tools.version>3.1</velocity-tools.version>
<sa-token.version>1.37.0</sa-token.version> <sa-token.version>1.37.0</sa-token.version>
<ip2region.version>2.7.0</ip2region.version> <ip2region.version>2.7.0</ip2region.version>
<bcprov.version>1.59</bcprov.version> <bcprov.version>1.80</bcprov.version>
<jackson-datatype-jsr310.version>2.13.4</jackson-datatype-jsr310.version> <jackson-datatype-jsr310.version>2.13.4</jackson-datatype-jsr310.version>
<jackson-dataformat-yaml.version>2.16.1</jackson-dataformat-yaml.version> <jackson-dataformat-yaml.version>2.16.1</jackson-dataformat-yaml.version>
<smartdb.version>1.2.0</smartdb.version> <smartdb.version>1.2.0</smartdb.version>
@@ -56,6 +58,7 @@
<snakeyaml.version>2.2</snakeyaml.version> <snakeyaml.version>2.2</snakeyaml.version>
<freemarker.version>2.3.33</freemarker.version> <freemarker.version>2.3.33</freemarker.version>
<jsoup.version>1.18.1</jsoup.version> <jsoup.version>1.18.1</jsoup.version>
<tika.version>3.1.0</tika.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@@ -83,6 +86,12 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>${spring-security-crypto.version}</version>
</dependency>
<dependency> <dependency>
<groupId>p6spy</groupId> <groupId>p6spy</groupId>
<artifactId>p6spy</artifactId> <artifactId>p6spy</artifactId>
@@ -156,6 +165,12 @@
<version>${commons-collections4.version}</version> <version>${commons-collections4.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.version}</version>
</dependency>
<dependency> <dependency>
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>
@@ -235,18 +250,18 @@
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId> <artifactId>bcprov-jdk18on</artifactId>
<version>${bcprov.version}</version> <version>${bcprov.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>cn.idev.excel</groupId>
<artifactId>easyexcel</artifactId> <artifactId>fastexcel</artifactId>
<version>${easy-excel.version}</version> <version>${fast-excel.version}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<artifactId>poi-ooxml-schemas</artifactId> <artifactId>logback-classic</artifactId>
<groupId>org.apache.poi</groupId> <groupId>ch.qos.logback</groupId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
@@ -318,6 +333,12 @@
<version>${freemarker.version}</version> <version>${freemarker.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>${tika.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@@ -2,8 +2,8 @@ package net.lab1024.sa.admin.interceptor;
import cn.dev33.satoken.annotation.SaIgnore; import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.exception.SaTokenException; import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaStrategy; import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@@ -14,14 +14,9 @@ import net.lab1024.sa.admin.module.system.login.service.LoginService;
import net.lab1024.sa.base.common.annoation.NoNeedLogin; import net.lab1024.sa.base.common.annoation.NoNeedLogin;
import net.lab1024.sa.base.common.code.SystemErrorCode; import net.lab1024.sa.base.common.code.SystemErrorCode;
import net.lab1024.sa.base.common.code.UserErrorCode; import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.constant.StringConst;
import net.lab1024.sa.base.common.domain.ResponseDTO; import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.domain.SystemEnvironment;
import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum;
import net.lab1024.sa.base.common.enumeration.UserTypeEnum;
import net.lab1024.sa.base.common.util.SmartRequestUtil; import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.common.util.SmartResponseUtil; import net.lab1024.sa.base.common.util.SmartResponseUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -47,9 +42,6 @@ public class AdminInterceptor implements HandlerInterceptor {
@Resource @Resource
private LoginService loginService; private LoginService loginService;
@Resource
private SystemEnvironment systemEnvironment;
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
@@ -68,17 +60,7 @@ public class AdminInterceptor implements HandlerInterceptor {
// --------------- 第一步: 根据token 获取用户 --------------- // --------------- 第一步: 根据token 获取用户 ---------------
String tokenValue = StpUtil.getTokenValue(); String tokenValue = StpUtil.getTokenValue();
boolean debugNumberTokenFlag = isDevDebugNumberToken(tokenValue); String loginId = (String) StpUtil.getLoginIdByToken(tokenValue);
String loginId = null;
if (debugNumberTokenFlag) {
//开发、测试环境,且为数字的话,则表明为 调试临时用户,即需要调用 sa-token switch
loginId = UserTypeEnum.ADMIN_EMPLOYEE.getValue() + StringConst.COLON + tokenValue;
StpUtil.switchTo(loginId);
} else {
loginId = (String) StpUtil.getLoginIdByToken(tokenValue);
}
RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request); RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request);
// --------------- 第二步: 校验 登录 --------------- // --------------- 第二步: 校验 登录 ---------------
@@ -86,7 +68,7 @@ public class AdminInterceptor implements HandlerInterceptor {
Method method = ((HandlerMethod) handler).getMethod(); Method method = ((HandlerMethod) handler).getMethod();
NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class); NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class);
if (noNeedLogin != null) { if (noNeedLogin != null) {
checkActiveTimeout(requestEmployee, debugNumberTokenFlag); checkActiveTimeout(requestEmployee);
return true; return true;
} }
@@ -96,7 +78,7 @@ public class AdminInterceptor implements HandlerInterceptor {
} }
// 检测token 活跃频率 // 检测token 活跃频率
checkActiveTimeout(requestEmployee, debugNumberTokenFlag); checkActiveTimeout(requestEmployee);
// --------------- 第三步: 校验 权限 --------------- // --------------- 第三步: 校验 权限 ---------------
@@ -143,12 +125,7 @@ public class AdminInterceptor implements HandlerInterceptor {
/** /**
* 检测token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结 * 检测token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结
*/ */
private void checkActiveTimeout(RequestEmployee requestEmployee, boolean debugNumberTokenFlag) { private void checkActiveTimeout(RequestEmployee requestEmployee) {
// 对于开发环境的 数字 debug token ,不需要检测活跃有效期
if (debugNumberTokenFlag) {
return;
}
// 用户不在线,也不用检测 // 用户不在线,也不用检测
if (requestEmployee == null) { if (requestEmployee == null) {
@@ -160,28 +137,11 @@ public class AdminInterceptor implements HandlerInterceptor {
} }
/**
* 是否为开发使用的 debug token
*
* @param token
* @return
*/
private boolean isDevDebugNumberToken(String token) {
if (!StrUtil.isNumeric(token)) {
return false;
}
return systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.DEV
|| systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.TEST;
}
@Override @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 清除上下文 // 清除上下文
SmartRequestUtil.remove(); SmartRequestUtil.remove();
// 开发环境,关闭 sa token 的临时切换用户
if (systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.DEV) {
StpUtil.endSwitch();
}
} }

View File

@@ -1,6 +1,6 @@
package net.lab1024.sa.admin.module.business.goods.domain.form; package net.lab1024.sa.admin.module.business.goods.domain.form;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@@ -1,6 +1,7 @@
package net.lab1024.sa.admin.module.business.goods.domain.vo; package net.lab1024.sa.admin.module.business.goods.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;

View File

@@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum; import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
import net.lab1024.sa.base.common.json.serializer.DictValueVoSerializer;
import net.lab1024.sa.base.common.swagger.SchemaEnum; import net.lab1024.sa.base.common.swagger.SchemaEnum;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -32,7 +31,6 @@ public class GoodsVO {
private Integer goodsStatus; private Integer goodsStatus;
@Schema(description = "产地") @Schema(description = "产地")
@JsonSerialize(using = DictValueVoSerializer.class)
private String place; private String place;
@Schema(description = "商品价格") @Schema(description = "商品价格")

View File

@@ -1,6 +1,6 @@
package net.lab1024.sa.admin.module.business.goods.service; package net.lab1024.sa.admin.module.business.goods.service;
import com.alibaba.excel.EasyExcel; import cn.idev.excel.FastExcel;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -174,7 +174,7 @@ public class GoodsService {
public ResponseDTO<String> importGoods(MultipartFile file) { public ResponseDTO<String> importGoods(MultipartFile file) {
List<GoodsImportForm> dataList; List<GoodsImportForm> dataList;
try { try {
dataList = EasyExcel.read(file.getInputStream()).head(GoodsImportForm.class) dataList = FastExcel.read(file.getInputStream()).head(GoodsImportForm.class)
.sheet() .sheet()
.doReadSync(); .doReadSync();
} catch (IOException e) { } catch (IOException e) {
@@ -194,12 +194,13 @@ public class GoodsService {
*/ */
public List<GoodsExcelVO> getAllGoods() { public List<GoodsExcelVO> getAllGoods() {
List<GoodsEntity> goodsEntityList = goodsDao.selectList(null); List<GoodsEntity> goodsEntityList = goodsDao.selectList(null);
String keyCode="GODOS_PLACE";
return goodsEntityList.stream() return goodsEntityList.stream()
.map(e -> .map(e ->
GoodsExcelVO.builder() GoodsExcelVO.builder()
.goodsStatus(SmartEnumUtil.getEnumDescByValue(e.getGoodsStatus(), GoodsStatusEnum.class)) .goodsStatus(SmartEnumUtil.getEnumDescByValue(e.getGoodsStatus(), GoodsStatusEnum.class))
.categoryName(categoryQueryService.queryCategoryName(e.getCategoryId())) .categoryName(categoryQueryService.queryCategoryName(e.getCategoryId()))
.place(Arrays.stream(e.getPlace().split(",")).map(code -> dictCacheService.selectValueNameByValueCode(code)).collect(Collectors.joining(","))) .place(Arrays.stream(e.getPlace().split(",")).map(code -> dictCacheService.selectValueNameByValueCode(keyCode,code)).collect(Collectors.joining(",")))
.price(e.getPrice()) .price(e.getPrice())
.goodsName(e.getGoodsName()) .goodsName(e.getGoodsName())
.remark(e.getRemark()) .remark(e.getRemark())

View File

@@ -1,6 +1,6 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo; package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data; import lombok.Data;
/** /**

View File

@@ -28,7 +28,7 @@ public class NoticeQueryForm extends PageParam {
private String documentNumber; private String documentNumber;
@Schema(description = "创建人") @Schema(description = "创建人")
private Long createUserId; private String createUserName;
@Schema(description = "删除标识") @Schema(description = "删除标识")
private Boolean deletedFlag; private Boolean deletedFlag;

View File

@@ -208,6 +208,10 @@ public class NoticeService {
} }
NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class); NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class);
NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(noticeEntity.getNoticeTypeId());
updateFormVO.setNoticeTypeName(noticeType.getNoticeTypeName());
updateFormVO.setPublishFlag(updateFormVO.getPublishTime() != null && updateFormVO.getPublishTime().isBefore(LocalDateTime.now()));
if (!updateFormVO.getAllVisibleFlag()) { if (!updateFormVO.getAllVisibleFlag()) {
List<NoticeVisibleRangeVO> noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId); List<NoticeVisibleRangeVO> noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId);
List<Long> employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType())) List<Long> employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType()))

View File

@@ -5,7 +5,7 @@ import net.lab1024.sa.base.common.enumeration.BaseEnum;
/** /**
* 数据范围 种类 * 数据可见范围类型
* *
* @Author 1024创新实验室: 罗伊 * @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17 * @Date 2020/11/28 20:59:17

View File

@@ -25,7 +25,7 @@ public class DataScopeSqlConfig {
/** /**
* join sql 具体实现类 * join sql 具体实现类
*/ */
private Class joinSqlImplClazz; private Class<?> joinSqlImplClazz;
private String joinSql; private String joinSql;

View File

@@ -5,7 +5,7 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
/** /**
* 数据范围 * 数据可见范围
* *
* @Author 1024创新实验室: 罗伊 * @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17 * @Date 2020/11/28 20:59:17

View File

@@ -46,6 +46,11 @@ public class DataScopeSqlConfigService {
private static final String DEPARTMENT_PARAM = "#departmentIds"; private static final String DEPARTMENT_PARAM = "#departmentIds";
/**
* 用于拼接查看本人数据范围的 SQL
*/
private static final String CREATE_USER_ID_EQUALS = "create_user_id = ";
private final ConcurrentHashMap<String, DataScopeSqlConfig> dataScopeMethodMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, DataScopeSqlConfig> dataScopeMethodMap = new ConcurrentHashMap<>();
@Resource @Resource
@@ -94,14 +99,23 @@ public class DataScopeSqlConfigService {
* 组装需要拼接的sql * 组装需要拼接的sql
*/ */
public String getJoinSql(Map<String, Object> paramMap, DataScopeSqlConfig sqlConfigDTO) { public String getJoinSql(Map<String, Object> paramMap, DataScopeSqlConfig sqlConfigDTO) {
DataScopeTypeEnum dataScopeTypeEnum = sqlConfigDTO.getDataScopeType();
String joinSql = sqlConfigDTO.getJoinSql();
Long employeeId = SmartRequestUtil.getRequestUserId(); Long employeeId = SmartRequestUtil.getRequestUserId();
if (employeeId == null) { if (employeeId == null) {
return ""; return "";
} }
DataScopeTypeEnum dataScopeTypeEnum = sqlConfigDTO.getDataScopeType();
DataScopeViewTypeEnum viewTypeEnum = dataScopeViewService.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
// 数据权限设置为仅本人可见时 直接返回 create_user_id = employeeId
if (DataScopeViewTypeEnum.ME == viewTypeEnum) {
return CREATE_USER_ID_EQUALS + employeeId;
}
String joinSql = sqlConfigDTO.getJoinSql();
if (DataScopeWhereInTypeEnum.CUSTOM_STRATEGY == sqlConfigDTO.getDataScopeWhereInType()) { if (DataScopeWhereInTypeEnum.CUSTOM_STRATEGY == sqlConfigDTO.getDataScopeWhereInType()) {
Class strategyClass = sqlConfigDTO.getJoinSqlImplClazz(); Class<?> strategyClass = sqlConfigDTO.getJoinSqlImplClazz();
if (strategyClass == null) { if (strategyClass == null) {
log.warn("data scope custom strategy class is null"); log.warn("data scope custom strategy class is null");
return ""; return "";
@@ -111,11 +125,10 @@ public class DataScopeSqlConfigService {
log.warn("data scope custom strategy class{} ,bean is null", sqlConfigDTO.getJoinSqlImplClazz()); log.warn("data scope custom strategy class{} ,bean is null", sqlConfigDTO.getJoinSqlImplClazz());
return ""; return "";
} }
DataScopeViewTypeEnum viewTypeEnum = dataScopeViewService.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
return powerStrategy.getCondition(viewTypeEnum,paramMap, sqlConfigDTO); return powerStrategy.getCondition(viewTypeEnum,paramMap, sqlConfigDTO);
} }
if (DataScopeWhereInTypeEnum.EMPLOYEE == sqlConfigDTO.getDataScopeWhereInType()) { if (DataScopeWhereInTypeEnum.EMPLOYEE == sqlConfigDTO.getDataScopeWhereInType()) {
List<Long> canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(dataScopeTypeEnum, employeeId); List<Long> canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(viewTypeEnum, employeeId);
if (CollectionUtils.isEmpty(canViewEmployeeIds)) { if (CollectionUtils.isEmpty(canViewEmployeeIds)) {
return ""; return "";
} }
@@ -124,7 +137,7 @@ public class DataScopeSqlConfigService {
return sql; return sql;
} }
if (DataScopeWhereInTypeEnum.DEPARTMENT == sqlConfigDTO.getDataScopeWhereInType()) { if (DataScopeWhereInTypeEnum.DEPARTMENT == sqlConfigDTO.getDataScopeWhereInType()) {
List<Long> canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(dataScopeTypeEnum, employeeId); List<Long> canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(viewTypeEnum, employeeId);
if (CollectionUtils.isEmpty(canViewDepartmentIds)) { if (CollectionUtils.isEmpty(canViewDepartmentIds)) {
return ""; return "";
} }

View File

@@ -44,10 +44,9 @@ public class DataScopeViewService {
private DepartmentService departmentService; private DepartmentService departmentService;
/** /**
* 获取某人可以查看的所有人员信息 * 获取某人可以查看的所有人员数据
*/ */
public List<Long> getCanViewEmployeeId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) { public List<Long> getCanViewEmployeeId(DataScopeViewTypeEnum viewType, Long employeeId) {
DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
if (DataScopeViewTypeEnum.ME == viewType) { if (DataScopeViewTypeEnum.ME == viewType) {
return this.getMeEmployeeIdList(employeeId); return this.getMeEmployeeIdList(employeeId);
} }
@@ -61,12 +60,12 @@ public class DataScopeViewService {
} }
/** /**
* 获取某人可以查看的所有部门信息 * 获取某人可以查看的所有部门数据
*/ */
public List<Long> getCanViewDepartmentId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) { public List<Long> getCanViewDepartmentId(DataScopeViewTypeEnum viewType, Long employeeId) {
DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
if (DataScopeViewTypeEnum.ME == viewType) { if (DataScopeViewTypeEnum.ME == viewType) {
return this.getMeDepartmentIdList(employeeId); // 数据可见范围类型为本人时 不可以查看任何部门数据
return Lists.newArrayList(0L);
} }
if (DataScopeViewTypeEnum.DEPARTMENT == viewType) { if (DataScopeViewTypeEnum.DEPARTMENT == viewType) {
return this.getMeDepartmentIdList(employeeId); return this.getMeDepartmentIdList(employeeId);
@@ -74,6 +73,7 @@ public class DataScopeViewService {
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) { if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) {
return this.getDepartmentAndSubIdList(employeeId); return this.getDepartmentAndSubIdList(employeeId);
} }
// 可以查看所有部门数据
return Lists.newArrayList(); return Lists.newArrayList();
} }
@@ -91,10 +91,16 @@ public class DataScopeViewService {
* 根据员工id 获取各数据范围最大的可见范围 map<dataScopeType,viewType></> * 根据员工id 获取各数据范围最大的可见范围 map<dataScopeType,viewType></>
*/ */
public DataScopeViewTypeEnum getEmployeeDataScopeViewType(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) { public DataScopeViewTypeEnum getEmployeeDataScopeViewType(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
if (employeeId == null) { EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
if (employeeEntity == null || employeeEntity.getEmployeeId() == null) {
return DataScopeViewTypeEnum.ME; return DataScopeViewTypeEnum.ME;
} }
// 如果是超级管理员 则可查看全部
if (employeeEntity.getAdministratorFlag()) {
return DataScopeViewTypeEnum.ALL;
}
List<Long> roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId); List<Long> roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId);
//未设置角色 默认本人 //未设置角色 默认本人
if (CollectionUtils.isEmpty(roleIdList)) { if (CollectionUtils.isEmpty(roleIdList)) {

View File

@@ -3,6 +3,8 @@ package net.lab1024.sa.admin.module.system.department.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -34,6 +36,7 @@ public class DepartmentEntity {
/** /**
* 负责人员工 id * 负责人员工 id
*/ */
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Long managerId; private Long managerId;
/** /**

View File

@@ -57,11 +57,11 @@ public class EmployeeController {
return employeeService.updateEmployee(employeeUpdateForm); return employeeService.updateEmployee(employeeUpdateForm);
} }
@Operation(summary = "更新登录人信息 @author 善逸") @Operation(summary = "更新员工个人中心信息 @author 善逸")
@PostMapping("/employee/update/login") @PostMapping("/employee/update/center")
public ResponseDTO<String> updateByLogin(@Valid @RequestBody EmployeeUpdateForm employeeUpdateForm) { public ResponseDTO<String> updateCenter(@Valid @RequestBody EmployeeUpdateCenterForm updateCenterForm) {
employeeUpdateForm.setEmployeeId(SmartRequestUtil.getRequestUserId()); updateCenterForm.setEmployeeId(SmartRequestUtil.getRequestUserId());
return employeeService.updateEmployee(employeeUpdateForm); return employeeService.updateCenter(updateCenterForm);
} }
@Operation(summary = "更新登录人头像 @author 善逸") @Operation(summary = "更新登录人头像 @author 善逸")

View File

@@ -34,31 +34,30 @@ public interface EmployeeDao extends BaseMapper<EmployeeEntity> {
*/ */
List<EmployeeVO> selectEmployeeByDisabledAndDeleted(@Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag); List<EmployeeVO> selectEmployeeByDisabledAndDeleted(@Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 更新单个 * 更新禁用状态
*/ */
void updateDisableFlag(@Param("employeeId") Long employeeId, @Param("disabledFlag") Boolean disabledFlag); void updateDisableFlag(@Param("employeeId") Long employeeId, @Param("disabledFlag") Boolean disabledFlag);
/** /**
* 通过登录名查询 * 通过登录名查询
*/ */
EmployeeEntity getByLoginName(@Param("loginName") String loginName, EmployeeEntity getByLoginName(@Param("loginName") String loginName, @Param("deletedFlag") Boolean deletedFlag);
@Param("disabledFlag") Boolean disabledFlag);
/** /**
* 通过姓名查询 * 通过姓名查询
*/ */
EmployeeEntity getByActualName(@Param("actualName") String actualName, EmployeeEntity getByActualName(@Param("actualName") String actualName, @Param("deletedFlag") Boolean deletedFlag);
@Param("disabledFlag") Boolean disabledFlag
);
/** /**
* 通过手机号查询 * 通过手机号查询
*/ */
EmployeeEntity getByPhone(@Param("phone") String phone, @Param("disabledFlag") Boolean disabledFlag); EmployeeEntity getByPhone(@Param("phone") String phone, @Param("deletedFlag") Boolean deletedFlag);
/**
* 通过邮箱账号查询
*/
EmployeeEntity getByEmail(@Param("email") String email, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取所有员工 * 获取所有员工
@@ -67,7 +66,6 @@ public interface EmployeeDao extends BaseMapper<EmployeeEntity> {
/** /**
* 获取某个部门员工数 * 获取某个部门员工数
*
*/ */
Integer countByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag); Integer countByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag);
@@ -76,39 +74,35 @@ public interface EmployeeDao extends BaseMapper<EmployeeEntity> {
*/ */
List<EmployeeVO> getEmployeeByIds(@Param("employeeIds") Collection<Long> employeeIds); List<EmployeeVO> getEmployeeByIds(@Param("employeeIds") Collection<Long> employeeIds);
/** /**
* 查询单个员工信息 * 查询单个员工信息
*/ */
EmployeeVO getEmployeeById(@Param("employeeId") Long employeeId); EmployeeVO getEmployeeById(@Param("employeeId") Long employeeId);
/** /**
* 获取某个部门的员工 * 获取某个部门的员工
*/ */
List<EmployeeEntity> selectByDepartmentId(@Param("departmentId") Long departmentId, @Param("disabledFlag") Boolean disabledFlag); List<EmployeeEntity> selectByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 查询某些部门下用户名是xxx的员工 * 查询某些部门下用户名是xxx的员工
*/ */
List<EmployeeEntity> selectByActualName(@Param("departmentIdList") List<Long> departmentIdList, @Param("actualName") String actualName, @Param("disabledFlag") Boolean disabledFlag); List<EmployeeEntity> selectByActualName(@Param("departmentIdList") List<Long> departmentIdList, @Param("actualName") String actualName, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取某批部门的员工Id * 获取某批部门的员工Id
*/ */
List<Long> getEmployeeIdByDepartmentIdList(@Param("departmentIds") List<Long> departmentIds, @Param("disabledFlag") Boolean disabledFlag); List<Long> getEmployeeIdByDepartmentIdList(@Param("departmentIds") List<Long> departmentIds, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取所有 * 获取所有
*/ */
List<Long> getEmployeeId(@Param("leaveFlag") Boolean leaveFlag, @Param("disabledFlag") Boolean disabledFlag); List<Long> getEmployeeId(@Param("leaveFlag") Boolean leaveFlag, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取某个部门的员工Id * 获取某个部门的员工Id
*/ */
List<Long> getEmployeeIdByDepartmentId(@Param("departmentId") Long departmentId, @Param("disabledFlag") Boolean disabledFlag); List<Long> getEmployeeIdByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 员工重置密码 * 员工重置密码

View File

@@ -51,17 +51,19 @@ public class EmployeeAddForm {
@Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确") @Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确")
private String phone; private String phone;
@Schema(description = "邮箱") @Schema(description = "邮箱账号")
@NotNull(message = "邮箱账号不能为空")
@Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱账号格式不正确")
private String email; private String email;
@Schema(description = "职务级别ID")
private Long positionId;
@Schema(description = "角色列表") @Schema(description = "角色列表")
private List<Long> roleIdList; private List<Long> roleIdList;
@Schema(description = "备注") @Schema(description = "备注")
@Length(max = 30, message = "备注最多200字符") @Length(max = 200, message = "备注最多200字符")
private String remark; private String remark;
@Schema(description = "职务级别ID")
private Long positionId;
} }

View File

@@ -0,0 +1,56 @@
package net.lab1024.sa.admin.module.system.employee.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import net.lab1024.sa.base.common.enumeration.GenderEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.util.SmartVerificationUtil;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
/**
* 更新员工个人中心信息
*
* @Author 1024创新实验室: 开云
* @Date 2021-12-20 21:06:49
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EmployeeUpdateCenterForm {
@Schema(hidden = true)
private Long employeeId;
@Schema(description = "姓名")
@NotNull(message = "姓名不能为空")
@Length(max = 30, message = "姓名最多30字符")
private String actualName;
@SchemaEnum(GenderEnum.class)
@CheckEnum(value = GenderEnum.class, message = "性别错误")
private Integer gender;
@Schema(description = "手机号")
@NotNull(message = "手机号不能为空")
@Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确")
private String phone;
@Schema(description = "邮箱账号")
@NotNull(message = "邮箱账号不能为空")
@Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱账号格式不正确")
private String email;
@Schema(description = "职务级别ID")
private Long positionId;
@Schema(description = "头像")
private String avatar;
@Schema(description = "备注")
@Length(max = 200, message = "备注最多200字符")
private String remark;
}

View File

@@ -168,19 +168,14 @@ public class EmployeeService {
return ResponseDTO.userErrorParam("部门不存在"); return ResponseDTO.userErrorParam("部门不存在");
} }
// 检查唯一性
EmployeeEntity existEntity = employeeDao.getByLoginName(employeeUpdateForm.getLoginName(), null); ResponseDTO<String> checkResponse = checkUniqueness(employeeId, employeeUpdateForm.getLoginName(), employeeUpdateForm.getPhone(), employeeUpdateForm.getEmail());
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) { if (!checkResponse.getOk()) {
return ResponseDTO.userErrorParam("登录名重复"); return checkResponse;
} }
existEntity = employeeDao.getByPhone(employeeUpdateForm.getPhone(), null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("手机号已存在");
}
// 不更新密码
EmployeeEntity entity = SmartBeanUtil.copy(employeeUpdateForm, EmployeeEntity.class); EmployeeEntity entity = SmartBeanUtil.copy(employeeUpdateForm, EmployeeEntity.class);
// 不更新密码
entity.setLoginPwd(null); entity.setLoginPwd(null);
// 更新数据 // 更新数据
@@ -192,6 +187,58 @@ public class EmployeeService {
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
/**
* 更新员工个人中心信息
*/
public ResponseDTO<String> updateCenter(EmployeeUpdateCenterForm updateCenterForm) {
Long employeeId = updateCenterForm.getEmployeeId();
EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
if (null == employeeEntity) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
// 检查唯一性 登录账号不能修改则不需要检查
ResponseDTO<String> checkResponse = checkUniqueness(employeeId, "", updateCenterForm.getPhone(), updateCenterForm.getEmail());
if (!checkResponse.getOk()) {
return checkResponse;
}
EmployeeEntity employee = SmartBeanUtil.copy(updateCenterForm, EmployeeEntity.class);
// 不更新密码
employee.setLoginPwd(null);
// 更新数据
employeeDao.updateById(employee);
// 清除员工缓存
loginService.clearLoginEmployeeCache(employeeId);
return ResponseDTO.ok();
}
/**
* 检查唯一性
*/
private ResponseDTO<String> checkUniqueness(Long employeeId, String loginName, String phone, String email) {
EmployeeEntity existEntity = employeeDao.getByLoginName(loginName, null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("登录名重复");
}
existEntity = employeeDao.getByPhone(phone, null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("手机号已存在");
}
existEntity = employeeDao.getByEmail(email, null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("邮箱账号已存在");
}
return ResponseDTO.ok();
}
/** /**
* 更新登录人头像 * 更新登录人头像
@@ -297,38 +344,39 @@ public class EmployeeService {
if (employeeEntity == null) { if (employeeEntity == null) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
} }
// 校验原始密码 // 校验原始密码
String oldPassword = SecurityPasswordService.getEncryptPwd(updatePasswordForm.getOldPassword()); if (!SecurityPasswordService.matchesPwd(updatePasswordForm.getOldPassword(),employeeEntity.getLoginPwd()) ) {
if (!Objects.equals(oldPassword, employeeEntity.getLoginPwd())) {
return ResponseDTO.userErrorParam("原密码有误,请重新输入"); return ResponseDTO.userErrorParam("原密码有误,请重新输入");
} }
// 新旧密码相同
if (Objects.equals(updatePasswordForm.getOldPassword(), updatePasswordForm.getNewPassword()) ){
return ResponseDTO.userErrorParam("新密码与原始密码相同,请重新输入");
}
// 校验密码复杂度 // 校验密码复杂度
ResponseDTO<String> validatePassComplexity = securityPasswordService.validatePasswordComplexity(updatePasswordForm.getNewPassword()); ResponseDTO<String> validatePassComplexity = securityPasswordService.validatePasswordComplexity(updatePasswordForm.getNewPassword());
if (!validatePassComplexity.getOk()) { if (!validatePassComplexity.getOk()) {
return validatePassComplexity; return validatePassComplexity;
} }
// 新旧密码相同
String newPassword = SecurityPasswordService.getEncryptPwd(updatePasswordForm.getNewPassword());
if (Objects.equals(oldPassword, newPassword)) {
return ResponseDTO.userErrorParam("新密码与原始密码相同,请重新输入");
}
// 根据三级等保规则,校验密码是否重复 // 根据三级等保规则,校验密码是否重复
ResponseDTO<String> passwordRepeatTimes = securityPasswordService.validatePasswordRepeatTimes(requestUser, updatePasswordForm.getNewPassword()); ResponseDTO<String> passwordRepeatTimes = securityPasswordService.validatePasswordRepeatTimes(requestUser, updatePasswordForm.getNewPassword());
if (!passwordRepeatTimes.getOk()) { if (!passwordRepeatTimes.getOk()) {
return ResponseDTO.error(passwordRepeatTimes); return ResponseDTO.error(passwordRepeatTimes);
} }
// 更新密码 // 更新密码
String newEncryptPassword = SecurityPasswordService.getEncryptPwd(updatePasswordForm.getNewPassword());
EmployeeEntity updateEntity = new EmployeeEntity(); EmployeeEntity updateEntity = new EmployeeEntity();
updateEntity.setEmployeeId(employeeId); updateEntity.setEmployeeId(employeeId);
updateEntity.setLoginPwd(newPassword); updateEntity.setLoginPwd(newEncryptPassword);
employeeDao.updateById(updateEntity); employeeDao.updateById(updateEntity);
// 保存修改密码密码记录 // 保存修改密码密码记录
securityPasswordService.saveUserChangePasswordLog(requestUser, newPassword, oldPassword); securityPasswordService.saveUserChangePasswordLog(requestUser, newEncryptPassword, employeeEntity.getLoginPwd());
return ResponseDTO.ok(); return ResponseDTO.ok();
} }

View File

@@ -59,8 +59,8 @@ public class LoginController {
@Operation(summary = "退出登陆 @author 卓大") @Operation(summary = "退出登陆 @author 卓大")
@GetMapping("/login/logout") @GetMapping("/login/logout")
public ResponseDTO<String> logout(@RequestHeader(value = RequestHeaderConst.TOKEN, required = false) String token) { public ResponseDTO<String> logout() {
return loginService.logout(token, SmartRequestUtil.getRequestUser()); return loginService.logout(SmartRequestUtil.getRequestUser());
} }
@Operation(summary = "获取验证码 @author 卓大") @Operation(summary = "获取验证码 @author 卓大")

View File

@@ -46,6 +46,12 @@ public class RequestEmployee implements RequestUser {
@Schema(description = "部门名称") @Schema(description = "部门名称")
private String departmentName; private String departmentName;
@Schema(description = "职务级别ID")
private Long positionId;
@Schema(description = "邮箱")
private String email;
@Schema(description = "是否禁用") @Schema(description = "是否禁用")
private Boolean disabledFlag; private Boolean disabledFlag;

View File

@@ -162,10 +162,15 @@ public class LoginService implements StpInterface {
// 验证登录名 // 验证登录名
EmployeeEntity employeeEntity = employeeService.getByLoginName(loginForm.getLoginName()); EmployeeEntity employeeEntity = employeeService.getByLoginName(loginForm.getLoginName());
if (null == employeeEntity) { if (null == employeeEntity) {
return ResponseDTO.userErrorParam("登录名不存在"); return ResponseDTO.userErrorParam("登录名或密码错误");
} }
// 验证账号状态 // 验证账号状态
if (employeeEntity.getDeletedFlag()) {
saveLoginLog(employeeEntity, ip, userAgent, "账号已删除", LoginLogResultEnum.LOGIN_FAIL);
return ResponseDTO.userErrorParam("您的账号已被删除,请联系工作人员!");
}
if (employeeEntity.getDisabledFlag()) { if (employeeEntity.getDisabledFlag()) {
saveLoginLog(employeeEntity, ip, userAgent, "账号已禁用", LoginLogResultEnum.LOGIN_FAIL); saveLoginLog(employeeEntity, ip, userAgent, "账号已禁用", LoginLogResultEnum.LOGIN_FAIL);
return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!"); return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!");
@@ -201,7 +206,7 @@ public class LoginService implements StpInterface {
} }
// 密码错误 // 密码错误
if (!employeeEntity.getLoginPwd().equals(SecurityPasswordService.getEncryptPwd(requestPassword))) { if ( !SecurityPasswordService.matchesPwd(requestPassword,employeeEntity.getLoginPwd()) ) {
// 记录登录失败 // 记录登录失败
saveLoginLog(employeeEntity, ip, userAgent, "密码错误", LoginLogResultEnum.LOGIN_FAIL); saveLoginLog(employeeEntity, ip, userAgent, "密码错误", LoginLogResultEnum.LOGIN_FAIL);
// 记录等级保护次数 // 记录等级保护次数
@@ -371,10 +376,10 @@ public class LoginService implements StpInterface {
/** /**
* 退出登录 * 退出登录
*/ */
public ResponseDTO<String> logout(String token, RequestUser requestUser) { public ResponseDTO<String> logout(RequestUser requestUser) {
// sa token 登出 // sa token 登出
StpUtil.logoutByTokenValue(token); StpUtil.logout();
// 清空登录信息缓存 // 清空登录信息缓存
loginEmployeeCache.remove(requestUser.getUserId()); loginEmployeeCache.remove(requestUser.getUserId());
@@ -504,10 +509,14 @@ public class LoginService implements StpInterface {
// 验证登录名 // 验证登录名
EmployeeEntity employeeEntity = employeeService.getByLoginName(loginName); EmployeeEntity employeeEntity = employeeService.getByLoginName(loginName);
if (null == employeeEntity) { if (null == employeeEntity) {
return ResponseDTO.userErrorParam("登录名不存在!"); return ResponseDTO.ok();
} }
// 验证账号状态 // 验证账号状态
if (employeeEntity.getDeletedFlag()) {
return ResponseDTO.userErrorParam("您的账号已被删除,请联系工作人员!");
}
if (employeeEntity.getDisabledFlag()) { if (employeeEntity.getDisabledFlag()) {
return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!"); return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!");
} }

View File

@@ -2,6 +2,28 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao"> <mapper namespace="net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao">
<!-- 查询结果列 -->
<sql id="base_columns">
t_notice.notice_id,
t_notice.notice_type_id,
t_notice.title,
t_notice.all_visible_flag,
t_notice.scheduled_publish_flag,
t_notice.publish_time,
t_notice.content_text,
t_notice.content_html,
t_notice.attachment,
t_notice.page_view_count,
t_notice.user_view_count,
t_notice.source,
t_notice.author,
t_notice.document_number,
t_notice.deleted_flag,
t_notice.create_user_id,
t_notice.update_time,
t_notice.create_time
</sql>
<!-- ================================== 可见范围相关 ================================== --> <!-- ================================== 可见范围相关 ================================== -->
<insert id="insertVisibleRange"> <insert id="insertVisibleRange">
@@ -35,32 +57,30 @@
<!-- 后管分页查询资讯 --> <!-- 后管分页查询资讯 -->
<select id="query" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO"> <select id="query" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO">
SELECT SELECT
t_notice.* , <include refid="base_columns"/>,
t_notice_type.notice_type_name as noticeTypeName, t_notice_type.notice_type_name as noticeTypeName,
t_employee.actual_name as createUserName, t_employee.actual_name as createUserName
t_department.name as departmentName
FROM t_notice FROM t_notice
left join t_notice_type on t_notice_type.notice_type_id = t_notice.notice_type_id LEFT JOIN t_notice_type on t_notice.notice_type_id = t_notice_type.notice_type_id
left join t_employee on t_notice.create_user_id = t_employee.employee_id LEFT JOIN t_employee on t_notice.create_user_id = t_employee.employee_id
left join t_department on t_employee.department_id = t_department.department_id
<where> <where>
<if test="query.noticeTypeId != null"> <if test="query.noticeTypeId != null">
AND t_notice_type.notice_type_id = #{query.noticeTypeId} AND t_notice_type.notice_type_id = #{query.noticeTypeId}
</if> </if>
<if test="query.keywords != null and query.keywords !=''"> <if test="query.keywords != null and query.keywords != ''">
AND ( INSTR(t_notice.title,#{query.keywords}) AND ( INSTR(t_notice.title,#{query.keywords})
OR INSTR(t_notice.author,#{query.keywords}) OR INSTR(t_notice.author,#{query.keywords})
OR INSTR(t_notice.source,#{query.keywords}) OR INSTR(t_notice.source,#{query.keywords})
) )
</if> </if>
<if test="query.documentNumber != null and query.documentNumber !=''"> <if test="query.documentNumber != null and query.documentNumber != ''">
AND INSTR(t_notice.document_number, #{query.documentNumber}) AND INSTR(t_notice.document_number, #{query.documentNumber})
</if> </if>
<if test="query.createUserId != null"> <if test="query.createUserName != null and query.createUserName != ''">
AND t_notice.create_user_id = #{createUserId} AND t_employee.actual_name = #{query.createUserName}
</if> </if>
<if test="query.deletedFlag != null"> <if test="query.deletedFlag != null">
and t_notice.deleted_flag = #{query.deletedFlag} AND t_notice.deleted_flag = #{query.deletedFlag}
</if> </if>
<if test="query.createTimeBegin != null"> <if test="query.createTimeBegin != null">
AND DATE_FORMAT(t_notice.create_time, '%Y-%m-%d') &gt;= DATE_FORMAT(#{query.createTimeBegin}, AND DATE_FORMAT(t_notice.create_time, '%Y-%m-%d') &gt;= DATE_FORMAT(#{query.createTimeBegin},
@@ -84,10 +104,9 @@
</select> </select>
<!-- ================================== 通知公告【员工查看】相关 ================================== --> <!-- ================================== 通知公告【员工查看】相关 ================================== -->
<select id="queryEmployeeNotice" <select id="queryEmployeeNotice" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
select select
t_notice.*, <include refid="base_columns"/>,
t_notice_type.notice_type_name, t_notice_type.notice_type_name,
(select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and
t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag
@@ -142,12 +161,11 @@
</where> </where>
order by t_notice.publish_time desc order by t_notice.publish_time desc
</select> </select>
<select id="queryEmployeeNotViewNotice" <select id="queryEmployeeNotViewNotice" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
select * from select * from
( (
select select
t_notice.*, <include refid="base_columns"/>,
t_notice_type.notice_type_name, t_notice_type.notice_type_name,
(select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and
t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag
@@ -198,8 +216,7 @@
) t where viewFlag = 0 ) t where viewFlag = 0
order by t.publish_time desc order by t.publish_time desc
</select> </select>
<select id="queryNoticeViewRecordList" <select id="queryNoticeViewRecordList" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeViewRecordVO">
resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeViewRecordVO">
select t_notice_view_record.*, select t_notice_view_record.*,
t_employee.actual_name as employeeName, t_employee.actual_name as employeeName,
t_department.name as departmentName t_department.name as departmentName

View File

@@ -33,21 +33,19 @@
</where> </where>
</select> </select>
<update id="updateDisableFlag"> <update id="updateDisableFlag">
UPDATE t_employee UPDATE t_employee
SET disabled_flag = #{disabledFlag} SET disabled_flag = #{disabledFlag}
WHERE employee_id = #{employeeId} WHERE employee_id = #{employeeId}
</update> </update>
<select id="getByLoginName" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity"> <select id="getByLoginName" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * SELECT *
FROM t_employee FROM t_employee
<where> <where>
login_name = #{loginName} login_name = #{loginName}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
@@ -57,24 +55,33 @@
FROM t_employee FROM t_employee
<where> <where>
actual_name = #{actualName} actual_name = #{actualName}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
<select id="getByPhone" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity"> <select id="getByPhone" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * SELECT *
FROM t_employee FROM t_employee
<where> <where>
phone = #{phone} phone = #{phone}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
<select id="getByEmail" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT *
FROM t_employee
<where>
email = #{email}
<if test="deletedFlag != null">
AND deleted_flag = #{deletedFlag}
</if>
</where>
</select>
<select id="listAll" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO"> <select id="listAll" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
SELECT * SELECT *
@@ -88,22 +95,19 @@
department_id = #{departmentId} AND deleted_flag = #{deletedFlag} department_id = #{departmentId} AND deleted_flag = #{deletedFlag}
</select> </select>
<select id="selectByDepartmentId" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
<select id="selectByDepartmentId"
resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * SELECT *
FROM t_employee FROM t_employee
<where> <where>
department_id = #{departmentId} department_id = #{departmentId}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
</select> </select>
<select id="selectByActualName" <select id="selectByActualName" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * FROM t_employee SELECT * FROM t_employee
<where> <where>
actual_name = #{actualName} actual_name = #{actualName}
@@ -111,8 +115,8 @@
<foreach collection="departmentIdList" item="item" open="(" close=")" separator=","> <foreach collection="departmentIdList" item="item" open="(" close=")" separator=",">
#{item} #{item}
</foreach> </foreach>
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
@@ -125,20 +129,19 @@
<foreach collection="departmentIds" item="item" open="(" close=")" separator=","> <foreach collection="departmentIds" item="item" open="(" close=")" separator=",">
#{item} #{item}
</foreach> </foreach>
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
</select> </select>
<select id="getEmployeeId" resultType="java.lang.Long"> <select id="getEmployeeId" resultType="java.lang.Long">
SELECT employee_id SELECT employee_id
FROM t_employee FROM t_employee
<where> <where>
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
@@ -148,8 +151,8 @@
FROM t_employee FROM t_employee
<where> <where>
department_id = #{departmentId} department_id = #{departmentId}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
@@ -164,7 +167,6 @@
ORDER BY create_time DESC ORDER BY create_time DESC
</select> </select>
<select id="getEmployeeById" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO"> <select id="getEmployeeById" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
SELECT t_employee.*, SELECT t_employee.*,
t_department.name AS departmentName t_department.name AS departmentName
@@ -173,8 +175,7 @@
where t_employee.employee_id = #{employeeId} where t_employee.employee_id = #{employeeId}
</select> </select>
<select id="selectEmployeeByDisabledAndDeleted" <select id="selectEmployeeByDisabledAndDeleted" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
SELECT SELECT
t_employee.*, t_employee.*,
t_department.name AS departmentName t_department.name AS departmentName
@@ -196,5 +197,4 @@
WHERE employee_id = #{employeeId} WHERE employee_id = #{employeeId}
</update> </update>
</mapper> </mapper>

View File

@@ -19,9 +19,8 @@
<select id="selectMenuListByRoleIdList" <select id="selectMenuListByRoleIdList"
resultType="net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity"> resultType="net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity">
SELECT SELECT
t_menu.* distinct t_menu.*
from t_menu from t_menu
left join t_role_menu on t_role_menu.menu_id = t_menu.menu_id left join t_role_menu on t_role_menu.menu_id = t_menu.menu_id
<where> <where>
@@ -35,8 +34,6 @@
</foreach> </foreach>
</if> </if>
</where> </where>
group by t_menu.menu_id
ORDER BY t_menu.sort ASC ORDER BY t_menu.sort ASC
</select> </select>
</mapper> </mapper>

View File

@@ -49,6 +49,11 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<!-- sa-token start --> <!-- sa-token start -->
<dependency> <dependency>
<groupId>cn.dev33</groupId> <groupId>cn.dev33</groupId>
@@ -172,6 +177,11 @@
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>
@@ -204,12 +214,18 @@
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId> <artifactId>bcprov-jdk18on</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>cn.idev.excel</groupId>
<artifactId>easyexcel</artifactId> <artifactId>fastexcel</artifactId>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
@@ -268,6 +284,11 @@
<artifactId>freemarker</artifactId> <artifactId>freemarker</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@@ -11,7 +11,7 @@ package net.lab1024.sa.base.common.constant;
*/ */
public class RequestHeaderConst { public class RequestHeaderConst {
public static final String TOKEN = "x-access-token"; public static final String TOKEN = "Authorization";
public static final String USER_AGENT = "user-agent"; public static final String USER_AGENT = "user-agent";

View File

@@ -1,52 +0,0 @@
package net.lab1024.sa.base.common.json.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import net.lab1024.sa.base.module.support.dict.domain.vo.DictValueVO;
import net.lab1024.sa.base.module.support.dict.service.DictCacheService;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* 字典序列化
*
* @Author 1024创新实验室: 罗伊
* @Date 2022-08-12 22:17:53
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public class DictValueVoSerializer extends JsonSerializer<String> {
@Resource
private DictCacheService dictCacheService;
@Override
public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (StringUtils.isEmpty(value)) {
jsonGenerator.writeObject(Lists.newArrayList());
return;
}
String[] valueCodeArray = value.split(",");
List<String> valueCodeList = Arrays.asList(valueCodeArray);
List<DictValueVO> dictValueVOList = Lists.newArrayList();
valueCodeList.forEach(e->{
if(StringUtils.isNotBlank(e)){
DictValueVO dictValueVO = dictCacheService.selectValueByValueCode(e);
if(dictValueVO != null){
dictValueVOList.add(dictValueVO);
}
}
});
jsonGenerator.writeObject(dictValueVOList);
}
}

View File

@@ -1,9 +1,9 @@
package net.lab1024.sa.base.common.util; package net.lab1024.sa.base.common.util;
import com.alibaba.excel.EasyExcel; import cn.idev.excel.FastExcel;
import com.alibaba.excel.write.handler.SheetWriteHandler; import cn.idev.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -43,7 +43,7 @@ public final class SmartExcelUtil {
// 设置下载消息头 // 设置下载消息头
SmartResponseUtil.setDownloadFileHeader(response, fileName, null); SmartResponseUtil.setDownloadFileHeader(response, fileName, null);
// 下载 // 下载
EasyExcel.write(response.getOutputStream(), head) FastExcel.write(response.getOutputStream(), head)
.autoCloseStream(Boolean.FALSE) .autoCloseStream(Boolean.FALSE)
.sheet(sheetName) .sheet(sheetName)
.doWrite(data); .doWrite(data);
@@ -58,7 +58,7 @@ public final class SmartExcelUtil {
// 水印 // 水印
Watermark watermark = new Watermark(watermarkString); Watermark watermark = new Watermark(watermarkString);
// 一定要inMemory // 一定要inMemory
EasyExcel.write(response.getOutputStream(), head) FastExcel.write(response.getOutputStream(), head)
.inMemory(true) .inMemory(true)
.sheet(sheetName) .sheet(sheetName)
.registerWriteHandler(new CustomWaterMarkHandler(watermark)) .registerWriteHandler(new CustomWaterMarkHandler(watermark))

View File

@@ -9,8 +9,10 @@ import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory; import org.springframework.http.MediaTypeFactory;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import static cn.hutool.core.util.CharsetUtil.UTF_8;
/** /**
* 返回工具栏 * 返回工具栏
@@ -27,8 +29,8 @@ public class SmartResponseUtil {
public static void write(HttpServletResponse response, ResponseDTO<?> responseDTO) { public static void write(HttpServletResponse response, ResponseDTO<?> responseDTO) {
// 重置response // 重置response
response.setContentType("application/json"); response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding(UTF_8);
try { try {
response.getWriter().write(JSON.toJSONString(responseDTO)); response.getWriter().write(JSON.toJSONString(responseDTO));
@@ -44,20 +46,15 @@ public class SmartResponseUtil {
} }
public static void setDownloadFileHeader(HttpServletResponse response, String fileName, Long fileSize) { public static void setDownloadFileHeader(HttpServletResponse response, String fileName, Long fileSize) {
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding(UTF_8);
try { if (fileSize != null) {
if (fileSize != null) { response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileSize));
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileSize)); }
}
if (SmartStringUtil.isNotEmpty(fileName)) { if (SmartStringUtil.isNotEmpty(fileName)) {
response.setHeader(HttpHeaders.CONTENT_TYPE, MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM) + ";charset=utf-8"); response.setHeader(HttpHeaders.CONTENT_TYPE, MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM) + ";charset=utf-8");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20")); response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20"));
response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION); response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
}
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
} }
} }

View File

@@ -77,7 +77,7 @@ public class SwaggerConfig {
private Components components() { private Components components() {
return new Components() return new Components()
.addSecuritySchemes(RequestHeaderConst.TOKEN, new SecurityScheme().type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER).name(RequestHeaderConst.TOKEN)); .addSecuritySchemes(RequestHeaderConst.TOKEN, new SecurityScheme().scheme("Bearer").description("请输入token,格式为[Bearer xxxxxxxx]").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER).name(RequestHeaderConst.TOKEN));
} }
@Bean @Bean

View File

@@ -18,5 +18,5 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
public @interface DataTracerFieldDict { public @interface DataTracerFieldDict {
String keyCode() default "";
} }

View File

@@ -303,7 +303,7 @@ public class DataTracerChangeContentService {
fieldContent = SmartEnumUtil.getEnumDescByValue(fieldValue, dataTracerFieldEnum.enumClass()); fieldContent = SmartEnumUtil.getEnumDescByValue(fieldValue, dataTracerFieldEnum.enumClass());
} }
} else if (dataTracerFieldDict != null) { } else if (dataTracerFieldDict != null) {
fieldContent = dictCacheService.selectValueNameByValueCodeSplit(fieldValue.toString()); fieldContent = dictCacheService.selectValueNameByValueCodeSplit(dataTracerFieldDict.keyCode(), fieldValue.toString());
} else if (dataTracerFieldSql != null) { } else if (dataTracerFieldSql != null) {
fieldContent = this.getRelateDisplayValue(fieldValue, dataTracerFieldSql); fieldContent = this.getRelateDisplayValue(fieldValue, dataTracerFieldSql);
} else if (fieldValue instanceof Date) { } else if (fieldValue instanceof Date) {

View File

@@ -52,5 +52,5 @@ public interface DictValueDao extends BaseMapper<DictValueEntity> {
* 跟进code查询 * 跟进code查询
* *
*/ */
DictValueEntity selectByCode(@Param("valueCode") String valueCode, @Param("deletedFlag") Boolean deletedFlag); DictValueEntity selectByCode(@Param("dictKeyId") Long dictKeyId,@Param("valueCode") String valueCode, @Param("deletedFlag") Boolean deletedFlag);
} }

View File

@@ -18,6 +18,7 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -41,8 +42,6 @@ public class DictCacheService {
private ConcurrentHashMap<String, List<DictValueVO>> DICT_CACHE = new ConcurrentHashMap<>(); private ConcurrentHashMap<String, List<DictValueVO>> DICT_CACHE = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, DictValueVO> VALUE_CACHE = new ConcurrentHashMap<>();
@PostConstruct @PostConstruct
public void dictCache() { public void dictCache() {
@@ -63,10 +62,6 @@ public class DictCacheService {
Long dictKeyId = dictKeyEntity.getDictKeyId(); Long dictKeyId = dictKeyEntity.getDictKeyId();
DICT_CACHE.put(keyCode, valueListMap.getOrDefault(dictKeyId, Lists.newArrayList())); DICT_CACHE.put(keyCode, valueListMap.getOrDefault(dictKeyId, Lists.newArrayList()));
} }
//字典值缓存
dictValueVOList.forEach(e -> {
VALUE_CACHE.put(e.getValueCode(), e);
});
log.info("################# 数据字典缓存初始化完毕 ###################"); log.info("################# 数据字典缓存初始化完毕 ###################");
} }
@@ -75,7 +70,6 @@ public class DictCacheService {
*/ */
public ResponseDTO<String> cacheRefresh() { public ResponseDTO<String> cacheRefresh() {
DICT_CACHE.clear(); DICT_CACHE.clear();
VALUE_CACHE.clear();
this.cacheInit(); this.cacheInit();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -92,37 +86,45 @@ public class DictCacheService {
/** /**
* 查询值code名称 * 查询值code名称
* * @param keyCode
* @param valueCode * @param valueCode
* @return * @return
*/ */
public String selectValueNameByValueCode(String valueCode) { public String selectValueNameByValueCode(String keyCode, String valueCode) {
if (StrUtil.isEmpty(valueCode)) { DictValueVO dictValueVO = this.selectValueByValueCode(keyCode, valueCode);
return null; if (dictValueVO == null){
}
DictValueVO dictValueVO = VALUE_CACHE.get(valueCode);
if (dictValueVO == null) {
return ""; return "";
} }
return dictValueVO.getValueName(); return dictValueVO.getValueName()
;
} }
public DictValueVO selectValueByValueCode(String valueCode) { public DictValueVO selectValueByValueCode(String keyCode, String valueCode) {
if (StrUtil.isEmpty(valueCode)) { if (StrUtil.isEmpty(valueCode)) {
return null; return null;
} }
return VALUE_CACHE.get(valueCode); if (StrUtil.isEmpty(keyCode)) {
} return null;
}
public String selectValueNameByValueCodeSplit(String valueCodes) { List<DictValueVO> dictValueVOList = DICT_CACHE.get(valueCode);
if (CollectionUtils.isEmpty(dictValueVOList)) {
return null;
}
Optional<DictValueVO> option = dictValueVOList.stream().filter(e->e.getValueCode().equals(valueCode)).findFirst();
if(option.isPresent()){
return option.get();
}
return null;
}
public String selectValueNameByValueCodeSplit(String keyCode, String valueCodes) {
if (StrUtil.isEmpty(valueCodes)) { if (StrUtil.isEmpty(valueCodes)) {
return ""; return "";
} }
List<String> valueNameList = Lists.newArrayList(); List<String> valueNameList = Lists.newArrayList();
String[] valueCodeArray = valueCodes.split(","); String[] valueCodeArray = valueCodes.split(",");
for (String valueCode : valueCodeArray) { for (String valueCode : valueCodeArray) {
DictValueVO dictValueVO = VALUE_CACHE.get(valueCode); DictValueVO dictValueVO = this.selectValueByValueCode(keyCode, valueCode);
if (dictValueVO != null) { if (dictValueVO != null) {
valueNameList.add(dictValueVO.getValueName()); valueNameList.add(dictValueVO.getValueName());
} }

View File

@@ -66,7 +66,7 @@ public class DictService {
* @return * @return
*/ */
public synchronized ResponseDTO<String> valueAdd(DictValueAddForm valueAddForm) { public synchronized ResponseDTO<String> valueAdd(DictValueAddForm valueAddForm) {
DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueAddForm.getValueCode(), false); DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueAddForm.getDictKeyId(),valueAddForm.getValueCode(), false);
if (dictValueEntity != null) { if (dictValueEntity != null) {
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST); return ResponseDTO.error(UserErrorCode.ALREADY_EXIST);
} }
@@ -106,7 +106,7 @@ public class DictService {
if (dictKeyEntity == null || dictKeyEntity.getDeletedFlag()) { if (dictKeyEntity == null || dictKeyEntity.getDeletedFlag()) {
return ResponseDTO.userErrorParam("key不能存在"); return ResponseDTO.userErrorParam("key不能存在");
} }
DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueUpdateForm.getValueCode(), false); DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueUpdateForm.getDictKeyId(),valueUpdateForm.getValueCode(), false);
if (dictValueEntity != null && !dictValueEntity.getDictValueId().equals(valueUpdateForm.getDictValueId())) { if (dictValueEntity != null && !dictValueEntity.getDictValueId().equals(valueUpdateForm.getDictValueId())) {
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST); return ResponseDTO.error(UserErrorCode.ALREADY_EXIST);
} }

View File

@@ -161,6 +161,10 @@ public class Level3ProtectConfigService {
this.maxUploadFileSizeMb = configForm.getMaxUploadFileSizeMb(); this.maxUploadFileSizeMb = configForm.getMaxUploadFileSizeMb();
} }
if (configForm.getLoginFailMaxTimes() != null) {
this.loginFailMaxTimes = configForm.getLoginFailMaxTimes();
}
if (configForm.getLoginFailLockMinutes() != null) { if (configForm.getLoginFailLockMinutes() != null) {
this.loginFailLockSeconds = configForm.getLoginFailLockMinutes() * 60; this.loginFailLockSeconds = configForm.getLoginFailLockMinutes() * 60;
} }

View File

@@ -1,14 +1,24 @@
package net.lab1024.sa.base.module.support.securityprotect.service; package net.lab1024.sa.base.module.support.securityprotect.service;
import lombok.extern.slf4j.Slf4j;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import net.lab1024.sa.base.common.domain.ResponseDTO; import net.lab1024.sa.base.common.domain.ResponseDTO;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypes;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.File; import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/** /**
* 三级等保 文件上传 相关 * 三级等保 文件 相关
* *
* @Author 1024创新实验室-主任:卓大 * @Author 1024创新实验室-主任:卓大
* @Date 2024/08/22 19:25:59 * @Date 2024/08/22 19:25:59
@@ -18,11 +28,34 @@ import java.io.File;
*/ */
@Service @Service
@Slf4j
public class SecurityFileService { public class SecurityFileService {
@Resource @Resource
private Level3ProtectConfigService level3ProtectConfigService; private Level3ProtectConfigService level3ProtectConfigService;
// 定义白名单MIME类型
private static final List<String> ALLOWED_MIME_TYPES = Arrays.asList(
"application/json",
"application/zip",
"application/x-7z-compressed",
"application/pdf",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-works",
"text/csv",
"audio/*",
"video/*",
// 图片类型 svg有安全隐患所以不使用"image/*"
"image/jpeg",
"image/png",
"image/gif",
"image/bmp"
);
/** /**
* 检测文件安全类型 * 检测文件安全类型
@@ -38,15 +71,51 @@ public class SecurityFileService {
} }
// 文件类型安全检测 // 文件类型安全检测
if (!level3ProtectConfigService.isFileDetectFlag()) { if (level3ProtectConfigService.isFileDetectFlag()) {
return ResponseDTO.ok(); String fileType = getFileMimeType(file);
if(ALLOWED_MIME_TYPES.stream()
.noneMatch(allowedType -> matchesMimeType(fileType, allowedType))){
return ResponseDTO.userErrorParam("禁止上传此文件类型");
}
} }
// 检测文件类型
// .....
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
/**
* 获取文件的 MIME 类型
*
* @param file 要检查的文件
* @return 文件的 MIME 类型
*
*/
public static String getFileMimeType(MultipartFile file) {
try {
TikaConfig tika = new TikaConfig();
Metadata metadata = new Metadata();
metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename());
TikaInputStream stream = TikaInputStream.get(file.getInputStream());
MediaType mimetype = tika.getDetector().detect(stream, metadata);
return mimetype.toString();
} catch (IOException | TikaException e) {
log.error(e.getMessage(), e);
return MimeTypes.OCTET_STREAM;
}
}
/**
* 检查文件的 MIME 类型是否与指定的MIME 类型匹配(支持通配符)
*
* @param fileType 文件的 MIME 类型
* @param mimetype MIME 类型(支持通配符)
* @return 是否匹配
*/
private static boolean matchesMimeType(String fileType, String mimetype) {
if (mimetype.endsWith("/*")) {
String prefix = mimetype.substring(0, mimetype.length() - 1);
return fileType.startsWith(prefix);
} else {
return fileType.equalsIgnoreCase(mimetype);
}
}
} }
;

View File

@@ -8,6 +8,7 @@ import net.lab1024.sa.base.module.support.securityprotect.dao.PasswordLogDao;
import net.lab1024.sa.base.module.support.securityprotect.domain.PasswordLogEntity; import net.lab1024.sa.base.module.support.securityprotect.domain.PasswordLogEntity;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -34,10 +35,8 @@ public class SecurityPasswordService {
public static final String PASSWORD_FORMAT_MSG = "密码必须为长度8-20位且必须包含大小写字母、数字、特殊符号@#$%^&*()_+-=)等三种字符"; public static final String PASSWORD_FORMAT_MSG = "密码必须为长度8-20位且必须包含大小写字母、数字、特殊符号@#$%^&*()_+-=)等三种字符";
private static final int PASSWORD_LENGTH = 8; private static final int PASSWORD_LENGTH = 8;
private static final String PASSWORD_SALT_FORMAT = "smart_%s_admin_$^&*";
@Resource @Resource
@@ -46,6 +45,8 @@ public class SecurityPasswordService {
@Resource @Resource
private Level3ProtectConfigService level3ProtectConfigService; private Level3ProtectConfigService level3ProtectConfigService;
static Argon2PasswordEncoder ARGON2_PASSWORD_ENCODER = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
/** /**
* 校验密码复杂度 * 校验密码复杂度
*/ */
@@ -84,8 +85,9 @@ public class SecurityPasswordService {
// 检查最近几次是否有重复密码 // 检查最近几次是否有重复密码
List<String> oldPasswords = passwordLogDao.selectOldPassword(requestUser.getUserType().getValue(), requestUser.getUserId(), level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes()); List<String> oldPasswords = passwordLogDao.selectOldPassword(requestUser.getUserType().getValue(), requestUser.getUserId(), level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes());
if (oldPasswords != null && oldPasswords.contains(getEncryptPwd(newPassword))) { boolean isDuplicate = oldPasswords.stream().anyMatch(oldPassword -> ARGON2_PASSWORD_ENCODER.matches(newPassword, oldPassword));
return ResponseDTO.userErrorParam(String.format("与前%s个历史密码重复请换个密码!", level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes())); if (isDuplicate) {
return ResponseDTO.userErrorParam(String.format("与前%d个历史密码重复请换个密码!", level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes()));
} }
return ResponseDTO.ok(); return ResponseDTO.ok();
@@ -143,7 +145,14 @@ public class SecurityPasswordService {
* 获取 加密后 的密码 * 获取 加密后 的密码
*/ */
public static String getEncryptPwd(String password) { public static String getEncryptPwd(String password) {
return DigestUtils.md5Hex(String.format(PASSWORD_SALT_FORMAT, password)); return ARGON2_PASSWORD_ENCODER.encode(password);
}
/**
* 校验密码是否匹配
*/
public static Boolean matchesPwd( String password, String encodedPassword){
return ARGON2_PASSWORD_ENCODER.matches( password, encodedPassword);
} }
} }

View File

@@ -37,14 +37,14 @@ public interface ${name.upperCamel}Dao extends BaseMapper<${name.upperCamel}Enti
/** /**
* 更新删除状态 * 更新删除状态
*/ */
long updateDeleted(@Param("${primaryKeyFieldName}")${primaryKeyJavaType} ${primaryKeyFieldName},@Param("deletedFlag")boolean deletedFlag); long updateDeleted(@Param("${primaryKeyFieldName}") ${primaryKeyJavaType} ${primaryKeyFieldName}, @Param("deletedFlag") boolean deletedFlag);
#end #end
#if($deleteInfo.deleteEnum == "Batch" || $deleteInfo.deleteEnum == "SingleAndBatch") #if($deleteInfo.deleteEnum == "Batch" || $deleteInfo.deleteEnum == "SingleAndBatch")
/** /**
* 批量更新删除状态 * 批量更新删除状态
*/ */
void batchUpdateDeleted(@Param("idList")List<${primaryKeyJavaType}> idList,@Param("deletedFlag")boolean deletedFlag); void batchUpdateDeleted(@Param("idList") List<${primaryKeyJavaType}> idList, @Param("deletedFlag") boolean deletedFlag);
#end #end
#end #end

View File

@@ -10,13 +10,13 @@ SET @parent_id = NULL;
SELECT t_menu.menu_id INTO @parent_id FROM t_menu WHERE t_menu.menu_name = '${basic.description}'; SELECT t_menu.menu_id INTO @parent_id FROM t_menu WHERE t_menu.menu_name = '${basic.description}';
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id ) INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '查询', 3, @parent_id, false, true, true, false, '${name.lowerCamel}:query', 1, @parent_id, 1 ); VALUES ( '查询', 3, @parent_id, false, false, true, false, '${name.lowerCamel}:query', 1, @parent_id, 1 );
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id ) INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '添加', 3, @parent_id, false, true, true, false, '${name.lowerCamel}:add', 1, @parent_id, 1 ); VALUES ( '添加', 3, @parent_id, false, false, true, false, '${name.lowerCamel}:add', 1, @parent_id, 1 );
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id ) INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '更新', 3, @parent_id, false, true, true, false, '${name.lowerCamel}:update', 1, @parent_id, 1 ); VALUES ( '更新', 3, @parent_id, false, false, true, false, '${name.lowerCamel}:update', 1, @parent_id, 1 );
INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id ) INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, api_perms, perms_type, context_menu_id, create_user_id )
VALUES ( '删除', 3, @parent_id, false, true, true, false, '${name.lowerCamel}:delete', 1, @parent_id, 1 ); VALUES ( '删除', 3, @parent_id, false, false, true, false, '${name.lowerCamel}:delete', 1, @parent_id, 1 );

View File

@@ -132,7 +132,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bearer
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -29,7 +29,7 @@
<select id="selectByCode" <select id="selectByCode"
resultType="net.lab1024.sa.base.module.support.dict.domain.entity.DictValueEntity"> resultType="net.lab1024.sa.base.module.support.dict.domain.entity.DictValueEntity">
select * from t_dict_value where value_code = #{valueCode} and deleted_flag = #{deletedFlag} select * from t_dict_value where dict_Key_id = #{dictKeyId} and value_code = #{valueCode} and deleted_flag = #{deletedFlag}
</select> </select>
<select id="selectByDeletedFlag" <select id="selectByDeletedFlag"

View File

@@ -132,7 +132,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bear
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -129,7 +129,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bear
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -132,7 +132,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bear
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -1 +0,0 @@
# Smart Admin API

View File

@@ -21,6 +21,7 @@
<java.version>1.8</java.version> <java.version>1.8</java.version>
<springboot.version>2.7.18</springboot.version> <springboot.version>2.7.18</springboot.version>
<spring-mock.version>2.0.8</spring-mock.version> <spring-mock.version>2.0.8</spring-mock.version>
<spring-security-crypto.version>5.8.16</spring-security-crypto.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version> <mybatis-plus.version>3.5.2</mybatis-plus.version>
<mysql-connector-j.version>8.0.33</mysql-connector-j.version> <mysql-connector-j.version>8.0.33</mysql-connector-j.version>
<p6spy.version>3.9.1</p6spy.version> <p6spy.version>3.9.1</p6spy.version>
@@ -35,10 +36,11 @@
<commons-io.version>2.15.0</commons-io.version> <commons-io.version>2.15.0</commons-io.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<commons-collections4.version>4.4</commons-collections4.version> <commons-collections4.version>4.4</commons-collections4.version>
<commons-compress.version>1.26.0</commons-compress.version>
<commons-codec.version>1.13</commons-codec.version> <commons-codec.version>1.13</commons-codec.version>
<commons-text.version>1.9</commons-text.version> <commons-text.version>1.9</commons-text.version>
<xerces.version>2.12.0</xerces.version> <xerces.version>2.12.0</xerces.version>
<easy-excel.version>3.3.2</easy-excel.version> <fast-excel.version>1.0.0</fast-excel.version>
<poi.version>5.2.4</poi.version> <poi.version>5.2.4</poi.version>
<ooxml-schemas.version>1.4</ooxml-schemas.version> <ooxml-schemas.version>1.4</ooxml-schemas.version>
<aws-java-sdk.version>1.11.842</aws-java-sdk.version> <aws-java-sdk.version>1.11.842</aws-java-sdk.version>
@@ -50,7 +52,7 @@
<velocity-tools.version>3.1</velocity-tools.version> <velocity-tools.version>3.1</velocity-tools.version>
<sa-token.version>1.37.0</sa-token.version> <sa-token.version>1.37.0</sa-token.version>
<ip2region.version>2.7.0</ip2region.version> <ip2region.version>2.7.0</ip2region.version>
<bcprov.version>1.59</bcprov.version> <bcprov.version>1.80</bcprov.version>
<jackson-datatype-jsr310.version>2.13.4</jackson-datatype-jsr310.version> <jackson-datatype-jsr310.version>2.13.4</jackson-datatype-jsr310.version>
<jackson-dataformat-yaml.version>2.16.1</jackson-dataformat-yaml.version> <jackson-dataformat-yaml.version>2.16.1</jackson-dataformat-yaml.version>
<smartdb.version>1.2.0</smartdb.version> <smartdb.version>1.2.0</smartdb.version>
@@ -58,6 +60,7 @@
<snakeyaml.version>2.2</snakeyaml.version> <snakeyaml.version>2.2</snakeyaml.version>
<freemarker.version>2.3.33</freemarker.version> <freemarker.version>2.3.33</freemarker.version>
<jsoup.version>1.18.1</jsoup.version> <jsoup.version>1.18.1</jsoup.version>
<tika.version>2.9.3</tika.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@@ -85,6 +88,12 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>${spring-security-crypto.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
@@ -181,6 +190,12 @@
<version>${commons-collections4.version}</version> <version>${commons-collections4.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.version}</version>
</dependency>
<dependency> <dependency>
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>
@@ -261,18 +276,18 @@
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId> <artifactId>bcprov-jdk18on</artifactId>
<version>${bcprov.version}</version> <version>${bcprov.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>cn.idev.excel</groupId>
<artifactId>easyexcel</artifactId> <artifactId>fastexcel</artifactId>
<version>${easy-excel.version}</version> <version>${fast-excel.version}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<artifactId>poi-ooxml-schemas</artifactId> <artifactId>logback-classic</artifactId>
<groupId>org.apache.poi</groupId> <groupId>ch.qos.logback</groupId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
@@ -363,6 +378,12 @@
<version>${freemarker.version}</version> <version>${freemarker.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>${tika.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@@ -4,21 +4,15 @@ import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.exception.SaTokenException; import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaStrategy; import cn.dev33.satoken.strategy.SaStrategy;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee; import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee;
import net.lab1024.sa.admin.module.system.login.service.LoginService; import net.lab1024.sa.admin.module.system.login.service.LoginService;
import net.lab1024.sa.base.common.annoation.NoNeedLogin; import net.lab1024.sa.base.common.annoation.NoNeedLogin;
import net.lab1024.sa.base.common.code.SystemErrorCode; import net.lab1024.sa.base.common.code.SystemErrorCode;
import net.lab1024.sa.base.common.code.UserErrorCode; import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.constant.StringConst;
import net.lab1024.sa.base.common.domain.ResponseDTO; import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.domain.SystemEnvironment;
import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum;
import net.lab1024.sa.base.common.enumeration.UserTypeEnum;
import net.lab1024.sa.base.common.util.SmartRequestUtil; import net.lab1024.sa.base.common.util.SmartRequestUtil;
import net.lab1024.sa.base.common.util.SmartResponseUtil; import net.lab1024.sa.base.common.util.SmartResponseUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -47,9 +41,6 @@ public class AdminInterceptor implements HandlerInterceptor {
@Resource @Resource
private LoginService loginService; private LoginService loginService;
@Resource
private SystemEnvironment systemEnvironment;
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
@@ -68,17 +59,7 @@ public class AdminInterceptor implements HandlerInterceptor {
// --------------- 第一步: 根据token 获取用户 --------------- // --------------- 第一步: 根据token 获取用户 ---------------
String tokenValue = StpUtil.getTokenValue(); String tokenValue = StpUtil.getTokenValue();
boolean debugNumberTokenFlag = isDevDebugNumberToken(tokenValue); String loginId = (String) StpUtil.getLoginIdByToken(tokenValue);
String loginId = null;
if (debugNumberTokenFlag) {
//开发、测试环境,且为数字的话,则表明为 调试临时用户,即需要调用 sa-token switch
loginId = UserTypeEnum.ADMIN_EMPLOYEE.getValue() + StringConst.COLON + tokenValue;
StpUtil.switchTo(loginId);
} else {
loginId = (String) StpUtil.getLoginIdByToken(tokenValue);
}
RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request); RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request);
// --------------- 第二步: 校验 登录 --------------- // --------------- 第二步: 校验 登录 ---------------
@@ -86,7 +67,7 @@ public class AdminInterceptor implements HandlerInterceptor {
Method method = ((HandlerMethod) handler).getMethod(); Method method = ((HandlerMethod) handler).getMethod();
NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class); NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class);
if (noNeedLogin != null) { if (noNeedLogin != null) {
checkActiveTimeout(requestEmployee, debugNumberTokenFlag); checkActiveTimeout(requestEmployee);
return true; return true;
} }
@@ -96,7 +77,7 @@ public class AdminInterceptor implements HandlerInterceptor {
} }
// 检测token 活跃频率 // 检测token 活跃频率
checkActiveTimeout(requestEmployee, debugNumberTokenFlag); checkActiveTimeout(requestEmployee);
// --------------- 第三步: 校验 权限 --------------- // --------------- 第三步: 校验 权限 ---------------
@@ -143,13 +124,7 @@ public class AdminInterceptor implements HandlerInterceptor {
/** /**
* 检测token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结 * 检测token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结
*/ */
private void checkActiveTimeout(RequestEmployee requestEmployee, boolean debugNumberTokenFlag) { private void checkActiveTimeout(RequestEmployee requestEmployee) {
// 对于开发环境的 数字 debug token ,不需要检测活跃有效期
if (debugNumberTokenFlag) {
return;
}
// 用户不在线,也不用检测 // 用户不在线,也不用检测
if (requestEmployee == null) { if (requestEmployee == null) {
return; return;
@@ -160,29 +135,9 @@ public class AdminInterceptor implements HandlerInterceptor {
} }
/**
* 是否为开发使用的 debug token
*
* @param token
* @return
*/
private boolean isDevDebugNumberToken(String token) {
if (!StrUtil.isNumeric(token)) {
return false;
}
return systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.DEV
|| systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.TEST;
}
@Override @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 清除上下文 // 清除上下文
SmartRequestUtil.remove(); SmartRequestUtil.remove();
// 开发环境,关闭 sa token 的临时切换用户
if (systemEnvironment.getCurrentEnvironment() == SystemEnvironmentEnum.DEV) {
StpUtil.endSwitch();
}
} }
} }

View File

@@ -1,6 +1,6 @@
package net.lab1024.sa.admin.module.business.goods.domain.form; package net.lab1024.sa.admin.module.business.goods.domain.form;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@@ -1,6 +1,6 @@
package net.lab1024.sa.admin.module.business.goods.domain.vo; package net.lab1024.sa.admin.module.business.goods.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;

View File

@@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum; import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum;
import net.lab1024.sa.base.common.json.serializer.DictValueVoSerializer;
import net.lab1024.sa.base.common.swagger.SchemaEnum; import net.lab1024.sa.base.common.swagger.SchemaEnum;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -32,7 +31,6 @@ public class GoodsVO {
private Integer goodsStatus; private Integer goodsStatus;
@Schema(description = "产地") @Schema(description = "产地")
@JsonSerialize(using = DictValueVoSerializer.class)
private String place; private String place;
@Schema(description = "商品价格") @Schema(description = "商品价格")

View File

@@ -1,6 +1,6 @@
package net.lab1024.sa.admin.module.business.goods.service; package net.lab1024.sa.admin.module.business.goods.service;
import com.alibaba.excel.EasyExcel; import cn.idev.excel.FastExcel;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -174,7 +174,7 @@ public class GoodsService {
public ResponseDTO<String> importGoods(MultipartFile file) { public ResponseDTO<String> importGoods(MultipartFile file) {
List<GoodsImportForm> dataList; List<GoodsImportForm> dataList;
try { try {
dataList = EasyExcel.read(file.getInputStream()).head(GoodsImportForm.class) dataList = FastExcel.read(file.getInputStream()).head(GoodsImportForm.class)
.sheet() .sheet()
.doReadSync(); .doReadSync();
} catch (IOException e) { } catch (IOException e) {
@@ -194,12 +194,13 @@ public class GoodsService {
*/ */
public List<GoodsExcelVO> getAllGoods() { public List<GoodsExcelVO> getAllGoods() {
List<GoodsEntity> goodsEntityList = goodsDao.selectList(null); List<GoodsEntity> goodsEntityList = goodsDao.selectList(null);
String keyCode="GODOS_PLACE";
return goodsEntityList.stream() return goodsEntityList.stream()
.map(e -> .map(e ->
GoodsExcelVO.builder() GoodsExcelVO.builder()
.goodsStatus(SmartEnumUtil.getEnumDescByValue(e.getGoodsStatus(), GoodsStatusEnum.class)) .goodsStatus(SmartEnumUtil.getEnumDescByValue(e.getGoodsStatus(), GoodsStatusEnum.class))
.categoryName(categoryQueryService.queryCategoryName(e.getCategoryId())) .categoryName(categoryQueryService.queryCategoryName(e.getCategoryId()))
.place(Arrays.stream(e.getPlace().split(",")).map(code -> dictCacheService.selectValueNameByValueCode(code)).collect(Collectors.joining(","))) .place(Arrays.stream(e.getPlace().split(",")).map(code -> dictCacheService.selectValueNameByValueCode(keyCode,code)).collect(Collectors.joining(",")))
.price(e.getPrice()) .price(e.getPrice())
.goodsName(e.getGoodsName()) .goodsName(e.getGoodsName())
.remark(e.getRemark()) .remark(e.getRemark())

View File

@@ -1,6 +1,6 @@
package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo; package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data; import lombok.Data;
/** /**

View File

@@ -28,7 +28,7 @@ public class NoticeQueryForm extends PageParam {
private String documentNumber; private String documentNumber;
@Schema(description = "创建人") @Schema(description = "创建人")
private Long createUserId; private String createUserName;
@Schema(description = "删除标识") @Schema(description = "删除标识")
private Boolean deletedFlag; private Boolean deletedFlag;

View File

@@ -208,6 +208,10 @@ public class NoticeService {
} }
NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class); NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class);
NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(noticeEntity.getNoticeTypeId());
updateFormVO.setNoticeTypeName(noticeType.getNoticeTypeName());
updateFormVO.setPublishFlag(updateFormVO.getPublishTime() != null && updateFormVO.getPublishTime().isBefore(LocalDateTime.now()));
if (!updateFormVO.getAllVisibleFlag()) { if (!updateFormVO.getAllVisibleFlag()) {
List<NoticeVisibleRangeVO> noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId); List<NoticeVisibleRangeVO> noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId);
List<Long> employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType())) List<Long> employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType()))

View File

@@ -5,7 +5,7 @@ import net.lab1024.sa.base.common.enumeration.BaseEnum;
/** /**
* 数据范围 种类 * 数据可见范围类型
* *
* @Author 1024创新实验室: 罗伊 * @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17 * @Date 2020/11/28 20:59:17

View File

@@ -25,7 +25,7 @@ public class DataScopeSqlConfig {
/** /**
* join sql 具体实现类 * join sql 具体实现类
*/ */
private Class joinSqlImplClazz; private Class<?> joinSqlImplClazz;
private String joinSql; private String joinSql;

View File

@@ -5,7 +5,7 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
/** /**
* 数据范围 * 数据可见范围
* *
* @Author 1024创新实验室: 罗伊 * @Author 1024创新实验室: 罗伊
* @Date 2020/11/28 20:59:17 * @Date 2020/11/28 20:59:17

View File

@@ -33,7 +33,7 @@ import java.util.concurrent.ConcurrentHashMap;
* @Date 2020/11/28 20:59:17 * @Date 2020/11/28 20:59:17
* @Wechat zhuoda1024 * @Wechat zhuoda1024
* @Email lab1024@163.com * @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a> * @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/ */
@Slf4j @Slf4j
@Service @Service
@@ -46,6 +46,11 @@ public class DataScopeSqlConfigService {
private static final String DEPARTMENT_PARAM = "#departmentIds"; private static final String DEPARTMENT_PARAM = "#departmentIds";
/**
* 用于拼接查看本人数据范围的 SQL
*/
private static final String CREATE_USER_ID_EQUALS = "create_user_id = ";
private final ConcurrentHashMap<String, DataScopeSqlConfig> dataScopeMethodMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, DataScopeSqlConfig> dataScopeMethodMap = new ConcurrentHashMap<>();
@Resource @Resource
@@ -84,7 +89,6 @@ public class DataScopeSqlConfigService {
/** /**
* 根据调用的方法获取,此方法的配置信息 * 根据调用的方法获取,此方法的配置信息
*
*/ */
public DataScopeSqlConfig getSqlConfig(String method) { public DataScopeSqlConfig getSqlConfig(String method) {
return this.dataScopeMethodMap.get(method); return this.dataScopeMethodMap.get(method);
@@ -94,14 +98,23 @@ public class DataScopeSqlConfigService {
* 组装需要拼接的sql * 组装需要拼接的sql
*/ */
public String getJoinSql(Map<String, Object> paramMap, DataScopeSqlConfig sqlConfigDTO) { public String getJoinSql(Map<String, Object> paramMap, DataScopeSqlConfig sqlConfigDTO) {
DataScopeTypeEnum dataScopeTypeEnum = sqlConfigDTO.getDataScopeType();
String joinSql = sqlConfigDTO.getJoinSql();
Long employeeId = SmartRequestUtil.getRequestUserId(); Long employeeId = SmartRequestUtil.getRequestUserId();
if (employeeId == null) { if (employeeId == null) {
return ""; return "";
} }
DataScopeTypeEnum dataScopeTypeEnum = sqlConfigDTO.getDataScopeType();
DataScopeViewTypeEnum viewTypeEnum = dataScopeViewService.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
// 数据权限设置为仅本人可见时 直接返回 create_user_id = employeeId
if (DataScopeViewTypeEnum.ME == viewTypeEnum) {
return CREATE_USER_ID_EQUALS + employeeId;
}
String joinSql = sqlConfigDTO.getJoinSql();
if (DataScopeWhereInTypeEnum.CUSTOM_STRATEGY == sqlConfigDTO.getDataScopeWhereInType()) { if (DataScopeWhereInTypeEnum.CUSTOM_STRATEGY == sqlConfigDTO.getDataScopeWhereInType()) {
Class strategyClass = sqlConfigDTO.getJoinSqlImplClazz(); Class<?> strategyClass = sqlConfigDTO.getJoinSqlImplClazz();
if (strategyClass == null) { if (strategyClass == null) {
log.warn("data scope custom strategy class is null"); log.warn("data scope custom strategy class is null");
return ""; return "";
@@ -111,11 +124,10 @@ public class DataScopeSqlConfigService {
log.warn("data scope custom strategy class{} ,bean is null", sqlConfigDTO.getJoinSqlImplClazz()); log.warn("data scope custom strategy class{} ,bean is null", sqlConfigDTO.getJoinSqlImplClazz());
return ""; return "";
} }
DataScopeViewTypeEnum viewTypeEnum = dataScopeViewService.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId); return powerStrategy.getCondition(viewTypeEnum, paramMap, sqlConfigDTO);
return powerStrategy.getCondition(viewTypeEnum,paramMap, sqlConfigDTO);
} }
if (DataScopeWhereInTypeEnum.EMPLOYEE == sqlConfigDTO.getDataScopeWhereInType()) { if (DataScopeWhereInTypeEnum.EMPLOYEE == sqlConfigDTO.getDataScopeWhereInType()) {
List<Long> canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(dataScopeTypeEnum, employeeId); List<Long> canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(viewTypeEnum, employeeId);
if (CollectionUtils.isEmpty(canViewEmployeeIds)) { if (CollectionUtils.isEmpty(canViewEmployeeIds)) {
return ""; return "";
} }
@@ -124,7 +136,7 @@ public class DataScopeSqlConfigService {
return sql; return sql;
} }
if (DataScopeWhereInTypeEnum.DEPARTMENT == sqlConfigDTO.getDataScopeWhereInType()) { if (DataScopeWhereInTypeEnum.DEPARTMENT == sqlConfigDTO.getDataScopeWhereInType()) {
List<Long> canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(dataScopeTypeEnum, employeeId); List<Long> canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(viewTypeEnum, employeeId);
if (CollectionUtils.isEmpty(canViewDepartmentIds)) { if (CollectionUtils.isEmpty(canViewDepartmentIds)) {
return ""; return "";
} }

View File

@@ -44,10 +44,9 @@ public class DataScopeViewService {
private DepartmentService departmentService; private DepartmentService departmentService;
/** /**
* 获取某人可以查看的所有人员信息 * 获取某人可以查看的所有人员数据
*/ */
public List<Long> getCanViewEmployeeId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) { public List<Long> getCanViewEmployeeId(DataScopeViewTypeEnum viewType, Long employeeId) {
DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
if (DataScopeViewTypeEnum.ME == viewType) { if (DataScopeViewTypeEnum.ME == viewType) {
return this.getMeEmployeeIdList(employeeId); return this.getMeEmployeeIdList(employeeId);
} }
@@ -57,16 +56,17 @@ public class DataScopeViewService {
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) { if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) {
return this.getDepartmentAndSubEmployeeIdList(employeeId); return this.getDepartmentAndSubEmployeeIdList(employeeId);
} }
// 可以查看所有员工数据
return Lists.newArrayList(); return Lists.newArrayList();
} }
/** /**
* 获取某人可以查看的所有部门信息 * 获取某人可以查看的所有部门数据
*/ */
public List<Long> getCanViewDepartmentId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) { public List<Long> getCanViewDepartmentId(DataScopeViewTypeEnum viewType, Long employeeId) {
DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
if (DataScopeViewTypeEnum.ME == viewType) { if (DataScopeViewTypeEnum.ME == viewType) {
return this.getMeDepartmentIdList(employeeId); // 数据可见范围类型为本人时 不可以查看任何部门数据
return Lists.newArrayList(0L);
} }
if (DataScopeViewTypeEnum.DEPARTMENT == viewType) { if (DataScopeViewTypeEnum.DEPARTMENT == viewType) {
return this.getMeDepartmentIdList(employeeId); return this.getMeDepartmentIdList(employeeId);
@@ -74,6 +74,7 @@ public class DataScopeViewService {
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) { if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) {
return this.getDepartmentAndSubIdList(employeeId); return this.getDepartmentAndSubIdList(employeeId);
} }
// 可以查看所有部门数据
return Lists.newArrayList(); return Lists.newArrayList();
} }
@@ -91,10 +92,16 @@ public class DataScopeViewService {
* 根据员工id 获取各数据范围最大的可见范围 map<dataScopeType,viewType></> * 根据员工id 获取各数据范围最大的可见范围 map<dataScopeType,viewType></>
*/ */
public DataScopeViewTypeEnum getEmployeeDataScopeViewType(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) { public DataScopeViewTypeEnum getEmployeeDataScopeViewType(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
if (employeeId == null) { EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
if (employeeEntity == null || employeeEntity.getEmployeeId() == null) {
return DataScopeViewTypeEnum.ME; return DataScopeViewTypeEnum.ME;
} }
// 如果是超级管理员 则可查看全部
if (employeeEntity.getAdministratorFlag()) {
return DataScopeViewTypeEnum.ALL;
}
List<Long> roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId); List<Long> roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId);
//未设置角色 默认本人 //未设置角色 默认本人
if (CollectionUtils.isEmpty(roleIdList)) { if (CollectionUtils.isEmpty(roleIdList)) {

View File

@@ -3,6 +3,8 @@ package net.lab1024.sa.admin.module.system.department.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -34,6 +36,7 @@ public class DepartmentEntity {
/** /**
* 负责人员工 id * 负责人员工 id
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Long managerId; private Long managerId;
/** /**

View File

@@ -57,11 +57,11 @@ public class EmployeeController {
return employeeService.updateEmployee(employeeUpdateForm); return employeeService.updateEmployee(employeeUpdateForm);
} }
@Operation(summary = "更新登录人信息 @author 善逸") @Operation(summary = "更新员工个人中心信息 @author 善逸")
@PostMapping("/employee/update/login") @PostMapping("/employee/update/center")
public ResponseDTO<String> updateByLogin(@Valid @RequestBody EmployeeUpdateForm employeeUpdateForm) { public ResponseDTO<String> updateCenter(@Valid @RequestBody EmployeeUpdateCenterForm updateCenterForm) {
employeeUpdateForm.setEmployeeId(SmartRequestUtil.getRequestUserId()); updateCenterForm.setEmployeeId(SmartRequestUtil.getRequestUserId());
return employeeService.updateEmployee(employeeUpdateForm); return employeeService.updateCenter(updateCenterForm);
} }
@Operation(summary = "更新登录人头像 @author 善逸") @Operation(summary = "更新登录人头像 @author 善逸")
@@ -117,7 +117,7 @@ public class EmployeeController {
@Operation(summary = "查询员工-根据部门id @author 卓大") @Operation(summary = "查询员工-根据部门id @author 卓大")
@GetMapping("/employee/getAllEmployeeByDepartmentId/{departmentId}") @GetMapping("/employee/getAllEmployeeByDepartmentId/{departmentId}")
public ResponseDTO<List<EmployeeVO>> getAllEmployeeByDepartmentId(@PathVariable Long departmentId) { public ResponseDTO<List<EmployeeVO>> getAllEmployeeByDepartmentId(@PathVariable Long departmentId) {
return employeeService.getAllEmployeeByDepartmentId(departmentId, Boolean.FALSE); return employeeService.getAllEmployeeByDepartmentId(departmentId);
} }
@Operation(summary = "查询所有员工 @author 卓大") @Operation(summary = "查询所有员工 @author 卓大")

View File

@@ -34,31 +34,30 @@ public interface EmployeeDao extends BaseMapper<EmployeeEntity> {
*/ */
List<EmployeeVO> selectEmployeeByDisabledAndDeleted(@Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag); List<EmployeeVO> selectEmployeeByDisabledAndDeleted(@Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 更新单个 * 更新单个
*/ */
void updateDisableFlag(@Param("employeeId") Long employeeId, @Param("disabledFlag") Boolean disabledFlag); void updateDisableFlag(@Param("employeeId") Long employeeId, @Param("disabledFlag") Boolean disabledFlag);
/** /**
* 通过登录名查询 * 通过登录名查询
*/ */
EmployeeEntity getByLoginName(@Param("loginName") String loginName, EmployeeEntity getByLoginName(@Param("loginName") String loginName, @Param("deletedFlag") Boolean deletedFlag);
@Param("disabledFlag") Boolean disabledFlag);
/** /**
* 通过姓名查询 * 通过姓名查询
*/ */
EmployeeEntity getByActualName(@Param("actualName") String actualName, EmployeeEntity getByActualName(@Param("actualName") String actualName, @Param("deletedFlag") Boolean deletedFlag);
@Param("disabledFlag") Boolean disabledFlag
);
/** /**
* 通过手机号查询 * 通过手机号查询
*/ */
EmployeeEntity getByPhone(@Param("phone") String phone, @Param("disabledFlag") Boolean disabledFlag); EmployeeEntity getByPhone(@Param("phone") String phone, @Param("deletedFlag") Boolean deletedFlag);
/**
* 通过邮箱账号查询
*/
EmployeeEntity getByEmail(@Param("email") String email, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取所有员工 * 获取所有员工
@@ -67,7 +66,6 @@ public interface EmployeeDao extends BaseMapper<EmployeeEntity> {
/** /**
* 获取某个部门员工数 * 获取某个部门员工数
*
*/ */
Integer countByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag); Integer countByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag);
@@ -76,39 +74,35 @@ public interface EmployeeDao extends BaseMapper<EmployeeEntity> {
*/ */
List<EmployeeVO> getEmployeeByIds(@Param("employeeIds") Collection<Long> employeeIds); List<EmployeeVO> getEmployeeByIds(@Param("employeeIds") Collection<Long> employeeIds);
/** /**
* 查询单个员工信息 * 查询单个员工信息
*/ */
EmployeeVO getEmployeeById(@Param("employeeId") Long employeeId); EmployeeVO getEmployeeById(@Param("employeeId") Long employeeId);
/** /**
* 获取某个部门的员工 * 获取某个部门的员工
*/ */
List<EmployeeEntity> selectByDepartmentId(@Param("departmentId") Long departmentId, @Param("disabledFlag") Boolean disabledFlag); List<EmployeeEntity> selectByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 查询某些部门下用户名是xxx的员工 * 查询某些部门下用户名是xxx的员工
*/ */
List<EmployeeEntity> selectByActualName(@Param("departmentIdList") List<Long> departmentIdList, @Param("actualName") String actualName, @Param("disabledFlag") Boolean disabledFlag); List<EmployeeEntity> selectByActualName(@Param("departmentIdList") List<Long> departmentIdList, @Param("actualName") String actualName, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取某批部门的员工Id * 获取某批部门的员工Id
*/ */
List<Long> getEmployeeIdByDepartmentIdList(@Param("departmentIds") List<Long> departmentIds, @Param("disabledFlag") Boolean disabledFlag); List<Long> getEmployeeIdByDepartmentIdList(@Param("departmentIds") List<Long> departmentIds, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取所有 * 获取所有
*/ */
List<Long> getEmployeeId(@Param("leaveFlag") Boolean leaveFlag, @Param("disabledFlag") Boolean disabledFlag); List<Long> getEmployeeId(@Param("leaveFlag") Boolean leaveFlag, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 获取某个部门的员工Id * 获取某个部门的员工Id
*/ */
List<Long> getEmployeeIdByDepartmentId(@Param("departmentId") Long departmentId, @Param("disabledFlag") Boolean disabledFlag); List<Long> getEmployeeIdByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag);
/** /**
* 员工重置密码 * 员工重置密码

View File

@@ -51,17 +51,19 @@ public class EmployeeAddForm {
@Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确") @Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确")
private String phone; private String phone;
@Schema(description = "邮箱") @Schema(description = "邮箱账号")
@NotNull(message = "邮箱账号不能为空")
@Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱账号格式不正确")
private String email; private String email;
@Schema(description = "职务级别ID")
private Long positionId;
@Schema(description = "角色列表") @Schema(description = "角色列表")
private List<Long> roleIdList; private List<Long> roleIdList;
@Schema(description = "备注") @Schema(description = "备注")
@Length(max = 30, message = "备注最多200字符") @Length(max = 200, message = "备注最多200字符")
private String remark; private String remark;
@Schema(description = "职务级别ID")
private Long positionId;
} }

View File

@@ -0,0 +1,58 @@
package net.lab1024.sa.admin.module.system.employee.domain.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.lab1024.sa.base.common.enumeration.GenderEnum;
import net.lab1024.sa.base.common.swagger.SchemaEnum;
import net.lab1024.sa.base.common.util.SmartVerificationUtil;
import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
/**
* 更新员工个人中心信息
*
* @Author 1024创新实验室: 开云
* @Date 2021-12-20 21:06:49
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
@Data
public class EmployeeUpdateCenterForm {
@Schema(hidden = true)
private Long employeeId;
@Schema(description = "姓名")
@NotNull(message = "姓名不能为空")
@Length(max = 30, message = "姓名最多30字符")
private String actualName;
@SchemaEnum(GenderEnum.class)
@CheckEnum(value = GenderEnum.class, message = "性别错误")
private Integer gender;
@Schema(description = "手机号")
@NotNull(message = "手机号不能为空")
@Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确")
private String phone;
@Schema(description = "邮箱账号")
@NotNull(message = "邮箱账号不能为空")
@Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱账号格式不正确")
private String email;
@Schema(description = "职务级别ID")
private Long positionId;
@Schema(description = "头像")
private String avatar;
@Schema(description = "备注")
@Length(max = 200, message = "备注最多200字符")
private String remark;
}

View File

@@ -168,19 +168,14 @@ public class EmployeeService {
return ResponseDTO.userErrorParam("部门不存在"); return ResponseDTO.userErrorParam("部门不存在");
} }
// 检查唯一性
EmployeeEntity existEntity = employeeDao.getByLoginName(employeeUpdateForm.getLoginName(), null); ResponseDTO<String> checkResponse = checkUniqueness(employeeId, employeeUpdateForm.getLoginName(), employeeUpdateForm.getPhone(), employeeUpdateForm.getEmail());
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) { if (!checkResponse.getOk()) {
return ResponseDTO.userErrorParam("登录名重复"); return checkResponse;
} }
existEntity = employeeDao.getByPhone(employeeUpdateForm.getPhone(), null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("手机号已存在");
}
// 不更新密码
EmployeeEntity entity = SmartBeanUtil.copy(employeeUpdateForm, EmployeeEntity.class); EmployeeEntity entity = SmartBeanUtil.copy(employeeUpdateForm, EmployeeEntity.class);
// 不更新密码
entity.setLoginPwd(null); entity.setLoginPwd(null);
// 更新数据 // 更新数据
@@ -192,6 +187,57 @@ public class EmployeeService {
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
/**
* 更新员工个人中心信息
*/
public ResponseDTO<String> updateCenter(EmployeeUpdateCenterForm updateCenterForm) {
Long employeeId = updateCenterForm.getEmployeeId();
EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
if (null == employeeEntity) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
}
// 检查唯一性 登录账号不能修改则不需要检查
ResponseDTO<String> checkResponse = checkUniqueness(employeeId, "", updateCenterForm.getPhone(), updateCenterForm.getEmail());
if (!checkResponse.getOk()) {
return checkResponse;
}
EmployeeEntity employee = SmartBeanUtil.copy(updateCenterForm, EmployeeEntity.class);
// 不更新密码
employee.setLoginPwd(null);
// 更新数据
employeeDao.updateById(employee);
// 清除员工缓存
loginService.clearLoginEmployeeCache(employeeId);
return ResponseDTO.ok();
}
/**
* 检查唯一性
*/
private ResponseDTO<String> checkUniqueness(Long employeeId, String loginName, String phone, String email) {
EmployeeEntity existEntity = employeeDao.getByLoginName(loginName, null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("登录名重复");
}
existEntity = employeeDao.getByPhone(phone, null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("手机号已存在");
}
existEntity = employeeDao.getByEmail(email, null);
if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) {
return ResponseDTO.userErrorParam("邮箱账号已存在");
}
return ResponseDTO.ok();
}
/** /**
* 更新登录人头像 * 更新登录人头像
@@ -297,38 +343,39 @@ public class EmployeeService {
if (employeeEntity == null) { if (employeeEntity == null) {
return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST);
} }
// 校验原始密码 // 校验原始密码
String oldPassword = SecurityPasswordService.getEncryptPwd(updatePasswordForm.getOldPassword()); if (!SecurityPasswordService.matchesPwd(updatePasswordForm.getOldPassword(),employeeEntity.getLoginPwd()) ) {
if (!Objects.equals(oldPassword, employeeEntity.getLoginPwd())) {
return ResponseDTO.userErrorParam("原密码有误,请重新输入"); return ResponseDTO.userErrorParam("原密码有误,请重新输入");
} }
// 新旧密码相同
if (Objects.equals(updatePasswordForm.getOldPassword(), updatePasswordForm.getNewPassword()) ){
return ResponseDTO.userErrorParam("新密码与原始密码相同,请重新输入");
}
// 校验密码复杂度 // 校验密码复杂度
ResponseDTO<String> validatePassComplexity = securityPasswordService.validatePasswordComplexity(updatePasswordForm.getNewPassword()); ResponseDTO<String> validatePassComplexity = securityPasswordService.validatePasswordComplexity(updatePasswordForm.getNewPassword());
if (!validatePassComplexity.getOk()) { if (!validatePassComplexity.getOk()) {
return validatePassComplexity; return validatePassComplexity;
} }
// 新旧密码相同
String newPassword = SecurityPasswordService.getEncryptPwd(updatePasswordForm.getNewPassword());
if (Objects.equals(oldPassword, newPassword)) {
return ResponseDTO.userErrorParam("新密码与原始密码相同,请重新输入");
}
// 根据三级等保规则,校验密码是否重复 // 根据三级等保规则,校验密码是否重复
ResponseDTO<String> passwordRepeatTimes = securityPasswordService.validatePasswordRepeatTimes(requestUser, updatePasswordForm.getNewPassword()); ResponseDTO<String> passwordRepeatTimes = securityPasswordService.validatePasswordRepeatTimes(requestUser, updatePasswordForm.getNewPassword());
if (!passwordRepeatTimes.getOk()) { if (!passwordRepeatTimes.getOk()) {
return ResponseDTO.error(passwordRepeatTimes); return ResponseDTO.error(passwordRepeatTimes);
} }
// 更新密码 // 更新密码
String newEncryptPassword = SecurityPasswordService.getEncryptPwd(updatePasswordForm.getNewPassword());
EmployeeEntity updateEntity = new EmployeeEntity(); EmployeeEntity updateEntity = new EmployeeEntity();
updateEntity.setEmployeeId(employeeId); updateEntity.setEmployeeId(employeeId);
updateEntity.setLoginPwd(newPassword); updateEntity.setLoginPwd(newEncryptPassword);
employeeDao.updateById(updateEntity); employeeDao.updateById(updateEntity);
// 保存修改密码密码记录 // 保存修改密码密码记录
securityPasswordService.saveUserChangePasswordLog(requestUser, newPassword, oldPassword); securityPasswordService.saveUserChangePasswordLog(requestUser, newEncryptPassword, employeeEntity.getLoginPwd());
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -336,11 +383,8 @@ public class EmployeeService {
/** /**
* 获取某个部门的员工信息 * 获取某个部门的员工信息
*/ */
public ResponseDTO<List<EmployeeVO>> getAllEmployeeByDepartmentId(Long departmentId, Boolean disabledFlag) { public ResponseDTO<List<EmployeeVO>> getAllEmployeeByDepartmentId(Long departmentId) {
List<EmployeeEntity> employeeEntityList = employeeDao.selectByDepartmentId(departmentId, disabledFlag); List<EmployeeEntity> employeeEntityList = employeeDao.selectByDepartmentId(departmentId, Boolean.FALSE);
if (disabledFlag != null) {
employeeEntityList = employeeEntityList.stream().filter(e -> e.getDisabledFlag().equals(disabledFlag)).collect(Collectors.toList());
}
if (CollectionUtils.isEmpty(employeeEntityList)) { if (CollectionUtils.isEmpty(employeeEntityList)) {
return ResponseDTO.ok(Collections.emptyList()); return ResponseDTO.ok(Collections.emptyList());
@@ -381,7 +425,7 @@ public class EmployeeService {
* 根据登录名获取员工 * 根据登录名获取员工
*/ */
public EmployeeEntity getByLoginName(String loginName) { public EmployeeEntity getByLoginName(String loginName) {
return employeeDao.getByLoginName(loginName, null); return employeeDao.getByLoginName(loginName, false);
} }
} }

View File

@@ -60,8 +60,8 @@ public class LoginController {
@Operation(summary = "退出登陆 @author 卓大") @Operation(summary = "退出登陆 @author 卓大")
@GetMapping("/login/logout") @GetMapping("/login/logout")
public ResponseDTO<String> logout(@RequestHeader(value = RequestHeaderConst.TOKEN, required = false) String token) { public ResponseDTO<String> logout() {
return loginService.logout(token, SmartRequestUtil.getRequestUser()); return loginService.logout(SmartRequestUtil.getRequestUser());
} }
@Operation(summary = "获取验证码 @author 卓大") @Operation(summary = "获取验证码 @author 卓大")

View File

@@ -46,6 +46,12 @@ public class RequestEmployee implements RequestUser {
@Schema(description = "部门名称") @Schema(description = "部门名称")
private String departmentName; private String departmentName;
@Schema(description = "职务级别ID")
private Long positionId;
@Schema(description = "邮箱")
private String email;
@Schema(description = "是否禁用") @Schema(description = "是否禁用")
private Boolean disabledFlag; private Boolean disabledFlag;

View File

@@ -164,10 +164,15 @@ public class LoginService implements StpInterface {
// 验证登录名 // 验证登录名
EmployeeEntity employeeEntity = employeeService.getByLoginName(loginForm.getLoginName()); EmployeeEntity employeeEntity = employeeService.getByLoginName(loginForm.getLoginName());
if (null == employeeEntity) { if (null == employeeEntity) {
return ResponseDTO.userErrorParam("登录名不存在"); return ResponseDTO.userErrorParam("登录名或密码错误");
} }
// 验证账号状态 // 验证账号状态
if (employeeEntity.getDeletedFlag()) {
saveLoginLog(employeeEntity, ip, userAgent, "账号已删除", LoginLogResultEnum.LOGIN_FAIL);
return ResponseDTO.userErrorParam("您的账号已被删除,请联系工作人员!");
}
if (employeeEntity.getDisabledFlag()) { if (employeeEntity.getDisabledFlag()) {
saveLoginLog(employeeEntity, ip, userAgent, "账号已禁用", LoginLogResultEnum.LOGIN_FAIL); saveLoginLog(employeeEntity, ip, userAgent, "账号已禁用", LoginLogResultEnum.LOGIN_FAIL);
return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!"); return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!");
@@ -203,7 +208,7 @@ public class LoginService implements StpInterface {
} }
// 密码错误 // 密码错误
if (!employeeEntity.getLoginPwd().equals(SecurityPasswordService.getEncryptPwd(requestPassword))) { if ( !SecurityPasswordService.matchesPwd(requestPassword,employeeEntity.getLoginPwd()) ) {
// 记录登录失败 // 记录登录失败
saveLoginLog(employeeEntity, ip, userAgent, "密码错误", LoginLogResultEnum.LOGIN_FAIL); saveLoginLog(employeeEntity, ip, userAgent, "密码错误", LoginLogResultEnum.LOGIN_FAIL);
// 记录等级保护次数 // 记录等级保护次数
@@ -373,10 +378,10 @@ public class LoginService implements StpInterface {
/** /**
* 退出登录 * 退出登录
*/ */
public ResponseDTO<String> logout(String token, RequestUser requestUser) { public ResponseDTO<String> logout(RequestUser requestUser) {
// sa token 登出 // sa token 登出
StpUtil.logoutByTokenValue(token); StpUtil.logout();
// 清空登录信息缓存 // 清空登录信息缓存
loginEmployeeCache.remove(requestUser.getUserId()); loginEmployeeCache.remove(requestUser.getUserId());
@@ -506,10 +511,14 @@ public class LoginService implements StpInterface {
// 验证登录名 // 验证登录名
EmployeeEntity employeeEntity = employeeService.getByLoginName(loginName); EmployeeEntity employeeEntity = employeeService.getByLoginName(loginName);
if (null == employeeEntity) { if (null == employeeEntity) {
return ResponseDTO.userErrorParam("登录名不存在!"); return ResponseDTO.ok();
} }
// 验证账号状态 // 验证账号状态
if (employeeEntity.getDeletedFlag()) {
return ResponseDTO.userErrorParam("您的账号已被删除,请联系工作人员!");
}
if (employeeEntity.getDisabledFlag()) { if (employeeEntity.getDisabledFlag()) {
return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!"); return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!");
} }

View File

@@ -2,6 +2,28 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao"> <mapper namespace="net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao">
<!-- 查询结果列 -->
<sql id="base_columns">
t_notice.notice_id,
t_notice.notice_type_id,
t_notice.title,
t_notice.all_visible_flag,
t_notice.scheduled_publish_flag,
t_notice.publish_time,
t_notice.content_text,
t_notice.content_html,
t_notice.attachment,
t_notice.page_view_count,
t_notice.user_view_count,
t_notice.source,
t_notice.author,
t_notice.document_number,
t_notice.deleted_flag,
t_notice.create_user_id,
t_notice.update_time,
t_notice.create_time
</sql>
<!-- ================================== 可见范围相关 ================================== --> <!-- ================================== 可见范围相关 ================================== -->
<insert id="insertVisibleRange"> <insert id="insertVisibleRange">
@@ -35,32 +57,30 @@
<!-- 后管分页查询资讯 --> <!-- 后管分页查询资讯 -->
<select id="query" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO"> <select id="query" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO">
SELECT SELECT
t_notice.* , <include refid="base_columns"/>,
t_notice_type.notice_type_name as noticeTypeName, t_notice_type.notice_type_name as noticeTypeName,
t_employee.actual_name as createUserName, t_employee.actual_name as createUserName
t_department.name as departmentName
FROM t_notice FROM t_notice
left join t_notice_type on t_notice_type.notice_type_id = t_notice.notice_type_id LEFT JOIN t_notice_type on t_notice.notice_type_id = t_notice_type.notice_type_id
left join t_employee on t_notice.create_user_id = t_employee.employee_id LEFT JOIN t_employee on t_notice.create_user_id = t_employee.employee_id
left join t_department on t_employee.department_id = t_department.department_id
<where> <where>
<if test="query.noticeTypeId != null"> <if test="query.noticeTypeId != null">
AND t_notice_type.notice_type_id = #{query.noticeTypeId} AND t_notice_type.notice_type_id = #{query.noticeTypeId}
</if> </if>
<if test="query.keywords != null and query.keywords !=''"> <if test="query.keywords != null and query.keywords != ''">
AND ( INSTR(t_notice.title,#{query.keywords}) AND ( INSTR(t_notice.title,#{query.keywords})
OR INSTR(t_notice.author,#{query.keywords}) OR INSTR(t_notice.author,#{query.keywords})
OR INSTR(t_notice.source,#{query.keywords}) OR INSTR(t_notice.source,#{query.keywords})
) )
</if> </if>
<if test="query.documentNumber != null and query.documentNumber !=''"> <if test="query.documentNumber != null and query.documentNumber != ''">
AND INSTR(t_notice.document_number, #{query.documentNumber}) AND INSTR(t_notice.document_number, #{query.documentNumber})
</if> </if>
<if test="query.createUserId != null"> <if test="query.createUserName != null and query.createUserName != ''">
AND t_notice.create_user_id = #{createUserId} AND t_employee.actual_name = #{query.createUserName}
</if> </if>
<if test="query.deletedFlag != null"> <if test="query.deletedFlag != null">
and t_notice.deleted_flag = #{query.deletedFlag} AND t_notice.deleted_flag = #{query.deletedFlag}
</if> </if>
<if test="query.createTimeBegin != null"> <if test="query.createTimeBegin != null">
AND DATE_FORMAT(t_notice.create_time, '%Y-%m-%d') &gt;= DATE_FORMAT(#{query.createTimeBegin}, AND DATE_FORMAT(t_notice.create_time, '%Y-%m-%d') &gt;= DATE_FORMAT(#{query.createTimeBegin},
@@ -84,10 +104,9 @@
</select> </select>
<!-- ================================== 通知公告【员工查看】相关 ================================== --> <!-- ================================== 通知公告【员工查看】相关 ================================== -->
<select id="queryEmployeeNotice" <select id="queryEmployeeNotice" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
select select
t_notice.*, <include refid="base_columns"/>,
t_notice_type.notice_type_name, t_notice_type.notice_type_name,
(select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and
t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag
@@ -142,12 +161,11 @@
</where> </where>
order by t_notice.publish_time desc order by t_notice.publish_time desc
</select> </select>
<select id="queryEmployeeNotViewNotice" <select id="queryEmployeeNotViewNotice" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO">
select * from select * from
( (
select select
t_notice.*, <include refid="base_columns"/>,
t_notice_type.notice_type_name, t_notice_type.notice_type_name,
(select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = #{requestEmployeeId} and
t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag
@@ -198,8 +216,7 @@
) t where viewFlag = 0 ) t where viewFlag = 0
order by t.publish_time desc order by t.publish_time desc
</select> </select>
<select id="queryNoticeViewRecordList" <select id="queryNoticeViewRecordList" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeViewRecordVO">
resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeViewRecordVO">
select t_notice_view_record.*, select t_notice_view_record.*,
t_employee.actual_name as employeeName, t_employee.actual_name as employeeName,
t_department.name as departmentName t_department.name as departmentName

View File

@@ -33,21 +33,19 @@
</where> </where>
</select> </select>
<update id="updateDisableFlag"> <update id="updateDisableFlag">
UPDATE t_employee UPDATE t_employee
SET disabled_flag = #{disabledFlag} SET disabled_flag = #{disabledFlag}
WHERE employee_id = #{employeeId} WHERE employee_id = #{employeeId}
</update> </update>
<select id="getByLoginName" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity"> <select id="getByLoginName" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * SELECT *
FROM t_employee FROM t_employee
<where> <where>
login_name = #{loginName} login_name = #{loginName}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
@@ -57,24 +55,33 @@
FROM t_employee FROM t_employee
<where> <where>
actual_name = #{actualName} actual_name = #{actualName}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
<select id="getByPhone" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity"> <select id="getByPhone" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * SELECT *
FROM t_employee FROM t_employee
<where> <where>
phone = #{phone} phone = #{phone}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
<select id="getByEmail" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT *
FROM t_employee
<where>
email = #{email}
<if test="deletedFlag != null">
AND deleted_flag = #{deletedFlag}
</if>
</where>
</select>
<select id="listAll" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO"> <select id="listAll" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
SELECT * SELECT *
@@ -88,22 +95,19 @@
department_id = #{departmentId} AND deleted_flag = #{deletedFlag} department_id = #{departmentId} AND deleted_flag = #{deletedFlag}
</select> </select>
<select id="selectByDepartmentId" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
<select id="selectByDepartmentId"
resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * SELECT *
FROM t_employee FROM t_employee
<where> <where>
department_id = #{departmentId} department_id = #{departmentId}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
</select> </select>
<select id="selectByActualName" <select id="selectByActualName" resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
resultType="net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity">
SELECT * FROM t_employee SELECT * FROM t_employee
<where> <where>
actual_name = #{actualName} actual_name = #{actualName}
@@ -111,8 +115,8 @@
<foreach collection="departmentIdList" item="item" open="(" close=")" separator=","> <foreach collection="departmentIdList" item="item" open="(" close=")" separator=",">
#{item} #{item}
</foreach> </foreach>
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
@@ -125,20 +129,19 @@
<foreach collection="departmentIds" item="item" open="(" close=")" separator=","> <foreach collection="departmentIds" item="item" open="(" close=")" separator=",">
#{item} #{item}
</foreach> </foreach>
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
</select> </select>
<select id="getEmployeeId" resultType="java.lang.Long"> <select id="getEmployeeId" resultType="java.lang.Long">
SELECT employee_id SELECT employee_id
FROM t_employee FROM t_employee
<where> <where>
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
</select> </select>
@@ -148,8 +151,8 @@
FROM t_employee FROM t_employee
<where> <where>
department_id = #{departmentId} department_id = #{departmentId}
<if test="disabledFlag != null"> <if test="deletedFlag != null">
AND disabled_flag = #{disabledFlag} AND deleted_flag = #{deletedFlag}
</if> </if>
</where> </where>
ORDER BY create_time DESC ORDER BY create_time DESC
@@ -164,7 +167,6 @@
ORDER BY create_time DESC ORDER BY create_time DESC
</select> </select>
<select id="getEmployeeById" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO"> <select id="getEmployeeById" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
SELECT t_employee.*, SELECT t_employee.*,
t_department.name AS departmentName t_department.name AS departmentName
@@ -173,8 +175,7 @@
where t_employee.employee_id = #{employeeId} where t_employee.employee_id = #{employeeId}
</select> </select>
<select id="selectEmployeeByDisabledAndDeleted" <select id="selectEmployeeByDisabledAndDeleted" resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
resultType="net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO">
SELECT SELECT
t_employee.*, t_employee.*,
t_department.name AS departmentName t_department.name AS departmentName
@@ -196,5 +197,4 @@
WHERE employee_id = #{employeeId} WHERE employee_id = #{employeeId}
</update> </update>
</mapper> </mapper>

View File

@@ -19,9 +19,8 @@
<select id="selectMenuListByRoleIdList" <select id="selectMenuListByRoleIdList"
resultType="net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity"> resultType="net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity">
SELECT SELECT
t_menu.* distinct t_menu.*
from t_menu from t_menu
left join t_role_menu on t_role_menu.menu_id = t_menu.menu_id left join t_role_menu on t_role_menu.menu_id = t_menu.menu_id
<where> <where>
@@ -35,8 +34,6 @@
</foreach> </foreach>
</if> </if>
</where> </where>
group by t_menu.menu_id
ORDER BY t_menu.sort ASC ORDER BY t_menu.sort ASC
</select> </select>
</mapper> </mapper>

View File

@@ -87,6 +87,11 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
@@ -193,6 +198,11 @@
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>
@@ -225,12 +235,18 @@
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId> <artifactId>bcprov-jdk18on</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>cn.idev.excel</groupId>
<artifactId>easyexcel</artifactId> <artifactId>fastexcel</artifactId>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
@@ -298,6 +314,11 @@
<artifactId>freemarker</artifactId> <artifactId>freemarker</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>${tika.version}</version>
</dependency>
</dependencies> </dependencies>

View File

@@ -11,7 +11,7 @@ package net.lab1024.sa.base.common.constant;
*/ */
public class RequestHeaderConst { public class RequestHeaderConst {
public static final String TOKEN = "x-access-token"; public static final String TOKEN = "Authorization";
public static final String USER_AGENT = "user-agent"; public static final String USER_AGENT = "user-agent";

View File

@@ -1,52 +0,0 @@
package net.lab1024.sa.base.common.json.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.google.common.collect.Lists;
import net.lab1024.sa.base.module.support.dict.domain.vo.DictValueVO;
import net.lab1024.sa.base.module.support.dict.service.DictCacheService;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* 字典序列化
*
* @Author 1024创新实验室: 罗伊
* @Date 2022-08-12 22:17:53
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/
public class DictValueVoSerializer extends JsonSerializer<String> {
@Resource
private DictCacheService dictCacheService;
@Override
public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (StringUtils.isEmpty(value)) {
jsonGenerator.writeObject(Lists.newArrayList());
return;
}
String[] valueCodeArray = value.split(",");
List<String> valueCodeList = Arrays.asList(valueCodeArray);
List<DictValueVO> dictValueVOList = Lists.newArrayList();
valueCodeList.forEach(e->{
if(StringUtils.isNotBlank(e)){
DictValueVO dictValueVO = dictCacheService.selectValueByValueCode(e);
if(dictValueVO != null){
dictValueVOList.add(dictValueVO);
}
}
});
jsonGenerator.writeObject(dictValueVOList);
}
}

View File

@@ -1,9 +1,9 @@
package net.lab1024.sa.base.common.util; package net.lab1024.sa.base.common.util;
import com.alibaba.excel.EasyExcel; import cn.idev.excel.FastExcel;
import com.alibaba.excel.write.handler.SheetWriteHandler; import cn.idev.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackagePartName;
@@ -43,7 +43,7 @@ public final class SmartExcelUtil {
// 设置下载消息头 // 设置下载消息头
SmartResponseUtil.setDownloadFileHeader(response, fileName, null); SmartResponseUtil.setDownloadFileHeader(response, fileName, null);
// 下载 // 下载
EasyExcel.write(response.getOutputStream(), head) FastExcel.write(response.getOutputStream(), head)
.autoCloseStream(Boolean.FALSE) .autoCloseStream(Boolean.FALSE)
.sheet(sheetName) .sheet(sheetName)
.doWrite(data); .doWrite(data);
@@ -58,7 +58,7 @@ public final class SmartExcelUtil {
// 水印 // 水印
Watermark watermark = new Watermark(watermarkString); Watermark watermark = new Watermark(watermarkString);
// 一定要inMemory // 一定要inMemory
EasyExcel.write(response.getOutputStream(), head) FastExcel.write(response.getOutputStream(), head)
.inMemory(true) .inMemory(true)
.sheet(sheetName) .sheet(sheetName)
.registerWriteHandler(new CustomWaterMarkHandler(watermark)) .registerWriteHandler(new CustomWaterMarkHandler(watermark))

View File

@@ -73,7 +73,7 @@ public class SwaggerConfig {
private Components components() { private Components components() {
return new Components() return new Components()
.addSecuritySchemes(RequestHeaderConst.TOKEN, new SecurityScheme().type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER).name(RequestHeaderConst.TOKEN)); .addSecuritySchemes(RequestHeaderConst.TOKEN, new SecurityScheme().scheme("Bearer").description("请输入token,格式为[Bearer xxxxxxxx]").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER).name(RequestHeaderConst.TOKEN));
} }
@Bean @Bean

View File

@@ -40,7 +40,7 @@ public class MapperVariableService extends CodeGenerateBaseVariableService {
List<String> columnNameList = queryField.getColumnNameList(); List<String> columnNameList = queryField.getColumnNameList();
if (columnNameList.size() == 1) { if (columnNameList.size() == 1) {
// AND INSTR(t_notice.title,#{query.keywords}) // AND INSTR(t_notice.title,#{query.keywords})
stringBuilder.append(" AND INSTR(") stringBuilder.append("AND INSTR(")
.append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(0)) .append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(0))
.append(",#{queryForm.") .append(",#{queryForm.")
.append(queryField.getFieldName()) .append(queryField.getFieldName())
@@ -48,21 +48,21 @@ public class MapperVariableService extends CodeGenerateBaseVariableService {
} else { } else {
for (int i = 0; i < columnNameList.size(); i++) { for (int i = 0; i < columnNameList.size(); i++) {
if (i == 0) { if (i == 0) {
stringBuilder.append("AND ( INSTR(") stringBuilder.append("AND (\n INSTR(")
.append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(i)) .append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(i))
.append(",#{queryForm.") .append(",#{queryForm.")
.append(queryField.getFieldName()) .append(queryField.getFieldName())
.append("})"); .append("})");
} else { } else {
// OR INSTR(t_notice.author,#{query.keywords}) // OR INSTR(t_notice.author,#{query.keywords})
stringBuilder.append("\n OR INSTR(") stringBuilder.append("\n OR INSTR(")
.append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(i)) .append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(i))
.append(",#{queryForm.") .append(",#{queryForm.")
.append(queryField.getFieldName()) .append(queryField.getFieldName())
.append("})"); .append("})");
} }
} }
stringBuilder.append("\n )"); stringBuilder.append("\n )");
} }
fieldMap.put("likeStr", stringBuilder.toString()); fieldMap.put("likeStr", stringBuilder.toString());
} else if (CodeQueryFieldQueryTypeEnum.DICT.equalsValue(queryField.getQueryTypeEnum())) { } else if (CodeQueryFieldQueryTypeEnum.DICT.equalsValue(queryField.getQueryTypeEnum())) {

View File

@@ -18,5 +18,5 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
public @interface DataTracerFieldDict { public @interface DataTracerFieldDict {
String keyCode() default "";
} }

View File

@@ -303,7 +303,7 @@ public class DataTracerChangeContentService {
fieldContent = SmartEnumUtil.getEnumDescByValue(fieldValue, dataTracerFieldEnum.enumClass()); fieldContent = SmartEnumUtil.getEnumDescByValue(fieldValue, dataTracerFieldEnum.enumClass());
} }
} else if (dataTracerFieldDict != null) { } else if (dataTracerFieldDict != null) {
fieldContent = dictCacheService.selectValueNameByValueCodeSplit(fieldValue.toString()); fieldContent = dictCacheService.selectValueNameByValueCodeSplit(dataTracerFieldDict.keyCode(), fieldValue.toString());
} else if (dataTracerFieldSql != null) { } else if (dataTracerFieldSql != null) {
fieldContent = this.getRelateDisplayValue(fieldValue, dataTracerFieldSql); fieldContent = this.getRelateDisplayValue(fieldValue, dataTracerFieldSql);
} else if (fieldValue instanceof Date) { } else if (fieldValue instanceof Date) {

View File

@@ -52,5 +52,5 @@ public interface DictValueDao extends BaseMapper<DictValueEntity> {
* 跟进code查询 * 跟进code查询
* *
*/ */
DictValueEntity selectByCode(@Param("valueCode") String valueCode, @Param("deletedFlag") Boolean deletedFlag); DictValueEntity selectByCode(@Param("dictKeyId") Long dictKeyId,@Param("valueCode") String valueCode, @Param("deletedFlag") Boolean deletedFlag);
} }

View File

@@ -18,6 +18,7 @@ import javax.annotation.PostConstruct;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -41,8 +42,6 @@ public class DictCacheService {
private ConcurrentHashMap<String, List<DictValueVO>> DICT_CACHE = new ConcurrentHashMap<>(); private ConcurrentHashMap<String, List<DictValueVO>> DICT_CACHE = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, DictValueVO> VALUE_CACHE = new ConcurrentHashMap<>();
@PostConstruct @PostConstruct
public void dictCache() { public void dictCache() {
@@ -63,10 +62,6 @@ public class DictCacheService {
Long dictKeyId = dictKeyEntity.getDictKeyId(); Long dictKeyId = dictKeyEntity.getDictKeyId();
DICT_CACHE.put(keyCode, valueListMap.getOrDefault(dictKeyId, Lists.newArrayList())); DICT_CACHE.put(keyCode, valueListMap.getOrDefault(dictKeyId, Lists.newArrayList()));
} }
//字典值缓存
dictValueVOList.forEach(e -> {
VALUE_CACHE.put(e.getValueCode(), e);
});
log.info("################# 数据字典缓存初始化完毕 ###################"); log.info("################# 数据字典缓存初始化完毕 ###################");
} }
@@ -75,7 +70,6 @@ public class DictCacheService {
*/ */
public ResponseDTO<String> cacheRefresh() { public ResponseDTO<String> cacheRefresh() {
DICT_CACHE.clear(); DICT_CACHE.clear();
VALUE_CACHE.clear();
this.cacheInit(); this.cacheInit();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -92,37 +86,45 @@ public class DictCacheService {
/** /**
* 查询值code名称 * 查询值code名称
* * @param keyCode
* @param valueCode * @param valueCode
* @return * @return
*/ */
public String selectValueNameByValueCode(String valueCode) { public String selectValueNameByValueCode(String keyCode, String valueCode) {
if (StrUtil.isEmpty(valueCode)) { DictValueVO dictValueVO = this.selectValueByValueCode(keyCode, valueCode);
return null; if (dictValueVO == null){
}
DictValueVO dictValueVO = VALUE_CACHE.get(valueCode);
if (dictValueVO == null) {
return ""; return "";
} }
return dictValueVO.getValueName(); return dictValueVO.getValueName()
;
} }
public DictValueVO selectValueByValueCode(String valueCode) { public DictValueVO selectValueByValueCode(String keyCode, String valueCode) {
if (StrUtil.isEmpty(valueCode)) { if (StrUtil.isEmpty(valueCode)) {
return null; return null;
} }
return VALUE_CACHE.get(valueCode); if (StrUtil.isEmpty(keyCode)) {
} return null;
}
public String selectValueNameByValueCodeSplit(String valueCodes) { List<DictValueVO> dictValueVOList = DICT_CACHE.get(valueCode);
if (CollectionUtils.isEmpty(dictValueVOList)) {
return null;
}
Optional<DictValueVO> option = dictValueVOList.stream().filter(e->e.getValueCode().equals(valueCode)).findFirst();
if(option.isPresent()){
return option.get();
}
return null;
}
public String selectValueNameByValueCodeSplit(String keyCode, String valueCodes) {
if (StrUtil.isEmpty(valueCodes)) { if (StrUtil.isEmpty(valueCodes)) {
return ""; return "";
} }
List<String> valueNameList = Lists.newArrayList(); List<String> valueNameList = Lists.newArrayList();
String[] valueCodeArray = valueCodes.split(","); String[] valueCodeArray = valueCodes.split(",");
for (String valueCode : valueCodeArray) { for (String valueCode : valueCodeArray) {
DictValueVO dictValueVO = VALUE_CACHE.get(valueCode); DictValueVO dictValueVO = this.selectValueByValueCode(keyCode, valueCode);
if (dictValueVO != null) { if (dictValueVO != null) {
valueNameList.add(dictValueVO.getValueName()); valueNameList.add(dictValueVO.getValueName());
} }

View File

@@ -1,6 +1,8 @@
package net.lab1024.sa.base.module.support.dict.service; package net.lab1024.sa.base.module.support.dict.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import net.lab1024.sa.base.common.code.UserErrorCode; import net.lab1024.sa.base.common.code.UserErrorCode;
import net.lab1024.sa.base.common.domain.PageResult; import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO; import net.lab1024.sa.base.common.domain.ResponseDTO;
@@ -26,7 +28,7 @@ import java.util.List;
* @Date 2022/5/26 19:40:55 * @Date 2022/5/26 19:40:55
* @Wechat zhuoda1024 * @Wechat zhuoda1024
* @Email lab1024@163.com * @Email lab1024@163.com
* @Copyright <a href="https://1024lab.net">1024创新实验室</a> * @Copyright <a href="https://1024lab.net">1024创新实验室</a>
*/ */
@Service @Service
public class DictService { public class DictService {
@@ -37,6 +39,10 @@ public class DictService {
private DictValueDao dictValueDao; private DictValueDao dictValueDao;
@Resource @Resource
private DictCacheService dictCacheService; private DictCacheService dictCacheService;
/**
* CODE锁
*/
private static final Interner<String> CODE_POOL = Interners.newWeakInterner();
/** /**
@@ -45,15 +51,15 @@ public class DictService {
* @param keyAddForm * @param keyAddForm
* @return * @return
*/ */
public synchronized ResponseDTO<String> keyAdd(DictKeyAddForm keyAddForm) { public ResponseDTO<String> keyAdd(DictKeyAddForm keyAddForm) {
DictKeyEntity dictKeyEntity = dictKeyDao.selectByCode(keyAddForm.getKeyCode(), false); synchronized (CODE_POOL.intern(keyAddForm.getKeyCode())) {
if (dictKeyEntity != null) { DictKeyEntity dictKeyEntity = dictKeyDao.selectByCode(keyAddForm.getKeyCode(), false);
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST); if (dictKeyEntity != null) {
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST);
}
dictKeyEntity = SmartBeanUtil.copy(keyAddForm, DictKeyEntity.class);
dictKeyDao.insert(dictKeyEntity);
} }
dictKeyEntity = SmartBeanUtil.copy(keyAddForm, DictKeyEntity.class);
dictKeyDao.insert(dictKeyEntity);
//刷新缓存
dictCacheService.cacheRefresh();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -63,15 +69,16 @@ public class DictService {
* @param valueAddForm * @param valueAddForm
* @return * @return
*/ */
public synchronized ResponseDTO<String> valueAdd(DictValueAddForm valueAddForm) { public ResponseDTO<String> valueAdd(DictValueAddForm valueAddForm) {
DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueAddForm.getValueCode(), false);
if (dictValueEntity != null) { synchronized (CODE_POOL.intern(valueAddForm.getValueCode())) {
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST); DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueAddForm.getDictKeyId(),valueAddForm.getValueCode(), false);
if (dictValueEntity != null) {
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST);
}
dictValueEntity = SmartBeanUtil.copy(valueAddForm, DictValueEntity.class);
dictValueDao.insert(dictValueEntity);
} }
dictValueEntity = SmartBeanUtil.copy(valueAddForm, DictValueEntity.class);
dictValueDao.insert(dictValueEntity);
//刷新缓存
dictCacheService.cacheRefresh();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -81,15 +88,15 @@ public class DictService {
* @param keyUpdateForm * @param keyUpdateForm
* @return * @return
*/ */
public synchronized ResponseDTO<String> keyEdit(DictKeyUpdateForm keyUpdateForm) { public ResponseDTO<String> keyEdit(DictKeyUpdateForm keyUpdateForm) {
DictKeyEntity dictKeyEntity = dictKeyDao.selectByCode(keyUpdateForm.getKeyCode(), false); synchronized (CODE_POOL.intern(keyUpdateForm.getKeyCode())) {
if (dictKeyEntity != null && !dictKeyEntity.getDictKeyId().equals(keyUpdateForm.getDictKeyId())) { DictKeyEntity dictKeyEntity = dictKeyDao.selectByCode(keyUpdateForm.getKeyCode(), false);
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST); if (dictKeyEntity != null && !dictKeyEntity.getDictKeyId().equals(keyUpdateForm.getDictKeyId())) {
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST);
}
DictKeyEntity dictKeyUpdateEntity = SmartBeanUtil.copy(keyUpdateForm, DictKeyEntity.class);
dictKeyDao.updateById(dictKeyUpdateEntity);
} }
DictKeyEntity dictKeyUpdateEntity = SmartBeanUtil.copy(keyUpdateForm, DictKeyEntity.class);
dictKeyDao.updateById(dictKeyUpdateEntity);
//刷新缓存
dictCacheService.cacheRefresh();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -99,19 +106,19 @@ public class DictService {
* @param valueUpdateForm * @param valueUpdateForm
* @return * @return
*/ */
public synchronized ResponseDTO<String> valueEdit(DictValueUpdateForm valueUpdateForm) { public ResponseDTO<String> valueEdit(DictValueUpdateForm valueUpdateForm) {
DictKeyEntity dictKeyEntity = dictKeyDao.selectById(valueUpdateForm.getDictKeyId()); DictKeyEntity dictKeyEntity = dictKeyDao.selectById(valueUpdateForm.getDictKeyId());
if (dictKeyEntity == null || dictKeyEntity.getDeletedFlag()) { if (dictKeyEntity == null || dictKeyEntity.getDeletedFlag()) {
return ResponseDTO.userErrorParam("key不能存在"); return ResponseDTO.userErrorParam("key不能存在");
} }
DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueUpdateForm.getValueCode(), false); synchronized (CODE_POOL.intern(valueUpdateForm.getValueCode())) {
if (dictValueEntity != null && !dictValueEntity.getDictValueId().equals(valueUpdateForm.getDictValueId())) { DictValueEntity dictValueEntity = dictValueDao.selectByCode(valueUpdateForm.getDictKeyId() ,valueUpdateForm.getValueCode(), false);
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST); if (dictValueEntity != null && !dictValueEntity.getDictValueId().equals(valueUpdateForm.getDictValueId())) {
return ResponseDTO.error(UserErrorCode.ALREADY_EXIST);
}
DictValueEntity dictValueUpdateEntity = SmartBeanUtil.copy(valueUpdateForm, DictValueEntity.class);
dictValueDao.updateById(dictValueUpdateEntity);
} }
DictValueEntity dictValueUpdateEntity = SmartBeanUtil.copy(valueUpdateForm, DictValueEntity.class);
dictValueDao.updateById(dictValueUpdateEntity);
//刷新缓存
dictCacheService.cacheRefresh();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -121,13 +128,11 @@ public class DictService {
* @param keyIdList * @param keyIdList
* @return * @return
*/ */
public synchronized ResponseDTO<String> keyDelete(List<Long> keyIdList) { public ResponseDTO<String> keyDelete(List<Long> keyIdList) {
if (CollectionUtils.isEmpty(keyIdList)) { if (CollectionUtils.isEmpty(keyIdList)) {
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
dictKeyDao.updateDeletedFlagByIdList(keyIdList, true); dictKeyDao.updateDeletedFlagByIdList(keyIdList, true);
//刷新缓存
dictCacheService.cacheRefresh();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
@@ -137,13 +142,11 @@ public class DictService {
* @param valueIdList * @param valueIdList
* @return * @return
*/ */
public synchronized ResponseDTO<String> valueDelete(List<Long> valueIdList) { public ResponseDTO<String> valueDelete(List<Long> valueIdList) {
if (CollectionUtils.isEmpty(valueIdList)) { if (CollectionUtils.isEmpty(valueIdList)) {
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
dictValueDao.updateDeletedFlagByIdList(valueIdList, true); dictValueDao.updateDeletedFlagByIdList(valueIdList, true);
//刷新缓存
dictCacheService.cacheRefresh();
return ResponseDTO.ok(); return ResponseDTO.ok();
} }

View File

@@ -162,6 +162,10 @@ public class Level3ProtectConfigService {
this.maxUploadFileSizeMb = configForm.getMaxUploadFileSizeMb(); this.maxUploadFileSizeMb = configForm.getMaxUploadFileSizeMb();
} }
if (configForm.getLoginFailMaxTimes() != null) {
this.loginFailMaxTimes = configForm.getLoginFailMaxTimes();
}
if (configForm.getLoginFailLockMinutes() != null) { if (configForm.getLoginFailLockMinutes() != null) {
this.loginFailLockSeconds = configForm.getLoginFailLockMinutes() * 60; this.loginFailLockSeconds = configForm.getLoginFailLockMinutes() * 60;
} }

View File

@@ -1,14 +1,24 @@
package net.lab1024.sa.base.module.support.securityprotect.service; package net.lab1024.sa.base.module.support.securityprotect.service;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.base.common.domain.ResponseDTO; import net.lab1024.sa.base.common.domain.ResponseDTO;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypes;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.File; import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/** /**
* 三级等保 文件上传 相关 * 三级等保 文件 相关
* *
* @Author 1024创新实验室-主任:卓大 * @Author 1024创新实验室-主任:卓大
* @Date 2024/08/22 19:25:59 * @Date 2024/08/22 19:25:59
@@ -18,11 +28,34 @@ import java.io.File;
*/ */
@Service @Service
@Slf4j
public class SecurityFileService { public class SecurityFileService {
@Resource @Resource
private Level3ProtectConfigService level3ProtectConfigService; private Level3ProtectConfigService level3ProtectConfigService;
// 定义白名单MIME类型
private static final List<String> ALLOWED_MIME_TYPES = Arrays.asList(
"application/json",
"application/zip",
"application/x-7z-compressed",
"application/pdf",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-works",
"text/csv",
"audio/*",
"video/*",
// 图片类型 svg有安全隐患所以不使用"image/*"
"image/jpeg",
"image/png",
"image/gif",
"image/bmp"
);
/** /**
* 检测文件安全类型 * 检测文件安全类型
@@ -38,15 +71,50 @@ public class SecurityFileService {
} }
// 文件类型安全检测 // 文件类型安全检测
if (!level3ProtectConfigService.isFileDetectFlag()) { if (level3ProtectConfigService.isFileDetectFlag()) {
return ResponseDTO.ok(); String fileType = getFileMimeType(file);
if (ALLOWED_MIME_TYPES.stream()
.noneMatch(allowedType -> matchesMimeType(fileType, allowedType))) {
return ResponseDTO.userErrorParam("禁止上传此文件类型");
}
} }
// 检测文件类型
// .....
return ResponseDTO.ok(); return ResponseDTO.ok();
} }
/**
* 获取文件的 MIME 类型
*
* @param file 要检查的文件
* @return 文件的 MIME 类型
*/
public static String getFileMimeType(MultipartFile file) {
try {
TikaConfig tika = new TikaConfig();
Metadata metadata = new Metadata();
metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename());
TikaInputStream stream = TikaInputStream.get(file.getInputStream());
MediaType mimetype = tika.getDetector().detect(stream, metadata);
return mimetype.toString();
} catch (IOException | TikaException e) {
log.error(e.getMessage(), e);
return MimeTypes.OCTET_STREAM;
}
}
/**
* 检查文件的 MIME 类型是否与指定的MIME 类型匹配(支持通配符)
*
* @param fileType 文件的 MIME 类型
* @param mimetype MIME 类型(支持通配符)
* @return 是否匹配
*/
private static boolean matchesMimeType(String fileType, String mimetype) {
if (mimetype.endsWith("/*")) {
String prefix = mimetype.substring(0, mimetype.length() - 1);
return fileType.startsWith(prefix);
} else {
return fileType.equalsIgnoreCase(mimetype);
}
}
} }
;

View File

@@ -5,8 +5,8 @@ import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartStringUtil; import net.lab1024.sa.base.common.util.SmartStringUtil;
import net.lab1024.sa.base.module.support.securityprotect.dao.PasswordLogDao; import net.lab1024.sa.base.module.support.securityprotect.dao.PasswordLogDao;
import net.lab1024.sa.base.module.support.securityprotect.domain.PasswordLogEntity; import net.lab1024.sa.base.module.support.securityprotect.domain.PasswordLogEntity;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@@ -34,11 +34,8 @@ public class SecurityPasswordService {
public static final String PASSWORD_FORMAT_MSG = "密码必须为长度8-20位且必须包含大小写字母、数字、特殊符号@#$%^&*()_+-=)等三种字符"; public static final String PASSWORD_FORMAT_MSG = "密码必须为长度8-20位且必须包含大小写字母、数字、特殊符号@#$%^&*()_+-=)等三种字符";
private static final int PASSWORD_LENGTH = 8; private static final int PASSWORD_LENGTH = 8;
private static final String PASSWORD_SALT_FORMAT = "smart_%s_admin_$^&*";
@Resource @Resource
private PasswordLogDao passwordLogDao; private PasswordLogDao passwordLogDao;
@@ -46,6 +43,8 @@ public class SecurityPasswordService {
@Resource @Resource
private Level3ProtectConfigService level3ProtectConfigService; private Level3ProtectConfigService level3ProtectConfigService;
static Argon2PasswordEncoder ARGON2_PASSWORD_ENCODER = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
/** /**
* 校验密码复杂度 * 校验密码复杂度
*/ */
@@ -84,8 +83,9 @@ public class SecurityPasswordService {
// 检查最近几次是否有重复密码 // 检查最近几次是否有重复密码
List<String> oldPasswords = passwordLogDao.selectOldPassword(requestUser.getUserType().getValue(), requestUser.getUserId(), level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes()); List<String> oldPasswords = passwordLogDao.selectOldPassword(requestUser.getUserType().getValue(), requestUser.getUserId(), level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes());
if (oldPasswords != null && oldPasswords.contains(getEncryptPwd(newPassword))) { boolean isDuplicate = oldPasswords.stream().anyMatch(oldPassword -> ARGON2_PASSWORD_ENCODER.matches(newPassword, oldPassword));
return ResponseDTO.userErrorParam(String.format("与前%s个历史密码重复请换个密码!", level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes())); if (isDuplicate) {
return ResponseDTO.userErrorParam(String.format("与前%d个历史密码重复请换个密码!", level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes()));
} }
return ResponseDTO.ok(); return ResponseDTO.ok();
@@ -143,7 +143,14 @@ public class SecurityPasswordService {
* 获取 加密后 的密码 * 获取 加密后 的密码
*/ */
public static String getEncryptPwd(String password) { public static String getEncryptPwd(String password) {
return DigestUtils.md5Hex(String.format(PASSWORD_SALT_FORMAT, password)); return ARGON2_PASSWORD_ENCODER.encode(password);
}
/**
* 校验密码是否匹配
*/
public static Boolean matchesPwd(String password, String encodedPassword) {
return ARGON2_PASSWORD_ENCODER.matches(password, encodedPassword);
} }
} }

View File

@@ -131,7 +131,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bearer
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -29,7 +29,7 @@
<select id="selectByCode" <select id="selectByCode"
resultType="net.lab1024.sa.base.module.support.dict.domain.entity.DictValueEntity"> resultType="net.lab1024.sa.base.module.support.dict.domain.entity.DictValueEntity">
select * from t_dict_value where value_code = #{valueCode} and deleted_flag = #{deletedFlag} select * from t_dict_value where dict_Key_id = #{dictKeyId} and value_code = #{valueCode} and deleted_flag = #{deletedFlag}
</select> </select>
<select id="selectByDeletedFlag" <select id="selectByDeletedFlag"

View File

@@ -131,7 +131,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bear
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -128,7 +128,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bear
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -131,7 +131,9 @@ reload:
# sa-token 配置 # sa-token 配置
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)
token-name: x-access-token token-name: Authorization
# token 前缀 例如:Bear
token-prefix: Bearer
# token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效 # token 有效期(单位:秒) 默认30天2592000秒-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结

View File

@@ -17,7 +17,7 @@
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@ant-design/icons-vue": "^6.1.0", "@ant-design/icons-vue": "^7.0.1",
"@wangeditor/editor": "5.1.14", "@wangeditor/editor": "5.1.14",
"@wangeditor/editor-for-vue": "5.1.12", "@wangeditor/editor-for-vue": "5.1.12",
"ant-design-vue": "4.2.5", "ant-design-vue": "4.2.5",
@@ -38,6 +38,7 @@
"sm-crypto": "0.3.13", "sm-crypto": "0.3.13",
"sortablejs": "1.15.0", "sortablejs": "1.15.0",
"ua-parser-js": "1.0.35", "ua-parser-js": "1.0.35",
"uuid": "^11.1.0",
"v-viewer": "~1.6.4", "v-viewer": "~1.6.4",
"vue": "3.4.27", "vue": "3.4.27",
"vue-i18n": "9.13.1", "vue-i18n": "9.13.1",

View File

@@ -32,6 +32,7 @@
}, },
}, },
}" }"
:transformCellText="transformCellText"
> >
<!---全局loading---> <!---全局loading--->
<a-spin :spinning="spinning" tip="稍等片刻,我在拼命加载中..." size="large"> <a-spin :spinning="spinning" tip="稍等片刻,我在拼命加载中..." size="large">
@@ -43,13 +44,16 @@
<script setup> <script setup>
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { computed } from 'vue'; import { computed, h, useSlots } from 'vue';
import { messages } from '/@/i18n'; import { messages } from '/@/i18n';
import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { useSpinStore } from '/@/store/modules/system/spin'; import { useSpinStore } from '/@/store/modules/system/spin';
import { theme } from 'ant-design-vue'; import { theme } from 'ant-design-vue';
import { themeColors } from '/@/theme/color.js'; import { themeColors } from '/@/theme/color.js';
import { Popover } from 'ant-design-vue';
import SmartCopyIcon from '/@/components/smart-copy-icon/index.vue';
const slots = useSlots();
const antdLocale = computed(() => messages[useAppConfigStore().language].antdLocale); const antdLocale = computed(() => messages[useAppConfigStore().language].antdLocale);
const dayjsLocale = computed(() => messages[useAppConfigStore().language].dayjsLocale); const dayjsLocale = computed(() => messages[useAppConfigStore().language].dayjsLocale);
dayjs.locale(dayjsLocale); dayjs.locale(dayjsLocale);
@@ -67,4 +71,28 @@
const borderRadius = computed(() => { const borderRadius = computed(() => {
return useAppConfigStore().borderRadius; return useAppConfigStore().borderRadius;
}); });
function transformCellText({ text, column, record, index }) {
if (column && column.textEllipsisFlag === true) {
return h(
Popover,
{ placement: 'bottom' },
{
default: () =>
h('div', { style: { whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }, id: `${column.dataIndex}${index}` }, text),
content: () =>
h('div', { style: { display: 'flex' } }, [
h('div', text),
h(SmartCopyIcon, { value: document.getElementById(`${column.dataIndex}${index}`).innerText }),
]),
}
);
} else {
return text;
}
}
</script> </script>
<style scoped lang="less">
:deep(.ant-table-column-sorters) {
align-items: flex-start !important;
}
</style>

View File

@@ -36,10 +36,10 @@ export const employeeApi = {
return postRequest('/employee/update', params); return postRequest('/employee/update', params);
}, },
/** /**
* 更新登录人信息 * 更新员工个人中心信息
*/ */
updateByLogin: (params) => { updateCenter: (params) => {
return postRequest('/employee/update/login', params); return postRequest('/employee/update/center', params);
}, },
/** /**
* 更新登录人头像 * 更新登录人头像
@@ -77,25 +77,22 @@ export const employeeApi = {
updateEmployeePassword: (param) => { updateEmployeePassword: (param) => {
return postEncryptRequest('/employee/update/password', param); return postEncryptRequest('/employee/update/password', param);
}, },
/** /**
* 获取密码复杂度 * 获取密码复杂度
*/ */
getPasswordComplexityEnabled: () => { getPasswordComplexityEnabled: () => {
return getRequest('/employee/getPasswordComplexityEnabled'); return getRequest('/employee/getPasswordComplexityEnabled');
}, },
/** /**
* 更新员工禁用状态 * 更新员工禁用状态
*/ */
updateDisabled: (employeeId) => { updateDisabled: (employeeId) => {
return getRequest(`/employee/update/disabled/${employeeId}`); return getRequest(`/employee/update/disabled/${employeeId}`);
}, },
/** /**
* 查询员工-根据部门id * 查询员工-根据部门id
*/ */
queryEmployeeByDeptId: (departmentId) => { queryEmployeeByDeptId: (departmentId) => {
return getRequest(`/employee/query/dept/${departmentId}`); return getRequest(`/employee/getAllEmployeeByDepartmentId/${departmentId}`);
}, },
}; };

View File

@@ -0,0 +1,28 @@
<template>
<div>
<template v-for="(item, index) in options">
<template v-if="values.includes(item.valueCode)">
{{ item.valueName }}
<span> </span>
</template>
</template>
</div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
// 数据
options: {
type: Array,
default: null,
},
// 当前的值
value: [Number, String, Array],
});
const values = computed(() => {
if (props.value === null || typeof props.value === 'undefined' || props.value === '') return [];
return Array.isArray(props.value) ? props.value.map((item) => item.valueCode) : props.value.split(',');
});
</script>

View File

@@ -9,7 +9,11 @@
* *
--> -->
<template> <template>
<a-checkbox-group :style="`width: ${width}`" v-model:value="selectValue" :options="optionList" @change="handleChange" /> <a-checkbox-group :style="`width: ${width}`" v-model:value="selectValue" @change="handleChange" :disabled="disabled">
<a-checkbox v-for="item in valueDescList" :key="item.value" :value="item.value" :disabled="disabledOption.includes(item.value)">
{{ item.desc }}
</a-checkbox>
</a-checkbox-group>
</template> </template>
<script setup> <script setup>
@@ -22,19 +26,32 @@
type: String, type: String,
default: '200px', default: '200px',
}, },
// 禁用整个多选框
disabled: {
type: Boolean,
default: false,
},
// 需要禁用的选项枚举值
disabledOption: {
type: Array,
default: () => [],
},
// 需要隐藏的选项枚举值
hiddenOption: {
type: Array,
default: () => [],
},
}); });
// ------------ 枚举数据 加载和构建 ------------ // ------------ 枚举数据 加载和构建 ------------
const optionList = ref([]); const valueDescList = ref([]);
function buildOptionList() {
onMounted(() => {
const internalInstance = getCurrentInstance(); // 有效 全局 const internalInstance = getCurrentInstance(); // 有效 全局
const smartEnumPlugin = internalInstance.appContext.config.globalProperties.$smartEnumPlugin; const smartEnumPlugin = internalInstance.appContext.config.globalProperties.$smartEnumPlugin;
const valueList = smartEnumPlugin.getValueDescList(props.enumName); valueDescList.value = smartEnumPlugin.getValueDescList(props.enumName).filter((item) => !props.hiddenOption.includes(item.value));
optionList.value = valueList.map((e) => Object.assign({}, { value: e.value, label: e.desc })); });
}
onMounted(buildOptionList);
// ------------ 数据选中 事件及其相关 ------------ // ------------ 数据选中 事件及其相关 ------------
@@ -43,11 +60,14 @@
watch( watch(
() => props.value, () => props.value,
(newValue) => { (newValue) => {
selectValue.value = newValue; // 如果传入的值是被禁用或被隐藏的选项,则移除这些选项
} selectValue.value = newValue.filter((item) => !props.hiddenOption.includes(item) && !props.disabledOption.includes(item));
},
{ immediate: true }
); );
const emit = defineEmits(['update:value', 'change']); const emit = defineEmits(['update:value', 'change']);
function handleChange(value) { function handleChange(value) {
emit('update:value', value); emit('update:value', value);
emit('change', value); emit('change', value);

View File

@@ -10,15 +10,15 @@
--> -->
<template> <template>
<template v-if="isButton"> <template v-if="isButton">
<a-radio-group v-model:value="selectValue" @change="handleChange" button-style="solid"> <a-radio-group v-model:value="selectValue" @change="handleChange" button-style="solid" :disabled="disabled">
<a-radio-button v-for="item in $smartEnumPlugin.getValueDescList(props.enumName)" :key="item.value" :value="item.value"> <a-radio-button v-for="item in valueDescList" :key="item.value" :value="item.value" :disabled="disabledOption.includes(item.value)">
{{ item.desc }} {{ item.desc }}
</a-radio-button> </a-radio-button>
</a-radio-group> </a-radio-group>
</template> </template>
<template v-else> <template v-else>
<a-radio-group v-model:value="selectValue" @change="handleChange"> <a-radio-group v-model:value="selectValue" @change="handleChange" :disabled="disabled">
<a-radio v-for="item in $smartEnumPlugin.getValueDescList(props.enumName)" :key="item.value" :value="item.value"> <a-radio v-for="item in valueDescList" :key="item.value" :value="item.value" :disabled="disabledOption.includes(item.value)">
{{ item.desc }} {{ item.desc }}
</a-radio> </a-radio>
</a-radio-group> </a-radio-group>
@@ -26,7 +26,7 @@
</template> </template>
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch, onMounted, getCurrentInstance } from 'vue';
const props = defineProps({ const props = defineProps({
enumName: String, enumName: String,
@@ -43,19 +43,44 @@
type: Boolean, type: Boolean,
default: false, default: false,
}, },
// 禁用整个单选框
disabled: {
type: Boolean,
default: false,
},
// 需要禁用的选项枚举值
disabledOption: {
type: Array,
default: () => [],
},
// 需要隐藏的选项枚举值
hiddenOption: {
type: Array,
default: () => [],
},
}); });
const emit = defineEmits(['update:value', 'change']); const valueDescList = ref([]);
onMounted(() => {
const internalInstance = getCurrentInstance(); // 有效 全局
const smartEnumPlugin = internalInstance.appContext.config.globalProperties.$smartEnumPlugin;
valueDescList.value = smartEnumPlugin.getValueDescList(props.enumName).filter((item) => !props.hiddenOption.includes(item.value));
});
const selectValue = ref(props.value); const selectValue = ref(props.value);
watch( watch(
() => props.value, () => props.value,
(newValue) => { (newValue) => {
selectValue.value = newValue; // 如果传入的值是被禁用或被隐藏的选项,则移除该选项
} selectValue.value = props.disabledOption.includes(newValue) || props.hiddenOption.includes(newValue) ? undefined : newValue;
},
{ immediate: true }
); );
const emit = defineEmits(['update:value', 'change']);
function handleChange(e) { function handleChange(e) {
emit('update:value', e.target.value); emit('update:value', e.target.value);
emit('change', e.target.value); emit('change', e.target.value);

View File

@@ -19,18 +19,18 @@
@change="handleChange" @change="handleChange"
:disabled="disabled" :disabled="disabled"
> >
<a-select-option v-for="item in $smartEnumPlugin.getValueDescList(props.enumName)" :key="item.value" :value="item.value"> <a-select-option v-for="item in valueDescList" :key="item.value" :value="item.value" :disabled="disabledOption.includes(item.value)">
{{ item.desc }} {{ item.desc }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</template> </template>
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch, onMounted, getCurrentInstance } from 'vue';
const props = defineProps({ const props = defineProps({
enumName: String, enumName: String,
value: [Number,String], value: [Number, String],
width: { width: {
type: String, type: String,
default: '100%', default: '100%',
@@ -43,23 +43,44 @@
type: String, type: String,
default: 'default', default: 'default',
}, },
// 禁用整个下拉选择框
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
// 需要禁用的选项枚举值
disabledOption: {
type: Array,
default: () => [],
},
// 需要隐藏的选项枚举值
hiddenOption: {
type: Array,
default: () => [],
},
}); });
const emit = defineEmits(['update:value', 'change']); const valueDescList = ref([]);
onMounted(() => {
const internalInstance = getCurrentInstance(); // 有效 全局
const smartEnumPlugin = internalInstance.appContext.config.globalProperties.$smartEnumPlugin;
valueDescList.value = smartEnumPlugin.getValueDescList(props.enumName).filter((item) => !props.hiddenOption.includes(item.value));
});
const selectValue = ref(props.value); const selectValue = ref(props.value);
watch( watch(
() => props.value, () => props.value,
(newValue) => { (newValue) => {
selectValue.value = newValue; // 如果传入的值是被禁用或被隐藏的选项,则移除该选项
} selectValue.value = props.disabledOption.includes(newValue) || props.hiddenOption.includes(newValue) ? undefined : newValue;
},
{ immediate: true }
); );
const emit = defineEmits(['update:value', 'change']);
function handleChange(value) { function handleChange(value) {
emit('update:value', value); emit('update:value', value);
emit('change', value); emit('change', value);

Some files were not shown because too many files have changed in this diff Show More