diff --git a/.gitignore b/.gitignore index 9154f4c..326f057 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ hs_err_pid* replay_pid* +.idea +target \ No newline at end of file diff --git a/db/xm_examination.sql b/db/xm_examination.sql new file mode 100644 index 0000000..afaff92 --- /dev/null +++ b/db/xm_examination.sql @@ -0,0 +1,271 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost_3306 + Source Server Type : MySQL + Source Server Version : 80013 + Source Host : localhost:3306 + Source Schema : xm_examination + + Target Server Type : MySQL + Target Server Version : 80013 + File Encoding : 65001 + + Date: 12/10/2024 22:52:44 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for admin +-- ---------------------------- +DROP TABLE IF EXISTS `admin`; +CREATE TABLE `admin` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '账号', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '密码', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '姓名', + `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '头像', + `role` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '角色', + `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '电话', + `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '邮箱', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '管理员表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of admin +-- ---------------------------- +INSERT INTO `admin` VALUES (1, 'admin', 'admin', '管理员', 'http://localhost:9090/files/download/1721114905635-柴犬.jpeg', 'ADMIN', '18899990011', 'admin2@xm.com'); + +-- ---------------------------- +-- Table structure for article +-- ---------------------------- +DROP TABLE IF EXISTS `article`; +CREATE TABLE `article` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '帖子标题', + `img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '帖子主图', + `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '帖子内容', + `time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '发布时间', + `student_id` int(10) NULL DEFAULT NULL COMMENT '学生ID', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '帖子信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of article +-- ---------------------------- +INSERT INTO `article` VALUES (2, '关于学习Java枚举的笔记经验分享', 'http://localhost:9090/files/download/1728563732106-2.png', '

基于Springboot3+Vue3的在线考试系统

角色:管理员、教师、学生

功能模块:

登录注册:(已完成)

个人中心:(已完成)

修改密码:(已完成)

管理员信息:(已完成)

教师信息:(已完成)

学生信息:(已完成)

考试安排:(已完成)

题型管理:包括单选、多选、判断、填空、简答(已完成)

课程管理:(已完成)

学习交流管理:

题库管理:题库里的题目需要根据课程进行分类,不同的课程都得有对应的题库,教师可以给自己的课程题库里新增试题(已完成)

组卷:选择课程出卷时,支持随机和人工从题库里抽选题目,组成试卷

试卷预览:

成绩管理:

自动阅卷:客观题自动阅卷,主观题(简答)可以支持手动给分

前台学生:

查看考试安排、查看试卷

在线答题:试卷每种题型在线展示,供学生答题

学习交流:发布学习心得

\"\"

', '2024-10-10 20:35:34', 1); +INSERT INTO `article` VALUES (3, '武哥10万字Springboot经典教程学习笔记', 'http://localhost:9090/files/download/1728564558044-9.png', '66666', '2024-10-10 20:49:20', 2); +INSERT INTO `article` VALUES (5, '在线考试系统功能点描述分享', 'http://localhost:9090/files/download/1728564833337-10.png', '

基于Springboot3+Vue3的在线考试系统

角色:管理员、教师、学生

功能模块:

登录注册:(已完成)

个人中心:(已完成)

修改密码:(已完成)

管理员信息:(已完成)

教师信息:(已完成)

学生信息:(已完成)

考试安排:(已完成)

题型管理:包括单选、多选、判断、填空、简答(已完成)

课程管理:(已完成)

学习交流管理:


题库管理:题库里的题目需要根据课程进行分类,不同的课程都得有对应的题库,教师可以给自己的课程题库里新增试题(已完成)

组卷:选择课程出卷时,支持随机和人工从题库里抽选题目,组成试卷

试卷预览:

成绩管理:

自动阅卷:客观题自动阅卷,主观题(简答)可以支持手动给分

前台学生:

查看考试安排、查看试卷

在线答题:试卷每种题型在线展示,供学生答题

学习交流:发布学习心得


', '2024-10-10 20:53:55', 1); +INSERT INTO `article` VALUES (6, 'Vue3基础知识学习笔记', 'http://localhost:9090/files/download/1728568543079-7.png', '

哈哈哈

呵呵呵

嘿嘿嘿

嘎嘎嘎

啦啦啦

', '2024-10-10 21:55:52', 1); +INSERT INTO `article` VALUES (7, '前端三件套html,css,js学习心得', 'http://localhost:9090/files/download/1728568566399-right.jpg', '

哈哈哈

哈哈哈

嘿嘿黑

呵呵呵

嘎嘎嘎

', '2024-10-10 21:56:13', 1); + +-- ---------------------------- +-- Table structure for course +-- ---------------------------- +DROP TABLE IF EXISTS `course`; +CREATE TABLE `course` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '课程名称', + `img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '课程封面', + `score` int(10) NULL DEFAULT NULL COMMENT '课程学分', + `teacher_id` int(10) NULL DEFAULT NULL COMMENT '教师ID', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '课程信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of course +-- ---------------------------- +INSERT INTO `course` VALUES (2, 'Java基础入门课', 'http://localhost:9090/files/download/1728545691210-Java基础入门课程.jpg', 3, 1); +INSERT INTO `course` VALUES (3, 'Vue最新实战教程', 'http://localhost:9090/files/download/1728545950698-Vue最新教程.jpg', 3, 1); +INSERT INTO `course` VALUES (4, 'Java入学课程', 'http://localhost:9090/files/download/1728545989297-Java入学课程.jpg', 3, 2); + +-- ---------------------------- +-- Table structure for exam_plan +-- ---------------------------- +DROP TABLE IF EXISTS `exam_plan`; +CREATE TABLE `exam_plan` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '标题', + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '内容', + `time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '发布时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '考试安排表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of exam_plan +-- ---------------------------- +INSERT INTO `exam_plan` VALUES (1, '关于第一学期期末考试的安排', '考试时间:xxxx-xx-xx,考试地点:xxxx。注意事项:xxxx', '2024-10-10 14:21:13'); +INSERT INTO `exam_plan` VALUES (2, '关于考试考场纪律和作弊处罚措施', '本着公平公正原则,考试过程严禁作弊,请监考老师以及同学严格遵守,一旦发现,会取消该门课的考试资格,等待补考,如果补考作弊,该门课需要重修!', '2024-10-10 14:21:28'); +INSERT INTO `exam_plan` VALUES (3, '信息工程学院期末考试安排', '本着公平公正原则,考试过程严禁作弊,请监考老师以及同学严格遵守,一旦发现,会取消该门课的考试资格,等待补考,如果补考作弊,该门课需要重修!', '2024-10-10 14:21:40'); +INSERT INTO `exam_plan` VALUES (4, '软件学院期末考试安排', '考试时间:xxxx-xx-xx,考试地点:xxxx。注意事项:xxxx', '2024-10-10 14:21:51'); +INSERT INTO `exam_plan` VALUES (5, '经济管理学期末考试安排', '考试时间:xxxx-xx-xx,考试地点:xxxx。注意事项:xxxx', '2024-10-10 14:22:05'); +INSERT INTO `exam_plan` VALUES (6, '物流工程学院考试安排', '考试时间:xxxx-xx-xx,考试地点:xxxx。注意事项:xxxx', '2024-10-12 22:35:08'); + +-- ---------------------------- +-- Table structure for notice +-- ---------------------------- +DROP TABLE IF EXISTS `notice`; +CREATE TABLE `notice` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '公告标题', + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '公告内容', + `time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '发布时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统公告表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of notice +-- ---------------------------- +INSERT INTO `notice` VALUES (1, '今天天气真的不错', '今天好开心呀!因为天气很好,我又可以肆无忌惮的跟着武哥和青哥学习了!!真的好开心!', '2024-07-16 15:51:17'); +INSERT INTO `notice` VALUES (2, '项目所有功能开发完毕!', '我的项目所有的功能都开发完啦!真的很有成就感!', '2024-07-16 15:52:22'); +INSERT INTO `notice` VALUES (3, '项目功能都测试完成,准备上线!', '经过半个月的学习和练习,终于把这个项目完成了,可以打包上线了!', '2024-07-16 15:52:56'); + +-- ---------------------------- +-- Table structure for question +-- ---------------------------- +DROP TABLE IF EXISTS `question`; +CREATE TABLE `question` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '题目名称', + `course_id` int(10) NULL DEFAULT NULL COMMENT '课程ID', + `teacher_id` int(10) NULL DEFAULT NULL COMMENT '教师ID', + `type_id` int(10) NULL DEFAULT NULL COMMENT '题型ID', + `option_a` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '选项A', + `option_b` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '选项B', + `option_c` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '选项C', + `option_d` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '选项D', + `answer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '题目答案', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '题目信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of question +-- ---------------------------- +INSERT INTO `question` VALUES (2, 'Java是世界上最好的语言!', 2, 1, 3, NULL, NULL, NULL, NULL, '正确'); +INSERT INTO `question` VALUES (3, '下面哪一项不是Java基本数据类型?', 2, 1, 1, 'int', 'int', 'float', 'let', 'D'); +INSERT INTO `question` VALUES (4, '下面哪些选项是Java的特点?', 2, 1, 2, 'Java是后端语言', 'Java是前端语言', 'Java是强类型语言', 'Java是弱类型语言', 'A,C'); +INSERT INTO `question` VALUES (5, 'Java语言的创造者是______。', 2, 1, 4, NULL, NULL, NULL, NULL, 'James Gosling'); +INSERT INTO `question` VALUES (6, '请写一个冒泡排序算法。', 2, 1, 5, NULL, NULL, NULL, NULL, 'public void bubbleSort(int[] source) {\n for(int i = source.length - 1; i > 0; i--) {\n for(int j = 0; j < i; j++) {\n if(a[j] > a[j+1])\n swap(source, j, j+1); \n }\n }\n}'); +INSERT INTO `question` VALUES (7, '所有的Java项目里都有一个启动的______方法。', 4, 2, 4, NULL, NULL, NULL, NULL, 'main'); + +-- ---------------------------- +-- Table structure for question_type +-- ---------------------------- +DROP TABLE IF EXISTS `question_type`; +CREATE TABLE `question_type` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '题型名称', + `score` int(10) NULL DEFAULT NULL COMMENT '题型分数', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '题型信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of question_type +-- ---------------------------- +INSERT INTO `question_type` VALUES (1, '单选题', 4); +INSERT INTO `question_type` VALUES (2, '多选题', 5); +INSERT INTO `question_type` VALUES (3, '判断题', 2); +INSERT INTO `question_type` VALUES (4, '填空题', 4); +INSERT INTO `question_type` VALUES (5, '简答题', 20); + +-- ---------------------------- +-- Table structure for score +-- ---------------------------- +DROP TABLE IF EXISTS `score`; +CREATE TABLE `score` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '试卷名称', + `course_id` int(10) NULL DEFAULT NULL COMMENT '课程ID', + `teacher_id` int(10) NULL DEFAULT NULL COMMENT '教师ID', + `student_id` int(10) NULL DEFAULT NULL COMMENT '学生ID', + `paper_id` int(10) NULL DEFAULT NULL COMMENT '试卷ID', + `score` int(10) NULL DEFAULT NULL COMMENT '成绩得分', + `status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '状态', + `answer` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '提交结果', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '成绩信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of score +-- ---------------------------- +INSERT INTO `score` VALUES (2, 'Java基础入门课小测验2', 2, 1, 1, 2, 13, '已阅卷', '[{\"typeName\":\"单选题\",\"questionId\":3,\"score\":4,\"answer\":\"D\",\"newAnswer\":\"D\"},{\"typeName\":\"多选题\",\"questionId\":4,\"score\":5,\"answer\":\"A,C\",\"newAnswer\":\"A,C\"},{\"typeName\":\"判断题\",\"questionId\":2,\"score\":2,\"answer\":\"正确\",\"newAnswer\":\"正确\"},{\"typeName\":\"填空题\",\"questionId\":5,\"score\":4,\"answer\":\"James Gosling\",\"newAnswer\":\"张三\"},{\"typeName\":\"简答题\",\"questionId\":6,\"score\":20,\"answer\":\"public void bubbleSort(int[] source) {\\n for(int i = source.length - 1; i > 0; i--) {\\n for(int j = 0; j < i; j++) {\\n if(a[j] > a[j+1])\\n swap(source, j, j+1); \\n }\\n }\\n}\",\"newAnswer\":\"public static void main() \"}]'); +INSERT INTO `score` VALUES (3, 'Java基础入门课小测验3', 2, 1, 1, 3, NULL, '待阅卷', '[{\"typeName\":\"单选题\",\"questionId\":3,\"score\":4,\"answer\":\"D\",\"newAnswer\":\"D\"},{\"typeName\":\"多选题\",\"questionId\":4,\"score\":5,\"answer\":\"A,C\",\"newAnswer\":\"A,C\"},{\"typeName\":\"简答题\",\"questionId\":6,\"score\":20,\"answer\":\"public void bubbleSort(int[] source) {\\n for(int i = source.length - 1; i > 0; i--) {\\n for(int j = 0; j < i; j++) {\\n if(a[j] > a[j+1])\\n swap(source, j, j+1); \\n }\\n }\\n}\",\"newAnswer\":\"public void bubbleSort(int[] source) {\\n for(int i = source.length - 1; i > 0; i--) {\\n for(int j = 0; j < i; j++) {\\n if(a[j] > a[j+1])\\n swap(source, j, j+1); \\n }\\n }\\n}\"}]'); +INSERT INTO `score` VALUES (4, 'Java基础入门课小测验1', 2, 1, 1, 1, 20, '已阅卷', '[{\"typeName\":\"判断题\",\"questionId\":2,\"score\":2,\"answer\":\"正确\",\"newAnswer\":\"正确\"},{\"typeName\":\"单选题\",\"questionId\":3,\"score\":4,\"answer\":\"D\",\"newAnswer\":\"D\"},{\"typeName\":\"多选题\",\"questionId\":4,\"score\":5,\"answer\":\"A,C\",\"newAnswer\":\"C,A\"},{\"typeName\":\"填空题\",\"questionId\":5,\"score\":4,\"answer\":\"James Gosling\",\"newAnswer\":\"James Gosling\"},{\"typeName\":\"简答题\",\"questionId\":6,\"score\":20,\"answer\":\"public void bubbleSort(int[] source) {\\n for(int i = source.length - 1; i > 0; i--) {\\n for(int j = 0; j < i; j++) {\\n if(a[j] > a[j+1])\\n swap(source, j, j+1); \\n }\\n }\\n}\",\"newAnswer\":\"public static void main( ) {\\n System.print......\\n 老师我不会了,给我点辛苦分吧~\\n}\"}]'); + +-- ---------------------------- +-- Table structure for student +-- ---------------------------- +DROP TABLE IF EXISTS `student`; +CREATE TABLE `student` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '账号', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '密码', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '姓名', + `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '头像', + `role` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '角色', + `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '电话', + `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '邮箱', + `status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '状态', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '学生信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of student +-- ---------------------------- +INSERT INTO `student` VALUES (1, 'zhangsan', '123456', '张三', 'http://localhost:9090/files/download/1728486694570-柴犬.jpeg', 'STUDENT', '18899990000', 'zhangsan@xm.com', '审核通过'); +INSERT INTO `student` VALUES (2, 'lisi', '123456', '李四', 'http://localhost:9090/files/download/1728486728196-拉布拉多.jpeg', 'STUDENT', '18899995555', 'lisi@xm.com', '审核通过'); +INSERT INTO `student` VALUES (3, 'wangwu', '123456', '王五', 'http://localhost:9090/files/download/1728486753434-柯基.jpeg', 'STUDENT', '18844445555', 'wangwu@xm.com', '审核通过'); +INSERT INTO `student` VALUES (4, 'zhaoliu', '123456', 'zhaoliu', NULL, 'STUDENT', NULL, NULL, '待审核'); + +-- ---------------------------- +-- Table structure for teacher +-- ---------------------------- +DROP TABLE IF EXISTS `teacher`; +CREATE TABLE `teacher` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '账号', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '密码', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '姓名', + `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '头像', + `role` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '角色', + `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '电话', + `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '邮箱', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '教师信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of teacher +-- ---------------------------- +INSERT INTO `teacher` VALUES (1, 'zhang', '123456', '张老师', 'http://localhost:9090/files/download/1728484762449-柴犬.jpeg', 'TEACHER', '18800001111', 'zhang@xm.com'); +INSERT INTO `teacher` VALUES (2, 'li', '123456', '李老师', 'http://localhost:9090/files/download/1728484862680-柯基.jpeg', 'TEACHER', '18877776666', 'li@xm.com'); +INSERT INTO `teacher` VALUES (3, 'zhao', '123456', 'zhao', NULL, 'TEACHER', NULL, NULL); + +-- ---------------------------- +-- Table structure for test_paper +-- ---------------------------- +DROP TABLE IF EXISTS `test_paper`; +CREATE TABLE `test_paper` ( + `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '试卷名称', + `course_id` int(10) NULL DEFAULT NULL COMMENT '课程ID', + `teacher_id` int(10) NULL DEFAULT NULL COMMENT '教师ID', + `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '类型', + `start` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '开始时间', + `end` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '结束时间', + `time` int(10) NULL DEFAULT NULL COMMENT '考试时长', + `question_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '题目IDs', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '试卷信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_paper +-- ---------------------------- +INSERT INTO `test_paper` VALUES (1, 'Java基础入门课小测验1', 2, 1, '手动选题', '2024-10-11', '2024-10-26', 60, '[2,3,4,5,6]'); +INSERT INTO `test_paper` VALUES (2, 'Java基础入门课小测验2', 2, 1, '自动组卷', '2024-10-11', '2024-10-26', 60, '[3,4,2,5,6]'); +INSERT INTO `test_paper` VALUES (3, 'Java基础入门课小测验3', 2, 1, '自动组卷', '2024-10-11', '2024-10-24', 60, '[3,4,6]'); +INSERT INTO `test_paper` VALUES (4, 'Java基础入门小测验4', 2, 1, '手动选题', '2024-10-12', '2025-11-13', 60, '[3,4,2,6]'); +INSERT INTO `test_paper` VALUES (5, 'Java基础入门小测验5', 2, 1, '自动组卷', '2024-10-12', '2025-10-09', 60, '[3,4,2,5,6]'); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/files/1721114905635-柴犬.jpeg b/files/1721114905635-柴犬.jpeg new file mode 100644 index 0000000..ec1ef01 Binary files /dev/null and b/files/1721114905635-柴犬.jpeg differ diff --git a/files/1728484762449-柴犬.jpeg b/files/1728484762449-柴犬.jpeg new file mode 100644 index 0000000..ec1ef01 Binary files /dev/null and b/files/1728484762449-柴犬.jpeg differ diff --git a/files/1728484862680-柯基.jpeg b/files/1728484862680-柯基.jpeg new file mode 100644 index 0000000..d78f64b Binary files /dev/null and b/files/1728484862680-柯基.jpeg differ diff --git a/files/1728486694570-柴犬.jpeg b/files/1728486694570-柴犬.jpeg new file mode 100644 index 0000000..ec1ef01 Binary files /dev/null and b/files/1728486694570-柴犬.jpeg differ diff --git a/files/1728486728196-拉布拉多.jpeg b/files/1728486728196-拉布拉多.jpeg new file mode 100644 index 0000000..bbae442 Binary files /dev/null and b/files/1728486728196-拉布拉多.jpeg differ diff --git a/files/1728486753434-柯基.jpeg b/files/1728486753434-柯基.jpeg new file mode 100644 index 0000000..d78f64b Binary files /dev/null and b/files/1728486753434-柯基.jpeg differ diff --git a/files/1728545484737-Java基础入门课程.jpg b/files/1728545484737-Java基础入门课程.jpg new file mode 100644 index 0000000..53aaf6a Binary files /dev/null and b/files/1728545484737-Java基础入门课程.jpg differ diff --git a/files/1728545691210-Java基础入门课程.jpg b/files/1728545691210-Java基础入门课程.jpg new file mode 100644 index 0000000..53aaf6a Binary files /dev/null and b/files/1728545691210-Java基础入门课程.jpg differ diff --git a/files/1728545950698-Vue最新教程.jpg b/files/1728545950698-Vue最新教程.jpg new file mode 100644 index 0000000..6cae207 Binary files /dev/null and b/files/1728545950698-Vue最新教程.jpg differ diff --git a/files/1728545989297-Java入学课程.jpg b/files/1728545989297-Java入学课程.jpg new file mode 100644 index 0000000..48c0a73 Binary files /dev/null and b/files/1728545989297-Java入学课程.jpg differ diff --git a/files/1728563597926-2.png b/files/1728563597926-2.png new file mode 100644 index 0000000..bfccb63 Binary files /dev/null and b/files/1728563597926-2.png differ diff --git a/files/1728563732106-2.png b/files/1728563732106-2.png new file mode 100644 index 0000000..bfccb63 Binary files /dev/null and b/files/1728563732106-2.png differ diff --git a/files/1728564558044-9.png b/files/1728564558044-9.png new file mode 100644 index 0000000..1a8446d Binary files /dev/null and b/files/1728564558044-9.png differ diff --git a/files/1728564626540-10.png b/files/1728564626540-10.png new file mode 100644 index 0000000..27ce7e2 Binary files /dev/null and b/files/1728564626540-10.png differ diff --git a/files/1728564833337-10.png b/files/1728564833337-10.png new file mode 100644 index 0000000..27ce7e2 Binary files /dev/null and b/files/1728564833337-10.png differ diff --git a/files/1728566947212-柴犬.jpeg b/files/1728566947212-柴犬.jpeg new file mode 100644 index 0000000..ec1ef01 Binary files /dev/null and b/files/1728566947212-柴犬.jpeg differ diff --git a/files/1728568543079-7.png b/files/1728568543079-7.png new file mode 100644 index 0000000..8df622b Binary files /dev/null and b/files/1728568543079-7.png differ diff --git a/files/1728568566399-right.jpg b/files/1728568566399-right.jpg new file mode 100644 index 0000000..3150b0b Binary files /dev/null and b/files/1728568566399-right.jpg differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..104293a --- /dev/null +++ b/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.1 + + + com.example + java-experiment + 0.0.1-SNAPSHOT + springboot + springboot + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.3 + + + + com.mysql + mysql-connector-j + runtime + + + + cn.hutool + hutool-all + 5.8.25 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.6 + + + org.mybatis + mybatis + + + + + + + com.auth0 + java-jwt + 4.3.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/src/main/java/com/example/SpringbootApplication.java b/src/main/java/com/example/SpringbootApplication.java new file mode 100644 index 0000000..f0d2eb2 --- /dev/null +++ b/src/main/java/com/example/SpringbootApplication.java @@ -0,0 +1,13 @@ +package com.example; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.example.mapper") +public class SpringbootApplication { public static void main(String[] args) { + SpringApplication.run(SpringbootApplication.class, args); + } + +} diff --git a/src/main/java/com/example/common/Constants.java b/src/main/java/com/example/common/Constants.java new file mode 100644 index 0000000..2e09293 --- /dev/null +++ b/src/main/java/com/example/common/Constants.java @@ -0,0 +1,7 @@ +package com.example.common; + +public interface Constants { + + String TOKEN = "token"; + String USER_DEFAULT_PASSWORD = "123456"; +} diff --git a/src/main/java/com/example/common/Result.java b/src/main/java/com/example/common/Result.java new file mode 100644 index 0000000..22ac335 --- /dev/null +++ b/src/main/java/com/example/common/Result.java @@ -0,0 +1,70 @@ +package com.example.common; + +public class Result { + + private String code; + private String msg; + private Object data; + + public Result() { + + } + + public static Result success() { + Result result = new Result(); + result.setCode("200"); + result.setMsg("请求成功"); + return result; + } + + public static Result success(Object data) { + Result result = success(); + result.setData(data); + return result; + } + + public static Result error() { + Result result = new Result(); + result.setCode("500"); + result.setMsg("系统异常"); + return result; + } + + public static Result error(String code, String msg) { + Result result = new Result(); + result.setCode(code); + result.setMsg(msg); + return result; + } + + public static Result error(String msg) { + Result result = new Result(); + result.setCode("500"); + result.setMsg(msg); + return result; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } +} diff --git a/src/main/java/com/example/common/config/CorsConfig.java b/src/main/java/com/example/common/config/CorsConfig.java new file mode 100644 index 0000000..9be21e6 --- /dev/null +++ b/src/main/java/com/example/common/config/CorsConfig.java @@ -0,0 +1,25 @@ +package com.example.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +/** + * 跨域配置 + */ +@Configuration +public class CorsConfig { + + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址 + corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头 + corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法 + source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置 + return new CorsFilter(source); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/common/config/JWTInterceptor.java b/src/main/java/com/example/common/config/JWTInterceptor.java new file mode 100644 index 0000000..6eadc9b --- /dev/null +++ b/src/main/java/com/example/common/config/JWTInterceptor.java @@ -0,0 +1,81 @@ +package com.example.common.config; + +import cn.hutool.core.util.ObjectUtil; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.example.common.Constants; +import com.example.common.enums.ResultCodeEnum; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.exception.CustomException; +import com.example.service.AdminService; +import com.example.service.StudentService; +import com.example.service.TeacherService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * JWT拦截器 + */ +@Component +public class JWTInterceptor implements HandlerInterceptor { + + @Resource + private AdminService adminService; + @Resource + private TeacherService teacherService; + @Resource + private StudentService studentService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 1. 从http请求标头里面拿到token + String token = request.getHeader(Constants.TOKEN); + if (ObjectUtil.isNull(token)) { + // 如果没拿到,那么再从请求参数里拿一次 + request.getParameter(Constants.TOKEN); + } + // 2. 开始执行认证 + if (ObjectUtil.isNull(token)) { + throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR); + } + Account account = null; + try { + String audience = JWT.decode(token).getAudience().get(0); + String userId = audience.split("-")[0]; + String role = audience.split("-")[1]; + // 根据用户角色判断用户属于哪个数据库表 然后查询用户数据 + if (RoleEnum.ADMIN.name().equals(role)) { + account = adminService.selectById(Integer.valueOf(userId)); + } + if (RoleEnum.TEACHER.name().equals(role)) { + account = teacherService.selectById(Integer.valueOf(userId)); + } + if (RoleEnum.STUDENT.name().equals(role)) { + account = studentService.selectById(Integer.valueOf(userId)); + } + } catch (Exception e) { + throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR); + } + // 根据token里面携带的用户ID去对应的角色表查询 没查到 所有报了这个“用户不存在”错误 + if (ObjectUtil.isNull(account)) { + // 用户不存在 + throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR); + } + try { + // 通过用户的密码作为密钥再次验证token的合法性 + JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(account.getPassword())).build(); + jwtVerifier.verify(token); // 验证token + } catch (JWTVerificationException e) { + // 用户不存在 + throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR); + } + return true; + } + +} diff --git a/src/main/java/com/example/common/config/WebConfig.java b/src/main/java/com/example/common/config/WebConfig.java new file mode 100644 index 0000000..5d7d975 --- /dev/null +++ b/src/main/java/com/example/common/config/WebConfig.java @@ -0,0 +1,21 @@ +package com.example.common.config; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Resource + private JWTInterceptor jwtInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtInterceptor).addPathPatterns("/**") + .excludePathPatterns("/") + .excludePathPatterns("/login", "/register", "/files/**"); + } + +} diff --git a/src/main/java/com/example/common/enums/ResultCodeEnum.java b/src/main/java/com/example/common/enums/ResultCodeEnum.java new file mode 100644 index 0000000..7b6e41e --- /dev/null +++ b/src/main/java/com/example/common/enums/ResultCodeEnum.java @@ -0,0 +1,26 @@ +package com.example.common.enums; + +public enum ResultCodeEnum { + + SUCCESS("200", "成功"), + PARAM_ERROR("400", "参数异常"), + TOKEN_INVALID_ERROR("401", "无效的token"), + TOKEN_CHECK_ERROR("401", "token验证失败,请重新登录"), + PARAM_LOST_ERROR("4001", "参数缺失"), + + SYSTEM_ERROR("500", "系统异常"), + USER_EXIST_ERROR("5001", "用户名已存在"), + USER_NOT_LOGIN("5002", "用户未登录"), + USER_ACCOUNT_ERROR("5003", "账号或密码错误"), + USER_NOT_EXIST_ERROR("5004", "用户不存在"), + PARAM_PASSWORD_ERROR("5005", "原密码输入错误"), + ; + + public String code; + public String msg; + + ResultCodeEnum(String code, String msg) { + this.code = code; + this.msg = msg; + } +} diff --git a/src/main/java/com/example/common/enums/RoleEnum.java b/src/main/java/com/example/common/enums/RoleEnum.java new file mode 100644 index 0000000..cf7aed7 --- /dev/null +++ b/src/main/java/com/example/common/enums/RoleEnum.java @@ -0,0 +1,10 @@ +package com.example.common.enums; + +public enum RoleEnum { + // 管理员 + ADMIN, + // 教师 + TEACHER, + // 学生 + STUDENT +} diff --git a/src/main/java/com/example/controller/AdminController.java b/src/main/java/com/example/controller/AdminController.java new file mode 100644 index 0000000..7783195 --- /dev/null +++ b/src/main/java/com/example/controller/AdminController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Admin; +import com.example.service.AdminService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 前端请求接口 + */ +@RestController +@RequestMapping("/admin") +public class AdminController { + + @Resource + private AdminService adminService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody Admin admin) { + adminService.add(admin); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Admin admin) { + adminService.updateById(admin); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + adminService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + adminService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Admin admin = adminService.selectById(id); + return Result.success(admin); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Admin admin) { + List list = adminService.selectAll(admin); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Admin admin, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = adminService.selectPage(admin, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/ArticleController.java b/src/main/java/com/example/controller/ArticleController.java new file mode 100644 index 0000000..7c0ffa8 --- /dev/null +++ b/src/main/java/com/example/controller/ArticleController.java @@ -0,0 +1,93 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Article; +import com.example.service.ArticleService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 帖子信息前端请求接口 + */ +@RestController +@RequestMapping("/article") +public class ArticleController { + + @Resource + private ArticleService articleService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody Article article) { + articleService.add(article); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Article article) { + articleService.updateById(article); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + articleService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + articleService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Article article = articleService.selectById(id); + return Result.success(article); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Article article) { + List
list = articleService.selectAll(article); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Article article, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo
pageInfo = articleService.selectPage(article, pageNum, pageSize); + return Result.success(pageInfo); + } + + @GetMapping("/selectRandom") + public Result selectRandom() { + List
list = articleService.selectRandom(); + return Result.success(list); + } + +} diff --git a/src/main/java/com/example/controller/CourseController.java b/src/main/java/com/example/controller/CourseController.java new file mode 100644 index 0000000..658ce38 --- /dev/null +++ b/src/main/java/com/example/controller/CourseController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Course; +import com.example.service.CourseService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 课程信息前端请求接口 + */ +@RestController +@RequestMapping("/course") +public class CourseController { + + @Resource + private CourseService courseService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody Course course) { + courseService.add(course); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Course course) { + courseService.updateById(course); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + courseService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + courseService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Course course = courseService.selectById(id); + return Result.success(course); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Course course) { + List list = courseService.selectAll(course); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Course course, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = courseService.selectPage(course, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/ExamPlanController.java b/src/main/java/com/example/controller/ExamPlanController.java new file mode 100644 index 0000000..54e37f5 --- /dev/null +++ b/src/main/java/com/example/controller/ExamPlanController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.ExamPlan; +import com.example.service.ExamPlanService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 考试安排前端请求接口 + */ +@RestController +@RequestMapping("/examPlan") +public class ExamPlanController { + + @Resource + private ExamPlanService examPlanService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody ExamPlan examPlan) { + examPlanService.add(examPlan); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody ExamPlan examPlan) { + examPlanService.updateById(examPlan); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + examPlanService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + examPlanService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + ExamPlan examPlan = examPlanService.selectById(id); + return Result.success(examPlan); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(ExamPlan examPlan) { + List list = examPlanService.selectAll(examPlan); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(ExamPlan examPlan, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = examPlanService.selectPage(examPlan, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/FileController.java b/src/main/java/com/example/controller/FileController.java new file mode 100644 index 0000000..ad4c9cc --- /dev/null +++ b/src/main/java/com/example/controller/FileController.java @@ -0,0 +1,96 @@ +package com.example.controller; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import com.example.common.Result; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.OutputStream; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/files") +public class FileController { + + private static final Logger log = LoggerFactory.getLogger(FileController.class); + + private static final String filePath = System.getProperty("user.dir") + "/files/"; + + @Value("${fileBaseUrl:}") + private String fileBaseUrl; + + /** + * 文件上传 + */ + @PostMapping("/upload") + public Result upload(MultipartFile file) { + String fileName = file.getOriginalFilename(); + try { + if (!FileUtil.isDirectory(filePath)) { + FileUtil.mkdir(filePath); + } + fileName = System.currentTimeMillis() + "-" + fileName; + String realFilePath = filePath + fileName; + // 文件存储形式:时间戳-文件名 + FileUtil.writeBytes(file.getBytes(), realFilePath); + } catch (Exception e) { + log.error(fileName + "--文件上传失败", e); + } + String url = fileBaseUrl + "/files/download/" + fileName; + return Result.success(url); + } + + /** + * 获取文件 + */ + @GetMapping("/download/{fileName}") + public void download(@PathVariable String fileName, HttpServletResponse response) { + OutputStream os; + try { + if (StrUtil.isNotEmpty(fileName)) { + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8)); + response.setContentType("application/octet-stream"); + byte[] bytes = FileUtil.readBytes(filePath + fileName); + os = response.getOutputStream(); + os.write(bytes); + os.flush(); + os.close(); + } + } catch (Exception e) { + log.warn("文件下载失败:" + fileName); + } + } + + /** + * wang-editor编辑器文件上传接口 + */ + @PostMapping("/wang/upload") + public Map wangEditorUpload(MultipartFile file) { + String flag = System.currentTimeMillis() + ""; + String fileName = file.getOriginalFilename(); + try { + // 文件存储形式:时间戳-文件名 + FileUtil.writeBytes(file.getBytes(), filePath + flag + "-" + fileName); + System.out.println(fileName + "--上传成功"); + Thread.sleep(1L); + } catch (Exception e) { + System.err.println(fileName + "--文件上传失败"); + } + String http = fileBaseUrl + "/files/download/"; + Map resMap = new HashMap<>(); + // wangEditor上传图片成功后, 需要返回的参数 + resMap.put("errno", 0); + resMap.put("data", CollUtil.newArrayList(Dict.create().set("url", http + flag + "-" + fileName))); + return resMap; + } +} diff --git a/src/main/java/com/example/controller/NoticeController.java b/src/main/java/com/example/controller/NoticeController.java new file mode 100644 index 0000000..891d9de --- /dev/null +++ b/src/main/java/com/example/controller/NoticeController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Notice; +import com.example.service.NoticeService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 前端请求接口 + */ +@RestController +@RequestMapping("/notice") +public class NoticeController { + + @Resource + private NoticeService noticeService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody Notice notice) { + noticeService.add(notice); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Notice notice) { + noticeService.updateById(notice); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + noticeService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + noticeService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Notice notice = noticeService.selectById(id); + return Result.success(notice); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Notice notice) { + List list = noticeService.selectAll(notice); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Notice notice, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = noticeService.selectPage(notice, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/QuestionController.java b/src/main/java/com/example/controller/QuestionController.java new file mode 100644 index 0000000..f363224 --- /dev/null +++ b/src/main/java/com/example/controller/QuestionController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Question; +import com.example.service.QuestionService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 题目信息前端请求接口 + */ +@RestController +@RequestMapping("/question") +public class QuestionController { + + @Resource + private QuestionService questionService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody Question question) { + questionService.add(question); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Question question) { + questionService.updateById(question); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + questionService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + questionService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Question question = questionService.selectById(id); + return Result.success(question); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Question question) { + List list = questionService.selectAll(question); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Question question, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = questionService.selectPage(question, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/QuestionTypeController.java b/src/main/java/com/example/controller/QuestionTypeController.java new file mode 100644 index 0000000..d4a8cc6 --- /dev/null +++ b/src/main/java/com/example/controller/QuestionTypeController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.QuestionType; +import com.example.service.QuestionTypeService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 题型信息前端请求接口 + */ +@RestController +@RequestMapping("/questionType") +public class QuestionTypeController { + + @Resource + private QuestionTypeService questionTypeService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody QuestionType questionType) { + questionTypeService.add(questionType); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody QuestionType questionType) { + questionTypeService.updateById(questionType); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + questionTypeService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + questionTypeService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + QuestionType questionType = questionTypeService.selectById(id); + return Result.success(questionType); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(QuestionType questionType) { + List list = questionTypeService.selectAll(questionType); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(QuestionType questionType, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = questionTypeService.selectPage(questionType, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/ScoreController.java b/src/main/java/com/example/controller/ScoreController.java new file mode 100644 index 0000000..e2331d1 --- /dev/null +++ b/src/main/java/com/example/controller/ScoreController.java @@ -0,0 +1,94 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Answer; +import com.example.entity.Score; +import com.example.entity.TestPaper; +import com.example.service.ScoreService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 试卷信息前端请求接口 + */ +@RestController +@RequestMapping("/score") +public class ScoreController { + + @Resource + private ScoreService scoreService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody TestPaper testPaper) { + scoreService.add(testPaper); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Score score) { + scoreService.updateById(score); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + scoreService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + scoreService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Score score = scoreService.selectById(id); + return Result.success(score); + } + @GetMapping("/selectAnswer/{id}") + public Result selectAnswer(@PathVariable Integer id) { + List list = scoreService.selectAnswer(id); + return Result.success(list); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Score score) { + List list = scoreService.selectAll(score); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Score score, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = scoreService.selectPage(score, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/StudentController.java b/src/main/java/com/example/controller/StudentController.java new file mode 100644 index 0000000..5e36dd1 --- /dev/null +++ b/src/main/java/com/example/controller/StudentController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Student; +import com.example.service.StudentService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 学生信息前端请求接口 + */ +@RestController +@RequestMapping("/student") +public class StudentController { + + @Resource + private StudentService studentService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody Student student) { + studentService.add(student); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Student student) { + studentService.updateById(student); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + studentService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + studentService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Student student = studentService.selectById(id); + return Result.success(student); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Student student) { + List list = studentService.selectAll(student); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Student student, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = studentService.selectPage(student, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/TeacherController.java b/src/main/java/com/example/controller/TeacherController.java new file mode 100644 index 0000000..cd9da22 --- /dev/null +++ b/src/main/java/com/example/controller/TeacherController.java @@ -0,0 +1,87 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.Teacher; +import com.example.service.TeacherService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 教师信息前端请求接口 + */ +@RestController +@RequestMapping("/teacher") +public class TeacherController { + + @Resource + private TeacherService teacherService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody Teacher teacher) { + teacherService.add(teacher); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody Teacher teacher) { + teacherService.updateById(teacher); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + teacherService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + teacherService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + Teacher teacher = teacherService.selectById(id); + return Result.success(teacher); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(Teacher teacher) { + List list = teacherService.selectAll(teacher); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(Teacher teacher, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) { + PageInfo pageInfo = teacherService.selectPage(teacher, pageNum, pageSize); + return Result.success(pageInfo); + } + +} diff --git a/src/main/java/com/example/controller/TestPaperController.java b/src/main/java/com/example/controller/TestPaperController.java new file mode 100644 index 0000000..2a83b97 --- /dev/null +++ b/src/main/java/com/example/controller/TestPaperController.java @@ -0,0 +1,100 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.entity.TestPaper; +import com.example.service.TestPaperService; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.text.ParseException; +import java.util.List; + +/** + * 试卷信息前端请求接口 + */ +@RestController +@RequestMapping("/testPaper") +public class TestPaperController { + + @Resource + private TestPaperService testPaperService; + + /** + * 新增 + */ + @PostMapping("/add") + public Result add(@RequestBody TestPaper testPaper) throws ParseException { + testPaperService.add(testPaper); + return Result.success(); + } + + /** + * 修改 + */ + @PutMapping("/update") + public Result update(@RequestBody TestPaper testPaper) { + testPaperService.updateById(testPaper); + return Result.success(); + } + + /** + * 单个删除 + */ + @DeleteMapping("/delete/{id}") + public Result delete(@PathVariable Integer id) { + testPaperService.deleteById(id); + return Result.success(); + } + + /** + * 批量删除 + */ + @DeleteMapping("/delete/batch") + public Result delete(@RequestBody List ids) { + testPaperService.deleteBatch(ids); + return Result.success(); + } + + /** + * 单个查询 + */ + @GetMapping("/selectById/{id}") + public Result selectById(@PathVariable Integer id) { + TestPaper testPaper = testPaperService.selectById(id); + return Result.success(testPaper); + } + + @GetMapping("/check/{id}") + public Result check(@PathVariable Integer id) { + testPaperService.checkTestPaper(id); + return Result.success(); + } + + /** + * 查询所有 + */ + @GetMapping("/selectAll") + public Result selectAll(TestPaper testPaper) { + List list = testPaperService.selectAll(testPaper); + return Result.success(list); + } + + /** + * 分页查询 + */ + @GetMapping("/selectPage") + public Result selectPage(TestPaper testPaper, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize) throws ParseException { + PageInfo pageInfo = testPaperService.selectPage(testPaper, pageNum, pageSize); + return Result.success(pageInfo); + } + + @GetMapping("/selectRandom") + public Result selectRandom() throws ParseException { + List list = testPaperService.selectRandom(); + return Result.success(list); + } + +} diff --git a/src/main/java/com/example/controller/WebController.java b/src/main/java/com/example/controller/WebController.java new file mode 100644 index 0000000..e81888d --- /dev/null +++ b/src/main/java/com/example/controller/WebController.java @@ -0,0 +1,79 @@ +package com.example.controller; + +import com.example.common.Result; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.service.AdminService; +import com.example.service.StudentService; +import com.example.service.TeacherService; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +@RestController +public class WebController { + + @Resource + private AdminService adminService; + @Resource + private TeacherService teacherService; + @Resource + private StudentService studentService; + + /** + * 默认请求接口 + */ + @GetMapping("/") + public Result hello () { + return Result.success(); + } + + /** + * 登录 + */ + @PostMapping("/login") + public Result login(@RequestBody Account account) { + Account loginAccount = null; + if (RoleEnum.ADMIN.name().equals(account.getRole())) { + loginAccount = adminService.login(account); + } + if (RoleEnum.TEACHER.name().equals(account.getRole())) { + loginAccount = teacherService.login(account); + } + if (RoleEnum.STUDENT.name().equals(account.getRole())) { + loginAccount = studentService.login(account); + } + return Result.success(loginAccount); + } + + /** + * 注册 + */ + @PostMapping("/register") + public Result register(@RequestBody Account account) { + if (RoleEnum.TEACHER.name().equals(account.getRole())) { + teacherService.register(account); + } + if (RoleEnum.STUDENT.name().equals(account.getRole())) { + studentService.register(account); + } + return Result.success(); + } + + /** + * 修改密码 + */ + @PutMapping("/updatePassword") + public Result updatePassword(@RequestBody Account account) { + if (RoleEnum.ADMIN.name().equals(account.getRole())) { + adminService.updatePassword(account); + } + if (RoleEnum.TEACHER.name().equals(account.getRole())) { + teacherService.updatePassword(account); + } + if (RoleEnum.STUDENT.name().equals(account.getRole())) { + studentService.updatePassword(account); + } + return Result.success(); + } + +} diff --git a/src/main/java/com/example/entity/Account.java b/src/main/java/com/example/entity/Account.java new file mode 100644 index 0000000..78c96e7 --- /dev/null +++ b/src/main/java/com/example/entity/Account.java @@ -0,0 +1,59 @@ +package com.example.entity; + +public class Account { + + private Integer id; + private String username; + private String password; + private String role; + private String newPassword; + private String token; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/src/main/java/com/example/entity/Admin.java b/src/main/java/com/example/entity/Admin.java new file mode 100644 index 0000000..b40aa42 --- /dev/null +++ b/src/main/java/com/example/entity/Admin.java @@ -0,0 +1,79 @@ +package com.example.entity; + +public class Admin extends Account { + + /** 主键ID */ + private Integer id; + /** 账号 */ + private String username; + private String password; + private String name; + private String avatar; + private String role; + private String phone; + private String email; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } +} diff --git a/src/main/java/com/example/entity/Answer.java b/src/main/java/com/example/entity/Answer.java new file mode 100644 index 0000000..3167b67 --- /dev/null +++ b/src/main/java/com/example/entity/Answer.java @@ -0,0 +1,70 @@ +package com.example.entity; + +public class Answer { + + private String typeName; + private Integer questionId; + private Integer score; + private String answer; + private String newAnswer; + private Integer result; + + private String questionName; + + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public Integer getQuestionId() { + return questionId; + } + + public void setQuestionId(Integer questionId) { + this.questionId = questionId; + } + + public Integer getScore() { + return score; + } + + public void setScore(Integer score) { + this.score = score; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + public String getNewAnswer() { + return newAnswer; + } + + public void setNewAnswer(String newAnswer) { + this.newAnswer = newAnswer; + } + + public Integer getResult() { + return result; + } + + public void setResult(Integer result) { + this.result = result; + } + + public String getQuestionName() { + return questionName; + } + + public void setQuestionName(String questionName) { + this.questionName = questionName; + } +} diff --git a/src/main/java/com/example/entity/Article.java b/src/main/java/com/example/entity/Article.java new file mode 100644 index 0000000..8deb591 --- /dev/null +++ b/src/main/java/com/example/entity/Article.java @@ -0,0 +1,77 @@ +package com.example.entity; + +public class Article { + private Integer id; + private String title; + private String img; + private String content; + private String time; + private Integer studentId; + + private String studentName; + private String studentAvatar; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public Integer getStudentId() { + return studentId; + } + + public void setStudentId(Integer studentId) { + this.studentId = studentId; + } + + public String getStudentName() { + return studentName; + } + + public void setStudentName(String studentName) { + this.studentName = studentName; + } + + public String getStudentAvatar() { + return studentAvatar; + } + + public void setStudentAvatar(String studentAvatar) { + this.studentAvatar = studentAvatar; + } +} diff --git a/src/main/java/com/example/entity/Course.java b/src/main/java/com/example/entity/Course.java new file mode 100644 index 0000000..ab81cbe --- /dev/null +++ b/src/main/java/com/example/entity/Course.java @@ -0,0 +1,58 @@ +package com.example.entity; + +public class Course { + private Integer id; + private String name; + private String img; + private Integer score; + private Integer teacherId; + private String teacherName; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public Integer getScore() { + return score; + } + + public void setScore(Integer score) { + this.score = score; + } + + public Integer getTeacherId() { + return teacherId; + } + + public void setTeacherId(Integer teacherId) { + this.teacherId = teacherId; + } + + public String getTeacherName() { + return teacherName; + } + + public void setTeacherName(String teacherName) { + this.teacherName = teacherName; + } +} diff --git a/src/main/java/com/example/entity/ExamPlan.java b/src/main/java/com/example/entity/ExamPlan.java new file mode 100644 index 0000000..47fef7d --- /dev/null +++ b/src/main/java/com/example/entity/ExamPlan.java @@ -0,0 +1,40 @@ +package com.example.entity; + +public class ExamPlan { + private Integer id; + private String title; + private String content; + private String time; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } +} diff --git a/src/main/java/com/example/entity/Notice.java b/src/main/java/com/example/entity/Notice.java new file mode 100644 index 0000000..31cb6f6 --- /dev/null +++ b/src/main/java/com/example/entity/Notice.java @@ -0,0 +1,40 @@ +package com.example.entity; + +public class Notice { + private Integer id; + private String title; + private String content; + private String time; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } +} diff --git a/src/main/java/com/example/entity/Question.java b/src/main/java/com/example/entity/Question.java new file mode 100644 index 0000000..23cf3c8 --- /dev/null +++ b/src/main/java/com/example/entity/Question.java @@ -0,0 +1,153 @@ +package com.example.entity; + +import java.util.ArrayList; +import java.util.List; + +public class Question { + private Integer id; + private String name; + private Integer courseId; + private Integer teacherId; + private Integer typeId; + private String optionA; + private String optionB; + private String optionC; + private String optionD; + private String answer; + + private String courseName; + private String teacherName; + private String typeName; + private Integer typeScore; + + private String newAnswer; + private List checkList = new ArrayList<>(); + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getCourseId() { + return courseId; + } + + public void setCourseId(Integer courseId) { + this.courseId = courseId; + } + + public Integer getTeacherId() { + return teacherId; + } + + public void setTeacherId(Integer teacherId) { + this.teacherId = teacherId; + } + + public Integer getTypeId() { + return typeId; + } + + public void setTypeId(Integer typeId) { + this.typeId = typeId; + } + + public String getOptionA() { + return optionA; + } + + public void setOptionA(String optionA) { + this.optionA = optionA; + } + + public String getOptionB() { + return optionB; + } + + public void setOptionB(String optionB) { + this.optionB = optionB; + } + + public String getOptionC() { + return optionC; + } + + public void setOptionC(String optionC) { + this.optionC = optionC; + } + + public String getOptionD() { + return optionD; + } + + public void setOptionD(String optionD) { + this.optionD = optionD; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + public String getCourseName() { + return courseName; + } + + public void setCourseName(String courseName) { + this.courseName = courseName; + } + + public String getTeacherName() { + return teacherName; + } + + public void setTeacherName(String teacherName) { + this.teacherName = teacherName; + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public Integer getTypeScore() { + return typeScore; + } + + public void setTypeScore(Integer typeScore) { + this.typeScore = typeScore; + } + + public String getNewAnswer() { + return newAnswer; + } + + public void setNewAnswer(String newAnswer) { + this.newAnswer = newAnswer; + } + + public List getCheckList() { + return checkList; + } + + public void setCheckList(List checkList) { + this.checkList = checkList; + } +} diff --git a/src/main/java/com/example/entity/QuestionType.java b/src/main/java/com/example/entity/QuestionType.java new file mode 100644 index 0000000..6ababc6 --- /dev/null +++ b/src/main/java/com/example/entity/QuestionType.java @@ -0,0 +1,31 @@ +package com.example.entity; + +public class QuestionType { + private Integer id; + private String name; + private Integer score; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getScore() { + return score; + } + + public void setScore(Integer score) { + this.score = score; + } +} diff --git a/src/main/java/com/example/entity/Score.java b/src/main/java/com/example/entity/Score.java new file mode 100644 index 0000000..d41455b --- /dev/null +++ b/src/main/java/com/example/entity/Score.java @@ -0,0 +1,135 @@ +package com.example.entity; + +import java.util.List; + +public class Score { + private Integer id; + private String name; + private Integer courseId; + private Integer teacherId; + private Integer studentId; + private Integer paperId; + private Integer score; + private String status; + private String answer; + + private String courseName; + private String teacherName; + private String studentName; + + private List questions; + private List answerData; + + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getCourseId() { + return courseId; + } + + public void setCourseId(Integer courseId) { + this.courseId = courseId; + } + + public Integer getTeacherId() { + return teacherId; + } + + public void setTeacherId(Integer teacherId) { + this.teacherId = teacherId; + } + + public Integer getStudentId() { + return studentId; + } + + public void setStudentId(Integer studentId) { + this.studentId = studentId; + } + + public Integer getPaperId() { + return paperId; + } + + public void setPaperId(Integer paperId) { + this.paperId = paperId; + } + + public Integer getScore() { + return score; + } + + public void setScore(Integer score) { + this.score = score; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + public String getCourseName() { + return courseName; + } + + public void setCourseName(String courseName) { + this.courseName = courseName; + } + + public String getTeacherName() { + return teacherName; + } + + public void setTeacherName(String teacherName) { + this.teacherName = teacherName; + } + + public String getStudentName() { + return studentName; + } + + public void setStudentName(String studentName) { + this.studentName = studentName; + } + + public List getQuestions() { + return questions; + } + + public void setQuestions(List questions) { + this.questions = questions; + } + + public List getAnswerData() { + return answerData; + } + + public void setAnswerData(List answerData) { + this.answerData = answerData; + } +} diff --git a/src/main/java/com/example/entity/Student.java b/src/main/java/com/example/entity/Student.java new file mode 100644 index 0000000..bd0a748 --- /dev/null +++ b/src/main/java/com/example/entity/Student.java @@ -0,0 +1,88 @@ +package com.example.entity; + +public class Student extends Account { + + /** 主键ID */ + private Integer id; + /** 账号 */ + private String username; + private String password; + private String name; + private String avatar; + private String role; + private String phone; + private String email; + private String status; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/src/main/java/com/example/entity/Teacher.java b/src/main/java/com/example/entity/Teacher.java new file mode 100644 index 0000000..fcc44a3 --- /dev/null +++ b/src/main/java/com/example/entity/Teacher.java @@ -0,0 +1,79 @@ +package com.example.entity; + +public class Teacher extends Account { + + /** 主键ID */ + private Integer id; + /** 账号 */ + private String username; + private String password; + private String name; + private String avatar; + private String role; + private String phone; + private String email; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } +} diff --git a/src/main/java/com/example/entity/TestPaper.java b/src/main/java/com/example/entity/TestPaper.java new file mode 100644 index 0000000..11ca4a2 --- /dev/null +++ b/src/main/java/com/example/entity/TestPaper.java @@ -0,0 +1,210 @@ +package com.example.entity; + +import java.util.List; + +public class TestPaper { + // 数据库的基本字段 + private Integer id; + private String name; + private Integer courseId; + private Integer teacherId; + private String type; + private String start; + private String end; + private Integer time; + private String questionIds; // 保存该试卷所有的题目的id的json字符串: "[1,2,3,4,5]" + + // 关联课程信息表和教师信息表查询的额外的字段信息 + private String courseName; + private String courseImg; + private String teacherName; + private String teacherAvatar; + private String status; + + // 用来接收前台那边传过来的业务字段 + private List idList; // 接收前台那边手动选题选中的所有的题目的id + private Integer choiceNum; // 接收前台那边自动组卷填写的单选题的数量 + private Integer multiChoiceNum; // 接收前台那边自动组卷填写的多选题的数量 + private Integer fillInNum; // 接收前台那边自动组卷填写的填空题的数量 + private Integer checkNum; // 接收前台那边自动组卷填写的判断题的数量 + private Integer answerNum; // 接收前台那边自动组卷填写的简答题的数量 + + private List questions; + private Integer maxTime; // 存储时长(秒) + + public List getQuestions() { + return questions; + } + + public void setQuestions(List questions) { + this.questions = questions; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getCourseId() { + return courseId; + } + + public void setCourseId(Integer courseId) { + this.courseId = courseId; + } + + public Integer getTeacherId() { + return teacherId; + } + + public void setTeacherId(Integer teacherId) { + this.teacherId = teacherId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getStart() { + return start; + } + + public void setStart(String start) { + this.start = start; + } + + public String getEnd() { + return end; + } + + public void setEnd(String end) { + this.end = end; + } + + public Integer getTime() { + return time; + } + + public void setTime(Integer time) { + this.time = time; + } + + public String getQuestionIds() { + return questionIds; + } + + public void setQuestionIds(String questionIds) { + this.questionIds = questionIds; + } + + public String getCourseName() { + return courseName; + } + + public void setCourseName(String courseName) { + this.courseName = courseName; + } + + public String getCourseImg() { + return courseImg; + } + + public void setCourseImg(String courseImg) { + this.courseImg = courseImg; + } + + public String getTeacherName() { + return teacherName; + } + + public void setTeacherName(String teacherName) { + this.teacherName = teacherName; + } + + public String getTeacherAvatar() { + return teacherAvatar; + } + + public void setTeacherAvatar(String teacherAvatar) { + this.teacherAvatar = teacherAvatar; + } + + public List getIdList() { + return idList; + } + + public void setIdList(List idList) { + this.idList = idList; + } + + public Integer getChoiceNum() { + return choiceNum; + } + + public void setChoiceNum(Integer choiceNum) { + this.choiceNum = choiceNum; + } + + public Integer getMultiChoiceNum() { + return multiChoiceNum; + } + + public void setMultiChoiceNum(Integer multiChoiceNum) { + this.multiChoiceNum = multiChoiceNum; + } + + public Integer getFillInNum() { + return fillInNum; + } + + public void setFillInNum(Integer fillInNum) { + this.fillInNum = fillInNum; + } + + public Integer getCheckNum() { + return checkNum; + } + + public void setCheckNum(Integer checkNum) { + this.checkNum = checkNum; + } + + public Integer getAnswerNum() { + return answerNum; + } + + public void setAnswerNum(Integer answerNum) { + this.answerNum = answerNum; + } + + public Integer getMaxTime() { + return maxTime; + } + + public void setMaxTime(Integer maxTime) { + this.maxTime = maxTime; + } +} diff --git a/src/main/java/com/example/exception/CustomException.java b/src/main/java/com/example/exception/CustomException.java new file mode 100644 index 0000000..4388f75 --- /dev/null +++ b/src/main/java/com/example/exception/CustomException.java @@ -0,0 +1,35 @@ +package com.example.exception; + +import com.example.common.enums.ResultCodeEnum; + +public class CustomException extends RuntimeException { + + private String code; + private String msg; + + public CustomException(String code, String msg) { + this.code = code; + this.msg = msg; + } + + public CustomException(ResultCodeEnum resultCodeEnum) { + this.code = resultCodeEnum.code; + this.msg = resultCodeEnum.msg; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } +} diff --git a/src/main/java/com/example/exception/GlobalExceptionHandler.java b/src/main/java/com/example/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..eb89d17 --- /dev/null +++ b/src/main/java/com/example/exception/GlobalExceptionHandler.java @@ -0,0 +1,28 @@ +package com.example.exception; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.example.common.Result; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +@ControllerAdvice("com.example.controller") +public class GlobalExceptionHandler { + + private static final Log log = LogFactory.get(); + + @ExceptionHandler(Exception.class) + @ResponseBody // 返回json串 + public Result error(Exception e) { + log.error("异常信息:", e); + return Result.error(); + } + + @ExceptionHandler(CustomException.class) + @ResponseBody // 返回json串 + public Result error(CustomException e) { +// log.error("异常信息:", e); + return Result.error(e.getCode(), e.getMsg()); + } +} diff --git a/src/main/java/com/example/mapper/AdminMapper.java b/src/main/java/com/example/mapper/AdminMapper.java new file mode 100644 index 0000000..1b678ce --- /dev/null +++ b/src/main/java/com/example/mapper/AdminMapper.java @@ -0,0 +1,24 @@ +package com.example.mapper; + +import com.example.entity.Admin; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface AdminMapper { + + int insert(Admin admin); + + void updateById(Admin admin); + + void deleteById(Integer id); + + @Select("select * from `admin` where id = #{id}") + Admin selectById(Integer id); + + @Select("select * from `admin` where username = #{username}") + Admin selectByUsername(String username); + + List selectAll(Admin admin); + +} diff --git a/src/main/java/com/example/mapper/ArticleMapper.java b/src/main/java/com/example/mapper/ArticleMapper.java new file mode 100644 index 0000000..4af508d --- /dev/null +++ b/src/main/java/com/example/mapper/ArticleMapper.java @@ -0,0 +1,23 @@ +package com.example.mapper; + +import com.example.entity.Article; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface ArticleMapper { + + int insert(Article article); + + void updateById(Article article); + + void deleteById(Integer id); + + @Select("select article.*, student.name as studentName from `article` " + + "left join student on article.student_id = student.id " + + "where article.id = #{id}") + Article selectById(Integer id); + + List
selectAll(Article article); + +} diff --git a/src/main/java/com/example/mapper/CourseMapper.java b/src/main/java/com/example/mapper/CourseMapper.java new file mode 100644 index 0000000..6041d1d --- /dev/null +++ b/src/main/java/com/example/mapper/CourseMapper.java @@ -0,0 +1,21 @@ +package com.example.mapper; + +import com.example.entity.Course; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface CourseMapper { + + int insert(Course course); + + void updateById(Course course); + + void deleteById(Integer id); + + @Select("select * from `course` where id = #{id}") + Course selectById(Integer id); + + List selectAll(Course course); + +} diff --git a/src/main/java/com/example/mapper/ExamPlanMapper.java b/src/main/java/com/example/mapper/ExamPlanMapper.java new file mode 100644 index 0000000..9bc8bfb --- /dev/null +++ b/src/main/java/com/example/mapper/ExamPlanMapper.java @@ -0,0 +1,21 @@ +package com.example.mapper; + +import com.example.entity.ExamPlan; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface ExamPlanMapper { + + int insert(ExamPlan examPlan); + + void updateById(ExamPlan examPlan); + + void deleteById(Integer id); + + @Select("select * from `examPlan` where id = #{id}") + ExamPlan selectById(Integer id); + + List selectAll(ExamPlan examPlan); + +} diff --git a/src/main/java/com/example/mapper/NoticeMapper.java b/src/main/java/com/example/mapper/NoticeMapper.java new file mode 100644 index 0000000..3e19f0d --- /dev/null +++ b/src/main/java/com/example/mapper/NoticeMapper.java @@ -0,0 +1,21 @@ +package com.example.mapper; + +import com.example.entity.Notice; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface NoticeMapper { + + int insert(Notice notice); + + void updateById(Notice notice); + + void deleteById(Integer id); + + @Select("select * from `notice` where id = #{id}") + Notice selectById(Integer id); + + List selectAll(Notice notice); + +} diff --git a/src/main/java/com/example/mapper/QuestionMapper.java b/src/main/java/com/example/mapper/QuestionMapper.java new file mode 100644 index 0000000..28cee45 --- /dev/null +++ b/src/main/java/com/example/mapper/QuestionMapper.java @@ -0,0 +1,26 @@ +package com.example.mapper; + +import com.example.entity.Question; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface QuestionMapper { + + int insert(Question question); + + void updateById(Question question); + + void deleteById(Integer id); + + @Select("select question.*, question_type.score as typeScore, question_type.name as typeName from `question` " + + "left join question_type on question.type_id = question_type.id " + + "where question.id = #{id}") + Question selectById(Integer id); + + List selectAll(Question question); + + @Select("select * from question where course_id = #{courseId} and type_id = #{typeId}") + List selectByCouserIdAndTypeId(@Param("courseId") Integer courseId, @Param("typeId") Integer typeId); +} diff --git a/src/main/java/com/example/mapper/QuestionTypeMapper.java b/src/main/java/com/example/mapper/QuestionTypeMapper.java new file mode 100644 index 0000000..0d7e6c5 --- /dev/null +++ b/src/main/java/com/example/mapper/QuestionTypeMapper.java @@ -0,0 +1,23 @@ +package com.example.mapper; + +import com.example.entity.QuestionType; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface QuestionTypeMapper { + + int insert(QuestionType questionType); + + void updateById(QuestionType questionType); + + void deleteById(Integer id); + + @Select("select * from `question_type` where id = #{id}") + QuestionType selectById(Integer id); + + List selectAll(QuestionType questionType); + + @Select("select * from question_type where name = #{name}") + List selectByName(String name); +} diff --git a/src/main/java/com/example/mapper/ScoreMapper.java b/src/main/java/com/example/mapper/ScoreMapper.java new file mode 100644 index 0000000..e618941 --- /dev/null +++ b/src/main/java/com/example/mapper/ScoreMapper.java @@ -0,0 +1,21 @@ +package com.example.mapper; + +import com.example.entity.Score; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface ScoreMapper { + + int insert(Score score); + + void updateById(Score score); + + void deleteById(Integer id); + + @Select("select * from `score` where id = #{id}") + Score selectById(Integer id); + + List selectAll(Score score); + +} diff --git a/src/main/java/com/example/mapper/StudentMapper.java b/src/main/java/com/example/mapper/StudentMapper.java new file mode 100644 index 0000000..57f2b12 --- /dev/null +++ b/src/main/java/com/example/mapper/StudentMapper.java @@ -0,0 +1,24 @@ +package com.example.mapper; + +import com.example.entity.Student; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface StudentMapper { + + int insert(Student student); + + void updateById(Student student); + + void deleteById(Integer id); + + @Select("select * from `student` where id = #{id}") + Student selectById(Integer id); + + @Select("select * from `student` where username = #{username}") + Student selectByUsername(String username); + + List selectAll(Student student); + +} diff --git a/src/main/java/com/example/mapper/TeacherMapper.java b/src/main/java/com/example/mapper/TeacherMapper.java new file mode 100644 index 0000000..c2abf69 --- /dev/null +++ b/src/main/java/com/example/mapper/TeacherMapper.java @@ -0,0 +1,24 @@ +package com.example.mapper; + +import com.example.entity.Teacher; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface TeacherMapper { + + int insert(Teacher teacher); + + void updateById(Teacher teacher); + + void deleteById(Integer id); + + @Select("select * from `teacher` where id = #{id}") + Teacher selectById(Integer id); + + @Select("select * from `teacher` where username = #{username}") + Teacher selectByUsername(String username); + + List selectAll(Teacher teacher); + +} diff --git a/src/main/java/com/example/mapper/TestPaperMapper.java b/src/main/java/com/example/mapper/TestPaperMapper.java new file mode 100644 index 0000000..07414e9 --- /dev/null +++ b/src/main/java/com/example/mapper/TestPaperMapper.java @@ -0,0 +1,21 @@ +package com.example.mapper; + +import com.example.entity.TestPaper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +public interface TestPaperMapper { + + int insert(TestPaper testPaper); + + void updateById(TestPaper testPaper); + + void deleteById(Integer id); + + @Select("select * from `test_paper` where id = #{id}") + TestPaper selectById(Integer id); + + List selectAll(TestPaper testPaper); + +} diff --git a/src/main/java/com/example/service/AdminService.java b/src/main/java/com/example/service/AdminService.java new file mode 100644 index 0000000..0b25130 --- /dev/null +++ b/src/main/java/com/example/service/AdminService.java @@ -0,0 +1,103 @@ +package com.example.service; + +import cn.hutool.core.util.ObjectUtil; +import com.example.common.Constants; +import com.example.common.enums.ResultCodeEnum; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.entity.Admin; +import com.example.exception.CustomException; +import com.example.mapper.AdminMapper; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 业务层方法 + */ +@Service +public class AdminService { + + @Resource + private AdminMapper adminMapper; + + public void add(Admin admin) { + Admin dbAdmin = adminMapper.selectByUsername(admin.getUsername()); + if (ObjectUtil.isNotNull(dbAdmin)) { + throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR); + } + if (ObjectUtil.isEmpty(admin.getPassword())) { + admin.setPassword(Constants.USER_DEFAULT_PASSWORD); + } + if (ObjectUtil.isEmpty(admin.getName())) { + admin.setName(admin.getUsername()); + } + admin.setRole(RoleEnum.ADMIN.name()); + adminMapper.insert(admin); + } + + public void updateById(Admin admin) { + adminMapper.updateById(admin); + } + + public void deleteById(Integer id) { + adminMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + adminMapper.deleteById(id); + } + } + + public Admin selectById(Integer id) { + return adminMapper.selectById(id); + } + + public List selectAll(Admin admin) { + return adminMapper.selectAll(admin); + } + + public PageInfo selectPage(Admin admin, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List list = adminMapper.selectAll(admin); + return PageInfo.of(list); + } + + /** + * 登录 + */ + public Admin login(Account account) { + Admin dbAdmin = adminMapper.selectByUsername(account.getUsername()); + if (ObjectUtil.isNull(dbAdmin)) { + throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR); + } + if (!dbAdmin.getPassword().equals(account.getPassword())) { + throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR); + } + // 生成token + String token = TokenUtils.createToken(dbAdmin.getId() + "-" + dbAdmin.getRole(), dbAdmin.getPassword()); + dbAdmin.setToken(token); + return dbAdmin; + } + + /** + * 修改密码 + */ + public void updatePassword(Account account) { + Admin dbAdmin = adminMapper.selectByUsername(account.getUsername()); + if (ObjectUtil.isNull(dbAdmin)) { + throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR); + } + if (!account.getPassword().equals(dbAdmin.getPassword())) { + throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR); + } + dbAdmin.setPassword(account.getNewPassword()); + adminMapper.updateById(dbAdmin); + } + +} diff --git a/src/main/java/com/example/service/ArticleService.java b/src/main/java/com/example/service/ArticleService.java new file mode 100644 index 0000000..bdc2330 --- /dev/null +++ b/src/main/java/com/example/service/ArticleService.java @@ -0,0 +1,68 @@ +package com.example.service; + +import cn.hutool.core.date.DateUtil; +import com.example.entity.Account; +import com.example.entity.Article; +import com.example.mapper.ArticleMapper; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; + +/** + * 帖子信息业务层方法 + */ +@Service +public class ArticleService { + + @Resource + private ArticleMapper articleMapper; + + public void add(Article article) { + Account currentUser = TokenUtils.getCurrentUser(); + article.setStudentId(currentUser.getId()); + article.setTime(DateUtil.now()); + articleMapper.insert(article); + } + + public void updateById(Article article) { + articleMapper.updateById(article); + } + + public void deleteById(Integer id) { + articleMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + articleMapper.deleteById(id); + } + } + + public Article selectById(Integer id) { + return articleMapper.selectById(id); + } + + public List
selectAll(Article article) { + return articleMapper.selectAll(article); + } + + public PageInfo
selectPage(Article article, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List
list = articleMapper.selectAll(article); + return PageInfo.of(list); + } + + public List
selectRandom() { + List
list = articleMapper.selectAll(new Article()); + Collections.shuffle(list); + if (list.size() > 3) { + return list.subList(0, 3); + } + return list; + } +} diff --git a/src/main/java/com/example/service/CourseService.java b/src/main/java/com/example/service/CourseService.java new file mode 100644 index 0000000..f536df1 --- /dev/null +++ b/src/main/java/com/example/service/CourseService.java @@ -0,0 +1,63 @@ +package com.example.service; + +import cn.hutool.core.date.DateUtil; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.entity.Course; +import com.example.mapper.CourseMapper; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 课程信息业务层方法 + */ +@Service +public class CourseService { + + @Resource + private CourseMapper courseMapper; + + public void add(Course course) { + Account currentUser = TokenUtils.getCurrentUser(); + course.setTeacherId(currentUser.getId()); + courseMapper.insert(course); + } + + public void updateById(Course course) { + courseMapper.updateById(course); + } + + public void deleteById(Integer id) { + courseMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + courseMapper.deleteById(id); + } + } + + public Course selectById(Integer id) { + return courseMapper.selectById(id); + } + + public List selectAll(Course course) { + return courseMapper.selectAll(course); + } + + public PageInfo selectPage(Course course, Integer pageNum, Integer pageSize) { + Account currentUser = TokenUtils.getCurrentUser(); + if (RoleEnum.TEACHER.name().equals(currentUser.getRole())) { + course.setTeacherId(currentUser.getId()); + } + PageHelper.startPage(pageNum, pageSize); + List list = courseMapper.selectAll(course); + return PageInfo.of(list); + } + +} diff --git a/src/main/java/com/example/service/ExamPlanService.java b/src/main/java/com/example/service/ExamPlanService.java new file mode 100644 index 0000000..e675f0c --- /dev/null +++ b/src/main/java/com/example/service/ExamPlanService.java @@ -0,0 +1,55 @@ +package com.example.service; + +import cn.hutool.core.date.DateUtil; +import com.example.entity.ExamPlan; +import com.example.mapper.ExamPlanMapper; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 考试安排业务层方法 + */ +@Service +public class ExamPlanService { + + @Resource + private ExamPlanMapper examPlanMapper; + + public void add(ExamPlan examPlan) { + examPlan.setTime(DateUtil.now()); + examPlanMapper.insert(examPlan); + } + + public void updateById(ExamPlan examPlan) { + examPlanMapper.updateById(examPlan); + } + + public void deleteById(Integer id) { + examPlanMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + examPlanMapper.deleteById(id); + } + } + + public ExamPlan selectById(Integer id) { + return examPlanMapper.selectById(id); + } + + public List selectAll(ExamPlan examPlan) { + return examPlanMapper.selectAll(examPlan); + } + + public PageInfo selectPage(ExamPlan examPlan, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List list = examPlanMapper.selectAll(examPlan); + return PageInfo.of(list); + } + +} diff --git a/src/main/java/com/example/service/NoticeService.java b/src/main/java/com/example/service/NoticeService.java new file mode 100644 index 0000000..9fc72d9 --- /dev/null +++ b/src/main/java/com/example/service/NoticeService.java @@ -0,0 +1,55 @@ +package com.example.service; + +import cn.hutool.core.date.DateUtil; +import com.example.entity.Notice; +import com.example.mapper.NoticeMapper; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 业务层方法 + */ +@Service +public class NoticeService { + + @Resource + private NoticeMapper noticeMapper; + + public void add(Notice notice) { + notice.setTime(DateUtil.now()); + noticeMapper.insert(notice); + } + + public void updateById(Notice notice) { + noticeMapper.updateById(notice); + } + + public void deleteById(Integer id) { + noticeMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + noticeMapper.deleteById(id); + } + } + + public Notice selectById(Integer id) { + return noticeMapper.selectById(id); + } + + public List selectAll(Notice notice) { + return noticeMapper.selectAll(notice); + } + + public PageInfo selectPage(Notice notice, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List list = noticeMapper.selectAll(notice); + return PageInfo.of(list); + } + +} diff --git a/src/main/java/com/example/service/QuestionService.java b/src/main/java/com/example/service/QuestionService.java new file mode 100644 index 0000000..9a08166 --- /dev/null +++ b/src/main/java/com/example/service/QuestionService.java @@ -0,0 +1,63 @@ +package com.example.service; + +import cn.hutool.core.date.DateUtil; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.entity.Question; +import com.example.mapper.QuestionMapper; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 题目信息业务层方法 + */ +@Service +public class QuestionService { + + @Resource + private QuestionMapper questionMapper; + + public void add(Question question) { + Account currentUser = TokenUtils.getCurrentUser(); + question.setTeacherId(currentUser.getId()); + questionMapper.insert(question); + } + + public void updateById(Question question) { + questionMapper.updateById(question); + } + + public void deleteById(Integer id) { + questionMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + questionMapper.deleteById(id); + } + } + + public Question selectById(Integer id) { + return questionMapper.selectById(id); + } + + public List selectAll(Question question) { + return questionMapper.selectAll(question); + } + + public PageInfo selectPage(Question question, Integer pageNum, Integer pageSize) { + Account currentUser = TokenUtils.getCurrentUser(); + if (RoleEnum.TEACHER.name().equals(currentUser.getRole())) { + question.setTeacherId(currentUser.getId()); + } + PageHelper.startPage(pageNum, pageSize); + List list = questionMapper.selectAll(question); + return PageInfo.of(list); + } + +} diff --git a/src/main/java/com/example/service/QuestionTypeService.java b/src/main/java/com/example/service/QuestionTypeService.java new file mode 100644 index 0000000..9a14619 --- /dev/null +++ b/src/main/java/com/example/service/QuestionTypeService.java @@ -0,0 +1,66 @@ +package com.example.service; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import com.example.entity.QuestionType; +import com.example.exception.CustomException; +import com.example.mapper.QuestionTypeMapper; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 题型信息业务层方法 + */ +@Service +public class QuestionTypeService { + + @Resource + private QuestionTypeMapper questionTypeMapper; + + public void add(QuestionType questionType) { + // 同一题型不能被重复添加 + List list = questionTypeMapper.selectByName(questionType.getName()); + if (CollectionUtil.isNotEmpty(list)) { + throw new CustomException("-1", "题型名称不能重复"); + } + questionTypeMapper.insert(questionType); + } + + public void updateById(QuestionType questionType) { + // 同一题型不能被重复添加 + List list = questionTypeMapper.selectByName(questionType.getName()); + if (CollectionUtil.isNotEmpty(list) && !questionType.getId().equals(list.get(0).getId())) { + throw new CustomException("-1", "题型名称不能重复"); + } + questionTypeMapper.updateById(questionType); + } + + public void deleteById(Integer id) { + questionTypeMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + questionTypeMapper.deleteById(id); + } + } + + public QuestionType selectById(Integer id) { + return questionTypeMapper.selectById(id); + } + + public List selectAll(QuestionType questionType) { + return questionTypeMapper.selectAll(questionType); + } + + public PageInfo selectPage(QuestionType questionType, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List list = questionTypeMapper.selectAll(questionType); + return PageInfo.of(list); + } + +} diff --git a/src/main/java/com/example/service/ScoreService.java b/src/main/java/com/example/service/ScoreService.java new file mode 100644 index 0000000..259c201 --- /dev/null +++ b/src/main/java/com/example/service/ScoreService.java @@ -0,0 +1,165 @@ +package com.example.service; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONUtil; +import com.example.common.enums.RoleEnum; +import com.example.entity.*; +import com.example.mapper.QuestionMapper; +import com.example.mapper.ScoreMapper; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** + * 成绩信息业务层方法 + */ +@Service +public class ScoreService { + + @Resource + private ScoreMapper scoreMapper; + @Resource + private QuestionMapper questionMapper; + + public void add(TestPaper testPaper) { + + // 封装一下用户提交的试卷信息 + List list = new ArrayList<>(); + for (Question question : testPaper.getQuestions()) { + Answer answer = new Answer(); + answer.setTypeName(question.getTypeName()); + answer.setScore(question.getTypeScore()); + answer.setQuestionId(question.getId()); + if ("多选题".equals(question.getTypeName())) { + List checkList = question.getCheckList(); + answer.setNewAnswer(String.join(",", checkList)); + } else { + answer.setNewAnswer(question.getNewAnswer()); + } + answer.setAnswer(question.getAnswer()); + list.add(answer); + } + + Score score = new Score(); + Account currentUser = TokenUtils.getCurrentUser(); + score.setStudentId(currentUser.getId()); + score.setTeacherId(testPaper.getTeacherId()); + score.setCourseId(testPaper.getCourseId()); + score.setName(testPaper.getName()); + score.setPaperId(testPaper.getId()); + score.setStatus("待阅卷"); + score.setAnswer(JSONUtil.toJsonStr(list)); + scoreMapper.insert(score); + } + + public void updateById(Score score) { + List answerData = score.getAnswerData(); + int total = 0; + for (Answer answer : answerData) { + if (ObjectUtil.isNotEmpty(answer.getResult())) { + total += answer.getResult(); + } + } + score.setScore(total); + score.setAnswer(JSONUtil.toJsonStr(answerData)); + score.setStatus("已阅卷"); + scoreMapper.updateById(score); + } + + public void deleteById(Integer id) { + scoreMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + scoreMapper.deleteById(id); + } + } + + public Score selectById(Integer id) { + List scores = scoreMapper.selectAll(new Score()); + Score score = scores.stream().filter(x -> x.getId().equals(id)).findFirst().get(); + String answer = score.getAnswer(); + List list = JSONUtil.toList(answer, Answer.class); + + List questions = new ArrayList<>(); + for (Answer ans : list) { + Question question = questionMapper.selectById(ans.getQuestionId()); + if (ObjectUtil.isNotEmpty(question)) { + if ("多选题".equals(ans.getTypeName())) { + String newAnswer = ans.getNewAnswer(); // A,B,C + List checkList = Arrays.asList(newAnswer.split(",")); + question.setCheckList(checkList); + } else { + question.setNewAnswer(ans.getNewAnswer()); + } + questions.add(question); + } + } + score.setQuestions(questions); + return score; + } + + public List selectAll(Score score) { + return scoreMapper.selectAll(score); + } + + public PageInfo selectPage(Score score, Integer pageNum, Integer pageSize) { + Account currentUser = TokenUtils.getCurrentUser(); + if (RoleEnum.STUDENT.name().equals(currentUser.getRole())) { + score.setStudentId(currentUser.getId()); + } + if (RoleEnum.TEACHER.name().equals(currentUser.getRole())) { + score.setTeacherId(currentUser.getId()); + } + PageHelper.startPage(pageNum, pageSize); + List list = scoreMapper.selectAll(score); + return PageInfo.of(list); + } + + public List selectAnswer(Integer id) { + Score score = scoreMapper.selectById(id); + List list = JSONUtil.toList(score.getAnswer(), Answer.class); + // 客观题自动阅卷功能 + for (Answer answer : list) { + Question question = questionMapper.selectById(answer.getQuestionId()); + answer.setQuestionName(question.getName()); + // 客观题自动打分 + if (!"简答题".equals(answer.getTypeName())) { + if (!"多选题".equals(answer.getTypeName())) { + if (answer.getAnswer().equals(answer.getNewAnswer())) { + answer.setResult(answer.getScore()); + } else { + answer.setResult(0); + } + } else { + // 多选题 只要选项都对就行 顺序没有关系: A,B,C 和 B,A,C 是一样的 + List standardList = Arrays.asList(answer.getAnswer().split(",")); // [A, B, C] + List studentList = Arrays.asList(answer.getNewAnswer().split(",")); // [B, A, C] + for (String s : standardList) { + if (!studentList.contains(s)) { + answer.setResult(0); + break; + } + } + if (ObjectUtil.isEmpty(answer.getResult())) { + if (studentList.size() == standardList.size()) { + answer.setResult(answer.getScore()); + } else { + answer.setResult(0); + } + } + } + } + } + return list; + } +} diff --git a/src/main/java/com/example/service/StudentService.java b/src/main/java/com/example/service/StudentService.java new file mode 100644 index 0000000..dd2f825 --- /dev/null +++ b/src/main/java/com/example/service/StudentService.java @@ -0,0 +1,113 @@ +package com.example.service; + +import cn.hutool.core.util.ObjectUtil; +import com.example.common.Constants; +import com.example.common.enums.ResultCodeEnum; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.entity.Student; +import com.example.exception.CustomException; +import com.example.mapper.StudentMapper; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 学生信息业务层方法 + */ +@Service +public class StudentService { + + @Resource + private StudentMapper studentMapper; + + public void add(Student student) { + Student dbStudent = studentMapper.selectByUsername(student.getUsername()); + if (ObjectUtil.isNotNull(dbStudent)) { + throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR); + } + if (ObjectUtil.isEmpty(student.getPassword())) { + student.setPassword(Constants.USER_DEFAULT_PASSWORD); + } + if (ObjectUtil.isEmpty(student.getName())) { + student.setName(student.getUsername()); + } + student.setRole(RoleEnum.STUDENT.name()); + student.setStatus("待审核"); + studentMapper.insert(student); + } + + public void updateById(Student student) { + studentMapper.updateById(student); + } + + public void deleteById(Integer id) { + studentMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + studentMapper.deleteById(id); + } + } + + public Student selectById(Integer id) { + return studentMapper.selectById(id); + } + + public List selectAll(Student student) { + return studentMapper.selectAll(student); + } + + public PageInfo selectPage(Student student, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List list = studentMapper.selectAll(student); + return PageInfo.of(list); + } + + /** + * 登录 + */ + public Student login(Account account) { + Student dbStudent = studentMapper.selectByUsername(account.getUsername()); + if (ObjectUtil.isNull(dbStudent)) { + throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR); + } + if (!dbStudent.getPassword().equals(account.getPassword())) { + throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR); + } + if (!"审核通过".equals(dbStudent.getStatus())) { + throw new CustomException("-1", "您的注册信息尚未审核通过,暂不允许登录,请耐心等待管理员审核"); + } + // 生成token + String token = TokenUtils.createToken(dbStudent.getId() + "-" + dbStudent.getRole(), dbStudent.getPassword()); + dbStudent.setToken(token); + return dbStudent; + } + + /** + * 修改密码 + */ + public void updatePassword(Account account) { + Student dbStudent = studentMapper.selectByUsername(account.getUsername()); + if (ObjectUtil.isNull(dbStudent)) { + throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR); + } + if (!account.getPassword().equals(dbStudent.getPassword())) { + throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR); + } + dbStudent.setPassword(account.getNewPassword()); + studentMapper.updateById(dbStudent); + } + + public void register(Account account) { + Student student = new Student(); + BeanUtils.copyProperties(account, student); + add(student); + } +} diff --git a/src/main/java/com/example/service/TeacherService.java b/src/main/java/com/example/service/TeacherService.java new file mode 100644 index 0000000..b7f4f14 --- /dev/null +++ b/src/main/java/com/example/service/TeacherService.java @@ -0,0 +1,109 @@ +package com.example.service; + +import cn.hutool.core.util.ObjectUtil; +import com.example.common.Constants; +import com.example.common.enums.ResultCodeEnum; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.entity.Teacher; +import com.example.exception.CustomException; +import com.example.mapper.TeacherMapper; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 教师信息业务层方法 + */ +@Service +public class TeacherService { + + @Resource + private TeacherMapper teacherMapper; + + public void add(Teacher teacher) { + Teacher dbTeacher = teacherMapper.selectByUsername(teacher.getUsername()); + if (ObjectUtil.isNotNull(dbTeacher)) { + throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR); + } + if (ObjectUtil.isEmpty(teacher.getPassword())) { + teacher.setPassword(Constants.USER_DEFAULT_PASSWORD); + } + if (ObjectUtil.isEmpty(teacher.getName())) { + teacher.setName(teacher.getUsername()); + } + teacher.setRole(RoleEnum.TEACHER.name()); + teacherMapper.insert(teacher); + } + + public void updateById(Teacher teacher) { + teacherMapper.updateById(teacher); + } + + public void deleteById(Integer id) { + teacherMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + teacherMapper.deleteById(id); + } + } + + public Teacher selectById(Integer id) { + return teacherMapper.selectById(id); + } + + public List selectAll(Teacher teacher) { + return teacherMapper.selectAll(teacher); + } + + public PageInfo selectPage(Teacher teacher, Integer pageNum, Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List list = teacherMapper.selectAll(teacher); + return PageInfo.of(list); + } + + /** + * 登录 + */ + public Teacher login(Account account) { + Teacher dbTeacher = teacherMapper.selectByUsername(account.getUsername()); + if (ObjectUtil.isNull(dbTeacher)) { + throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR); + } + if (!dbTeacher.getPassword().equals(account.getPassword())) { + throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR); + } + // 生成token + String token = TokenUtils.createToken(dbTeacher.getId() + "-" + dbTeacher.getRole(), dbTeacher.getPassword()); + dbTeacher.setToken(token); + return dbTeacher; + } + + /** + * 修改密码 + */ + public void updatePassword(Account account) { + Teacher dbTeacher = teacherMapper.selectByUsername(account.getUsername()); + if (ObjectUtil.isNull(dbTeacher)) { + throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR); + } + if (!account.getPassword().equals(dbTeacher.getPassword())) { + throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR); + } + dbTeacher.setPassword(account.getNewPassword()); + teacherMapper.updateById(dbTeacher); + } + + public void register(Account account) { + Teacher teacher = new Teacher(); + BeanUtils.copyProperties(account, teacher); + add(teacher); + } +} diff --git a/src/main/java/com/example/service/TestPaperService.java b/src/main/java/com/example/service/TestPaperService.java new file mode 100644 index 0000000..4702829 --- /dev/null +++ b/src/main/java/com/example/service/TestPaperService.java @@ -0,0 +1,209 @@ +package com.example.service; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONUtil; +import com.example.common.enums.RoleEnum; +import com.example.entity.*; +import com.example.exception.CustomException; +import com.example.mapper.*; +import com.example.utils.TokenUtils; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 试卷信息业务层方法 + */ +@Service +public class TestPaperService { + + @Resource + private TestPaperMapper testPaperMapper; + @Resource + private QuestionMapper questionMapper; + @Resource + private CourseMapper courseMapper; + @Resource + private TeacherMapper teacherMapper; + @Resource + private ScoreMapper scoreMapper; + + public void add(TestPaper testPaper) throws ParseException { + // 先要校验前台传过来的数据 + check(testPaper); + Account currentUser = TokenUtils.getCurrentUser(); + testPaper.setTeacherId(currentUser.getId()); + // 手动选题 + if ("手动选题".equals(testPaper.getType())) { + List idList = testPaper.getIdList(); + testPaper.setQuestionIds(JSONUtil.toJsonStr(idList)); + } + if ("自动组卷".equals(testPaper.getType())) { + List list = new ArrayList<>(); + // 自动选取每个题型的题目 + randomQuestionIds(testPaper, testPaper.getChoiceNum(), list, 1, "单选题"); + randomQuestionIds(testPaper, testPaper.getMultiChoiceNum(), list, 2, "多选题"); + randomQuestionIds(testPaper, testPaper.getCheckNum(), list, 3, "判断题"); + randomQuestionIds(testPaper, testPaper.getFillInNum(), list, 4, "填空题"); + randomQuestionIds(testPaper, testPaper.getAnswerNum(), list, 5, "简答题"); + + testPaper.setQuestionIds(JSONUtil.toJsonStr(list)); + } + + testPaperMapper.insert(testPaper); + } + + private void randomQuestionIds(TestPaper testPaper, Integer choiceNum, List list, Integer typeId, String typeName) { + List choiceList = questionMapper.selectByCouserIdAndTypeId(testPaper.getCourseId(), typeId); + if (choiceList.size() < choiceNum) { + throw new CustomException("-1", "您的题库里该课程的" + typeName + "数量不足,请减少出题的" + typeName + "数量或者增加题库里该课程的" + typeName + "数量"); + } + Collections.shuffle(choiceList); // 打乱 + List questions = choiceList.subList(0, choiceNum).stream().map(Question::getId).toList(); + list.addAll(questions); + } + + public void check (TestPaper testPaper) throws ParseException { + if (ObjectUtil.isEmpty(testPaper.getName()) + || ObjectUtil.isEmpty(testPaper.getCourseId()) + || ObjectUtil.isEmpty(testPaper.getStart()) + || ObjectUtil.isEmpty(testPaper.getEnd()) + || ObjectUtil.isEmpty(testPaper.getTime()) + || ObjectUtil.isEmpty(testPaper.getType()) + ) { + throw new CustomException("-1", "请填写完整您要提交的试卷信息"); + } + // 开始时间要早于结束时间 + long start = new SimpleDateFormat("yyyy-MM-dd").parse(testPaper.getStart()).getTime(); + long end = new SimpleDateFormat("yyyy-MM-dd").parse(testPaper.getEnd()).getTime(); + if (start >= end) { + throw new CustomException("-1", "开始时间必须早于结束时间"); + } + // 校验手动选题 + if ("手动选题".equals(testPaper.getType())) { + if (CollectionUtil.isEmpty(testPaper.getIdList())) { + throw new CustomException("-1", "手动选题方式,您需要选择具体的题目"); + } + } + // 自动组卷校验 + if ("自动组卷".equals(testPaper.getType())) { + if (ObjectUtil.isEmpty(testPaper.getChoiceNum()) + || ObjectUtil.isEmpty(testPaper.getMultiChoiceNum()) + || ObjectUtil.isEmpty(testPaper.getFillInNum()) + || ObjectUtil.isEmpty(testPaper.getCheckNum()) + || ObjectUtil.isEmpty(testPaper.getAnswerNum()) + ) { + throw new CustomException("-1", "请填写题型的数量,如果不需要某个题型,请输入0"); + } + if (testPaper.getChoiceNum() < 0 + || testPaper.getMultiChoiceNum() < 0 + || testPaper.getFillInNum() < 0 + || testPaper.getCheckNum() < 0 + || testPaper.getAnswerNum() < 0 + ) { + throw new CustomException("-1", "题型的数量不能小于0"); + } + } + } + + public void updateById(TestPaper testPaper) { + testPaperMapper.updateById(testPaper); + } + + public void deleteById(Integer id) { + testPaperMapper.deleteById(id); + } + + public void deleteBatch(List ids) { + for (Integer id : ids) { + testPaperMapper.deleteById(id); + } + } + + public TestPaper selectById(Integer id) { + TestPaper testPaper = testPaperMapper.selectById(id); + Course course = courseMapper.selectById(testPaper.getCourseId()); + if (ObjectUtil.isNotEmpty(course)) { + testPaper.setCourseName(course.getName()); + } + Teacher teacher = teacherMapper.selectById(testPaper.getTeacherId()); + if (ObjectUtil.isNotEmpty(teacher)) { + testPaper.setTeacherName(teacher.getName()); + } + // 开始组装该试卷里所有的题目数据 + String questionIds = testPaper.getQuestionIds(); + List idList = JSONUtil.toList(questionIds, Integer.class); + List questions = new ArrayList<>(); + for (Integer questionId : idList) { + Question question = questionMapper.selectById(questionId); + questions.add(question); + } + testPaper.setQuestions(questions); + testPaper.setMaxTime(testPaper.getTime() * 60); + return testPaper; + } + + public List selectAll(TestPaper testPaper) { + return testPaperMapper.selectAll(testPaper); + } + + public PageInfo selectPage(TestPaper testPaper, Integer pageNum, Integer pageSize) throws ParseException { + Account currentUser = TokenUtils.getCurrentUser(); + if (RoleEnum.TEACHER.name().equals(currentUser.getRole())) { + testPaper.setTeacherId(currentUser.getId()); + } + PageHelper.startPage(pageNum, pageSize); + List list = testPaperMapper.selectAll(testPaper); + // 初始化每个考试的状态 + initStatus(list); + return PageInfo.of(list); + } + + private static void initStatus(List list) throws ParseException { + for (TestPaper paper : list) { + long now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(DateUtil.now()).getTime(); + long start = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(paper.getStart() + " 00:00:00").getTime(); + long end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(paper.getEnd() + " 23:59:59").getTime(); + if (now < start) { + paper.setStatus("未开始"); + } else if (now > end) { + paper.setStatus("已结束"); + } else { + paper.setStatus("进行中"); + } + } + } + + public void checkTestPaper(Integer id) { + Account currentUser = TokenUtils.getCurrentUser(); + Score score = new Score(); + score.setPaperId(id); + score.setStudentId(currentUser.getId()); + List scores = scoreMapper.selectAll(score); + if (CollectionUtil.isNotEmpty(scores)) { + throw new CustomException("-1", "该门考试您已经提交过试卷了,入口已关闭"); + } + } + + public List selectRandom() throws ParseException { + List list = testPaperMapper.selectAll(new TestPaper()); + Collections.shuffle(list); + // 初始化每个考试的状态 + initStatus(list); + if (list.size() > 4) { + return list.subList(0, 4); + } + return list; + } +} diff --git a/src/main/java/com/example/utils/TokenUtils.java b/src/main/java/com/example/utils/TokenUtils.java new file mode 100644 index 0000000..1200379 --- /dev/null +++ b/src/main/java/com/example/utils/TokenUtils.java @@ -0,0 +1,84 @@ +package com.example.utils; + +import cn.hutool.core.date.DateUtil; +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.example.common.Constants; +import com.example.common.enums.RoleEnum; +import com.example.entity.Account; +import com.example.service.AdminService; +import com.example.service.StudentService; +import com.example.service.TeacherService; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.Date; + +/** + * Token工具类 + */ +@Component +public class TokenUtils { + private static final Logger log = LoggerFactory.getLogger(TokenUtils.class); + + @Resource + private AdminService adminService; + @Resource + private TeacherService teacherService; + @Resource + private StudentService studentService; + + private static AdminService staticAdminService; + private static TeacherService staticTeacherService; + private static StudentService staticStudentService; + + @PostConstruct + public void init() { + staticAdminService = adminService; + staticTeacherService = teacherService; + staticStudentService = studentService; + } + + /** + * 生成JWT token + */ + public static String createToken(String data, String sign) { + // audience是存储数据的一个媒介 存储用户ID和用户的角色 1-ADMIN + return JWT.create().withAudience(data) + .withExpiresAt(DateUtil.offsetDay(new Date(), 1)) // 设置过期时间1天后 + .sign(Algorithm.HMAC256(sign)); + } + + /** + * 获取当前登录的用户 + */ + public static Account getCurrentUser() { + try { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String token = request.getHeader(Constants.TOKEN); + String audience = JWT.decode(token).getAudience().get(0); + String[] userRole = audience.split("-"); + Integer userId = Integer.valueOf(userRole[0]); + String role = userRole[1]; + if (RoleEnum.ADMIN.name().equals(role)) { + return staticAdminService.selectById(userId); + } + if (RoleEnum.TEACHER.name().equals(role)) { + return staticTeacherService.selectById(userId); + } + if (RoleEnum.STUDENT.name().equals(role)) { + return staticStudentService.selectById(userId); + } + } catch (Exception e) { + log.error("获取当前登录用户出错", e); + } + return null; + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..c225a2f --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,19 @@ +server: + port: 9090 + +# 数据库配置 +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: 123456 + url: jdbc:mysql://localhost:33060/java-experiment?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=true + +# 配置mybatis实体和xml映射 +mybatis: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: true + mapper-locations: classpath:mapper/*.xml + +fileBaseUrl: http://localhost:${server.port} \ No newline at end of file diff --git a/src/main/resources/mapper/AdminMapper.xml b/src/main/resources/mapper/AdminMapper.xml new file mode 100644 index 0000000..6e94c52 --- /dev/null +++ b/src/main/resources/mapper/AdminMapper.xml @@ -0,0 +1,71 @@ + + + + + + + delete from `admin` + where id = #{id} + + + + + insert into `admin` + + id, + username, + password, + name, + phone, + email, + avatar, + role, + + + #{id}, + #{username}, + #{password}, + #{name}, + #{phone}, + #{email}, + #{avatar}, + #{role}, + + + + + update `admin` + + + username = #{username}, + + + password = #{password}, + + + name = #{name}, + + + phone = #{phone}, + + + email = #{email}, + + + avatar = #{avatar}, + + + role = #{role}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ArticleMapper.xml b/src/main/resources/mapper/ArticleMapper.xml new file mode 100644 index 0000000..2434ebd --- /dev/null +++ b/src/main/resources/mapper/ArticleMapper.xml @@ -0,0 +1,60 @@ + + + + + + + delete from `article` + where id = #{id} + + + + + insert into `article` + + id, + title, + content, + time, + img, + student_id, + + + #{id}, + #{title}, + #{content}, + #{time}, + #{img}, + #{studentId}, + + + + + update `article` + + + title = #{title}, + + + content = #{content}, + + + time = #{time}, + + + img = #{img}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/CourseMapper.xml b/src/main/resources/mapper/CourseMapper.xml new file mode 100644 index 0000000..2088dd0 --- /dev/null +++ b/src/main/resources/mapper/CourseMapper.xml @@ -0,0 +1,55 @@ + + + + + + + delete from `course` + where id = #{id} + + + + + insert into `course` + + id, + name, + img, + score, + teacher_id, + + + #{id}, + #{name}, + #{img}, + #{score}, + #{teacherId}, + + + + + update `course` + + + name = #{name}, + + + img = #{img}, + + + score = #{score}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ExamPlanMapper.xml b/src/main/resources/mapper/ExamPlanMapper.xml new file mode 100644 index 0000000..9224b64 --- /dev/null +++ b/src/main/resources/mapper/ExamPlanMapper.xml @@ -0,0 +1,51 @@ + + + + + + + delete from `exam_plan` + where id = #{id} + + + + + insert into `exam_plan` + + id, + title, + content, + time, + + + #{id}, + #{title}, + #{content}, + #{time}, + + + + + update `exam_plan` + + + title = #{title}, + + + content = #{content}, + + + time = #{time}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/NoticeMapper.xml b/src/main/resources/mapper/NoticeMapper.xml new file mode 100644 index 0000000..4cc8682 --- /dev/null +++ b/src/main/resources/mapper/NoticeMapper.xml @@ -0,0 +1,51 @@ + + + + + + + delete from `notice` + where id = #{id} + + + + + insert into `notice` + + id, + title, + content, + time, + + + #{id}, + #{title}, + #{content}, + #{time}, + + + + + update `notice` + + + title = #{title}, + + + content = #{content}, + + + time = #{time}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/QuestionMapper.xml b/src/main/resources/mapper/QuestionMapper.xml new file mode 100644 index 0000000..15b68d2 --- /dev/null +++ b/src/main/resources/mapper/QuestionMapper.xml @@ -0,0 +1,86 @@ + + + + + + + delete from `question` + where id = #{id} + + + + + insert into `question` + + id, + name, + course_id, + teacher_id, + type_id, + option_a, + option_b, + option_c, + option_d, + answer, + + + #{id}, + #{name}, + #{courseId}, + #{teacherId}, + #{typeId}, + #{optionA}, + #{optionB}, + #{optionC}, + #{optionD}, + #{answer}, + + + + + update `question` + + + name = #{name}, + + + course_id = #{courseId}, + + + type_id = #{typeId}, + + + option_a = #{optionA}, + + + option_b = #{optionB}, + + + option_c = #{optionC}, + + + option_d = #{optionD}, + + + answer = #{answer}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/QuestionTypeMapper.xml b/src/main/resources/mapper/QuestionTypeMapper.xml new file mode 100644 index 0000000..9079013 --- /dev/null +++ b/src/main/resources/mapper/QuestionTypeMapper.xml @@ -0,0 +1,46 @@ + + + + + + + delete from `question_type` + where id = #{id} + + + + + insert into `question_type` + + id, + name, + score, + + + #{id}, + #{name}, + #{score}, + + + + + update `question_type` + + + name = #{name}, + + + score = #{score}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ScoreMapper.xml b/src/main/resources/mapper/ScoreMapper.xml new file mode 100644 index 0000000..c0214c4 --- /dev/null +++ b/src/main/resources/mapper/ScoreMapper.xml @@ -0,0 +1,66 @@ + + + + + + + delete from `score` + where id = #{id} + + + + + insert into `score` + + id, + name, + course_id, + teacher_id, + student_id, + paper_id, + score, + status, + answer, + + + #{id}, + #{name}, + #{courseId}, + #{teacherId}, + #{studentId}, + #{paperId}, + #{score}, + #{status}, + #{answer}, + + + + + update `score` + + + score = #{score}, + + + status = #{status}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/StudentMapper.xml b/src/main/resources/mapper/StudentMapper.xml new file mode 100644 index 0000000..b573368 --- /dev/null +++ b/src/main/resources/mapper/StudentMapper.xml @@ -0,0 +1,76 @@ + + + + + + + delete from `student` + where id = #{id} + + + + + insert into `student` + + id, + username, + password, + name, + phone, + email, + avatar, + role, + status, + + + #{id}, + #{username}, + #{password}, + #{name}, + #{phone}, + #{email}, + #{avatar}, + #{role}, + #{status}, + + + + + update `student` + + + username = #{username}, + + + password = #{password}, + + + name = #{name}, + + + phone = #{phone}, + + + email = #{email}, + + + avatar = #{avatar}, + + + role = #{role}, + + + status = #{status}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/TeacherMapper.xml b/src/main/resources/mapper/TeacherMapper.xml new file mode 100644 index 0000000..c459aa5 --- /dev/null +++ b/src/main/resources/mapper/TeacherMapper.xml @@ -0,0 +1,71 @@ + + + + + + + delete from `teacher` + where id = #{id} + + + + + insert into `teacher` + + id, + username, + password, + name, + phone, + email, + avatar, + role, + + + #{id}, + #{username}, + #{password}, + #{name}, + #{phone}, + #{email}, + #{avatar}, + #{role}, + + + + + update `teacher` + + + username = #{username}, + + + password = #{password}, + + + name = #{name}, + + + phone = #{phone}, + + + email = #{email}, + + + avatar = #{avatar}, + + + role = #{role}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/src/main/resources/mapper/TestPaperMapper.xml b/src/main/resources/mapper/TestPaperMapper.xml new file mode 100644 index 0000000..cbac808 --- /dev/null +++ b/src/main/resources/mapper/TestPaperMapper.xml @@ -0,0 +1,61 @@ + + + + + + + delete from `test_paper` + where id = #{id} + + + + + insert into `test_paper` + + id, + name, + course_id, + teacher_id, + type, + start, + end, + time, + question_ids, + + + #{id}, + #{name}, + #{courseId}, + #{teacherId}, + #{type}, + #{start}, + #{end}, + #{time}, + #{questionIds}, + + + + + update `test_paper` + + + name = #{name}, + + + where id = #{id} + + + \ No newline at end of file diff --git a/ui/.env.development b/ui/.env.development new file mode 100644 index 0000000..62bb4ac --- /dev/null +++ b/ui/.env.development @@ -0,0 +1 @@ +VITE_BASE_URL='http://localhost:9090' \ No newline at end of file diff --git a/ui/.env.production b/ui/.env.production new file mode 100644 index 0000000..2beb7d1 --- /dev/null +++ b/ui/.env.production @@ -0,0 +1 @@ +VITE_BASE_URL='http://:9090' \ No newline at end of file diff --git a/ui/.gitignore b/ui/.gitignore new file mode 100644 index 0000000..c6660fa --- /dev/null +++ b/ui/.gitignore @@ -0,0 +1,28 @@ +# ---> Java +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +.idea +node_modules diff --git a/ui/index.html b/ui/index.html new file mode 100644 index 0000000..b3dc0fe --- /dev/null +++ b/ui/index.html @@ -0,0 +1,13 @@ + + + + + + + 在线考试系统 + + +
+ + + diff --git a/ui/jsconfig.json b/ui/jsconfig.json new file mode 100644 index 0000000..5a1f2d2 --- /dev/null +++ b/ui/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/ui/package.json b/ui/package.json new file mode 100644 index 0000000..c8c45c3 --- /dev/null +++ b/ui/package.json @@ -0,0 +1,28 @@ +{ + "name": "vue", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", + "axios": "^1.7.2", + "element-plus": "^2.7.6", + "vue": "^3.4.29", + "vue-router": "^4.3.3" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.5", + "sass": "^1.89.0", + "unplugin-auto-import": "^0.17.6", + "unplugin-element-plus": "^0.8.0", + "unplugin-vue-components": "^0.27.2", + "vite": "^5.3.1" + } +} diff --git a/ui/public/favicon.ico b/ui/public/favicon.ico new file mode 100644 index 0000000..eafa13b Binary files /dev/null and b/ui/public/favicon.ico differ diff --git a/ui/src/App.vue b/ui/src/App.vue new file mode 100644 index 0000000..6d11557 --- /dev/null +++ b/ui/src/App.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/ui/src/assets/css/front.css b/ui/src/assets/css/front.css new file mode 100644 index 0000000..1425567 --- /dev/null +++ b/ui/src/assets/css/front.css @@ -0,0 +1,57 @@ +.front-notice { + padding: 5px 20px; + color: #666; + font-size: 12px; + display: flex; + align-items: center; +} + +.front-header { + display: flex; + height: 60px; + line-height: 60px; + border-bottom: 1px solid #eee; +} + +.front-header-left { + width: 350px; + display: flex; + align-items: center; + padding-left: 30px; +} + +.front-header-left img { + width: 35px; + height: 35px; + border-radius: 50%; +} + +.front-header-left .title { + color: #333; + cursor: pointer; + margin-left: 10px; + font-size: 20px; + font-weight: bold; +} + +.front-header-center { + flex: 1; +} + +.front-header-right { + padding-right: 20px; +} + +.main-content { + width: 80%; + margin: 5px auto; +} + +/*Element-Plus样式覆盖*/ +.el-menu--horizontal { + border: none !important; + height: 59px; +} +.el-tooltip__trigger { + outline: none; +} \ No newline at end of file diff --git a/ui/src/assets/css/global.css b/ui/src/assets/css/global.css new file mode 100644 index 0000000..ee8e02b --- /dev/null +++ b/ui/src/assets/css/global.css @@ -0,0 +1,21 @@ +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + color: #333; + font-size: 14px; +} + +a { + text-decoration: none; +} + +.card { + background-color: #fff; + border-radius: 5px; + padding: 10px; + box-shadow: 0 0 10px rgba(0,0,0,.1); +} \ No newline at end of file diff --git a/ui/src/assets/css/index.scss b/ui/src/assets/css/index.scss new file mode 100644 index 0000000..f8162aa --- /dev/null +++ b/ui/src/assets/css/index.scss @@ -0,0 +1,7 @@ +@forward "element-plus/theme-chalk/src/common/var.scss" with ($colors: ( + "primary": ("base": #1baf8a), + "success": ("base": #46b61f), + "warning": ("base": #f1cf61), + "danger": ("base": #e52f2f), + "info": ("base": #7d83d5), +)); diff --git a/ui/src/assets/css/manager.css b/ui/src/assets/css/manager.css new file mode 100644 index 0000000..2305801 --- /dev/null +++ b/ui/src/assets/css/manager.css @@ -0,0 +1,108 @@ +.manager-container { + background-color: #f8f8ff; + min-height: 100vh; +} + +.manager-header { + height: 60px; + background-color: #07c796; + display: flex; + align-items: center; + box-shadow: 0 1px 4px rgba(0, 21, 41, .08); +} + +.manager-header-left { + background-color: #07c796; + width: 250px; + height: 100%; + padding-left: 10px; + display: flex; + align-items: center +} + +.manager-header-left img { + width: 30px; + height: 30px; +} + +.manager-header-left .title { + font-weight: bold; + font-size: 20px; + margin-left: 10px; + color: #eee; +} + +.manager-header-center { + flex: 1; + padding-left: 20px; +} + +.manager-main-left { + width: 200px; + background-color: #fff; + min-height: calc(100vh - 60px); + box-shadow: 0 0 6px rgba(0, 21, 41, .35); +} + +.manager-main-right { + flex: 1; + width: 0; + background-color: #f8f8ff; + padding: 10px; +} + + +/* ElementUI */ +.el-menu { + border: none; + background-color: #fff; +} + +.el-tooltip__trigger { + outline: none; +} + +/deep/.el-sub-menu__title { + color: #666 !important; + height: 50px; + line-height: 50px; + background-color: #fff !important; +} + +.el-sub-menu__title:hover { + background-color: #fff; /* 必须加上这个背景色,否则鼠标移入会出现白色 */ + color: #fff; +} + +.el-menu-item { + color: #666; + height: 50px; + line-height: 50px; + background-color: #fff !important; /* 必须加上这个背景色,否则鼠标离开会出现白色 */ +} + +.el-menu--inline .el-menu-item { + background-color: #fff !important; +} + +.el-menu-item.is-active { + background-color: #cdf4ea !important; + color: #07c796; + border-right: 3px solid #07c796; +} + +.el-menu-item:not(.is-active):hover { + color: #fff; +} +.el-menu-item:hover { + background-color: #e6f9f5 !important; + color: #07c796 !important; +} + +/deep/.el-breadcrumb__inner { + color: white !important; +} + +/deep/.manager-header-right span { + color: white; +} diff --git a/ui/src/assets/imgs/404.jpg b/ui/src/assets/imgs/404.jpg new file mode 100644 index 0000000..7ce045c Binary files /dev/null and b/ui/src/assets/imgs/404.jpg differ diff --git a/ui/src/assets/imgs/avatar.png b/ui/src/assets/imgs/avatar.png new file mode 100644 index 0000000..e16488e Binary files /dev/null and b/ui/src/assets/imgs/avatar.png differ diff --git a/ui/src/assets/imgs/bg.jpg b/ui/src/assets/imgs/bg.jpg new file mode 100644 index 0000000..4df0a9b Binary files /dev/null and b/ui/src/assets/imgs/bg.jpg differ diff --git a/ui/src/assets/imgs/carousel-1.jpg b/ui/src/assets/imgs/carousel-1.jpg new file mode 100644 index 0000000..53c9ea6 Binary files /dev/null and b/ui/src/assets/imgs/carousel-1.jpg differ diff --git a/ui/src/assets/imgs/carousel-2.jpg b/ui/src/assets/imgs/carousel-2.jpg new file mode 100644 index 0000000..5db5eef Binary files /dev/null and b/ui/src/assets/imgs/carousel-2.jpg differ diff --git a/ui/src/assets/imgs/carousel-3.jpg b/ui/src/assets/imgs/carousel-3.jpg new file mode 100644 index 0000000..275d60d Binary files /dev/null and b/ui/src/assets/imgs/carousel-3.jpg differ diff --git a/ui/src/assets/imgs/logo.png b/ui/src/assets/imgs/logo.png new file mode 100644 index 0000000..eafa13b Binary files /dev/null and b/ui/src/assets/imgs/logo.png differ diff --git a/ui/src/main.js b/ui/src/main.js new file mode 100644 index 0000000..3bf9304 --- /dev/null +++ b/ui/src/main.js @@ -0,0 +1,19 @@ +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' +import '@/assets/css/global.css' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' +import zhCn from 'element-plus/es/locale/lang/zh-cn' + +const app = createApp(App) + +app.use(router) +app.use(ElementPlus, { locale: zhCn }) +app.mount('#app') + +import * as ElementPlusIconsVue from '@element-plus/icons-vue' + +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} diff --git a/ui/src/router/index.js b/ui/src/router/index.js new file mode 100644 index 0000000..6edb019 --- /dev/null +++ b/ui/src/router/index.js @@ -0,0 +1,49 @@ +import { createRouter, createWebHistory } from 'vue-router' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { path: '/', redirect: '/manager/home' }, + { + path: '/manager', + component: () => import('@/views/Manager.vue'), + children: [ + { path: 'home', meta: { name: '系统首页' }, component: () => import('@/views/manager/Home.vue'), }, + { path: 'admin', meta: { name: '管理员信息' }, component: () => import('@/views/manager/Admin.vue'), }, + { path: 'notice', meta: { name: '系统公告' }, component: () => import('@/views/manager/Notice.vue'), }, + { path: 'person', meta: { name: '个人资料' }, component: () => import('@/views/manager/Person.vue'), }, + { path: 'password', meta: { name: '修改密码' }, component: () => import('@/views/manager/Password.vue'), }, + { path: 'teacher', meta: { name: '教师信息' }, component: () => import('@/views/manager/Teacher.vue'), }, + { path: 'student', meta: { name: '学生信息' }, component: () => import('@/views/manager/Student.vue'), }, + { path: 'examPlan', meta: { name: '考试安排' }, component: () => import('@/views/manager/ExamPlan.vue'), }, + { path: 'questionType', meta: { name: '题型信息' }, component: () => import('@/views/manager/QuestionType.vue'), }, + { path: 'course', meta: { name: '课程信息' }, component: () => import('@/views/manager/Course.vue'), }, + { path: 'question', meta: { name: '题库信息' }, component: () => import('@/views/manager/Question.vue'), }, + { path: 'share', meta: { name: '交流分享' }, component: () => import('@/views/manager/Share.vue'), }, + { path: 'testPaper', meta: { name: '交流分享' }, component: () => import('@/views/manager/TestPaper.vue'), }, + { path: 'score', meta: { name: '交流分享' }, component: () => import('@/views/manager/Score.vue'), }, + ] + }, + { + path: '/front', + component: () => import('@/views/Front.vue'), + children: [ + { path: 'home', component: () => import('@/views/front/Home.vue'), }, + { path: 'person', component: () => import('@/views/front/Person.vue'), }, + { path: 'myShare', component: () => import('@/views/front/MyShare.vue'), }, + { path: 'forum', component: () => import('@/views/front/Forum.vue'), }, + { path: 'forumDetail', component: () => import('@/views/front/ForumDetail.vue'), }, + { path: 'exam', component: () => import('@/views/front/Exam.vue'), }, + { path: 'testPaper', component: () => import('@/views/front/TestPaper.vue'), }, + { path: 'testPaperView', component: () => import('@/views/front/TestPaperView.vue'), }, + { path: 'score', component: () => import('@/views/front/Score.vue'), }, + ] + }, + { path: '/login', component: () => import('@/views/Login.vue') }, + { path: '/register', component: () => import('@/views/Register.vue') }, + { path: '/404', component: () => import('@/views/404.vue') }, + { path: '/:pathMatch(.*)', redirect: '/404' } + ] +}) + +export default router diff --git a/ui/src/utils/request.js b/ui/src/utils/request.js new file mode 100644 index 0000000..f200aff --- /dev/null +++ b/ui/src/utils/request.js @@ -0,0 +1,53 @@ +import axios from "axios"; +import {ElMessage} from "element-plus"; +import router from "@/router/index.js"; + +const request = axios.create({ + baseURL: import.meta.env.VITE_BASE_URL, + timeout: 30000 // 后台接口超时时间 +}) + +// request 拦截器 +// 可以自请求发送前对请求做一些处理 +request.interceptors.request.use(config => { + config.headers['Content-Type'] = 'application/json;charset=utf-8'; + let user = JSON.parse(localStorage.getItem("xm-user") || '{}') + config.headers['token'] = user.token || '' + return config +}, error => { + return Promise.reject(error) +}); + +// response 拦截器 +// 可以在接口响应后统一处理结果 +request.interceptors.response.use( + response => { + let res = response.data; + // 如果是返回的文件 + if (response.config.responseType === 'blob') { + return res + } + // 当权限验证不通过的时候给出提示 + if (res.code === '401') { + ElMessage.error(res.msg) + router.push('/login') + } + // 兼容服务端返回的字符串数据 + if (typeof res === 'string') { + res = res ? JSON.parse(res) : res + } + return res; + }, + error => { + if (error.response.status === 404) { + ElMessage.error('未找到请求接口') + } else if (error.response.status === 500) { + ElMessage.error('系统异常,请查看后端控制台报错') + } else { + console.error(error.message) + } + return Promise.reject(error) + } +) + +export default request diff --git a/ui/src/views/404.vue b/ui/src/views/404.vue new file mode 100644 index 0000000..3e9868b --- /dev/null +++ b/ui/src/views/404.vue @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/ui/src/views/Front.vue b/ui/src/views/Front.vue new file mode 100644 index 0000000..0570621 --- /dev/null +++ b/ui/src/views/Front.vue @@ -0,0 +1,86 @@ + + + + + \ No newline at end of file diff --git a/ui/src/views/Login.vue b/ui/src/views/Login.vue new file mode 100644 index 0000000..88d40f0 --- /dev/null +++ b/ui/src/views/Login.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/ui/src/views/Manager.vue b/ui/src/views/Manager.vue new file mode 100644 index 0000000..bb55884 --- /dev/null +++ b/ui/src/views/Manager.vue @@ -0,0 +1,104 @@ + + + + + \ No newline at end of file diff --git a/ui/src/views/Register.vue b/ui/src/views/Register.vue new file mode 100644 index 0000000..63f69aa --- /dev/null +++ b/ui/src/views/Register.vue @@ -0,0 +1,103 @@ + + + + + \ No newline at end of file diff --git a/ui/src/views/front/Exam.vue b/ui/src/views/front/Exam.vue new file mode 100644 index 0000000..230fc87 --- /dev/null +++ b/ui/src/views/front/Exam.vue @@ -0,0 +1,91 @@ + + + \ No newline at end of file diff --git a/ui/src/views/front/Forum.vue b/ui/src/views/front/Forum.vue new file mode 100644 index 0000000..642a71b --- /dev/null +++ b/ui/src/views/front/Forum.vue @@ -0,0 +1,71 @@ + + + \ No newline at end of file diff --git a/ui/src/views/front/ForumDetail.vue b/ui/src/views/front/ForumDetail.vue new file mode 100644 index 0000000..e49b96e --- /dev/null +++ b/ui/src/views/front/ForumDetail.vue @@ -0,0 +1,35 @@ + + \ No newline at end of file diff --git a/ui/src/views/front/Home.vue b/ui/src/views/front/Home.vue new file mode 100644 index 0000000..09c980b --- /dev/null +++ b/ui/src/views/front/Home.vue @@ -0,0 +1,150 @@ + + + \ No newline at end of file diff --git a/ui/src/views/front/MyShare.vue b/ui/src/views/front/MyShare.vue new file mode 100644 index 0000000..3c6c1dd --- /dev/null +++ b/ui/src/views/front/MyShare.vue @@ -0,0 +1,198 @@ + + \ No newline at end of file diff --git a/ui/src/views/front/Person.vue b/ui/src/views/front/Person.vue new file mode 100644 index 0000000..e6c93e2 --- /dev/null +++ b/ui/src/views/front/Person.vue @@ -0,0 +1,158 @@ + + + + + \ No newline at end of file diff --git a/ui/src/views/front/Score.vue b/ui/src/views/front/Score.vue new file mode 100644 index 0000000..3cb0a41 --- /dev/null +++ b/ui/src/views/front/Score.vue @@ -0,0 +1,60 @@ + + \ No newline at end of file diff --git a/ui/src/views/front/TestPaper.vue b/ui/src/views/front/TestPaper.vue new file mode 100644 index 0000000..8e04b9b --- /dev/null +++ b/ui/src/views/front/TestPaper.vue @@ -0,0 +1,123 @@ + + + \ No newline at end of file diff --git a/ui/src/views/front/TestPaperView.vue b/ui/src/views/front/TestPaperView.vue new file mode 100644 index 0000000..3796cf3 --- /dev/null +++ b/ui/src/views/front/TestPaperView.vue @@ -0,0 +1,90 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Admin.vue b/ui/src/views/manager/Admin.vue new file mode 100644 index 0000000..4233a18 --- /dev/null +++ b/ui/src/views/manager/Admin.vue @@ -0,0 +1,187 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Course.vue b/ui/src/views/manager/Course.vue new file mode 100644 index 0000000..4a1d5a0 --- /dev/null +++ b/ui/src/views/manager/Course.vue @@ -0,0 +1,182 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/ExamPlan.vue b/ui/src/views/manager/ExamPlan.vue new file mode 100644 index 0000000..9ae1045 --- /dev/null +++ b/ui/src/views/manager/ExamPlan.vue @@ -0,0 +1,159 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Home.vue b/ui/src/views/manager/Home.vue new file mode 100644 index 0000000..b77acd3 --- /dev/null +++ b/ui/src/views/manager/Home.vue @@ -0,0 +1,71 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Notice.vue b/ui/src/views/manager/Notice.vue new file mode 100644 index 0000000..6572b2f --- /dev/null +++ b/ui/src/views/manager/Notice.vue @@ -0,0 +1,159 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Password.vue b/ui/src/views/manager/Password.vue new file mode 100644 index 0000000..65325f8 --- /dev/null +++ b/ui/src/views/manager/Password.vue @@ -0,0 +1,76 @@ + + + + + \ No newline at end of file diff --git a/ui/src/views/manager/Person.vue b/ui/src/views/manager/Person.vue new file mode 100644 index 0000000..646882d --- /dev/null +++ b/ui/src/views/manager/Person.vue @@ -0,0 +1,105 @@ + + + + + \ No newline at end of file diff --git a/ui/src/views/manager/Question.vue b/ui/src/views/manager/Question.vue new file mode 100644 index 0000000..f3f4cfc --- /dev/null +++ b/ui/src/views/manager/Question.vue @@ -0,0 +1,254 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/QuestionType.vue b/ui/src/views/manager/QuestionType.vue new file mode 100644 index 0000000..9e4bcac --- /dev/null +++ b/ui/src/views/manager/QuestionType.vue @@ -0,0 +1,160 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Score.vue b/ui/src/views/manager/Score.vue new file mode 100644 index 0000000..639f1e5 --- /dev/null +++ b/ui/src/views/manager/Score.vue @@ -0,0 +1,140 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Share.vue b/ui/src/views/manager/Share.vue new file mode 100644 index 0000000..15dda7f --- /dev/null +++ b/ui/src/views/manager/Share.vue @@ -0,0 +1,106 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Student.vue b/ui/src/views/manager/Student.vue new file mode 100644 index 0000000..7e20dea --- /dev/null +++ b/ui/src/views/manager/Student.vue @@ -0,0 +1,201 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/Teacher.vue b/ui/src/views/manager/Teacher.vue new file mode 100644 index 0000000..98ebfd0 --- /dev/null +++ b/ui/src/views/manager/Teacher.vue @@ -0,0 +1,187 @@ + + + \ No newline at end of file diff --git a/ui/src/views/manager/TestPaper.vue b/ui/src/views/manager/TestPaper.vue new file mode 100644 index 0000000..a311513 --- /dev/null +++ b/ui/src/views/manager/TestPaper.vue @@ -0,0 +1,252 @@ + + + \ No newline at end of file diff --git a/ui/vite.config.js b/ui/vite.config.js new file mode 100644 index 0000000..9f8d580 --- /dev/null +++ b/ui/vite.config.js @@ -0,0 +1,103 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import ElementPlus from 'unplugin-element-plus/vite' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + // 按需定制主题配置 + ElementPlus({ + useSource: true, + }), + AutoImport({ + resolvers: [ElementPlusResolver({ importStyle: 'sass' })], + }), + Components({ + resolvers: [ElementPlusResolver({ importStyle: 'sass' })], + }), + ], + // 预加载项目必需的组件 + optimizeDeps: { + include: [ + "vue", + "vue-router", + "axios", + "element-plus/es/components/base/style/css", + "element-plus/es/components/message/style/css", + "element-plus/es/components/message-box/style/css", + "element-plus/es/components/form/style/css", + "element-plus/es/components/form-item/style/css", + "element-plus/es/components/button/style/css", + "element-plus/es/components/input/style/css", + "element-plus/es/components/input-number/style/css", + "element-plus/es/components/switch/style/css", + "element-plus/es/components/upload/style/css", + "element-plus/es/components/menu/style/css", + "element-plus/es/components/col/style/css", + "element-plus/es/components/icon/style/css", + "element-plus/es/components/row/style/css", + "element-plus/es/components/tag/style/css", + "element-plus/es/components/dialog/style/css", + "element-plus/es/components/loading/style/css", + "element-plus/es/components/radio/style/css", + "element-plus/es/components/radio-group/style/css", + "element-plus/es/components/popover/style/css", + "element-plus/es/components/scrollbar/style/css", + "element-plus/es/components/tooltip/style/css", + "element-plus/es/components/dropdown/style/css", + "element-plus/es/components/dropdown-menu/style/css", + "element-plus/es/components/dropdown-item/style/css", + "element-plus/es/components/sub-menu/style/css", + "element-plus/es/components/menu-item/style/css", + "element-plus/es/components/divider/style/css", + "element-plus/es/components/card/style/css", + "element-plus/es/components/link/style/css", + "element-plus/es/components/breadcrumb/style/css", + "element-plus/es/components/breadcrumb-item/style/css", + "element-plus/es/components/table/style/css", + "element-plus/es/components/tree-select/style/css", + "element-plus/es/components/table-column/style/css", + "element-plus/es/components/select/style/css", + "element-plus/es/components/option/style/css", + "element-plus/es/components/pagination/style/css", + "element-plus/es/components/tree/style/css", + "element-plus/es/components/alert/style/css", + "element-plus/es/components/radio-button/style/css", + "element-plus/es/components/checkbox-group/style/css", + "element-plus/es/components/checkbox/style/css", + "element-plus/es/components/tabs/style/css", + "element-plus/es/components/tab-pane/style/css", + "element-plus/es/components/rate/style/css", + "element-plus/es/components/date-picker/style/css", + "element-plus/es/components/notification/style/css", + "element-plus/es/components/image/style/css", + "element-plus/es/components/statistic/style/css", + "element-plus/es/components/watermark/style/css", + "element-plus/es/components/config-provider/style/css", + "element-plus/es/components/text/style/css", + "element-plus/es/components/drawer/style/css", + "element-plus/es/components/color-picker/style/css", + ], + }, + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + css: { + preprocessorOptions: { + scss: { + // 自动导入定制化样式文件进行样式覆盖 + additionalData: ` + @use "@/assets/css/index.scss" as *; + `, + } + } + }, +}) diff --git a/ui/yarn.lock b/ui/yarn.lock new file mode 100644 index 0000000..396d293 --- /dev/null +++ b/ui/yarn.lock @@ -0,0 +1,1661 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@antfu/utils@^0.7.10": + version "0.7.10" + resolved "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz#ae829f170158e297a9b6a28f161a8e487d00814d" + integrity sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@babel/parser@^7.27.2": + version "7.27.2" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" + integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw== + dependencies: + "@babel/types" "^7.27.1" + +"@babel/runtime@^7.12.0": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz#9fce313d12c9a77507f264de74626e87fd0dc541" + integrity sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog== + +"@babel/types@^7.27.1": + version "7.27.1" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" + integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + +"@ctrl/tinycolor@^3.4.1": + version "3.6.1" + resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31" + integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== + +"@element-plus/icons-vue@^2.3.1": + version "2.3.1" + resolved "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz#1f635ad5fdd5c85ed936481525570e82b5a8307a" + integrity sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg== + +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + +"@floating-ui/core@^1.7.0": + version "1.7.0" + resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz#1aff27a993ea1b254a586318c29c3b16ea0f4d0a" + integrity sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA== + dependencies: + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/dom@^1.0.1": + version "1.7.0" + resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz#f9f83ee4fee78ac23ad9e65b128fc11a27857532" + integrity sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg== + dependencies: + "@floating-ui/core" "^1.7.0" + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/utils@^0.2.9": + version "0.2.9" + resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" + integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== + +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.0" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@parcel/watcher-android-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1" + integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA== + +"@parcel/watcher-darwin-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67" + integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw== + +"@parcel/watcher-darwin-x64@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8" + integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg== + +"@parcel/watcher-freebsd-x64@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b" + integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ== + +"@parcel/watcher-linux-arm-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1" + integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA== + +"@parcel/watcher-linux-arm-musl@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e" + integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q== + +"@parcel/watcher-linux-arm64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30" + integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w== + +"@parcel/watcher-linux-arm64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2" + integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg== + +"@parcel/watcher-linux-x64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e" + integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A== + +"@parcel/watcher-linux-x64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee" + integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg== + +"@parcel/watcher-win32-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243" + integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw== + +"@parcel/watcher-win32-ia32@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6" + integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ== + +"@parcel/watcher-win32-x64@2.5.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947" + integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA== + +"@parcel/watcher@^2.4.1": + version "2.5.1" + resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200" + integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.1" + "@parcel/watcher-darwin-arm64" "2.5.1" + "@parcel/watcher-darwin-x64" "2.5.1" + "@parcel/watcher-freebsd-x64" "2.5.1" + "@parcel/watcher-linux-arm-glibc" "2.5.1" + "@parcel/watcher-linux-arm-musl" "2.5.1" + "@parcel/watcher-linux-arm64-glibc" "2.5.1" + "@parcel/watcher-linux-arm64-musl" "2.5.1" + "@parcel/watcher-linux-x64-glibc" "2.5.1" + "@parcel/watcher-linux-x64-musl" "2.5.1" + "@parcel/watcher-win32-arm64" "2.5.1" + "@parcel/watcher-win32-ia32" "2.5.1" + "@parcel/watcher-win32-x64" "2.5.1" + +"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7": + version "2.11.7" + resolved "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz#a7f69e3665d3da9b115f9e71671dae1b97e13671" + integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ== + +"@rollup/pluginutils@^5.0.2", "@rollup/pluginutils@^5.1.0", "@rollup/pluginutils@^5.1.3", "@rollup/pluginutils@^5.1.4": + version "5.1.4" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" + integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^4.0.2" + +"@rollup/rollup-android-arm-eabi@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz#f39f09f60d4a562de727c960d7b202a2cf797424" + integrity sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw== + +"@rollup/rollup-android-arm64@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz#d19af7e23760717f1d879d4ca3d2cd247742dff2" + integrity sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA== + +"@rollup/rollup-darwin-arm64@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz#1c3a2fbf205d80641728e05f4a56c909e95218b7" + integrity sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w== + +"@rollup/rollup-darwin-x64@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz#aa66d2ba1a25e609500e13bef06dc0e71cc0c0d4" + integrity sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg== + +"@rollup/rollup-freebsd-arm64@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz#df10a7b6316a0ef1028c6ca71a081124c537e30d" + integrity sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg== + +"@rollup/rollup-freebsd-x64@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz#a3fdce8a05e95b068cbcb46e4df5185e407d0c35" + integrity sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA== + +"@rollup/rollup-linux-arm-gnueabihf@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz#49f766c55383bd0498014a9d76924348c2f3890c" + integrity sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg== + +"@rollup/rollup-linux-arm-musleabihf@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz#1d4d7d32fc557e17d52e1857817381ea365e2959" + integrity sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA== + +"@rollup/rollup-linux-arm64-gnu@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz#f4fc317268441e9589edad3be8f62b6c03009bc1" + integrity sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA== + +"@rollup/rollup-linux-arm64-musl@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz#63a1f1b0671cb17822dabae827fef0e443aebeb7" + integrity sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg== + +"@rollup/rollup-linux-loongarch64-gnu@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz#c659b01cc6c0730b547571fc3973e1e955369f98" + integrity sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw== + +"@rollup/rollup-linux-powerpc64le-gnu@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz#612e746f9ad7e58480f964d65e0d6c3f4aae69a8" + integrity sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A== + +"@rollup/rollup-linux-riscv64-gnu@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz#4610dbd1dcfbbae32fbc10c20ae7387acb31110c" + integrity sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw== + +"@rollup/rollup-linux-riscv64-musl@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz#054911fab40dc83fafc21e470193c058108f19d8" + integrity sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw== + +"@rollup/rollup-linux-s390x-gnu@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz#98896eca8012547c7f04bd07eaa6896825f9e1a5" + integrity sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g== + +"@rollup/rollup-linux-x64-gnu@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz#01cf56844a1e636ee80dfb364e72c2b7142ad896" + integrity sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A== + +"@rollup/rollup-linux-x64-musl@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz#e67c7531df6dff0b4c241101d4096617fbca87c3" + integrity sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ== + +"@rollup/rollup-win32-arm64-msvc@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz#7eeada98444e580674de6989284e4baacd48ea65" + integrity sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ== + +"@rollup/rollup-win32-ia32-msvc@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz#516c4b54f80587b4a390aaf4940b40870271d35d" + integrity sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg== + +"@rollup/rollup-win32-x64-msvc@4.41.1": + version "4.41.1" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz#848f99b0d9936d92221bb6070baeff4db6947a30" + integrity sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw== + +"@transloadit/prettier-bytes@0.0.7": + version "0.0.7" + resolved "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz#cdb5399f445fdd606ed833872fa0cabdbc51686b" + integrity sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA== + +"@types/estree@1.0.7", "@types/estree@^1.0.0": + version "1.0.7" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" + integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== + +"@types/event-emitter@^0.3.3": + version "0.3.5" + resolved "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.5.tgz#ce9b513f72c50dcf0443a12165a93a79ba7a7092" + integrity sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ== + +"@types/lodash-es@^4.17.6": + version "4.17.12" + resolved "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz#65f6d1e5f80539aa7cfbfc962de5def0cf4f341b" + integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*", "@types/lodash@^4.14.182": + version "4.17.17" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz#fb85a04f47e9e4da888384feead0de05f7070355" + integrity sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ== + +"@types/web-bluetooth@^0.0.16": + version "0.0.16" + resolved "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8" + integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ== + +"@uppy/companion-client@^2.2.2": + version "2.2.2" + resolved "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.2.2.tgz#c70b42fdcca728ef88b3eebf7ee3e2fa04b4923b" + integrity sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og== + dependencies: + "@uppy/utils" "^4.1.2" + namespace-emitter "^2.0.1" + +"@uppy/core@^2.1.1": + version "2.3.4" + resolved "https://registry.npmjs.org/@uppy/core/-/core-2.3.4.tgz#260b85b6bf3aa03cdc67da231f8c69cfbfdcc84a" + integrity sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ== + dependencies: + "@transloadit/prettier-bytes" "0.0.7" + "@uppy/store-default" "^2.1.1" + "@uppy/utils" "^4.1.3" + lodash.throttle "^4.1.1" + mime-match "^1.0.2" + namespace-emitter "^2.0.1" + nanoid "^3.1.25" + preact "^10.5.13" + +"@uppy/store-default@^2.1.1": + version "2.1.1" + resolved "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz#62a656a099bdaa012306e054d093754cb2d36e3e" + integrity sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ== + +"@uppy/utils@^4.1.2", "@uppy/utils@^4.1.3": + version "4.1.3" + resolved "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.3.tgz#9d0be6ece4df25f228d30ef40be0f14208258ce3" + integrity sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw== + dependencies: + lodash.throttle "^4.1.1" + +"@uppy/xhr-upload@^2.0.3": + version "2.1.3" + resolved "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz#0d4e355332fe0c6eb372d7731315e04d02aeeb18" + integrity sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ== + dependencies: + "@uppy/companion-client" "^2.2.2" + "@uppy/utils" "^4.1.2" + nanoid "^3.1.25" + +"@vitejs/plugin-vue@^5.0.5": + version "5.2.4" + resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz#9e8a512eb174bfc2a333ba959bbf9de428d89ad8" + integrity sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA== + +"@vue/compiler-core@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.15.tgz#7cbda69429490f4ec0f68126dd0d6eae050dd01c" + integrity sha512-nGRc6YJg/kxNqbv/7Tg4juirPnjHvuVdhcmDvQWVZXlLHjouq7VsKmV1hIxM/8yKM0VUfwT/Uzc0lO510ltZqw== + dependencies: + "@babel/parser" "^7.27.2" + "@vue/shared" "3.5.15" + entities "^4.5.0" + estree-walker "^2.0.2" + source-map-js "^1.2.1" + +"@vue/compiler-dom@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.15.tgz#2de7fec1a685c236585a4a1fb12cc586d7f0ffef" + integrity sha512-ZelQd9n+O/UCBdL00rlwCrsArSak+YLZpBVuNDio1hN3+wrCshYZEDUO3khSLAzPbF1oQS2duEoMDUHScUlYjA== + dependencies: + "@vue/compiler-core" "3.5.15" + "@vue/shared" "3.5.15" + +"@vue/compiler-sfc@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.15.tgz#d45a5c5171d8823c59725d31af406693c8816195" + integrity sha512-3zndKbxMsOU6afQWer75Zot/aydjtxNj0T2KLg033rAFaQUn2PGuE32ZRe4iMhflbTcAxL0yEYsRWFxtPro8RQ== + dependencies: + "@babel/parser" "^7.27.2" + "@vue/compiler-core" "3.5.15" + "@vue/compiler-dom" "3.5.15" + "@vue/compiler-ssr" "3.5.15" + "@vue/shared" "3.5.15" + estree-walker "^2.0.2" + magic-string "^0.30.17" + postcss "^8.5.3" + source-map-js "^1.2.1" + +"@vue/compiler-ssr@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.15.tgz#b6ffbb19ff7126fc0e60cbf9c4ca34d9a9ce9fb2" + integrity sha512-gShn8zRREZbrXqTtmLSCffgZXDWv8nHc/GhsW+mbwBfNZL5pI96e7IWcIq8XGQe1TLtVbu7EV9gFIVSmfyarPg== + dependencies: + "@vue/compiler-dom" "3.5.15" + "@vue/shared" "3.5.15" + +"@vue/devtools-api@^6.6.4": + version "6.6.4" + resolved "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343" + integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g== + +"@vue/reactivity@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.15.tgz#18d00ae922e8b0dc09afe952bd47510c6e4305e9" + integrity sha512-GaA5VUm30YWobCwpvcs9nvFKf27EdSLKDo2jA0IXzGS344oNpFNbEQ9z+Pp5ESDaxyS8FcH0vFN/XSe95BZtHQ== + dependencies: + "@vue/shared" "3.5.15" + +"@vue/runtime-core@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.15.tgz#0accac4b441bb4aa00f58ba353b6f61e83f45202" + integrity sha512-CZAlIOQ93nj0OPpWWOx4+QDLCMzBNY85IQR4Voe6vIID149yF8g9WQaWnw042f/6JfvLttK7dnyWlC1EVCRK8Q== + dependencies: + "@vue/reactivity" "3.5.15" + "@vue/shared" "3.5.15" + +"@vue/runtime-dom@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.15.tgz#048b725069f6d3fe5002e53eba118466d1fbec84" + integrity sha512-wFplHKzKO/v998up2iCW3RN9TNUeDMhdBcNYZgs5LOokHntrB48dyuZHspcahKZczKKh3v6i164gapMPxBTKNw== + dependencies: + "@vue/reactivity" "3.5.15" + "@vue/runtime-core" "3.5.15" + "@vue/shared" "3.5.15" + csstype "^3.1.3" + +"@vue/server-renderer@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.15.tgz#c1e8597e4bec8ea0b323c32dc032aa5c1f2983f4" + integrity sha512-Gehc693kVTYkLt6QSYEjGvqvdK2zZ/gf/D5zkgmvBdeB30dNnVZS8yY7+IlBmHRd1rR/zwaqeu06Ij04ZxBscg== + dependencies: + "@vue/compiler-ssr" "3.5.15" + "@vue/shared" "3.5.15" + +"@vue/shared@3.5.15": + version "3.5.15" + resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.15.tgz#4c633a0e66f38119e38eecf340b4a65b0bad7192" + integrity sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA== + +"@vueuse/core@^9.1.0": + version "9.13.0" + resolved "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz#2f69e66d1905c1e4eebc249a01759cf88ea00cf4" + integrity sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw== + dependencies: + "@types/web-bluetooth" "^0.0.16" + "@vueuse/metadata" "9.13.0" + "@vueuse/shared" "9.13.0" + vue-demi "*" + +"@vueuse/metadata@9.13.0": + version "9.13.0" + resolved "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz#bc25a6cdad1b1a93c36ce30191124da6520539ff" + integrity sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ== + +"@vueuse/shared@9.13.0": + version "9.13.0" + resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz#089ff4cc4e2e7a4015e57a8f32e4b39d096353b9" + integrity sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw== + dependencies: + vue-demi "*" + +"@wangeditor/basic-modules@^1.1.7": + version "1.1.7" + resolved "https://registry.npmjs.org/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz#a9c3ccf4ef53332f29550d59d3676e15f395946f" + integrity sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg== + dependencies: + is-url "^1.2.4" + +"@wangeditor/code-highlight@^1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz#90256857714d5c0cf83ac475aea64db7bf29a7cd" + integrity sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw== + dependencies: + prismjs "^1.23.0" + +"@wangeditor/core@^1.1.19": + version "1.1.19" + resolved "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.19.tgz#f9155f7fd92d03cb1982405b3b82e54c31f1c2b0" + integrity sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q== + dependencies: + "@types/event-emitter" "^0.3.3" + event-emitter "^0.3.5" + html-void-elements "^2.0.0" + i18next "^20.4.0" + scroll-into-view-if-needed "^2.2.28" + slate-history "^0.66.0" + +"@wangeditor/editor-for-vue@^5.1.12": + version "5.1.12" + resolved "https://registry.npmjs.org/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz#f7d5f239b39cdfc01d31151488de8443fe6edc64" + integrity sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ== + +"@wangeditor/editor@^5.1.23": + version "5.1.23" + resolved "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.23.tgz#c9d2007b7cb0ceef6b72692b4ee87b01ee2367b3" + integrity sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ== + dependencies: + "@uppy/core" "^2.1.1" + "@uppy/xhr-upload" "^2.0.3" + "@wangeditor/basic-modules" "^1.1.7" + "@wangeditor/code-highlight" "^1.0.3" + "@wangeditor/core" "^1.1.19" + "@wangeditor/list-module" "^1.0.5" + "@wangeditor/table-module" "^1.1.4" + "@wangeditor/upload-image-module" "^1.0.2" + "@wangeditor/video-module" "^1.1.4" + dom7 "^3.0.0" + is-hotkey "^0.2.0" + lodash.camelcase "^4.3.0" + lodash.clonedeep "^4.5.0" + lodash.debounce "^4.0.8" + lodash.foreach "^4.5.0" + lodash.isequal "^4.5.0" + lodash.throttle "^4.1.1" + lodash.toarray "^4.4.0" + nanoid "^3.2.0" + slate "^0.72.0" + snabbdom "^3.1.0" + +"@wangeditor/list-module@^1.0.5": + version "1.0.5" + resolved "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.5.tgz#3fc0b167acddf885536b45fa0c127f9c6adaea33" + integrity sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ== + +"@wangeditor/table-module@^1.1.4": + version "1.1.4" + resolved "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.4.tgz#757d4a5868b2b658041cd323854a4d707c8347e9" + integrity sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w== + +"@wangeditor/upload-image-module@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz#89e9b9467e10cbc6b11dc5748e08dd23aaebee30" + integrity sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA== + +"@wangeditor/video-module@^1.1.4": + version "1.1.4" + resolved "https://registry.npmjs.org/@wangeditor/video-module/-/video-module-1.1.4.tgz#b9df1b3ab2cd53f678b19b4d927e200774a6f532" + integrity sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg== + +acorn@^8.14.0: + version "8.14.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +async-validator@^4.2.5: + version "4.2.5" + resolved "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339" + integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.7.2: + version "1.9.0" + resolved "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz#25534e3b72b54540077d33046f77e3b8d7081901" + integrity sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +compute-scroll-into-view@^1.0.20: + version "1.0.20" + resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz#1768b5522d1172754f5d0c9b02de3af6be506a43" + integrity sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.1: + version "0.2.2" + resolved "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +csstype@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + dependencies: + es5-ext "^0.10.64" + type "^2.7.2" + +dayjs@^1.11.13: + version "1.11.13" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + +debug@^4.3.7: + version "4.4.1" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + +dom7@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz#b861ce5d67a6becd7aaa3ad02942ff14b1240331" + integrity sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g== + dependencies: + ssr-window "^3.0.0-alpha.1" + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +element-plus@^2.7.6: + version "2.9.11" + resolved "https://registry.npmjs.org/element-plus/-/element-plus-2.9.11.tgz#c939a8d945330f596b7a35aae0e501ea170874a2" + integrity sha512-x4L/6YC8de4JtuE3vpaEugJdQIeHQaHtIYKyk67IeF6dTIiVax45aX4nWOygnh+xX+0gTvL6xO+9BZhPA3G82w== + dependencies: + "@ctrl/tinycolor" "^3.4.1" + "@element-plus/icons-vue" "^2.3.1" + "@floating-ui/dom" "^1.0.1" + "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7" + "@types/lodash" "^4.14.182" + "@types/lodash-es" "^4.17.6" + "@vueuse/core" "^9.1.0" + async-validator "^4.2.5" + dayjs "^1.11.13" + escape-html "^1.0.3" + lodash "^4.17.21" + lodash-es "^4.17.21" + lodash-unified "^1.0.2" + memoize-one "^6.0.0" + normalize-wheel-es "^1.2.0" + +entities@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-module-lexer@^1.3.0: + version "1.7.0" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + dependencies: + d "^1.0.2" + ext "^1.7.0" + +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +exsolve@^1.0.1: + version "1.0.5" + resolved "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz#1f5b6b4fe82ad6b28a173ccb955a635d77859dcf" + integrity sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg== + +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +fast-glob@^3.3.2, fast-glob@^3.3.3: + version "3.3.3" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + +form-data@^4.0.0: + version "4.0.2" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" + integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + mime-types "^2.1.12" + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +html-void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" + integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== + +i18next@^20.4.0: + version "20.6.1" + resolved "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz#535e5f6e5baeb685c7d25df70db63bf3cc0aa345" + integrity sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A== + dependencies: + "@babel/runtime" "^7.12.0" + +immer@^9.0.6: + version "9.0.21" + resolved "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== + +immutable@^5.0.2: + version "5.1.2" + resolved "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz#e8169476414505e5a4fa650107b65e1227d16d4b" + integrity sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hotkey@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz#1835a68171a91e5c9460869d96336947c8340cef" + integrity sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +js-tokens@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" + integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== + +local-pkg@^0.5.0, local-pkg@^0.5.1: + version "0.5.1" + resolved "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz#69658638d2a95287534d4c2fff757980100dbb6d" + integrity sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ== + dependencies: + mlly "^1.7.3" + pkg-types "^1.2.1" + +local-pkg@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz#f5fe74a97a3bd3c165788ee08ca9fbe998dc58dd" + integrity sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg== + dependencies: + mlly "^1.7.4" + pkg-types "^2.0.1" + quansync "^0.2.8" + +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash-unified@^1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz#80b1eac10ed2eb02ed189f08614a29c27d07c894" + integrity sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" + integrity sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +magic-string@^0.30.1, magic-string@^0.30.10, magic-string@^0.30.14, magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.5, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-match@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz#3f87c31e9af1a5fd485fb9db134428b23bbb7ba8" + integrity sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg== + dependencies: + wildcard "^1.1.0" + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@^9.0.4, minimatch@^9.0.5: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +mlly@^1.7.3, mlly@^1.7.4: + version "1.7.4" + resolved "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz#3d7295ea2358ec7a271eaa5d000a0f84febe100f" + integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== + dependencies: + acorn "^8.14.0" + pathe "^2.0.1" + pkg-types "^1.3.0" + ufo "^1.5.4" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +namespace-emitter@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz#978d51361c61313b4e6b8cf6f3853d08dfa2b17c" + integrity sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g== + +nanoid@^3.1.25, nanoid@^3.2.0, nanoid@^3.3.8: + version "3.3.11" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-wheel-es@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz#0fa2593d619f7245a541652619105ab076acf09e" + integrity sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw== + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +pkg-types@^1.2.1, pkg-types@^1.3.0: + version "1.3.1" + resolved "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.0.1: + version "2.1.0" + resolved "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz#70c9e1b9c74b63fdde749876ee0aa007ea9edead" + integrity sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A== + dependencies: + confbox "^0.2.1" + exsolve "^1.0.1" + pathe "^2.0.3" + +postcss@^8.4.43, postcss@^8.5.3: + version "8.5.3" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== + dependencies: + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +preact@^10.5.13: + version "10.26.7" + resolved "https://registry.npmjs.org/preact/-/preact-10.26.7.tgz#7b4b2620dfbbd9d4654d88f1b3cee0fb9dea6e80" + integrity sha512-43xS+QYc1X1IPbw03faSgY6I6OYWcLrJRv3hU0+qMOfh/XCHcP0MX2CVjNARYR2cC/guu975sta4OcjlczxD7g== + +prismjs@^1.23.0: + version "1.30.0" + resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9" + integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +quansync@^0.2.8: + version "0.2.10" + resolved "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" + integrity sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rollup@^4.20.0: + version "4.41.1" + resolved "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz#46ddc1b33cf1b0baa99320d3b0b4973dc2253b6a" + integrity sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw== + dependencies: + "@types/estree" "1.0.7" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.41.1" + "@rollup/rollup-android-arm64" "4.41.1" + "@rollup/rollup-darwin-arm64" "4.41.1" + "@rollup/rollup-darwin-x64" "4.41.1" + "@rollup/rollup-freebsd-arm64" "4.41.1" + "@rollup/rollup-freebsd-x64" "4.41.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.41.1" + "@rollup/rollup-linux-arm-musleabihf" "4.41.1" + "@rollup/rollup-linux-arm64-gnu" "4.41.1" + "@rollup/rollup-linux-arm64-musl" "4.41.1" + "@rollup/rollup-linux-loongarch64-gnu" "4.41.1" + "@rollup/rollup-linux-powerpc64le-gnu" "4.41.1" + "@rollup/rollup-linux-riscv64-gnu" "4.41.1" + "@rollup/rollup-linux-riscv64-musl" "4.41.1" + "@rollup/rollup-linux-s390x-gnu" "4.41.1" + "@rollup/rollup-linux-x64-gnu" "4.41.1" + "@rollup/rollup-linux-x64-musl" "4.41.1" + "@rollup/rollup-win32-arm64-msvc" "4.41.1" + "@rollup/rollup-win32-ia32-msvc" "4.41.1" + "@rollup/rollup-win32-x64-msvc" "4.41.1" + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +sass@^1.89.0: + version "1.89.0" + resolved "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz#6df72360c5c3ec2a9833c49adafe57b28206752d" + integrity sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ== + dependencies: + chokidar "^4.0.0" + immutable "^5.0.2" + source-map-js ">=0.6.2 <2.0.0" + optionalDependencies: + "@parcel/watcher" "^2.4.1" + +scroll-into-view-if-needed@^2.2.28: + version "2.2.31" + resolved "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz#d3c482959dc483e37962d1521254e3295d0d1587" + integrity sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA== + dependencies: + compute-scroll-into-view "^1.0.20" + +scule@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz#6efbd22fd0bb801bdcc585c89266a7d2daa8fbd3" + integrity sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g== + +slate-history@^0.66.0: + version "0.66.0" + resolved "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz#ac63fddb903098ceb4c944433e3f75fe63acf940" + integrity sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng== + dependencies: + is-plain-object "^5.0.0" + +slate@^0.72.0: + version "0.72.8" + resolved "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz#5a018edf24e45448655293a68bfbcf563aa5ba81" + integrity sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw== + dependencies: + immer "^9.0.6" + is-plain-object "^5.0.0" + tiny-warning "^1.0.3" + +snabbdom@^3.1.0: + version "3.6.2" + resolved "https://registry.npmjs.org/snabbdom/-/snabbdom-3.6.2.tgz#57dd66878f6320497fa7f67941df356a045c75a1" + integrity sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q== + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +ssr-window@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz#fd5b82801638943e0cc704c4691801435af7ac37" + integrity sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA== + +strip-literal@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz#26906e65f606d49f748454a08084e94190c2e5ad" + integrity sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q== + dependencies: + js-tokens "^9.0.1" + +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +type@^2.7.2: + version "2.7.3" + resolved "https://registry.npmjs.org/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + +ufo@^1.5.4: + version "1.6.1" + resolved "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +unimport@^3.7.2: + version "3.14.6" + resolved "https://registry.npmjs.org/unimport/-/unimport-3.14.6.tgz#f01170aa2fb94c4f97b22c0ac2822ef7e8e0726d" + integrity sha512-CYvbDaTT04Rh8bmD8jz3WPmHYZRG/NnvYVzwD6V1YAlvvKROlAeNDUBhkBGzNav2RKaeuXvlWYaa1V4Lfi/O0g== + dependencies: + "@rollup/pluginutils" "^5.1.4" + acorn "^8.14.0" + escape-string-regexp "^5.0.0" + estree-walker "^3.0.3" + fast-glob "^3.3.3" + local-pkg "^1.0.0" + magic-string "^0.30.17" + mlly "^1.7.4" + pathe "^2.0.1" + picomatch "^4.0.2" + pkg-types "^1.3.0" + scule "^1.3.0" + strip-literal "^2.1.1" + unplugin "^1.16.1" + +unplugin-auto-import@^0.17.6: + version "0.17.8" + resolved "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.17.8.tgz#8dd5d1f21700171242553f1a476bd43ffad74af6" + integrity sha512-CHryj6HzJ+n4ASjzwHruD8arhbdl+UXvhuAIlHDs15Y/IMecG3wrf7FVg4pVH/DIysbq/n0phIjNHAjl7TG7Iw== + dependencies: + "@antfu/utils" "^0.7.10" + "@rollup/pluginutils" "^5.1.0" + fast-glob "^3.3.2" + local-pkg "^0.5.0" + magic-string "^0.30.10" + minimatch "^9.0.4" + unimport "^3.7.2" + unplugin "^1.11.0" + +unplugin-element-plus@^0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/unplugin-element-plus/-/unplugin-element-plus-0.8.0.tgz#320c8b43a87fe6d680b9117656476f597bccf700" + integrity sha512-jByUGY3FG2B8RJKFryqxx4eNtSTj+Hjlo8edcOdJymewndDQjThZ1pRUQHRjQsbKhTV2jEctJV7t7RJ405UL4g== + dependencies: + "@rollup/pluginutils" "^5.0.2" + es-module-lexer "^1.3.0" + magic-string "^0.30.1" + unplugin "^1.3.2" + +unplugin-vue-components@^0.27.2: + version "0.27.5" + resolved "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.27.5.tgz#81b8460c5183146c084c09fae5ec9db7afd45c4b" + integrity sha512-m9j4goBeNwXyNN8oZHHxvIIYiG8FQ9UfmKWeNllpDvhU7btKNNELGPt+o3mckQKuPwrE7e0PvCsx+IWuDSD9Vg== + dependencies: + "@antfu/utils" "^0.7.10" + "@rollup/pluginutils" "^5.1.3" + chokidar "^3.6.0" + debug "^4.3.7" + fast-glob "^3.3.2" + local-pkg "^0.5.1" + magic-string "^0.30.14" + minimatch "^9.0.5" + mlly "^1.7.3" + unplugin "^1.16.0" + +unplugin@^1.11.0, unplugin@^1.16.0, unplugin@^1.16.1, unplugin@^1.3.2: + version "1.16.1" + resolved "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz#a844d2e3c3b14a4ac2945c42be80409321b61199" + integrity sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w== + dependencies: + acorn "^8.14.0" + webpack-virtual-modules "^0.6.2" + +vite@^5.3.1: + version "5.4.19" + resolved "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz#20efd060410044b3ed555049418a5e7d1998f959" + integrity sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.43" + rollup "^4.20.0" + optionalDependencies: + fsevents "~2.3.3" + +vue-demi@*: + version "0.14.10" + resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04" + integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg== + +vue-router@^4.3.3: + version "4.5.1" + resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz#47bffe2d3a5479d2886a9a244547a853aa0abf69" + integrity sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw== + dependencies: + "@vue/devtools-api" "^6.6.4" + +vue@^3.4.29: + version "3.5.15" + resolved "https://registry.npmjs.org/vue/-/vue-3.5.15.tgz#5896569a33a1bcafd764c6b27e4e6f8cb55f4bee" + integrity sha512-aD9zK4rB43JAMK/5BmS4LdPiEp8Fdh8P1Ve/XNuMF5YRf78fCyPE6FUbQwcaWQ5oZ1R2CD9NKE0FFOVpMR7gEQ== + dependencies: + "@vue/compiler-dom" "3.5.15" + "@vue/compiler-sfc" "3.5.15" + "@vue/runtime-dom" "3.5.15" + "@vue/server-renderer" "3.5.15" + "@vue/shared" "3.5.15" + +webpack-virtual-modules@^0.6.2: + version "0.6.2" + resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" + integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== + +wildcard@^1.1.0: + version "1.1.2" + resolved "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz#a7020453084d8cd2efe70ba9d3696263de1710a5" + integrity sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==