diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/backend/classroll-parent/.gitignore b/backend/classroll-parent/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/backend/classroll-parent/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/backend/classroll-parent/common/common-log/pom.xml b/backend/classroll-parent/common/common-log/pom.xml
new file mode 100644
index 0000000..13e4993
--- /dev/null
+++ b/backend/classroll-parent/common/common-log/pom.xml
@@ -0,0 +1,38 @@
+
+
+
+ com.cxy.classroll
+ common
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ common-log
+
+
+
+ com.cxy.classroll
+ model
+ 0.0.1-SNAPSHOT
+ provided
+
+
+ com.cxy.classroll
+ common-util
+ 0.0.1-SNAPSHOT
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+ provided
+
+
+
+
diff --git a/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/annotaion/Log.java b/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/annotaion/Log.java
new file mode 100644
index 0000000..3246b05
--- /dev/null
+++ b/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/annotaion/Log.java
@@ -0,0 +1,39 @@
+package com.cxy.classroll.common.annotaion;
+
+import com.cxy.classroll.common.enums.BusinessType;
+import com.cxy.classroll.common.enums.OperatorType;
+
+import java.lang.annotation.*;
+
+/**
+ * 自定义操作日志记录注解
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log {
+ /**
+ * 模块
+ */
+ public String title() default "";
+
+ /**
+ * 功能
+ */
+ public BusinessType businessType() default BusinessType.OTHER;
+
+ /**
+ * 操作人类别
+ */
+ public OperatorType operatorType() default OperatorType.MANAGE;
+
+ /**
+ * 是否保存请求的参数
+ */
+ public boolean isSaveRequestData() default true;
+
+ /**
+ * 是否保存响应的参数
+ */
+ public boolean isSaveResponseData() default true;
+}
diff --git a/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/enums/BusinessType.java b/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/enums/BusinessType.java
new file mode 100644
index 0000000..c805ae1
--- /dev/null
+++ b/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/enums/BusinessType.java
@@ -0,0 +1,51 @@
+package com.cxy.classroll.common.enums;
+/**
+ * 业务操作类型
+ */
+public enum BusinessType {
+ /**
+ * 其它
+ */
+ OTHER,
+
+ /**
+ * 新增
+ */
+ INSERT,
+
+ /**
+ * 修改
+ */
+ UPDATE,
+
+ /**
+ * 删除
+ */
+ DELETE,
+
+ /**
+ * 授权
+ */
+ ASSGIN,
+
+ /**
+ * 导出
+ */
+ EXPORT,
+
+ /**
+ * 导入
+ */
+ IMPORT,
+
+
+ /**
+ * 更新状态
+ */
+ STATUS,
+
+ /**
+ * 清空数据
+ */
+ CLEAN,
+}
diff --git a/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/enums/OperatorType.java b/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/enums/OperatorType.java
new file mode 100644
index 0000000..303ab80
--- /dev/null
+++ b/backend/classroll-parent/common/common-log/src/main/java/com/cxy/classroll/common/enums/OperatorType.java
@@ -0,0 +1,20 @@
+package com.cxy.classroll.common.enums;
+/**
+ * 操作人类别
+ */
+public enum OperatorType {
+ /**
+ * 其它
+ */
+ OTHER,
+
+ /**
+ * 后台用户
+ */
+ MANAGE,
+
+ /**
+ * 手机端用户
+ */
+ MOBILE
+}
diff --git a/backend/classroll-parent/common/common-util/pom.xml b/backend/classroll-parent/common/common-util/pom.xml
new file mode 100644
index 0000000..819ee57
--- /dev/null
+++ b/backend/classroll-parent/common/common-util/pom.xml
@@ -0,0 +1,38 @@
+
+
+
+ com.cxy.classroll
+ common
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ common-util
+ jar
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+ org.projectlombok
+ lombok
+
+
+ com.alibaba
+ fastjson
+
+
+ joda-time
+ joda-time
+
+
+ commons-io
+ commons-io
+
+
+
+
diff --git a/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/result/Result.java b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/result/Result.java
new file mode 100644
index 0000000..b0f0a68
--- /dev/null
+++ b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/result/Result.java
@@ -0,0 +1,77 @@
+package com.cxy.classroll.common.result;
+
+import lombok.Data;
+
+@Data
+public class Result {
+ //返回码
+ private Integer code;
+
+ //返回消息
+ private String message;
+
+ //返回数据
+ private T data;
+
+ public Result(){}
+
+ // 返回数据
+ protected static Result build(T data) {
+ Result result = new Result();
+ if (data != null)
+ result.setData(data);
+ return result;
+ }
+
+ public static Result build(T body, Integer code, String message) {
+ Result result = build(body);
+ result.setCode(code);
+ result.setMessage(message);
+ return result;
+ }
+
+ public static Result build(T body, ResultCodeEnum resultCodeEnum) {
+ Result result = build(body);
+ result.setCode(resultCodeEnum.getCode());
+ result.setMessage(resultCodeEnum.getMessage());
+ return result;
+ }
+
+ public static Result ok(){
+ return Result.ok(null);
+ }
+
+ /**
+ * 操作成功
+ * @param data baseCategory1List
+ * @param
+ * @return
+ */
+ public static Result ok(T data){
+ return build(data, ResultCodeEnum.SUCCESS);
+ }
+
+ public static Result fail(){
+ return Result.fail(null);
+ }
+
+ /**
+ * 操作失败
+ * @param data
+ * @param
+ * @return
+ */
+ public static Result fail(T data){
+ return build(data, ResultCodeEnum.FAIL);
+ }
+
+ public Result message(String msg){
+ this.setMessage(msg);
+ return this;
+ }
+
+ public Result code(Integer code){
+ this.setCode(code);
+ return this;
+ }
+}
diff --git a/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/result/ResultCodeEnum.java b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/result/ResultCodeEnum.java
new file mode 100644
index 0000000..ec2e91b
--- /dev/null
+++ b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/result/ResultCodeEnum.java
@@ -0,0 +1,32 @@
+package com.cxy.classroll.common.result;
+
+import lombok.Getter;
+
+@Getter
+public enum ResultCodeEnum {
+ SUCCESS(200,"成功"),
+ FAIL(201, "失败"),
+ SERVICE_ERROR(2012, "服务异常"),
+ DATA_ERROR(204, "数据异常"),
+ ILLEGAL_REQUEST(205, "非法请求"),
+ REPEAT_SUBMIT(206, "重复提交"),
+ FEIGN_FAIL(207, "远程调用失败"),
+ UPDATE_ERROR(204, "数据更新失败"),
+
+ ARGUMENT_VALID_ERROR(210, "参数校验异常"),
+
+ LOGIN_AUTH(208, "未登陆"),
+ PERMISSION(209, "没有权限"),
+ ACCOUNT_ERROR(214, "账号不正确"),
+ PASSWORD_ERROR(215, "密码不正确"),
+ ;
+
+ private Integer code;
+
+ private String message;
+
+ private ResultCodeEnum(Integer code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+}
diff --git a/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/util/AuthContextHolder.java b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/util/AuthContextHolder.java
new file mode 100644
index 0000000..70bd609
--- /dev/null
+++ b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/util/AuthContextHolder.java
@@ -0,0 +1,19 @@
+package com.cxy.classroll.common.util;
+/**
+ * 获取当前用户信息帮助类
+ */
+public class AuthContextHolder {
+ private static ThreadLocal userId = new ThreadLocal();
+
+ public static void setUserId(Long _userId) {
+ userId.set(_userId);
+ }
+
+ public static Long getUserId() {
+ return userId.get();
+ }
+
+ public static void removeUserId() {
+ userId.remove();
+ }
+}
diff --git a/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/util/MD5.java b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/util/MD5.java
new file mode 100644
index 0000000..8c68893
--- /dev/null
+++ b/backend/classroll-parent/common/common-util/src/main/java/com/cxy/classroll/common/util/MD5.java
@@ -0,0 +1,29 @@
+package com.cxy.classroll.common.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class MD5 {
+ public static String encrypt(String strSrc) {
+ try {
+ char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ byte[] bytes = strSrc.getBytes();
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(bytes);
+ bytes = md.digest();
+ int j = bytes.length;
+ char[] chars = new char[j * 2];
+ int k = 0;
+ for (int i = 0; i < bytes.length; i++) {
+ byte b = bytes[i];
+ chars[k++] = hexChars[b >>> 4 & 0xf];
+ chars[k++] = hexChars[b & 0xf];
+ }
+ return new String(chars);
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ throw new RuntimeException("MD5加密出错!!+" + e);
+ }
+ }
+}
diff --git a/backend/classroll-parent/common/pom.xml b/backend/classroll-parent/common/pom.xml
new file mode 100644
index 0000000..1086f39
--- /dev/null
+++ b/backend/classroll-parent/common/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ com.cxy.classroll
+ classroll-parent
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ common
+ pom
+
+
+ common-log
+ common-util
+ service-util
+
+
+
diff --git a/backend/classroll-parent/common/service-util/pom.xml b/backend/classroll-parent/common/service-util/pom.xml
new file mode 100644
index 0000000..bf9b29a
--- /dev/null
+++ b/backend/classroll-parent/common/service-util/pom.xml
@@ -0,0 +1,76 @@
+
+
+
+ com.cxy.classroll
+ common
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ service-util
+
+
+
+ com.cxy.classroll
+ common-util
+ 0.0.1-SNAPSHOT
+
+
+ com.cxy.classroll
+ model
+ 0.0.1-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+
+ mysql
+ mysql-connector-java
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-jakarta-spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.redisson
+ redisson
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ provided
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+ provided
+
+
+
+
diff --git a/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/knife4j/Knife4jConfig.java b/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/knife4j/Knife4jConfig.java
new file mode 100644
index 0000000..9fdc5e4
--- /dev/null
+++ b/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/knife4j/Knife4jConfig.java
@@ -0,0 +1,34 @@
+package com.cxy.classroll.common.config.knife4j;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import org.springdoc.core.models.GroupedOpenApi;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class Knife4jConfig {
+ @Bean
+ public GroupedOpenApi webApi() {
+ return GroupedOpenApi.builder()
+ .group("web-api")
+ .pathsToMatch("/**")
+ .build();
+ }
+
+ /***
+ * @description 自定义接口信息
+ */
+ @Bean
+ public OpenAPI customOpenAPI() {
+
+ return new OpenAPI()
+ .info(new Info()
+ .title("课堂点名小程序接口文档")
+ .version("1.0")
+ .description("课堂点名小程序接口文档")
+ .contact(new Contact().name("cxy")));
+ }
+
+}
diff --git a/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/mybatisPlus/MybatisPlusConfig.java b/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/mybatisPlus/MybatisPlusConfig.java
new file mode 100644
index 0000000..1c6d6a3
--- /dev/null
+++ b/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/mybatisPlus/MybatisPlusConfig.java
@@ -0,0 +1,30 @@
+package com.cxy.classroll.common.config.mybatisPlus;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * MybatisPlus配置类
+ *
+ */
+@EnableTransactionManagement
+@Configuration
+@MapperScan("com.cxy.classroll.*.mapper")
+public class MybatisPlusConfig {
+ /**
+ *
+ * @return
+ */
+ @Bean
+ public MybatisPlusInterceptor optimisticLockerInnerInterceptor(){
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ //向Mybatis过滤器链中添加分页拦截器
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ return interceptor;
+ }
+}
diff --git a/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/redis/RedisConfig.java b/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/redis/RedisConfig.java
new file mode 100644
index 0000000..39944cb
--- /dev/null
+++ b/backend/classroll-parent/common/service-util/src/main/java/com/cxy/classroll/common/config/redis/RedisConfig.java
@@ -0,0 +1,89 @@
+package com.cxy.classroll.common.config.redis;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.*;
+
+import java.lang.reflect.Method;
+import java.time.Duration;
+
+/**
+ * Redis配置类
+ *
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig {
+ // 使用默认标签做缓存
+ @Bean
+ public KeyGenerator keyGenerator() {
+ return new KeyGenerator() {
+ @Override
+ public Object generate(Object target, Method method, Object... params) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(target.getClass().getName());
+ sb.append(method.getName());
+ for (Object obj : params) {
+ sb.append(obj.toString());
+ }
+ return sb.toString();
+ }
+ };
+ }
+
+ @Bean
+ @Primary
+ public RedisTemplate