Compare commits
10 Commits
db762a0f03
...
94bee0be90
| Author | SHA1 | Date | |
|---|---|---|---|
| 94bee0be90 | |||
| 4277ff1869 | |||
| 7e77f64cc1 | |||
| daaf3d4bfa | |||
| 1544286664 | |||
| 42fea892c6 | |||
| 102fe8a94b | |||
| 2c64f7575f | |||
| 251d7ca502 | |||
| 4085b44d0b |
@@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 参考检查Controller
|
||||
* 背景调查Controller
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-01-29
|
||||
@@ -30,9 +30,9 @@ public class HotakeReferenceCheckController extends BaseController {
|
||||
private IHotakeReferenceCheckService hotakeReferenceCheckService;
|
||||
|
||||
/**
|
||||
* 查询参考检查列表
|
||||
* 查询背景调查列表
|
||||
*/
|
||||
@ApiOperation("查询参考检查列表(分页)")
|
||||
@ApiOperation("查询背景调查列表(分页)")
|
||||
@GetMapping("/getPagelist")
|
||||
public TableWebDataInfo<HotakeReferenceCheck> list(HotakeReferenceCheck hotakeReferenceCheck) {
|
||||
startPage();
|
||||
@@ -42,9 +42,9 @@ public class HotakeReferenceCheckController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询参考检查列表
|
||||
* 查询背景调查列表
|
||||
*/
|
||||
@ApiOperation("查询参考检查列表(无分页)")
|
||||
@ApiOperation("查询背景调查列表(无分页)")
|
||||
@GetMapping("/getList")
|
||||
public R<List<HotakeReferenceCheck>> getList(HotakeReferenceCheck hotakeReferenceCheck) {
|
||||
hotakeReferenceCheck.setCreateBy(getUsername());
|
||||
@@ -53,39 +53,50 @@ public class HotakeReferenceCheckController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取参考检查详细信息
|
||||
* 获取背景调查详细信息
|
||||
*/
|
||||
@ApiOperation("获取参考检查详细信息")
|
||||
@ApiOperation("获取背景调查详细信息")
|
||||
@GetMapping(value = "/{id}")
|
||||
public R<HotakeReferenceCheck> getInfo(@ApiParam("参考检查ID") @PathVariable("id") Integer id) {
|
||||
public R<HotakeReferenceCheck> getInfo(@ApiParam("背景调查ID") @PathVariable("id") Integer id) {
|
||||
return R.ok(hotakeReferenceCheckService.selectHotakeReferenceCheckById(id), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增参考检查
|
||||
* 新增背景调查
|
||||
*/
|
||||
@ApiOperation("新增参考检查")
|
||||
@Log(title = "参考检查", businessType = BusinessType.INSERT)
|
||||
@ApiOperation("新增背景调查")
|
||||
@Log(title = "背景调查", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public R<HotakeReferenceCheck> add(@RequestBody HotakeReferenceCheck hotakeReferenceCheck) {
|
||||
return R.ok(hotakeReferenceCheckService.insertHotakeReferenceCheck(hotakeReferenceCheck));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改参考检查
|
||||
* 批量新增背景调查
|
||||
*/
|
||||
@ApiOperation("修改参考检查")
|
||||
@Log(title = "参考检查", businessType = BusinessType.UPDATE)
|
||||
@ApiOperation("批量新增背景调查")
|
||||
@Log(title = "背景调查", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/batch")
|
||||
public R<Integer> batchAdd(@RequestBody List<HotakeReferenceCheck> hotakeReferenceCheckList) {
|
||||
int count = hotakeReferenceCheckService.batchInsertHotakeReferenceCheck(hotakeReferenceCheckList);
|
||||
return R.ok(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改背景调查
|
||||
*/
|
||||
@ApiOperation("修改背景调查")
|
||||
@Log(title = "背景调查", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public R<HotakeReferenceCheck> edit(@RequestBody HotakeReferenceCheck hotakeReferenceCheck) {
|
||||
return R.ok(hotakeReferenceCheckService.updateHotakeReferenceCheck(hotakeReferenceCheck));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除参考检查
|
||||
* 删除背景调查
|
||||
*/
|
||||
@ApiOperation("删除参考检查")
|
||||
@Log(title = "参考检查", businessType = BusinessType.DELETE)
|
||||
@ApiOperation("删除背景调查")
|
||||
@Log(title = "背景调查", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{id}")
|
||||
public R remove(@PathVariable Integer id) {
|
||||
return R.ok(hotakeReferenceCheckService.deleteHotakeReferenceCheckById(id));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# 开发环境配置
|
||||
server:
|
||||
# 服务器的HTTP端口,默认为8080
|
||||
port: 8686
|
||||
port: 8080
|
||||
servlet:
|
||||
# 应用的访问路径
|
||||
context-path: /
|
||||
@@ -40,9 +40,9 @@ spring:
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://13.211.168.80:3306/vetti_service?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: vetti_service
|
||||
password: Hotake@2025
|
||||
url: jdbc:mysql://ddns.hotake.cn:13306/vetti_service?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: Hamkke@2021
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
@@ -207,7 +207,7 @@ oauth2:
|
||||
google:
|
||||
client-id: 398978985110-ve0usu381mmdio12ff01iqvv1g087qvi.apps.googleusercontent.com # Google Cloud Console获取
|
||||
client-secret: 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 # Google Cloud Console获取
|
||||
redirect-uri: https://vetti.hotake.cn/oauth2/callback/google
|
||||
redirect-uri: https://vetti.com.au/oauth2/callback/google
|
||||
scope: openid email profile # Google标准scope(空格分隔)
|
||||
auth-uri: https://accounts.google.com/o/oauth2/v2/auth # Google授权地址
|
||||
token-uri: https://oauth2.googleapis.com/token # Google令牌地址
|
||||
@@ -220,7 +220,7 @@ oauth2:
|
||||
microsoft:
|
||||
client-id: 608cbc4f-3ee2-4f51-a72c-b2e3133fc5b2 # Azure Portal获取
|
||||
client-secret: gvw8Q~dwG8Sv7HN3R3W3R7TQtcZyvrh88ZiJubPa # Azure Portal获取
|
||||
redirect-uri: https://vetti.hotake.cn/api/oauth2/callback/microsoft
|
||||
redirect-uri: https://vetti.com.au/oauth2/callback/microsoft
|
||||
scope: openid,email,profile,User.Read # 需要额外的User.Read权限才能读取用户信息
|
||||
auth-uri: https://login.microsoftonline.com/common/oauth2/v2.0/authorize # 微软授权地址
|
||||
token-uri: https://login.microsoftonline.com/common/oauth2/v2.0/token # 微软令牌地址
|
||||
@@ -233,7 +233,7 @@ oauth2:
|
||||
linkedin:
|
||||
client-id: 86uq3opzshd3bq # LinkedIn Developer Portal获取
|
||||
client-secret: WPL_AP1.mipgyxfgfBoN12Th.1TXeFg== # LinkedIn Developer Portal获取
|
||||
redirect-uri: https://vetti.hotake.cn/api/oauth2/callback/linkedin
|
||||
redirect-uri: https://vetti.com.au/oauth2/callback/linkedin
|
||||
scope: openid profile email # LinkedIn使用OpenID Connect,scope顺序和命名略有不同
|
||||
auth-uri: https://www.linkedin.com/oauth/v2/authorization # LinkedIn授权地址
|
||||
token-uri: https://www.linkedin.com/oauth/v2/accessToken # LinkedIn令牌地址
|
||||
|
||||
@@ -86,3 +86,10 @@ HotakeSecurityController10004 = All other sessions terminated
|
||||
|
||||
# Logout related
|
||||
HotakeSecurityServiceImpl10011 = User logged out
|
||||
|
||||
|
||||
# Trusted device related messages
|
||||
HotakeSecurityServiceImpl10012 = Updated trusted device
|
||||
HotakeSecurityServiceImpl10013 = Added trusted device
|
||||
HotakeSecurityServiceImpl10014 = Device does not exist or no permission to operate
|
||||
HotakeSecurityServiceImpl10015 = Removed trusted device
|
||||
|
||||
@@ -83,3 +83,10 @@ HotakeSecurityController10004 = 所有其他会话已终止
|
||||
|
||||
# 退出登录相关
|
||||
HotakeSecurityServiceImpl10011 = 用户退出登录
|
||||
|
||||
|
||||
# 可信设备相关消息
|
||||
HotakeSecurityServiceImpl10012 = 更新可信设备
|
||||
HotakeSecurityServiceImpl10013 = 添加可信设备
|
||||
HotakeSecurityServiceImpl10014 = 设备不存在或无权操作
|
||||
HotakeSecurityServiceImpl10015 = 移除可信设备
|
||||
|
||||
@@ -154,6 +154,25 @@ public class ResumeTextExtractor {
|
||||
* 3. 设置合理的经验范围限制(1-30年)
|
||||
* 4. 如果无法估算,返回随机的合理值(2-10年)
|
||||
*
|
||||
* TODO: 修复工作年限计算错误 - Bug修复说明
|
||||
* 问题:原有算法直接用 endYear - earliestYear 计算工作年限,
|
||||
* 这会导致将教育时间也计算在内,例如:
|
||||
* - 2006年上大学,2025年工作 = 19年(错误)
|
||||
* - 实际应该是2010年毕业后开始工作,约15年
|
||||
*
|
||||
* 修复方案:
|
||||
* 1. 优先使用AI解析的experienceYear字段(已在AI提示词中修复)
|
||||
* 2. 此方法作为备用估算,采用保守策略:
|
||||
* - 假设教育时间约4年(本科)
|
||||
* - 从最早年份+4年开始计算工作经验
|
||||
* - 这样可以避免将教育时间计入工作年限
|
||||
* 3. 如果年份跨度小于4年,说明可能没有教育经历,直接计算
|
||||
*
|
||||
* 注意:这只是备用估算方法,主要依赖AI解析的准确结果
|
||||
*
|
||||
* 修改日期:2026-02-04
|
||||
* 修改人:sxc
|
||||
*
|
||||
* @param text 简历文本
|
||||
* @return 估算的工作经验年数
|
||||
*/
|
||||
@@ -178,9 +197,25 @@ public class ResumeTextExtractor {
|
||||
int latestYear = years.get(years.size() - 1);
|
||||
int currentYear = Year.now().getValue();
|
||||
|
||||
// 计算工作经验:从最早年份到最新年份(不超过当前年份)
|
||||
// 计算工作经验:从最新年份(不超过当前年份)
|
||||
int endYear = Math.min(latestYear, currentYear);
|
||||
int experience = endYear - earliestYear;
|
||||
|
||||
// TODO: 修复点 - 排除教育时间
|
||||
// 假设教育时间约4年,从最早年份+4年开始计算工作经验
|
||||
// 这样可以避免将大学时间计入工作年限
|
||||
int yearSpan = endYear - earliestYear;
|
||||
int experience;
|
||||
|
||||
if (yearSpan <= 4) {
|
||||
// 如果年份跨度小于等于4年,说明可能没有教育经历或者是短期工作
|
||||
// 直接使用年份差
|
||||
experience = yearSpan;
|
||||
} else {
|
||||
// 年份跨度大于4年,假设前4年是教育时间
|
||||
// 从最早年份+4年开始计算工作经验
|
||||
int workStartYear = earliestYear + 4;
|
||||
experience = endYear - workStartYear;
|
||||
}
|
||||
|
||||
// 限制经验年数在合理范围内(1-30年)
|
||||
return Math.max(1, Math.min(experience, 30));
|
||||
|
||||
@@ -114,7 +114,7 @@ public class SecurityConfig
|
||||
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
||||
requests.antMatchers("/login", "/register", "/captchaImage","/aiCommon/**","/voice-websocket/multiple/**",
|
||||
"/voice-websocket/**","/voice-websocket/multiplePcm/**","/verification/email/send","/verification/email/verify","/verification/phone/send",
|
||||
"/forgotPassword","/verification/email/register/send","/voice-websocket/elevenLabsAgent/**").permitAll()
|
||||
"/forgotPassword","/verification/email/register/send","/voice-websocket/elevenLabsAgent/**","/oauth2/authorize/**","/prod-api/oauth2/authorize/**").permitAll()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.vetti.hotake.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 修改密码DTO
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("修改密码请求")
|
||||
public class SecurityChangePasswordDto
|
||||
{
|
||||
/** 当前密码 */
|
||||
@ApiModelProperty(value = "当前密码", required = true)
|
||||
@NotBlank(message = "当前密码不能为空")
|
||||
private String currentPassword;
|
||||
|
||||
/** 新密码 */
|
||||
@ApiModelProperty(value = "新密码", required = true)
|
||||
@NotBlank(message = "新密码不能为空")
|
||||
@Size(min = 6, max = 20, message = "密码长度必须在6-20个字符之间")
|
||||
private String newPassword;
|
||||
|
||||
/** 确认新密码 */
|
||||
@ApiModelProperty(value = "确认新密码", required = true)
|
||||
@NotBlank(message = "确认密码不能为空")
|
||||
private String confirmPassword;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.vetti.hotake.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 登录会话VO
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("登录会话信息")
|
||||
public class SecuritySessionVo
|
||||
{
|
||||
/** 会话ID */
|
||||
@ApiModelProperty("会话ID")
|
||||
private Long id;
|
||||
|
||||
/** 设备名称(浏览器 + 操作系统) */
|
||||
@ApiModelProperty("设备名称")
|
||||
private String deviceName;
|
||||
|
||||
/** 设备类型 */
|
||||
@ApiModelProperty("设备类型")
|
||||
private String deviceType;
|
||||
|
||||
/** 浏览器 */
|
||||
@ApiModelProperty("浏览器")
|
||||
private String browser;
|
||||
|
||||
/** 操作系统 */
|
||||
@ApiModelProperty("操作系统")
|
||||
private String os;
|
||||
|
||||
/** IP地址 */
|
||||
@ApiModelProperty("IP地址")
|
||||
private String ipAddress;
|
||||
|
||||
/** 地理位置 */
|
||||
@ApiModelProperty("地理位置")
|
||||
private String location;
|
||||
|
||||
/** 登录时间 */
|
||||
@ApiModelProperty("登录时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date loginTime;
|
||||
|
||||
/** 最后活动时间 */
|
||||
@ApiModelProperty("最后活动时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date lastActivityTime;
|
||||
|
||||
/** 是否当前会话 */
|
||||
@ApiModelProperty("是否当前会话")
|
||||
private Boolean isCurrent;
|
||||
|
||||
/** 是否活跃 */
|
||||
@ApiModelProperty("是否活跃")
|
||||
private Boolean isActive;
|
||||
}
|
||||
@@ -35,6 +35,14 @@ public interface HotakeReferenceCheckMapper
|
||||
*/
|
||||
public int insertHotakeReferenceCheck(HotakeReferenceCheck hotakeReferenceCheck);
|
||||
|
||||
/**
|
||||
* 批量新增参考检查
|
||||
*
|
||||
* @param hotakeReferenceCheckList 参考检查列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batchInsertHotakeReferenceCheck(List<HotakeReferenceCheck> hotakeReferenceCheckList);
|
||||
|
||||
/**
|
||||
* 修改参考检查
|
||||
*
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.vetti.hotake.mapper;
|
||||
|
||||
import com.vetti.hotake.domain.HotakeSecurityLoginSessions;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户登录会话Mapper接口
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
public interface HotakeSecurityLoginSessionsMapper
|
||||
{
|
||||
/**
|
||||
* 查询用户登录会话
|
||||
*
|
||||
* @param id 用户登录会话主键
|
||||
* @return 用户登录会话
|
||||
*/
|
||||
public HotakeSecurityLoginSessions selectHotakeSecurityLoginSessionsById(Long id);
|
||||
|
||||
/**
|
||||
* 根据会话令牌查询会话
|
||||
*
|
||||
* @param sessionToken 会话令牌
|
||||
* @return 用户登录会话
|
||||
*/
|
||||
public HotakeSecurityLoginSessions selectHotakeSecurityLoginSessionsByToken(String sessionToken);
|
||||
|
||||
/**
|
||||
* 查询用户登录会话列表
|
||||
*
|
||||
* @param hotakeSecurityLoginSessions 用户登录会话
|
||||
* @return 用户登录会话集合
|
||||
*/
|
||||
public List<HotakeSecurityLoginSessions> selectHotakeSecurityLoginSessionsList(HotakeSecurityLoginSessions hotakeSecurityLoginSessions);
|
||||
|
||||
/**
|
||||
* 查询用户的活跃会话列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 用户登录会话集合
|
||||
*/
|
||||
public List<HotakeSecurityLoginSessions> selectActiveSessionsByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 新增用户登录会话
|
||||
*
|
||||
* @param hotakeSecurityLoginSessions 用户登录会话
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertHotakeSecurityLoginSessions(HotakeSecurityLoginSessions hotakeSecurityLoginSessions);
|
||||
|
||||
/**
|
||||
* 修改用户登录会话
|
||||
*
|
||||
* @param hotakeSecurityLoginSessions 用户登录会话
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateHotakeSecurityLoginSessions(HotakeSecurityLoginSessions hotakeSecurityLoginSessions);
|
||||
|
||||
/**
|
||||
* 删除用户登录会话
|
||||
*
|
||||
* @param id 用户登录会话主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityLoginSessionsById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除用户登录会话
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityLoginSessionsByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 终止用户的其他会话(除了当前会话)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param currentSessionToken 当前会话令牌
|
||||
* @return 结果
|
||||
*/
|
||||
public int terminateOtherSessions(@Param("userId") Long userId, @Param("currentSessionToken") String currentSessionToken);
|
||||
|
||||
/**
|
||||
* 终止指定会话
|
||||
*
|
||||
* @param id 会话ID
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int terminateSession(@Param("id") Long id, @Param("userId") Long userId);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.vetti.hotake.mapper;
|
||||
|
||||
import com.vetti.hotake.domain.HotakeSecurityPasswordHistory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 密码历史记录Mapper接口
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
public interface HotakeSecurityPasswordHistoryMapper
|
||||
{
|
||||
/**
|
||||
* 查询密码历史记录
|
||||
*
|
||||
* @param id 密码历史记录主键
|
||||
* @return 密码历史记录
|
||||
*/
|
||||
public HotakeSecurityPasswordHistory selectHotakeSecurityPasswordHistoryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询密码历史记录列表
|
||||
*
|
||||
* @param hotakeSecurityPasswordHistory 密码历史记录
|
||||
* @return 密码历史记录集合
|
||||
*/
|
||||
public List<HotakeSecurityPasswordHistory> selectHotakeSecurityPasswordHistoryList(HotakeSecurityPasswordHistory hotakeSecurityPasswordHistory);
|
||||
|
||||
/**
|
||||
* 查询用户最近的密码历史记录
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param limit 查询数量
|
||||
* @return 密码历史记录集合
|
||||
*/
|
||||
public List<HotakeSecurityPasswordHistory> selectRecentPasswordHistory(Long userId, int limit);
|
||||
|
||||
/**
|
||||
* 新增密码历史记录
|
||||
*
|
||||
* @param hotakeSecurityPasswordHistory 密码历史记录
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertHotakeSecurityPasswordHistory(HotakeSecurityPasswordHistory hotakeSecurityPasswordHistory);
|
||||
|
||||
/**
|
||||
* 修改密码历史记录
|
||||
*
|
||||
* @param hotakeSecurityPasswordHistory 密码历史记录
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateHotakeSecurityPasswordHistory(HotakeSecurityPasswordHistory hotakeSecurityPasswordHistory);
|
||||
|
||||
/**
|
||||
* 删除密码历史记录
|
||||
*
|
||||
* @param id 密码历史记录主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityPasswordHistoryById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除密码历史记录
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityPasswordHistoryByIds(Long[] ids);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.vetti.hotake.mapper;
|
||||
|
||||
import com.vetti.hotake.domain.HotakeSecuritySecurityLogs;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 安全日志Mapper接口
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
public interface HotakeSecuritySecurityLogsMapper
|
||||
{
|
||||
/**
|
||||
* 查询安全日志
|
||||
*
|
||||
* @param id 安全日志主键
|
||||
* @return 安全日志
|
||||
*/
|
||||
public HotakeSecuritySecurityLogs selectHotakeSecuritySecurityLogsById(Long id);
|
||||
|
||||
/**
|
||||
* 查询安全日志列表
|
||||
*
|
||||
* @param hotakeSecuritySecurityLogs 安全日志
|
||||
* @return 安全日志集合
|
||||
*/
|
||||
public List<HotakeSecuritySecurityLogs> selectHotakeSecuritySecurityLogsList(HotakeSecuritySecurityLogs hotakeSecuritySecurityLogs);
|
||||
|
||||
/**
|
||||
* 新增安全日志
|
||||
*
|
||||
* @param hotakeSecuritySecurityLogs 安全日志
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertHotakeSecuritySecurityLogs(HotakeSecuritySecurityLogs hotakeSecuritySecurityLogs);
|
||||
|
||||
/**
|
||||
* 修改安全日志
|
||||
*
|
||||
* @param hotakeSecuritySecurityLogs 安全日志
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateHotakeSecuritySecurityLogs(HotakeSecuritySecurityLogs hotakeSecuritySecurityLogs);
|
||||
|
||||
/**
|
||||
* 删除安全日志
|
||||
*
|
||||
* @param id 安全日志主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecuritySecurityLogsById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除安全日志
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecuritySecurityLogsByIds(Long[] ids);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.vetti.hotake.mapper;
|
||||
|
||||
import com.vetti.hotake.domain.HotakeSecuritySettings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户安全设置Mapper接口
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
public interface HotakeSecuritySettingsMapper
|
||||
{
|
||||
/**
|
||||
* 查询用户安全设置
|
||||
*
|
||||
* @param id 用户安全设置主键
|
||||
* @return 用户安全设置
|
||||
*/
|
||||
public HotakeSecuritySettings selectHotakeSecuritySettingsById(Long id);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询安全设置
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 用户安全设置
|
||||
*/
|
||||
public HotakeSecuritySettings selectHotakeSecuritySettingsByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户安全设置列表
|
||||
*
|
||||
* @param hotakeSecuritySettings 用户安全设置
|
||||
* @return 用户安全设置集合
|
||||
*/
|
||||
public List<HotakeSecuritySettings> selectHotakeSecuritySettingsList(HotakeSecuritySettings hotakeSecuritySettings);
|
||||
|
||||
/**
|
||||
* 新增用户安全设置
|
||||
*
|
||||
* @param hotakeSecuritySettings 用户安全设置
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertHotakeSecuritySettings(HotakeSecuritySettings hotakeSecuritySettings);
|
||||
|
||||
/**
|
||||
* 修改用户安全设置
|
||||
*
|
||||
* @param hotakeSecuritySettings 用户安全设置
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateHotakeSecuritySettings(HotakeSecuritySettings hotakeSecuritySettings);
|
||||
|
||||
/**
|
||||
* 删除用户安全设置
|
||||
*
|
||||
* @param id 用户安全设置主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecuritySettingsById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除用户安全设置
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecuritySettingsByIds(Long[] ids);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.vetti.hotake.mapper;
|
||||
|
||||
import com.vetti.hotake.domain.HotakeSecurityTrustedDevices;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 可信设备Mapper接口
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
public interface HotakeSecurityTrustedDevicesMapper
|
||||
{
|
||||
/**
|
||||
* 查询可信设备
|
||||
*
|
||||
* @param id 可信设备主键
|
||||
* @return 可信设备
|
||||
*/
|
||||
public HotakeSecurityTrustedDevices selectHotakeSecurityTrustedDevicesById(Long id);
|
||||
|
||||
/**
|
||||
* 根据用户ID和设备ID查询可信设备
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param deviceId 设备ID
|
||||
* @return 可信设备
|
||||
*/
|
||||
public HotakeSecurityTrustedDevices selectByUserIdAndDeviceId(@Param("userId") Long userId, @Param("deviceId") String deviceId);
|
||||
|
||||
/**
|
||||
* 查询可信设备列表
|
||||
*
|
||||
* @param hotakeSecurityTrustedDevices 可信设备
|
||||
* @return 可信设备集合
|
||||
*/
|
||||
public List<HotakeSecurityTrustedDevices> selectHotakeSecurityTrustedDevicesList(HotakeSecurityTrustedDevices hotakeSecurityTrustedDevices);
|
||||
|
||||
/**
|
||||
* 查询用户的可信设备列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 可信设备集合
|
||||
*/
|
||||
public List<HotakeSecurityTrustedDevices> selectTrustedDevicesByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 新增可信设备
|
||||
*
|
||||
* @param hotakeSecurityTrustedDevices 可信设备
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertHotakeSecurityTrustedDevices(HotakeSecurityTrustedDevices hotakeSecurityTrustedDevices);
|
||||
|
||||
/**
|
||||
* 修改可信设备
|
||||
*
|
||||
* @param hotakeSecurityTrustedDevices 可信设备
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateHotakeSecurityTrustedDevices(HotakeSecurityTrustedDevices hotakeSecurityTrustedDevices);
|
||||
|
||||
/**
|
||||
* 删除可信设备
|
||||
*
|
||||
* @param id 可信设备主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityTrustedDevicesById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除可信设备
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityTrustedDevicesByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 移除用户的可信设备
|
||||
*
|
||||
* @param id 设备记录ID
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int removeTrustedDevice(@Param("id") Long id, @Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 清理过期的可信设备
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public int cleanExpiredTrustedDevices();
|
||||
}
|
||||
@@ -35,6 +35,14 @@ public interface IHotakeReferenceCheckService
|
||||
*/
|
||||
public HotakeReferenceCheck insertHotakeReferenceCheck(HotakeReferenceCheck hotakeReferenceCheck);
|
||||
|
||||
/**
|
||||
* 批量新增参考检查
|
||||
*
|
||||
* @param hotakeReferenceCheckList 参考检查列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batchInsertHotakeReferenceCheck(List<HotakeReferenceCheck> hotakeReferenceCheckList);
|
||||
|
||||
/**
|
||||
* 修改参考检查
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.vetti.hotake.service;
|
||||
import com.vetti.hotake.domain.HotakeSecuritySettings;
|
||||
import com.vetti.hotake.domain.dto.SecurityChangePasswordDto;
|
||||
import com.vetti.hotake.domain.vo.SecuritySessionVo;
|
||||
import com.vetti.hotake.domain.vo.SecurityTrustedDeviceVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -97,4 +98,37 @@ public interface IHotakeSecurityService
|
||||
* @return 结果
|
||||
*/
|
||||
int updateSessionLogout(String sessionToken);
|
||||
|
||||
/**
|
||||
* 获取当前用户的可信设备列表
|
||||
*
|
||||
* @return 可信设备列表
|
||||
*/
|
||||
List<SecurityTrustedDeviceVo> getTrustedDevices();
|
||||
|
||||
/**
|
||||
* 添加可信设备
|
||||
*
|
||||
* @param deviceId 设备唯一标识
|
||||
* @param deviceName 设备名称
|
||||
* @return 结果
|
||||
*/
|
||||
int addTrustedDevice(String deviceId, String deviceName);
|
||||
|
||||
/**
|
||||
* 移除可信设备
|
||||
*
|
||||
* @param id 设备记录ID
|
||||
* @return 结果
|
||||
*/
|
||||
int removeTrustedDevice(Long id);
|
||||
|
||||
/**
|
||||
* 检查设备是否为可信设备
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param deviceId 设备唯一标识
|
||||
* @return 是否可信
|
||||
*/
|
||||
boolean isTrustedDevice(Long userId, String deviceId);
|
||||
}
|
||||
|
||||
@@ -1427,28 +1427,30 @@ public class HotakeAiCommonToolsServiceImpl extends BaseServiceImpl implements I
|
||||
String resultJsonOne = resultStrOne.replaceAll("```json", "").replaceAll("```", "");
|
||||
log.info("候选人面试综合评估:{}", resultJsonOne);
|
||||
Map dataMap = JSONUtil.toBean(resultJsonOne, Map.class);
|
||||
Map scoreBreakdownMap = (Map) dataMap.get("score_breakdown");
|
||||
if (scoreBreakdownMap != null) {
|
||||
Map assessmentMap = (Map) scoreBreakdownMap.get("assessment");
|
||||
if (assessmentMap != null) {
|
||||
dto.setAssessmentScore(assessmentMap.get("score").toString());
|
||||
dto.setAssessmentLevel(assessmentMap.get("score").toString());
|
||||
List<String> details = (List<String>) assessmentMap.get("details");
|
||||
dto.setAssessmentDetails(details);
|
||||
}
|
||||
Map ratingMap = (Map) scoreBreakdownMap.get("rating");
|
||||
if (ratingMap != null) {
|
||||
dto.setRatingScore(ratingMap.get("score").toString());
|
||||
dto.setRatingLevel(ratingMap.get("score").toString());
|
||||
List<String> details = (List<String>) ratingMap.get("details");
|
||||
dto.setRatingDetails(details);
|
||||
}
|
||||
Map questionsMap = (Map) scoreBreakdownMap.get("questions");
|
||||
if (questionsMap != null) {
|
||||
dto.setQuestionsScore(questionsMap.get("score").toString());
|
||||
dto.setQuestionsLevel(questionsMap.get("score").toString());
|
||||
List<String> details = (List<String>) questionsMap.get("details");
|
||||
dto.setQuestionsDetails(details);
|
||||
if(dataMap != null){
|
||||
Map scoreBreakdownMap = (Map) dataMap.get("score_breakdown");
|
||||
if (scoreBreakdownMap != null) {
|
||||
Map assessmentMap = (Map) scoreBreakdownMap.get("assessment");
|
||||
if (assessmentMap != null) {
|
||||
dto.setAssessmentScore(assessmentMap.get("score").toString());
|
||||
dto.setAssessmentLevel(assessmentMap.get("score").toString());
|
||||
List<String> details = (List<String>) assessmentMap.get("details");
|
||||
dto.setAssessmentDetails(details);
|
||||
}
|
||||
Map ratingMap = (Map) scoreBreakdownMap.get("rating");
|
||||
if (ratingMap != null) {
|
||||
dto.setRatingScore(ratingMap.get("score").toString());
|
||||
dto.setRatingLevel(ratingMap.get("score").toString());
|
||||
List<String> details = (List<String>) ratingMap.get("details");
|
||||
dto.setRatingDetails(details);
|
||||
}
|
||||
Map questionsMap = (Map) scoreBreakdownMap.get("questions");
|
||||
if (questionsMap != null) {
|
||||
dto.setQuestionsScore(questionsMap.get("score").toString());
|
||||
dto.setQuestionsLevel(questionsMap.get("score").toString());
|
||||
List<String> details = (List<String>) questionsMap.get("details");
|
||||
dto.setQuestionsDetails(details);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -547,7 +547,21 @@ public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeC
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> entity = new HashMap<>();
|
||||
entity.put("role", "user");
|
||||
entity.put("content", "从下面提供的文本中提取所有能识别到的简历信息,只提取原文中存在的内容,不要补充、不推测、不总结。需要提取的字段包括:name(姓名或人名)、phone(电话号码)、email(电子邮件地址)、experienceYear(根据工作经验计算出来的工作年限)、position(岗位或者简历中自己期望的职位等)、location(地点或者地址、家庭住址)、links(所有链接地址)、currentWork(当前工作公司)、about(关于我/自我介绍)、skills_tools(关键资格(许可证、注册/会员资格、认证))、languages(语言能力,主要就是Languages下面的语言)、experience(工作经历,除了title、company、location、durationStart、durationEnd,其他的都放到description里面,并且description里面要根据换行符分成不同的content),日期要拆分成开始时间(durationStart)和结束时间(durationEnd))、education(教育经历,日期要拆分成开始时间(durationStart)和结束时间(durationEnd))。请将提取结果以结构化 JSON 格式返回,格式如下:{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"currentWork\\\": \\\"\\\", \\\"position\\\": \\\"\\\", \\\"location\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"experienceYear\\\": \\\"\\\", \\\"links\\\": [{\\\"content\\\":\\\"\\\"}], \\\"about\\\": \\\"\\\", \\\"skillsTools\\\": [{\\\"content\\\":\\\"\\\"}], \\\"languages\\\": [{\\\"content\\\":\\\"\\\"}], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\",\\\"description\\\": [{\\\"content\\\":\\\"\\\"}]}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息," +
|
||||
// TODO: 修复工作年限计算错误 - Bug修复说明
|
||||
// 问题:之前的提示词中"experienceYear(根据工作经验计算出来的工作年限)"描述不够明确,
|
||||
// 导致AI可能会将教育时间也计算在内,或者简单地用最早年份到最新年份的差值,
|
||||
// 例如:2006年上大学到2025年工作 = 19年(错误),实际应该是2010年毕业后开始工作约15年
|
||||
//
|
||||
// 修复方案:在提示词中明确工作年限的计算规则:
|
||||
// 1. 只计算experience(工作经历)中的时间段,不包括education(教育经历)
|
||||
// 2. 累加所有工作经历的实际工作时长(年)
|
||||
// 3. 如果工作结束时间是"Present"、"Current"、"至今"等,使用当前年份(2026)计算
|
||||
// 4. 计算公式:总工作年限 = Σ(每段工作的结束年份 - 开始年份)
|
||||
// 5. 结果保留整数,向下取整
|
||||
//
|
||||
// 修改日期:2026-02-04
|
||||
// 修改人:sxc
|
||||
entity.put("content", "从下面提供的文本中提取所有能识别到的简历信息,只提取原文中存在的内容,不要补充、不推测、不总结。需要提取的字段包括:name(姓名或人名)、phone(电话号码)、email(电子邮件地址)、experienceYear(工作年限,重要:只计算experience工作经历中的实际工作时长,不包括education教育时间。计算方法:累加所有工作经历的年数,如果结束时间是Present/Current/至今则用2026年计算,例如:2018-01到2020-06工作2年+2021-03到Present工作5年=总共7年工作经验)、position(岗位或者简历中自己期望的职位等)、location(地点或者地址、家庭住址)、links(所有链接地址)、currentWork(当前工作公司)、about(关于我/自我介绍)、skills_tools(关键资格(许可证、注册/会员资格、认证))、languages(语言能力,主要就是Languages下面的语言)、experience(工作经历,除了title、company、location、durationStart、durationEnd,其他的都放到description里面,并且description里面要根据换行符分成不同的content),日期要拆分成开始时间(durationStart)和结束时间(durationEnd))、education(教育经历,日期要拆分成开始时间(durationStart)和结束时间(durationEnd))。请将提取结果以结构化 JSON 格式返回,格式如下:{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"currentWork\\\": \\\"\\\", \\\"position\\\": \\\"\\\", \\\"location\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"experienceYear\\\": \\\"\\\", \\\"links\\\": [{\\\"content\\\":\\\"\\\"}], \\\"about\\\": \\\"\\\", \\\"skillsTools\\\": [{\\\"content\\\":\\\"\\\"}], \\\"languages\\\": [{\\\"content\\\":\\\"\\\"}], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\",\\\"description\\\": [{\\\"content\\\":\\\"\\\"}]}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息," +
|
||||
"不要解释说明,不要改写内容,其中日期字段要转换格式为:yyyy-MM,例如 Apr 2016,要转换成 2016-04,并且只有年要补充固定月份01月,例如2025,要转换成2025-01。以下为待处理文本:" + contents);
|
||||
//根据AI做
|
||||
list.add(entity);
|
||||
|
||||
@@ -277,34 +277,37 @@ public class HotakeInitScreQuestionsReplyRecordInfoServiceImpl extends BaseServi
|
||||
// HotakeCandidateCompatibilityDto compatibilityDto = aiCommonToolsService.handleCandidateCompatibility(compatibilityVo);
|
||||
// applyInfo.setCandidateCompatibilityJson(JSONUtil.toJsonStr(compatibilityDto));
|
||||
// applyInfo.setCandidateCompatibilityScore(compatibilityDto.getOverallScore());
|
||||
try{
|
||||
//候选人面试综合评估
|
||||
HotakeCandidateInterviewEvaluationVo evaluationVo = new HotakeCandidateInterviewEvaluationVo();
|
||||
|
||||
//候选人面试综合评估
|
||||
HotakeCandidateInterviewEvaluationVo evaluationVo = new HotakeCandidateInterviewEvaluationVo();
|
||||
evaluationVo.setTitle(rolesInf.getRoleName());
|
||||
evaluationVo.setDescription(rolesInf.getAboutRole());
|
||||
evaluationVo.setRequiredSkills(rolesInf.getRequiredSkillsJson());
|
||||
evaluationVo.setPreferredSkills(rolesInf.getNiceToHaveSkillsJson());
|
||||
evaluationVo.setExperienceRequired(rolesInf.getJobExperience());
|
||||
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(applyInfo.getCvTemplateJson(), HotakeCvInfoDto.class);
|
||||
evaluationVo.setName(cvInfoDto.getName());
|
||||
evaluationVo.setCurrentPosition(cvInfoDto.getPosition());
|
||||
evaluationVo.setEmail(cvInfoDto.getEmail());
|
||||
evaluationVo.setWorkExperience(JSONUtil.toJsonStr(cvInfoDto.getExperience()));
|
||||
evaluationVo.setSkills(JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()));
|
||||
evaluationVo.setEducation(JSONUtil.toJsonStr(cvInfoDto.getEducation()));
|
||||
evaluationVo.setCertifications("");
|
||||
evaluationVo.setInterviewData("");
|
||||
evaluationVo.setQuestions("");
|
||||
evaluationVo.setAnswers("");
|
||||
evaluationVo.setTechnical("");
|
||||
evaluationVo.setCommunication("");
|
||||
evaluationVo.setSafetyAwareness("");
|
||||
evaluationVo.setProblemSolving("");
|
||||
|
||||
evaluationVo.setTitle(rolesInf.getRoleName());
|
||||
evaluationVo.setDescription(rolesInf.getAboutRole());
|
||||
evaluationVo.setRequiredSkills(rolesInf.getRequiredSkillsJson());
|
||||
evaluationVo.setPreferredSkills(rolesInf.getNiceToHaveSkillsJson());
|
||||
evaluationVo.setExperienceRequired(rolesInf.getJobExperience());
|
||||
HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(applyInfo.getCvTemplateJson(), HotakeCvInfoDto.class);
|
||||
evaluationVo.setName(cvInfoDto.getName());
|
||||
evaluationVo.setCurrentPosition(cvInfoDto.getPosition());
|
||||
evaluationVo.setEmail(cvInfoDto.getEmail());
|
||||
evaluationVo.setWorkExperience(JSONUtil.toJsonStr(cvInfoDto.getExperience()));
|
||||
evaluationVo.setSkills(JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()));
|
||||
evaluationVo.setEducation(JSONUtil.toJsonStr(cvInfoDto.getEducation()));
|
||||
evaluationVo.setCertifications("");
|
||||
evaluationVo.setInterviewData("");
|
||||
evaluationVo.setQuestions("");
|
||||
evaluationVo.setAnswers("");
|
||||
evaluationVo.setTechnical("");
|
||||
evaluationVo.setCommunication("");
|
||||
evaluationVo.setSafetyAwareness("");
|
||||
evaluationVo.setProblemSolving("");
|
||||
|
||||
HotakeCandidateInterviewEvaluationDto evaluationDto = aiCommonToolsService.getCandidateInterviewEvaluation(evaluationVo);
|
||||
applyInfo.setEvaluationJson(JSONUtil.toJsonStr(evaluationDto));
|
||||
applyInfo.setEvaluationScore(new BigDecimal(evaluationDto.getOverallScore()));
|
||||
HotakeCandidateInterviewEvaluationDto evaluationDto = aiCommonToolsService.getCandidateInterviewEvaluation(evaluationVo);
|
||||
applyInfo.setEvaluationJson(JSONUtil.toJsonStr(evaluationDto));
|
||||
applyInfo.setEvaluationScore(new BigDecimal(evaluationDto.getOverallScore()));
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
applyInfo.setRecruiterId(rolesInf.getRecruiterId());
|
||||
applyInfo.setStage(StageEnum.APPLIED.getCode());
|
||||
@@ -333,7 +336,21 @@ public class HotakeInitScreQuestionsReplyRecordInfoServiceImpl extends BaseServi
|
||||
List<Map<String, String>> list = new LinkedList();
|
||||
Map<String, String> entity = new HashMap<>();
|
||||
entity.put("role", "user");
|
||||
entity.put("content", "从下面提供的文本中提取所有能识别到的简历信息,只提取原文中存在的内容,不要补充、不推测、不总结。需要提取的字段包括:name(姓名或人名)、phone(电话号码)、email(电子邮件地址)、experienceYear(根据工作经验计算出来的工作年限)、position(岗位或者简历中自己期望的职位等)、location(地点或者地址、家庭住址)、links(所有链接地址)、currentWork(当前工作公司)、about(关于我/自我介绍)、skills_tools(关键资格(许可证、注册/会员资格、认证))、languages(语言能力,主要就是Languages下面的语言)、experience(工作经历,除了title、company、location、durationStart、durationEnd,其他的都放到description里面,并且description里面要根据换行符分成不同的content),日期要拆分成开始时间(durationStart)和结束时间(durationEnd))、education(教育经历,日期要拆分成开始时间(durationStart)和结束时间(durationEnd))。请将提取结果以结构化 JSON 格式返回,格式如下:{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"currentWork\\\": \\\"\\\", \\\"position\\\": \\\"\\\", \\\"location\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"experienceYear\\\": \\\"\\\", \\\"links\\\": [{\\\"content\\\":\\\"\\\"}], \\\"about\\\": \\\"\\\", \\\"skillsTools\\\": [{\\\"content\\\":\\\"\\\"}], \\\"languages\\\": [{\\\"content\\\":\\\"\\\"}], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\",\\\"description\\\": [{\\\"content\\\":\\\"\\\"}]}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息,不要解释说明,不要改写内容。以下为待处理文本:" + contents);
|
||||
// TODO: 修复工作年限计算错误 - Bug修复说明
|
||||
// 问题:之前的提示词中"experienceYear(根据工作经验计算出来的工作年限)"描述不够明确,
|
||||
// 导致AI可能会将教育时间也计算在内,或者简单地用最早年份到最新年份的差值,
|
||||
// 例如:2006年上大学到2025年工作 = 19年(错误),实际应该是2010年毕业后开始工作约15年
|
||||
//
|
||||
// 修复方案:在提示词中明确工作年限的计算规则:
|
||||
// 1. 只计算experience(工作经历)中的时间段,不包括education(教育经历)
|
||||
// 2. 累加所有工作经历的实际工作时长(年)
|
||||
// 3. 如果工作结束时间是"Present"、"Current"、"至今"等,使用当前年份(2026)计算
|
||||
// 4. 计算公式:总工作年限 = Σ(每段工作的结束年份 - 开始年份)
|
||||
// 5. 结果保留整数,向下取整
|
||||
//
|
||||
// 修改日期:2026-02-04
|
||||
// 修改人:sxc
|
||||
entity.put("content", "从下面提供的文本中提取所有能识别到的简历信息,只提取原文中存在的内容,不要补充、不推测、不总结。需要提取的字段包括:name(姓名或人名)、phone(电话号码)、email(电子邮件地址)、experienceYear(工作年限,重要:只计算experience工作经历中的实际工作时长,不包括education教育时间。计算方法:累加所有工作经历的年数,如果结束时间是Present/Current/至今则用2026年计算,例如:2018-01到2020-06工作2年+2021-03到Present工作5年=总共7年工作经验)、position(岗位或者简历中自己期望的职位等)、location(地点或者地址、家庭住址)、links(所有链接地址)、currentWork(当前工作公司)、about(关于我/自我介绍)、skills_tools(关键资格(许可证、注册/会员资格、认证))、languages(语言能力,主要就是Languages下面的语言)、experience(工作经历,除了title、company、location、durationStart、durationEnd,其他的都放到description里面,并且description里面要根据换行符分成不同的content),日期要拆分成开始时间(durationStart)和结束时间(durationEnd))、education(教育经历,日期要拆分成开始时间(durationStart)和结束时间(durationEnd))。请将提取结果以结构化 JSON 格式返回,格式如下:{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"currentWork\\\": \\\"\\\", \\\"position\\\": \\\"\\\", \\\"location\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"experienceYear\\\": \\\"\\\", \\\"links\\\": [{\\\"content\\\":\\\"\\\"}], \\\"about\\\": \\\"\\\", \\\"skillsTools\\\": [{\\\"content\\\":\\\"\\\"}], \\\"languages\\\": [{\\\"content\\\":\\\"\\\"}], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\",\\\"description\\\": [{\\\"content\\\":\\\"\\\"}]}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息,不要解释说明,不要改写内容。以下为待处理文本:" + contents);
|
||||
//根据AI做
|
||||
list.add(entity);
|
||||
String resultCv = chatGPTClient.handleAiChat(JSONUtil.toJsonStr(list), "JX");
|
||||
|
||||
@@ -73,6 +73,24 @@ public class HotakeReferenceCheckServiceImpl extends BaseServiceImpl implements
|
||||
return hotakeReferenceCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增参考检查
|
||||
*
|
||||
* @param hotakeReferenceCheckList 参考检查列表
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchInsertHotakeReferenceCheck(List<HotakeReferenceCheck> hotakeReferenceCheckList) {
|
||||
if (CollectionUtil.isEmpty(hotakeReferenceCheckList)) {
|
||||
return 0;
|
||||
}
|
||||
for (HotakeReferenceCheck hotakeReferenceCheck : hotakeReferenceCheckList) {
|
||||
fill(FillTypeEnum.INSERT.getCode(), hotakeReferenceCheck);
|
||||
}
|
||||
return hotakeReferenceCheckMapper.batchInsertHotakeReferenceCheck(hotakeReferenceCheckList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改参考检查
|
||||
*
|
||||
|
||||
@@ -16,12 +16,15 @@ import com.vetti.hotake.domain.HotakeSecurityLoginSessions;
|
||||
import com.vetti.hotake.domain.HotakeSecurityPasswordHistory;
|
||||
import com.vetti.hotake.domain.HotakeSecuritySecurityLogs;
|
||||
import com.vetti.hotake.domain.HotakeSecuritySettings;
|
||||
import com.vetti.hotake.domain.HotakeSecurityTrustedDevices;
|
||||
import com.vetti.hotake.domain.dto.SecurityChangePasswordDto;
|
||||
import com.vetti.hotake.domain.vo.SecuritySessionVo;
|
||||
import com.vetti.hotake.domain.vo.SecurityTrustedDeviceVo;
|
||||
import com.vetti.hotake.mapper.HotakeSecurityLoginSessionsMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecurityPasswordHistoryMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecuritySecurityLogsMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecuritySettingsMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecurityTrustedDevicesMapper;
|
||||
import com.vetti.hotake.service.IHotakeSecurityService;
|
||||
import com.vetti.system.service.ISysUserService;
|
||||
import eu.bitwalker.useragentutils.Browser;
|
||||
@@ -60,6 +63,9 @@ public class HotakeSecurityServiceImpl extends BaseServiceImpl implements IHotak
|
||||
@Autowired
|
||||
private HotakeSecuritySecurityLogsMapper securityLogsMapper;
|
||||
|
||||
@Autowired
|
||||
private HotakeSecurityTrustedDevicesMapper trustedDevicesMapper;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@@ -451,4 +457,202 @@ public class HotakeSecurityServiceImpl extends BaseServiceImpl implements IHotak
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的可信设备列表
|
||||
*
|
||||
* @return 可信设备列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@Override
|
||||
public List<SecurityTrustedDeviceVo> getTrustedDevices()
|
||||
{
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
|
||||
// 查询用户的可信设备
|
||||
List<HotakeSecurityTrustedDevices> devicesList = trustedDevicesMapper.selectTrustedDevicesByUserId(userId);
|
||||
|
||||
// 获取当前设备标识(可以从请求头或Cookie中获取)
|
||||
String currentDeviceId = getCurrentDeviceId();
|
||||
|
||||
// 转换为VO
|
||||
List<SecurityTrustedDeviceVo> voList = new ArrayList<>();
|
||||
for (HotakeSecurityTrustedDevices device : devicesList)
|
||||
{
|
||||
SecurityTrustedDeviceVo vo = new SecurityTrustedDeviceVo();
|
||||
vo.setId(device.getId());
|
||||
vo.setDeviceId(device.getDeviceId());
|
||||
vo.setDeviceName(device.getDeviceName());
|
||||
vo.setDeviceType(device.getDeviceType());
|
||||
vo.setBrowser(device.getBrowser());
|
||||
vo.setOs(device.getOs());
|
||||
vo.setIpAddress(device.getIpAddress());
|
||||
vo.setLocation(device.getLocation());
|
||||
vo.setTrustExpiresAt(device.getTrustExpiresAt());
|
||||
vo.setCreateTime(device.getCreateTime());
|
||||
vo.setIsCurrent(device.getDeviceId().equals(currentDeviceId));
|
||||
|
||||
voList.add(vo);
|
||||
}
|
||||
|
||||
return voList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加可信设备
|
||||
*
|
||||
* @param deviceId 设备唯一标识
|
||||
* @param deviceName 设备名称
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int addTrustedDevice(String deviceId, String deviceName)
|
||||
{
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
|
||||
// 检查是否已存在
|
||||
HotakeSecurityTrustedDevices existDevice = trustedDevicesMapper.selectByUserIdAndDeviceId(userId, deviceId);
|
||||
if (existDevice != null)
|
||||
{
|
||||
// 已存在,更新信任状态
|
||||
existDevice.setIsTrusted(1);
|
||||
existDevice.setDeviceName(deviceName);
|
||||
// 设置信任过期时间(30天)
|
||||
existDevice.setTrustExpiresAt(new Date(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000));
|
||||
fill(FillTypeEnum.UPDATE.getCode(), existDevice);
|
||||
|
||||
recordSecurityLog(userId, "TRUSTED_DEVICE_UPDATE",
|
||||
MessageUtils.messageCustomize("HotakeSecurityServiceImpl10012") + ":" + deviceName, "SUCCESS");
|
||||
|
||||
return trustedDevicesMapper.updateHotakeSecurityTrustedDevices(existDevice);
|
||||
}
|
||||
|
||||
// 解析User-Agent
|
||||
String userAgent = ServletUtils.getRequest().getHeader("User-Agent");
|
||||
UserAgent ua = UserAgent.parseUserAgentString(userAgent);
|
||||
Browser browser = ua.getBrowser();
|
||||
OperatingSystem os = ua.getOperatingSystem();
|
||||
|
||||
// 获取IP和位置
|
||||
String ipAddress = IpUtils.getIpAddr();
|
||||
String location = AddressUtils.getRealAddressByIP(ipAddress);
|
||||
|
||||
// 判断设备类型
|
||||
String deviceType = "Desktop";
|
||||
if (os.getDeviceType() != null)
|
||||
{
|
||||
deviceType = os.getDeviceType().getName();
|
||||
}
|
||||
|
||||
// 创建新的可信设备记录
|
||||
HotakeSecurityTrustedDevices device = new HotakeSecurityTrustedDevices();
|
||||
device.setUserId(userId);
|
||||
device.setDeviceId(deviceId);
|
||||
device.setDeviceName(StringUtils.isNotEmpty(deviceName) ? deviceName : browser.getName() + " / " + os.getName());
|
||||
device.setDeviceType(deviceType);
|
||||
device.setBrowser(browser.getName());
|
||||
device.setOs(os.getName());
|
||||
device.setIpAddress(ipAddress);
|
||||
device.setLocation(location);
|
||||
device.setIsTrusted(1);
|
||||
// 设置信任过期时间(30天)
|
||||
device.setTrustExpiresAt(new Date(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000));
|
||||
|
||||
fill(FillTypeEnum.INSERT.getCode(), device);
|
||||
|
||||
// 记录安全日志
|
||||
recordSecurityLog(userId, "TRUSTED_DEVICE_ADD",
|
||||
MessageUtils.messageCustomize("HotakeSecurityServiceImpl10013") + ":" + device.getDeviceName(), "SUCCESS");
|
||||
|
||||
return trustedDevicesMapper.insertHotakeSecurityTrustedDevices(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除可信设备
|
||||
*
|
||||
* @param id 设备记录ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int removeTrustedDevice(Long id)
|
||||
{
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
|
||||
// 查询设备信息
|
||||
HotakeSecurityTrustedDevices device = trustedDevicesMapper.selectHotakeSecurityTrustedDevicesById(id);
|
||||
if (device == null || !device.getUserId().equals(userId))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.messageCustomize("HotakeSecurityServiceImpl10014"));
|
||||
}
|
||||
|
||||
// 删除设备
|
||||
int result = trustedDevicesMapper.removeTrustedDevice(id, userId);
|
||||
|
||||
// 记录安全日志
|
||||
recordSecurityLog(userId, "TRUSTED_DEVICE_REMOVE",
|
||||
MessageUtils.messageCustomize("HotakeSecurityServiceImpl10015") + ":" + device.getDeviceName(), "SUCCESS");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查设备是否为可信设备
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param deviceId 设备唯一标识
|
||||
* @return 是否可信
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@Override
|
||||
public boolean isTrustedDevice(Long userId, String deviceId)
|
||||
{
|
||||
if (StringUtils.isEmpty(deviceId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HotakeSecurityTrustedDevices device = trustedDevicesMapper.selectByUserIdAndDeviceId(userId, deviceId);
|
||||
if (device == null || device.getIsTrusted() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否过期
|
||||
if (device.getTrustExpiresAt() != null && device.getTrustExpiresAt().before(new Date()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前设备标识
|
||||
* 可以从请求头或Cookie中获取,这里简单实现
|
||||
*/
|
||||
private String getCurrentDeviceId()
|
||||
{
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
// 优先从请求头获取
|
||||
String deviceId = request.getHeader("X-Device-Id");
|
||||
if (StringUtils.isEmpty(deviceId))
|
||||
{
|
||||
// 从Cookie获取
|
||||
javax.servlet.http.Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null)
|
||||
{
|
||||
for (javax.servlet.http.Cookie cookie : cookies)
|
||||
{
|
||||
if ("device_id".equals(cookie.getName()))
|
||||
{
|
||||
deviceId = cookie.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return deviceId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<insert id="batchInsertHotakeReferenceCheck" parameterType="java.util.List">
|
||||
insert into hotake_reference_check
|
||||
(company, full_name, position, relationship, email, save_job_experience, del_flag, create_by, create_time, update_by, update_time, remark)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{item.company},
|
||||
#{item.fullName},
|
||||
#{item.position},
|
||||
#{item.relationship},
|
||||
#{item.email},
|
||||
#{item.saveJobExperience},
|
||||
#{item.delFlag},
|
||||
#{item.createBy},
|
||||
#{item.createTime},
|
||||
#{item.updateBy},
|
||||
#{item.updateTime},
|
||||
#{item.remark}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<update id="updateHotakeReferenceCheck" parameterType="HotakeReferenceCheck">
|
||||
update hotake_reference_check
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.vetti.hotake.mapper.HotakeSecurityTrustedDevicesMapper">
|
||||
|
||||
<resultMap type="HotakeSecurityTrustedDevices" id="HotakeSecurityTrustedDevicesResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="userId" column="user_id" />
|
||||
<result property="deviceId" column="device_id" />
|
||||
<result property="deviceName" column="device_name" />
|
||||
<result property="deviceType" column="device_type" />
|
||||
<result property="browser" column="browser" />
|
||||
<result property="os" column="os" />
|
||||
<result property="ipAddress" column="ip_address" />
|
||||
<result property="location" column="location" />
|
||||
<result property="isTrusted" column="is_trusted" />
|
||||
<result property="trustExpiresAt" column="trust_expires_at"/>
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="remark" column="remark" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectHotakeSecurityTrustedDevicesVo">
|
||||
select id, user_id, device_id, device_name, device_type, browser, os, ip_address, location, is_trusted, trust_expires_at, create_by, create_time, update_by, update_time, remark from hotake_security_trusted_devices
|
||||
</sql>
|
||||
|
||||
<select id="selectHotakeSecurityTrustedDevicesList" parameterType="HotakeSecurityTrustedDevices" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
<where>
|
||||
<if test="userId != null "> and user_id = #{userId}</if>
|
||||
<if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
|
||||
<if test="deviceName != null and deviceName != ''"> and device_name like concat('%', #{deviceName}, '%')</if>
|
||||
<if test="deviceType != null and deviceType != ''"> and device_type = #{deviceType}</if>
|
||||
<if test="browser != null and browser != ''"> and browser = #{browser}</if>
|
||||
<if test="os != null and os != ''"> and os = #{os}</if>
|
||||
<if test="isTrusted != null "> and is_trusted = #{isTrusted}</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectHotakeSecurityTrustedDevicesById" parameterType="Long" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectByUserIdAndDeviceId" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
where user_id = #{userId} and device_id = #{deviceId}
|
||||
</select>
|
||||
|
||||
<select id="selectTrustedDevicesByUserId" parameterType="Long" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
where user_id = #{userId} and is_trusted = 1 and (trust_expires_at is null or trust_expires_at > now())
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<insert id="insertHotakeSecurityTrustedDevices" parameterType="HotakeSecurityTrustedDevices" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into hotake_security_trusted_devices
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">user_id,</if>
|
||||
<if test="deviceId != null and deviceId != ''">device_id,</if>
|
||||
<if test="deviceName != null">device_name,</if>
|
||||
<if test="deviceType != null">device_type,</if>
|
||||
<if test="browser != null">browser,</if>
|
||||
<if test="os != null">os,</if>
|
||||
<if test="ipAddress != null">ip_address,</if>
|
||||
<if test="location != null">location,</if>
|
||||
<if test="isTrusted != null">is_trusted,</if>
|
||||
<if test="trustExpiresAt != null">trust_expires_at,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">#{userId},</if>
|
||||
<if test="deviceId != null and deviceId != ''">#{deviceId},</if>
|
||||
<if test="deviceName != null">#{deviceName},</if>
|
||||
<if test="deviceType != null">#{deviceType},</if>
|
||||
<if test="browser != null">#{browser},</if>
|
||||
<if test="os != null">#{os},</if>
|
||||
<if test="ipAddress != null">#{ipAddress},</if>
|
||||
<if test="location != null">#{location},</if>
|
||||
<if test="isTrusted != null">#{isTrusted},</if>
|
||||
<if test="trustExpiresAt != null">#{trustExpiresAt},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateHotakeSecurityTrustedDevices" parameterType="HotakeSecurityTrustedDevices">
|
||||
update hotake_security_trusted_devices
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="userId != null">user_id = #{userId},</if>
|
||||
<if test="deviceId != null and deviceId != ''">device_id = #{deviceId},</if>
|
||||
<if test="deviceName != null">device_name = #{deviceName},</if>
|
||||
<if test="deviceType != null">device_type = #{deviceType},</if>
|
||||
<if test="browser != null">browser = #{browser},</if>
|
||||
<if test="os != null">os = #{os},</if>
|
||||
<if test="ipAddress != null">ip_address = #{ipAddress},</if>
|
||||
<if test="location != null">location = #{location},</if>
|
||||
<if test="isTrusted != null">is_trusted = #{isTrusted},</if>
|
||||
<if test="trustExpiresAt != null">trust_expires_at = #{trustExpiresAt},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteHotakeSecurityTrustedDevicesById" parameterType="Long">
|
||||
delete from hotake_security_trusted_devices where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteHotakeSecurityTrustedDevicesByIds" parameterType="String">
|
||||
delete from hotake_security_trusted_devices where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="removeTrustedDevice">
|
||||
delete from hotake_security_trusted_devices where id = #{id} and user_id = #{userId}
|
||||
</delete>
|
||||
|
||||
<delete id="cleanExpiredTrustedDevices">
|
||||
delete from hotake_security_trusted_devices where trust_expires_at is not null and trust_expires_at < now()
|
||||
</delete>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user