forked from hnu202326010229/ArtifactLLM
Merge branch 'develop' of https://bdgit.educoder.net/hnu202326010229/ArtifactLLM into limengyuan_branch
commit
5a79489e9c
@ -0,0 +1,37 @@
|
||||
# 个人周计划-第11周
|
||||
|
||||
## 姓名和起止时间
|
||||
|
||||
**姓 名:** 哈俊元
|
||||
|
||||
**团队名称:** 2班-老师指定的组队
|
||||
|
||||
**开始时间:** 2025-12-01
|
||||
|
||||
**结束时间:** 2025-12-08
|
||||
|
||||
## 本周任务计划安排
|
||||
|
||||
| 序号 | 计划内容 | 协作人 | 情况说明 |
|
||||
|------|----------|--------|----------|
|
||||
| 1 | 前端代码优化 | 个人 | 继续优化前端代码结构和性能,提高用户体验 |
|
||||
| 2 | 前后端联调准备 | 个人 | 等待后端开发完成,准备进行前后端联调 |
|
||||
| 3 | Bug修复 | 个人 | 根据测试结果修复前端可能存在的问题 |
|
||||
| 4 | 文档完善 | 个人 | 更新和完善相关技术文档 |
|
||||
| 5 | 团队协作 | 全体成员 | 参与团队会议,协调联调工作安排 |
|
||||
|
||||
## 小结
|
||||
|
||||
1. **持续优化:** 通过不断优化前端代码提升系统性能和用户体验;
|
||||
2. **联调准备:** 积极准备前后端联调工作,确保接口对接顺利;
|
||||
3. **团队协作:** 密切关注后端开发进度,及时进行沟通协调;
|
||||
4. **质量保证:** 注重代码质量和系统稳定性,做好充分的测试准备。
|
||||
|
||||
---
|
||||
|
||||
## 【注】
|
||||
|
||||
1. 在小结一栏中写出希望得到如何的帮助,如讲座等;
|
||||
2. 请将个人计划和总结提前发给负责人;
|
||||
3. 周任务总结与计划是项目小组评分考核的重要依据,将直接记入平时成绩,请各位同学按要求认真填写并按时提交;
|
||||
4. 所有组员都需提交个人周计划、周总结文档,按时上传至代码托管平台;
|
||||
@ -0,0 +1,41 @@
|
||||
|
||||
package cn.edu.hnu.artifactcommon.constant;
|
||||
|
||||
/**
|
||||
* 系统通用常量
|
||||
*/
|
||||
public class SystemConstant {
|
||||
/**
|
||||
* 用户角色常量
|
||||
*/
|
||||
public static final String ROLE_GUEST = "guest";
|
||||
public static final String ROLE_USER = "user";
|
||||
public static final String ROLE_ADVANCED = "advanced";
|
||||
public static final String ROLE_ADMIN = "admin";
|
||||
|
||||
/**
|
||||
* 用户状态常量
|
||||
*/
|
||||
public static final Integer STATUS_NORMAL = 0; // 正常
|
||||
public static final Integer STATUS_DISABLED = 1; // 禁用
|
||||
|
||||
/**
|
||||
* JWT相关常量
|
||||
*/
|
||||
public static final String JWT_HEADER = "Authorization";
|
||||
public static final String JWT_PREFIX = "Bearer ";
|
||||
public static final String JWT_SECRET = "artifact-system-secret-key";
|
||||
public static final Long JWT_EXPIRATION = 7 * 24 * 60 * 60 * 1000L; // 7天
|
||||
|
||||
/**
|
||||
* Redis缓存相关常量
|
||||
*/
|
||||
public static final String REDIS_KEY_PREFIX = "artifact:";
|
||||
public static final String REDIS_KEY_CAPTCHA = "captcha:";
|
||||
public static final String REDIS_KEY_USER = "user:";
|
||||
public static final String REDIS_KEY_TOKEN = "token:";
|
||||
|
||||
private SystemConstant() {
|
||||
// 私有构造方法,防止实例化
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
|
||||
package cn.edu.hnu.artifactcommon.context;
|
||||
|
||||
/**
|
||||
* 用户上下文
|
||||
*/
|
||||
public class UserContext {
|
||||
|
||||
/**
|
||||
* 使用ThreadLocal存储当前线程的用户信息
|
||||
*/
|
||||
private static final ThreadLocal<String> USER_THREAD_LOCAL = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 设置当前线程的用户名
|
||||
*/
|
||||
public static void setCurrentUsername(String username) {
|
||||
USER_THREAD_LOCAL.set(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前线程的用户名
|
||||
*/
|
||||
public static String getCurrentUsername() {
|
||||
return USER_THREAD_LOCAL.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除当前线程的用户信息
|
||||
*/
|
||||
public static void clear() {
|
||||
USER_THREAD_LOCAL.remove();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
|
||||
package cn.edu.hnu.artifactcommon.exception;
|
||||
|
||||
/**
|
||||
* 业务异常类
|
||||
*/
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 错误消息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
public BusinessException(String message) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
this.code = 500;
|
||||
}
|
||||
|
||||
public BusinessException(Integer code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public BusinessException(String message, Throwable e) {
|
||||
super(message, e);
|
||||
this.message = message;
|
||||
this.code = 500;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(Integer code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
|
||||
package cn.edu.hnu.artifactcommon.pojo.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用户数据传输对象
|
||||
*/
|
||||
@Data
|
||||
public class UserDTO {
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
private String captcha;
|
||||
|
||||
/**
|
||||
* 验证码UUID
|
||||
*/
|
||||
private String captchaUuid;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
package cn.edu.hnu.artifactcommon.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 登录响应视图对象
|
||||
*/
|
||||
@Data
|
||||
public class LoginVO {
|
||||
/**
|
||||
* JWT令牌
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
private UserVO user;
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
|
||||
package cn.edu.hnu.artifactcommon.utils;
|
||||
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 加密工具类
|
||||
*/
|
||||
public class EncryptUtil {
|
||||
|
||||
/**
|
||||
* MD5加密
|
||||
* @param text 明文
|
||||
* @return 密文
|
||||
*/
|
||||
public static String md5(String text) {
|
||||
return DigestUtils.md5DigestAsHex(text.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5加盐加密
|
||||
* @param text 明文
|
||||
* @param salt 盐
|
||||
* @return 密文
|
||||
*/
|
||||
public static String md5(String text, String salt) {
|
||||
return md5(text + salt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机盐
|
||||
* @return 盐
|
||||
*/
|
||||
public static String generateSalt() {
|
||||
return UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* BCrypt加密
|
||||
* @param password 明文密码
|
||||
* @return 密文
|
||||
*/
|
||||
public static String bcrypt(String password) {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
return encoder.encode(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* BCrypt密码验证
|
||||
* @param password 明文密码
|
||||
* @param encodedPassword 密文密码
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean bcryptMatch(String password, String encodedPassword) {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
return encoder.matches(password, encodedPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA256加密
|
||||
* @param text 明文
|
||||
* @return 密文
|
||||
*/
|
||||
public static String sha256(String text) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = digest.digest(text.getBytes());
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
|
||||
for (byte b : hash) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
|
||||
return hexString.toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("SHA-256加密失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
|
||||
package cn.edu.hnu.artifactcommon.utils;
|
||||
|
||||
import cn.edu.hnu.artifactcommon.constant.SystemConstant;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.security.Key;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* JWT工具类
|
||||
*/
|
||||
@Component
|
||||
public class JwtUtil {
|
||||
|
||||
/**
|
||||
* 获取签名密钥
|
||||
*/
|
||||
private Key getSigningKey() {
|
||||
return Keys.hmacShaKeyFor(SystemConstant.JWT_SECRET.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从token中获取用户名
|
||||
*/
|
||||
public String getUsernameFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getSubject);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从token中获取过期时间
|
||||
*/
|
||||
public Date getExpirationDateFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getExpiration);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从token中获取指定声明
|
||||
*/
|
||||
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||||
final Claims claims = getAllClaimsFromToken(token);
|
||||
return claimsResolver.apply(claims);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从token中获取所有声明
|
||||
*/
|
||||
private Claims getAllClaimsFromToken(String token) {
|
||||
return Jwts.parserBuilder()
|
||||
.setSigningKey(getSigningKey())
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查token是否过期
|
||||
*/
|
||||
private Boolean isTokenExpired(String token) {
|
||||
final Date expiration = getExpirationDateFromToken(token);
|
||||
return expiration.before(new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
*/
|
||||
public String generateToken(String username, String role) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("role", role);
|
||||
return doGenerateToken(claims, username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成token的具体实现
|
||||
*/
|
||||
private String doGenerateToken(Map<String, Object> claims, String subject) {
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setSubject(subject)
|
||||
.setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + SystemConstant.JWT_EXPIRATION))
|
||||
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证token
|
||||
*/
|
||||
public Boolean validateToken(String token, String username) {
|
||||
final String tokenUsername = getUsernameFromToken(token);
|
||||
return (tokenUsername.equals(username) && !isTokenExpired(token));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.controller;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.Permission;
|
||||
import cn.edu.hnu.artifactsystem.service.IPermissionService;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/permissions")
|
||||
public class PermissionController {
|
||||
|
||||
@Resource
|
||||
private IPermissionService permissionService;
|
||||
|
||||
/**
|
||||
* 分页查询权限列表
|
||||
*/
|
||||
@GetMapping
|
||||
public Page<Permission> getPermissionPage(
|
||||
@RequestParam(defaultValue = "1") int current,
|
||||
@RequestParam(defaultValue = "10") int size,
|
||||
@RequestParam(required = false) String name,
|
||||
@RequestParam(required = false) Integer type,
|
||||
@RequestParam(required = false) Integer status) {
|
||||
return permissionService.getPermissionPage(current, size, name, type, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取权限
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Permission getPermissionById(@PathVariable Long id) {
|
||||
return permissionService.getPermissionById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有权限
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public List<Permission> getAllPermissions() {
|
||||
return permissionService.getAllPermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树形结构权限列表
|
||||
*/
|
||||
@GetMapping("/tree")
|
||||
public List<Permission> getPermissionTree() {
|
||||
return permissionService.getPermissionTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加权限
|
||||
*/
|
||||
@PostMapping
|
||||
public Permission addPermission(@RequestBody Permission permission) {
|
||||
return permissionService.addPermission(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新权限
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public boolean updatePermission(@PathVariable Long id, @RequestBody Permission permission) {
|
||||
permission.setId(id);
|
||||
return permissionService.updatePermission(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除权限
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public boolean deletePermission(@PathVariable Long id) {
|
||||
return permissionService.deletePermission(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除权限
|
||||
*/
|
||||
@DeleteMapping("/batch")
|
||||
public boolean batchDeletePermissions(@RequestBody List<Long> ids) {
|
||||
return permissionService.batchDeletePermissions(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID获取权限列表
|
||||
*/
|
||||
@GetMapping("/user/{userId}")
|
||||
public List<Permission> getPermissionsByUserId(@PathVariable Long userId) {
|
||||
return permissionService.getPermissionsByUserId(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色ID获取权限列表
|
||||
*/
|
||||
@GetMapping("/role/{roleId}")
|
||||
public List<Permission> getPermissionsByRoleId(@PathVariable Long roleId) {
|
||||
return permissionService.getPermissionsByRoleId(roleId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.controller;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.Role;
|
||||
import cn.edu.hnu.artifactsystem.service.IRoleService;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/roles")
|
||||
public class RoleController {
|
||||
|
||||
@Resource
|
||||
private IRoleService roleService;
|
||||
|
||||
/**
|
||||
* 分页查询角色列表
|
||||
*/
|
||||
@GetMapping
|
||||
public Page<Role> getRolePage(
|
||||
@RequestParam(defaultValue = "1") int current,
|
||||
@RequestParam(defaultValue = "10") int size,
|
||||
@RequestParam(required = false) String name,
|
||||
@RequestParam(required = false) Integer status) {
|
||||
return roleService.getRolePage(current, size, name, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取角色
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Role getRoleById(@PathVariable Long id) {
|
||||
return roleService.getRoleById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有角色
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public List<Role> getAllRoles() {
|
||||
return roleService.getAllRoles();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加角色
|
||||
*/
|
||||
@PostMapping
|
||||
public Role addRole(@RequestBody Role role) {
|
||||
return roleService.addRole(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新角色
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public boolean updateRole(@PathVariable Long id, @RequestBody Role role) {
|
||||
role.setId(id);
|
||||
return roleService.updateRole(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除角色
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public boolean deleteRole(@PathVariable Long id) {
|
||||
return roleService.deleteRole(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除角色
|
||||
*/
|
||||
@DeleteMapping("/batch")
|
||||
public boolean batchDeleteRoles(@RequestBody List<Long> ids) {
|
||||
return roleService.batchDeleteRoles(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID获取角色列表
|
||||
*/
|
||||
@GetMapping("/user/{userId}")
|
||||
public List<Role> getRolesByUserId(@PathVariable Long userId) {
|
||||
return roleService.getRolesByUserId(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为用户分配角色
|
||||
*/
|
||||
@PostMapping("/user/{userId}")
|
||||
public boolean assignRolesToUser(@PathVariable Long userId, @RequestBody List<Long> roleIds) {
|
||||
return roleService.assignRolesToUser(userId, roleIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色ID获取权限ID列表
|
||||
*/
|
||||
@GetMapping("/{roleId}/permissions")
|
||||
public List<Long> getPermissionIdsByRoleId(@PathVariable Long roleId) {
|
||||
return roleService.getPermissionIdsByRoleId(roleId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为角色分配权限
|
||||
*/
|
||||
@PostMapping("/{roleId}/permissions")
|
||||
public boolean assignPermissionsToRole(@PathVariable Long roleId, @RequestBody List<Long> permissionIds) {
|
||||
return roleService.assignPermissionsToRole(roleId, permissionIds);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.controller;
|
||||
|
||||
import cn.edu.hnu.artifactcommon.pojo.dto.UserDTO;
|
||||
import cn.edu.hnu.artifactcommon.pojo.vo.LoginVO;
|
||||
import cn.edu.hnu.artifactcommon.pojo.vo.UserVO;
|
||||
import cn.edu.hnu.artifactcommon.utils.CaptchaUtil;
|
||||
import cn.edu.hnu.artifactsystem.service.IUserService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 用户控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
public class UserController {
|
||||
|
||||
@Resource
|
||||
private IUserService userService;
|
||||
|
||||
@Resource
|
||||
private CaptchaUtil captchaUtil;
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
@PostMapping("/register")
|
||||
public UserVO register(@RequestBody UserDTO userDTO) {
|
||||
return userService.register(userDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public LoginVO login(@RequestBody UserDTO userDTO) {
|
||||
return userService.login(userDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证码
|
||||
*/
|
||||
@GetMapping("/captcha")
|
||||
public Map<String, String> getCaptcha() throws IOException {
|
||||
// 生成UUID作为验证码标识
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
// 生成验证码图片
|
||||
String captchaImage = captchaUtil.generateCaptcha(uuid);
|
||||
|
||||
// 返回验证码图片和UUID
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("uuid", uuid);
|
||||
result.put("image", captchaImage);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户信息
|
||||
*/
|
||||
@GetMapping("/info")
|
||||
public UserVO getCurrentUser(HttpServletRequest request) {
|
||||
// 从请求属性中获取用户名
|
||||
String username = (String) request.getAttribute("username");
|
||||
|
||||
if (username == null || username.isEmpty()) {
|
||||
throw new RuntimeException("未登录或令牌已过期");
|
||||
}
|
||||
|
||||
return userService.getUserByUsername(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登出
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
public String logout() {
|
||||
// 实际应用中可以在这里处理令牌黑名单等逻辑
|
||||
return "登出成功";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.controller;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.User;
|
||||
import cn.edu.hnu.artifactsystem.service.IUserService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户管理控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
public class UserManagementController {
|
||||
|
||||
@Resource
|
||||
private IUserService userService;
|
||||
|
||||
/**
|
||||
* 分页查询用户列表
|
||||
*/
|
||||
@GetMapping
|
||||
public Map<String, Object> getUserPage(
|
||||
@RequestParam(defaultValue = "1") int current,
|
||||
@RequestParam(defaultValue = "10") int size,
|
||||
@RequestParam(required = false) String username) {
|
||||
|
||||
Page<User> page = new Page<>(current, size);
|
||||
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
if (username != null && !username.isEmpty()) {
|
||||
queryWrapper.like("username", username);
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc("create_time");
|
||||
Page<User> userPage = userService.page(page, queryWrapper);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("items", userPage.getRecords());
|
||||
result.put("total", userPage.getTotal());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取用户
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public User getUserById(@PathVariable Long id) {
|
||||
return userService.getById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public boolean updateUser(@PathVariable Long id, @RequestBody User user) {
|
||||
user.setId(id);
|
||||
return userService.updateById(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public boolean deleteUser(@PathVariable Long id) {
|
||||
return userService.removeById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除用户
|
||||
*/
|
||||
@DeleteMapping("/batch")
|
||||
public boolean batchDeleteUsers(@RequestBody List<Long> ids) {
|
||||
return userService.removeByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换用户状态
|
||||
*/
|
||||
@PutMapping("/{id}/status")
|
||||
public boolean toggleUserStatus(@PathVariable Long id, @RequestParam Integer status) {
|
||||
User user = userService.getById(id);
|
||||
if (user != null) {
|
||||
user.setStatus(status);
|
||||
return userService.updateById(user);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 角色权限关联实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_role_permission")
|
||||
public class RolePermission {
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 权限ID
|
||||
*/
|
||||
private Long permissionId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户角色关联实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_user_role")
|
||||
public class UserRole {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.mapper;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.RolePermission;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色权限映射器接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface RolePermissionMapper extends BaseMapper<RolePermission> {
|
||||
|
||||
/**
|
||||
* 根据角色ID查询权限ID列表
|
||||
*/
|
||||
@Select("SELECT permission_id FROM sys_role_permission WHERE role_id = #{roleId}")
|
||||
List<Long> selectPermissionIdsByRoleId(@Param("roleId") Long roleId);
|
||||
|
||||
/**
|
||||
* 根据权限ID查询角色ID列表
|
||||
*/
|
||||
@Select("SELECT role_id FROM sys_role_permission WHERE permission_id = #{permissionId}")
|
||||
List<Long> selectRoleIdsByPermissionId(@Param("permissionId") Long permissionId);
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.mapper;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.UserRole;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户角色映射器接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserRoleMapper extends BaseMapper<UserRole> {
|
||||
|
||||
/**
|
||||
* 根据用户ID查询角色ID列表
|
||||
*/
|
||||
@Select("SELECT role_id FROM sys_user_role WHERE user_id = #{userId}")
|
||||
List<Long> selectRoleIdsByUserId(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 根据角色ID查询用户ID列表
|
||||
*/
|
||||
@Select("SELECT user_id FROM sys_user_role WHERE role_id = #{roleId}")
|
||||
List<Long> selectUserIdsByRoleId(@Param("roleId") Long roleId);
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.service;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.Permission;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限服务接口
|
||||
*/
|
||||
public interface IPermissionService extends IService<Permission> {
|
||||
|
||||
/**
|
||||
* 分页查询权限列表
|
||||
*/
|
||||
Page<Permission> getPermissionPage(int current, int size, String name, Integer type, Integer status);
|
||||
|
||||
/**
|
||||
* 根据ID获取权限
|
||||
*/
|
||||
Permission getPermissionById(Long id);
|
||||
|
||||
/**
|
||||
* 添加权限
|
||||
*/
|
||||
Permission addPermission(Permission permission);
|
||||
|
||||
/**
|
||||
* 更新权限
|
||||
*/
|
||||
boolean updatePermission(Permission permission);
|
||||
|
||||
/**
|
||||
* 删除权限
|
||||
*/
|
||||
boolean deletePermission(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除权限
|
||||
*/
|
||||
boolean batchDeletePermissions(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获取所有权限
|
||||
*/
|
||||
List<Permission> getAllPermissions();
|
||||
|
||||
/**
|
||||
* 获取树形结构权限列表
|
||||
*/
|
||||
List<Permission> getPermissionTree();
|
||||
|
||||
/**
|
||||
* 根据用户ID获取权限列表
|
||||
*/
|
||||
List<Permission> getPermissionsByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据角色ID获取权限列表
|
||||
*/
|
||||
List<Permission> getPermissionsByRoleId(Long roleId);
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.service;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.Role;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色服务接口
|
||||
*/
|
||||
public interface IRoleService extends IService<Role> {
|
||||
|
||||
/**
|
||||
* 分页查询角色列表
|
||||
*/
|
||||
Page<Role> getRolePage(int current, int size, String name, Integer status);
|
||||
|
||||
/**
|
||||
* 根据ID获取角色
|
||||
*/
|
||||
Role getRoleById(Long id);
|
||||
|
||||
/**
|
||||
* 添加角色
|
||||
*/
|
||||
Role addRole(Role role);
|
||||
|
||||
/**
|
||||
* 更新角色
|
||||
*/
|
||||
boolean updateRole(Role role);
|
||||
|
||||
/**
|
||||
* 删除角色
|
||||
*/
|
||||
boolean deleteRole(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除角色
|
||||
*/
|
||||
boolean batchDeleteRoles(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获取所有角色
|
||||
*/
|
||||
List<Role> getAllRoles();
|
||||
|
||||
/**
|
||||
* 根据用户ID获取角色列表
|
||||
*/
|
||||
List<Role> getRolesByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 为用户分配角色
|
||||
*/
|
||||
boolean assignRolesToUser(Long userId, List<Long> roleIds);
|
||||
|
||||
/**
|
||||
* 根据角色ID获取权限ID列表
|
||||
*/
|
||||
List<Long> getPermissionIdsByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 为角色分配权限
|
||||
*/
|
||||
boolean assignPermissionsToRole(Long roleId, List<Long> permissionIds);
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.service;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.User;
|
||||
import cn.edu.hnu.artifactcommon.pojo.dto.UserDTO;
|
||||
import cn.edu.hnu.artifactcommon.pojo.vo.LoginVO;
|
||||
import cn.edu.hnu.artifactcommon.pojo.vo.UserVO;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* 用户服务接口
|
||||
*/
|
||||
public interface IUserService extends IService<User> {
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
UserVO register(UserDTO userDTO);
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*/
|
||||
LoginVO login(UserDTO userDTO);
|
||||
|
||||
/**
|
||||
* 根据用户名查询用户
|
||||
*/
|
||||
User findByUsername(String username);
|
||||
|
||||
/**
|
||||
* 根据ID获取用户VO
|
||||
*/
|
||||
UserVO getUserById(Long id);
|
||||
|
||||
/**
|
||||
* 检查用户名是否存在
|
||||
*/
|
||||
boolean checkUsernameExists(String username);
|
||||
|
||||
/**
|
||||
* 根据用户名获取用户VO
|
||||
*/
|
||||
UserVO getUserByUsername(String username);
|
||||
}
|
||||
@ -0,0 +1,179 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.service.impl;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.Permission;
|
||||
import cn.edu.hnu.artifactsystem.entity.RolePermission;
|
||||
import cn.edu.hnu.artifactsystem.entity.UserRole;
|
||||
import cn.edu.hnu.artifactsystem.mapper.PermissionMapper;
|
||||
import cn.edu.hnu.artifactsystem.mapper.RolePermissionMapper;
|
||||
import cn.edu.hnu.artifactsystem.mapper.UserRoleMapper;
|
||||
import cn.edu.hnu.artifactsystem.service.IPermissionService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 权限服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {
|
||||
|
||||
@Resource
|
||||
private PermissionMapper permissionMapper;
|
||||
|
||||
@Resource
|
||||
private UserRoleMapper userRoleMapper;
|
||||
|
||||
@Resource
|
||||
private RolePermissionMapper rolePermissionMapper;
|
||||
|
||||
@Override
|
||||
public Page<Permission> getPermissionPage(int current, int size, String name, Integer type, Integer status) {
|
||||
Page<Permission> page = new Page<>(current, size);
|
||||
QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
if (name != null && !name.isEmpty()) {
|
||||
queryWrapper.like("name", name);
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
queryWrapper.eq("type", type);
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
queryWrapper.eq("status", status);
|
||||
}
|
||||
|
||||
queryWrapper.orderByAsc("sort_order");
|
||||
return permissionMapper.selectPage(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission getPermissionById(Long id) {
|
||||
return permissionMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission addPermission(Permission permission) {
|
||||
permission.setCreateTime(LocalDateTime.now());
|
||||
permissionMapper.insert(permission);
|
||||
return permission;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updatePermission(Permission permission) {
|
||||
permission.setUpdateTime(LocalDateTime.now());
|
||||
return permissionMapper.updateById(permission) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deletePermission(Long id) {
|
||||
// 删除权限前,先检查是否有角色使用该权限
|
||||
List<Long> roleIds = rolePermissionMapper.selectRoleIdsByPermissionId(id);
|
||||
if (roleIds != null && !roleIds.isEmpty()) {
|
||||
throw new RuntimeException("该权限已被角色使用,无法删除");
|
||||
}
|
||||
|
||||
// 删除权限
|
||||
return permissionMapper.deleteById(id) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean batchDeletePermissions(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Long id : ids) {
|
||||
deletePermission(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Permission> getAllPermissions() {
|
||||
QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("status", 0); // 只查询正常状态的权限
|
||||
queryWrapper.orderByAsc("sort_order");
|
||||
return permissionMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Permission> getPermissionTree() {
|
||||
List<Permission> allPermissions = getAllPermissions();
|
||||
|
||||
// 构建父子关系
|
||||
Map<Long, Permission> permissionMap = new HashMap<>();
|
||||
for (Permission permission : allPermissions) {
|
||||
permissionMap.put(permission.getId(), permission);
|
||||
}
|
||||
|
||||
List<Permission> rootPermissions = new ArrayList<>();
|
||||
for (Permission permission : allPermissions) {
|
||||
if (permission.getParentId() == null || permission.getParentId() == 0) {
|
||||
rootPermissions.add(permission);
|
||||
} else {
|
||||
Permission parent = permissionMap.get(permission.getParentId());
|
||||
if (parent != null) {
|
||||
if (parent.getChildren() == null) {
|
||||
parent.setChildren(new ArrayList<>());
|
||||
}
|
||||
parent.getChildren().add(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rootPermissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Permission> getPermissionsByUserId(Long userId) {
|
||||
// 先获取用户的所有角色ID
|
||||
List<Long> roleIds = userRoleMapper.selectRoleIdsByUserId(userId);
|
||||
|
||||
if (roleIds == null || roleIds.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 再获取这些角色的所有权限ID
|
||||
List<Long> permissionIds = new ArrayList<>();
|
||||
for (Long roleId : roleIds) {
|
||||
List<Long> ids = rolePermissionMapper.selectPermissionIdsByRoleId(roleId);
|
||||
if (ids != null) {
|
||||
permissionIds.addAll(ids);
|
||||
}
|
||||
}
|
||||
|
||||
// 去重
|
||||
permissionIds = permissionIds.stream().distinct().collect(Collectors.toList());
|
||||
|
||||
// 最后根据权限ID获取权限信息
|
||||
if (permissionIds.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return permissionMapper.selectBatchIds(permissionIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Permission> getPermissionsByRoleId(Long roleId) {
|
||||
// 先获取角色的所有权限ID
|
||||
List<Long> permissionIds = rolePermissionMapper.selectPermissionIdsByRoleId(roleId);
|
||||
|
||||
if (permissionIds == null || permissionIds.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 根据权限ID获取权限信息
|
||||
return permissionMapper.selectBatchIds(permissionIds);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,169 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.service.impl;
|
||||
|
||||
import cn.edu.hnu.artifactsystem.entity.Role;
|
||||
import cn.edu.hnu.artifactsystem.entity.RolePermission;
|
||||
import cn.edu.hnu.artifactsystem.entity.UserRole;
|
||||
import cn.edu.hnu.artifactsystem.mapper.RoleMapper;
|
||||
import cn.edu.hnu.artifactsystem.mapper.RolePermissionMapper;
|
||||
import cn.edu.hnu.artifactsystem.mapper.UserRoleMapper;
|
||||
import cn.edu.hnu.artifactsystem.service.IRoleService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
|
||||
|
||||
@Resource
|
||||
private RoleMapper roleMapper;
|
||||
|
||||
@Resource
|
||||
private UserRoleMapper userRoleMapper;
|
||||
|
||||
@Resource
|
||||
private RolePermissionMapper rolePermissionMapper;
|
||||
|
||||
@Override
|
||||
public Page<Role> getRolePage(int current, int size, String name, Integer status) {
|
||||
Page<Role> page = new Page<>(current, size);
|
||||
QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
if (name != null && !name.isEmpty()) {
|
||||
queryWrapper.like("name", name);
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
queryWrapper.eq("status", status);
|
||||
}
|
||||
|
||||
queryWrapper.orderByAsc("sort_order");
|
||||
return roleMapper.selectPage(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role getRoleById(Long id) {
|
||||
return roleMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role addRole(Role role) {
|
||||
role.setCreateTime(LocalDateTime.now());
|
||||
roleMapper.insert(role);
|
||||
return role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateRole(Role role) {
|
||||
role.setUpdateTime(LocalDateTime.now());
|
||||
return roleMapper.updateById(role) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteRole(Long id) {
|
||||
// 删除角色前,先删除角色与用户的关联关系
|
||||
QueryWrapper<UserRole> userRoleWrapper = new QueryWrapper<>();
|
||||
userRoleWrapper.eq("role_id", id);
|
||||
userRoleMapper.delete(userRoleWrapper);
|
||||
|
||||
// 删除角色前,先删除角色与权限的关联关系
|
||||
QueryWrapper<RolePermission> rolePermissionWrapper = new QueryWrapper<>();
|
||||
rolePermissionWrapper.eq("role_id", id);
|
||||
rolePermissionMapper.delete(rolePermissionWrapper);
|
||||
|
||||
// 删除角色
|
||||
return roleMapper.deleteById(id) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean batchDeleteRoles(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Long id : ids) {
|
||||
deleteRole(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Role> getAllRoles() {
|
||||
QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("status", 0); // 只查询正常状态的角色
|
||||
queryWrapper.orderByAsc("sort_order");
|
||||
return roleMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Role> getRolesByUserId(Long userId) {
|
||||
// 先查询用户拥有的角色ID
|
||||
List<Long> roleIds = userRoleMapper.selectRoleIdsByUserId(userId);
|
||||
|
||||
if (roleIds == null || roleIds.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 再根据角色ID查询角色信息
|
||||
return roleMapper.selectBatchIds(roleIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean assignRolesToUser(Long userId, List<Long> roleIds) {
|
||||
// 先删除用户原有的角色关系
|
||||
QueryWrapper<UserRole> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("user_id", userId);
|
||||
userRoleMapper.delete(wrapper);
|
||||
|
||||
// 添加新的角色关系
|
||||
if (roleIds != null && !roleIds.isEmpty()) {
|
||||
for (Long roleId : roleIds) {
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setUserId(userId);
|
||||
userRole.setRoleId(roleId);
|
||||
userRole.setCreateTime(LocalDateTime.now());
|
||||
userRoleMapper.insert(userRole);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> getPermissionIdsByRoleId(Long roleId) {
|
||||
return rolePermissionMapper.selectPermissionIdsByRoleId(roleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean assignPermissionsToRole(Long roleId, List<Long> permissionIds) {
|
||||
// 先删除角色原有的权限关系
|
||||
QueryWrapper<RolePermission> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("role_id", roleId);
|
||||
rolePermissionMapper.delete(wrapper);
|
||||
|
||||
// 添加新的权限关系
|
||||
if (permissionIds != null && !permissionIds.isEmpty()) {
|
||||
for (Long permissionId : permissionIds) {
|
||||
RolePermission rolePermission = new RolePermission();
|
||||
rolePermission.setRoleId(roleId);
|
||||
rolePermission.setPermissionId(permissionId);
|
||||
rolePermission.setCreateTime(LocalDateTime.now());
|
||||
rolePermissionMapper.insert(rolePermission);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
|
||||
package cn.edu.hnu.artifactsystem.service.impl;
|
||||
|
||||
import cn.edu.hnu.artifactcommon.constant.SystemConstant;
|
||||
import cn.edu.hnu.artifactcommon.pojo.dto.UserDTO;
|
||||
import cn.edu.hnu.artifactcommon.pojo.vo.LoginVO;
|
||||
import cn.edu.hnu.artifactcommon.pojo.vo.UserVO;
|
||||
import cn.edu.hnu.artifactcommon.utils.CaptchaUtil;
|
||||
import cn.edu.hnu.artifactcommon.utils.EncryptUtil;
|
||||
import cn.edu.hnu.artifactcommon.utils.JwtUtil;
|
||||
import cn.edu.hnu.artifactsystem.entity.User;
|
||||
import cn.edu.hnu.artifactsystem.mapper.UserMapper;
|
||||
import cn.edu.hnu.artifactsystem.service.IUserService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户服务实现类
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
|
||||
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Resource
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
@Resource
|
||||
private CaptchaUtil captchaUtil;
|
||||
|
||||
@Override
|
||||
public UserVO register(UserDTO userDTO) {
|
||||
// 验证验证码
|
||||
if (!captchaUtil.validateCaptcha(userDTO.getCaptchaUuid(), userDTO.getCaptcha())) {
|
||||
throw new RuntimeException("验证码错误");
|
||||
}
|
||||
|
||||
// 检查用户名是否已存在
|
||||
if (checkUsernameExists(userDTO.getUsername())) {
|
||||
throw new RuntimeException("用户名已存在");
|
||||
}
|
||||
|
||||
// 创建用户实体
|
||||
User user = new User();
|
||||
user.setUsername(userDTO.getUsername());
|
||||
user.setPassword(encryptPassword(userDTO.getPassword()));
|
||||
user.setEmail(userDTO.getEmail());
|
||||
user.setRole(SystemConstant.ROLE_USER); // 默认角色为普通用户
|
||||
user.setStatus(SystemConstant.STATUS_NORMAL); // 默认状态为正常
|
||||
user.setCreateTime(LocalDateTime.now());
|
||||
|
||||
// 保存用户
|
||||
userMapper.insert(user);
|
||||
|
||||
// 转换为VO并返回
|
||||
return convertToVO(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginVO login(UserDTO userDTO) {
|
||||
// 验证验证码
|
||||
if (!captchaUtil.validateCaptcha(userDTO.getCaptchaUuid(), userDTO.getCaptcha())) {
|
||||
throw new RuntimeException("验证码错误");
|
||||
}
|
||||
|
||||
// 根据用户名查询用户
|
||||
User user = findByUsername(userDTO.getUsername());
|
||||
if (user == null) {
|
||||
throw new RuntimeException("用户不存在");
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
if (!user.getPassword().equals(encryptPassword(userDTO.getPassword()))) {
|
||||
throw new RuntimeException("密码错误");
|
||||
}
|
||||
|
||||
// 检查用户状态
|
||||
if (!SystemConstant.STATUS_NORMAL.equals(user.getStatus())) {
|
||||
throw new RuntimeException("账户已被禁用");
|
||||
}
|
||||
|
||||
// 更新最后登录时间
|
||||
user.setLastLoginTime(LocalDateTime.now());
|
||||
userMapper.updateById(user);
|
||||
|
||||
// 生成JWT令牌
|
||||
String token = jwtUtil.generateToken(user.getUsername(), user.getRole());
|
||||
|
||||
// 构建登录响应
|
||||
LoginVO loginVO = new LoginVO();
|
||||
loginVO.setToken(token);
|
||||
loginVO.setUser(convertToVO(user));
|
||||
|
||||
return loginVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User findByUsername(String username) {
|
||||
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("username", username);
|
||||
return userMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserVO getUserById(Long id) {
|
||||
User user = userMapper.selectById(id);
|
||||
return user != null ? convertToVO(user) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkUsernameExists(String username) {
|
||||
return findByUsername(username) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserVO getUserByUsername(String username) {
|
||||
User user = findByUsername(username);
|
||||
return user != null ? convertToVO(user) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码加密
|
||||
*/
|
||||
private String encryptPassword(String password) {
|
||||
return EncryptUtil.md5(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实体转VO
|
||||
*/
|
||||
private UserVO convertToVO(User user) {
|
||||
UserVO userVO = new UserVO();
|
||||
BeanUtils.copyProperties(user, userVO);
|
||||
// 不返回密码
|
||||
return userVO;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
-- 创建数据库
|
||||
CREATE DATABASE IF NOT EXISTS artifact_llm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- 使用数据库
|
||||
USE artifact_llm;
|
||||
|
||||
/*==============================================================*/
|
||||
/* DBMS name: MySQL 8.0 */
|
||||
/* Created on: 2024/XX/XX 10:00:00 */
|
||||
/*==============================================================*/
|
||||
|
||||
-- 删除所有表(按依赖关系逆序)
|
||||
DROP TABLE IF EXISTS audit_trails;
|
||||
DROP TABLE IF EXISTS user_management_logs;
|
||||
DROP TABLE IF EXISTS content_review_logs;
|
||||
DROP TABLE IF EXISTS model_review_records;
|
||||
DROP TABLE IF EXISTS feedback;
|
||||
DROP TABLE IF EXISTS user_favorites;
|
||||
DROP TABLE IF EXISTS search_history;
|
||||
DROP TABLE IF EXISTS messages;
|
||||
DROP TABLE IF EXISTS kg_update_requests;
|
||||
DROP TABLE IF EXISTS modeling_versions;
|
||||
DROP TABLE IF EXISTS modeling_projects;
|
||||
DROP TABLE IF EXISTS user_defined_relations;
|
||||
DROP TABLE IF EXISTS user_defined_entities;
|
||||
DROP TABLE IF EXISTS ai_research_reports;
|
||||
DROP TABLE IF EXISTS ai_messages;
|
||||
DROP TABLE IF EXISTS entity_relations;
|
||||
DROP TABLE IF EXISTS relic_multi_mode;
|
||||
DROP TABLE IF EXISTS cultural_relics;
|
||||
DROP TABLE IF EXISTS login_operation_log;
|
||||
DROP TABLE IF EXISTS users;
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: users */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE users
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
username VARCHAR(50) NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(100),
|
||||
real_name VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
user_type VARCHAR(20) NOT NULL DEFAULT 'normal',
|
||||
status VARCHAR(10) NOT NULL DEFAULT 'active',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
last_login DATETIME,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_username (username),
|
||||
UNIQUE KEY uk_email (email)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: login_operation_log */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE login_operation_log
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
user_id INT NOT NULL,
|
||||
operation_type VARCHAR(50) NOT NULL,
|
||||
operation_detail TEXT,
|
||||
ip_address VARCHAR(45),
|
||||
user_agent TEXT,
|
||||
operation_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
status VARCHAR(10) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: cultural_relics */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE cultural_relics
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
relic_code VARCHAR(50) NOT NULL,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
era VARCHAR(100),
|
||||
material VARCHAR(100),
|
||||
size VARCHAR(100),
|
||||
discovery_site VARCHAR(200),
|
||||
current_location VARCHAR(200),
|
||||
description TEXT,
|
||||
cultural_level VARCHAR(50),
|
||||
preservation_status VARCHAR(50),
|
||||
created_by INT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_by INT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_relic_code (relic_code),
|
||||
FOREIGN KEY (created_by) REFERENCES users (id),
|
||||
FOREIGN KEY (updated_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: relic_multi_mode */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE relic_multi_mode
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
relic_id INT NOT NULL,
|
||||
resource_type VARCHAR(20) NOT NULL,
|
||||
resource_name VARCHAR(200) NOT NULL,
|
||||
resource_path VARCHAR(500) NOT NULL,
|
||||
file_size BIGINT,
|
||||
file_format VARCHAR(20),
|
||||
description TEXT,
|
||||
upload_by INT NOT NULL,
|
||||
upload_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
is_approved TINYINT NOT NULL DEFAULT 0,
|
||||
approved_by INT,
|
||||
approved_time DATETIME,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (relic_id) REFERENCES cultural_relics (id),
|
||||
FOREIGN KEY (upload_by) REFERENCES users (id),
|
||||
FOREIGN KEY (approved_by) REFERENCES users (id)
|
||||
);
|
||||
@ -0,0 +1,98 @@
|
||||
/*==============================================================*/
|
||||
/* Table: entity_relations */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE entity_relations
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
source_entity_id INT NOT NULL,
|
||||
target_entity_id INT NOT NULL,
|
||||
relation_type VARCHAR(50) NOT NULL,
|
||||
relation_name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
confidence DECIMAL(3,2),
|
||||
created_by INT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_by INT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (source_entity_id) REFERENCES cultural_relics (id),
|
||||
FOREIGN KEY (target_entity_id) REFERENCES cultural_relics (id),
|
||||
FOREIGN KEY (created_by) REFERENCES users (id),
|
||||
FOREIGN KEY (updated_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: ai_messages */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE ai_messages
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
user_id INT NOT NULL,
|
||||
session_id VARCHAR(100) NOT NULL,
|
||||
message_type VARCHAR(10) NOT NULL,
|
||||
message_content TEXT NOT NULL,
|
||||
ai_response TEXT,
|
||||
response_time INT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
is_satisfied TINYINT,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: ai_research_reports */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE ai_research_reports
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
report_title VARCHAR(200) NOT NULL,
|
||||
report_type VARCHAR(50) NOT NULL,
|
||||
report_content TEXT NOT NULL,
|
||||
generated_by INT NOT NULL,
|
||||
generated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
data_source TEXT,
|
||||
keywords VARCHAR(500),
|
||||
download_count INT NOT NULL DEFAULT 0,
|
||||
is_public TINYINT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (generated_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: user_defined_entities */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE user_defined_entities
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
entity_name VARCHAR(200) NOT NULL,
|
||||
entity_type VARCHAR(50) NOT NULL,
|
||||
description TEXT,
|
||||
properties JSON,
|
||||
created_by INT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_by INT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
status VARCHAR(10) NOT NULL DEFAULT 'pending',
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (created_by) REFERENCES users (id),
|
||||
FOREIGN KEY (updated_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: user_defined_relations */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE user_defined_relations
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
source_entity_id INT NOT NULL,
|
||||
target_entity_id INT NOT NULL,
|
||||
relation_name VARCHAR(100) NOT NULL,
|
||||
relation_description TEXT,
|
||||
created_by INT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
status VARCHAR(10) NOT NULL DEFAULT 'pending',
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (source_entity_id) REFERENCES user_defined_entities (id),
|
||||
FOREIGN KEY (target_entity_id) REFERENCES user_defined_entities (id),
|
||||
FOREIGN KEY (created_by) REFERENCES users (id)
|
||||
);
|
||||
@ -0,0 +1,57 @@
|
||||
/*==============================================================*/
|
||||
/* Table: modeling_projects */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE modeling_projects
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
project_name VARCHAR(200) NOT NULL,
|
||||
project_description TEXT,
|
||||
created_by INT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'drafting',
|
||||
is_collaborative TINYINT NOT NULL DEFAULT 0,
|
||||
collaborators JSON,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (created_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: modeling_versions */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE modeling_versions
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
project_id INT NOT NULL,
|
||||
version_number VARCHAR(20) NOT NULL,
|
||||
version_description TEXT,
|
||||
model_data JSON NOT NULL,
|
||||
created_by INT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
is_current TINYINT NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (project_id) REFERENCES modeling_projects (id),
|
||||
FOREIGN KEY (created_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: kg_update_requests */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE kg_update_requests
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
request_type VARCHAR(20) NOT NULL,
|
||||
target_type VARCHAR(20) NOT NULL,
|
||||
target_id INT,
|
||||
request_data JSON,
|
||||
request_reason TEXT,
|
||||
requested_by INT NOT NULL,
|
||||
requested_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
processed_by INT,
|
||||
processed_at DATETIME,
|
||||
process_comment TEXT,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (requested_by) REFERENCES users (id),
|
||||
FOREIGN KEY (processed_by) REFERENCES users (id)
|
||||
);
|
||||
@ -0,0 +1,50 @@
|
||||
/*==============================================================*/
|
||||
/* Table: messages */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE messages
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
sender_id INT NOT NULL,
|
||||
receiver_id INT NOT NULL,
|
||||
message_type VARCHAR(20) NOT NULL,
|
||||
message_title VARCHAR(200),
|
||||
message_content TEXT NOT NULL,
|
||||
sent_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
is_read TINYINT NOT NULL DEFAULT 0,
|
||||
read_at DATETIME,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (sender_id) REFERENCES users (id),
|
||||
FOREIGN KEY (receiver_id) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: search_history */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE search_history
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
user_id INT NOT NULL,
|
||||
search_keywords VARCHAR(500) NOT NULL,
|
||||
search_filters JSON,
|
||||
search_results INT,
|
||||
search_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
search_duration INT,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: user_favorites */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE user_favorites
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
user_id INT NOT NULL,
|
||||
favorite_type VARCHAR(20) NOT NULL,
|
||||
favorite_target_id INT NOT NULL,
|
||||
favorite_title VARCHAR(200) NOT NULL,
|
||||
favorite_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
tags VARCHAR(500),
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
||||
);
|
||||
@ -0,0 +1,54 @@
|
||||
/*==============================================================*/
|
||||
/* Table: feedback */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE feedback
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
user_id INT NOT NULL,
|
||||
feedback_type VARCHAR(20) NOT NULL,
|
||||
feedback_title VARCHAR(200) NOT NULL,
|
||||
feedback_content TEXT NOT NULL,
|
||||
contact_info VARCHAR(100),
|
||||
submitted_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
processed_by INT,
|
||||
processed_at DATETIME,
|
||||
process_result TEXT,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (user_id) REFERENCES users (id),
|
||||
FOREIGN KEY (processed_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: model_review_records */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE model_review_records
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
project_id INT NOT NULL,
|
||||
reviewer_id INT NOT NULL,
|
||||
review_result VARCHAR(20) NOT NULL,
|
||||
review_comment TEXT,
|
||||
reviewed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
revision_required TINYINT NOT NULL DEFAULT 0,
|
||||
revision_deadline DATETIME,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (project_id) REFERENCES modeling_projects (id),
|
||||
FOREIGN KEY (reviewer_id) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: content_review_logs */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE content_review_logs
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
content_type VARCHAR(20) NOT NULL,
|
||||
content_id INT NOT NULL,
|
||||
reviewer_id INT NOT NULL,
|
||||
review_result VARCHAR(20) NOT NULL,
|
||||
review_comment TEXT,
|
||||
reviewed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (reviewer_id) REFERENCES users (id)
|
||||
);
|
||||
@ -0,0 +1,54 @@
|
||||
/*==============================================================*/
|
||||
/* Table: user_management_logs */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE user_management_logs
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
admin_id INT NOT NULL,
|
||||
target_user_id INT NOT NULL,
|
||||
operation_type VARCHAR(20) NOT NULL,
|
||||
operation_detail TEXT,
|
||||
operation_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ip_address VARCHAR(45),
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (admin_id) REFERENCES users (id),
|
||||
FOREIGN KEY (target_user_id) REFERENCES users (id)
|
||||
);
|
||||
|
||||
/*==============================================================*/
|
||||
/* Table: audit_trails */
|
||||
/*==============================================================*/
|
||||
CREATE TABLE audit_trails
|
||||
(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
user_id INT NOT NULL,
|
||||
event_type VARCHAR(50) NOT NULL,
|
||||
event_description TEXT,
|
||||
event_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ip_address VARCHAR(45),
|
||||
user_agent TEXT,
|
||||
resource_accessed VARCHAR(500),
|
||||
operation_result VARCHAR(20) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
||||
);
|
||||
|
||||
-- 创建索引以提高查询性能
|
||||
CREATE INDEX idx_users_user_type ON users(user_type);
|
||||
CREATE INDEX idx_users_status ON users(status);
|
||||
CREATE INDEX idx_login_operation_log_user_id ON login_operation_log(user_id);
|
||||
CREATE INDEX idx_login_operation_log_operation_time ON login_operation_log(operation_time);
|
||||
CREATE INDEX idx_cultural_relics_relic_code ON cultural_relics(relic_code);
|
||||
CREATE INDEX idx_cultural_relics_era ON cultural_relics(era);
|
||||
CREATE INDEX idx_relic_multi_mode_relic_id ON relic_multi_mode(relic_id);
|
||||
CREATE INDEX idx_relic_multi_mode_resource_type ON relic_multi_mode(resource_type);
|
||||
CREATE INDEX idx_entity_relations_source_target ON entity_relations(source_entity_id, target_entity_id);
|
||||
CREATE INDEX idx_ai_messages_user_id ON ai_messages(user_id);
|
||||
CREATE INDEX idx_ai_messages_session_id ON ai_messages(session_id);
|
||||
CREATE INDEX idx_ai_research_reports_generated_by ON ai_research_reports(generated_by);
|
||||
CREATE INDEX idx_ai_research_reports_is_public ON ai_research_reports(is_public);
|
||||
CREATE INDEX idx_user_favorites_user_id ON user_favorites(user_id);
|
||||
CREATE INDEX idx_search_history_user_id ON search_history(user_id);
|
||||
CREATE INDEX idx_search_history_search_time ON search_history(search_time);
|
||||
CREATE INDEX idx_audit_trails_user_id ON audit_trails(user_id);
|
||||
CREATE INDEX idx_audit_trails_event_time ON audit_trails(event_time);
|
||||
Loading…
Reference in new issue