source upload

main
lensfrex 2 months ago
commit 7711942d07
Signed by: lensfrex
GPG Key ID: 0F69A0A2FBEE98A0
  1. 36
      .gitignore
  2. 40
      backend/.gitignore
  3. 7
      backend/Dockerfile
  4. 54
      backend/docker-compose.yml
  5. 581
      backend/docker/database.sql
  6. 273
      backend/pom.xml
  7. 26
      backend/src/main/java/rd/BackendMain.java
  8. 36
      backend/src/main/java/rd/configure/CorsFilter.java
  9. 11
      backend/src/main/java/rd/configure/JSR310SupportedGenericJackson2JsonRedisSerializer.java
  10. 29
      backend/src/main/java/rd/configure/JacksonConfigure.java
  11. 17
      backend/src/main/java/rd/configure/MybatisConfigure.java
  12. 13
      backend/src/main/java/rd/configure/OkhttpConfigure.java
  13. 32
      backend/src/main/java/rd/configure/OpenAPIConfigure.java
  14. 12
      backend/src/main/java/rd/configure/RdConfigure.java
  15. 29
      backend/src/main/java/rd/configure/RedisConfigure.java
  16. 15
      backend/src/main/java/rd/configure/SaTokenConfigure.java
  17. 51
      backend/src/main/java/rd/configure/ThreadPoolConfigure.java
  18. 13
      backend/src/main/java/rd/controller/Health.java
  19. 44
      backend/src/main/java/rd/controller/activity/ActivityController.java
  20. 44
      backend/src/main/java/rd/controller/activity/AdminActivityController.java
  21. 138
      backend/src/main/java/rd/controller/activity/AdminActivityTargetController.java
  22. 59
      backend/src/main/java/rd/controller/course/AdminCourseController.java
  23. 175
      backend/src/main/java/rd/controller/course/CourseController.java
  24. 72
      backend/src/main/java/rd/controller/course/CourseTeacherController.java
  25. 76
      backend/src/main/java/rd/controller/course/StudentCourseController.java
  26. 35
      backend/src/main/java/rd/controller/major/AdminMajorController.java
  27. 34
      backend/src/main/java/rd/controller/major/PublicMajor.java
  28. 68
      backend/src/main/java/rd/controller/schedule/AdminScheduleController.java
  29. 59
      backend/src/main/java/rd/controller/schedule/ScheduleController.java
  30. 102
      backend/src/main/java/rd/controller/schedule/StudentScheduleController.java
  31. 32
      backend/src/main/java/rd/controller/schedule/TeacherScheduleController.java
  32. 66
      backend/src/main/java/rd/controller/score/ScoreController.java
  33. 31
      backend/src/main/java/rd/controller/score/StudentScoreController.java
  34. 43
      backend/src/main/java/rd/controller/score/TeacherScoreController.java
  35. 79
      backend/src/main/java/rd/controller/student/AdminStudentController.java
  36. 38
      backend/src/main/java/rd/controller/student/StudentController.java
  37. 52
      backend/src/main/java/rd/controller/teacher/AdminTeacherController.java
  38. 35
      backend/src/main/java/rd/controller/teacher/TeacherController.java
  39. 120
      backend/src/main/java/rd/controller/user/UserAuthController.java
  40. 35
      backend/src/main/java/rd/controller/user/UserInfoController.java
  41. 19
      backend/src/main/java/rd/dao/BatchSQLInjector.java
  42. 16
      backend/src/main/java/rd/dao/mapper/activity/ActivityMapper.java
  43. 12
      backend/src/main/java/rd/dao/mapper/activity/ActivityTargetMapper.java
  44. 36
      backend/src/main/java/rd/dao/mapper/course/CourseMapper.java
  45. 35
      backend/src/main/java/rd/dao/mapper/course/CourseSelectionMapper.java
  46. 22
      backend/src/main/java/rd/dao/mapper/course/CourseTeacherMapper.java
  47. 10
      backend/src/main/java/rd/dao/mapper/experiment/ExperimentItemMapper.java
  48. 9
      backend/src/main/java/rd/dao/mapper/major/MajorMapper.java
  49. 22
      backend/src/main/java/rd/dao/mapper/schedule/CourseScheduleMapper.java
  50. 9
      backend/src/main/java/rd/dao/mapper/score/ExperimentScoreMapper.java
  51. 23
      backend/src/main/java/rd/dao/mapper/score/ScoreMapper.java
  52. 11
      backend/src/main/java/rd/dao/mapper/user/StudentInfoMapper.java
  53. 9
      backend/src/main/java/rd/dao/mapper/user/TeacherInfoMapper.java
  54. 9
      backend/src/main/java/rd/dao/mapper/user/UserBasicMapper.java
  55. 77
      backend/src/main/java/rd/dao/type/DoubleListTypeHandler.java
  56. 77
      backend/src/main/java/rd/dao/type/FloatListTypeHandler.java
  57. 67
      backend/src/main/java/rd/dao/type/IntegerListTypeHandler.java
  58. 69
      backend/src/main/java/rd/dao/type/LongListTypeHandler.java
  59. 69
      backend/src/main/java/rd/dao/type/ShortListTypeHandler.java
  60. 55
      backend/src/main/java/rd/dao/type/StringListTypeHandler.java
  61. 9
      backend/src/main/java/rd/dao/type/json/BaseJsonListTypeHandler.java
  62. 63
      backend/src/main/java/rd/dao/type/json/BaseJsonTypeHandler.java
  63. 15
      backend/src/main/java/rd/dao/type/json/FloatMapTypeHandler.java
  64. 9
      backend/src/main/java/rd/dao/type/json/UsualScoreItemListTypeHandler.java
  65. 20
      backend/src/main/java/rd/data/Constants.java
  66. 49
      backend/src/main/java/rd/data/code/ServiceCode.java
  67. 76
      backend/src/main/java/rd/data/db/CourseScheduleSelectionInfo.java
  68. 84
      backend/src/main/java/rd/data/db/CourseScheduleWithCourseIdName.java
  69. 7
      backend/src/main/java/rd/data/db/UsualScoreItem.java
  70. 68
      backend/src/main/java/rd/data/db/table/Activity.java
  71. 54
      backend/src/main/java/rd/data/db/table/ActivityTarget.java
  72. 63
      backend/src/main/java/rd/data/db/table/Course.java
  73. 85
      backend/src/main/java/rd/data/db/table/CourseSchedule.java
  74. 52
      backend/src/main/java/rd/data/db/table/CourseSelection.java
  75. 41
      backend/src/main/java/rd/data/db/table/CourseTeacher.java
  76. 42
      backend/src/main/java/rd/data/db/table/ExperimentItem.java
  77. 17
      backend/src/main/java/rd/data/db/table/ExperimentScore.java
  78. 58
      backend/src/main/java/rd/data/db/table/Major.java
  79. 38
      backend/src/main/java/rd/data/db/table/Score.java
  80. 64
      backend/src/main/java/rd/data/db/table/StudentInfo.java
  81. 43
      backend/src/main/java/rd/data/db/table/TeacherInfo.java
  82. 51
      backend/src/main/java/rd/data/db/table/UserBasic.java
  83. 13
      backend/src/main/java/rd/data/dto/FileByteDataWrapper.java
  84. 23
      backend/src/main/java/rd/data/dto/activity/ActivityTargetAddDto.java
  85. 23
      backend/src/main/java/rd/data/dto/activity/ActivityTargetUpdateDto.java
  86. 41
      backend/src/main/java/rd/data/dto/course/CourseDTO.java
  87. 19
      backend/src/main/java/rd/data/dto/course/CourseNameDTO.java
  88. 76
      backend/src/main/java/rd/data/dto/course/CourseScheduleSelectionInfoDTO.java
  89. 45
      backend/src/main/java/rd/data/dto/schedule/CourseScheduleDTO.java
  90. 75
      backend/src/main/java/rd/data/dto/schedule/CourseScheduleDetailDTO.java
  91. 67
      backend/src/main/java/rd/data/dto/schedule/CourseScheduleWithCourseNameDTO.java
  92. 11
      backend/src/main/java/rd/data/dto/schedule/NotSelectStudentExportDto.java
  93. 12
      backend/src/main/java/rd/data/dto/schedule/SelectedStudentExportDto.java
  94. 24
      backend/src/main/java/rd/data/dto/score/CourseScoreInfoDto.java
  95. 20
      backend/src/main/java/rd/data/dto/score/ScoreExportDto.java
  96. 18
      backend/src/main/java/rd/data/dto/score/StudentScore.java
  97. 4
      backend/src/main/java/rd/data/dto/user/UserBasicInfoDTO.java
  98. 4
      backend/src/main/java/rd/data/dto/user/student/BasicStudentInfoDto.java
  99. 4
      backend/src/main/java/rd/data/dto/user/student/BasicStudentInfoWithMajorNameDto.java
  100. 7
      backend/src/main/java/rd/data/dto/user/student/NewStudentDTO.java
  101. Some files were not shown because too many files have changed in this diff Show More

36
.gitignore vendored

@ -0,0 +1,36 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
.env
logs

40
backend/.gitignore vendored

@ -0,0 +1,40 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
.env

@ -0,0 +1,7 @@
FROM eclipse-temurin:17
RUN mkdir /opt/app
COPY target/radical-dreamers.jar /opt/app
CMD ["java", "-jar", "/opt/app/radical-dreamers.jar"]

@ -0,0 +1,54 @@
name: rd-srv-backend
services:
# 主服务
rd:
build:
context: .
dockerfile: Dockerfile
ports:
- "8800:8800"
environment:
spring.data.redis.host: redis
spring.data.redis.port: 6379
spring.datasource.url: jdbc:postgresql://db:5432/rdrev?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
spring.datasource.username: postgres
spring.datasource.password: a7d929f76d45d13a4337f2d16f5634bc17e5b8b2
server.port: 8800
depends_on:
redis:
condition: service_started
db:
condition: service_healthy
networks:
- rd-network
# Postgresql
db:
image: postgres:14.12-alpine3.19
environment:
PGUSER: postgres
POSTGRES_USER: postgres
POSTGRES_DB: rdrev
POSTGRES_PASSWORD: a7d929f76d45d13a4337f2d16f5634bc17e5b8b2
volumes:
- ./docker:/docker-entrypoint-initdb.d/
networks:
- rd-network
healthcheck:
test: [ "CMD-SHELL", "pg_isready", "-d", "db_prod"]
interval: 10s
timeout: 60s
retries: 5
start_period: 5s
# Redis
redis:
image: redis
networks:
- rd-network
networks:
rd-network:
internal: false

@ -0,0 +1,581 @@
/*
Navicat Premium Data Transfer
Source Server : local_postgresql
Source Server Type : PostgreSQL
Source Server Version : 140012
Source Host : localhost:5432
Source Catalog : little_busters
Source Schema : public
Target Server Type : PostgreSQL
Target Server Version : 140012
File Encoding : 65001
Date: 14/02/2025 13:14:12
*/
-- ----------------------------
-- Table structure for activity
-- ----------------------------
DROP TABLE IF EXISTS "public"."activity";
CREATE TABLE "public"."activity" (
"id" int8 NOT NULL DEFAULT 0,
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying,
"term" varchar(11) COLLATE "pg_catalog"."default" NOT NULL DEFAULT '2023-2024-1'::character varying,
"start_time" timestamp(6) NOT NULL DEFAULT now(),
"end_time" timestamp(6) NOT NULL DEFAULT now(),
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0
)
;
COMMENT ON COLUMN "public"."activity"."id" IS '选课活动id';
COMMENT ON COLUMN "public"."activity"."name" IS '活动id';
COMMENT ON COLUMN "public"."activity"."term" IS '学期,格式如2023-2024-1';
COMMENT ON COLUMN "public"."activity"."start_time" IS '开始时间';
COMMENT ON COLUMN "public"."activity"."end_time" IS '结束时间';
-- ----------------------------
-- Records of activity
-- ----------------------------
-- ----------------------------
-- Table structure for activity_target
-- ----------------------------
DROP TABLE IF EXISTS "public"."activity_target";
CREATE TABLE "public"."activity_target" (
"id" int8 NOT NULL,
"activity" int8 NOT NULL,
"grade" int2 NOT NULL,
"major" int8 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0,
"course_list" int8[] NOT NULL
)
;
COMMENT ON COLUMN "public"."activity_target"."activity" IS '活动id';
COMMENT ON COLUMN "public"."activity_target"."grade" IS '年级,入学年份';
COMMENT ON COLUMN "public"."activity_target"."major" IS '专业id';
COMMENT ON COLUMN "public"."activity_target"."course_list" IS '课程id数组';
-- ----------------------------
-- Records of activity_target
-- ----------------------------
-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS "public"."course";
CREATE TABLE "public"."course" (
"id" int8 NOT NULL,
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"course_hours" int2 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"spring_term" bool NOT NULL DEFAULT true,
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0,
"exam_ratio" float4 NOT NULL,
"distribution" jsonb NOT NULL DEFAULT '{}'::jsonb
)
;
COMMENT ON COLUMN "public"."course"."id" IS '课程id';
COMMENT ON COLUMN "public"."course"."name" IS '课程名称';
COMMENT ON COLUMN "public"."course"."course_hours" IS '课时';
COMMENT ON COLUMN "public"."course"."spring_term" IS '是否春季期课程(false即是秋季期)';
COMMENT ON COLUMN "public"."course"."exam_ratio" IS '考试成绩占比';
COMMENT ON COLUMN "public"."course"."distribution" IS '平时分成绩分布,usual_score参考依据';
-- ----------------------------
-- Records of course
-- ----------------------------
-- ----------------------------
-- Table structure for course_schedule
-- ----------------------------
DROP TABLE IF EXISTS "public"."course_schedule";
CREATE TABLE "public"."course_schedule" (
"id" int8 NOT NULL,
"course" int8 NOT NULL,
"start_week" int2 NOT NULL,
"end_week" int2 NOT NULL,
"time" int2 NOT NULL,
"academic_term" varchar(11) COLLATE "pg_catalog"."default" NOT NULL DEFAULT '2023-2024-1'::character varying,
"place" varchar(255) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"weekday" int2 NOT NULL DEFAULT 1,
"status" int2 NOT NULL DEFAULT 0,
"deleted" bool NOT NULL DEFAULT false
)
;
COMMENT ON COLUMN "public"."course_schedule"."id" IS '课堂id';
COMMENT ON COLUMN "public"."course_schedule"."course" IS '课程id';
COMMENT ON COLUMN "public"."course_schedule"."start_week" IS '开始周';
COMMENT ON COLUMN "public"."course_schedule"."end_week" IS '结束周';
COMMENT ON COLUMN "public"."course_schedule"."time" IS '节次时间,即第几节课';
COMMENT ON COLUMN "public"."course_schedule"."academic_term" IS '学年学期,格式如2023-2024-2';
COMMENT ON COLUMN "public"."course_schedule"."place" IS '上课地点';
COMMENT ON COLUMN "public"."course_schedule"."weekday" IS '星期几';
-- ----------------------------
-- Records of course_schedule
-- ----------------------------
-- ----------------------------
-- Table structure for course_selection
-- ----------------------------
DROP TABLE IF EXISTS "public"."course_selection";
CREATE TABLE "public"."course_selection" (
"id" int8 NOT NULL,
"student" int8 NOT NULL,
"schedule" int8 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"activity" int8 NOT NULL,
"status" int2 NOT NULL DEFAULT 0,
"term" varchar(11) COLLATE "pg_catalog"."default" NOT NULL
)
;
COMMENT ON COLUMN "public"."course_selection"."id" IS '选课记录id';
COMMENT ON COLUMN "public"."course_selection"."student" IS '学生id';
COMMENT ON COLUMN "public"."course_selection"."schedule" IS '课堂id';
COMMENT ON COLUMN "public"."course_selection"."activity" IS '选课时候的活动id';
COMMENT ON COLUMN "public"."course_selection"."term" IS '学期';
-- ----------------------------
-- Records of course_selection
-- ----------------------------
-- ----------------------------
-- Table structure for course_teacher
-- ----------------------------
DROP TABLE IF EXISTS "public"."course_teacher";
CREATE TABLE "public"."course_teacher" (
"teacher" int8 NOT NULL,
"course" int8 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0
)
;
COMMENT ON COLUMN "public"."course_teacher"."teacher" IS '教师id';
COMMENT ON COLUMN "public"."course_teacher"."course" IS '课程班级id';
-- ----------------------------
-- Records of course_teacher
-- ----------------------------
-- ----------------------------
-- Table structure for experiment_item
-- ----------------------------
DROP TABLE IF EXISTS "public"."experiment_item";
CREATE TABLE "public"."experiment_item" (
"id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"course" int8 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0
)
;
COMMENT ON COLUMN "public"."experiment_item"."id" IS '实验项目id';
COMMENT ON COLUMN "public"."experiment_item"."name" IS '项目名称';
COMMENT ON COLUMN "public"."experiment_item"."course" IS '课程id';
-- ----------------------------
-- Records of experiment_item
-- ----------------------------
-- ----------------------------
-- Table structure for experiment_score
-- ----------------------------
DROP TABLE IF EXISTS "public"."experiment_score";
CREATE TABLE "public"."experiment_score" (
"id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"student" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"experiment" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"score" int2 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0
)
;
COMMENT ON COLUMN "public"."experiment_score"."id" IS '成绩id';
COMMENT ON COLUMN "public"."experiment_score"."student" IS '学生id';
COMMENT ON COLUMN "public"."experiment_score"."experiment" IS '实验id';
COMMENT ON COLUMN "public"."experiment_score"."score" IS '实验分';
-- ----------------------------
-- Records of experiment_score
-- ----------------------------
-- ----------------------------
-- Table structure for major
-- ----------------------------
DROP TABLE IF EXISTS "public"."major";
CREATE TABLE "public"."major" (
"id" int8 NOT NULL,
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0
)
;
COMMENT ON COLUMN "public"."major"."id" IS '专业id';
COMMENT ON COLUMN "public"."major"."name" IS '专业名称';
-- ----------------------------
-- Records of major
-- ----------------------------
-- ----------------------------
-- Table structure for score
-- ----------------------------
DROP TABLE IF EXISTS "public"."score";
CREATE TABLE "public"."score" (
"id" int8 NOT NULL,
"student" int8 NOT NULL,
"usual_score" float4 NOT NULL,
"exam_score" float4 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"course" int8 NOT NULL,
"term" varchar(11) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying,
"status" int2 NOT NULL DEFAULT 0,
"exam_ratio" float4 NOT NULL DEFAULT 1.0
)
;
COMMENT ON COLUMN "public"."score"."id" IS '成绩id';
COMMENT ON COLUMN "public"."score"."student" IS '学生id';
COMMENT ON COLUMN "public"."score"."usual_score" IS '平时分';
COMMENT ON COLUMN "public"."score"."exam_score" IS '考试分';
COMMENT ON COLUMN "public"."score"."course" IS '课程id';
COMMENT ON COLUMN "public"."score"."term" IS '学期';
COMMENT ON COLUMN "public"."score"."exam_ratio" IS '考试成绩占比';
-- ----------------------------
-- Records of score
-- ----------------------------
-- ----------------------------
-- Table structure for student_info
-- ----------------------------
DROP TABLE IF EXISTS "public"."student_info";
CREATE TABLE "public"."student_info" (
"id" int8 NOT NULL,
"student_number" varchar(12) COLLATE "pg_catalog"."default" NOT NULL,
"name" varchar(16) COLLATE "pg_catalog"."default" NOT NULL,
"major" int8 NOT NULL,
"grade" int2 NOT NULL DEFAULT 2,
"class" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0
)
;
COMMENT ON COLUMN "public"."student_info"."id" IS '学生id';
COMMENT ON COLUMN "public"."student_info"."student_number" IS '学号';
COMMENT ON COLUMN "public"."student_info"."name" IS '学生姓名';
COMMENT ON COLUMN "public"."student_info"."major" IS '专业id';
COMMENT ON COLUMN "public"."student_info"."grade" IS '年级,使用大x表示,如大二:2';
COMMENT ON COLUMN "public"."student_info"."class" IS '班级';
-- ----------------------------
-- Records of student_info
-- ----------------------------
-- ----------------------------
-- Table structure for teacher_info
-- ----------------------------
DROP TABLE IF EXISTS "public"."teacher_info";
CREATE TABLE "public"."teacher_info" (
"id" int8 NOT NULL,
"name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0
)
;
COMMENT ON COLUMN "public"."teacher_info"."id" IS '教师id';
COMMENT ON COLUMN "public"."teacher_info"."name" IS '教师姓名';
-- ----------------------------
-- Records of teacher_info
-- ----------------------------
-- ----------------------------
-- Table structure for user_basic
-- ----------------------------
DROP TABLE IF EXISTS "public"."user_basic";
CREATE TABLE "public"."user_basic" (
"id" int8 NOT NULL,
"username" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
"password" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,
"type" int2 NOT NULL,
"create_time" timestamp(6) NOT NULL DEFAULT now(),
"edit_time" timestamp(6) NOT NULL DEFAULT now(),
"deleted" bool NOT NULL DEFAULT false,
"status" int2 NOT NULL DEFAULT 0,
"oid" varchar(255) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying
)
;
COMMENT ON COLUMN "public"."user_basic"."id" IS '用户uuid';
COMMENT ON COLUMN "public"."user_basic"."username" IS '用户名,登陆用';
COMMENT ON COLUMN "public"."user_basic"."password" IS '密码';
COMMENT ON COLUMN "public"."user_basic"."type" IS '用户类型,0:学生,1:教师,2:管理员';
COMMENT ON COLUMN "public"."user_basic"."oid" IS 'oidc id';
-- ----------------------------
-- Records of user_basic
-- ----------------------------
INSERT INTO "public"."user_basic" VALUES (0, 'root', '$2a$10$L6bKqBVE9LWlaSWglepokeqd5HKnsptci8uta2PUt0MctfANEk84C', 2, '2025-02-14 05:12:34.578087', '2025-02-14 05:12:34.578087', 'f', 0, '');
-- ----------------------------
-- Function structure for cs_timestamp
-- ----------------------------
DROP FUNCTION IF EXISTS "public"."cs_timestamp"();
CREATE OR REPLACE FUNCTION "public"."cs_timestamp"()
RETURNS "pg_catalog"."trigger" AS $BODY$
begin
new.update_time= current_timestame;
return new;
end
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
-- ----------------------------
-- Indexes structure for table activity
-- ----------------------------
CREATE INDEX "act_idx_end" ON "public"."activity" USING btree (
"end_time" "pg_catalog"."timestamp_ops" ASC NULLS LAST
);
CREATE INDEX "act_idx_id" ON "public"."activity" USING hash (
"id" "pg_catalog"."int8_ops"
);
CREATE INDEX "act_idx_start" ON "public"."activity" USING brin (
"start_time" "pg_catalog"."timestamp_minmax_ops"
);
CREATE INDEX "act_idx_term" ON "public"."activity" USING btree (
"term" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table activity
-- ----------------------------
ALTER TABLE "public"."activity" ADD CONSTRAINT "activity_pkey" PRIMARY KEY ("id", "term", "start_time", "end_time");
-- ----------------------------
-- Indexes structure for table activity_target
-- ----------------------------
CREATE INDEX "idx_at_act" ON "public"."activity_target" USING btree (
"activity" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE UNIQUE INDEX "idx_at_act_major_grade" ON "public"."activity_target" USING btree (
"grade" "pg_catalog"."int2_ops" ASC NULLS LAST,
"major" "pg_catalog"."int8_ops" ASC NULLS LAST,
"activity" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "idx_at_course" ON "public"."activity_target" USING gin (
"course_list" "pg_catalog"."array_ops"
) WITH (GIN_PENDING_LIST_LIMIT = 128);
CREATE INDEX "idx_at_major_grade" ON "public"."activity_target" USING btree (
"grade" "pg_catalog"."int2_ops" ASC NULLS LAST,
"major" "pg_catalog"."int8_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table activity_target
-- ----------------------------
ALTER TABLE "public"."activity_target" ADD CONSTRAINT "activity_course_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table course
-- ----------------------------
CREATE INDEX "course_idx_id" ON "public"."course" USING hash (
"id" "pg_catalog"."int8_ops"
);
COMMENT ON INDEX "public"."course_idx_id" IS 'id索引';
-- ----------------------------
-- Primary Key structure for table course
-- ----------------------------
ALTER TABLE "public"."course" ADD CONSTRAINT "course_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table course_schedule
-- ----------------------------
CREATE INDEX "cs_idx_course" ON "public"."course_schedule" USING btree (
"course" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "cs_idx_course_schedule" ON "public"."course_schedule" USING btree (
"id" "pg_catalog"."int8_ops" ASC NULLS LAST,
"course" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "cs_idx_course_term" ON "public"."course_schedule" USING btree (
"course" "pg_catalog"."int8_ops" ASC NULLS LAST,
"academic_term" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
CREATE INDEX "cs_idx_id" ON "public"."course_schedule" USING btree (
"id" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "cs_idx_term" ON "public"."course_schedule" USING btree (
"academic_term" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table course_schedule
-- ----------------------------
ALTER TABLE "public"."course_schedule" ADD CONSTRAINT "class_pkey" PRIMARY KEY ("id", "course");
-- ----------------------------
-- Indexes structure for table course_selection
-- ----------------------------
CREATE INDEX "course_selection_student_idx" ON "public"."course_selection" USING btree (
"student" "pg_catalog"."int8_ops" ASC NULLS LAST,
"term" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
CREATE INDEX "csel_idex_student" ON "public"."course_selection" USING btree (
"student" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "csel_idx_activity" ON "public"."course_selection" USING btree (
"activity" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "csel_idx_course" ON "public"."course_selection" USING btree (
"schedule" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "csel_idx_id" ON "public"."course_selection" USING btree (
"id" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "csel_idx_id_term" ON "public"."course_selection" USING btree (
"id" "pg_catalog"."int8_ops" ASC NULLS LAST,
"term" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table course_selection
-- ----------------------------
ALTER TABLE "public"."course_selection" ADD CONSTRAINT "course_selection_pkey" PRIMARY KEY ("id", "student", "schedule");
-- ----------------------------
-- Indexes structure for table course_teacher
-- ----------------------------
CREATE INDEX "tc_idx_course" ON "public"."course_teacher" USING btree (
"course" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "tc_idx_teacher" ON "public"."course_teacher" USING btree (
"teacher" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "teacher_course_teacher_course_idx" ON "public"."course_teacher" USING btree (
"teacher" "pg_catalog"."int8_ops" ASC NULLS LAST,
"course" "pg_catalog"."int8_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table experiment_item
-- ----------------------------
ALTER TABLE "public"."experiment_item" ADD CONSTRAINT "course_experiment_pkey" PRIMARY KEY ("id", "course");
-- ----------------------------
-- Primary Key structure for table experiment_score
-- ----------------------------
ALTER TABLE "public"."experiment_score" ADD CONSTRAINT "experiment_score_pkey" PRIMARY KEY ("id", "student", "experiment");
-- ----------------------------
-- Indexes structure for table major
-- ----------------------------
CREATE INDEX "major_idx_id" ON "public"."major" USING hash (
"id" "pg_catalog"."int8_ops"
);
CREATE INDEX "major_idx_name" ON "public"."major" USING btree (
"name" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table major
-- ----------------------------
ALTER TABLE "public"."major" ADD CONSTRAINT "major_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table score
-- ----------------------------
CREATE INDEX "score_idx_course_term" ON "public"."score" USING btree (
"course" "pg_catalog"."int8_ops" ASC NULLS LAST,
"term" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
CREATE INDEX "score_idx_id" ON "public"."score" USING hash (
"id" "pg_catalog"."int8_ops"
);
CREATE INDEX "score_idx_student" ON "public"."score" USING btree (
"student" "pg_catalog"."int8_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table score
-- ----------------------------
ALTER TABLE "public"."score" ADD CONSTRAINT "score_pkey" PRIMARY KEY ("student", "course", "term");
-- ----------------------------
-- Indexes structure for table student_info
-- ----------------------------
CREATE INDEX "stu_dix_grade" ON "public"."student_info" USING btree (
"grade" "pg_catalog"."int2_ops" ASC NULLS LAST
);
CREATE INDEX "stu_idx_id" ON "public"."student_info" USING hash (
"id" "pg_catalog"."int8_ops"
);
CREATE INDEX "stu_idx_major" ON "public"."student_info" USING btree (
"major" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "stu_idx_num" ON "public"."student_info" USING btree (
"student_number" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table student_info
-- ----------------------------
ALTER TABLE "public"."student_info" ADD CONSTRAINT "student_info_pkey" PRIMARY KEY ("id", "student_number");
-- ----------------------------
-- Indexes structure for table teacher_info
-- ----------------------------
CREATE INDEX "ti_idx_id" ON "public"."teacher_info" USING hash (
"id" "pg_catalog"."int8_ops"
);
-- ----------------------------
-- Primary Key structure for table teacher_info
-- ----------------------------
ALTER TABLE "public"."teacher_info" ADD CONSTRAINT "teacher_info_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Indexes structure for table user_basic
-- ----------------------------
CREATE INDEX "usr_bsic_oid" ON "public"."user_basic" USING hash (
"oid" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops"
);
CREATE INDEX "usr_idx_id" ON "public"."user_basic" USING hash (
"id" "pg_catalog"."int8_ops"
);
CREATE INDEX "usr_idx_username" ON "public"."user_basic" USING btree (
"username" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
-- ----------------------------
-- Primary Key structure for table user_basic
-- ----------------------------
ALTER TABLE "public"."user_basic" ADD CONSTRAINT "user_pkey" PRIMARY KEY ("id", "username", "password");

@ -0,0 +1,273 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.lensfrex.service</groupId>
<artifactId>radical-dreamers</artifactId>
<version>${revision}</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<revision>0.0.1-SNAPSHOT</revision>
<springboot.version>3.1.1</springboot.version>
<caffeine.version>3.1.6</caffeine.version>
<snakeyaml.version>2.0</snakeyaml.version>
<junit.version>5.10.0-RC1</junit.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<mybatis.version>3.0.2</mybatis.version>
<lombok.version>1.18.26</lombok.version>
<hutool.version>5.8.20</hutool.version>
<satoken.version>1.34.0</satoken.version>
<lettuce.bersion>6.2.5.RELEASE</lettuce.bersion>
<idgen.version>1.0.6</idgen.version>
<spring-doc.version>2.5.0</spring-doc.version>
<easyexcel.version>3.3.2</easyexcel.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-bom</artifactId>
<version>${hutool.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter-test</artifactId>
<version>3.5.3.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- snakeyaml版本提升(烦人的漏洞警告) -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- swagger -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${spring-doc.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>${spring-doc.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 数据库,mybatis和mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- caffeine缓存 -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>${caffeine.version}</version>
</dependency>
<!-- web框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>${lettuce.bersion}</version>
</dependency>
<!-- id生成 -->
<dependency>
<groupId>com.github.yitter</groupId>
<artifactId>yitter-idgenerator</artifactId>
<version>${idgen.version}</version>
</dependency>
<!-- 权限认证 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>${satoken.version}</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- 各种小工具 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<!-- excel导出 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.23.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>5.0.0-alpha.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.4.0-jre</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>central</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/repository/public</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<finalName>radical-dreamers</finalName>
<addResources>true</addResources>
<!-- <fork>true</fork>-->
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,26 @@
package rd;
import com.github.yitter.contract.IdGeneratorOptions;
import com.github.yitter.idgen.YitIdHelper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableAsync
@EnableScheduling
@SpringBootApplication
@EnableTransactionManagement
@MapperScan(basePackages = "rd.dao.mapper")
public class BackendMain {
public static void main(String[] args) {
IdGeneratorOptions options = new IdGeneratorOptions();
options.WorkerIdBitLength = 4;
options.WorkerId = 0;
YitIdHelper.setIdGenerator(options);
SpringApplication.run(BackendMain.class, args);
}
}

@ -0,0 +1,36 @@
package rd.configure;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@WebFilter(filterName = "CorsFilter", urlPatterns = "/*")
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}

@ -0,0 +1,11 @@
package rd.configure;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
public class JSR310SupportedGenericJackson2JsonRedisSerializer extends GenericJackson2JsonRedisSerializer {
public JSR310SupportedGenericJackson2JsonRedisSerializer() {
super();
getObjectMapper().registerModule(new JavaTimeModule());
}
}

@ -0,0 +1,29 @@
package rd.configure;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class JacksonConfigure {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// other serializer and deSerializer config ...
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_DATE_TIME));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME));
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
}

@ -0,0 +1,17 @@
package rd.configure;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfigure {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
return interceptor;
}
}

@ -0,0 +1,13 @@
package rd.configure;
import okhttp3.OkHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OkhttpConfigure {
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
}

@ -0,0 +1,32 @@
package rd.configure;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Getter
@Component
@Configuration
public class OpenAPIConfigure {
private String serverUrl;
@Value("${wusthelper.docs.server-url:/}")
public void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl;
}
@Bean
public OpenAPI openAPI() {
var info = new Info()
.title("rd")
.description("rd api")
.version("v1");
return new OpenAPI()
.info(info);
}
}

@ -0,0 +1,12 @@
package rd.configure;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
public class RdConfigure {
@Value("${rd.WusthelperBaseUrl}")
private String wusthelperBaseUrl;
}

@ -0,0 +1,29 @@
package rd.configure;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
@EnableCaching
public class RedisConfigure {
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
var jsonRedisSerializer = new JSR310SupportedGenericJackson2JsonRedisSerializer();
redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setDefaultSerializer(jsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

@ -0,0 +1,15 @@
package rd.configure;
import cn.dev33.satoken.interceptor.SaInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
}
}

@ -0,0 +1,51 @@
package rd.configure;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@EnableAsync
@Configuration
public class ThreadPoolConfigure implements AsyncConfigurer {
@Value("${spring.task.execution.pool.core-size}")
private int corePoolSize;
@Value("${spring.task.execution.pool.max-size}")
private int maxPoolSize;
@Value("${spring.task.execution.pool.queue-capacity}")
private int queueCapacity;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(300);
executor.setThreadNamePrefix("rd-thr-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (e, method, params) -> {
log.error("Uncaught exception in task executing: {}", e.getMessage(), e);
log.error("Method: {}", method.getName());
};
}
}

@ -0,0 +1,13 @@
package rd.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/health")
public class Health {
@RequestMapping("")
public String health() {
return "";
}
}

@ -0,0 +1,44 @@
package rd.controller.activity;
import rd.data.db.table.Activity;
import rd.data.model.response.PaginationWrapper;
import rd.data.model.response.Response;
import rd.service.activity.ActivityService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/activity")
public class ActivityController {
private final ActivityService activityService;
public ActivityController(ActivityService activityService) {
this.activityService = activityService;
}
@RequestMapping("/current")
public Response<Activity> current() {
var result = activityService.getCurrentActivity();
return Response.success(result);
}
@RequestMapping("/list")
public Response<PaginationWrapper<List<Activity>>> list(
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
) {
var result = activityService.list(page, pageSize);
return Response.success(result);
}
@RequestMapping("/info")
public Response<Activity> info(@RequestParam(value = "id") Long id) {
var result = activityService.getById(id);
return Response.success(result);
}
}

@ -0,0 +1,44 @@
package rd.controller.activity;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.db.table.Activity;
import rd.data.model.request.admin.ActivityInfoDto;
import rd.data.model.response.Response;
import rd.service.activity.ActivityService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/activity")
public class AdminActivityController {
private final ActivityService activityService;
public AdminActivityController(ActivityService activityService) {
this.activityService = activityService;
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/add")
public Response<Activity> add(@RequestBody ActivityInfoDto request) {
activityService.addActivity(request);
return Response.success();
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/update")
public Response<Activity> update(@RequestParam("id") Long id, @RequestBody ActivityInfoDto request) {
var activity = activityService.update(id, request);
return Response.success(activity);
}
@SaCheckRole("ADMIN")
@PostMapping("/delete")
public Response<Activity> delete(@RequestParam("id") Long id) {
activityService.delete(id);
return Response.success();
}
}

@ -0,0 +1,138 @@
package rd.controller.activity;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.dto.activity.ActivityTargetAddDto;
import rd.data.dto.activity.ActivityTargetUpdateDto;
import rd.data.db.table.ActivityTarget;
import rd.data.model.request.activity.ActivityTargetAddRequest;
import rd.data.model.request.activity.ActivityTargetUpadeRequest;
import rd.data.model.response.Response;
import rd.data.model.response.activity.ActivityTargetResponse;
import rd.data.model.response.activity.ActivityTargetWithClassNameResponse;
import rd.service.activity.ActivityTargetService;
import rd.service.course.CourseService;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/admin/activity/targets")
public class AdminActivityTargetController {
private final ActivityTargetService activityTargetService;
private final CourseService courseService;
public AdminActivityTargetController(ActivityTargetService activityTargetService, CourseService courseService) {
this.activityTargetService = activityTargetService;
this.courseService = courseService;
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@GetMapping("/list")
public Response<List<ActivityTargetWithClassNameResponse>> listActivityTarget(@RequestParam("act") Long activityId) {
var activityTargetList = activityTargetService.getActivityTargetList(activityId);
var activityTargetResponseList = activityTargetList.stream().map(activityTarget -> {
var activityTargetResponse = convertWithCourseName(activityTarget);
var courseNameList = Arrays.stream(activityTarget.getCourseList())
.map(courseId -> {
var course = courseService.getCourse(courseId);
return course == null ? (String.format("[已删除课程%d]", courseId)) : course.getName();
})
.toList();
activityTargetResponse.setCourse(courseNameList);
return activityTargetResponse;
})
.toList();
return Response.success(activityTargetResponseList);
}
private ActivityTargetWithClassNameResponse convertWithCourseName(ActivityTarget activityTarget) {
ActivityTargetWithClassNameResponse activityTargetWithClassNameResponse = new ActivityTargetWithClassNameResponse();
activityTargetWithClassNameResponse.setId(activityTarget.getId());
activityTargetWithClassNameResponse.setActivity(activityTarget.getActivity());
activityTargetWithClassNameResponse.setGrade(activityTarget.getGrade());
activityTargetWithClassNameResponse.setMajor(activityTarget.getMajor());
activityTargetWithClassNameResponse.setCreateTime(activityTarget.getCreateTime());
activityTargetWithClassNameResponse.setEditTime(activityTarget.getEditTime());
return activityTargetWithClassNameResponse;
}
private ActivityTargetResponse convertWithCourseId(ActivityTarget activityTarget) {
ActivityTargetResponse activityTargetWithClassNameResponse = new ActivityTargetResponse();
activityTargetWithClassNameResponse.setId(activityTarget.getId());
activityTargetWithClassNameResponse.setActivity(activityTarget.getActivity());
activityTargetWithClassNameResponse.setGrade(activityTarget.getGrade());
activityTargetWithClassNameResponse.setMajor(activityTarget.getMajor());
activityTargetWithClassNameResponse.setCourse(Arrays.asList(activityTarget.getCourseList()));
activityTargetWithClassNameResponse.setCreateTime(activityTarget.getCreateTime());
activityTargetWithClassNameResponse.setEditTime(activityTarget.getEditTime());
return activityTargetWithClassNameResponse;
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@GetMapping("/info")
public Response<ActivityTargetResponse> getActivityTargetInfo(@RequestParam("id") Long id) {
var activityTarget = activityTargetService.getActivityTargetInfo(id);
return Response.success(convertWithCourseId(activityTarget));
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/add")
public Response<Object> addActivityTarget(@RequestParam("act") Long activityId,
@RequestBody ActivityTargetAddRequest activityTargetAddRequest
) {
activityTargetService.addActivityTargetCourse(activityId, convert(activityTargetAddRequest));
return Response.success();
}
private ActivityTargetAddDto convert(ActivityTargetAddRequest request) {
ActivityTargetAddDto activityTargetAddDto = new ActivityTargetAddDto();
activityTargetAddDto.setGrade(request.getGrade());
activityTargetAddDto.setMajor(request.getMajor());
activityTargetAddDto.setCourse(request.getCourse());
return activityTargetAddDto;
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/duplicate")
public Response<Object> duplicateActivityTarget(@RequestParam("src") Long src, @RequestParam("dst") Long dst) {
activityTargetService.duplicateFromExistsActivity(src, dst);
return Response.success();
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/update")
public Response<Object> updateActivityTarget(@RequestParam("id") Long id,
@RequestBody ActivityTargetUpadeRequest activityTargetUpadeRequest
) {
activityTargetService.updateActivityTargetCourse(id, convert(activityTargetUpadeRequest));
return Response.success();
}
private ActivityTargetUpdateDto convert(ActivityTargetUpadeRequest request) {
ActivityTargetUpdateDto activityTargetUpdateDto = new ActivityTargetUpdateDto();
activityTargetUpdateDto.setGrade(request.getGrade());
activityTargetUpdateDto.setMajor(request.getMajor());
activityTargetUpdateDto.setCourse(request.getCourse());
return activityTargetUpdateDto;
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/delete")
public Response<Object> deleteActivityTarget(@RequestParam("id") Long id) {
activityTargetService.removeActivityTargetCourse(id);
return Response.success();
}
}

@ -0,0 +1,59 @@
package rd.controller.course;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.dto.course.CourseDTO;
import rd.data.model.request.course.CourseRequest;
import rd.data.model.response.Response;
import rd.service.course.CourseService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/course")
public class AdminCourseController {
private final CourseService courseService;
public AdminCourseController(CourseService courseService) {
this.courseService = courseService;
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/add")
public Response<CourseDTO> add(@RequestBody CourseRequest request) {
CourseDTO dto = CourseDTO.builder()
.name(request.getName())
.courseHours(request.getCourseHours())
.springTerm(request.getSpringTerm())
.examRatio(request.getExamRatio())
.build();
var newCourse = courseService.add(dto);
return Response.success(newCourse);
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/update")
public Response<CourseDTO> update(@RequestParam("id") Long id, @RequestBody CourseRequest request) {
CourseDTO dto = CourseDTO.builder()
.name(request.getName())
.courseHours(request.getCourseHours())
.springTerm(request.getSpringTerm())
.examRatio(request.getExamRatio())
.build();
var teacherInfo = courseService.update(id, dto);
return Response.success(teacherInfo);
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/delete")
public Response<Object> delete(@RequestParam("id") Long id) {
courseService.delete(id);
return Response.success();
}
}

@ -0,0 +1,175 @@
package rd.controller.course;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.net.URLEncodeUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletResponse;
import rd.data.code.ServiceCode;
import rd.data.dto.FileByteDataWrapper;
import rd.data.dto.course.CourseDTO;
import rd.data.dto.course.CourseNameDTO;
import rd.data.db.CourseScheduleSelectionInfo;
import rd.data.db.table.Course;
import rd.data.db.table.StudentInfo;
import rd.data.model.response.PaginationWrapper;
import rd.data.model.response.Response;
import rd.service.course.CourseService;
import rd.service.course.CourseTeacherService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
@RestController
@RequestMapping("/course")
public class CourseController {
private final CourseService courseService;
private final ObjectMapper objectMapper;
private final CourseTeacherService courseTeacherService;
public CourseController(CourseService courseService,
ObjectMapper objectMapper, CourseTeacherService courseTeacherService) {
this.courseService = courseService;
this.objectMapper = objectMapper;
this.courseTeacherService = courseTeacherService;
}
@GetMapping("/list")
public Response<PaginationWrapper<List<CourseDTO>>> list(
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
) {
var result = courseService.list(page, pageSize);
return Response.success(result);
}
@GetMapping("/list-names")
public Response<PaginationWrapper<List<CourseNameDTO>>> listCourseName(
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
) {
var result = courseService.listCourseName(page, pageSize);
return Response.success(result);
}
@GetMapping("/info")
public Response<CourseDTO> info(@RequestParam(value = "id") Long id) {
var result = courseService.getCourseDTO(id);
return Response.success(result);
}
@SaCheckRole(value = {"TEACHER", "ADMIN"}, mode = SaMode.OR)
@GetMapping("/get-selected-students")
public Response<List<CourseScheduleSelectionInfo>> getSelectedStudents(
@RequestParam("course") Long courseId, @RequestParam("term") String term,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
) {
var courseScheduleSelectionInfoList = courseService.getSelectedStudentList(courseId, term);
return Response.success(courseScheduleSelectionInfoList);
}
@SaCheckRole(value = {"TEACHER", "ADMIN"}, mode = SaMode.OR)
@GetMapping("/get-not-selected-students")
public Response<List<StudentInfo>> getNotSelectedStudents(
@RequestParam("course") Long courseId, @RequestParam("term") String term,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
) {
var courseScheduleSelectionInfoList = courseService.getNotSelectStudentList(courseId, term);
return Response.success(courseScheduleSelectionInfoList);
}
@SaCheckRole(value = {"TEACHER", "ADMIN"}, mode = SaMode.OR)
@GetMapping("/export-students")
public void exportSelectedStudents(@RequestParam("course") Long course,
@RequestParam("term") String term,
HttpServletResponse response
) throws IOException {
if (course == null) {
Response<String> responseData = Response.error(ServiceCode.ParamWrong);
response.setContentType("application/json");
response.getWriter().write(objectMapper.writeValueAsString(responseData));
return;
}
var data = courseService.exportSelectedStudents(course, term);
var filename = String.format("exported_students_%s_%s.xlsx", data.getFileName(), term);
this.responseExcelFile(response, URLEncodeUtil.encodeAll(filename), data);
}
@SaCheckRole(value = {"TEACHER", "ADMIN"}, mode = SaMode.OR)
@GetMapping("/export-not-select-students")
public void exportNotSelectStudents(@RequestParam("course") Long course,
@RequestParam("term") String term,
HttpServletResponse response
) throws IOException {
if (course == null) {
Response<String> responseData = Response.error(ServiceCode.ParamWrong);
response.setContentType("application/json");
response.getWriter().write(objectMapper.writeValueAsString(responseData));
return;
}
var data = courseService.exportNotSelectStudents(course, term);
var filename = String.format("exported_not_select_students_%s_%s.xlsx", data.getFileName(), term);
this.responseExcelFile(response, URLEncodeUtil.encodeAll(filename), data);
}
private void responseExcelFile(HttpServletResponse response,
String filename, FileByteDataWrapper data
) throws IOException {
if (data == null) {
Response<String> responseData = Response.success("数据是空的");
response.setContentType("application/json");
response.getWriter().write(objectMapper.writeValueAsString(responseData));
return;
}
response.setContentLength(data.getData().length);
response.setContentType("application/octet-stream");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", filename));
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.getOutputStream().write(data.getData());
}
@SaCheckRole(value = {"TEACHER", "ADMIN"}, mode = SaMode.OR)
@GetMapping("/teacher-courses")
public Response<List<CourseDTO>> getCourseForTeacher(@RequestParam(value = "teacher", required = false) Long teacher) {
if (teacher == null) {
teacher = StpUtil.getLoginIdAsLong();
}
var courseList = courseTeacherService.getCourseForTeacher(teacher);
var courseDTOList = courseList.stream().map(CourseController::convert).toList();
return Response.success(courseDTOList);
}
private static CourseDTO convert(Course course) {
CourseDTO courseDTO = new CourseDTO();
courseDTO.setId(course.getId());
courseDTO.setName(course.getName());
courseDTO.setCourseHours(course.getCourseHours());
courseDTO.setSpringTerm(course.getSpringTerm());
courseDTO.setExamRatio(course.getExamRatio());
courseDTO.setDistribution(course.getDistribution());
return courseDTO;
}
}

@ -0,0 +1,72 @@
package rd.controller.course;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.model.request.course.CourseTeacherUpdateRequest;
import rd.data.model.response.Response;
import rd.data.model.response.course.CourseTeacherResponse;
import rd.service.course.CourseTeacherService;
import org.springframework.web.bind.annotation.*;
import java.util.HashSet;
import java.util.List;
@RestController
@RequestMapping("/course/teachers")
public class CourseTeacherController {
private final CourseTeacherService courseTeacherService;
public CourseTeacherController(CourseTeacherService courseTeacherService) {
this.courseTeacherService = courseTeacherService;
}
@GetMapping("/list")
public Response<List<CourseTeacherResponse>> getCourseTeachers(@RequestParam("course") Long course) {
var courseTeacherList = courseTeacherService.getCourseTeacherList(course);
var courseTeacherResponseList = courseTeacherList.stream()
.map(teacherInfo -> new CourseTeacherResponse(teacherInfo.getId(), teacherInfo.getName()))
.toList();
return Response.success(courseTeacherResponseList);
}
@SaCheckRole({"ADMIN"})
@PostMapping("/add")
public Response<List<CourseTeacherResponse>> addCourseTeacher(@RequestParam("course") Long courseId,
@RequestParam("teacher") Long teacherId
) {
var courseTeacherList = courseTeacherService.addCourseTeacher(courseId, teacherId);
var courseTeacherResponseList = courseTeacherList.stream()
.map(teacherInfo -> new CourseTeacherResponse(teacherInfo.getId(), teacherInfo.getName()))
.toList();
return Response.success(courseTeacherResponseList);
}
@SaCheckRole({"ADMIN"})
@PostMapping("/remove")
public Response<List<CourseTeacherResponse>> removeCourseTeacher(@RequestParam("course") Long courseId,
@RequestParam("teacher") Long teacherId
) {
var courseTeacherList = courseTeacherService.removeCourseTeacher(courseId, teacherId);
var courseTeacherResponseList = courseTeacherList.stream()
.map(teacherInfo -> new CourseTeacherResponse(teacherInfo.getId(), teacherInfo.getName()))
.toList();
return Response.success(courseTeacherResponseList);
}
@SaCheckRole({"ADMIN"})
@PostMapping("/update")
public Response<List<CourseTeacherResponse>> updateCourseTeacher(@RequestParam("course") Long courseId,
@RequestBody CourseTeacherUpdateRequest courseTeacherUpdateRequest
) {
var courseTeacherIdSet = new HashSet<>(courseTeacherUpdateRequest.getTeachers());
var courseTeacherList = courseTeacherService.updateCourseTeacherList(courseId, courseTeacherIdSet);
var courseTeacherResponseList = courseTeacherList.stream()
.map(teacherInfo -> new CourseTeacherResponse(teacherInfo.getId(), teacherInfo.getName()))
.toList();
return Response.success(courseTeacherResponseList);
}
}

@ -0,0 +1,76 @@
package rd.controller.course;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import rd.data.dto.course.CourseDTO;
import rd.data.db.table.Course;
import rd.data.model.response.Response;
import rd.service.activity.ActivityService;
import rd.service.activity.ActivityTargetService;
import rd.service.course.CourseService;
import rd.service.user.StudentUserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/student/course")
public class StudentCourseController {
private final CourseService courseService;
private final ActivityTargetService activityTargetService;
private final StudentUserService studentUserService;
private final ActivityService activityService;
public StudentCourseController(CourseService courseService,
ActivityTargetService activityTargetService,
StudentUserService studentUserService,
ActivityService activityService) {
this.courseService = courseService;
this.activityTargetService = activityTargetService;
this.studentUserService = studentUserService;
this.activityService = activityService;
}
@SaCheckLogin
@SaCheckRole("STUDENT")
@GetMapping("/candidate")
public Response<List<CourseDTO>> listCandidate(@RequestParam(value = "act", required = false) Long activityId) {
Long uid = StpUtil.getLoginIdAsLong();
var studentInfo = studentUserService.getInfoById(uid);
if (activityId == null) {
var currentActivity = activityService.getCurrentActivity();
if (currentActivity == null) {
return Response.success(new ArrayList<>());
}
activityId = currentActivity.getId();
}
var courseIdList = activityTargetService.getMajorGradeActivityCandidateCourses(
studentInfo.major(), studentInfo.grade(), activityId
);
var courseIdMap = courseService.getCourse(courseIdList);
var courseList = courseIdMap.values().stream()
.map(this::convertCourse)
.toList();
return Response.success(courseList);
}
private CourseDTO convertCourse(Course course) {
CourseDTO courseDTO = new CourseDTO();
courseDTO.setId(course.getId());
courseDTO.setName(course.getName());
courseDTO.setCourseHours(course.getCourseHours());
courseDTO.setSpringTerm(course.getSpringTerm());
return courseDTO;
}
}

@ -0,0 +1,35 @@
package rd.controller.major;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.db.table.Major;
import rd.data.model.response.Response;
import rd.service.major.MajorService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/major")
public class AdminMajorController {
private final MajorService majorService;
public AdminMajorController(MajorService majorService) {
this.majorService = majorService;
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/add")
public Response<Major> add(@RequestParam("name") String name) {
Major major = majorService.addMajorIfNotExists(name);
return Response.success(major);
}
@SaCheckLogin
@SaCheckRole("ADMIN")
@PostMapping("/delete")
public Response<Object> delete(@RequestParam("id") Long id) {
majorService.deleteMajor(id);
return Response.success();
}
}

@ -0,0 +1,34 @@
package rd.controller.major;
import rd.data.db.table.Major;
import rd.data.model.response.Response;
import rd.service.major.MajorService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Set;
@RestController
@RequestMapping("/major")
public class PublicMajor {
private final MajorService majorService;
public PublicMajor(MajorService majorService) {
this.majorService = majorService;
}
@GetMapping("/info")
public Response<Major> get(@RequestParam("id") Long id) {
Major major = majorService.getMajor(id);
return Response.success(major);
}
@GetMapping("/list")
public Response<Set<Major>> list() {
var majorList = majorService.listAllMajor();
return Response.success(majorList);
}
}

@ -0,0 +1,68 @@
package rd.controller.schedule;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.dto.schedule.CourseScheduleDTO;
import rd.data.db.table.CourseSchedule;
import rd.data.model.request.schedule.CourseScheduleRequest;
import rd.data.model.response.Response;
import rd.service.schedule.CourseScheduleService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/course-schedule")
public class AdminScheduleController {
private final CourseScheduleService courseScheduleService;
public AdminScheduleController(CourseScheduleService courseScheduleService) {
this.courseScheduleService = courseScheduleService;
}
@SaCheckRole("ADMIN")
@PostMapping("/add")
public Response<CourseSchedule> add(@RequestParam("course") Long courseId,
@RequestBody CourseScheduleRequest request) {
var newCourse = courseScheduleService.add(courseId, convert(request));
return Response.success(newCourse);
}
@SaCheckRole("ADMIN")
@RequestMapping("/clone")
public Response<Object> clone(@RequestParam("course") Long course,
@RequestParam("from") String sourceTerm,
@RequestParam("to") String targetTerm) {
courseScheduleService.cloneSchedule(course, sourceTerm, targetTerm);
return Response.success();
}
@SaCheckRole("ADMIN")
@PostMapping("/update")
public Response<CourseSchedule> update(@RequestParam("id") Long id, @RequestBody CourseScheduleRequest request) {
var dto = convert(request);
var newCourse = courseScheduleService.update(id, dto);
return Response.success(newCourse);
}
private CourseScheduleDTO convert(CourseScheduleRequest request) {
CourseScheduleDTO dto = new CourseScheduleDTO();
dto.setStartWeek(request.getStartWeek());
dto.setEndWeek(request.getEndWeek());
dto.setTime(request.getEndWeek());
dto.setWeekday(request.getWeekday());
dto.setAcademicTerm(request.getTerm());
dto.setPlace(request.getPlace());
dto.setTime(request.getSection());
return dto;
}
@SaCheckRole("ADMIN")
@PostMapping("/delete")
public Response<Object> delete(@RequestParam("id") Long id) {
courseScheduleService.delete(id);
return Response.success();
}
}

@ -0,0 +1,59 @@
package rd.controller.schedule;
import rd.data.dto.schedule.CourseScheduleDTO;
import rd.data.model.response.PaginationWrapper;
import rd.data.model.response.Response;
import rd.service.schedule.CourseScheduleService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/course-schedule")
public class ScheduleController {
private final CourseScheduleService courseScheduleService;
public ScheduleController(CourseScheduleService courseScheduleService) {
this.courseScheduleService = courseScheduleService;
}
@RequestMapping("/list")
public Response<PaginationWrapper<List<CourseScheduleDTO>>> list(
@RequestParam(value = "course") Long course,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize,
@RequestParam(value = "term", required = false) String term
) {
if (term == null || term.isEmpty() | term.equals("全部")) {
term = null;
}
var result = courseScheduleService.getScheduleOfCourse(course, term, page, pageSize);
return Response.success(result);
}
@RequestMapping("/list-available")
public Response<List<CourseScheduleDTO>> getAllForCourse(
@RequestParam(value = "course") Long course,
@RequestParam(value = "term") String term
) {
var result = courseScheduleService.getTermCourseSchedule(course, term);
return Response.success(result);
}
@RequestMapping("/info")
public Response<CourseScheduleDTO> info(@RequestParam("id") Long id) {
var result = courseScheduleService.getScheduleDTO(id);
return Response.success(result);
}
@RequestMapping("/selected-count")
public Response<Integer> selectCount(@RequestParam("id") Long id) {
var result = courseScheduleService.getSelectedCount(id);
return Response.success(result);
}
}

@ -0,0 +1,102 @@
package rd.controller.schedule;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import rd.data.dto.schedule.CourseScheduleDetailDTO;
import rd.data.dto.schedule.CourseScheduleWithCourseNameDTO;
import rd.data.db.CourseScheduleWithCourseIdName;
import rd.data.db.table.TeacherInfo;
import rd.data.model.response.Response;
import rd.service.schedule.CourseScheduleService;
import rd.service.schedule.StudentCourseScheduleService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import rd.util.StringUtil;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/student/course-schedule")
public class StudentScheduleController {
private final CourseScheduleService courseScheduleService;
private final StudentCourseScheduleService studentCourseScheduleService;
public StudentScheduleController(CourseScheduleService courseScheduleService,
StudentCourseScheduleService studentCourseScheduleService) {
this.courseScheduleService = courseScheduleService;
this.studentCourseScheduleService = studentCourseScheduleService;
}
@SaCheckRole("STUDENT")
@RequestMapping("/result")
public Response<List<CourseScheduleDetailDTO>> list(
@RequestParam(value = "term", required = false, defaultValue = "") String term
) {
if (term == null || term.isEmpty()) {
term = StringUtil.getCurrentTermString();
}
var uid = StpUtil.getLoginIdAsLong();
var schedules = courseScheduleService.getStudentTermSchedule(uid, term);
var result = schedules.stream().map(StudentScheduleController::convert).toList();
return Response.success(result);
}
private static CourseScheduleDetailDTO convert(CourseScheduleWithCourseIdName courseScheduleWithCourseIdName) {
CourseScheduleDetailDTO courseScheduleDetailDTO = new CourseScheduleDetailDTO();
courseScheduleDetailDTO.setCourseId(courseScheduleWithCourseIdName.getCourseId());
courseScheduleDetailDTO.setScheduleId(courseScheduleWithCourseIdName.getScheduleId());
courseScheduleDetailDTO.setCourseName(courseScheduleWithCourseIdName.getCourseName());
courseScheduleDetailDTO.setCourseHours(courseScheduleWithCourseIdName.getCourseHours());
courseScheduleDetailDTO.setStartWeek(courseScheduleWithCourseIdName.getStartWeek());
courseScheduleDetailDTO.setEndWeek(courseScheduleWithCourseIdName.getEndWeek());
courseScheduleDetailDTO.setTime(courseScheduleWithCourseIdName.getTime());
courseScheduleDetailDTO.setWeekday(courseScheduleWithCourseIdName.getWeekday());
courseScheduleDetailDTO.setAcademicTerm(courseScheduleWithCourseIdName.getAcademicTerm());
courseScheduleDetailDTO.setSpringTerm(courseScheduleWithCourseIdName.getSpringTerm());
courseScheduleDetailDTO.setPlace(courseScheduleWithCourseIdName.getPlace());
courseScheduleDetailDTO.setExamRatio(courseScheduleWithCourseIdName.getExamRatio());
courseScheduleDetailDTO.setCreateTime(courseScheduleWithCourseIdName.getCreateTime());
return courseScheduleDetailDTO;
}
@SaCheckRole("STUDENT")
@RequestMapping("/select")
public Response<Object> select(@RequestParam("schedule") Long schedule,
@RequestParam("activity") Long activity
) {
Long uid = StpUtil.getLoginIdAsLong();
studentCourseScheduleService.selectSchedule(uid, schedule, activity);
return Response.success();
}
@SaCheckRole("STUDENT")
@RequestMapping("/unselect")
public Response<Object> unselect(@RequestParam("id") Long schedule) {
Long uid = StpUtil.getLoginIdAsLong();
studentCourseScheduleService.unselect(uid, schedule);
return Response.success();
}
@SaCheckRole("STUDENT")
@RequestMapping("/check-selected")
public Response<Boolean> select(@RequestParam("id") Long schedule) {
Long uid = StpUtil.getLoginIdAsLong();
var result = studentCourseScheduleService.isStudentSelected(uid, schedule);
return Response.success(result);
}
}

@ -0,0 +1,32 @@
package rd.controller.schedule;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import rd.data.db.CourseScheduleWithCourseIdName;
import rd.data.model.response.Response;
import rd.service.schedule.TeacherCourseScheduleService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/teacher/course-schedule")
public class TeacherScheduleController {
private final TeacherCourseScheduleService teacherCourseScheduleService;
public TeacherScheduleController(TeacherCourseScheduleService teacherCourseScheduleService) {
this.teacherCourseScheduleService = teacherCourseScheduleService;
}
@SaCheckRole("TEACHER")
@RequestMapping("/teacher-schedules")
public Response<List<CourseScheduleWithCourseIdName>> list(@RequestParam("term") String term) {
var uid = StpUtil.getLoginIdAsLong();
var result = teacherCourseScheduleService.getTeacherSchedule(uid, term);
return Response.success(result);
}
}

@ -0,0 +1,66 @@
package rd.controller.score;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.net.URLEncodeUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletResponse;
import rd.data.code.ServiceCode;
import rd.data.model.response.Response;
import rd.service.score.ScoreService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
@RequestMapping("/score")
public class ScoreController {
private final ScoreService scoreService;
private final ObjectMapper objectMapper;
public ScoreController(ScoreService scoreService, ObjectMapper objectMapper) {
this.scoreService = scoreService;
this.objectMapper = objectMapper;
}
@SaCheckRole(value = {"TEACHER", "ADMIN"}, mode = SaMode.OR)
@RequestMapping("/export")
public void exportCourseTermScoreList(@RequestParam("course") Long course,
@RequestParam("term") String term,
HttpServletResponse response
) throws IOException {
if (course == null) {
Response<String> responseData = Response.error(ServiceCode.ParamWrong);
response.setContentType("application/json");
response.getWriter().write(objectMapper.writeValueAsString(responseData));
return;
}
var data = scoreService.exportTermCourseAllStudentScoreExcel(course, term);
if (data == null) {
Response<String> responseData = Response.success("数据是空的");
response.setContentType("application/json");
response.getWriter().write(objectMapper.writeValueAsString(responseData));
return;
}
response.setContentLength(data.getData().length);
response.setContentType("application/octet-stream");
var filename = String.format("export_score_%s_%s_%d.xlsx", data.getFileName(), term, course);
filename = URLEncodeUtil.encodeAll(filename);
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", filename));
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.getOutputStream().write(data.getData());
}
}

@ -0,0 +1,31 @@
package rd.controller.score;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import rd.data.dto.score.StudentScore;
import rd.data.model.response.Response;
import rd.service.score.ScoreService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/student/score")
public class StudentScoreController {
private final ScoreService scoreService;
public StudentScoreController(ScoreService scoreService) {
this.scoreService = scoreService;
}
@SaCheckRole("STUDENT")
@RequestMapping("/all")
public Response<List<StudentScore>> getAll() {
var uid = StpUtil.getLoginIdAsLong();
var result = scoreService.getStudentAllScore(uid, null);
return Response.success(result);
}
}

@ -0,0 +1,43 @@
package rd.controller.score;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.dto.score.CourseScoreInfoDto;
import rd.data.model.response.Response;
import rd.service.score.ScoreService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/teacher/score")
public class TeacherScoreController {
private final ScoreService scoreService;
public TeacherScoreController(ScoreService scoreService) {
this.scoreService = scoreService;
}
@SaCheckRole("TEACHER")
@RequestMapping("/list-students")
public Response<List<CourseScoreInfoDto>> listStudents(@RequestParam("course") Long courseId,
@RequestParam("term") String term
) {
var result = scoreService.getCourseTermAllSelectedStudentScore(courseId, term);
return Response.success(result);
}
@SaCheckRole("TEACHER")
@PostMapping("/update")
public Response<Object> update(@RequestParam(value = "scoreId", required = false) Long scoreId,
@RequestParam("course") Long courseId, @RequestParam("term") String term,
@RequestBody CourseScoreInfoDto courseScoreInfoDto) {
scoreService.insertOrUpdateScore(scoreId, courseId, term, courseScoreInfoDto);
return Response.success();
}
}

@ -0,0 +1,79 @@
package rd.controller.student;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.code.ServiceCode;
import rd.data.dto.user.student.BasicStudentInfoDto;
import rd.data.dto.user.student.BasicStudentInfoWithMajorNameDto;
import rd.data.db.table.StudentInfo;
import rd.data.db.table.TeacherInfo;
import rd.data.model.request.admin.StudentAddWithMajorIdRequest;
import rd.data.model.request.admin.StudentAddWithMajorNameRequest;
import rd.data.model.response.Response;
import rd.service.user.StudentUserService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/user/student")
public class AdminStudentController {
private final StudentUserService studentUserService;
public AdminStudentController(StudentUserService studentUserService) {
this.studentUserService = studentUserService;
}
@SaCheckRole("ADMIN")
@PostMapping("/add")
public Response<StudentInfo> add(@RequestBody StudentAddWithMajorIdRequest request) {
var dto = new BasicStudentInfoDto(
request.studentNumber(), request.studentName(), request.majorId()
);
var teacherInfo = studentUserService.add(dto);
return Response.success(teacherInfo);
}
//
// @SaCheckRole("ADMIN")
// @PostMapping("/add-batch")
// public Response<StudentInfo> addBatch(@RequestBody StudentBatchAddRequest request) {
// var dto = new BasicStudentInfoDto(request.studentNumber(), request.studentName(), request.major());
//
// var teacherInfo = studentUserService.add(dto);
// return Response.success(teacherInfo);
// }
@SaCheckRole("ADMIN")
@PostMapping("/add-with-auto-major")
public Response<StudentInfo> addWithAutoMajor(@RequestBody StudentAddWithMajorNameRequest request) {
if (request.studentNumber() == null || request.studentName() == null || request.majorName() == null) {
return Response.error(ServiceCode.ParamWrong);
}
var dto = new BasicStudentInfoWithMajorNameDto(
request.studentNumber(), request.studentName(), request.majorName()
);
var teacherInfo = studentUserService.addWithAutoMajor(dto);
return Response.success(teacherInfo);
}
//
// @SaCheckRole("ADMIN")
// @PostMapping("/update")
// public Response<StudentInfo> update(@RequestParam("id") String id, @RequestBody StudentAddRequest request) {
// String username = request.studentNumber();
// String teacherName = request.studentName();
// String initialPassword = request.initialPassword();
//
// var dto = new BasicStudentInfoDto(request.studentNumber(), request.studentName());
//
// var teacherInfo = studentUserService.update(id, dto);
//
// return Response.success(teacherInfo);
// }
@SaCheckRole("ADMIN")
@PostMapping("/delete")
public Response<TeacherInfo> delete(@RequestParam("id") Long id) {
studentUserService.delete(id);
return Response.success();
}
}

@ -0,0 +1,38 @@
package rd.controller.student;
import rd.data.dto.user.student.StudentUserInfoDTO;
import rd.data.db.table.StudentInfo;
import rd.data.model.response.PaginationWrapper;
import rd.data.model.response.Response;
import rd.service.user.StudentUserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/student")
public class StudentController {
private final StudentUserService studentUserService;
public StudentController(StudentUserService studentUserService) {
this.studentUserService = studentUserService;
}
@GetMapping("/list")
public Response<PaginationWrapper<List<StudentInfo>>> list(
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
) {
var result = studentUserService.list(page, pageSize);
return Response.success(result);
}
@GetMapping("/info")
public Response<StudentUserInfoDTO> info(@RequestParam(value = "id") Long id) {
var result = studentUserService.getInfoById(id);
return Response.success(result);
}
}

@ -0,0 +1,52 @@
package rd.controller.teacher;
import cn.dev33.satoken.annotation.SaCheckRole;
import rd.data.dto.user.teacher.TeacherUserDTO;
import rd.data.db.table.TeacherInfo;
import rd.data.model.request.admin.TeacherAddRequest;
import rd.data.model.response.Response;
import rd.service.user.TeacherUserService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/admin/user/teacher")
public class AdminTeacherController {
private final TeacherUserService teacherUserService;
public AdminTeacherController(TeacherUserService teacherUserService) {
this.teacherUserService = teacherUserService;
}
@SaCheckRole("ADMIN")
@PostMapping("/add")
public Response<TeacherInfo> add(@RequestBody TeacherAddRequest request) {
String username = request.username();
String teacherName = request.teacherName();
String initialPassword = request.initialPassword();
TeacherUserDTO dto = new TeacherUserDTO(username, teacherName, initialPassword);
var teacherInfo = teacherUserService.add(dto);
return Response.success(teacherInfo);
}
@SaCheckRole("ADMIN")
@PostMapping("/update")
public Response<TeacherInfo> update(@RequestParam("id") Long id, @RequestBody TeacherAddRequest request) {
String username = request.username();
String teacherName = request.teacherName();
String initialPassword = request.initialPassword();
TeacherUserDTO dto = new TeacherUserDTO(username, teacherName, initialPassword);
var teacherInfo = teacherUserService.update(id, dto);
return Response.success(teacherInfo);
}
@SaCheckRole("ADMIN")
@PostMapping("/delete")
public Response<TeacherInfo> delete(@RequestParam("id") Long id) {
teacherUserService.delete(id);
return Response.success();
}
}

@ -0,0 +1,35 @@
package rd.controller.teacher;
import rd.data.dto.user.teacher.TeacherUserInfoDTO;
import rd.data.db.table.TeacherInfo;
import rd.data.model.response.PaginationWrapper;
import rd.data.model.response.Response;
import rd.service.user.TeacherUserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/teacher")
public class TeacherController {
private final TeacherUserService teacherUserService;
public TeacherController(TeacherUserService teacherUserService) {
this.teacherUserService = teacherUserService;
}
@GetMapping("/list")
public Response<PaginationWrapper<List<TeacherInfo>>> list(
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
) {
var result = teacherUserService.list(page, pageSize);
return Response.success(result);
}
@GetMapping("/info")
public Response<TeacherUserInfoDTO> info(@RequestParam(value = "id") Long id) {
var result = teacherUserService.getUserInfoById(id);
return Response.success(result);
}
}

@ -0,0 +1,120 @@
package rd.controller.user;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.digest.BCrypt;
import lombok.extern.slf4j.Slf4j;
import rd.data.code.ServiceCode;
import rd.data.db.table.UserBasic;
import rd.data.enums.UserType;
import rd.data.model.request.auth.UserLoginRequest;
import rd.data.model.response.Response;
import rd.data.model.response.auth.UserLoginStatusResponse;
import rd.data.model.response.user.UserBasicInfo;
import rd.service.user.StudentUserService;
import rd.service.user.UserBasicService;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 登录认证Controller
*/
@Slf4j
@RestController
@RequestMapping("/user/auth")
public class UserAuthController {
private final UserBasicService userBasicService;
private final StudentUserService studentUserService;
public UserAuthController(UserBasicService userBasicService, StudentUserService studentUserService) {
this.userBasicService = userBasicService;
this.studentUserService = studentUserService;
}
@RequestMapping("/login")
public Response<UserBasicInfo> login(@RequestBody UserLoginRequest loginRequest) {
String username = loginRequest.username();
String password = loginRequest.password();
UserBasic userBasic = userBasicService.getUserBasicByUsername(username);
if (userBasic == null || userBasic.getPassword() == null || userBasic.getPassword().isEmpty()) {
// 用户不存在,尝试从教务处获取用户信息
log.info("用户'{}'不存在,尝试从教务处获取用户信息", username);
try {
var newStudentDto = studentUserService.tryAddStudentFromOfficial(username, password);
userBasic = newStudentDto.userBasic();
} catch (Exception e) {
return Response.error(ServiceCode.StuNumDoesNotExists,
"从教务处获取用户信息失败,\n" +
"如果是非学生学生用户,请检查用户名是否正确;\n" +
"如果是学生用户,请检查用户名和密码,或者再重试重试一下。\nException:" + e
);
}
} else {
// 用户已经存在,直接从数据库获取数据
if (!BCrypt.checkpw(password, userBasic.getPassword())) {
return Response.error(ServiceCode.UserPasswordWrong);
}
}
StpUtil.login(userBasic.getId());
UserType userType = switch (userBasic.getType()) {
case 0 -> UserType.STUDENT;
case 1 -> UserType.TEACHER;
case 2 -> UserType.ADMIN;
default -> {
log.warn("未知的用户类型:{}", userBasic.getType());
yield UserType.STUDENT;
}
};
var basicInfoResponse = UserBasicInfo.builder()
.id(userBasic.getId())
.username(userBasic.getUsername())
.userType(userType)
.build();
return Response.success(basicInfoResponse);
}
@RequestMapping("/logout")
public Response<String> logout() {
StpUtil.logout();
return Response.success();
}
@RequestMapping("/check")
public Response<UserLoginStatusResponse> checkLogin() {
boolean login = StpUtil.isLogin();
if (!login) {
return Response.success(new UserLoginStatusResponse(null, null, false));
}
Long uid = StpUtil.getLoginIdAsLong();
String role = StpUtil.getRoleList().get(0);
return Response.success(new UserLoginStatusResponse(uid, role, true));
}
@SaCheckLogin
@RequestMapping("/modify-password")
public Response<Object> modifyPassword(@RequestParam("old") String oldPassword,
@RequestParam("new") String newPassword) {
Long uid = StpUtil.getLoginIdAsLong();
var userBasic = userBasicService.getUserBasicById(uid);
if (!BCrypt.checkpw(oldPassword, userBasic.getPassword())) {
return Response.error(ServiceCode.UserPasswordWrong);
}
userBasicService.updatePassword(uid, newPassword);
StpUtil.logout();
return Response.success();
}
}

@ -0,0 +1,35 @@
package rd.controller.user;
import cn.dev33.satoken.stp.StpUtil;
import rd.data.code.ServiceCode;
import rd.data.enums.UserType;
import rd.data.model.response.Response;
import rd.service.user.UserInfoService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user/info")
public class UserInfoController {
private final UserInfoService userInfoService;
public UserInfoController(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
@RequestMapping("")
public Object getUserInfo(@RequestParam("uid") Long uid, @RequestParam("userType") String userType) {
// 如果不是自己的账号并且也不是管理员
if (!uid.equals(StpUtil.getLoginIdAsLong()) && !StpUtil.hasRole(UserType.ADMIN.name())) {
return Response.error(ServiceCode.PermissionDenied);
}
Object userInfo = switch (userType) {
case "STUDENT" -> userInfoService.getAsStudent(uid);
case "TEACHER" -> userInfoService.getAsTeacher(uid);
default -> null;
};
return Response.success(userInfo);
}
}

@ -0,0 +1,19 @@
package rd.dao;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class BatchSQLInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertBatchSomeColumn());
return methodList;
}
}

@ -0,0 +1,16 @@
package rd.dao.mapper.activity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.Activity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
@Mapper
public interface ActivityMapper extends BaseMapper<Activity> {
List<Activity> getConflictActivity(@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end
);
}

@ -0,0 +1,12 @@
package rd.dao.mapper.activity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.ActivityTarget;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ActivityTargetMapper extends BaseMapper<ActivityTarget> {
int insertBatchSomeColumn(List<ActivityTarget> entityList);
}

@ -0,0 +1,36 @@
package rd.dao.mapper.course;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.Course;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CourseMapper extends BaseMapper<Course> {
/**
* 获取某专业某一年级在对应活动中的可选课程
*
* @param grade 年级
* @param major 专业id
* @param activity 活动id
* @return
*/
List<Course> getGradeMajorActivityCandidateCourse(@Param("grade") Integer grade,
@Param("major") Long major,
@Param("activity") Long activity
);
/**
* 获取学生在对应活动中的可选课程
*
* @param studentId 学生id
* @param activity 活动id
* @return
*/
List<Course> getStudentActivityCandidateCourse(@Param("studentId") Long studentId,
@Param("activity") Long activity
);
}

@ -0,0 +1,35 @@
package rd.dao.mapper.course;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.CourseScheduleWithCourseIdName;
import rd.data.db.CourseScheduleSelectionInfo;
import rd.data.db.table.CourseSchedule;
import rd.data.db.table.CourseSelection;
import rd.data.db.table.StudentInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CourseSelectionMapper extends BaseMapper<CourseSelection> {
List<CourseScheduleWithCourseIdName> getStudentSelectedSchedulesDetail(
@Param("student") Long student,
@Param("term") String term
);
List<CourseSchedule> getStudentSelectedSchedules(@Param("student") Long student, @Param("term") String term);
Integer isStudentSelected(@Param("student") Long student,
@Param("term") String term,
@Param("course") Long course
);
List<CourseScheduleSelectionInfo> getSelectedStudentList(@Param("course") Long course,
@Param("term") String term
);
List<StudentInfo> getNotSelectStudentList(@Param("course") Long course,
@Param("term") String term
);
}

@ -0,0 +1,22 @@
package rd.dao.mapper.course;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.CourseScheduleWithCourseIdName;
import rd.data.db.table.Course;
import rd.data.db.table.CourseTeacher;
import rd.data.db.table.TeacherInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CourseTeacherMapper extends BaseMapper<CourseTeacher> {
List<CourseScheduleWithCourseIdName> getAllCourseScheduleForTeacher(@Param("teacher") Long teacher, @Param("term") String term);
List<TeacherInfo> getCourseAllTeacherInfo(@Param("course") Long course);
List<Course> getCourseForTeacher(@Param("teacher") Long teacher);
int insertBatchSomeColumn(List<CourseTeacher> entityList);
}

@ -0,0 +1,10 @@
package rd.dao.mapper.experiment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.ExperimentItem;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ExperimentItemMapper extends BaseMapper<ExperimentItem> {
}

@ -0,0 +1,9 @@
package rd.dao.mapper.major;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.Major;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MajorMapper extends BaseMapper<Major> {
}

@ -0,0 +1,22 @@
package rd.dao.mapper.schedule;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.CourseSchedule;
import rd.data.db.table.StudentInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CourseScheduleMapper extends BaseMapper<CourseSchedule> {
Object getScheduleDetailFromCourseId(String course);
Object getScheduleDetailFromScheduleId(String courseSchedule);
Integer getScheduleTotalStudent(String courseSchedule);
List<StudentInfo> getSelectedStudent(String courseSchedule);
Object getCourseScheduleDetail(@Param("id") Long id);
}

@ -0,0 +1,9 @@
package rd.dao.mapper.score;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.ExperimentScore;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ExperimentScoreMapper extends BaseMapper<ExperimentScore> {
}

@ -0,0 +1,23 @@
package rd.dao.mapper.score;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.dto.score.CourseScoreInfoDto;
import rd.data.dto.score.StudentScore;
import rd.data.db.table.Score;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ScoreMapper extends BaseMapper<Score> {
List<StudentScore> getStudentAllScore(@Param("student") Long student, @Param("term") String term);
List<CourseScoreInfoDto> getTermCourseAllSelectedStudentScore(@Param("course") Long course,
@Param("term") String term
);
void insertOrUpdateScore(@Param("score") Score score);
// void insertOrUpdateScoreBatch(@Param("scores") List<Score> score);
}

@ -0,0 +1,11 @@
package rd.dao.mapper.user;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.StudentInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface StudentInfoMapper extends BaseMapper<StudentInfo> {
void insertOrUpdate(@Param("student") StudentInfo studentInfo);
}

@ -0,0 +1,9 @@
package rd.dao.mapper.user;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.TeacherInfo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TeacherInfoMapper extends BaseMapper<TeacherInfo> {
}

@ -0,0 +1,9 @@
package rd.dao.mapper.user;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import rd.data.db.table.UserBasic;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserBasicMapper extends BaseMapper<UserBasic> {
}

@ -0,0 +1,77 @@
package rd.dao.type;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
//@MappedTypes(List<Double>.class)
@MappedJdbcTypes(JdbcType.ARRAY)
public class DoubleListTypeHandler extends BaseTypeHandler<List<Double>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<Double> parameter, JdbcType jdbcType) throws SQLException {
String typeName = "Double";
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter.toArray());
ps.setArray(i, array);
}
@Override
public List<Double> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getArray(rs.getArray(columnName));
}
@Override
public List<Double> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getArray(rs.getArray(columnIndex));
}
@Override
public List<Double> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getArray(cs.getArray(columnIndex));
}
private List<Double> getArray(Array array) {
if (array == null) {
return null;
}
try {
var arr = array.getArray();
var result = new ArrayList<Double>();
if (arr instanceof Double[] doubleArr) {
Collections.addAll(result, doubleArr);
} else if (arr instanceof Float[] floatArr) {
for (Float floatVal : floatArr) {
result.add(floatVal.doubleValue());
}
} else if (arr instanceof Integer[] intArr) {
for (Integer intVal : intArr) {
result.add(intVal.doubleValue());
}
} else if (arr instanceof Short[] shortArr) {
for (Short shortVal : shortArr) {
result.add(shortVal.doubleValue());
}
} else if (arr instanceof Long[] longArr) {
for (Long longVal : longArr) {
result.add(longVal.doubleValue());
}
}
return result;
} catch (Exception e) {
log.error("类型转换出错:", e);
}
return null;
}
}

@ -0,0 +1,77 @@
package rd.dao.type;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
//@MappedTypes(List<Float>.class)
@MappedJdbcTypes(JdbcType.ARRAY)
public class FloatListTypeHandler extends BaseTypeHandler<List<Float>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<Float> parameter, JdbcType jdbcType) throws SQLException {
String typeName = "double";
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter.toArray());
ps.setArray(i, array);
}
@Override
public List<Float> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getArray(rs.getArray(columnName));
}
@Override
public List<Float> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getArray(rs.getArray(columnIndex));
}
@Override
public List<Float> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getArray(cs.getArray(columnIndex));
}
private List<Float> getArray(Array array) {
if (array == null) {
return null;
}
try {
var arr = array.getArray();
var result = new ArrayList<Float>();
if (arr instanceof Float[] doubleArr) {
Collections.addAll(result, doubleArr);
} else if (arr instanceof Double[] doublearr) {
for (Double intVal : doublearr) {
result.add(intVal.floatValue());
}
} else if (arr instanceof Integer[] intArr) {
for (Integer intVal : intArr) {
result.add(intVal.floatValue());
}
} else if (arr instanceof Short[] shortArr) {
for (Short shortVal : shortArr) {
result.add(shortVal.floatValue());
}
} else if (arr instanceof Long[] longArr) {
for (Long longVal : longArr) {
result.add(longVal.floatValue());
}
}
return result;
} catch (Exception e) {
log.error("类型转换出错:", e);
}
return null;
}
}

@ -0,0 +1,67 @@
package rd.dao.type;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
//@MappedTypes(List<Integer>.class)
@MappedJdbcTypes(JdbcType.ARRAY)
public class IntegerListTypeHandler extends BaseTypeHandler<List<Integer>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<Integer> parameter, JdbcType jdbcType) throws SQLException {
String typeName = "integer";
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter.toArray());
ps.setArray(i, array);
}
@Override
public List<Integer> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getArray(rs.getArray(columnName));
}
@Override
public List<Integer> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getArray(rs.getArray(columnIndex));
}
@Override
public List<Integer> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getArray(cs.getArray(columnIndex));
}
private List<Integer> getArray(Array array) {
if (array == null) {
return null;
}
try {
var arr = array.getArray();
var result = new ArrayList<Integer>();
if (arr instanceof Integer[] intArr) {
Collections.addAll(result, intArr);
} else if (arr instanceof Short[] shortArr) {
for (Short shortVal : shortArr) {
result.add(shortVal.intValue());
}
} else if (arr instanceof Long[] longArr) {
for (Long longVal : longArr) {
result.add(longVal.intValue());
}
}
return result;
} catch (Exception e) {
log.error("类型转换出错:", e);
}
return null;
}
}

@ -0,0 +1,69 @@
package rd.dao.type;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
//@MappedTypes(List<Long>.class)
@MappedJdbcTypes(JdbcType.ARRAY)
public class LongListTypeHandler extends BaseTypeHandler<List<Long>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<Long> parameter, JdbcType jdbcType) throws SQLException {
String typeName = "varchar";
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter.toArray());
ps.setArray(i, array);
}
@Override
public List<Long> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getArray(rs.getArray(columnName));
}
@Override
public List<Long> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getArray(rs.getArray(columnIndex));
}
@Override
public List<Long> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getArray(cs.getArray(columnIndex));
}
private List<Long> getArray(Array array) {
if (array == null) {
return null;
}
try {
var arr = array.getArray();
var result = new ArrayList<Long>();
if (arr instanceof Long[] longArr) {
Collections.addAll(result, longArr);
} else if (arr instanceof Integer[] intArr) {
for (Integer intVal : intArr) {
result.add(intVal.longValue());
}
} else if (arr instanceof Short[] shortArr) {
for (Short shortVal : shortArr) {
result.add(shortVal.longValue());
}
}
return result;
} catch (Exception e) {
log.error("类型转换出错:", e);
}
return null;
}
}

@ -0,0 +1,69 @@
package rd.dao.type;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
//@MappedTypes(List<Short>.class)
@MappedJdbcTypes(JdbcType.ARRAY)
public class ShortListTypeHandler extends BaseTypeHandler<List<Short>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<Short> parameter, JdbcType jdbcType) throws SQLException {
String typeName = "integer";
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter.toArray());
ps.setArray(i, array);
}
@Override
public List<Short> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getArray(rs.getArray(columnName));
}
@Override
public List<Short> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getArray(rs.getArray(columnIndex));
}
@Override
public List<Short> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getArray(cs.getArray(columnIndex));
}
private List<Short> getArray(Array array) {
if (array == null) {
return null;
}
try {
var arr = array.getArray();
var result = new ArrayList<Short>();
if (arr instanceof Short[] shortArr) {
Collections.addAll(result, shortArr);
} else if (arr instanceof Integer[] intArr) {
for (Integer intVal : intArr) {
result.add(intVal.shortValue());
}
} else if (arr instanceof Long[] longArr) {
for (Long longVal : longArr) {
result.add(longVal.shortValue());
}
}
return result;
} catch (Exception e) {
log.error("类型转换出错:", e);
}
return null;
}
}

@ -0,0 +1,55 @@
package rd.dao.type;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
//@MappedTypes(List<String>.class)
@MappedJdbcTypes(JdbcType.ARRAY)
public class StringListTypeHandler extends BaseTypeHandler<List<String>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
String typeName = "varchar";
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter.toArray());
ps.setArray(i, array);
}
@Override
public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getArray(rs.getArray(columnName));
}
@Override
public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getArray(rs.getArray(columnIndex));
}
@Override
public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getArray(cs.getArray(columnIndex));
}
private List<String> getArray(Array array) {
if (array == null) {
return null;
}
try {
var strArray = (String[]) array.getArray();
var result = new ArrayList<String>(strArray.length);
Collections.addAll(result, strArray);
return result;
} catch (Exception e) {
log.error("类型转换出错:", e);
}
return null;
}
}

@ -0,0 +1,9 @@
package rd.dao.type.json;
import java.util.ArrayList;
public abstract class BaseJsonListTypeHandler<T> extends BaseJsonTypeHandler<ArrayList<T>> {
protected BaseJsonListTypeHandler(Class<T> clazz) {
super(objectMapper.getTypeFactory().constructParametricType(ArrayList.class, clazz));
}
}

@ -0,0 +1,63 @@
package rd.dao.type.json;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
import org.postgresql.util.PGobject;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@Slf4j
public abstract class BaseJsonTypeHandler<T> extends AbstractJsonTypeHandler<T> {
protected static final ObjectMapper objectMapper = new ObjectMapper();
protected final JavaType javaType;
protected final Class<T> clazz;
protected BaseJsonTypeHandler(JavaType javaType) {
this.javaType = javaType;
this.clazz = null;
}
protected BaseJsonTypeHandler(Class<T> clazz) {
this.javaType = null;
this.clazz = clazz;
}
@Override
protected T parse(String json) {
try {
if (clazz == null) {
return objectMapper.readValue(json, javaType);
} else {
return objectMapper.readValue(json, clazz);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
PGobject obj = new PGobject();
obj.setType("jsonb");
obj.setValue(toJson(parameter));
ps.setObject(i, obj);
}
@Override
protected String toJson(T obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("对象序列化异常:", e);
}
return null;
}
}

@ -0,0 +1,15 @@
package rd.dao.type.json;
import com.fasterxml.jackson.databind.JavaType;
import java.util.HashMap;
import java.util.Map;
public class FloatMapTypeHandler extends BaseJsonTypeHandler<Map<String, String>> {
private static final JavaType FLOAT_MAP_TYPE =
objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, Float.class);
public FloatMapTypeHandler() {
super(FLOAT_MAP_TYPE);
}
}

@ -0,0 +1,9 @@
package rd.dao.type.json;
import rd.data.db.UsualScoreItem;
public class UsualScoreItemListTypeHandler extends BaseJsonListTypeHandler<UsualScoreItem> {
public UsualScoreItemListTypeHandler() {
super(UsualScoreItem.class);
}
}

@ -0,0 +1,20 @@
package rd.data;
import java.time.format.DateTimeFormatter;
public class Constants {
public static class DateTime {
public static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static final DateTimeFormatter DEFAULT_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
}
public static class Redis {
public static final String WusthelperTokenCacheKey = "rd:cache:wusthelper:token:%s";
}
public static class Wusthelper {
public static final String UndergradLogin = "/jwc/login";
public static final String UndergradStuInfo = "/jwc/get-student-info";
}
}

@ -0,0 +1,49 @@
package rd.data.code;
public enum ServiceCode {
Ok(0, "ok"),
UnknownErr(-1, "未知错误"),
ApiNotImplement(-2, "api不存在或未开放/已弃用,请检查app版本"),
ParamWrong(-3, "参数错误"),
RequestInvalid(-4, "请求无效"),
PermissionDenied(-5, "权限不正确"),
UserAuthErr(100_0000, "登录状态无效或已过期"),
OidcCodeAuthWrong(100_0001, "oidc code 无效"),
ActivityEnded(101_0000, "活动已结束"),
DataConflict(102_0000, "数据冲突"),
DataDuplicate(102_0001, "数据重复"),
DataFormatWrong(102_0002, "数据格式错误"),
DataNotExists(102_0003, "数据不存在"),
DataNotMatch(102_0004, "数据不匹配"),
BaseJwcFetch(103_0000, "wusthelper api 请求错误"),
UserNotExists(104_0000, "用户不存在"),
UserPasswordWrong(104_0001, "用户密码错误"),
StuNumDoesNotExists(104_0002, "学号不存在"),
WusthelperApiRequestErr(105_0000, "wusthelper请求错误")
;
public final int code;
public final String msg;
ServiceCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public static ServiceCode of(int code) {
for (ServiceCode serviceCode : ServiceCode.values()) {
if (serviceCode.code == code) {
return serviceCode;
}
}
return null;
}
}

@ -0,0 +1,76 @@
package rd.data.db;
import lombok.Data;
@Data
public class CourseScheduleSelectionInfo {
/**
* 学生id
*/
private Long uid;
/**
* 学号
*/
private String studentNumber;
/**
* 学生姓名
*/
private String name;
/**
* 专业id
*/
private Long major;
/**
* 年级,使用大x表示,如大二2
*/
private Integer grade;
/**
* 班级
*/
private String clazz;
/**
* 课堂id
*/
private Long schedule;
/**
* 课程id
*/
private Long course;
/**
* 开始周
*/
private Integer startWeek;
/**
* 结束周
*/
private Integer endWeek;
/**
* 节次时间,即第几节课
*/
private Integer time;
/**
* 节次时间,即第几节课
*/
private Integer weekday;
/**
* 学年学期,格式如2023-2024
*/
private String academicTerm;
/**
* 上课地点
*/
private String place;
}

@ -0,0 +1,84 @@
package rd.data.db;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class CourseScheduleWithCourseIdName implements Serializable {
/**
* 课程id
*/
private Long courseId;
/**
* 课程安排id
*/
private Long scheduleId;
/**
* 课程名
*/
private String courseName;
/**
* 课时
*/
private Integer courseHours;
/**
* 开始周
*/
private Integer startWeek;
/**
* 结束周
*/
private Integer endWeek;
/**
* 节次时间,即第几节课
*/
private Integer time;
/**
* 节次时间,即第几节课
*/
private Integer weekday;
/**
* 学年学期,格式如2023-2024
*/
private String academicTerm;
/**
* 是否春季期课程
*/
private Boolean springTerm;
/**
* 上课地点
*/
private String place;
/**
* 考试成绩占比
*/
private Float examRatio;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
}

@ -0,0 +1,7 @@
package rd.data.db;
import lombok.Builder;
@Builder
public record UsualScoreItem(String name, float score, float ratio) {
}

@ -0,0 +1,68 @@
package rd.data.db.table;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.common.base.Objects;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Activity implements Serializable {
/**
* 活动id
*/
private Long id;
/**
* 活动名称
*/
private String name;
/**
* 学期,格式如2023-2024-1
*/
private String term;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
public Activity() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Activity activity = (Activity) o;
return Objects.equal(id, activity.id);
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
}

@ -0,0 +1,54 @@
package rd.data.db.table;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.apache.ibatis.type.ArrayTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.time.LocalDateTime;
@Data
@TableName(autoResultMap = true)
public class ActivityTarget {
/**
* id
*/
private Long id;
/**
* activity
*/
private Long activity;
/**
* grade
*/
private Integer grade;
/**
* major
*/
private Long major;
/**
* course
*/
@TableField(jdbcType = JdbcType.ARRAY, typeHandler = ArrayTypeHandler.class)
private Long[] courseList;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* deleted
*/
private Boolean deleted;
}

@ -0,0 +1,63 @@
package rd.data.db.table;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import rd.dao.type.json.FloatMapTypeHandler;
//import org.apache.ibatis.type.ArrayTypeHandler;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@TableName(autoResultMap = true)
public class Course implements Serializable {
/**
* 课程id
*/
private Long id;
/**
* 课程名称
*/
private String name;
/**
* 课时
*/
private Integer courseHours;
/**
* 是否春季期课程false即是秋季期
*/
private Boolean springTerm;
/**
* 考试成绩占比
*/
private Float examRatio;
/**
* 平时分组成描述
*/
@TableField(typeHandler = FloatMapTypeHandler.class)
private Map<String, Float> distribution;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
}

@ -0,0 +1,85 @@
package rd.data.db.table;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.common.base.Objects;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@TableName(autoResultMap = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CourseSchedule implements Serializable {
/**
* 课堂id
*/
private Long id;
/**
* 课程id
*/
private Long course;
/**
* 开始周
*/
private Integer startWeek;
/**
* 结束周
*/
private Integer endWeek;
/**
* 节次时间,即第几节课
*/
private Integer time;
/**
* 节次时间,即第几节课
*/
private Integer weekday;
/**
* 学年学期,格式如2023-2024
*/
private String academicTerm;
/**
* 上课地点
*/
private String place;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
public CourseSchedule() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CourseSchedule that = (CourseSchedule) o;
return Objects.equal(id, that.id);
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
}

@ -0,0 +1,52 @@
package rd.data.db.table;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class CourseSelection implements Serializable {
/**
* 选课记录id
*/
private Long id;
/**
* 学生id
*/
private Long student;
/**
* 课堂id
*/
private Long schedule;
/**
* 课堂id
*/
private Long activity;
/**
* 学期
*/
private String term;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
public CourseSelection() {
}
}

@ -0,0 +1,41 @@
package rd.data.db.table;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class CourseTeacher implements Serializable {
/**
* 教师id
*/
@TableId(type = IdType.INPUT)
private Long teacher;
/**
* 课程id
*/
private Long course;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* deleted
*/
private Boolean deleted;
public CourseTeacher() {
}
}

@ -0,0 +1,42 @@
package rd.data.db.table;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class ExperimentItem implements Serializable {
/**
* 实验项目id
*/
private Long id;
/**
* 项目名称
*/
private String name;
/**
* 课程id
*/
private Long course;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
public ExperimentItem() {
}
}

@ -0,0 +1,17 @@
package rd.data.db.table;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @param id 成绩id
* @param student 学生id
* @param experiment 实验项目id
* @param score 实验分
* @param createTime create_time
* @param editTime edit_time
* @param deleted delete
*/
public record ExperimentScore(Long id, Long student, Long experiment, Float score, LocalDateTime createTime,
LocalDateTime editTime, Boolean deleted) implements Serializable {
}

@ -0,0 +1,58 @@
package rd.data.db.table;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.common.base.Objects;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Major implements Serializable {
/**
* 专业id
*/
@TableId(type = IdType.INPUT)
private Long id;
/**
* 专业名称
*/
private String name;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Major major = (Major) o;
return Objects.equal(id, major.id) && Objects.equal(name, major.name);
}
@Override
public int hashCode() {
return Objects.hashCode(id, name);
}
}

@ -0,0 +1,38 @@
package rd.data.db.table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Score implements Serializable {
private Long id;
private Long student;
private Long course;
private String term;
private Float usualScore;
private Float examScore;
private Float examRatio;
private LocalDateTime createTime;
private LocalDateTime editTime;
private Boolean deleted;
}

@ -0,0 +1,64 @@
package rd.data.db.table;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StudentInfo implements Serializable {
/**
* 学生id
*/
private Long id;
/**
* 学号
*/
private String studentNumber;
/**
* 学生姓名
*/
private String name;
/**
* 专业id
*/
private Long major;
/**
* 年级,使用大x表示,如大二2
*/
private Integer grade;
/**
* 班级
*/
@TableField("class")
private String clazz;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
}

@ -0,0 +1,43 @@
package rd.data.db.table;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Builder
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class TeacherInfo implements Serializable {
/**
* 教师id
*/
private Long id;
/**
* 教师姓名
*/
private String name;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
public TeacherInfo() {
}
}

@ -0,0 +1,51 @@
package rd.data.db.table;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class UserBasic implements Serializable {
/**
* 用户uuid
*/
private Long id;
/**
* 用户名,登陆用
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 用户类型
*/
private Short type;
/**
* create_time
*/
private LocalDateTime createTime;
/**
* edit_time
*/
private LocalDateTime editTime;
/**
* delete
*/
private Boolean deleted;
private String oid;
private Short status;
public UserBasic() {
}
}

@ -0,0 +1,13 @@
package rd.data.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FileByteDataWrapper {
private byte[] data;
private String fileName;
}

@ -0,0 +1,23 @@
package rd.data.dto.activity;
import lombok.Data;
import java.util.List;
@Data
public class ActivityTargetAddDto {
/**
* grade
*/
private Integer grade;
/**
* major
*/
private Long major;
/**
* course
*/
private List<Long> course;
}

@ -0,0 +1,23 @@
package rd.data.dto.activity;
import lombok.Data;
import java.util.List;
@Data
public class ActivityTargetUpdateDto {
/**
* grade
*/
private Integer grade;
/**
* major
*/
private Long major;
/**
* course
*/
private List<Long> course;
}

@ -0,0 +1,41 @@
package rd.data.dto.course;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CourseDTO {
private Long id;
/**
* 课程名称
*/
private String name;
/**
* 课时
*/
private Integer courseHours;
/**
* 是否春季期课程false即是秋季期
*/
private Boolean springTerm;
/**
* 考试成绩占比
*/
private Float examRatio;
/**
* 平时分组成描述
*/
private Map<String, Float> distribution;
}

@ -0,0 +1,19 @@
package rd.data.dto.course;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CourseNameDTO {
private Long id;
/**
* 课程名称
*/
private String name;
}

@ -0,0 +1,76 @@
package rd.data.dto.course;
import lombok.Data;
@Data
public class CourseScheduleSelectionInfoDTO {
/**
* 学生id
*/
private Long uid;
/**
* 学号
*/
private String studentNumber;
/**
* 学生姓名
*/
private String name;
/**
* 专业id
*/
private Long major;
/**
* 年级,使用大x表示,如大二2
*/
private Integer grade;
/**
* 班级
*/
private String clazz;
/**
* 课堂id
*/
private Long schedule;
/**
* 课程id
*/
private Long course;
/**
* 开始周
*/
private Integer startWeek;
/**
* 结束周
*/
private Integer endWeek;
/**
* 节次时间,即第几节课
*/
private Integer time;
/**
* 节次时间,即第几节课
*/
private Integer weekday;
/**
* 学年学期,格式如2023-2024
*/
private String academicTerm;
/**
* 上课地点
*/
private String place;
}

@ -0,0 +1,45 @@
package rd.data.dto.schedule;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CourseScheduleDTO {
private Long id;
/**
* 课程id
*/
private Long course;
/**
* 开始周
*/
private int startWeek;
/**
* 结束周
*/
private int endWeek;
/**
* 节次时间,即第几节课
*/
private int time;
/**
* 节次时间,即第几节课
*/
private int weekday;
/**
* 学年学期,格式如2023-2024
*/
private String academicTerm;
/**
* 上课地点
*/
private String place;
}

@ -0,0 +1,75 @@
package rd.data.dto.schedule;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CourseScheduleDetailDTO {
/**
* 课程id
*/
private Long courseId;
/**
* 课程安排id
*/
private Long scheduleId;
/**
* 课程名
*/
private String courseName;
/**
* 课时
*/
private Integer courseHours;
/**
* 开始周
*/
private Integer startWeek;
/**
* 结束周
*/
private Integer endWeek;
/**
* 节次时间,即第几节课
*/
private Integer time;
/**
* 节次时间,即第几节课
*/
private Integer weekday;
/**
* 学年学期,格式如2023-2024
*/
private String academicTerm;
/**
* 是否春季期课程
*/
private Boolean springTerm;
/**
* 上课地点
*/
private String place;
/**
* 考试成绩占比
*/
private Float examRatio;
/**
* create_time
*/
private LocalDateTime createTime;
}

@ -0,0 +1,67 @@
package rd.data.dto.schedule;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import rd.data.db.table.TeacherInfo;
import java.util.List;
import java.util.Map;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CourseScheduleWithCourseNameDTO {
private Long id;
private String name;
/**
* 课程id
*/
private String course;
/**
* 开始周
*/
private int startWeek;
/**
* 结束周
*/
private int endWeek;
/**
* 节次时间,即第几节课
*/
private int time;
/**
* 节次时间,即第几节课
*/
private int weekday;
/**
* 学年学期,格式如2023-2024
*/
private String academicTerm;
/**
* 上课地点
*/
private String place;
/**
* 考试成绩占比
*/
private float ratio;
/**
* 平时分组成描述
*/
private Map<String, Float> distribution;
private List<TeacherInfo> teachers;
@JsonIgnore
private List<Long> teacherIds;
}

@ -0,0 +1,11 @@
package rd.data.dto.schedule;
import lombok.Data;
@Data
public class NotSelectStudentExportDto {
private int id;
private String studentNumber;
private String name;
private String clazz;
}

@ -0,0 +1,12 @@
package rd.data.dto.schedule;
import lombok.Data;
@Data
public class SelectedStudentExportDto {
private int id;
private String studentNumber;
private String name;
private String clazz;
private String selectedSchedule;
}

@ -0,0 +1,24 @@
package rd.data.dto.score;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CourseScoreInfoDto {
private Long id;
private String studentName;
private String studentNumber;
private Float examRatio;
private Float usualScore;
private Float examScore;
}

@ -0,0 +1,20 @@
package rd.data.dto.score;
import lombok.Data;
@Data
public class ScoreExportDto {
private int id;
private String studentName;
private String number;
private Float usualScore;
private Float examScore;
private Float examRatio;
private String finalScore;
}

@ -0,0 +1,18 @@
package rd.data.dto.score;
import lombok.Data;
@Data
public class StudentScore {
private Long id;
private String courseName;
private String term;
private Float examRatio;
private Float usualScore;
private Float examScore;
}

@ -0,0 +1,4 @@
package rd.data.dto.user;
public record UserBasicInfoDTO(Long id, String username, String password, Short type) {
}

@ -0,0 +1,4 @@
package rd.data.dto.user.student;
public record BasicStudentInfoDto(String studentNumber, String studentName, Long majorId) {
}

@ -0,0 +1,4 @@
package rd.data.dto.user.student;
public record BasicStudentInfoWithMajorNameDto(String studentNumber, String studentName, String majorName) {
}

@ -0,0 +1,7 @@
package rd.data.dto.user.student;
import rd.data.db.table.StudentInfo;
import rd.data.db.table.UserBasic;
public record NewStudentDTO(UserBasic userBasic, StudentInfo studentInfo) {
}

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

Loading…
Cancel
Save