diff --git a/deviceInfo_20243037.json b/deviceInfo_20243037.json new file mode 100644 index 0000000..297aa84 --- /dev/null +++ b/deviceInfo_20243037.json @@ -0,0 +1,30 @@ +{ + "deviceInfoVersion": 3, + "data": { + "display": "MIRAI.451530.001", + "product": "mirai", + "device": "mirai", + "board": "mirai", + "brand": "mamoe", + "model": "mirai", + "bootloader": "unknown", + "fingerprint": "mamoe/mirai/mirai:10/MIRAI.200122.001/9029684:user/release-keys", + "bootId": "0BBF2C49-3C4B-FBFC-8969-311C2F5D54C4", + "procVersion": "Linux version 3.0.31-v23xIXJS (android-build@xxx.xxx.xxx.xxx.com)", + "baseBand": "", + "version": { + "incremental": "5891938", + "release": "10", + "codename": "REL" + }, + "simInfo": "T-Mobile", + "osType": "android", + "macAddress": "02:00:00:00:00:00", + "wifiBSSID": "02:00:00:00:00:00", + "wifiSSID": "", + "imsiMd5": "6ba800c6d5513eb42b0fb90b6b5afd5c", + "imei": "864237812540469", + "apn": "wifi", + "androidId": "906fe7e62819be1e" + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8525c28..8b0a528 100644 --- a/pom.xml +++ b/pom.xml @@ -29,13 +29,34 @@ mysql-connector-java 8.0.33 - - + + net.mamoe + mirai-core-jvm + 2.99.0-local + com.baomidou mybatis-plus-boot-starter 3.5.9 + + + + com.squareup.okhttp3 + okhttp + 4.12.0 + + + + com.alibaba.fastjson2 + fastjson2 + 2.0.53 + + + com.github.xiaoymin + knife4j-openapi3-spring-boot-starter + 4.4.0 + com.alibaba druid-spring-boot-starter diff --git a/src/main/java/com/linxyun/homework/HomeworkApplication.java b/src/main/java/com/linxyun/homework/HomeworkApplication.java index a1df4fc..ce3d99d 100644 --- a/src/main/java/com/linxyun/homework/HomeworkApplication.java +++ b/src/main/java/com/linxyun/homework/HomeworkApplication.java @@ -7,9 +7,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.linxyun.homework.mapper") public class HomeworkApplication { - public static void main(String[] args) { SpringApplication.run(HomeworkApplication.class, args); } - } diff --git a/src/main/java/com/linxyun/homework/bot/MyBot.java b/src/main/java/com/linxyun/homework/bot/MyBot.java new file mode 100644 index 0000000..760354e --- /dev/null +++ b/src/main/java/com/linxyun/homework/bot/MyBot.java @@ -0,0 +1,82 @@ +package com.linxyun.homework.bot; + +import com.linxyun.homework.bot.handler.MyEventHandler; +import com.linxyun.homework.domain.dto.ClassGroupTeacher; +import com.linxyun.homework.mapper.ClassQqGroupTeacherMapper; +import lombok.RequiredArgsConstructor; +import net.mamoe.mirai.BotFactory; +import net.mamoe.mirai.auth.BotAuthorization; +import net.mamoe.mirai.event.EventChannel; +import net.mamoe.mirai.event.events.BotEvent; +import net.mamoe.mirai.event.events.GroupMessageEvent; +import net.mamoe.mirai.utils.BotConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; + + +@Component +@RequiredArgsConstructor +public class MyBot implements ApplicationRunner { + /* 监听对象 */ + public static CopyOnWriteArrayList listeningTarget; + + private final ClassQqGroupTeacherMapper classQqGroupTeacherMapper; + + private final MyEventHandler myEventHandler; + + /* 登录QQ */ + @Value("${mirai.bot.qq}") + public Long qq; + + @Override + public void run(ApplicationArguments args) { + // 先加载需要处理的群和老师 + getListeningTarget(); + // 启动BOT + runBot(); + } + + public void getListeningTarget() { + List classGroupTeachers = classQqGroupTeacherMapper.selectClassAndGroupTeacher(); + System.out.println(classGroupTeachers); + listeningTarget = new CopyOnWriteArrayList<>(classGroupTeachers); + } + + public void runBot() { + net.mamoe.mirai.Bot bot = BotFactory.INSTANCE.newBot(qq, BotAuthorization.byQRCode(), configuration -> { + configuration.setProtocol(BotConfiguration.MiraiProtocol.MACOS); + // 指定设备信息文件路径,文件不存在将自动生成一个默认的,存在就读取 + configuration.fileBasedDeviceInfo("deviceInfo_"+ qq + ".json"); + }); + bot.login(); + EventChannel eventChannel = bot.getEventChannel(); + eventChannel + .filterIsInstance(GroupMessageEvent.class) + .filter(ev -> { + long groupId = ev.getGroup().getId(); + long senderId = ev.getSender().getId(); + for (ClassGroupTeacher item : listeningTarget) { + if (groupId == Long.parseLong(item.getQqGroupId()) && senderId == Long.parseLong(item.getTeacherGroupId())) { + return true; + } + } + return false; + } + ).registerListenerHost(myEventHandler); + new Thread(bot::join).start(); + } + + public static ClassGroupTeacher getClassGroupTeacherByTeacherGroupId(String teacherGroupId) { + return listeningTarget.stream() + .filter(item -> Objects.equals(item.getTeacherGroupId(), teacherGroupId)) + .findFirst() + .orElse(null); + } +} diff --git a/src/main/java/com/linxyun/homework/bot/handler/MyEventHandler.java b/src/main/java/com/linxyun/homework/bot/handler/MyEventHandler.java new file mode 100644 index 0000000..f29de02 --- /dev/null +++ b/src/main/java/com/linxyun/homework/bot/handler/MyEventHandler.java @@ -0,0 +1,114 @@ +package com.linxyun.homework.bot.handler; + +import com.alibaba.druid.sql.dialect.odps.ast.OdpsAddFileStatement; +import com.linxyun.homework.bot.MyBot; +import com.linxyun.homework.domain.dto.ClassGroupTeacher; +import com.linxyun.homework.domain.po.TeacherQqMsgs; +import com.linxyun.homework.mapper.TeacherQqMsgsMapper; +import com.linxyun.homework.utils.FileUtils; +import com.linxyun.homework.utils.TimeUtils; +import kotlin.coroutines.CoroutineContext; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.mamoe.mirai.contact.file.AbsoluteFile; +import net.mamoe.mirai.event.EventHandler; +import net.mamoe.mirai.event.ListeningStatus; +import net.mamoe.mirai.event.SimpleListenerHost; +import net.mamoe.mirai.event.events.GroupMessageEvent; +import net.mamoe.mirai.message.data.*; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Component; + +import java.util.Optional; +import java.util.UUID; + +@Component +@Slf4j +@RequiredArgsConstructor +public class MyEventHandler extends SimpleListenerHost { + private final FileUtils fileUtils; + private final TeacherQqMsgsMapper teacherQqMsgsMapper; + @Override + public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception){ + // 处理事件处理时抛出的异常 + } + + @NotNull + @EventHandler + public ListeningStatus onMessage(@NotNull GroupMessageEvent event) { // 可以抛出任何异常, 将在 handleException 处理 + System.out.println("收到消息: " + event.getMessage()); + MessageChain messages = event.getMessage(); + // 发送人QQ + String teacherId = String.valueOf(event.getSender().getId()); + StringBuilder strBuilder = null; + StringBuilder contentBuilder = null; + for (SingleMessage message : messages) { + if (message instanceof PlainText plainText) { + log.info("文本: " + plainText.getContent()); + if (strBuilder == null) { + strBuilder = new StringBuilder(); + } + strBuilder.append(plainText.getContent()).append("|||"); + } + if (message instanceof Image image) { + log.info("图片: " + image.getImageId()); + if (image.isEmoji()) continue; + if (contentBuilder == null) contentBuilder = new StringBuilder(); + String url = Image.queryUrl(image); + String fileName = UUID.randomUUID().toString().replace("-", "") + "." + image.getImageType().name().toLowerCase(); + String resultUrl = fileUtils.uploadFileByUrl(url, fileName); + if (resultUrl == null) { + log.error("图片上传失败: " + url); + } + contentBuilder.append(resultUrl).append(";"); + } + if (message instanceof FileMessage file) { + log.info("文件: " + file.getName()); + if (contentBuilder == null) contentBuilder = new StringBuilder(); + AbsoluteFile absoluteFile = file.toAbsoluteFile(event.getGroup()); + String url = absoluteFile.getUrl(); + String resultUrl = fileUtils.uploadFileByUrl(url, file.getName()); + if (resultUrl == null) { + log.error("文件上传失败: " + url); + } + contentBuilder.append(resultUrl).append(";"); + } + } + // 插入数据库 + ClassGroupTeacher classGroupTeacher = MyBot.getClassGroupTeacherByTeacherGroupId(teacherId); + TeacherQqMsgs teacherQqMsgs = new TeacherQqMsgs(); + teacherQqMsgs.setCreateTime(TimeUtils.getCurrentTime()); + teacherQqMsgs.setTeacherQqId(teacherId); + teacherQqMsgs.setClassId(classGroupTeacher.getClassId()); + teacherQqMsgs.setCourseType(classGroupTeacher.getCourseType()); + Optional.ofNullable(strBuilder).ifPresent(item -> { + String remarks = item.substring(0, item.length() - 3); + log.info("提交的文本: " + remarks); + teacherQqMsgs.setRemarks(remarks); + }); + Optional.ofNullable(contentBuilder).ifPresent(item -> { + String msgContent = item.deleteCharAt(item.length() - 1).toString(); + log.info("提交的图片: " + msgContent); + teacherQqMsgs.setMsgContent(msgContent); + }); + int row = teacherQqMsgsMapper.insert(teacherQqMsgs); + if (row > 0) { + log.info("插入成功: " + messages); + } else { + log.error("插入失败: " + messages); + } + return ListeningStatus.LISTENING; // 表示继续监听事件 + } + +// @NotNull +// @EventHandler +// public ListeningStatus onMessage(@NotNull FriendMessageEvent event) throws Exception { // 可以抛出任何异常, 将在 handleException 处理 +// System.out.println("收到消息: " + event.getMessage()); +// MessageChain messages = event.getMessage(); +// messages. +// event.getSubject().sendMessage("friend"); +// return ListeningStatus.LISTENING; // 表示继续监听事件 +// // return ListeningStatus.STOPPED; // 表示停止监听事件 +// } + +} diff --git a/src/main/java/com/linxyun/homework/common/entity/Result.java b/src/main/java/com/linxyun/homework/common/entity/Result.java new file mode 100644 index 0000000..25dea4c --- /dev/null +++ b/src/main/java/com/linxyun/homework/common/entity/Result.java @@ -0,0 +1,60 @@ +package com.linxyun.homework.common.entity; + +import com.linxyun.homework.common.enums.ErrorCode; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +@Data +@ToString +@Schema(description = "统一返回结果") +public class Result { + @Schema(description = "返回数据") + public E data; + @Schema(description = "状态码") + public String code; + @Schema(description = "返回信息") + public String msg; + @Schema(description = "是否成功") + public boolean success = true; + + public Result(E data, String code, String msg, boolean success) { + this.data = data; + this.code = code; + this.msg = msg; + this.success = success; + } + + public static Result error(ErrorCode codeEnum) { + return new Result<>(null, codeEnum.getCode(), codeEnum.getMessage(), false); + + } + + public static Result error(String code, String msg) { + return new Result<>(null, code, msg, false); + } + + public static Result ok() { + return new Result<>(null, "0000", "操作成功", true); + } + + public static Result ok(String msg) { + return new Result<>(null, "0000", msg, true); + + } + public static Result ok(T data) { + return new Result<>(data, "0000", "操作成功", true); + + } + + public static Result ok(T data, String msg) { + return new Result<>(data, "0000", msg, true); + } + + public Result() { + this.success = false; + this.code = "9999"; + this.msg = "操作失败"; + this.data = null; + } +} diff --git a/src/main/java/com/linxyun/homework/common/enums/CourseType.java b/src/main/java/com/linxyun/homework/common/enums/CourseType.java new file mode 100644 index 0000000..1c0aae8 --- /dev/null +++ b/src/main/java/com/linxyun/homework/common/enums/CourseType.java @@ -0,0 +1,27 @@ +package com.linxyun.homework.common.enums; + +public enum CourseType { + // 语文 0 + CHINESE("0", "语文"), + // 数学 1 + MATH("1", "数学"), + // 英语 2 + ENGLISH("2", "英语"); + + private final String code; + private final String desc; + + CourseType(String code, String desc) { + this.code = code; + this.desc = desc; + } + + public static String getDescByCode(String code) { + for (CourseType type : CourseType.values()) { + if (type.code.equals(code)) { + return type.desc; + } + } + return null; + } +} diff --git a/src/main/java/com/linxyun/homework/common/enums/ErrorCode.java b/src/main/java/com/linxyun/homework/common/enums/ErrorCode.java new file mode 100644 index 0000000..1c9a79f --- /dev/null +++ b/src/main/java/com/linxyun/homework/common/enums/ErrorCode.java @@ -0,0 +1,122 @@ +package com.linxyun.homework.common.enums; + +import lombok.Getter; + +@Getter +public enum ErrorCode { + + // 用户不存在或密码不匹配 + USER_NOT_FOUND_OR_PASSWORD_MISMATCH("1006", "用户不存在或密码不匹配"), + + // 参数错误 + PARAMETER_ERROR("204", "参数错误"), + + // URI 不存在 + URI_NOT_FOUND("240", "URI不存在"), + + // URI 已经存在 + URI_ALREADY_EXISTS("241", "URI已经存在"), + + // 服务的路由异常,请联系管理员 + ROUTING_EXCEPTION("320", "服务的路由异常,请联系管理员"), + + // 处理超时,服务配置出错,请联系管理员 + TIMEOUT_ERROR("998", "处理超时,服务配置出错,请联系管理员"), + + // 登录超时,请重新登录 + LOGIN_TIMEOUT("9998", "登录超时,请重新登录"), + + // 登录超时,请重新登录 + LOGIN_TIMEOUT_2("401", "登录超时,请重新登录"), + + // 操作失败 + OPERATION_FAIL("1005", "操作失败"), + + // 用户已经存在 + USER_ALREADY_EXISTS("1007", "用户已经存在"), + + // 操作ID配置错误,请联系管理员 + OPERATION_ID_ERROR("1008", "操作ID配置错误,请联系管理员"), + + // 用户ID参数错误 + USER_ID_PARAMETER_ERROR("1009", "用户ID参数错误"), + + // 用户邮箱地址错误 + USER_EMAIL_ERROR("1011", "用户邮箱地址错误"), + + // 邮箱地址已经存在 + EMAIL_ALREADY_EXISTS("1012", "邮箱地址已经存在"), + + // 手机号码格式不正确 + PHONE_NUMBER_FORMAT_ERROR("1013", "手机号码格式不正确"), + + // 手机号码已经存在 + PHONE_NUMBER_ALREADY_EXISTS("1014", "手机号码已经存在"), + + // 登录验证出错 + LOGIN_VALIDATION_ERROR("1020", "登录验证出错"), + + // 用户没有登录 + USER_NOT_LOGGED_IN("1021", "用户没有登录"), + + // 用户状态不正常 + USER_STATUS_ERROR("1022", "用户状态不正常"), + + // 发送验证码失败 + SEND_VERIFICATION_CODE_FAIL("1023", "发送验证码失败"), + + // 验证码验证失败 + VERIFICATION_CODE_FAIL("1024", "验证码验证失败"), + + // 用户组已经存在 + USER_GROUP_ALREADY_EXISTS("1030", "用户组已经存在"), + + // 用户组不存在 + USER_GROUP_NOT_EXISTS("1031", "用户组不经存在"), + + // 操作出错 + OPERATION_ERROR("1999", "操作出错"), + + // 前端处理验证数据出错 + FRONTEND_VALIDATION_ERROR("886000", "前端处理验证数据出错"), + + // 请先删除内容 + DELETE_CONTENT_FIRST("2012", "请先删除内容"), + // 文件不存在 + FILE_NOT_FOUND("3000", "文件不存在"), + // 文件大小超出限制 + FILE_SIZE_EXCEEDED("3001", "文件大小超出限制"), + // 文件上传失败 + FILE_UPLOAD_FAILED("3002", "文件上传失败"), + // 请求失败 + REQUEST_FAILED("3003", "请求失败"), + NONE("6666666", "站位"); + + + + private final String code; + private final String message; + + ErrorCode(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } + + // 根据错误代码获取对应的错误信息 + public static String getMessageByCode(String code) { + for (ErrorCode errorCode : values()) { + if (errorCode.getCode().equals(code)) { + return errorCode.getMessage(); + } + } + return "未知错误"; + } +} diff --git a/src/main/java/com/linxyun/homework/config/OpenApiConfig.java b/src/main/java/com/linxyun/homework/config/OpenApiConfig.java new file mode 100644 index 0000000..d27b8a3 --- /dev/null +++ b/src/main/java/com/linxyun/homework/config/OpenApiConfig.java @@ -0,0 +1,25 @@ +package com.linxyun.homework.config; + +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.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class OpenApiConfig { + + @Bean + public OpenAPI springShopOpenAPI() { + return new OpenAPI() + // 接口文档标题 + .info(new Info() + .title("家庭作业助手接口文档") + // 接口文档描述 + .description("家庭作业助手接口") + // 接口文档版本 + .version("v1.0") + .contact(new Contact().name("wenxin")) + ); + } +} diff --git a/src/main/java/com/linxyun/homework/config/WebConfig.java b/src/main/java/com/linxyun/homework/config/WebConfig.java new file mode 100644 index 0000000..ff496c0 --- /dev/null +++ b/src/main/java/com/linxyun/homework/config/WebConfig.java @@ -0,0 +1,19 @@ +package com.linxyun.homework.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + // 全局跨域 + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") + .allowCredentials(true) + .maxAge(3600) + .allowedHeaders("*"); + } +} diff --git a/src/main/java/com/linxyun/homework/controller/ClassController.java b/src/main/java/com/linxyun/homework/controller/ClassController.java new file mode 100644 index 0000000..f967b10 --- /dev/null +++ b/src/main/java/com/linxyun/homework/controller/ClassController.java @@ -0,0 +1,87 @@ +package com.linxyun.homework.controller; + + +import com.linxyun.homework.common.entity.Result; +import com.linxyun.homework.common.enums.ErrorCode; +import com.linxyun.homework.domain.po.Class; +import com.linxyun.homework.service.ClassService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@RequestMapping("/class") +@RestController +@RequiredArgsConstructor +@Tag(name = "班级模块") +public class ClassController { + + private final ClassService classService; + + /** + * 添加班级 + * @param clazz 班级信息 + * @return Result + */ + @PostMapping + @Operation(summary = "添加班级") + public Result addClass(@RequestBody Class clazz) { + boolean status = classService.save(clazz); + if (!status) { + return Result.error(ErrorCode.OPERATION_FAIL); + } + return Result.ok(); + } + + /** + * 获取班级列表 + * @return Result + */ + @GetMapping + @Operation(summary = "获取班级列表") + public Result getClassList() { + return Result.ok(classService.list()); + } + + /** + * 根据班级id获取班级信息 + * @param classId 班级ID + * @return Result + */ + @GetMapping("/{classId}") + @Operation(summary = "根据班级id获取班级信息", parameters = { @Parameter(name = "classId", description = "班级ID", required = true) }) + public Result getClassById(@PathVariable Integer classId) { + return Result.ok(classService.getById(classId)); + } + + /** + * 删除班级 + * @param classId 班级ID + * @return Result + */ + @DeleteMapping("/{classId}") + @Operation(summary = "删除班级", parameters = { @Parameter(name = "classId", description = "班级ID", required = true) }) + public Result deleteClassById(@PathVariable Integer classId) { + boolean status = classService.removeById(classId); + if (!status) { + return Result.error(ErrorCode.OPERATION_FAIL); + } + return Result.ok(); + } + + /** + * 更新班级信息 + * @param clazz 班级信息 + * @return Result + */ + @PatchMapping + @Operation(summary = "更新班级信息") + public Result updateClass(@RequestBody Class clazz) { + boolean status = classService.updateById(clazz); + if (!status) { + return Result.error(ErrorCode.OPERATION_FAIL); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/linxyun/homework/controller/GroupMsgController.java b/src/main/java/com/linxyun/homework/controller/GroupMsgController.java new file mode 100644 index 0000000..2ce35a8 --- /dev/null +++ b/src/main/java/com/linxyun/homework/controller/GroupMsgController.java @@ -0,0 +1,16 @@ +package com.linxyun.homework.controller; + +import com.linxyun.homework.common.entity.Result; +import com.linxyun.homework.service.ClassQqGroupTeacherService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/group/msg") +public class GroupMsgController { + private final ClassQqGroupTeacherService groupMsgService; + +} diff --git a/src/main/java/com/linxyun/homework/controller/GroupTeacherController.java b/src/main/java/com/linxyun/homework/controller/GroupTeacherController.java new file mode 100644 index 0000000..ab853a2 --- /dev/null +++ b/src/main/java/com/linxyun/homework/controller/GroupTeacherController.java @@ -0,0 +1,13 @@ +package com.linxyun.homework.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/group/teacher") +public class GroupTeacherController { + +// private final +} diff --git a/src/main/java/com/linxyun/homework/controller/HomeworkAnswerController.java b/src/main/java/com/linxyun/homework/controller/HomeworkAnswerController.java new file mode 100644 index 0000000..cd1749c --- /dev/null +++ b/src/main/java/com/linxyun/homework/controller/HomeworkAnswerController.java @@ -0,0 +1,24 @@ +package com.linxyun.homework.controller; + +import com.linxyun.homework.common.entity.Result; +import com.linxyun.homework.domain.dto.AnswerMsg; +import com.linxyun.homework.service.HomeworkAnswerService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + + +@RestController +@RequestMapping("/answer") +@RequiredArgsConstructor +@Tag(name = "作业答案模块") +public class HomeworkAnswerController { + private final HomeworkAnswerService homeworkAnswerService; + + @PostMapping("/msg") + @Operation(summary = "通过消息添加答案") + public Result addAnswerByMsgId(@RequestBody AnswerMsg answerMsg) { + return homeworkAnswerService.addAnswerByMsgId(answerMsg); + } +} diff --git a/src/main/java/com/linxyun/homework/domain/dto/AnswerMsg.java b/src/main/java/com/linxyun/homework/domain/dto/AnswerMsg.java new file mode 100644 index 0000000..17c727c --- /dev/null +++ b/src/main/java/com/linxyun/homework/domain/dto/AnswerMsg.java @@ -0,0 +1,19 @@ +package com.linxyun.homework.domain.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "作业答案消息") +public class AnswerMsg { + @Schema(description = "消息ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer msgId; + @Schema(description = "会员ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer memberId; + @Schema(description = "作业标题") + private String title; + @Schema(description = "作业内容,多文本以 ||| 分隔") + private String content; + @Schema(description = "作业文件,多文件以 ; 分隔") + private String file; +} diff --git a/src/main/java/com/linxyun/homework/domain/dto/ClassGroupTeacher.java b/src/main/java/com/linxyun/homework/domain/dto/ClassGroupTeacher.java new file mode 100644 index 0000000..7fbfa39 --- /dev/null +++ b/src/main/java/com/linxyun/homework/domain/dto/ClassGroupTeacher.java @@ -0,0 +1,13 @@ +package com.linxyun.homework.domain.dto; + +import lombok.Data; + +@Data +public class ClassGroupTeacher { + private String teacherGroupId; + private String teacherNickname; + private String courseType; + private Integer classId; + private String className; + private String qqGroupId; +} diff --git a/src/main/java/com/linxyun/homework/domain/po/Class.java b/src/main/java/com/linxyun/homework/domain/po/Class.java new file mode 100644 index 0000000..1861a21 --- /dev/null +++ b/src/main/java/com/linxyun/homework/domain/po/Class.java @@ -0,0 +1,59 @@ +package com.linxyun.homework.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.ToString; + +/** + * + * @TableName tab_class + */ +@ToString +@TableName(value ="tab_class") +@Data +@Schema(description="班级") +public class Class implements Serializable { + /** + * 班级名 + */ + @TableId(value = "ClassID", type = IdType.AUTO) + @Schema(description = "班级ID") + private Integer classId; + + /** + * 班级名 + */ + @TableField(value = "ClassName") + @Schema(description = "班级名") + private String className; + + /** + * 对应年级枚举 + */ + @TableField(value = "Greade") + @Schema(description = "对应年级枚举") + private String greade; + + /** + * 学校ID + */ + @TableField(value = "SchoolID") + @Schema(description = "学校ID") + private Integer schoolId; + + /** + * 班级QQ群ID + */ + @TableField(value = "QQGroupID") + @Schema(description = "班级QQ群ID") + private String qqGroupId; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/linxyun/homework/domain/po/ClassQqGroupTeacher.java b/src/main/java/com/linxyun/homework/domain/po/ClassQqGroupTeacher.java new file mode 100644 index 0000000..5c60528 --- /dev/null +++ b/src/main/java/com/linxyun/homework/domain/po/ClassQqGroupTeacher.java @@ -0,0 +1,51 @@ +package com.linxyun.homework.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; +import lombok.ToString; + +/** + * + * @TableName tab_class_qqgroup_teacher + */ +@TableName(value ="tab_class_qqgroup_teacher") +@Data +@ToString +public class ClassQqGroupTeacher implements Serializable { + /** + * 记录ID + */ + @TableId(value = "RecordID", type = IdType.AUTO) + private Integer recordId; + + /** + * 班级ID + */ + @TableField(value = "ClassID") + private Integer classId; + + /** + * 老师在QQ群的ID + */ + @TableField(value = "TeacherGroupID") + private String teacherGroupId; + + /** + * QQ群中的名称 + */ + @TableField(value = "TeacherNickName") + private String teacherNickname; + + /** + * 课程类型 + */ + @TableField(value = "CourseType") + private String courseType; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/linxyun/homework/domain/po/HomeworkAnswer.java b/src/main/java/com/linxyun/homework/domain/po/HomeworkAnswer.java new file mode 100644 index 0000000..2ed5405 --- /dev/null +++ b/src/main/java/com/linxyun/homework/domain/po/HomeworkAnswer.java @@ -0,0 +1,81 @@ +package com.linxyun.homework.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; +import lombok.ToString; + +/** + * + * @TableName tab_homework_answer + */ +@TableName(value ="tab_homework_answer") +@Data +@ToString +public class HomeworkAnswer implements Serializable { + /** + * 答案ID + */ + @TableId(value = "AnswerID", type = IdType.AUTO) + private Integer answerId; + + /** + * 标题说明 + */ + @TableField(value = "Title") + private String title; + + /** + * 0:直接输入 1:选择资源 + */ + @TableField(value = "ContentType") + private Integer contentType; + + /** + * Content + */ + @TableField(value = "Content") + private String content; + + /** + * 附件ID + */ + @TableField(value = "ContentFileID") + private String contentFileId; + + /** + * 创建人会员ID + */ + @TableField(value = "MemberID") + private Integer memberId; + + /** + * 学生ID + */ + @TableField(value = "StudentID") + private Integer studentId; + + /** + * 0:个人 1:班级 + */ + @TableField(value = "CreateType") + private Integer createType; + + /** + * 创建时间 + */ + @TableField(value = "CreateTime") + private String createTime; + + /** + * 备注 + */ + @TableField(value = "Remark") + private String remark; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/linxyun/homework/domain/po/TeacherQqMsgs.java b/src/main/java/com/linxyun/homework/domain/po/TeacherQqMsgs.java new file mode 100644 index 0000000..ba18b3e --- /dev/null +++ b/src/main/java/com/linxyun/homework/domain/po/TeacherQqMsgs.java @@ -0,0 +1,69 @@ +package com.linxyun.homework.domain.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; +import lombok.ToString; + +/** + * + * @TableName tab_teacher_qq_msgs + */ +@TableName(value ="tab_teacher_qq_msgs") +@Data +@ToString +public class TeacherQqMsgs implements Serializable { + /** + * 消息ID + */ + @TableId(value = "MsgID", type = IdType.AUTO) + private Integer msgId; + + /** + * 班级ID + */ + @TableField(value = "ClassID") + private Integer classId; + + /** + * 老师的QQID + */ + @TableField(value = "TeacherQQID") + private String teacherQqId; + + /** + * 课程类型,枚举 + */ + @TableField(value = "CourseType") + private String courseType; + + /** + * 消息类型,对应作业内容类型,枚举 + */ + @TableField(value = "MsgType") + private String msgType; + + /** + * 文本直接存内容,其它存附件的文件ID,逗号分隔 + */ + @TableField(value = "MsgContent") + private String msgContent; + + /** + * 创建时间 + */ + @TableField(value = "CreateTime") + private String createTime; + + /** + * 备注 + */ + @TableField(value = "Remarks") + private String remarks; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/linxyun/homework/mapper/ClassMapper.java b/src/main/java/com/linxyun/homework/mapper/ClassMapper.java new file mode 100644 index 0000000..7f31e31 --- /dev/null +++ b/src/main/java/com/linxyun/homework/mapper/ClassMapper.java @@ -0,0 +1,18 @@ +package com.linxyun.homework.mapper; + +import com.linxyun.homework.domain.po.Class; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author wx_20 +* @description 针对表【tab_class】的数据库操作Mapper +* @createDate 2024-11-25 09:45:12 +* @Entity com.linxyun.homework.domain.po.Class +*/ +public interface ClassMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/linxyun/homework/mapper/ClassQqGroupTeacherMapper.java b/src/main/java/com/linxyun/homework/mapper/ClassQqGroupTeacherMapper.java new file mode 100644 index 0000000..63cd7ab --- /dev/null +++ b/src/main/java/com/linxyun/homework/mapper/ClassQqGroupTeacherMapper.java @@ -0,0 +1,21 @@ +package com.linxyun.homework.mapper; + +import com.linxyun.homework.domain.dto.ClassGroupTeacher; +import com.linxyun.homework.domain.po.ClassQqGroupTeacher; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.util.List; + +/** +* @author wx_20 +* @description 针对表【tab_class_qqgroup_teacher】的数据库操作Mapper +* @createDate 2024-11-25 09:45:12 +* @Entity com.linxyun.homework.domain.po.ClassQqgroupTeacher +*/ +public interface ClassQqGroupTeacherMapper extends BaseMapper { + List selectClassAndGroupTeacher(); +} + + + + diff --git a/src/main/java/com/linxyun/homework/mapper/HomeworkAnswerMapper.java b/src/main/java/com/linxyun/homework/mapper/HomeworkAnswerMapper.java new file mode 100644 index 0000000..38a2c0b --- /dev/null +++ b/src/main/java/com/linxyun/homework/mapper/HomeworkAnswerMapper.java @@ -0,0 +1,18 @@ +package com.linxyun.homework.mapper; + +import com.linxyun.homework.domain.po.HomeworkAnswer; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author wx_20 +* @description 针对表【tab_homework_answer】的数据库操作Mapper +* @createDate 2024-11-25 15:14:13 +* @Entity com.linxyun.homework.domain.po.HomeworkAnswer +*/ +public interface HomeworkAnswerMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/linxyun/homework/mapper/TeacherQqMsgsMapper.java b/src/main/java/com/linxyun/homework/mapper/TeacherQqMsgsMapper.java new file mode 100644 index 0000000..e6384a6 --- /dev/null +++ b/src/main/java/com/linxyun/homework/mapper/TeacherQqMsgsMapper.java @@ -0,0 +1,18 @@ +package com.linxyun.homework.mapper; + +import com.linxyun.homework.domain.po.TeacherQqMsgs; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author wx_20 +* @description 针对表【tab_teacher_qq_msgs】的数据库操作Mapper +* @createDate 2024-11-25 09:45:12 +* @Entity com.linxyun.homework.domain.po.TeacherQqMsgs +*/ +public interface TeacherQqMsgsMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/linxyun/homework/service/ClassQqGroupTeacherService.java b/src/main/java/com/linxyun/homework/service/ClassQqGroupTeacherService.java new file mode 100644 index 0000000..70aae30 --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/ClassQqGroupTeacherService.java @@ -0,0 +1,13 @@ +package com.linxyun.homework.service; + +import com.linxyun.homework.domain.po.ClassQqGroupTeacher; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author wx_20 +* @description 针对表【tab_class_qqgroup_teacher】的数据库操作Service +* @createDate 2024-11-25 09:45:12 +*/ +public interface ClassQqGroupTeacherService extends IService { + +} diff --git a/src/main/java/com/linxyun/homework/service/ClassService.java b/src/main/java/com/linxyun/homework/service/ClassService.java new file mode 100644 index 0000000..28373b5 --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/ClassService.java @@ -0,0 +1,13 @@ +package com.linxyun.homework.service; + +import com.linxyun.homework.domain.po.Class; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author wx_20 +* @description 针对表【tab_class】的数据库操作Service +* @createDate 2024-11-25 09:45:12 +*/ +public interface ClassService extends IService { + +} diff --git a/src/main/java/com/linxyun/homework/service/HomeworkAnswerService.java b/src/main/java/com/linxyun/homework/service/HomeworkAnswerService.java new file mode 100644 index 0000000..5647b3f --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/HomeworkAnswerService.java @@ -0,0 +1,16 @@ +package com.linxyun.homework.service; + +import com.linxyun.homework.common.entity.Result; +import com.linxyun.homework.domain.dto.AnswerMsg; +import com.linxyun.homework.domain.po.HomeworkAnswer; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author wx_20 +* @description 针对表【tab_homework_answer】的数据库操作Service +* @createDate 2024-11-25 15:14:13 +*/ +public interface HomeworkAnswerService extends IService { + + Result addAnswerByMsgId(AnswerMsg answerMsg); +} diff --git a/src/main/java/com/linxyun/homework/service/TeacherQqMsgsService.java b/src/main/java/com/linxyun/homework/service/TeacherQqMsgsService.java new file mode 100644 index 0000000..5393ef3 --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/TeacherQqMsgsService.java @@ -0,0 +1,13 @@ +package com.linxyun.homework.service; + +import com.linxyun.homework.domain.po.TeacherQqMsgs; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author wx_20 +* @description 针对表【tab_teacher_qq_msgs】的数据库操作Service +* @createDate 2024-11-25 09:45:12 +*/ +public interface TeacherQqMsgsService extends IService { + +} diff --git a/src/main/java/com/linxyun/homework/service/impl/ClassQqGroupTeacherServiceImpl.java b/src/main/java/com/linxyun/homework/service/impl/ClassQqGroupTeacherServiceImpl.java new file mode 100644 index 0000000..3bb8815 --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/impl/ClassQqGroupTeacherServiceImpl.java @@ -0,0 +1,22 @@ +package com.linxyun.homework.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.linxyun.homework.domain.po.ClassQqGroupTeacher; +import com.linxyun.homework.service.ClassQqGroupTeacherService; +import com.linxyun.homework.mapper.ClassQqGroupTeacherMapper; +import org.springframework.stereotype.Service; + +/** +* @author wx_20 +* @description 针对表【tab_class_qqgroup_teacher】的数据库操作Service实现 +* @createDate 2024-11-25 09:45:12 +*/ +@Service +public class ClassQqGroupTeacherServiceImpl extends ServiceImpl + implements ClassQqGroupTeacherService { + +} + + + + diff --git a/src/main/java/com/linxyun/homework/service/impl/ClassServiceImpl.java b/src/main/java/com/linxyun/homework/service/impl/ClassServiceImpl.java new file mode 100644 index 0000000..3273b0a --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/impl/ClassServiceImpl.java @@ -0,0 +1,22 @@ +package com.linxyun.homework.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.linxyun.homework.domain.po.Class; +import com.linxyun.homework.service.ClassService; +import com.linxyun.homework.mapper.ClassMapper; +import org.springframework.stereotype.Service; + +/** +* @author wx_20 +* @description 针对表【tab_class】的数据库操作Service实现 +* @createDate 2024-11-25 09:45:12 +*/ +@Service +public class ClassServiceImpl extends ServiceImpl + implements ClassService{ + +} + + + + diff --git a/src/main/java/com/linxyun/homework/service/impl/HomeworkAnswerServiceImpl.java b/src/main/java/com/linxyun/homework/service/impl/HomeworkAnswerServiceImpl.java new file mode 100644 index 0000000..d4fc267 --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/impl/HomeworkAnswerServiceImpl.java @@ -0,0 +1,75 @@ +package com.linxyun.homework.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.linxyun.homework.common.entity.Result; +import com.linxyun.homework.common.enums.CourseType; +import com.linxyun.homework.common.enums.ErrorCode; +import com.linxyun.homework.domain.dto.AnswerMsg; +import com.linxyun.homework.domain.po.HomeworkAnswer; +import com.linxyun.homework.domain.po.TeacherQqMsgs; +import com.linxyun.homework.mapper.TeacherQqMsgsMapper; +import com.linxyun.homework.service.HomeworkAnswerService; +import com.linxyun.homework.mapper.HomeworkAnswerMapper; +import com.linxyun.homework.utils.StringUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** +* @author wx_20 +* @description 针对表【tab_homework_answer】的数据库操作Service实现 +* @createDate 2024-11-25 15:14:13 +*/ +@Service +@RequiredArgsConstructor +public class HomeworkAnswerServiceImpl extends ServiceImpl + implements HomeworkAnswerService{ + + private final HomeworkAnswerMapper homeworkAnswerMapper; + private final TeacherQqMsgsMapper teacherQqMsgsMapper; + + @Override + public Result addAnswerByMsgId(AnswerMsg answerMsg) { + Integer msgId = answerMsg.getMsgId(); + String title = answerMsg.getTitle(); + Integer memberId = answerMsg.getMemberId(); + if (msgId == null || memberId == null) { + log.error("msgId is null"); + return Result.error(ErrorCode.PARAMETER_ERROR); + } + // 根据 msgId 查询 消息 + TeacherQqMsgs teacherQqMsgs = teacherQqMsgsMapper.selectById(msgId); + if (teacherQqMsgs == null) { + log.error("msgId: " + msgId + " not found"); + return Result.error(ErrorCode.PARAMETER_ERROR); + } + if (!(teacherQqMsgs.getMsgContent().contains(answerMsg.getFile()) && teacherQqMsgs.getRemarks().contains(answerMsg.getContent()))) { + return Result.error(ErrorCode.PARAMETER_ERROR); + } + HomeworkAnswer homeworkAnswer = new HomeworkAnswer(); + homeworkAnswer.setMemberId(memberId); + if (StringUtils.isEmpty(title)) { + homeworkAnswer.setTitle(CourseType.getDescByCode(teacherQqMsgs.getCourseType())); // 课程类型 + } else { + homeworkAnswer.setTitle(title); + } + homeworkAnswer.setCreateType(1); // 班级可看 + homeworkAnswer.setStudentId(teacherQqMsgs.getClassId()); + if(answerMsg.getFile() != null) { + homeworkAnswer.setContentType(1); + homeworkAnswer.setRemark(answerMsg.getContent()); + homeworkAnswer.setContentFileId(answerMsg.getFile()); // 文件资源 + } else { + homeworkAnswer.setContentType(0); + homeworkAnswer.setContent(answerMsg.getContent()); // 文字 + } + int row = homeworkAnswerMapper.insert(homeworkAnswer); + if (row < 1) { + return Result.error(ErrorCode.OPERATION_FAIL); + } + return Result.ok(); + } +} + + + + diff --git a/src/main/java/com/linxyun/homework/service/impl/TeacherQqMsgsServiceImpl.java b/src/main/java/com/linxyun/homework/service/impl/TeacherQqMsgsServiceImpl.java new file mode 100644 index 0000000..6f1a5cd --- /dev/null +++ b/src/main/java/com/linxyun/homework/service/impl/TeacherQqMsgsServiceImpl.java @@ -0,0 +1,22 @@ +package com.linxyun.homework.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.linxyun.homework.domain.po.TeacherQqMsgs; +import com.linxyun.homework.service.TeacherQqMsgsService; +import com.linxyun.homework.mapper.TeacherQqMsgsMapper; +import org.springframework.stereotype.Service; + +/** +* @author wx_20 +* @description 针对表【tab_teacher_qq_msgs】的数据库操作Service实现 +* @createDate 2024-11-25 09:45:12 +*/ +@Service +public class TeacherQqMsgsServiceImpl extends ServiceImpl + implements TeacherQqMsgsService{ + +} + + + + diff --git a/src/main/java/com/linxyun/homework/utils/FileUtils.java b/src/main/java/com/linxyun/homework/utils/FileUtils.java new file mode 100644 index 0000000..fb14517 --- /dev/null +++ b/src/main/java/com/linxyun/homework/utils/FileUtils.java @@ -0,0 +1,153 @@ +package com.linxyun.homework.utils; + +import com.alibaba.fastjson2.JSONObject; +import com.linxyun.homework.HomeworkApplication; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.io.*; + +@Slf4j +@Component +public class FileUtils { + private static final OkHttpClient client = new OkHttpClient(); + + @Value("${upload.base-url}") + private String baseUrl; + + /** + * 下载文件到指定目录 + * @param fileUrl 文件 URL + * @param targetDir 本地目标目录 + * @param fileName 保存的文件名 + * @throws IOException 如果发生 IO 异常 + */ + public void downloadFile(String fileUrl, String targetDir, String fileName) throws IOException { + // 构建请求 + Request request = new Request.Builder() + .url(fileUrl) + .build(); + + // 执行请求 + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw new IOException("文件下载失败, HTTP 响应码: " + response.code()); + } + + // 确保目标目录存在 + File directory = new File(targetDir); + if (!directory.exists() && !directory.mkdirs()) { + throw new IOException("无法创建目标目录: " + targetDir); + } + + // 获取输入流并保存文件 + try (InputStream inputStream = response.body().byteStream(); + FileOutputStream outputStream = new FileOutputStream(new File(directory, fileName))) { + + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + } + + System.out.println("文件下载完成: " + targetDir + File.separator + fileName); + } + } + + /** + * 下载指定 URL 的文件,并将内容转化为字节数组。 + * + * @param fileUrl 文件的 URL + * @param fileName 文件名(可以用来关联下载到本地的文件) + * @return 文件内容的字节数组 + */ + public String uploadFileByUrl(String fileUrl, String fileName) { + // 创建 GET 请求 + Request request = new Request.Builder() + .url(fileUrl) + .build(); + + // 执行请求 + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + log.error("Failed to download file: " + response.message()); + return null; + } + + // 获取文件内容作为字节数组 + try (ResponseBody responseBody = response.body(); + InputStream inputStream = responseBody.byteStream(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { + byte[] buffer = new byte[4096]; + int bytesRead; + + // 读取数据到缓冲区 + while ((bytesRead = inputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, bytesRead); + } + return uploadFile(byteArrayOutputStream.toByteArray(), fileName); + } + } catch (IOException e) { + log.error("FileUploadTool uploadFileByUrl exception: ", e); + return null; + } + } + + + + /** + * 使用 OkHttp 上传文件 + * + * @param fileBytes 文件字节数组 + * @param fileName 文件名 + * @return 上传成功时返回服务器响应的 "data" 字段;否则返回 null + */ + public String uploadFile(byte[] fileBytes, String fileName) { + String uploadUrl = baseUrl + "/eslithe/uploadFile.action"; + // 创建请求体 + RequestBody fileBody = RequestBody.create(fileBytes, MediaType.parse("application/octet-stream")); + MultipartBody requestBody = new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("file", fileName, fileBody) + .build(); + + // 创建请求 + Request request = new Request.Builder() + .url(uploadUrl) + .post(requestBody) + .build(); + + // 执行请求 + try (Response response = client.newCall(request).execute()) { + if (response.isSuccessful() && response.body() != null) { + String responseBody = response.body().string(); + log.info("FileUploadTool uploadFile result: " + responseBody); + + // 解析响应 + JSONObject jsonObject = JSONObject.parseObject(responseBody); + if (jsonObject != null + && jsonObject.getBoolean("success") != null + && jsonObject.getBoolean("success") + && jsonObject.containsKey("data")) { + return jsonObject.getString("data"); + } else { + log.error("FileUploadTool uploadFile failed: " + responseBody); + return null; + } + } else { + log.error("FileUploadTool uploadFile failed, HTTP code: " + response.code()); + return null; + } + } catch (IOException ex) { + log.error("FileUploadTool uploadFile exception: ", ex); + return null; + } + } +} diff --git a/src/main/java/com/linxyun/homework/utils/StringUtils.java b/src/main/java/com/linxyun/homework/utils/StringUtils.java new file mode 100644 index 0000000..9ca1730 --- /dev/null +++ b/src/main/java/com/linxyun/homework/utils/StringUtils.java @@ -0,0 +1,8 @@ +package com.linxyun.homework.utils; + +public class StringUtils { + public static boolean isEmpty(String str) + { + return str == null || str.isEmpty(); + } +} diff --git a/src/main/java/com/linxyun/homework/utils/TimeUtils.java b/src/main/java/com/linxyun/homework/utils/TimeUtils.java new file mode 100644 index 0000000..09e1687 --- /dev/null +++ b/src/main/java/com/linxyun/homework/utils/TimeUtils.java @@ -0,0 +1,21 @@ +package com.linxyun.homework.utils; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class TimeUtils { + static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); // 定义日期格式 + public static Date toDate(String dateStr) { + try { + return dateFormat.parse(dateStr); + } catch (Exception e) { + e.printStackTrace(); // 如果有异常,输出错误信息 + } + return null; + } + + public static String getCurrentTime() { + Date now = new Date(); + return dateFormat.format(now); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ac1f6ca..d3d1a05 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,9 +6,9 @@ spring: #springboot的配置 datasource: #定义数据源 #127.0.0.1为本机测试的ip,3306是mysql的端口号。serverTimezone是定义时区,照抄就好,mysql高版本需要定义这些东西 #useSSL也是某些高版本mysql需要问有没有用SSL连接 - url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8&useSSL=FALSE + url: jdbc:mysql://117.89.254.176:8846/homeworkor?serverTimezone=GMT%2B8&useSSL=FALSE username: root #数据库用户名,root为管理员 - password: 123456 #该数据库用户的密码 + password: Home.lxy.com #该数据库用户的密码 # 使用druid数据源 type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver @@ -32,4 +32,28 @@ mybatis-plus: # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段 call-setters-on-nulls: true # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl \ No newline at end of file + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: 'default' + paths-to-match: '/**' + packages-to-scan: com.linxyun.homework.controller +# knife4j的增强配置,不需要增强可以不配 +knife4j: + enable: true + setting: + language: zh_cn + +mirai: + bot: + qq: 20243037 + +upload: + base-url: http://www.linxyun.com \ No newline at end of file diff --git a/src/main/resources/mapper/ClassMapper.xml b/src/main/resources/mapper/ClassMapper.xml new file mode 100644 index 0000000..8cb25f4 --- /dev/null +++ b/src/main/resources/mapper/ClassMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + ClassID,ClassName,Greade, + SchoolID,QQGroupID + + diff --git a/src/main/resources/mapper/ClassQqGroupTeacherMapper.xml b/src/main/resources/mapper/ClassQqGroupTeacherMapper.xml new file mode 100644 index 0000000..e0f910a --- /dev/null +++ b/src/main/resources/mapper/ClassQqGroupTeacherMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + RecordID,ClassID,TeacherGroupID, + TeacherNickName,CourseType + + + diff --git a/src/main/resources/mapper/HomeworkAnswerMapper.xml b/src/main/resources/mapper/HomeworkAnswerMapper.xml new file mode 100644 index 0000000..08586d1 --- /dev/null +++ b/src/main/resources/mapper/HomeworkAnswerMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + AnswerID,Title,ContentType, + Content,ContentFileID,MemberID, + StudentID,CreateType,CreateTime, + Remark + + diff --git a/src/main/resources/mapper/TeacherQqMsgsMapper.xml b/src/main/resources/mapper/TeacherQqMsgsMapper.xml new file mode 100644 index 0000000..669b583 --- /dev/null +++ b/src/main/resources/mapper/TeacherQqMsgsMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + MsgID,ClassID,TeacherQQID, + CourseType,MsgType,MsgContent, + CreateTime,Remarks + + diff --git a/src/test/java/com/linxyun/homework/HomeworkApplicationTests.java b/src/test/java/com/linxyun/homework/HomeworkApplicationTests.java index a099d9a..ee2c5bb 100644 --- a/src/test/java/com/linxyun/homework/HomeworkApplicationTests.java +++ b/src/test/java/com/linxyun/homework/HomeworkApplicationTests.java @@ -1,13 +1,21 @@ package com.linxyun.homework; +import com.linxyun.homework.utils.FileUtils; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class HomeworkApplicationTests { + @Autowired + private FileUtils fileUtils; + @Test void contextLoads() { + String url = "http://gchat.qpic.cn/download?appid=1407&fileid=EhQrqU1fCrXPCi9TYDHFtqLuEFeGBhi4ByD_CiiMnbCLvPaJAzIEcHJvZFCAvaMBWhCeolMmVCPCtR86R_2_Nq9x&rkey=CAQSOAB6JWENi5LMPAmzyUMyWlnciGpTV_s6NNl-6sRPEdwD-8haSCwEZCXEAROFKSCk0Vmp7_ZB0GmX&spec=0"; + String result = fileUtils.uploadFileByUrl(url, "test.png"); + System.out.println(result); // file_00001_20241125114456_00001.png } }