重新修改了用户权限关联模块功能

This commit is contained in:
root 2025-06-20 09:02:20 +08:00
parent 90ca2cef2a
commit c6e7657e62
29 changed files with 1024 additions and 340 deletions

View File

@ -142,6 +142,13 @@
<artifactId>hutool-all</artifactId>
<version>5.8.8</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies>
<build>

View File

@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.stdproject.entity.AppOptLog;
import com.stdproject.service.IAppOptLogService;
import com.stdproject.utils.JwtUtils;
import com.stdproject.utils.commonUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
@ -92,8 +93,8 @@ public class OperationLogAspect {
optLog.setModule(operationLog.module());
optLog.setDescription(operationLog.description());
optLog.setMethod(request.getMethod() + " " + request.getRequestURI());
optLog.setRequestip(getIpAddress(request));
optLog.setBrowser(getBrowser(request));
optLog.setRequestip(commonUtils.getIpAddress(request));
optLog.setBrowser(commonUtils.getBrowser(request));
optLog.setLogtime(LocalDateTime.now());
// 设置操作用户
@ -150,32 +151,5 @@ public class OperationLogAspect {
}
}
public static String getBrowser(HttpServletRequest request) {
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
Browser browser = userAgent.getBrowser();
return browser.getName();
}
/**
* 获取客户端IP地址
*/
private String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}

View File

@ -1,197 +0,0 @@
package com.stdproject.config;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stdproject.entity.User;
import com.stdproject.service.IMenuService;
import com.stdproject.service.IRoleService;
import com.stdproject.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.Collectors;
/**
* 自定义用户详情服务
* 实现Spring Security的UserDetailsService接口
*
* @author StdProject
*/
@Slf4j
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private IUserService appUserService;
@Autowired
private IRoleService appRoleService;
@Autowired
private IMenuService appMenuService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.debug("加载用户信息: {}", username);
User appUser = appUserService.findByUsername(username);
if (appUser == null) {
log.warn("用户不存在: {}", username);
throw new UsernameNotFoundException("用户不存在: " + username);
}
// 检查用户状态
if (!"1".equals(appUser.getStatus())) {
log.warn("用户已被禁用: {}", username);
throw new UsernameNotFoundException("用户已被禁用: " + username);
}
// 构建用户权限
Collection<GrantedAuthority> authorities = buildUserAuthorities(appUser);
return org.springframework.security.core.userdetails.User.builder()
.username(appUser.getUsername())
.password(appUser.getPassword())
.authorities(authorities)
.accountExpired(false)
.accountLocked(isAccountLocked(appUser))
.credentialsExpired(isCredentialsExpired(appUser))
.disabled(!"1".equals(appUser.getStatus()))
.build();
}
/**
* 构建用户权限
*
* @param appUser 用户信息
* @return 权限集合
*/
private Collection<GrantedAuthority> buildUserAuthorities(User appUser) {
Set<GrantedAuthority> authorities = new HashSet<>();
try {
// 根据用户类型添加基本角色权限
if ("0".equals(appUser.getUsertype())) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
}
// 查询用户的角色
// QueryWrapper<RoleUser> roleUserQuery = new QueryWrapper<>();
// roleUserQuery.eq("userid", appUser.getId());
// List<RoleUser> roleUsers = appRoleUserService.list(roleUserQuery);
//
// if (!roleUsers.isEmpty()) {
// // 获取角色ID列表
// List<String> roleIds = roleUsers.stream()
// .map(AppRoleUser::getRoleid)
// .collect(Collectors.toList());
//
// // 查询角色信息并添加角色权限
// List<AppRole> roles = appRoleService.listByIds(roleIds);
// for (AppRole role : roles) {
// if ("1".equals(role.getIsvaild())) {
// // 添加角色权限格式ROLE_角色编码
// if (StringUtils.hasText(role.getRolecode())) {
// authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRolecode().toUpperCase()));
// }
// }
// }
//
// // 查询角色关联的菜单权限
// QueryWrapper<AppRoleMenu> roleMenuQuery = new QueryWrapper<>();
// roleMenuQuery.in("roleid", roleIds);
// List<AppRoleMenu> roleMenus = appRoleMenuService.list(roleMenuQuery);
//
// if (!roleMenus.isEmpty()) {
// // 获取菜单ID列表
// List<String> menuIds = roleMenus.stream()
// .map(AppRoleMenu::getMenuid)
// .distinct()
// .collect(Collectors.toList());
//
// // 查询菜单信息并添加菜单权限
// List<AppMenu> menus = appMenuService.listByIds(menuIds);
// for (AppMenu menu : menus) {
// if ("1".equals(menu.getIsdisplay()) && StringUtils.hasText(menu.getCode())) {
// // 添加菜单权限格式菜单编码
// authorities.add(new SimpleGrantedAuthority(menu.getCode()));
//
// // 根据菜单类型添加操作权限
// String menuCode = menu.getCode();
// if (StringUtils.hasText(menuCode)) {
// // 为每个菜单添加基本操作权限
// authorities.add(new SimpleGrantedAuthority(menuCode + ":list"));
// authorities.add(new SimpleGrantedAuthority(menuCode + ":detail"));
//
// // 管理员拥有所有操作权限
// if ("0".equals(appUser.getUsertype())) {
// authorities.add(new SimpleGrantedAuthority(menuCode + ":add"));
// authorities.add(new SimpleGrantedAuthority(menuCode + ":edit"));
// authorities.add(new SimpleGrantedAuthority(menuCode + ":delete"));
// authorities.add(new SimpleGrantedAuthority(menuCode + ":permission"));
// }
// }
// }
// }
// }
// }
log.debug("用户 {} 的权限列表: {}", appUser.getUsername(),
authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
} catch (Exception e) {
log.error("构建用户权限失败: {}", e.getMessage(), e);
// 发生异常时至少保证基本角色权限
authorities.clear();
if ("0".equals(appUser.getUsertype())) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
}
}
return authorities;
}
/**
* 检查账户是否被锁定
*
* @param appUser 用户信息
* @return 是否被锁定
*/
private boolean isAccountLocked(User appUser) {
// 检查登录失败锁定时间
if (appUser.getFailedlocktime() != null) {
// 如果锁定时间还未过期则账户被锁定
return appUser.getFailedlocktime().isAfter(java.time.LocalDateTime.now());
}
return false;
}
/**
* 检查凭证是否过期
*
* @param appUser 用户信息
* @return 是否过期
*/
private boolean isCredentialsExpired(User appUser) {
// 检查密码是否过期
if (appUser.getPwdresettime() != null && appUser.getPwdvalidperiod() != null) {
java.time.LocalDateTime expireTime = appUser.getPwdresettime().plusDays(appUser.getPwdvalidperiod());
return expireTime.isBefore(java.time.LocalDateTime.now());
}
return false;
}
}

View File

@ -1,5 +1,6 @@
package com.stdproject.config;
import com.stdproject.service.CustomUserDetailsService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -11,11 +12,9 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

View File

@ -28,6 +28,10 @@ public class WebConfig implements WebMvcConfigurer {
return CacheUtil.newTimedCache(jwtExpirationMs);
}
@Bean
public Cache<String, String> loginuserCache() {
return CacheUtil.newLRUCache(200);//用户登录缓存数 缺省200
}
/**
* 静态资源处理
*/

View File

@ -60,7 +60,7 @@ public class MenuController {
return ResponseResult.error("没有菜单ID");
}
//填写 当前用户名称
menu.setLastmodifier(AuthUtils.getUser().getUserId().toString());
// menu.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//填写 当前日期
menu.setLastmodifydate(LocalDateTime.now());
boolean isOk = menuService.updateById(menu);
@ -82,8 +82,9 @@ public class MenuController {
***********************************/
@PostMapping("/getMenuTree")
@ResponseBody
public List<Map<String, Object>> getMenuTree(String appId, String name, String isdisplay) {
return menuService.getMenuTree(appId, name, isdisplay);
public ResponseResult getMenuTree(String appId, String name, String isdisplay) {
List<Map<String, Object>> list= menuService.getMenuTree(appId, name, isdisplay);
return ResponseResult.successData(list);
}
@ -133,7 +134,7 @@ public class MenuController {
//根据id 修改是否显示 最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("isdisplay", isdisplay)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
boolean ok = menuService.update(updateWrapper);
if (ok) {
@ -157,7 +158,7 @@ public class MenuController {
//根据id 修改关联模块ID 最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("module_id", moduleId)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
boolean ok = menuService.update(updateWrapper);
if (ok) {
@ -176,8 +177,8 @@ public class MenuController {
***********************************/
@PostMapping("/permissionAssignment")
@ResponseBody
public List<Map<String, Object>> permissionAssignment(String appId, String roleId) {
return menuService.permissionAssignment(appId,roleId);
public ResponseResult permissionAssignment(String appId, String roleId) {
List<Map<String, Object>> list=menuService.permissionAssignment(appId,roleId);
return ResponseResult.successData( list);
}
}

View File

@ -0,0 +1,60 @@
package com.stdproject.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stdproject.config.ResponseResult;
import com.stdproject.entity.Module;
import com.stdproject.service.IModuleService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* <p>
* 应用_系统模块 前端控制器
* </p>
*
* @author zhengsl
* @since 2025-03-25
*/
@RestController
@RequestMapping("/module")
public class ModuleController {
// 添加Service注入
@Resource
private IModuleService moduleService;
// 分页查询模块列表
@GetMapping("/list")
public ResponseResult page(@RequestParam String appId) {
QueryWrapper<Module> wrapper = new QueryWrapper<>();
wrapper.eq("app_id",appId);
wrapper.orderByAsc("pid","sort"); // 按编码倒序排列
List<Map<String, Object>> list = moduleService.listMaps(wrapper);
return ResponseResult.successData(list);
}
// 删除模块
@DeleteMapping("/{id}")
public ResponseResult remove(@PathVariable String id) {
return ResponseResult.successData(moduleService.removeById(id));
}
// 获取模块详情
@GetMapping("/{id}")
public ResponseResult getById(@PathVariable String id) {
Map<String, Object> moduleMap=null;
try {
LambdaQueryWrapper<Module> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Module::getId, id);
moduleMap = moduleService.getMap(wrapper);
} catch (Exception e) {
e.printStackTrace();
}
return ResponseResult.successData(moduleMap);
}
}

View File

@ -69,7 +69,7 @@ public class OrganizationController {
return ResponseResult.error("组织信息不能为空");
}
//填写 最近修改者
organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
// organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//填写 最近修改时间
organization.setLastmodifydate(LocalDateTime.now());
//根据id 修改系统组织
@ -93,8 +93,9 @@ public class OrganizationController {
***********************************/
@PostMapping("/getOrganizations")
@ResponseBody
public List<Map<String, Object>> getOrganizations(String appId, String orgtype, String parentid, String orgName) {
return organizationService.getOrganizations(appId,orgtype, parentid, orgName);
public ResponseResult getOrganizations(String appId, String orgtype, String parentid, String orgName) {
List<Map<String, Object>> list=organizationService.getOrganizations(appId,orgtype, parentid, orgName);
return ResponseResult.successData(list);
}
/***********************************
@ -156,7 +157,7 @@ public class OrganizationController {
UpdateWrapper<Organization> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", id)
.set("isvaild", isvaild)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate", LocalDateTime.now());
boolean isOk = organizationService.update(updateWrapper);
if (isOk) {

View File

@ -63,7 +63,7 @@ public class RoleController {
return ResponseResult.error("需要提交角色ID");
}
//更新最近修改人
role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
// role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//更新最近修改时间
role.setLastmodifydate(LocalDateTime.now());
//根据id更新角色信息
@ -84,8 +84,9 @@ public class RoleController {
***********************************/
@PostMapping("/listRole")
@ResponseBody
public List<Role> listRole(String appId, String rolename) {
return roleService.listRole(appId,rolename);
public ResponseResult listRole(String appId, String rolename) {
List<Role> list=roleService.listRole(appId,rolename);
return ResponseResult.successData( list);
}
/***********************************
@ -152,7 +153,7 @@ public class RoleController {
//根据id 更新业务范围最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("isvaild", isvaild)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate",LocalDateTime.now());
boolean ok = roleService.update(updateWrapper);
if (ok) {

View File

@ -1,16 +1,42 @@
package com.stdproject.controller;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.config.ResponseResult;
import com.stdproject.config.WebConfig;
import com.stdproject.entity.AppOptLog;
import com.stdproject.entity.LoginUser;
import com.stdproject.entity.User;
import com.stdproject.service.IAppOptLogService;
import com.stdproject.service.IUserService;
import com.stdproject.utils.JwtUtils;
import com.stdproject.utils.RsaUtils;
import com.stdproject.utils.commonUtils;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@ -28,6 +54,18 @@ public class UserController {
@Resource
private IUserService userService;
@Value("${spring.security.rsa.private-key}")
private String privateKey;
@Value("${spring.security.jwt.expiration-ms}")
private Long jwtExpirationMs;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private WebConfig webConfig;
@Resource
private IAppOptLogService sysLogService;
@Autowired
private JwtUtils jwtUtils;
/***********************************
* 用途说明新增系统用户
@ -70,7 +108,7 @@ public class UserController {
***********************************/
@GetMapping("/queryUsers")
@ResponseBody
public ResponseResult queryUsers(String orgid,String appId, String nickname, Page<User> page) {
public ResponseResult queryUsers(String orgid, String appId, String nickname, Page<User> page) {
Page<Map<String, Object>> mapPage = userService.queryUsers(orgid, appId, nickname, page);
return ResponseResult.successData(mapPage);
}
@ -115,7 +153,6 @@ public class UserController {
}
/***********************************
* 用途说明设置账号状态(管理员)
* 参数说明
@ -125,7 +162,7 @@ public class UserController {
************************************/
@PostMapping("/setStatus")
@ResponseBody
public ResponseResult setStatus(@RequestParam String id,@RequestParam String status) {
public ResponseResult setStatus(@RequestParam String id, @RequestParam String status) {
if (StringUtils.isEmpty(id)) {
return ResponseResult.error("用户ID为空");
}
@ -159,22 +196,91 @@ public class UserController {
return ResponseResult.error();
}
}
@PostMapping("/login")
@ResponseBody
public ResponseResult login(String appid,String username, String password) {
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
return ResponseResult.error("用户名称或者密码不能为空!");
public ResponseResult login(String username, String password) throws Exception {
try {
// 密码解密
String encrypt_password = RsaUtils.decryptByPrivateKey(privateKey, password);
//如果认证通过了使用userId生成token token存入ResponseResult返回
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(username,
encrypt_password);
Authentication authenticate =
authenticationManager.authenticate(authenticationToken);
LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
// 获取请求信息
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
AppOptLog sysLog = new AppOptLog();
sysLog.setUsercode(username);
sysLog.setUsername(loginUser.getUser().getNickname());
sysLog.setRequestip(commonUtils.getIpAddress(request));
sysLog.setBrowser(commonUtils.getBrowser(request));
sysLog.setOpttype("登录(login)");
sysLog.setModule("用户登录");
String className = this.getClass().getName();
String method =
Thread.currentThread().getStackTrace()[1].getMethodName();
sysLog.setMethod(className + "." + method + "()");
//sysLog.setParams(user.toString());
sysLog.setDescription(loginUser.getUser().getNickname() + "登录系统!");
sysLog.setLogtime(LocalDateTime.now());
sysLogService.save(sysLog);
String userId = loginUser.getUser().getId();
long expireTime = System.currentTimeMillis() + jwtExpirationMs;
Map<String, Object> map = new HashMap();
map.put("userid", userId);
map.put("username", loginUser.getUsername());
map.put("expire_time", expireTime);
String token = jwtUtils.generateToken(loginUser.getUsername(), userId);
map.put("token", token);
//把完整的用户信息存入到HuTool缓存中userId作为key
String jsonStr = JSONUtil.toJsonStr(loginUser);
webConfig.loginuserCache().put("login:" + userId, jsonStr);
return ResponseResult.successData(map);
}
// 根据用户名查询用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
User user = userService.getOne(queryWrapper.eq("app_id",appid).eq("username", username));
if (ObjUtil.isEmpty( user)) {
return ResponseResult.error(String.format("%s您输入的用户账号不存在", username));
}
if(password.equals(user.getPassword())){
return ResponseResult.successData(user);
}else{
return ResponseResult.error("您输入的密码错误!");
catch (BadCredentialsException e) {
// 账号密码验证错误
return ResponseResult.error("账号或密码错误,请检查!");
} catch (DisabledException e) {
// 账号已停用
return ResponseResult.error("账号已停用,不能登录!");
} catch (LockedException e) {
// 账号被锁定
return ResponseResult.error("账号被锁定,不能登录!");
} catch (AccountExpiredException e) {
// 账号已过期
return ResponseResult.error("账号密码已过有效期,不能登录!");
} catch (AuthenticationException e) {
// 捕获其他认证异常
return ResponseResult.error("认证失败:" + e.getMessage());
}
}
@PostMapping("/logout")
@ResponseBody
public ResponseResult logout() {
//获取SecurityContextHolder中的用户id
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
String userId = loginuser.getUser().getId();
//删除redis中的登陆用户信息
webConfig.loginuserCache().remove("login:" + userId);
//记录退出日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
AppOptLog sysLog = new AppOptLog();
sysLog.setUsercode(loginuser.getUsername());
sysLog.setUsername(loginuser.getUser().getNickname());
sysLog.setRequestip(commonUtils.getIpAddress(request));
sysLog.setBrowser(commonUtils.getBrowser(request));
sysLog.setOpttype("其他(other)");
sysLog.setModule("注销退出");
sysLog.setDescription("注销退出系统!");
sysLog.setLogtime(LocalDateTime.now());
sysLogService.save(sysLog);
return ResponseResult.success();
}
}

View File

@ -0,0 +1,109 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 应用系统
* </p>
*
* @author zhengsl
* @since 2025-03-24
*/
@Getter
@Setter
@TableName("app_application")
public class Application implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private String id;
/**
* 应用类型 01-数据展示分析
*/
private String type;
/**
* 应用编号 自动生成000001
*/
private String code;
/**
* 应用名称
*/
private String name;
/**
* 应用简称
*/
private String simplename;
/**
* 创建日期
*/
private LocalDateTime createdate;
/**
* 应用描述
*/
private String description;
/**
* 应用图片 base64存储
*/
private String image;
/**
* 应用配置 JSON格式存储其他配置相关信息
*/
private String appconfig;
/**
* 数据库配置 JSON格式存储数据库信息配置数据库用于存储此应用系统的所有配置数据
*/
private String dbconfig;
/**
* 用户单位 使用这个应用系统的组织单位
*/
private String organization;
/**
* 状态 01-初始创建 02-正常运行 09-已停用
*/
private String status;
/**
* 最近修改者
*/
private String lastmodifier;
/**
* 最近修改日期
*/
private LocalDateTime lastmodifydate;
/**
* 备用1
*/
private String custom1;
/**
* 备用2
*/
private String custom2;
/**
* 备用3
*/
private String custom3;
}

View File

@ -0,0 +1,178 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import org.apache.ibatis.type.JdbcType;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 应用_系统模块
* </p>
*
* @author zhengsl
* @since 2025-03-25
*/
@Getter
@Setter
@TableName("app_module")
public class Module implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 名称
*/
private String name;
/**
* 父级ID 父级模块
*/
@TableField(value = "pid", jdbcType = JdbcType.VARCHAR)
private String pid;
/**
* 层级
*/
private Integer level;
/**
* 节点类型 01-目录 02-模块
*/
private String nodeType;
/**
* 类型 01-数据大屏 02-数据看板 03-弹窗页面 04-填报页面 06-移动端界面 09-自定义页面
*/
private String type;
/**
* 样式数据
*/
@TableField(value = "canvas_style_data", jdbcType = JdbcType.VARCHAR)
private String canvasStyleData;
/**
* 组件数据
*/
@TableField(value = "component_data", jdbcType = JdbcType.VARCHAR)
private String componentData;
/**
* 状态 0-未发布 1-已发布
*/
private Integer status;
/**
* 是否单独打开水印 0-关闭 1-开启
*/
private Integer selfWatermarkStatus;
/**
* 排序 目录内的排序号
*/
private Integer sort;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 创建人
*/
private String createBy;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 更新人
*/
private String updateBy;
/**
* 备注
*/
private String remark;
/**
* 数据来源
*/
private String source;
/**
* 删除标志
*/
private Byte deleteFlag;
/**
* 删除时间
*/
private LocalDateTime deleteTime;
/**
* 删除人
*/
private String deleteBy;
/**
* 可视化资源版本
*/
private Integer version;
/**
* 内容标识
*/
private String contentId;
/**
* 内容检查标识
*/
private String checkVersion;
/**
* 备用1
*/
private String custom1;
/**
* 备用2
*/
private String custom2;
/**
* 备用3
*/
private String custom3;
public Module(String appId, String name, String pid, Integer level, String nodeType, String type, Integer status, Integer sort, LocalDateTime createTime, String createBy){
this.appId = appId;
this.name = name;
this.pid = pid;
this.level = level;
this.nodeType = nodeType;
this.type = type;
this.status = status;
this.sort = sort;
this.createTime = createTime;
this.createBy = createBy;
};
}

View File

@ -0,0 +1,21 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.Application;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
/**
* <p>
* 应用系统 Mapper 接口
* </p>
*
* @author zhengsl
* @since 2025-03-24
*/
@Mapper
public interface ApplicationMapper extends BaseMapper<Application> {
@Select("SELECT MAX(CAST(code AS UNSIGNED)) FROM app_application")
Integer getMaxCode();
}

View File

@ -0,0 +1,17 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import com.stdproject.entity.Module;
/**
* <p>
* 应用_系统模块 Mapper 接口
* </p>
*
* @author zhengsl
* @since 2025-03-25
*/
@Mapper
public interface ModuleMapper extends BaseMapper<Module> {
}

View File

@ -0,0 +1,147 @@
package com.stdproject.service;
import com.stdproject.entity.LoginUser;
import com.stdproject.entity.Menu;
import com.stdproject.entity.Role;
import com.stdproject.entity.User;
import com.stdproject.mapper.MenuMapper;
import com.stdproject.mapper.RoleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 自定义用户详情服务
* 实现Spring Security的UserDetailsService接口
*
* @author StdProject
*/
@Slf4j
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private IUserService appUserService;
@Autowired
private IMenuService appMenuService;
@Autowired
private RoleMapper roleMapper;
@Autowired
private MenuMapper menuMapper;
@Override
public UserDetails loadUserByUsername(String username) {
User appUser = appUserService.findByUsername(username);
if (appUser == null) {
throw new UsernameNotFoundException("用户不存在: " + username);
}
Collection<GrantedAuthority> authorities = buildUserAuthorities(appUser);
LoginUser loginUser = new LoginUser(appUser,authorities);
return loginUser;
}
/**
* 构建用户权限
*
* @param appUser 用户信息
* @return 权限集合
*/
private Collection<GrantedAuthority> buildUserAuthorities(User appUser) {
Set<GrantedAuthority> authorities = new HashSet<>();
try {
// 根据用户类型添加基本角色权限
if ("0".equals(appUser.getUsertype())) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
}
// 使用RoleMapper直接查询用户的角色信息
List<Role> roles = roleMapper.getRoleByUserId(appUser.getId());
if (!roles.isEmpty()) {
// 处理角色权限
for (Role role : roles) {
if ("1".equals(role.getIsvaild())) {
// 添加角色权限格式ROLE_角色编码
if (StringUtils.hasText(role.getRolecode())) {
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRolecode().toUpperCase()));
}
}
}
// 获取角色ID列表
List<String> roleIds = roles.stream()
.map(Role::getId)
.collect(Collectors.toList());
// 处理每个角色的菜单权限
for (String roleId : roleIds) {
// 使用MenuMapper直接查询角色关联的菜单ID
List<String> menuIds = menuMapper.selectMenuByRoleId(appUser.getAppId(), roleId);
if (!menuIds.isEmpty()) {
// 查询菜单信息并添加菜单权限
List<Menu> menus = appMenuService.listByIds(menuIds);
for (Menu menu : menus) {
if ("1".equals(menu.getIsdisplay()) && StringUtils.hasText(menu.getCode())) {
// 添加菜单权限格式菜单编码
authorities.add(new SimpleGrantedAuthority(menu.getCode()));
// 根据菜单类型添加操作权限
String menuCode = menu.getCode();
if (StringUtils.hasText(menuCode)) {
// 为每个菜单添加基本操作权限
authorities.add(new SimpleGrantedAuthority(menuCode + ":list"));
authorities.add(new SimpleGrantedAuthority(menuCode + ":detail"));
// 管理员拥有所有操作权限
if ("0".equals(appUser.getUsertype())) {
authorities.add(new SimpleGrantedAuthority(menuCode + ":add"));
authorities.add(new SimpleGrantedAuthority(menuCode + ":edit"));
authorities.add(new SimpleGrantedAuthority(menuCode + ":delete"));
authorities.add(new SimpleGrantedAuthority(menuCode + ":permission"));
}
}
}
}
}
}
}
log.debug("用户 {} 的权限列表: {}", appUser.getUsername(),
authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
} catch (Exception e) {
log.error("构建用户权限失败: {}", e.getMessage(), e);
// 发生异常时至少保证基本角色权限
authorities.clear();
if ("0".equals(appUser.getUsertype())) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
}
}
return authorities;
}
}

View File

@ -0,0 +1,16 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.Application;
/**
* <p>
* 应用系统 服务类
* </p>
*
* @author zhengsl
* @since 2025-03-24
*/
public interface IApplicationService extends IService<Application> {
}

View File

@ -0,0 +1,15 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.Module;
/**
* <p>
* 应用_系统模块 服务类
* </p>
*
* @author zhengsl
* @since 2025-03-25
*/
public interface IModuleService extends IService<Module> {
}

View File

@ -0,0 +1,20 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.Application;
import com.stdproject.mapper.ApplicationMapper;
import com.stdproject.service.IApplicationService;
import org.springframework.stereotype.Service;
/**
* <p>
* 应用系统 服务实现类
* </p>
*
* @author zhengsl
* @since 2025-03-24
*/
@Service
public class ApplicationServiceImpl extends ServiceImpl<ApplicationMapper, Application> implements IApplicationService {
}

View File

@ -0,0 +1,21 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.Module;
import com.stdproject.mapper.ModuleMapper;
import com.stdproject.service.IModuleService;
import org.springframework.stereotype.Service;
/**
* <p>
* 应用_系统模块 服务实现类
* </p>
*
* @author zhengsl
* @since 2025-03-25
*/
@Service
public class ModuleServiceImpl extends ServiceImpl<ModuleMapper, Module> implements IModuleService {
}

View File

@ -166,7 +166,7 @@ public class OrganizationServiceImpl extends ServiceImpl<OrganizationMapper, Org
//填写 编号
organization.setOrgcode(code);
//填写 当前用户名称
organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
// organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//填写 当前日期
organization.setLastmodifydate(LocalDateTime.now());

View File

@ -77,7 +77,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
role.setIsvaild("1");
}
//添加最近修改者
role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
// role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//添加最近修改时间
role.setLastmodifydate(LocalDateTime.now());
return this.save(role);

View File

@ -12,6 +12,7 @@ import com.stdproject.entity.User; // 确保 User 类存在并路径正确
import com.stdproject.mapper.RoleMapper;
import com.stdproject.mapper.UserMapper;
import com.stdproject.service.IUserService; // 确保接口存在
import com.stdproject.utils.EncryptUtils;
import io.gisbi.utils.AuthUtils;
import io.gisbi.utils.RsaUtils;
import io.micrometer.common.util.StringUtils;
@ -64,12 +65,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
Map<String, String> result = new HashMap<>();
//普通用户
//设置缺省密码
String cryptPassword = RsaUtils.encryptStr(PASSWORD_VALID);
String cryptPassword = EncryptUtils.md5(PASSWORD_VALID);;
user.setPassword(cryptPassword);
//最近修改日期
user.setLastmodifydate(LocalDateTime.now());
//最近修改者
user.setLastmodifier(AuthUtils.getUser().getUserId().toString());
// user.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//账号有效 状态 1-有效 0-停用
user.setStatus(DEFAULT_IS_VALID);
//判断注册的登录账号是否存在
@ -274,8 +275,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
String cryptPassword = PASSWORD_VALID;
updateWrapper.eq("id", id).set("password", cryptPassword)
.set("pwdresettime", LocalDateTime.now())
.set("lastmodifydate", LocalDateTime.now())
.set("lastmodifier", AuthUtils.getUser().getUserId().toString());
.set("lastmodifydate", LocalDateTime.now());
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString());
//是否修改成功
isOk = this.update(updateWrapper);
return isOk;
@ -295,8 +296,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
//根据id修改用户状态最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("status", status)
.set("lastmodifydate", LocalDateTime.now())
.set("lastmodifier", AuthUtils.getUser().getUserId().toString());
.set("lastmodifydate", LocalDateTime.now());
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString());
//是否修改成功
isOk = this.update(updateWrapper);
return isOk;

View File

@ -0,0 +1,183 @@
package com.stdproject.utils;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* @author https://www.cnblogs.com/nihaorz/p/10690643.html
* @description Rsa 工具类公钥私钥生成加解密
* @date 2020-05-18
**/
public class RsaUtils {
private static final String SRC = "123456";
public static void main(String[] args) throws Exception {
System.out.println("\n");
RsaKeyPair keyPair = generateKeyPair();
System.out.println("公钥:" + keyPair.getPublicKey());
System.out.println("私钥:" + keyPair.getPrivateKey());
System.out.println("\n");
test1(keyPair);
System.out.println("\n");
test2(keyPair);
System.out.println("\n");
}
/**
* 公钥加密私钥解密
*/
private static void test1(RsaKeyPair keyPair) throws Exception {
System.out.println("***************** 公钥加密私钥解密开始 *****************");
String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC);
String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);
System.out.println("加密前:" + RsaUtils.SRC);
System.out.println("加密后:" + text1);
System.out.println("解密后:" + text2);
if (RsaUtils.SRC.equals(text2)) {
System.out.println("解密字符串和原始字符串一致,解密成功");
} else {
System.out.println("解密字符串和原始字符串不一致,解密失败");
}
System.out.println("***************** 公钥加密私钥解密结束 *****************");
}
/**
* 私钥加密公钥解密
* @throws Exception /
*/
private static void test2(RsaKeyPair keyPair) throws Exception {
System.out.println("***************** 私钥加密公钥解密开始 *****************");
String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC);
String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);
System.out.println("加密前:" + RsaUtils.SRC);
System.out.println("加密后:" + text1);
System.out.println("解密后:" + text2);
if (RsaUtils.SRC.equals(text2)) {
System.out.println("解密字符串和原始字符串一致,解密成功");
} else {
System.out.println("解密字符串和原始字符串不一致,解密失败");
}
System.out.println("***************** 私钥加密公钥解密结束 *****************");
}
/**
* 公钥解密
*
* @param publicKeyText 公钥
* @param text 待解密的信息
* @return /
* @throws Exception /
*/
public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 私钥加密
*
* @param privateKeyText 私钥
* @param text 待加密的信息
* @return /
* @throws Exception /
*/
public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 私钥解密
*
* @param privateKeyText 私钥
* @param text 待解密的文本
* @return /
* @throws Exception /
*/
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 公钥加密
*
* @param publicKeyText 公钥
* @param text 待加密的文本
* @return /
*/
public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 构建RSA密钥对
*
* @return /
* @throws NoSuchAlgorithmException /
*/
public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
return new RsaKeyPair(publicKeyString, privateKeyString);
}
/**
* RSA密钥对对象
*/
public static class RsaKeyPair {
private final String publicKey;
private final String privateKey;
public RsaKeyPair(String publicKey, String privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public String getPrivateKey() {
return privateKey;
}
}
}

View File

@ -0,0 +1,38 @@
package com.stdproject.utils;
import cn.hutool.http.useragent.Browser;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import jakarta.servlet.http.HttpServletRequest;
public class commonUtils {
public static String getBrowser(HttpServletRequest request) {
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
Browser browser = userAgent.getBrowser();
return browser.getName();
}
/**
* 获取客户端IP地址
*/
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}

View File

@ -13,3 +13,6 @@ SPRING_PROFILES_ACTIVE=dev
# CORS配置
CORS_ALLOWED_ORIGINS=https://your-frontend.com
# RSA密钥
RSA_PRIVATE_KEY = MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==

View File

@ -46,6 +46,8 @@ spring:
secret: ${JWT_SECRET:YourJWTSecretKeyForStdProjectBackendApplicationWhichIsVeryLongAndSecure2024!@#$%^&*()}
expiration-ms: ${JWT_EXPIRATION:86400000} # Token 过期时间 (例如: 24小时)
refresh-expiration-ms: ${JWT_REFRESH_EXPIRATION:604800000} # 刷新Token过期时间 (例如: 7天)
rsa:
private-key: ${RSA_PRIVATE_KEY:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==}
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml # MyBatis Mapper XML文件位置

View File

@ -9,55 +9,11 @@ export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
ElBreadcrumb: typeof import('element-plus-secondary/es')['ElBreadcrumb']
ElBreadcrumbItem: typeof import('element-plus-secondary/es')['ElBreadcrumbItem']
ElButton: typeof import('element-plus-secondary/es')['ElButton']
ElCard: typeof import('element-plus-secondary/es')['ElCard']
ElCheckbox: typeof import('element-plus-secondary/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus-secondary/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus-secondary/es')['ElCol']
ElCollapse: typeof import('element-plus-secondary/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus-secondary/es')['ElCollapseItem']
ElColorPicker: typeof import('element-plus-secondary/es')['ElColorPicker']
ElContainer: typeof import('element-plus-secondary/es')['ElContainer']
ElDatePicker: typeof import('element-plus-secondary/es')['ElDatePicker']
ElDialog: typeof import('element-plus-secondary/es')['ElDialog']
ElDivider: typeof import('element-plus-secondary/es')['ElDivider']
ElDropdown: typeof import('element-plus-secondary/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus-secondary/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus-secondary/es')['ElDropdownMenu']
ElEmpty: typeof import('element-plus-secondary/es')['ElEmpty']
ElForm: typeof import('element-plus-secondary/es')['ElForm']
ElFormItem: typeof import('element-plus-secondary/es')['ElFormItem']
ElHeader: typeof import('element-plus-secondary/es')['ElHeader']
ElIcon: typeof import('element-plus-secondary/es')['ElIcon']
ElInput: typeof import('element-plus-secondary/es')['ElInput']
ElInputNumber: typeof import('element-plus-secondary/es')['ElInputNumber']
ElMain: typeof import('element-plus-secondary/es')['ElMain']
ElOption: typeof import('element-plus-secondary/es')['ElOption']
ElOptionGroup: typeof import('element-plus-secondary/es')['ElOptionGroup']
ElPopover: typeof import('element-plus-secondary/es')['ElPopover']
ElRadio: typeof import('element-plus-secondary/es')['ElRadio']
ElRadioGroup: typeof import('element-plus-secondary/es')['ElRadioGroup']
ElRow: typeof import('element-plus-secondary/es')['ElRow']
ElScrollbar: typeof import('element-plus-secondary/es')['ElScrollbar']
ElSelect: typeof import('element-plus-secondary/es')['ElSelect']
ElSelectV2: typeof import('element-plus-secondary/es')['ElSelectV2']
ElSpace: typeof import('element-plus-secondary/es')['ElSpace']
ElSwitch: typeof import('element-plus-secondary/es')['ElSwitch']
ElTabPane: typeof import('element-plus-secondary/es')['ElTabPane']
ElTabs: typeof import('element-plus-secondary/es')['ElTabs']
ElTimeline: typeof import('element-plus-secondary/es')['ElTimeline']
ElTimelineItem: typeof import('element-plus-secondary/es')['ElTimelineItem']
ElTimePicker: typeof import('element-plus-secondary/es')['ElTimePicker']
ElTooltip: typeof import('element-plus-secondary/es')['ElTooltip']
ElTree: typeof import('element-plus-secondary/es')['ElTree']
ElTreeSelect: typeof import('element-plus-secondary/es')['ElTreeSelect']
ElUpload: typeof import('element-plus-secondary/es')['ElUpload']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
export interface ComponentCustomProperties {
vLoading: typeof import('element-plus-secondary/es')['ElLoadingDirective']
}
}

View File

@ -11,63 +11,65 @@
"format": "prettier --write src/"
},
"dependencies": {
"video.js": "^7.21.6",
"@videojs-player/vue": "^1.0.0",
"@vueuse/core": "^9.13.0",
"@npkg/tinymce-plugins": "^0.0.7",
"dayjs": "^1.11.9",
"flv.js": "^1.6.2",
"html2canvas": "^1.4.1",
"jspdf": "^2.5.1",
"html-to-image": "^1.11.11",
"echarts": "^5.5.1",
"file-saver": "^2.0.5",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"mathjs": "^11.6.0",
"@antv/g2plot": "^2.4.29",
"@antv/l7": "^2.22.0",
"@antv/l7plot": "^0.5.5",
"@antv/s2": "^1.49.0",
"vue-i18n": "^9.2.2",
"@element-plus/icons-vue": "^2.3.1",
"@form-create/designer": "^1.1.9",
"@form-create/element-ui": "^3.2.22",
"@form-create/vant": "^3.2.24",
"@turf/centroid": "^7.0.0",
"@npkg/tinymce-plugins": "^0.0.7",
"@tinymce/tinymce-vue": "^5.1.0",
"tinymce": "^5.8.2",
"@turf/centroid": "^7.0.0",
"@videojs-player/vue": "^1.0.0",
"@vueuse/core": "^9.13.0",
"axios": "^1.6.0",
"consola": "^3.4.2",
"dayjs": "^1.11.9",
"echarts": "^5.5.1",
"element-plus": "^2.4.4",
"element-plus-secondary": "^0.6.8",
"element-resize-detector": "^1.2.4",
"vuedraggable": "^4.1.0",
"exceljs": "^4.4.0",
"file-saver": "^2.0.5",
"flv.js": "^1.6.2",
"html-to-image": "^1.11.11",
"html2canvas": "^1.4.1",
"js-base64": "^3.7.5",
"jsencrypt": "^3.3.2",
"jspdf": "^2.5.1",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"mathjs": "^11.6.0",
"mitt": "^3.0.0",
"path": "^0.12.7",
"pinia": "^2.1.7",
"qs": "^6.11.0",
"screenfull": "^6.0.2",
"snowflake-id": "^1.1.0",
"tinymce": "^5.8.2",
"vant": "^4.9.19",
"video.js": "^7.21.6",
"vue": "^3.3.4",
"vue-i18n": "^9.2.2",
"vue-router": "^4.2.5",
"web-storage-cache": "^1.1.1",
"vue-types": "^5.0.2"
"vue-types": "^5.0.2",
"vue3-sfc-loader": "^0.9.5",
"vuedraggable": "^4.1.0",
"web-storage-cache": "^1.1.1"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^0.8.2",
"@rushstack/eslint-patch": "^1.3.3",
"@vitejs/plugin-vue": "^4.5.2",
"@vitejs/plugin-vue-jsx": "^4.2.0",
"@vue/eslint-config-prettier": "^8.0.0",
"less": "^4.1.3",
"jquery": "^3.6.4",
"consola": "^2.15.3",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"jquery": "^3.6.4",
"less": "^4.1.3",
"prettier": "^3.0.3",
"sass": "^1.89.0",
"sass-loader": "^16.0.5",
@ -76,7 +78,6 @@
"unplugin-vue-components-secondary": "^0.24.6",
"vite": "^5.0.8",
"vite-plugin-style-import-secondary": "^2.0.0",
"consola": "^2.15.3",
"vite-svg-loader": "^5.1.0"
},
"engines": {

View File

@ -54,7 +54,7 @@ export default defineConfig({
cors: true,
proxy: {
'/api': {
target: 'http://192.168.1.38:8100',
target: 'http://192.168.1.58:8080',
changeOrigin: true,
secure: false,
rewrite: path => path.replace(/^\/api/, '')