diff --git a/backend/src/main/java/com/innovation/platform/controller/UserController.java b/backend/src/main/java/com/innovation/platform/controller/UserController.java new file mode 100644 index 0000000..1dacb13 --- /dev/null +++ b/backend/src/main/java/com/innovation/platform/controller/UserController.java @@ -0,0 +1,161 @@ +package com.innovation.platform.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.innovation.platform.common.Result; +import com.innovation.platform.entity.SysUser; +import com.innovation.platform.service.SysUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 用户管理控制器 + */ +@Tag(name = "用户管理", description = "用户 CRUD 接口") +@RestController +@RequestMapping("/api/users") +@RequiredArgsConstructor +public class UserController { + + private final SysUserService sysUserService; + + @Operation(summary = "获取用户列表(分页)") + @GetMapping + public Result> getUserList( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String keyword, + @RequestParam(required = false) Integer roleType, + @RequestParam(required = false) Integer status + ) { + Page userPage = sysUserService.getUserList(page, size, keyword, roleType, status); + return Result.success("查询成功", toPageResult(userPage)); + } + + @Operation(summary = "获取用户详情") + @GetMapping("/{id}") + public Result getUserById(@PathVariable Long id) { + SysUser user = sysUserService.getById(id); + if (user == null) { + return Result.error("用户不存在"); + } + return Result.success("查询成功", user); + } + + @Operation(summary = "创建用户") + @PostMapping + public Result createUser(@RequestBody CreateUserRequest request) { + try { + SysUser user = sysUserService.createUser(request); + return Result.success("创建成功", user); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @Operation(summary = "更新用户") + @PutMapping("/{id}") + public Result updateUser(@PathVariable Long id, @RequestBody UpdateUserRequest request) { + try { + SysUser user = sysUserService.updateUser(id, request); + return Result.success("更新成功", user); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @Operation(summary = "删除用户") + @DeleteMapping("/{id}") + public Result deleteUser(@PathVariable Long id) { + try { + sysUserService.deleteUser(id); + return Result.success("删除成功", null); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @Operation(summary = "获取教师列表") + @GetMapping("/teachers") + public Result> getTeacherList() { + List teachers = sysUserService.getTeacherList(); + return Result.success("查询成功", teachers); + } + + @Operation(summary = "修改密码") + @PostMapping("/change-password") + public Result changePassword( + @RequestParam String oldPassword, + @RequestParam String newPassword + ) { + try { + sysUserService.changePassword(oldPassword, newPassword); + return Result.success("修改成功", null); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @Operation(summary = "更新个人资料") + @PutMapping("/profile") + public Result updateProfile(@RequestBody UpdateProfileRequest request) { + try { + SysUser user = sysUserService.updateProfile(request); + return Result.success("更新成功", user); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + private PageResult toPageResult(Page page) { + PageResult result = new PageResult<>(); + result.setList(page.getRecords()); + result.setTotal(page.getTotal()); + result.setPage((int) page.getCurrent()); + result.setSize((int) page.getSize()); + return result; + } + + @Data + public static class PageResult { + private List list; + private Long total; + private Integer page; + private Integer size; + } + + @Data + public static class CreateUserRequest { + private String username; + private String password; + private String realName; + private Integer gender; + private String phone; + private String email; + private String avatar; + private Integer roleType; + } + + @Data + public static class UpdateUserRequest { + private String realName; + private Integer gender; + private String phone; + private String email; + private String avatar; + private Integer roleType; + private Integer status; + } + + @Data + public static class UpdateProfileRequest { + private String realName; + private String phone; + private String email; + private String avatar; + } +} diff --git a/backend/src/main/java/com/innovation/platform/service/SysUserService.java b/backend/src/main/java/com/innovation/platform/service/SysUserService.java index ddc1bcf..3a02566 100755 --- a/backend/src/main/java/com/innovation/platform/service/SysUserService.java +++ b/backend/src/main/java/com/innovation/platform/service/SysUserService.java @@ -1,10 +1,16 @@ package com.innovation.platform.service; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.innovation.platform.controller.UserController.CreateUserRequest; +import com.innovation.platform.controller.UserController.UpdateProfileRequest; +import com.innovation.platform.controller.UserController.UpdateUserRequest; import com.innovation.platform.dto.LoginRequest; import com.innovation.platform.dto.LoginResponse; import com.innovation.platform.dto.RegisterRequest; import com.innovation.platform.entity.SysUser; +import java.util.List; + /** * 用户服务接口 */ @@ -31,7 +37,42 @@ public interface SysUserService { SysUser getByUsername(String username); /** - * 根据ID查询用户 + * 根据 ID 查询用户 */ SysUser getById(Long id); + + /** + * 获取用户列表(分页) + */ + Page getUserList(Integer page, Integer size, String keyword, Integer roleType, Integer status); + + /** + * 创建用户 + */ + SysUser createUser(CreateUserRequest request); + + /** + * 更新用户 + */ + SysUser updateUser(Long id, UpdateUserRequest request); + + /** + * 删除用户 + */ + void deleteUser(Long id); + + /** + * 获取教师列表 + */ + List getTeacherList(); + + /** + * 修改密码 + */ + void changePassword(String oldPassword, String newPassword); + + /** + * 更新个人资料 + */ + SysUser updateProfile(UpdateProfileRequest request); } diff --git a/backend/src/main/java/com/innovation/platform/service/impl/SysUserServiceImpl.java b/backend/src/main/java/com/innovation/platform/service/impl/SysUserServiceImpl.java index aa39168..d2a40b1 100755 --- a/backend/src/main/java/com/innovation/platform/service/impl/SysUserServiceImpl.java +++ b/backend/src/main/java/com/innovation/platform/service/impl/SysUserServiceImpl.java @@ -3,6 +3,10 @@ package com.innovation.platform.service.impl; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.crypto.digest.BCrypt; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.innovation.platform.controller.UserController.CreateUserRequest; +import com.innovation.platform.controller.UserController.UpdateProfileRequest; +import com.innovation.platform.controller.UserController.UpdateUserRequest; import com.innovation.platform.dto.LoginRequest; import com.innovation.platform.dto.LoginResponse; import com.innovation.platform.dto.RegisterRequest; @@ -12,6 +16,9 @@ import com.innovation.platform.service.SysUserService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.util.List; /** * 用户服务实现类 @@ -93,4 +100,169 @@ public class SysUserServiceImpl implements SysUserService { public SysUser getById(Long id) { return sysUserMapper.selectById(id); } + + @Override + public Page getUserList(Integer page, Integer size, String keyword, Integer roleType, Integer status) { + Page userPage = new Page<>(page, size); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + // 关键词搜索(用户名、姓名、手机号) + if (StringUtils.hasText(keyword)) { + wrapper.and(w -> w + .like(SysUser::getUsername, keyword) + .or() + .like(SysUser::getRealName, keyword) + .or() + .like(SysUser::getPhone, keyword) + ); + } + + // 角色类型过滤 + if (roleType != null) { + wrapper.eq(SysUser::getRoleType, roleType); + } + + // 状态过滤 + if (status != null) { + wrapper.eq(SysUser::getStatus, status); + } + + return sysUserMapper.selectPage(userPage, wrapper); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public SysUser createUser(CreateUserRequest request) { + // 检查用户名是否已存在 + if (getByUsername(request.getUsername()) != null) { + throw new RuntimeException("用户名已存在"); + } + + // 检查邮箱是否已存在 + if (StringUtils.hasText(request.getEmail()) && getByEmail(request.getEmail()) != null) { + throw new RuntimeException("邮箱已被使用"); + } + + // 创建用户 + SysUser user = new SysUser(); + user.setUsername(request.getUsername()); + user.setPassword(BCrypt.hashpw(request.getPassword() != null ? request.getPassword() : "123456")); + user.setRealName(request.getRealName()); + user.setGender(request.getGender()); + user.setPhone(request.getPhone()); + user.setEmail(request.getEmail()); + user.setAvatar(request.getAvatar()); + user.setRoleType(request.getRoleType() != null ? request.getRoleType() : 0); + user.setStatus(1); + + sysUserMapper.insert(user); + return user; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public SysUser updateUser(Long id, UpdateUserRequest request) { + SysUser user = sysUserMapper.selectById(id); + if (user == null) { + throw new RuntimeException("用户不存在"); + } + + // 检查邮箱是否已被其他用户使用 + if (StringUtils.hasText(request.getEmail())) { + SysUser existUser = getByEmail(request.getEmail()); + if (existUser != null && !existUser.getId().equals(id)) { + throw new RuntimeException("邮箱已被其他用户使用"); + } + user.setEmail(request.getEmail()); + } + + user.setRealName(request.getRealName()); + user.setGender(request.getGender()); + user.setPhone(request.getPhone()); + user.setAvatar(request.getAvatar()); + user.setRoleType(request.getRoleType()); + user.setStatus(request.getStatus()); + + sysUserMapper.updateById(user); + return user; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteUser(Long id) { + SysUser user = sysUserMapper.selectById(id); + if (user == null) { + throw new RuntimeException("用户不存在"); + } + + sysUserMapper.deleteById(id); + } + + @Override + public List getTeacherList() { + return sysUserMapper.selectList( + new LambdaQueryWrapper() + .eq(SysUser::getRoleType, 1) // 1 = 教师 + .eq(SysUser::getStatus, 1) // 只查询启用的用户 + ); + } + + @Override + public void changePassword(String oldPassword, String newPassword) { + // 获取当前登录用户 + Long userId = StpUtil.getLoginIdAsLong(); + SysUser user = sysUserMapper.selectById(userId); + + if (user == null) { + throw new RuntimeException("用户不存在"); + } + + // 验证旧密码 + if (!BCrypt.checkpw(oldPassword, user.getPassword())) { + throw new RuntimeException("旧密码错误"); + } + + // 更新密码 + user.setPassword(BCrypt.hashpw(newPassword)); + sysUserMapper.updateById(user); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public SysUser updateProfile(UpdateProfileRequest request) { + // 获取当前登录用户 + Long userId = StpUtil.getLoginIdAsLong(); + SysUser user = sysUserMapper.selectById(userId); + + if (user == null) { + throw new RuntimeException("用户不存在"); + } + + // 检查邮箱是否已被其他用户使用 + if (StringUtils.hasText(request.getEmail())) { + SysUser existUser = getByEmail(request.getEmail()); + if (existUser != null && !existUser.getId().equals(userId)) { + throw new RuntimeException("邮箱已被其他用户使用"); + } + user.setEmail(request.getEmail()); + } + + user.setRealName(request.getRealName()); + user.setPhone(request.getPhone()); + user.setAvatar(request.getAvatar()); + + sysUserMapper.updateById(user); + return user; + } + + /** + * 根据邮箱查询用户 + */ + private SysUser getByEmail(String email) { + return sysUserMapper.selectOne( + new LambdaQueryWrapper() + .eq(SysUser::getEmail, email) + ); + } } diff --git a/backend/src/main/resources/data.sql b/backend/src/main/resources/data.sql index 1455eb6..416ef47 100755 --- a/backend/src/main/resources/data.sql +++ b/backend/src/main/resources/data.sql @@ -1,38 +1,38 @@ -- 预埋测试数据 -- 1. 管理员账号 (密码: admin123) -INSERT INTO sys_user (username, password, real_name, gender, role_type, status) VALUES +INSERT IGNORE INTO sys_user (username, password, real_name, gender, role_type, status) VALUES ('admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '系统管理员', 1, 3, 1); -- 2. 教师账号 (密码: teacher123) -INSERT INTO sys_user (username, password, real_name, gender, role_type, status) VALUES +INSERT IGNORE INTO sys_user (username, password, real_name, gender, role_type, status) VALUES ('teacher001', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '张教授', 1, 2, 1), ('teacher002', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '李老师', 2, 2, 1); -- 3. 学生账号 (密码: student123) -INSERT INTO sys_user (username, password, real_name, gender, role_type, status) VALUES +INSERT IGNORE INTO sys_user (username, password, real_name, gender, role_type, status) VALUES ('student001', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '王小明', 1, 1, 1), ('student002', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '李小红', 2, 1, 1), ('student003', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '张小华', 1, 1, 1); -- 4. 教师信息 -INSERT INTO teacher_info (user_id, teacher_no, college, title, research_field) VALUES +INSERT IGNORE INTO teacher_info (user_id, teacher_no, college, title, research_field) VALUES (2, 'T2024001', '计算机学院', '教授', '人工智能'), (3, 'T2024002', '计算机学院', '副教授', '大数据'); -- 5. 学生信息 -INSERT INTO stu_info (user_id, student_no, college, major, grade, class_name, advisor_id) VALUES +INSERT IGNORE INTO stu_info (user_id, student_no, college, major, grade, class_name, advisor_id) VALUES (4, 'S2021001', '计算机学院', '计算机科学与技术', '2021', '计科2101', 2), (5, 'S2021002', '计算机学院', '软件工程', '2021', '软工2101', 2), (6, 'S2022001', '计算机学院', '计算机科学与技术', '2022', '计科2201', 3); -- 6. 测试项目 -INSERT INTO project (project_no, project_name, project_type, project_level, leader_id, advisor_id, description, status) VALUES +INSERT IGNORE INTO project (project_no, project_name, project_type, project_level, leader_id, advisor_id, description, status) VALUES ('PRJ2024001', '基于AI的智能问答系统', 1, 2, 4, 2, '本项目旨在开发一个基于大语言模型的智能问答系统', 3), ('PRJ2024002', '校园二手交易平台', 2, 1, 5, 3, '搭建一个面向高校学生的二手物品交易平台', 1); -- 7. 项目成员 -INSERT INTO project_member (project_id, user_id, member_order, role) VALUES +INSERT IGNORE INTO project_member (project_id, user_id, member_order, role) VALUES (1, 4, 1, 2), (1, 5, 2, 1), (2, 5, 1, 2), diff --git a/backend/src/main/resources/db/migration/V2__add_user_unique_constraints.sql b/backend/src/main/resources/db/migration/V2__add_user_unique_constraints.sql new file mode 100644 index 0000000..c2181c4 --- /dev/null +++ b/backend/src/main/resources/db/migration/V2__add_user_unique_constraints.sql @@ -0,0 +1,40 @@ +-- V2: 为 sys_user 表添加唯一约束 +-- 执行时间:2026-03-13 + +-- 1. 先清理可能存在的重复数据(保留 ID 最小的记录) +-- 删除重复的用户名(保留 id 最小的) +DELETE FROM sys_user +WHERE id NOT IN ( + SELECT id FROM ( + SELECT MIN(id) as id + FROM sys_user + WHERE username IS NOT NULL + GROUP BY username + ) as tmp +); + +-- 删除重复的邮箱(保留 id 最小的) +DELETE FROM sys_user +WHERE id NOT IN ( + SELECT id FROM ( + SELECT MIN(id) as id + FROM sys_user + WHERE email IS NOT NULL + GROUP BY email + ) as tmp +); + +-- 2. 为 username 添加唯一约束 +ALTER TABLE sys_user +ADD CONSTRAINT uk_username UNIQUE (username); + +-- 3. 为 email 添加唯一约束 +ALTER TABLE sys_user +ADD CONSTRAINT uk_email UNIQUE (email); + +-- 4. 为 phone 添加索引(不唯一,因为可能有没有手机号的情况) +CREATE INDEX idx_phone ON sys_user(phone); + +-- 5. 为 role_type 和 status 添加索引,优化查询性能 +CREATE INDEX idx_role_type ON sys_user(role_type); +CREATE INDEX idx_status ON sys_user(status); diff --git a/backend/src/main/resources/schema.sql b/backend/src/main/resources/schema.sql index 65dee80..aa62346 100755 --- a/backend/src/main/resources/schema.sql +++ b/backend/src/main/resources/schema.sql @@ -16,7 +16,11 @@ CREATE TABLE IF NOT EXISTS sys_user ( update_by BIGINT DEFAULT NULL, deleted TINYINT DEFAULT 0, PRIMARY KEY (id), - UNIQUE KEY uk_username (username) + UNIQUE KEY uk_username (username), + UNIQUE KEY uk_email (email), + KEY idx_phone (phone), + KEY idx_role_type (role_type), + KEY idx_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建学生信息表 diff --git a/backend/target/classes/com/innovation/platform/InnovationPlatformApplication.class b/backend/target/classes/com/innovation/platform/InnovationPlatformApplication.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/common/PageResult.class b/backend/target/classes/com/innovation/platform/common/PageResult.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/common/Result.class b/backend/target/classes/com/innovation/platform/common/Result.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/config/SaTokenConfig.class b/backend/target/classes/com/innovation/platform/config/SaTokenConfig.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/controller/AuthController.class b/backend/target/classes/com/innovation/platform/controller/AuthController.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/controller/ProjectController.class b/backend/target/classes/com/innovation/platform/controller/ProjectController.class new file mode 100644 index 0000000..94c0c44 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/controller/ProjectController.class differ diff --git a/backend/target/classes/com/innovation/platform/controller/UserController$CreateUserRequest.class b/backend/target/classes/com/innovation/platform/controller/UserController$CreateUserRequest.class new file mode 100644 index 0000000..2a89086 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/controller/UserController$CreateUserRequest.class differ diff --git a/backend/target/classes/com/innovation/platform/controller/UserController$PageResult.class b/backend/target/classes/com/innovation/platform/controller/UserController$PageResult.class new file mode 100644 index 0000000..8065e22 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/controller/UserController$PageResult.class differ diff --git a/backend/target/classes/com/innovation/platform/controller/UserController$UpdateProfileRequest.class b/backend/target/classes/com/innovation/platform/controller/UserController$UpdateProfileRequest.class new file mode 100644 index 0000000..5c763c6 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/controller/UserController$UpdateProfileRequest.class differ diff --git a/backend/target/classes/com/innovation/platform/controller/UserController$UpdateUserRequest.class b/backend/target/classes/com/innovation/platform/controller/UserController$UpdateUserRequest.class new file mode 100644 index 0000000..271bbe4 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/controller/UserController$UpdateUserRequest.class differ diff --git a/backend/target/classes/com/innovation/platform/controller/UserController.class b/backend/target/classes/com/innovation/platform/controller/UserController.class new file mode 100644 index 0000000..436004b Binary files /dev/null and b/backend/target/classes/com/innovation/platform/controller/UserController.class differ diff --git a/backend/target/classes/com/innovation/platform/dto/LoginRequest.class b/backend/target/classes/com/innovation/platform/dto/LoginRequest.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/dto/LoginResponse$LoginResponseBuilder.class b/backend/target/classes/com/innovation/platform/dto/LoginResponse$LoginResponseBuilder.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/dto/LoginResponse.class b/backend/target/classes/com/innovation/platform/dto/LoginResponse.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/dto/ProjectQueryRequest.class b/backend/target/classes/com/innovation/platform/dto/ProjectQueryRequest.class new file mode 100644 index 0000000..f76d49a Binary files /dev/null and b/backend/target/classes/com/innovation/platform/dto/ProjectQueryRequest.class differ diff --git a/backend/target/classes/com/innovation/platform/dto/ProjectRequest.class b/backend/target/classes/com/innovation/platform/dto/ProjectRequest.class new file mode 100644 index 0000000..c971fe7 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/dto/ProjectRequest.class differ diff --git a/backend/target/classes/com/innovation/platform/dto/ProjectResponse$ProjectResponseBuilder.class b/backend/target/classes/com/innovation/platform/dto/ProjectResponse$ProjectResponseBuilder.class new file mode 100644 index 0000000..80e655b Binary files /dev/null and b/backend/target/classes/com/innovation/platform/dto/ProjectResponse$ProjectResponseBuilder.class differ diff --git a/backend/target/classes/com/innovation/platform/dto/ProjectResponse.class b/backend/target/classes/com/innovation/platform/dto/ProjectResponse.class new file mode 100644 index 0000000..439560c Binary files /dev/null and b/backend/target/classes/com/innovation/platform/dto/ProjectResponse.class differ diff --git a/backend/target/classes/com/innovation/platform/dto/RegisterRequest.class b/backend/target/classes/com/innovation/platform/dto/RegisterRequest.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/Achievement.class b/backend/target/classes/com/innovation/platform/entity/Achievement.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/AchievementAttachment.class b/backend/target/classes/com/innovation/platform/entity/AchievementAttachment.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/BaseEntity.class b/backend/target/classes/com/innovation/platform/entity/BaseEntity.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/Project.class b/backend/target/classes/com/innovation/platform/entity/Project.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/ProjectAttachment.class b/backend/target/classes/com/innovation/platform/entity/ProjectAttachment.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/ProjectMember.class b/backend/target/classes/com/innovation/platform/entity/ProjectMember.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/Review.class b/backend/target/classes/com/innovation/platform/entity/Review.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/ReviewScoreItem.class b/backend/target/classes/com/innovation/platform/entity/ReviewScoreItem.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/StuInfo.class b/backend/target/classes/com/innovation/platform/entity/StuInfo.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/SysConfig.class b/backend/target/classes/com/innovation/platform/entity/SysConfig.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/SysLog.class b/backend/target/classes/com/innovation/platform/entity/SysLog.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/SysUser.class b/backend/target/classes/com/innovation/platform/entity/SysUser.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/entity/TeacherInfo.class b/backend/target/classes/com/innovation/platform/entity/TeacherInfo.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/exception/GlobalExceptionHandler.class b/backend/target/classes/com/innovation/platform/exception/GlobalExceptionHandler.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/mapper/ProjectMapper.class b/backend/target/classes/com/innovation/platform/mapper/ProjectMapper.class new file mode 100644 index 0000000..00dddb8 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/mapper/ProjectMapper.class differ diff --git a/backend/target/classes/com/innovation/platform/mapper/SysUserMapper.class b/backend/target/classes/com/innovation/platform/mapper/SysUserMapper.class old mode 100755 new mode 100644 diff --git a/backend/target/classes/com/innovation/platform/service/ProjectService.class b/backend/target/classes/com/innovation/platform/service/ProjectService.class new file mode 100644 index 0000000..ae44d84 Binary files /dev/null and b/backend/target/classes/com/innovation/platform/service/ProjectService.class differ diff --git a/backend/target/classes/com/innovation/platform/service/SysUserService.class b/backend/target/classes/com/innovation/platform/service/SysUserService.class old mode 100755 new mode 100644 index 89a924a..19b7669 Binary files a/backend/target/classes/com/innovation/platform/service/SysUserService.class and b/backend/target/classes/com/innovation/platform/service/SysUserService.class differ diff --git a/backend/target/classes/com/innovation/platform/service/impl/ProjectServiceImpl.class b/backend/target/classes/com/innovation/platform/service/impl/ProjectServiceImpl.class new file mode 100644 index 0000000..c3555dc Binary files /dev/null and b/backend/target/classes/com/innovation/platform/service/impl/ProjectServiceImpl.class differ diff --git a/backend/target/classes/com/innovation/platform/service/impl/SysUserServiceImpl.class b/backend/target/classes/com/innovation/platform/service/impl/SysUserServiceImpl.class old mode 100755 new mode 100644 index da5089f..5babcbb Binary files a/backend/target/classes/com/innovation/platform/service/impl/SysUserServiceImpl.class and b/backend/target/classes/com/innovation/platform/service/impl/SysUserServiceImpl.class differ diff --git a/backend/target/classes/data.sql b/backend/target/classes/data.sql index 1455eb6..416ef47 100755 --- a/backend/target/classes/data.sql +++ b/backend/target/classes/data.sql @@ -1,38 +1,38 @@ -- 预埋测试数据 -- 1. 管理员账号 (密码: admin123) -INSERT INTO sys_user (username, password, real_name, gender, role_type, status) VALUES +INSERT IGNORE INTO sys_user (username, password, real_name, gender, role_type, status) VALUES ('admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '系统管理员', 1, 3, 1); -- 2. 教师账号 (密码: teacher123) -INSERT INTO sys_user (username, password, real_name, gender, role_type, status) VALUES +INSERT IGNORE INTO sys_user (username, password, real_name, gender, role_type, status) VALUES ('teacher001', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '张教授', 1, 2, 1), ('teacher002', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '李老师', 2, 2, 1); -- 3. 学生账号 (密码: student123) -INSERT INTO sys_user (username, password, real_name, gender, role_type, status) VALUES +INSERT IGNORE INTO sys_user (username, password, real_name, gender, role_type, status) VALUES ('student001', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '王小明', 1, 1, 1), ('student002', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '李小红', 2, 1, 1), ('student003', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt9hQIu', '张小华', 1, 1, 1); -- 4. 教师信息 -INSERT INTO teacher_info (user_id, teacher_no, college, title, research_field) VALUES +INSERT IGNORE INTO teacher_info (user_id, teacher_no, college, title, research_field) VALUES (2, 'T2024001', '计算机学院', '教授', '人工智能'), (3, 'T2024002', '计算机学院', '副教授', '大数据'); -- 5. 学生信息 -INSERT INTO stu_info (user_id, student_no, college, major, grade, class_name, advisor_id) VALUES +INSERT IGNORE INTO stu_info (user_id, student_no, college, major, grade, class_name, advisor_id) VALUES (4, 'S2021001', '计算机学院', '计算机科学与技术', '2021', '计科2101', 2), (5, 'S2021002', '计算机学院', '软件工程', '2021', '软工2101', 2), (6, 'S2022001', '计算机学院', '计算机科学与技术', '2022', '计科2201', 3); -- 6. 测试项目 -INSERT INTO project (project_no, project_name, project_type, project_level, leader_id, advisor_id, description, status) VALUES +INSERT IGNORE INTO project (project_no, project_name, project_type, project_level, leader_id, advisor_id, description, status) VALUES ('PRJ2024001', '基于AI的智能问答系统', 1, 2, 4, 2, '本项目旨在开发一个基于大语言模型的智能问答系统', 3), ('PRJ2024002', '校园二手交易平台', 2, 1, 5, 3, '搭建一个面向高校学生的二手物品交易平台', 1); -- 7. 项目成员 -INSERT INTO project_member (project_id, user_id, member_order, role) VALUES +INSERT IGNORE INTO project_member (project_id, user_id, member_order, role) VALUES (1, 4, 1, 2), (1, 5, 2, 1), (2, 5, 1, 2), diff --git a/backend/target/classes/db/migration/V2__add_user_unique_constraints.sql b/backend/target/classes/db/migration/V2__add_user_unique_constraints.sql new file mode 100644 index 0000000..c2181c4 --- /dev/null +++ b/backend/target/classes/db/migration/V2__add_user_unique_constraints.sql @@ -0,0 +1,40 @@ +-- V2: 为 sys_user 表添加唯一约束 +-- 执行时间:2026-03-13 + +-- 1. 先清理可能存在的重复数据(保留 ID 最小的记录) +-- 删除重复的用户名(保留 id 最小的) +DELETE FROM sys_user +WHERE id NOT IN ( + SELECT id FROM ( + SELECT MIN(id) as id + FROM sys_user + WHERE username IS NOT NULL + GROUP BY username + ) as tmp +); + +-- 删除重复的邮箱(保留 id 最小的) +DELETE FROM sys_user +WHERE id NOT IN ( + SELECT id FROM ( + SELECT MIN(id) as id + FROM sys_user + WHERE email IS NOT NULL + GROUP BY email + ) as tmp +); + +-- 2. 为 username 添加唯一约束 +ALTER TABLE sys_user +ADD CONSTRAINT uk_username UNIQUE (username); + +-- 3. 为 email 添加唯一约束 +ALTER TABLE sys_user +ADD CONSTRAINT uk_email UNIQUE (email); + +-- 4. 为 phone 添加索引(不唯一,因为可能有没有手机号的情况) +CREATE INDEX idx_phone ON sys_user(phone); + +-- 5. 为 role_type 和 status 添加索引,优化查询性能 +CREATE INDEX idx_role_type ON sys_user(role_type); +CREATE INDEX idx_status ON sys_user(status); diff --git a/backend/target/classes/schema.sql b/backend/target/classes/schema.sql index 65dee80..aa62346 100755 --- a/backend/target/classes/schema.sql +++ b/backend/target/classes/schema.sql @@ -16,7 +16,11 @@ CREATE TABLE IF NOT EXISTS sys_user ( update_by BIGINT DEFAULT NULL, deleted TINYINT DEFAULT 0, PRIMARY KEY (id), - UNIQUE KEY uk_username (username) + UNIQUE KEY uk_username (username), + UNIQUE KEY uk_email (email), + KEY idx_phone (phone), + KEY idx_role_type (role_type), + KEY idx_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 创建学生信息表 diff --git a/backend/target/innovation-platform-1.0.0.jar b/backend/target/innovation-platform-1.0.0.jar deleted file mode 100755 index edfd390..0000000 Binary files a/backend/target/innovation-platform-1.0.0.jar and /dev/null differ diff --git a/backend/target/innovation-platform-1.0.0.jar.original b/backend/target/innovation-platform-1.0.0.jar.original deleted file mode 100755 index b764df0..0000000 Binary files a/backend/target/innovation-platform-1.0.0.jar.original and /dev/null differ diff --git a/backend/target/maven-archiver/pom.properties b/backend/target/maven-archiver/pom.properties deleted file mode 100755 index 390a8a5..0000000 --- a/backend/target/maven-archiver/pom.properties +++ /dev/null @@ -1,3 +0,0 @@ -artifactId=innovation-platform -groupId=com.innovation -version=1.0.0 diff --git a/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst old mode 100755 new mode 100644 index 637ce73..e9003c4 --- a/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1,10 +1,16 @@ com/innovation/platform/service/impl/SysUserServiceImpl.class +com/innovation/platform/service/ProjectService.class com/innovation/platform/common/Result.class +com/innovation/platform/dto/ProjectQueryRequest.class +com/innovation/platform/controller/UserController$PageResult.class +com/innovation/platform/controller/ProjectController.class com/innovation/platform/dto/LoginResponse$LoginResponseBuilder.class com/innovation/platform/entity/StuInfo.class com/innovation/platform/dto/RegisterRequest.class com/innovation/platform/dto/LoginResponse.class com/innovation/platform/entity/BaseEntity.class +com/innovation/platform/controller/UserController$UpdateUserRequest.class +com/innovation/platform/dto/ProjectResponse.class com/innovation/platform/InnovationPlatformApplication.class com/innovation/platform/entity/ProjectMember.class com/innovation/platform/entity/ReviewScoreItem.class @@ -15,12 +21,19 @@ com/innovation/platform/entity/ProjectAttachment.class com/innovation/platform/entity/SysUser.class com/innovation/platform/entity/Review.class com/innovation/platform/dto/LoginRequest.class +com/innovation/platform/controller/UserController$UpdateProfileRequest.class +com/innovation/platform/controller/UserController.class com/innovation/platform/exception/GlobalExceptionHandler.class com/innovation/platform/mapper/SysUserMapper.class com/innovation/platform/entity/TeacherInfo.class +com/innovation/platform/dto/ProjectResponse$ProjectResponseBuilder.class com/innovation/platform/entity/SysLog.class +com/innovation/platform/mapper/ProjectMapper.class +com/innovation/platform/dto/ProjectRequest.class +com/innovation/platform/controller/UserController$CreateUserRequest.class com/innovation/platform/entity/Project.class com/innovation/platform/config/SaTokenConfig.class com/innovation/platform/entity/SysConfig.class +com/innovation/platform/service/impl/ProjectServiceImpl.class com/innovation/platform/entity/AchievementAttachment.class com/innovation/platform/entity/Achievement.class diff --git a/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst old mode 100755 new mode 100644 index 31adbf5..90dce7f --- a/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/backend/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -3,13 +3,20 @@ /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/SysConfig.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/InnovationPlatformApplication.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/mapper/SysUserMapper.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/service/impl/ProjectServiceImpl.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/dto/RegisterRequest.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/SysLog.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/dto/ProjectQueryRequest.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/exception/GlobalExceptionHandler.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/service/SysUserService.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/service/ProjectService.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/BaseEntity.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/controller/AuthController.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/controller/ProjectController.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/dto/ProjectRequest.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/common/Result.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/dto/ProjectResponse.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/mapper/ProjectMapper.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/ProjectMember.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/dto/LoginResponse.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/service/impl/SysUserServiceImpl.java @@ -21,5 +28,6 @@ /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/Review.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/Achievement.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/ProjectAttachment.java +/home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/controller/UserController.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/SysUser.java /home/llm/projects/innovation-platform/backend/src/main/java/com/innovation/platform/entity/TeacherInfo.java diff --git a/backend/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/backend/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst deleted file mode 100755 index e69de29..0000000 diff --git a/backend/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/backend/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst deleted file mode 100755 index e69de29..0000000 diff --git a/docker-compose.yml b/docker-compose.yml index 617965d..8b816bb 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,7 +25,7 @@ services: SPRING_DATASOURCE_USERNAME: innovation SPRING_DATASOURCE_PASSWORD: innovation123 ports: - - "8080:8080" + - "127.0.0.1:8081:8080" networks: - innovation-network