添加机器人处理指定群老师的消息;添加knife4j,便于生成接口文档;添加FileUtils,可以通过url上传远程文件系统;可将群消息处理到家庭作业答案

This commit is contained in:
wenxin 2024-11-25 19:59:56 +08:00
parent c654f079bd
commit 68fe006b2a
41 changed files with 1519 additions and 7 deletions

30
deviceInfo_20243037.json Normal file
View File

@ -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": "<unknown ssid>",
"imsiMd5": "6ba800c6d5513eb42b0fb90b6b5afd5c",
"imei": "864237812540469",
"apn": "wifi",
"androidId": "906fe7e62819be1e"
}
}

25
pom.xml
View File

@ -29,13 +29,34 @@
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>net.mamoe</groupId>
<artifactId>mirai-core-jvm</artifactId>
<version>2.99.0-local</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.53</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>

View File

@ -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);
}
}

View File

@ -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<ClassGroupTeacher> 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<ClassGroupTeacher> 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<BotEvent> 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);
}
}

View File

@ -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; // 表示停止监听事件
// }
}

View File

@ -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<E> {
@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 <T> Result<T> error(ErrorCode codeEnum) {
return new Result<>(null, codeEnum.getCode(), codeEnum.getMessage(), false);
}
public static <T> Result<T> error(String code, String msg) {
return new Result<>(null, code, msg, false);
}
public static <T> Result<T> ok() {
return new Result<>(null, "0000", "操作成功", true);
}
public static <T> Result<T> ok(String msg) {
return new Result<>(null, "0000", msg, true);
}
public static <T> Result<T> ok(T data) {
return new Result<>(data, "0000", "操作成功", true);
}
public static <T> Result<T> 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;
}
}

View File

@ -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;
}
}

View File

@ -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 "未知错误";
}
}

View File

@ -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"))
);
}
}

View File

@ -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("*");
}
}

View File

@ -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<Object> 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<Object> 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<Object> 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<Object> 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<Object> updateClass(@RequestBody Class clazz) {
boolean status = classService.updateById(clazz);
if (!status) {
return Result.error(ErrorCode.OPERATION_FAIL);
}
return Result.ok();
}
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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<Object> addAnswerByMsgId(@RequestBody AnswerMsg answerMsg) {
return homeworkAnswerService.addAnswerByMsgId(answerMsg);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<Class> {
}

View File

@ -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<ClassQqGroupTeacher> {
List<ClassGroupTeacher> selectClassAndGroupTeacher();
}

View File

@ -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<HomeworkAnswer> {
}

View File

@ -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<TeacherQqMsgs> {
}

View File

@ -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<ClassQqGroupTeacher> {
}

View File

@ -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<Class> {
}

View File

@ -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<HomeworkAnswer> {
Result<Object> addAnswerByMsgId(AnswerMsg answerMsg);
}

View File

@ -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<TeacherQqMsgs> {
}

View File

@ -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<ClassQqGroupTeacherMapper, ClassQqGroupTeacher>
implements ClassQqGroupTeacherService {
}

View File

@ -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<ClassMapper, Class>
implements ClassService{
}

View File

@ -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<HomeworkAnswerMapper, HomeworkAnswer>
implements HomeworkAnswerService{
private final HomeworkAnswerMapper homeworkAnswerMapper;
private final TeacherQqMsgsMapper teacherQqMsgsMapper;
@Override
public Result<Object> 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();
}
}

View File

@ -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<TeacherQqMsgsMapper, TeacherQqMsgs>
implements TeacherQqMsgsService{
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,8 @@
package com.linxyun.homework.utils;
public class StringUtils {
public static boolean isEmpty(String str)
{
return str == null || str.isEmpty();
}
}

View File

@ -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);
}
}

View File

@ -6,9 +6,9 @@ spring: #springboot的配置
datasource: #定义数据源
#127.0.0.1为本机测试的ip3306是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
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

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.linxyun.homework.mapper.ClassMapper">
<resultMap id="BaseResultMap" type="com.linxyun.homework.domain.po.Class">
<id property="classid" column="ClassID" jdbcType="INTEGER"/>
<result property="classname" column="ClassName" jdbcType="VARCHAR"/>
<result property="greade" column="Greade" jdbcType="VARCHAR"/>
<result property="schoolid" column="SchoolID" jdbcType="INTEGER"/>
<result property="qqgroupid" column="QQGroupID" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
ClassID,ClassName,Greade,
SchoolID,QQGroupID
</sql>
</mapper>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.linxyun.homework.mapper.ClassQqGroupTeacherMapper">
<resultMap id="BaseResultMap" type="com.linxyun.homework.domain.po.ClassQqGroupTeacher">
<id property="recordId" column="RecordID" jdbcType="INTEGER"/>
<result property="classId" column="ClassID" jdbcType="INTEGER"/>
<result property="teacherGroupId" column="TeacherGroupID" jdbcType="VARCHAR"/>
<result property="teacherNickname" column="TeacherNickName" jdbcType="VARCHAR"/>
<result property="courseType" column="CourseType" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
RecordID,ClassID,TeacherGroupID,
TeacherNickName,CourseType
</sql>
<select id="selectClassAndGroupTeacher" resultType="com.linxyun.homework.domain.dto.ClassGroupTeacher">
select
t.TeacherGroupID,
t.TeacherNickName,
t.ClassID, t.CourseType,
c.ClassName,
c.QQGroupID
from tab_class_qqgroup_teacher t
inner join tab_class c on t.ClassID = c.ClassID
</select>
</mapper>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.linxyun.homework.mapper.HomeworkAnswerMapper">
<resultMap id="BaseResultMap" type="com.linxyun.homework.domain.po.HomeworkAnswer">
<id property="answerid" column="AnswerID" jdbcType="INTEGER"/>
<result property="title" column="Title" jdbcType="VARCHAR"/>
<result property="contenttype" column="ContentType" jdbcType="INTEGER"/>
<result property="content" column="Content" jdbcType="VARCHAR"/>
<result property="contentfileid" column="ContentFileID" jdbcType="VARCHAR"/>
<result property="memberid" column="MemberID" jdbcType="INTEGER"/>
<result property="studentid" column="StudentID" jdbcType="INTEGER"/>
<result property="createtype" column="CreateType" jdbcType="INTEGER"/>
<result property="createtime" column="CreateTime" jdbcType="VARCHAR"/>
<result property="remark" column="Remark" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
AnswerID,Title,ContentType,
Content,ContentFileID,MemberID,
StudentID,CreateType,CreateTime,
Remark
</sql>
</mapper>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.linxyun.homework.mapper.TeacherQqMsgsMapper">
<resultMap id="BaseResultMap" type="com.linxyun.homework.domain.po.TeacherQqMsgs">
<id property="msgid" column="MsgID" jdbcType="INTEGER"/>
<result property="classid" column="ClassID" jdbcType="INTEGER"/>
<result property="teacherqqid" column="TeacherQQID" jdbcType="VARCHAR"/>
<result property="coursetype" column="CourseType" jdbcType="VARCHAR"/>
<result property="msgtype" column="MsgType" jdbcType="VARCHAR"/>
<result property="msgcontent" column="MsgContent" jdbcType="VARCHAR"/>
<result property="createtime" column="CreateTime" jdbcType="VARCHAR"/>
<result property="remarks" column="Remarks" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
MsgID,ClassID,TeacherQQID,
CourseType,MsgType,MsgContent,
CreateTime,Remarks
</sql>
</mapper>

View File

@ -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
}
}