Merge remote-tracking branch 'yudao/feature/sub-table' into feature/sub-table

# Conflicts:
#	sql/mysql/ruoyi-vue-pro.sql
This commit is contained in:
puhui999 2023-11-20 09:57:24 +08:00
commit 737ea4635c
147 changed files with 8930 additions and 1957 deletions

View File

@ -11,7 +11,7 @@
Target Server Version : 80034
File Encoding : 65001
Date: 04/11/2023 20:42:49
Date: 18/11/2023 17:48:18
*/
SET NAMES utf8mb4;
@ -385,7 +385,7 @@ CREATE TABLE `infra_api_error_log` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1781 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
) ENGINE = InnoDB AUTO_INCREMENT = 1964 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
-- ----------------------------
-- Records of infra_api_error_log
@ -423,7 +423,7 @@ CREATE TABLE `infra_codegen_column` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1804 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
) ENGINE = InnoDB AUTO_INCREMENT = 1905 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
-- ----------------------------
-- Records of infra_codegen_column
@ -451,7 +451,7 @@ CREATE TABLE `infra_codegen_table` (
`front_type` tinyint NOT NULL COMMENT '前端类型',
`parent_menu_id` bigint NULL DEFAULT NULL COMMENT '父菜单编号',
`master_table_id` bigint NULL DEFAULT NULL COMMENT '主表的编号',
`sub_join_column_id` bigint NULL DEFAULT NULL COMMENT '自己子表关联主表的字段编号',
`sub_join_column_id` bigint NULL DEFAULT NULL COMMENT '子表关联主表的字段编号',
`sub_join_many` bit(1) NULL DEFAULT NULL COMMENT '主表与子表是否一对多',
`tree_parent_column_id` bigint NULL DEFAULT NULL COMMENT '树表的父字段编号',
`tree_name_column_id` bigint NULL DEFAULT NULL COMMENT '树表的名字字段编号',
@ -461,7 +461,7 @@ CREATE TABLE `infra_codegen_table` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 136 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
) ENGINE = InnoDB AUTO_INCREMENT = 146 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
-- ----------------------------
-- Records of infra_codegen_table
@ -526,6 +526,150 @@ CREATE TABLE `infra_data_source_config` (
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for infra_demo01_contact
-- ----------------------------
DROP TABLE IF EXISTS `infra_demo01_contact`;
CREATE TABLE `infra_demo01_contact` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字',
`sex` tinyint(1) NOT NULL COMMENT '性别',
`birthday` datetime NOT NULL COMMENT '出生年',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '简介',
`avatar` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '头像',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '示例联系人表';
-- ----------------------------
-- Records of infra_demo01_contact
-- ----------------------------
BEGIN;
INSERT INTO `infra_demo01_contact` (`id`, `name`, `sex`, `birthday`, `description`, `avatar`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '土豆', 2, '2023-11-07 00:00:00', '<p>天蚕土豆</p>', 'http://127.0.0.1:48080/admin-api/infra/file/4/get/46f8fa1a37db3f3960d8910ff2fe3962ab3b2db87cf2f8ccb4dc8145b8bdf237.jpeg', '1', '2023-11-15 23:34:30', '1', '2023-11-15 23:47:39', b'0', 1);
COMMIT;
-- ----------------------------
-- Table structure for infra_demo02_category
-- ----------------------------
DROP TABLE IF EXISTS `infra_demo02_category`;
CREATE TABLE `infra_demo02_category` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字',
`parent_id` bigint NOT NULL COMMENT '父级编号',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '示例分类表';
-- ----------------------------
-- Records of infra_demo02_category
-- ----------------------------
BEGIN;
INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '土豆', 0, '1', '2023-11-15 23:34:30', '1', '2023-11-16 20:24:23', b'0', 1);
INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '番茄', 0, '1', '2023-11-16 20:24:00', '1', '2023-11-16 20:24:15', b'0', 1);
INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, '怪怪', 0, '1', '2023-11-16 20:24:32', '1', '2023-11-16 20:24:32', b'0', 1);
INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, '小番茄', 2, '1', '2023-11-16 20:24:39', '1', '2023-11-16 20:24:39', b'0', 1);
INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, '大番茄', 2, '1', '2023-11-16 20:24:46', '1', '2023-11-16 20:24:46', b'0', 1);
COMMIT;
-- ----------------------------
-- Table structure for infra_demo03_course
-- ----------------------------
DROP TABLE IF EXISTS `infra_demo03_course`;
CREATE TABLE `infra_demo03_course` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`student_id` bigint NOT NULL COMMENT '学生编号',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字',
`score` tinyint NOT NULL COMMENT '分数',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '学生课程表';
-- ----------------------------
-- Records of infra_demo03_course
-- ----------------------------
BEGIN;
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 2, '语文', 66, '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', b'0', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, 2, '数学', 22, '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', b'0', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:44:40', b'1', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:44:40', b'1', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (8, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:47:09', b'1', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:47:09', b'1', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', b'0', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (11, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', b'0', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (12, 2, '电脑', 33, '1', '2023-11-17 00:20:42', '1', '2023-11-16 16:20:45', b'1', 1);
INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (13, 9, '滑雪', 12, '1', '2023-11-17 13:13:20', '1', '2023-11-17 13:13:20', b'0', 1);
COMMIT;
-- ----------------------------
-- Table structure for infra_demo03_grade
-- ----------------------------
DROP TABLE IF EXISTS `infra_demo03_grade`;
CREATE TABLE `infra_demo03_grade` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`student_id` bigint NOT NULL COMMENT '学生编号',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字',
`teacher` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '班主任',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '学生班级表';
-- ----------------------------
-- Records of infra_demo03_grade
-- ----------------------------
BEGIN;
INSERT INTO `infra_demo03_grade` (`id`, `student_id`, `name`, `teacher`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 2, '三年 2 ', '周杰伦', '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', b'0', 1);
INSERT INTO `infra_demo03_grade` (`id`, `student_id`, `name`, `teacher`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (8, 5, '华为', '遥遥领先', '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', b'0', 1);
INSERT INTO `infra_demo03_grade` (`id`, `student_id`, `name`, `teacher`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, 9, '小图', '小娃111', '1', '2023-11-17 13:10:23', '1', '2023-11-17 13:10:23', b'0', 1);
COMMIT;
-- ----------------------------
-- Table structure for infra_demo03_student
-- ----------------------------
DROP TABLE IF EXISTS `infra_demo03_student`;
CREATE TABLE `infra_demo03_student` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字',
`sex` tinyint NOT NULL COMMENT '性别',
`birthday` datetime NOT NULL COMMENT '出生日期',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '简介',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '学生表';
-- ----------------------------
-- Records of infra_demo03_student
-- ----------------------------
BEGIN;
INSERT INTO `infra_demo03_student` (`id`, `name`, `sex`, `birthday`, `description`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '小白', 1, '2023-11-16 00:00:00', '<p>厉害</p>', '1', '2023-11-16 23:21:49', '1', '2023-11-17 16:49:06', b'0', 1);
INSERT INTO `infra_demo03_student` (`id`, `name`, `sex`, `birthday`, `description`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, '大黑', 2, '2023-11-13 00:00:00', '<p>你在教我做事?</p>', '1', '2023-11-16 23:22:46', '1', '2023-11-17 16:49:07', b'0', 1);
INSERT INTO `infra_demo03_student` (`id`, `name`, `sex`, `birthday`, `description`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, '小花', 1, '2023-11-07 00:00:00', '<p>哈哈哈</p>', '1', '2023-11-17 00:04:47', '1', '2023-11-17 16:49:08', b'0', 1);
COMMIT;
-- ----------------------------
-- Table structure for infra_file
-- ----------------------------
@ -544,7 +688,7 @@ CREATE TABLE `infra_file` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1108 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
) ENGINE = InnoDB AUTO_INCREMENT = 1128 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
-- ----------------------------
-- Records of infra_file
@ -593,7 +737,7 @@ CREATE TABLE `infra_file_content` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 202 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
) ENGINE = InnoDB AUTO_INCREMENT = 221 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
-- ----------------------------
-- Records of infra_file_content
@ -670,31 +814,6 @@ CREATE TABLE `infra_job_log` (
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for infra_test_demo
-- ----------------------------
DROP TABLE IF EXISTS `infra_test_demo`;
CREATE TABLE `infra_test_demo` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '状态',
`type` tinyint NOT NULL COMMENT '类型',
`category` tinyint NOT NULL COMMENT '分类',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
-- ----------------------------
-- Records of infra_test_demo
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for member_address
-- ----------------------------
@ -1136,7 +1255,7 @@ CREATE TABLE `system_dept` (
-- Records of system_dept
-- ----------------------------
BEGIN;
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, '芋道源码', 0, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-06-19 00:29:10', b'0', 1);
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, '芋道源码', 0, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2023-11-14 23:30:36', b'0', 1);
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (101, '深圳总公司', 100, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-05-16 20:25:23', b'0', 1);
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (102, '长沙分公司', 100, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:40', b'0', 1);
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, '研发部门', 101, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-14 01:04:14', b'0', 1);
@ -1170,14 +1289,14 @@ CREATE TABLE `system_dict_data` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1435 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
) ENGINE = InnoDB AUTO_INCREMENT = 1447 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表';
-- ----------------------------
-- Records of system_dict_data
-- ----------------------------
BEGIN;
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 1, '男', '1', 'system_user_sex', 0, 'default', 'A', '性别男', 'admin', '2021-01-05 17:03:48', '1', '2022-03-29 00:14:39', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 2, '女', '2', 'system_user_sex', 1, 'success', '', '性别女', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 01:30:51', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 2, '女', '2', 'system_user_sex', 0, 'success', '', '性别女', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 23:30:37', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 1, '正常', '1', 'infra_job_status', 0, 'success', '', '正常状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:33:38', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (9, 2, '暂停', '2', 'infra_job_status', 0, 'danger', '', '停用状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:33:45', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (12, 1, '系统内置', '1', 'infra_config_type', 0, 'danger', '', '参数类型 - 系统内置', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:06:02', b'0');
@ -1479,6 +1598,12 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1438, 31, '微信公众平台', '31', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:18', '1', '2023-11-04 13:05:18', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1439, 32, '微信开放平台', '32', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:30', '1', '2023-11-04 13:05:30', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1440, 34, '微信小程序', '34', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:38', '1', '2023-11-04 13:07:16', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1441, 1, '上架', '1', 'crm_product_status', 0, 'success', '', '', '1', '2023-10-30 21:49:34', '1', '2023-10-30 21:49:34', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1442, 0, '下架', '0', 'crm_product_status', 0, 'success', '', '', '1', '2023-10-30 21:49:13', '1', '2023-10-30 21:49:13', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1443, 15, '子表', '15', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-13 23:06:16', '1', '2023-11-13 23:06:16', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1444, 10, '主表标准模式', '10', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-14 12:32:49', '1', '2023-11-14 12:32:49', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1445, 11, '主表ERP 模式', '11', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-14 12:33:05', '1', '2023-11-14 12:33:05', b'0');
INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1446, 12, '主表内嵌模式', '12', 'infra_codegen_template_type', 0, '', '', '', '1', '2023-11-14 12:33:31', '1', '2023-11-14 12:33:31', b'0');
COMMIT;
-- ----------------------------
@ -1499,7 +1624,7 @@ CREATE TABLE `system_dict_type` (
`deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 600 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
) ENGINE = InnoDB AUTO_INCREMENT = 605 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
-- ----------------------------
-- Records of system_dict_type
@ -1578,6 +1703,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (188, '客户来源', 'crm_customer_source', 0, 'CRM 客户来源', '1', '2023-10-28 23:00:34', '1', '2023-10-28 15:11:16', b'0', NULL);
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (600, 'Banner 位置', 'promotion_banner_position', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-11-04 13:04:02', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (601, '社交类型', 'system_social_type', 0, '', '1', '2023-11-04 13:03:54', '1', '2023-11-04 13:03:54', b'0', '1970-01-01 00:00:00');
INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (604, '产品状态', 'crm_product_status', 0, '', '1', '2023-10-30 21:47:59', '1', '2023-10-30 21:48:45', b'0', '1970-01-01 00:00:00');
COMMIT;
-- ----------------------------
@ -1626,7 +1752,7 @@ CREATE TABLE `system_login_log` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2631 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
) ENGINE = InnoDB AUTO_INCREMENT = 2647 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
-- ----------------------------
-- Records of system_login_log
@ -1756,7 +1882,7 @@ CREATE TABLE `system_menu` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2449 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
) ENGINE = InnoDB AUTO_INCREMENT = 2504 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表';
-- ----------------------------
-- Records of system_menu
@ -1844,11 +1970,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1065, '设置用户角色', 'system:permission:assign-user-role', 3, 8, 101, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-07 10:23:28', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1066, '获得 Redis 监控信息', 'infra:redis:get-monitor-info', 3, 1, 113, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-26 01:02:31', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1067, '获得 Redis Key 列表', 'infra:redis:get-key-list', 3, 2, 113, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-26 01:02:52', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1070, '代码生成示例', 'infra:test-demo:query', 2, 1, 2, 'test-demo', 'validCode', 'infra/testDemo/index', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1071, '测试示例表创建', 'infra:test-demo:create', 3, 1, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1072, '测试示例表更新', 'infra:test-demo:update', 3, 2, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1073, '测试示例表删除', 'infra:test-demo:delete', 3, 3, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1074, '测试示例表导出', 'infra:test-demo:export', 3, 4, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1070, '代码生成案例', '', 1, 1, 2, 'demo', 'ep:aim', 'infra/testDemo/index', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2023-11-15 23:45:53', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1075, '任务触发', 'infra:job:trigger', 3, 8, 110, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-07 13:03:10', '', '2022-04-20 17:03:10', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1076, '数据库文档', '', 2, 4, 2, 'db-doc', 'table', 'infra/dbDoc/index', 'InfraDBDoc', 0, b'1', b'1', b'1', '', '2021-02-08 01:41:47', '1', '2023-04-08 09:13:38', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1077, '监控平台', '', 2, 13, 2, 'skywalking', 'eye-open', 'infra/skywalking/index', 'InfraSkyWalking', 0, b'1', b'1', b'1', '', '2021-02-08 20:41:31', '1', '2023-04-08 10:39:06', b'0');
@ -2315,6 +2437,26 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2451, '三方应用更新', 'system:social-client:update', 3, 3, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:44:27', '1', '2023-11-04 12:44:27', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2452, '三方应用删除', 'system:social-client:delete', 3, 4, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:44:43', '1', '2023-11-04 12:44:43', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2453, '三方用户', 'system:social-user:query', 2, 2, 2447, 'user', 'ep:avatar', 'system/social/user/index.vue', 'SocialUser', 0, b'1', b'1', b'1', '1', '2023-11-04 14:01:05', '1', '2023-11-04 14:01:05', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2472, '主子表内嵌', '', 2, 12, 1070, 'demo03-inner', 'fa:power-off', 'infra/demo/demo03/inner/index', 'Demo03StudentInner', 0, b'1', b'1', b'1', '', '2023-11-13 04:39:51', '1', '2023-11-16 23:53:46', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2478, '单表增删改查', '', 2, 1, 1070, 'demo01-contact', 'ep:bicycle', 'infra/demo/demo01/index', 'Demo01Contact', 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '1', '2023-11-16 20:34:40', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2479, '示例联系人查询', 'infra:demo01-contact:query', 3, 1, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2480, '示例联系人创建', 'infra:demo01-contact:create', 3, 2, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2481, '示例联系人更新', 'infra:demo01-contact:update', 3, 3, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2482, '示例联系人删除', 'infra:demo01-contact:delete', 3, 4, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2483, '示例联系人导出', 'infra:demo01-contact:export', 3, 5, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2484, '树表增删改查', '', 2, 2, 1070, 'demo02-category', 'fa:tree', 'infra/demo/demo02/index', 'Demo02Category', 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '1', '2023-11-16 20:35:01', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2485, '示例分类查询', 'infra:demo02-category:query', 3, 1, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2486, '示例分类创建', 'infra:demo02-category:create', 3, 2, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2487, '示例分类更新', 'infra:demo02-category:update', 3, 3, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2488, '示例分类删除', 'infra:demo02-category:delete', 3, 4, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2489, '示例分类导出', 'infra:demo02-category:export', 3, 5, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2490, '主子表标准', '', 2, 10, 1070, 'demo03-normal', 'fa:battery-3', 'infra/demo/demo03/normal/index', 'Demo03StudentNormal', 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '1', '2023-11-16 23:10:03', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2491, '学生查询', 'infra:demo03-student:query', 3, 1, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2492, '学生创建', 'infra:demo03-student:create', 3, 2, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2493, '学生更新', 'infra:demo03-student:update', 3, 3, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2494, '学生删除', 'infra:demo03-student:delete', 3, 4, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2495, '学生导出', 'infra:demo03-student:export', 3, 5, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0');
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2497, '主子表ERP', '', 2, 11, 1070, 'demo03-erp', 'ep:calendar', 'infra/demo/demo03/erp/index', 'Demo03StudentERP', 0, b'1', b'1', b'1', '', '2023-11-16 15:50:59', '1', '2023-11-17 13:19:56', b'0');
COMMIT;
-- ----------------------------
@ -2341,7 +2483,7 @@ CREATE TABLE `system_notice` (
-- ----------------------------
BEGIN;
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '芋道的公众', '<p>新版本内容133</p>', 1, 0, 'admin', '2021-01-05 17:03:48', '1', '2022-05-04 21:00:20', b'0', 1);
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '维护通知2018-07-01 若依系统凌晨维护', '<p><img src=\"http://test.yudao.iocoder.cn/b7cb3cf49b4b3258bf7309a09dd2f4e5.jpg\">维护内容</p>', 2, 1, 'admin', '2021-01-05 17:03:48', '1', '2022-05-11 12:34:24', b'0', 1);
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '维护通知2018-07-01 若依系统凌晨维护', '<p><img src=\"http://test.yudao.iocoder.cn/b7cb3cf49b4b3258bf7309a09dd2f4e5.jpg\" alt=\"\" data-href=\"\" style=\"\"/>1111</p>', 2, 1, 'admin', '2021-01-05 17:03:48', '1', '2023-11-11 12:51:11', b'0', 1);
INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, '我是测试标题', '<p>哈哈哈哈123</p>', 1, 0, '110', '2022-02-22 01:01:25', '110', '2022-02-22 01:01:46', b'0', 121);
COMMIT;
@ -2435,7 +2577,7 @@ CREATE TABLE `system_oauth2_access_token` (
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_access_token`(`access_token` ASC) USING BTREE,
INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3152 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
) ENGINE = InnoDB AUTO_INCREMENT = 3467 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
-- ----------------------------
-- Records of system_oauth2_access_token
@ -2557,7 +2699,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1099 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
) ENGINE = InnoDB AUTO_INCREMENT = 1115 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌';
-- ----------------------------
-- Records of system_oauth2_refresh_token
@ -2597,7 +2739,7 @@ CREATE TABLE `system_operate_log` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8845 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
) ENGINE = InnoDB AUTO_INCREMENT = 9090 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
-- ----------------------------
-- Records of system_operate_log
@ -2623,15 +2765,15 @@ CREATE TABLE `system_post` (
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表';
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表';
-- ----------------------------
-- Records of system_post
-- ----------------------------
BEGIN;
INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'ceo', '董事长', 1, 0, '', 'admin', '2021-01-06 17:03:48', '1', '2023-02-11 15:19:04', b'0', 1);
INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-12-12 10:47:47', b'0', 1);
INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 'user', '普通员工', 4, 0, '111', 'admin', '2021-01-05 17:03:48', '1', '2023-02-11 15:19:00', b'0', 1);
INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 09:18:20', b'0', 1);
INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 'user', '普通员工', 4, 0, '111', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 09:18:18', b'0', 1);
COMMIT;
-- ----------------------------
@ -2824,10 +2966,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1657, 101, 1066, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1658, 101, 1067, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1659, 101, 1070, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1660, 101, 1071, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1661, 101, 1072, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1662, 101, 1073, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1663, 101, 1074, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1664, 101, 1075, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1665, 101, 1076, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1666, 101, 1077, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1);
@ -3145,10 +3283,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2027, 2, 1066, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2028, 2, 1067, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2029, 2, 1070, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2030, 2, 1071, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2031, 2, 1072, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2032, 2, 1073, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2033, 2, 1074, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2034, 2, 1075, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2035, 2, 1076, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2036, 2, 1082, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1);
@ -3648,7 +3782,7 @@ CREATE TABLE `system_sms_log` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 503 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
) ENGINE = InnoDB AUTO_INCREMENT = 502 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
-- ----------------------------
-- Records of system_sms_log
@ -3678,7 +3812,7 @@ CREATE TABLE `system_sms_template` (
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信模板';
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信模板';
-- ----------------------------
-- Records of system_sms_template
@ -3808,9 +3942,9 @@ CREATE TABLE `system_tenant` (
-- Records of system_tenant
-- ----------------------------
BEGIN;
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'https://www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2022-02-23 12:15:11', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'http://www.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-09-16 16:59:42', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'https://www.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-09-16 16:59:27', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-11-06 11:41:47', b'0');
INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-11-06 11:41:53', b'0');
COMMIT;
-- ----------------------------
@ -3949,7 +4083,7 @@ CREATE TABLE `system_users` (
-- Records of system_users
-- ----------------------------
BEGIN;
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2023-11-04 10:33:16', 'admin', '2021-01-05 17:03:47', NULL, '2023-11-04 10:33:16', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2023-11-18 17:19:30', 'admin', '2021-01-05 17:03:47', NULL, '2023-11-18 17:19:30', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', b'0', 1);
INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2023-09-24 18:21:19', '', '2021-01-21 02:13:53', NULL, '2023-09-24 18:21:19', b'0', 1);

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.json;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
@ -30,6 +31,7 @@ public class JsonUtils {
static {
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null
objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
}
@ -71,6 +73,20 @@ public class JsonUtils {
}
}
public static <T> T parseObject(String text, String path, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
return null;
}
try {
JsonNode treeNode = objectMapper.readTree(text);
JsonNode pathNode = treeNode.path(path);
return objectMapper.readValue(pathNode.toString(), clazz);
} catch (IOException e) {
log.error("json parse err,json:{}", text, e);
throw new RuntimeException(e);
}
}
public static <T> T parseObject(String text, Type type) {
if (StrUtil.isEmpty(text)) {
return null;
@ -132,6 +148,20 @@ public class JsonUtils {
}
}
public static <T> List<T> parseArray(String text, String path, Class<T> clazz) {
if (StrUtil.isEmpty(text)) {
return null;
}
try {
JsonNode treeNode = objectMapper.readTree(text);
JsonNode pathNode = treeNode.path(path);
return objectMapper.readValue(pathNode.toString(), objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
} catch (IOException e) {
log.error("json parse err,json:{}", text, e);
throw new RuntimeException(e);
}
}
public static JsonNode parseTree(String text) {
try {
return objectMapper.readTree(text);

View File

@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.google.common.collect.Sets;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.*;
import static cn.hutool.core.text.CharSequenceUtil.*;
@ -127,6 +128,10 @@ public class CodegenBuilder {
for (CodegenColumnDO column : columns) {
column.setTableId(tableId);
column.setOrdinalPosition(index++);
// 特殊处理Byte => Integer
if (Byte.class.getSimpleName().equals(column.getJavaType())) {
column.setJavaType(Integer.class.getSimpleName());
}
// 初始化 Column 列的默认字段
processColumnOperation(column); // 处理 CRUD 相关的字段的默认值
processColumnUI(column); // 处理 UI 相关的字段的默认值
@ -162,10 +167,13 @@ public class CodegenBuilder {
.filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey()))
.findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType()));
// 如果是 Boolean 类型时设置为 radio 类型.
// 其它类型因为字段名可以相对保障所以不进行处理例如说 date 对应 datetime 类型.
if (Boolean.class.getSimpleName().equals(column.getJavaType())) {
column.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType());
}
// 如果是 LocalDateTime 类型则设置为 datetime 类型
if (LocalDateTime.class.getSimpleName().equals(column.getJavaType())) {
column.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
}
// 兜底设置默认为 input 类型
if (column.getHtmlType() == null) {
column.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());

View File

@ -101,7 +101,7 @@ public class CodegenEngine {
private static final Table<Integer, String, String> FRONT_TEMPLATES = ImmutableTable.<Integer, String, String>builder()
// Vue2 标准模版
.put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/index.vue"),
vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
vueFilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
.put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("api/api.js"),
vueFilePath("api/${table.moduleName}/${classNameVar}.js"))
// Vue3 标准模版
@ -123,22 +123,22 @@ public class CodegenEngine {
vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
// Vue3 Schema 模版
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts"))
vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts"))
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/index.vue"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/form.vue"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue"))
vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue"))
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("api/api.ts"),
vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts"))
vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
// Vue3 vben 模版
.put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/data.ts"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts"))
vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts"))
.put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/index.vue"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
.put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/form.vue"),
vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Modal.vue"))
vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue"))
.put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("api/api.ts"),
vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts"))
vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
.build();
@Resource

View File

@ -49,13 +49,14 @@ public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
#end
## 特殊:主子表专属逻辑(非 ERP 模式)
#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 )
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#if ( $subTable.subJoinMany)
@Schema(description = "${subTable.classComment}列表")
private List<${subTable.className}DO> ${subClassNameVars.get($index)}s;
#else
@Schema(description = "${subTable.classComment}")
private ${subTable.className}DO ${subClassNameVars.get($index)};
#end

View File

@ -8,7 +8,7 @@
</Dialog>
</template>
<script setup lang="ts">
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
import { rules, allSchemas } from './${classNameVar}.data'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@ -54,7 +54,7 @@
</template>
<script setup lang="ts" name="${table.className}">
import { allSchemas } from './${classNameVar}.data'
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
import ${simpleClassName}Form from './${simpleClassName}Form.vue'
// tableObject表格的属性对象可获得分页大小、条数等属性

View File

@ -5,7 +5,7 @@ import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { BasicForm, useForm } from '@/components/Form'
import { BasicModal, useModalInner } from '@/components/Modal'
import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '@/api/${table.moduleName}/${classNameVar}'
import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
defineOptions({ name: '${table.className}Modal' })

View File

@ -5,7 +5,7 @@ import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { useModal } from '@/components/Modal'
import { useTable } from '@/components/Table'
import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page } from '@/api/${table.moduleName}/${classNameVar}'
import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page } from '@/api/${table.moduleName}/${table.businessName}'
defineOptions({ name: '${table.className}' })

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO;
import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class SchemaColumnMapperTest extends BaseDbUnitTest {
@Resource
private SchemaColumnMapper schemaColumnMapper;
@Test
public void testSelectListByTableName() {
List<SchemaColumnDO> columns = schemaColumnMapper.selectListByTableName("", "inf_config");
assertTrue(columns.size() > 0);
}
}

View File

@ -1,4 +0,0 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.infra.dal.mysql;

View File

@ -1,4 +0,0 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.infra.dal;

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.infra.service.codegen;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
public class CodegenEngineTest extends BaseDbUnitTest {
@Resource
private CodegenTableMapper codegenTableMapper;
@Resource
private CodegenColumnMapper codegenColumnMapper;
@Resource
private CodegenEngine codegenEngine;
@Test
public void testExecute() {
CodegenTableDO table = codegenTableMapper.selectById(20);
List<CodegenColumnDO> columns = codegenColumnMapper.selectListByTableId(table.getId());
Map<String, String> result = codegenEngine.execute(table, columns);
result.forEach((s, s2) -> System.out.println(s2));
// System.out.println(result.get("vue/views/system/test/index.vue"));
}
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.yudao.module.infra.service.codegen;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser;
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
public class CodegenSQLParserTest extends BaseDbUnitTest {
@Test
public void testParse() {
String sql = "CREATE TABLE `infra_test_demo` (\n" +
" `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',\n" +
" `name` varchar(100) NOT NULL DEFAULT '' COMMENT '名字',\n" +
" `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态',\n" +
" `type` tinyint(4) NOT NULL COMMENT '类型',\n" +
" `category` tinyint(4) NOT NULL COMMENT '分类',\n" +
" `remark` varchar(500) DEFAULT NULL COMMENT '备注',\n" +
" `create_by` varchar(64) DEFAULT '' COMMENT '创建者',\n" +
" `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" +
" `update_by` varchar(64) DEFAULT '' COMMENT '更新者',\n" +
" `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n" +
" `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',\n" +
" PRIMARY KEY (`id`) USING BTREE\n" +
") ENGINE=InnoDB AUTO_INCREMENT=108 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';";
CodegenSQLParser.parse(sql);
// TODO 芋艿后续完善断言
}
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.infra.service.codegen;
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
class CodegenServiceImplTest extends BaseDbUnitTest {
@Resource
private CodegenServiceImpl codegenService;
@Test
public void tetCreateCodegenTable() {
codegenService.createCodegen(0L, "infra_test_demo");
// infraCodegenService.createCodegenTable("infra_codegen_table");
// infraCodegenService.createCodegen("infra_codegen_column");
}
}

View File

@ -1,4 +0,0 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.infra.service;

View File

@ -1,38 +0,0 @@
package cn.iocoder.yudao.module.infra.test;
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisIntegrationTest.Application.class)
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
public class BaseDbAndRedisIntegrationTest {
@Import({
// DB 配置类
DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
// MyBatis 配置类
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
// Redis 配置类
RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
public static class Application {
}
}

View File

@ -1,23 +0,0 @@
package cn.iocoder.yudao.module.infra.test;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisIntegrationTest.Application.class)
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
public class BaseRedisIntegrationTest {
@Import({
// Redis 配置类
RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
public static class Application {
}
}

View File

@ -3,7 +3,10 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
@ -17,11 +20,10 @@ import org.mockito.Spy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link CodegenEngine} 的单元测试
@ -42,760 +44,127 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
codegenEngine.initGlobalBindingMap();
}
@Test
public void testExecute_vue3_one() {
// 准备参数
CodegenTableDO table = getTable("student")
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
.setTemplateType(CodegenTemplateTypeEnum.ONE.getType());
List<CodegenColumnDO> columns = getColumnList("student");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
// 断言
assertResult(result, "codegen/vue3_one");
// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one");
}
@Test
public void testExecute_vue3_tree() {
// 准备请求参数
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
.setTableName("infra_demo66_student").setTableComment("学生表")
.setModuleName("infra").setBusinessName("demo66").setClassName("InfraDemo66Student")
.setClassComment("学生").setAuthor("芋道源码")
.setTemplateType(CodegenTemplateTypeEnum.TREE.getType())
// 准备参数
CodegenTableDO table = getTable("category")
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
.setTreeParentColumnId(22L).setTreeNameColumnId(11L);
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setId(11L)
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO parentIdColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setId(22L)
.setColumnComment("父编号").setNullable(false)
.setJavaType("Long").setJavaField("parentId").setExample("2048")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, parentIdColumn);
.setTemplateType(CodegenTemplateTypeEnum.TREE.getType());
List<CodegenColumnDO> columns = getColumnList("category");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
// 构建 zip
writeFile(result, "/Users/yunai/test/demo66.zip");
}
@Test
public void testExecute_vue3_crud() {
// 准备请求参数
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
.setTableName("infra_demo01_student").setTableComment("学生表")
.setModuleName("infra").setBusinessName("demo01").setClassName("InfraDemo01Student")
.setClassComment("学生").setAuthor("芋道源码")
.setTemplateType(CodegenTemplateTypeEnum.ONE.getType())
.setFrontType(CodegenFrontTypeEnum.VUE3.getType());
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("简介").setNullable(false)
.setJavaType("String").setJavaField("description").setExample("我是介绍")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
.setColumnComment("出生日期").setNullable(false)
.setJavaType("LocalDateTime").setJavaField("birthday")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
.setColumnComment("性别").setNullable(false)
.setJavaType("Integer").setJavaField("sex").setExample("1")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
.setDictType("system_user_sex");
CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
.setColumnComment("是否有效").setNullable(false)
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
.setDictType("infra_boolean_string");
CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("头像").setNullable(false)
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("附件").setNullable(true)
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("备注").setNullable(false)
.setJavaType("String").setJavaField("memo").setExample("我是备注")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
.setColumnComment("创建时间").setNullable(true)
.setJavaType("LocalDateTime").setJavaField("createTime")
.setCreateOperation(false).setUpdateOperation(false)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,
sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn);
// 调用
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
// 构建 zip
writeFile(result, "/Users/yunai/test/demo01.zip");
// 断言
assertEquals(21, result.size());
// 断言 vo
for (String vo : new String[]{"SystemUserBaseVO", "SystemUserCreateReqVO", "SystemUserUpdateReqVO", "SystemUserRespVO",
"SystemUserPageReqVO", "SystemUserExportReqVO", "SystemUserExcelVO"}) {
assertPathContentEquals("vue3_crud/java/" + vo,
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/" + vo + ".java");
}
// 断言 controller
assertPathContentEquals("vue3_crud/java/SystemUserController",
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/SystemUserController.java");
// 断言 service
assertPathContentEquals("vue3_crud/java/SystemUserService",
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/SystemUserService.java");
assertPathContentEquals("vue3_crud/java/SystemUserServiceImpl",
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/SystemUserServiceImpl.java");
// 断言 convert
assertPathContentEquals("vue3_crud/java/SystemUserConvert",
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/user/SystemUserConvert.java");
// 断言 enums
assertPathContentEquals("vue3_crud/java/ErrorCodeConstants",
result, "yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants_手动操作.java");
// 断言 dal
assertPathContentEquals("vue3_crud/java/SystemUserDO",
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/SystemUserDO.java");
assertPathContentEquals("vue3_crud/java/SystemUserMapper",
result, "yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/SystemUserMapper.java");
assertPathContentEquals("vue3_crud/java/SystemUserMapper_xml",
result, "yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/user/SystemUserMapper.xml");
// 断言 test
assertPathContentEquals("vue3_crud/java/SystemUserServiceImplTest",
result, "yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/SystemUserServiceImplTest.java");
// 断言 sql 语句
assertPathContentEquals("vue3_crud/sql/h2",
result, "sql/h2.sql");
assertPathContentEquals("vue3_crud/sql/sql",
result, "sql/sql.sql");
// 断言 vue 语句
assertPathContentEquals("vue3_crud/vue/index",
result, "yudao-ui-admin-vue3/src/views/system/user/index.vue");
assertPathContentEquals("vue3_crud/vue/form",
result, "yudao-ui-admin-vue3/src/views/system/user/UserForm.vue");
assertPathContentEquals("vue3_crud/vue/api",
result, "yudao-ui-admin-vue3/src/api/system/user/index.ts");
assertResult(result, "codegen/vue3_tree");
// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree");
// writeFile(result, "/Users/yunai/test/demo66.zip");
}
@Test
public void testExecute_vue3_masterNormal() {
// 准备请求参数
// 主表
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
.setTableName("infra_demo11_student").setTableComment("学生表")
.setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11Student")
.setClassComment("学生").setAuthor("芋道源码")
.setTemplateType(CodegenTemplateTypeEnum.MASTER_NORMAL.getType())
.setFrontType(CodegenFrontTypeEnum.VUE3.getType());
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setId(100L)
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("简介").setNullable(false)
.setJavaType("String").setJavaField("description").setExample("我是介绍")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
.setColumnComment("出生日期").setNullable(false)
.setJavaType("LocalDateTime").setJavaField("birthday")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
.setColumnComment("性别").setNullable(false)
.setJavaType("Integer").setJavaField("sex").setExample("1")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
.setDictType("system_user_sex");
CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
.setColumnComment("是否有效").setNullable(false)
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
.setDictType("infra_boolean_string");
CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("头像").setNullable(false)
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("附件").setNullable(true)
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("备注").setNullable(false)
.setJavaType("String").setJavaField("memo").setExample("我是备注")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
.setColumnComment("创建时间").setNullable(true)
.setJavaType("LocalDateTime").setJavaField("createTime")
.setCreateOperation(false).setUpdateOperation(false)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,
sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn);
public void testExecute_vue3_master_normal() {
testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_NORMAL, "codegen/vue3_master_normal");
}
// 子表联系人
CodegenTableDO contactTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
.setTableName("infra_demo11_student_contact").setTableComment("学生联系人表")
.setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11StudentContact")
.setClassComment("学生联系人").setAuthor("芋道源码")
@Test
public void testExecute_vue3_master_erp() {
testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_ERP, "codegen/vue3_master_erp");
}
@Test
public void testExecute_vue3_master_inner() {
testExecute_vue3_master(CodegenTemplateTypeEnum.MASTER_INNER, "codegen/vue3_master_inner");
}
private void testExecute_vue3_master(CodegenTemplateTypeEnum templateType,
String path) {
// 准备参数
CodegenTableDO table = getTable("student")
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
.setTemplateType(templateType.getType());
List<CodegenColumnDO> columns = getColumnList("student");
// 准备参数子表
CodegenTableDO contactTable = getTable("contact")
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
.setSubJoinColumnId(100L).setSubJoinMany(true);
CodegenColumnDO contactIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO contactStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
.setJavaType("Long").setJavaField("studentId").setExample("2048")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setId(100L);
CodegenColumnDO contactNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO contactDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("简介").setNullable(false)
.setJavaType("String").setJavaField("description").setExample("我是介绍")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
CodegenColumnDO contactBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
.setColumnComment("出生日期").setNullable(false)
.setJavaType("LocalDateTime").setJavaField("birthday")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
CodegenColumnDO contactSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
.setColumnComment("性别").setNullable(false)
.setJavaType("Integer").setJavaField("sex").setExample("1")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
.setDictType("system_user_sex");
CodegenColumnDO contactEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
.setColumnComment("是否有效").setNullable(false)
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
.setDictType("infra_boolean_string");
CodegenColumnDO contactAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("头像").setNullable(false)
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
CodegenColumnDO contactVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("附件").setNullable(true)
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
CodegenColumnDO contactMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("备注").setNullable(false)
.setJavaType("String").setJavaField("memo").setExample("我是备注")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
CodegenColumnDO contactCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
.setColumnComment("创建时间").setNullable(true)
.setJavaType("LocalDateTime").setJavaField("createTime")
.setCreateOperation(false).setUpdateOperation(false)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn,
contactNameColumn, contactDescriptionColumn, contactBirthdayColumn,
contactSexColumn, contactEnabledColumn, contactAvatarColumn, contactVideoColumn, contactMemoColumn, contactCreateTimeColumn);
// 子表班主任
CodegenTableDO teacherTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
.setTableName("infra_demo11_student_teacher").setTableComment("学生班主任表")
.setModuleName("infra").setBusinessName("demo11").setClassName("InfraDemo11StudentTeacher")
.setClassComment("学生班主任").setAuthor("芋道源码")
List<CodegenColumnDO> contactColumns = getColumnList("contact");
// 准备参数班主任
CodegenTableDO teacherTable = getTable("teacher")
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
.setSubJoinColumnId(200L).setSubJoinMany(false);
CodegenColumnDO teacherIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO teacherStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
.setJavaType("Long").setJavaField("studentId").setExample("2048")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setId(200L);
CodegenColumnDO teacherNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO teacherDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("简介").setNullable(false)
.setJavaType("String").setJavaField("description").setExample("我是介绍")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
CodegenColumnDO teacherBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
.setColumnComment("出生日期").setNullable(false)
.setJavaType("LocalDateTime").setJavaField("birthday")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
CodegenColumnDO teacherSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
.setColumnComment("性别").setNullable(false)
.setJavaType("Integer").setJavaField("sex").setExample("1")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
.setDictType("system_user_sex");
CodegenColumnDO teacherEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
.setColumnComment("是否有效").setNullable(false)
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
.setDictType("infra_boolean_string");
CodegenColumnDO teacherAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("头像").setNullable(false)
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
CodegenColumnDO teacherVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("附件").setNullable(true)
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
CodegenColumnDO teacherMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("备注").setNullable(false)
.setJavaType("String").setJavaField("memo").setExample("我是备注")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
CodegenColumnDO teacherCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
.setColumnComment("创建时间").setNullable(true)
.setJavaType("LocalDateTime").setJavaField("createTime")
.setCreateOperation(false).setUpdateOperation(false)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
List<CodegenColumnDO> teacherColumns = Arrays.asList(teacherIdColumn, teacherStudentIdColumn,
teacherNameColumn, teacherDescriptionColumn, teacherBirthdayColumn,
teacherSexColumn, teacherEnabledColumn, teacherAvatarColumn, teacherVideoColumn, teacherMemoColumn, teacherCreateTimeColumn);
List<CodegenColumnDO> teacherColumns = getColumnList("teacher");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns,
Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));
// 构建 zip
writeFile(result, "/Users/yunai/test/demo11.zip");
// 断言
assertEquals(27, result.size());
for (Map.Entry<String, String> entry : result.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
System.out.println("");
System.out.println("");
System.out.println("");
}
assertResult(result, path);
// writeResult(result, "/root/ruoyi-vue-pro/yudao-module-infra/yudao-module-infra-biz/src/test/resources/" + path);
// writeFile(result, "/Users/yunai/test/demo11.zip");
}
@Test
public void testExecute_vue3_masterInner() {
// 准备请求参数
// 主表
CodegenTableDO table = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene()).setParentMenuId(888L)
.setTableName("infra_demo12_student").setTableComment("学生表")
.setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12Student")
.setClassComment("学生").setAuthor("芋道源码")
// .setTemplateType(CodegenTemplateTypeEnum.MASTER_INNER.getType())
.setTemplateType(CodegenTemplateTypeEnum.MASTER_ERP.getType())
.setFrontType(CodegenFrontTypeEnum.VUE3.getType());
CodegenColumnDO idColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setId(100L)
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO nameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO descriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("简介").setNullable(false)
.setJavaType("String").setJavaField("description").setExample("我是介绍")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
CodegenColumnDO birthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
.setColumnComment("出生日期").setNullable(false)
.setJavaType("LocalDateTime").setJavaField("birthday")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
CodegenColumnDO sexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
.setColumnComment("性别").setNullable(false)
.setJavaType("Integer").setJavaField("sex").setExample("1")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
.setDictType("system_user_sex");
CodegenColumnDO enabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
.setColumnComment("是否有效").setNullable(false)
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
.setDictType("infra_boolean_string");
CodegenColumnDO avatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("头像").setNullable(false)
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
CodegenColumnDO videoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("附件").setNullable(true)
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
CodegenColumnDO memoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("备注").setNullable(false)
.setJavaType("String").setJavaField("memo").setExample("我是备注")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
CodegenColumnDO createTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
.setColumnComment("创建时间").setNullable(true)
.setJavaType("LocalDateTime").setJavaField("createTime")
.setCreateOperation(false).setUpdateOperation(false)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
List<CodegenColumnDO> columns = Arrays.asList(idColumn, nameColumn, descriptionColumn, birthdayColumn,
sexColumn, enabledColumn, avatarColumn, videoColumn, memoColumn, createTimeColumn);
// 子表联系人
CodegenTableDO contactTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
.setTableName("infra_demo12_student_contact").setTableComment("学生联系人表")
.setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12StudentContact")
.setClassComment("学生联系人").setAuthor("芋道源码")
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
.setSubJoinColumnId(100L).setSubJoinMany(true);
CodegenColumnDO contactIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO contactStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
.setJavaType("Long").setJavaField("studentId").setExample("2048")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setId(100L);
CodegenColumnDO contactNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO contactDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("简介").setNullable(false)
.setJavaType("String").setJavaField("description").setExample("我是介绍")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
CodegenColumnDO contactBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
.setColumnComment("出生日期").setNullable(false)
.setJavaType("LocalDateTime").setJavaField("birthday")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
CodegenColumnDO contactSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
.setColumnComment("性别").setNullable(false)
.setJavaType("Integer").setJavaField("sex").setExample("1")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
.setDictType("system_user_sex");
CodegenColumnDO contactEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
.setColumnComment("是否有效").setNullable(false)
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
.setDictType("infra_boolean_string");
CodegenColumnDO contactAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("头像").setNullable(false)
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
CodegenColumnDO contactVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("附件").setNullable(true)
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
CodegenColumnDO contactMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("备注").setNullable(false)
.setJavaType("String").setJavaField("memo").setExample("我是备注")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
CodegenColumnDO contactCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
.setColumnComment("创建时间").setNullable(true)
.setJavaType("LocalDateTime").setJavaField("createTime")
.setCreateOperation(false).setUpdateOperation(false)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
List<CodegenColumnDO> contactColumns = Arrays.asList(contactIdColumn, contactStudentIdColumn,
contactNameColumn, contactDescriptionColumn, contactBirthdayColumn,
contactSexColumn, contactEnabledColumn, contactAvatarColumn, contactVideoColumn, contactMemoColumn, contactCreateTimeColumn);
// 子表班主任
CodegenTableDO teacherTable = new CodegenTableDO().setScene(CodegenSceneEnum.ADMIN.getScene())
.setTableName("infra_demo12_student_teacher").setTableComment("学生班主任表")
.setModuleName("infra").setBusinessName("demo12").setClassName("InfraDemo12StudentTeacher")
.setClassComment("学生班主任").setAuthor("芋道源码")
.setTemplateType(CodegenTemplateTypeEnum.SUB.getType())
.setFrontType(CodegenFrontTypeEnum.VUE3.getType())
.setSubJoinColumnId(200L).setSubJoinMany(false);
CodegenColumnDO teacherIdColumn = new CodegenColumnDO().setColumnName("id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("编号").setNullable(false).setPrimaryKey(true).setAutoIncrement(true)
.setJavaType("Long").setJavaField("id").setExample("1024")
.setCreateOperation(false).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true);
CodegenColumnDO teacherStudentIdColumn = new CodegenColumnDO().setColumnName("student_id").setDataType(JdbcType.BIGINT.name())
.setColumnComment("学生编号").setNullable(false).setPrimaryKey(false)
.setJavaType("Long").setJavaField("studentId").setExample("2048")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setId(200L);
CodegenColumnDO teacherNameColumn = new CodegenColumnDO().setColumnName("name").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("名字").setNullable(false)
.setJavaType("String").setJavaField("name").setExample("芋头")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.LIKE.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType());
CodegenColumnDO teacherDescriptionColumn = new CodegenColumnDO().setColumnName("description").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("简介").setNullable(false)
.setJavaType("String").setJavaField("description").setExample("我是介绍")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.TEXTAREA.getType());
CodegenColumnDO teacherBirthdayColumn = new CodegenColumnDO().setColumnName("birthday").setDataType(JdbcType.DATE.name())
.setColumnComment("出生日期").setNullable(false)
.setJavaType("LocalDateTime").setJavaField("birthday")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
CodegenColumnDO teacherSexColumn = new CodegenColumnDO().setColumnName("sex").setDataType(JdbcType.INTEGER.name())
.setColumnComment("性别").setNullable(false)
.setJavaType("Integer").setJavaField("sex").setExample("1")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.SELECT.getType())
.setDictType("system_user_sex");
CodegenColumnDO teacherEnabledColumn = new CodegenColumnDO().setColumnName("enabled").setDataType(JdbcType.BOOLEAN.name())
.setColumnComment("是否有效").setNullable(false)
.setJavaType("Boolean").setJavaField("enabled").setExample("true")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType())
.setDictType("infra_boolean_string");
CodegenColumnDO teacherAvatarColumn = new CodegenColumnDO().setColumnName("avatar").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("头像").setNullable(false)
.setJavaType("String").setJavaField("avatar").setExample("https://www.iocoder.cn/1.png")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD.getType());
CodegenColumnDO teacherVideoColumn = new CodegenColumnDO().setColumnName("video").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("附件").setNullable(true)
.setJavaType("String").setJavaField("video").setExample("https://www.iocoder.cn/1.mp4")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.FILE_UPLOAD.getType());
CodegenColumnDO teacherMemoColumn = new CodegenColumnDO().setColumnName("memo").setDataType(JdbcType.VARCHAR.name())
.setColumnComment("备注").setNullable(false)
.setJavaType("String").setJavaField("memo").setExample("我是备注")
.setCreateOperation(true).setUpdateOperation(true)
.setListOperation(false)
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.EDITOR.getType());
CodegenColumnDO teacherCreateTimeColumn = new CodegenColumnDO().setColumnName("create_time").setDataType(JdbcType.DATE.name())
.setColumnComment("创建时间").setNullable(true)
.setJavaType("LocalDateTime").setJavaField("createTime")
.setCreateOperation(false).setUpdateOperation(false)
.setListOperation(true).setListOperationCondition(CodegenColumnListConditionEnum.BETWEEN.getCondition())
.setListOperationResult(true)
.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType());
List<CodegenColumnDO> teacherColumns = Arrays.asList(teacherIdColumn, teacherStudentIdColumn,
teacherNameColumn, teacherDescriptionColumn, teacherBirthdayColumn,
teacherSexColumn, teacherEnabledColumn, teacherAvatarColumn, teacherVideoColumn, teacherMemoColumn, teacherCreateTimeColumn);
// 调用
Map<String, String> result = codegenEngine.execute(table, columns,
Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));
// 构建 zip
writeFile(result, "/Users/yunai/test/demo12.zip");
// 断言
assertEquals(27, result.size());
for (Map.Entry<String, String> entry : result.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
System.out.println("");
System.out.println("");
System.out.println("");
}
private static CodegenTableDO getTable(String name) {
String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
return JsonUtils.parseObject(content, "table", CodegenTableDO.class);
}
private void assertPathContentEquals(String path, Map<String, String> result, String key) {
String pathContent = ResourceUtil.readUtf8Str("codegen/" + path);
String valueContent = result.get(key);
assertEquals(pathContent, valueContent);
private static List<CodegenColumnDO> getColumnList(String name) {
String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
List<CodegenColumnDO> list = JsonUtils.parseArray(content, "columns", CodegenColumnDO.class);
list.forEach(column -> {
if (column.getNullable() == null) {
column.setNullable(false);
}
if (column.getCreateOperation() == null) {
column.setCreateOperation(false);
}
if (column.getUpdateOperation() == null) {
column.setUpdateOperation(false);
}
if (column.getListOperation() == null) {
column.setListOperation(false);
}
if (column.getListOperationResult() == null) {
column.setListOperationResult(false);
}
});
return list;
}
@SuppressWarnings("rawtypes")
private static void assertResult(Map<String, String> result, String path) {
String assertContent = ResourceUtil.readUtf8Str(path + "/assert.json");
List<HashMap> asserts = JsonUtils.parseArray(assertContent, HashMap.class);
assertEquals(asserts.size(), result.size());
// 校验每个文件
asserts.forEach(assertMap -> {
String contentPath = (String) assertMap.get("contentPath");
String filePath = (String) assertMap.get("filePath");
String content = ResourceUtil.readUtf8Str(path + "/" + contentPath);
assertEquals(content, result.get(filePath), filePath + ":不匹配");
});
}
// ==================== 调试专用 ====================
/**
* 将生成的代码写入到文件
*
* 用途方便本地调试
* 调试使用将生成的代码写入到文件
*
* @param result 生成的代码
* @param path 写入文件的路径
@ -810,4 +179,25 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
FileUtil.writeBytes(outputStream.toByteArray(), path);
}
/**
* 调试使用将生成的结果写入到文件
*
* @param result 生成的代码
* @param basePath 写入文件的路径绝对路径
*/
private void writeResult(Map<String, String> result, String basePath) {
// 写入文件内容
List<Map<String, String>> asserts = new ArrayList<>();
result.forEach((filePath, fileContent) -> {
String lastFilePath = StrUtil.subAfter(filePath, '/', true);
String contentPath = StrUtil.subAfter(lastFilePath, '.', true)
+ '/' + StrUtil.subBefore(lastFilePath, '.', true);
asserts.add(MapUtil.<String, String>builder().put("filePath", filePath)
.put("contentPath", contentPath).build());
FileUtil.writeUtf8String(fileContent, basePath + "/" + contentPath);
});
// 写入 assert.json 文件
FileUtil.writeUtf8String(JsonUtils.toJsonPrettyString(asserts), basePath +"/assert.json");
}
}

View File

@ -0,0 +1,53 @@
{
"table": {
"id": 10,
"scene" : 1,
"parentMenuId" : 888,
"tableName" : "infra_category",
"tableComment" : "分类表",
"moduleName" : "infra",
"businessName" : "demo",
"className" : "InfraCategory",
"classComment" : "分类",
"author" : "芋道源码",
"treeParentColumnId" : 22,
"treeNameColumnId" : 11
},
"columns": [ {
"columnName" : "id",
"dataType" : "BIGINT",
"columnComment" : "编号",
"primaryKey" : true,
"autoIncrement" : true,
"javaType" : "Long",
"javaField" : "id",
"example" : "1024",
"updateOperation" : true,
"listOperationResult" : true
}, {
"id" : 11,
"columnName" : "name",
"dataType" : "VARCHAR",
"columnComment" : "名字",
"javaType" : "String",
"javaField" : "name",
"example" : "芋头",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "LIKE",
"listOperationResult" : true,
"htmlType" : "input"
}, {
"id" : 22,
"columnName" : "description",
"dataType" : "VARCHAR",
"columnComment" : "父编号",
"javaType" : "Long",
"javaField" : "parentId",
"example" : "2048",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true
} ]
}

View File

@ -0,0 +1,144 @@
{
"table": {
"scene" : 1,
"tableName" : "infra_student_contact",
"tableComment" : "学生联系人表",
"moduleName" : "infra",
"businessName" : "demo",
"className" : "InfraStudentContact",
"classComment" : "学生联系人",
"author" : "芋道源码"
},
"columns": [ {
"columnName" : "id",
"dataType" : "BIGINT",
"columnComment" : "编号",
"primaryKey" : true,
"autoIncrement" : true,
"javaType" : "Long",
"javaField" : "id",
"example" : "1024",
"updateOperation" : true,
"listOperationResult" : true
}, {
"id" : 100,
"columnName" : "student_id",
"dataType" : "BIGINT",
"columnComment" : "学生编号",
"javaType" : "Long",
"javaField" : "studentId",
"example" : "2048",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true
}, {
"columnName" : "name",
"dataType" : "VARCHAR",
"columnComment" : "名字",
"javaType" : "String",
"javaField" : "name",
"example" : "芋头",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "LIKE",
"listOperationResult" : true,
"htmlType" : "input"
}, {
"columnName" : "description",
"dataType" : "VARCHAR",
"columnComment" : "简介",
"javaType" : "String",
"javaField" : "description",
"example" : "我是介绍",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "textarea"
}, {
"columnName" : "birthday",
"dataType" : "DATE",
"columnComment" : "出生日期",
"javaType" : "LocalDateTime",
"javaField" : "birthday",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "datetime"
}, {
"columnName" : "sex",
"dataType" : "INTEGER",
"columnComment" : "性别",
"javaType" : "Integer",
"javaField" : "sex",
"dictType" : "system_user_sex",
"example" : "1",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "select"
}, {
"columnName" : "enabled",
"dataType" : "BOOLEAN",
"columnComment" : "是否有效",
"javaType" : "Boolean",
"javaField" : "enabled",
"dictType" : "infra_boolean_string",
"example" : "true",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "radio"
}, {
"columnName" : "avatar",
"dataType" : "VARCHAR",
"columnComment" : "头像",
"javaType" : "String",
"javaField" : "avatar",
"example" : "https://www.iocoder.cn/1.png",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "imageUpload"
}, {
"columnName" : "video",
"dataType" : "VARCHAR",
"columnComment" : "附件",
"nullable" : true,
"javaType" : "String",
"javaField" : "video",
"example" : "https://www.iocoder.cn/1.mp4",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "fileUpload"
}, {
"columnName" : "memo",
"dataType" : "VARCHAR",
"columnComment" : "备注",
"javaType" : "String",
"javaField" : "memo",
"example" : "我是备注",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "editor"
}, {
"columnName" : "create_time",
"dataType" : "DATE",
"columnComment" : "创建时间",
"nullable" : true,
"javaType" : "LocalDateTime",
"javaField" : "createTime",
"listOperation" : true,
"listOperationCondition" : "BETWEEN",
"listOperationResult" : true,
"htmlType" : "datetime"
} ]
}

View File

@ -1,8 +1,135 @@
{
"table": {
"id": 1,
"scene" : 1,
"parentMenuId" : 888,
"tableName" : "infra_student",
"tableComment" : "学生表",
"moduleName" : "infra",
"businessName" : "demo",
"className" : "InfraStudent",
"classComment" : "学生",
"author" : "芋道源码"
},
"columns": [{
}]
"columns": [ {
"id" : 100,
"columnName" : "id",
"dataType" : "BIGINT",
"columnComment" : "编号",
"primaryKey" : true,
"autoIncrement" : true,
"javaType" : "Long",
"javaField" : "id",
"example" : "1024",
"updateOperation" : true,
"listOperationResult" : true
}, {
"columnName" : "name",
"dataType" : "VARCHAR",
"columnComment" : "名字",
"javaType" : "String",
"javaField" : "name",
"example" : "芋头",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "LIKE",
"listOperationResult" : true,
"htmlType" : "input"
}, {
"columnName" : "description",
"dataType" : "VARCHAR",
"columnComment" : "简介",
"javaType" : "String",
"javaField" : "description",
"example" : "我是介绍",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "textarea"
}, {
"columnName" : "birthday",
"dataType" : "DATE",
"columnComment" : "出生日期",
"javaType" : "LocalDateTime",
"javaField" : "birthday",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "datetime"
}, {
"columnName" : "sex",
"dataType" : "INTEGER",
"columnComment" : "性别",
"javaType" : "Integer",
"javaField" : "sex",
"dictType" : "system_user_sex",
"example" : "1",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "select"
}, {
"columnName" : "enabled",
"dataType" : "BOOLEAN",
"columnComment" : "是否有效",
"javaType" : "Boolean",
"javaField" : "enabled",
"dictType" : "infra_boolean_string",
"example" : "true",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "radio"
}, {
"columnName" : "avatar",
"dataType" : "VARCHAR",
"columnComment" : "头像",
"javaType" : "String",
"javaField" : "avatar",
"example" : "https://www.iocoder.cn/1.png",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "imageUpload"
}, {
"columnName" : "video",
"dataType" : "VARCHAR",
"columnComment" : "附件",
"javaType" : "String",
"javaField" : "video",
"example" : "https://www.iocoder.cn/1.mp4",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "fileUpload"
}, {
"columnName" : "memo",
"dataType" : "VARCHAR",
"columnComment" : "备注",
"javaType" : "String",
"javaField" : "memo",
"example" : "我是备注",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "editor"
}, {
"columnName" : "create_time",
"dataType" : "DATE",
"columnComment" : "创建时间",
"nullable" : true,
"javaType" : "LocalDateTime",
"javaField" : "createTime",
"listOperation" : true,
"listOperationCondition" : "BETWEEN",
"listOperationResult" : true,
"htmlType" : "datetime"
} ]
}

View File

@ -0,0 +1,144 @@
{
"table": {
"scene" : 1,
"tableName" : "infra_student_teacher",
"tableComment" : "学生班主任表",
"moduleName" : "infra",
"businessName" : "demo",
"className" : "InfraStudentTeacher",
"classComment" : "学生班主任",
"author" : "芋道源码"
},
"columns": [ {
"columnName" : "id",
"dataType" : "BIGINT",
"columnComment" : "编号",
"primaryKey" : true,
"autoIncrement" : true,
"javaType" : "Long",
"javaField" : "id",
"example" : "1024",
"updateOperation" : true,
"listOperationResult" : true
}, {
"id" : 200,
"columnName" : "student_id",
"dataType" : "BIGINT",
"columnComment" : "学生编号",
"javaType" : "Long",
"javaField" : "studentId",
"example" : "2048",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true
}, {
"columnName" : "name",
"dataType" : "VARCHAR",
"columnComment" : "名字",
"javaType" : "String",
"javaField" : "name",
"example" : "芋头",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "LIKE",
"listOperationResult" : true,
"htmlType" : "input"
}, {
"columnName" : "description",
"dataType" : "VARCHAR",
"columnComment" : "简介",
"javaType" : "String",
"javaField" : "description",
"example" : "我是介绍",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "textarea"
}, {
"columnName" : "birthday",
"dataType" : "DATE",
"columnComment" : "出生日期",
"javaType" : "LocalDateTime",
"javaField" : "birthday",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "datetime"
}, {
"columnName" : "sex",
"dataType" : "INTEGER",
"columnComment" : "性别",
"javaType" : "Integer",
"javaField" : "sex",
"dictType" : "system_user_sex",
"example" : "1",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "select"
}, {
"columnName" : "enabled",
"dataType" : "BOOLEAN",
"columnComment" : "是否有效",
"javaType" : "Boolean",
"javaField" : "enabled",
"dictType" : "infra_boolean_string",
"example" : "true",
"createOperation" : true,
"updateOperation" : true,
"listOperation" : true,
"listOperationCondition" : "=",
"listOperationResult" : true,
"htmlType" : "radio"
}, {
"columnName" : "avatar",
"dataType" : "VARCHAR",
"columnComment" : "头像",
"javaType" : "String",
"javaField" : "avatar",
"example" : "https://www.iocoder.cn/1.png",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "imageUpload"
}, {
"columnName" : "video",
"dataType" : "VARCHAR",
"columnComment" : "附件",
"nullable" : true,
"javaType" : "String",
"javaField" : "video",
"example" : "https://www.iocoder.cn/1.mp4",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "fileUpload"
}, {
"columnName" : "memo",
"dataType" : "VARCHAR",
"columnComment" : "备注",
"javaType" : "String",
"javaField" : "memo",
"example" : "我是备注",
"createOperation" : true,
"updateOperation" : true,
"listOperationResult" : true,
"htmlType" : "editor"
}, {
"columnName" : "create_time",
"dataType" : "DATE",
"columnComment" : "创建时间",
"nullable" : true,
"javaType" : "LocalDateTime",
"javaField" : "createTime",
"listOperation" : true,
"listOperationCondition" : "BETWEEN",
"listOperationResult" : true,
"htmlType" : "datetime"
} ]
}

View File

@ -1,3 +0,0 @@
// TODO 待办:请将下面的错误码复制到 yudao-module-system-api 模块的 ErrorCodeConstants 类中。注意请给“TODO 补充编号”设置一个错误码编号!!!
// ========== 用户 TODO 补充编号 ==========
ErrorCode USER_NOT_EXISTS = new ErrorCode(TODO 补充编号, "用户不存在");

View File

@ -1,53 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import javax.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 用户 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class SystemUserBaseVO {
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
@NotEmpty(message = "名字不能为空")
private String name;
@Schema(description = "头像", example = "https://www.iocoder.cn/1.png")
private String avatar;
@Schema(description = "视频", example = "https://www.iocoder.cn/1.mp4")
private String video;
@Schema(description = "个人简介", example = "我是介绍")
private String description;
@Schema(description = "性别 1", example = "男")
private String sex1;
@Schema(description = "性别 2", example = "1")
private Integer sex2;
@Schema(description = "性别 3", example = "true")
private Boolean sex3;
@Schema(description = "出生日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime birthday;
@Schema(description = "备注", example = "我是备注")
private String memo;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime createTime;
}

View File

@ -1,102 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.user;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
import cn.iocoder.yudao.module.system.convert.user.SystemUserConvert;
import cn.iocoder.yudao.module.system.service.user.SystemUserService;
@Tag(name = "管理后台 - 用户")
@RestController
@RequestMapping("/system/user")
@Validated
public class SystemUserController {
@Resource
private SystemUserService userService;
@PostMapping("/create")
@Operation(summary = "创建用户")
@PreAuthorize("@ss.hasPermission('system:user:create')")
public CommonResult<Long> createUser(@Valid @RequestBody SystemUserCreateReqVO createReqVO) {
return success(userService.createUser(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新用户")
@PreAuthorize("@ss.hasPermission('system:user:update')")
public CommonResult<Boolean> updateUser(@Valid @RequestBody SystemUserUpdateReqVO updateReqVO) {
userService.updateUser(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除用户")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:user:delete')")
public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {
userService.deleteUser(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得用户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:user:query')")
public CommonResult<SystemUserRespVO> getUser(@RequestParam("id") Long id) {
SystemUserDO user = userService.getUser(id);
return success(SystemUserConvert.INSTANCE.convert(user));
}
@GetMapping("/list")
@Operation(summary = "获得用户列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('system:user:query')")
public CommonResult<List<SystemUserRespVO>> getUserList(@RequestParam("ids") Collection<Long> ids) {
List<SystemUserDO> list = userService.getUserList(ids);
return success(SystemUserConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得用户分页")
@PreAuthorize("@ss.hasPermission('system:user:query')")
public CommonResult<PageResult<SystemUserRespVO>> getUserPage(@Valid SystemUserPageReqVO pageVO) {
PageResult<SystemUserDO> pageResult = userService.getUserPage(pageVO);
return success(SystemUserConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出用户 Excel")
@PreAuthorize("@ss.hasPermission('system:user:export')")
@OperateLog(type = EXPORT)
public void exportUserExcel(@Valid SystemUserExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<SystemUserDO> list = userService.getUserList(exportReqVO);
// 导出 Excel
List<SystemUserExcelVO> datas = SystemUserConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "用户.xls", "数据", SystemUserExcelVO.class, datas);
}
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.system.convert.user;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
/**
* 用户 Convert
*
* @author 芋道源码
*/
@Mapper
public interface SystemUserConvert {
SystemUserConvert INSTANCE = Mappers.getMapper(SystemUserConvert.class);
SystemUserDO convert(SystemUserCreateReqVO bean);
SystemUserDO convert(SystemUserUpdateReqVO bean);
SystemUserRespVO convert(SystemUserDO bean);
List<SystemUserRespVO> convertList(List<SystemUserDO> list);
PageResult<SystemUserRespVO> convertPage(PageResult<SystemUserDO> page);
List<SystemUserExcelVO> convertList02(List<SystemUserDO> list);
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 用户创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SystemUserCreateReqVO extends SystemUserBaseVO {
}

View File

@ -1,58 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
/**
* 用户 Excel VO
*
* @author 芋道源码
*/
@Data
public class SystemUserExcelVO {
@ExcelProperty("编号")
private Long id;
@ExcelProperty("名字")
private String name;
@ExcelProperty("头像")
private String avatar;
@ExcelProperty("视频")
private String video;
@ExcelProperty("个人简介")
private String description;
@ExcelProperty(value = "性别 1", converter = DictConvert.class)
@DictFormat("system_sex1") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
private String sex1;
@ExcelProperty(value = "性别 2", converter = DictConvert.class)
@DictFormat("system_sex2") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
private Integer sex2;
@ExcelProperty(value = "性别 3", converter = DictConvert.class)
@DictFormat("system_sex3") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
private Boolean sex3;
@ExcelProperty("出生日期")
private LocalDateTime birthday;
@ExcelProperty("备注")
private String memo;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -1,40 +0,0 @@
package cn.iocoder.yudao.module.system.dal.mysql.user;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
/**
* 用户 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface SystemUserMapper extends BaseMapperX<SystemUserDO> {
default PageResult<SystemUserDO> selectPage(SystemUserPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<SystemUserDO>()
.likeIfPresent(SystemUserDO::getName, reqVO.getName())
.eqIfPresent(SystemUserDO::getSex1, reqVO.getSex1())
.eqIfPresent(SystemUserDO::getSex2, reqVO.getSex2())
.eqIfPresent(SystemUserDO::getBirthday, reqVO.getBirthday())
.betweenIfPresent(SystemUserDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(SystemUserDO::getId));
}
default List<SystemUserDO> selectList(SystemUserExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<SystemUserDO>()
.likeIfPresent(SystemUserDO::getName, reqVO.getName())
.eqIfPresent(SystemUserDO::getSex1, reqVO.getSex1())
.eqIfPresent(SystemUserDO::getSex2, reqVO.getSex2())
.eqIfPresent(SystemUserDO::getBirthday, reqVO.getBirthday())
.betweenIfPresent(SystemUserDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(SystemUserDO::getId));
}
}

View File

@ -1,16 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 用户 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SystemUserRespVO extends SystemUserBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
}

View File

@ -1,70 +0,0 @@
package cn.iocoder.yudao.module.system.service.user;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
/**
* 用户 Service 接口
*
* @author 芋道源码
*/
public interface SystemUserService {
/**
* 创建用户
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createUser(@Valid SystemUserCreateReqVO createReqVO);
/**
* 更新用户
*
* @param updateReqVO 更新信息
*/
void updateUser(@Valid SystemUserUpdateReqVO updateReqVO);
/**
* 删除用户
*
* @param id 编号
*/
void deleteUser(Long id);
/**
* 获得用户
*
* @param id 编号
* @return 用户
*/
SystemUserDO getUser(Long id);
/**
* 获得用户列表
*
* @param ids 编号
* @return 用户列表
*/
List<SystemUserDO> getUserList(Collection<Long> ids);
/**
* 获得用户分页
*
* @param pageReqVO 分页查询
* @return 用户分页
*/
PageResult<SystemUserDO> getUserPage(SystemUserPageReqVO pageReqVO);
/**
* 获得用户列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 用户列表
*/
List<SystemUserDO> getUserList(SystemUserExportReqVO exportReqVO);
}

View File

@ -1,88 +0,0 @@
package cn.iocoder.yudao.module.system.service.user;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.convert.user.SystemUserConvert;
import cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
/**
* 用户 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class SystemUserServiceImpl implements SystemUserService {
@Resource
private SystemUserMapper userMapper;
@Override
public Long createUser(SystemUserCreateReqVO createReqVO) {
// 插入
SystemUserDO user = SystemUserConvert.INSTANCE.convert(createReqVO);
userMapper.insert(user);
// 返回
return user.getId();
}
@Override
public void updateUser(SystemUserUpdateReqVO updateReqVO) {
// 校验存在
validateUserExists(updateReqVO.getId());
// 更新
SystemUserDO updateObj = SystemUserConvert.INSTANCE.convert(updateReqVO);
userMapper.updateById(updateObj);
}
@Override
public void deleteUser(Long id) {
// 校验存在
validateUserExists(id);
// 删除
userMapper.deleteById(id);
}
private void validateUserExists(Long id) {
if (userMapper.selectById(id) == null) {
throw exception(USER_NOT_EXISTS);
}
}
@Override
public SystemUserDO getUser(Long id) {
return userMapper.selectById(id);
}
@Override
public List<SystemUserDO> getUserList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return ListUtil.empty();
}
return userMapper.selectBatchIds(ids);
}
@Override
public PageResult<SystemUserDO> getUserPage(SystemUserPageReqVO pageReqVO) {
return userMapper.selectPage(pageReqVO);
}
@Override
public List<SystemUserDO> getUserList(SystemUserExportReqVO exportReqVO) {
return userMapper.selectList(exportReqVO);
}
}

View File

@ -1,191 +0,0 @@
package cn.iocoder.yudao.module.system.service.user;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.module.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SystemUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.SystemUserMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.module.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link SystemUserServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(SystemUserServiceImpl.class)
public class SystemUserServiceImplTest extends BaseDbUnitTest {
@Resource
private SystemUserServiceImpl userService;
@Resource
private SystemUserMapper userMapper;
@Test
public void testCreateUser_success() {
// 准备参数
SystemUserCreateReqVO reqVO = randomPojo(SystemUserCreateReqVO.class);
// 调用
Long userId = userService.createUser(reqVO);
// 断言
assertNotNull(userId);
// 校验记录的属性是否正确
SystemUserDO user = userMapper.selectById(userId);
assertPojoEquals(reqVO, user);
}
@Test
public void testUpdateUser_success() {
// mock 数据
SystemUserDO dbUser = randomPojo(SystemUserDO.class);
userMapper.insert(dbUser);// @Sql: 先插入出一条存在的数据
// 准备参数
SystemUserUpdateReqVO reqVO = randomPojo(SystemUserUpdateReqVO.class, o -> {
o.setId(dbUser.getId()); // 设置更新的 ID
});
// 调用
userService.updateUser(reqVO);
// 校验是否更新正确
SystemUserDO user = userMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, user);
}
@Test
public void testUpdateUser_notExists() {
// 准备参数
SystemUserUpdateReqVO reqVO = randomPojo(SystemUserUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> userService.updateUser(reqVO), USER_NOT_EXISTS);
}
@Test
public void testDeleteUser_success() {
// mock 数据
SystemUserDO dbUser = randomPojo(SystemUserDO.class);
userMapper.insert(dbUser);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbUser.getId();
// 调用
userService.deleteUser(id);
// 校验数据不存在了
assertNull(userMapper.selectById(id));
}
@Test
public void testDeleteUser_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> userService.deleteUser(id), USER_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetUserPage() {
// mock 数据
SystemUserDO dbUser = randomPojo(SystemUserDO.class, o -> { // 等会查询到
o.setName(null);
o.setSex1(null);
o.setSex2(null);
o.setSex3(null);
o.setBirthday(null);
o.setCreateTime(null);
});
userMapper.insert(dbUser);
// 测试 name 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setName(null)));
// 测试 sex1 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex1(null)));
// 测试 sex2 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex2(null)));
// 测试 sex3 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex3(null)));
// 测试 birthday 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setBirthday(null)));
// 测试 createTime 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setCreateTime(null)));
// 准备参数
SystemUserPageReqVO reqVO = new SystemUserPageReqVO();
reqVO.setName(null);
reqVO.setSex1(null);
reqVO.setSex2(null);
reqVO.setSex3(null);
reqVO.setBirthday(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<SystemUserDO> pageResult = userService.getUserPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbUser, pageResult.getList().get(0));
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetUserList() {
// mock 数据
SystemUserDO dbUser = randomPojo(SystemUserDO.class, o -> { // 等会查询到
o.setName(null);
o.setSex1(null);
o.setSex2(null);
o.setSex3(null);
o.setBirthday(null);
o.setCreateTime(null);
});
userMapper.insert(dbUser);
// 测试 name 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setName(null)));
// 测试 sex1 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex1(null)));
// 测试 sex2 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex2(null)));
// 测试 sex3 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setSex3(null)));
// 测试 birthday 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setBirthday(null)));
// 测试 createTime 不匹配
userMapper.insert(cloneIgnoreId(dbUser, o -> o.setCreateTime(null)));
// 准备参数
SystemUserExportReqVO reqVO = new SystemUserExportReqVO();
reqVO.setName(null);
reqVO.setSex1(null);
reqVO.setSex2(null);
reqVO.setSex3(null);
reqVO.setBirthday(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
List<SystemUserDO> list = userService.getUserList(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(dbUser, list.get(0));
}
}

View File

@ -1,18 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 用户更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SystemUserUpdateReqVO extends SystemUserBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "编号不能为空")
private Long id;
}

View File

@ -1,18 +0,0 @@
-- 将该建表 SQL 语句,添加到 yudao-module-system-biz 模块的 test/resources/sql/create_tables.sql 文件里
CREATE TABLE IF NOT EXISTS "system_user" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar NOT NULL,
"avatar" varchar,
"video" varchar,
"description" varchar,
"sex1" varchar,
"sex2" int,
"sex3" bit,
"birthday" varchar,
"memo" varchar,
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ("id")
) COMMENT '用户表';
-- 将该删表 SQL 语句,添加到 yudao-module-system-biz 模块的 test/resources/sql/clean.sql 文件里
DELETE FROM "system_user";

View File

@ -1,45 +0,0 @@
import request from '@/config/axios'
export interface UserVO {
id: number
name: string
avatar: string
video: string
description: string
sex1: string
sex2: number
sex3: boolean
birthday: Date
memo: string
createTime: Date
}
// 查询用户列表
export const getUserPage = async (params) => {
return await request.get({ url: `/system/user/page`, params })
}
// 查询用户详情
export const getUser = async (id: number) => {
return await request.get({ url: `/system/user/get?id=` + id })
}
// 新增用户
export const createUser = async (data: UserVO) => {
return await request.post({ url: `/system/user/create`, data })
}
// 修改用户
export const updateUser = async (data: UserVO) => {
return await request.put({ url: `/system/user/update`, data })
}
// 删除用户
export const deleteUser = async (id: number) => {
return await request.delete({ url: `/system/user/delete?id=` + id })
}
// 导出用户 Excel
export const exportUser = async (params) => {
return await request.download({ url: `/system/user/export-excel`, params })
}

View File

@ -0,0 +1,73 @@
[ {
"contentPath" : "java/InfraStudentPageReqVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
}, {
"contentPath" : "java/InfraStudentRespVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
}, {
"contentPath" : "java/InfraStudentSaveReqVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
}, {
"contentPath" : "java/InfraStudentController",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
}, {
"contentPath" : "java/InfraStudentDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
}, {
"contentPath" : "java/InfraStudentContactDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
}, {
"contentPath" : "java/InfraStudentTeacherDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
}, {
"contentPath" : "java/InfraStudentMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
}, {
"contentPath" : "java/InfraStudentContactMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
}, {
"contentPath" : "java/InfraStudentTeacherMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
}, {
"contentPath" : "xml/InfraStudentMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
}, {
"contentPath" : "java/InfraStudentServiceImpl",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
}, {
"contentPath" : "java/InfraStudentService",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
}, {
"contentPath" : "java/InfraStudentServiceImplTest",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
}, {
"contentPath" : "java/ErrorCodeConstants_手动操作",
"filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
}, {
"contentPath" : "sql/sql",
"filePath" : "sql/sql.sql"
}, {
"contentPath" : "sql/h2",
"filePath" : "sql/h2.sql"
}, {
"contentPath" : "vue/index",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
}, {
"contentPath" : "vue/StudentForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
}, {
"contentPath" : "vue/StudentContactForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
}, {
"contentPath" : "vue/StudentTeacherForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
}, {
"contentPath" : "vue/StudentContactList",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue"
}, {
"contentPath" : "vue/StudentTeacherList",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue"
}, {
"contentPath" : "ts/index",
"filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
} ]

View File

@ -0,0 +1,6 @@
// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意请给“TODO 补充编号”设置一个错误码编号!!!
// ========== 学生 TODO 补充编号 ==========
ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");
ErrorCode STUDENT_CONTACT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生联系人不存在");
ErrorCode STUDENT_TEACHER_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任不存在");
ErrorCode STUDENT_TEACHER_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任已存在");

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.system.dal.dataobject.user;
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
@ -8,63 +8,61 @@ import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 用户 DO
* 学生联系人 DO
*
* @author 芋道源码
*/
@TableName("system_user")
@KeySequence("system_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@TableName("infra_student_contact")
@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SystemUserDO extends BaseDO {
public class InfraStudentContactDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 学生编号
*/
private Long studentId;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 视频
* 附件
*/
private String video;
/**
* 个人简介
*/
private String description;
/**
* 性别 1
*
* 枚举 {@link TODO system_sex1 对应的类}
*/
private String sex1;
/**
* 性别 2
*
* 枚举 {@link TODO system_sex2 对应的类}
*/
private Integer sex2;
/**
* 性别 3
*
* 枚举 {@link TODO system_sex3 对应的类}
*/
private Boolean sex3;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 备注
*/

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 学生联系人 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
default PageResult<InfraStudentContactDO> selectPage(PageParam reqVO, Long studentId) {
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentContactDO>()
.eq(InfraStudentContactDO::getStudentId, studentId)
.orderByDesc(InfraStudentContactDO::getId));
}
default int deleteByStudentId(Long studentId) {
return delete(InfraStudentContactDO::getStudentId, studentId);
}
}

View File

@ -0,0 +1,183 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
@Tag(name = "管理后台 - 学生")
@RestController
@RequestMapping("/infra/student")
@Validated
public class InfraStudentController {
@Resource
private InfraStudentService studentService;
@PostMapping("/create")
@Operation(summary = "创建学生")
@PreAuthorize("@ss.hasPermission('infra:student:create')")
public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
return success(studentService.createStudent(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新学生")
@PreAuthorize("@ss.hasPermission('infra:student:update')")
public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
studentService.updateStudent(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除学生")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
studentService.deleteStudent(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得学生")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
InfraStudentDO student = studentService.getStudent(id);
return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得学生分页")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出学生 Excel")
@PreAuthorize("@ss.hasPermission('infra:student:export')")
@OperateLog(type = EXPORT)
public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
BeanUtils.toBean(list, InfraStudentRespVO.class));
}
// ==================== 子表(学生联系人) ====================
@GetMapping("/student-contact/page")
@Operation(summary = "获得学生联系人分页")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<PageResult<InfraStudentContactDO>> getStudentContactPage(PageParam pageReqVO,
@RequestParam("studentId") Long studentId) {
return success(studentService.getStudentContactPage(pageReqVO, studentId));
}
@PostMapping("/student-contact/create")
@Operation(summary = "创建学生联系人")
@PreAuthorize("@ss.hasPermission('infra:student:create')")
public CommonResult<Long> createStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) {
return success(studentService.createStudentContact(studentContact));
}
@PutMapping("/student-contact/update")
@Operation(summary = "更新学生联系人")
@PreAuthorize("@ss.hasPermission('infra:student:update')")
public CommonResult<Boolean> updateStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) {
studentService.updateStudentContact(studentContact);
return success(true);
}
@DeleteMapping("/student-contact/delete")
@Parameter(name = "id", description = "编号", required = true)
@Operation(summary = "删除学生联系人")
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
public CommonResult<Boolean> deleteStudentContact(@RequestParam("id") Long id) {
studentService.deleteStudentContact(id);
return success(true);
}
@GetMapping("/student-contact/get")
@Operation(summary = "获得学生联系人")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<InfraStudentContactDO> getStudentContact(@RequestParam("id") Long id) {
return success(studentService.getStudentContact(id));
}
// ==================== 子表(学生班主任) ====================
@GetMapping("/student-teacher/page")
@Operation(summary = "获得学生班主任分页")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<PageResult<InfraStudentTeacherDO>> getStudentTeacherPage(PageParam pageReqVO,
@RequestParam("studentId") Long studentId) {
return success(studentService.getStudentTeacherPage(pageReqVO, studentId));
}
@PostMapping("/student-teacher/create")
@Operation(summary = "创建学生班主任")
@PreAuthorize("@ss.hasPermission('infra:student:create')")
public CommonResult<Long> createStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) {
return success(studentService.createStudentTeacher(studentTeacher));
}
@PutMapping("/student-teacher/update")
@Operation(summary = "更新学生班主任")
@PreAuthorize("@ss.hasPermission('infra:student:update')")
public CommonResult<Boolean> updateStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) {
studentService.updateStudentTeacher(studentTeacher);
return success(true);
}
@DeleteMapping("/student-teacher/delete")
@Parameter(name = "id", description = "编号", required = true)
@Operation(summary = "删除学生班主任")
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
public CommonResult<Boolean> deleteStudentTeacher(@RequestParam("id") Long id) {
studentService.deleteStudentTeacher(id);
return success(true);
}
@GetMapping("/student-teacher/get")
@Operation(summary = "获得学生班主任")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<InfraStudentTeacherDO> getStudentTeacher(@RequestParam("id") Long id) {
return success(studentService.getStudentTeacher(id));
}
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生 DO
*
* @author 芋道源码
*/
@TableName("infra_student")
@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraStudentDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 附件
*/
private String video;
/**
* 备注
*/
private String memo;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
/**
* 学生 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
.likeIfPresent(InfraStudentDO::getName, reqVO.getName())
.eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
.eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
.eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
.betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(InfraStudentDO::getId));
}
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import lombok.*;
import java.util.*;
@ -9,27 +9,24 @@ import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 用户分页 Request VO")
@Schema(description = "管理后台 - 学生分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SystemUserPageReqVO extends PageParam {
public class InfraStudentPageReqVO extends PageParam {
@Schema(description = "名字", example = "芋头")
private String name;
@Schema(description = "性别 1", example = "男")
private String sex1;
@Schema(description = "性别 2", example = "1")
private Integer sex2;
@Schema(description = "性别 3", example = "true")
private Boolean sex3;
@Schema(description = "出生日期")
private LocalDateTime birthday;
@Schema(description = "性别", example = "1")
private Integer sex;
@Schema(description = "是否有效", example = "true")
private Boolean enabled;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
@Schema(description = "管理后台 - 学生 Response VO")
@Data
@ExcelIgnoreUnannotated
public class InfraStudentRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("编号")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
@ExcelProperty("名字")
private String name;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
@ExcelProperty("简介")
private String description;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("出生日期")
private LocalDateTime birthday;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "性别", converter = DictConvert.class)
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Integer sex;
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@ExcelProperty(value = "是否有效", converter = DictConvert.class)
@DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Boolean enabled;
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@ExcelProperty("头像")
private String avatar;
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
@ExcelProperty("附件")
private String video;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
@ExcelProperty("备注")
private String memo;
@Schema(description = "创建时间")
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
@Data
public class InfraStudentSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
@NotEmpty(message = "名字不能为空")
private String name;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
@NotEmpty(message = "简介不能为空")
private String description;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "出生日期不能为空")
private LocalDateTime birthday;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "性别不能为空")
private Integer sex;
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否有效不能为空")
private Boolean enabled;
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@NotEmpty(message = "头像不能为空")
private String avatar;
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
@NotEmpty(message = "附件不能为空")
private String video;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
@NotEmpty(message = "备注不能为空")
private String memo;
}

View File

@ -0,0 +1,139 @@
package cn.iocoder.yudao.module.infra.service.demo;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 学生 Service 接口
*
* @author 芋道源码
*/
public interface InfraStudentService {
/**
* 创建学生
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
/**
* 更新学生
*
* @param updateReqVO 更新信息
*/
void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
/**
* 删除学生
*
* @param id 编号
*/
void deleteStudent(Long id);
/**
* 获得学生
*
* @param id 编号
* @return 学生
*/
InfraStudentDO getStudent(Long id);
/**
* 获得学生分页
*
* @param pageReqVO 分页查询
* @return 学生分页
*/
PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
// ==================== 子表(学生联系人) ====================
/**
* 获得学生联系人分页
*
* @param pageReqVO 分页查询
* @param studentId 学生编号
* @return 学生联系人分页
*/
PageResult<InfraStudentContactDO> getStudentContactPage(PageParam pageReqVO, Long studentId);
/**
* 创建学生联系人
*
* @param studentContact 创建信息
* @return 编号
*/
Long createStudentContact(@Valid InfraStudentContactDO studentContact);
/**
* 更新学生联系人
*
* @param studentContact 更新信息
*/
void updateStudentContact(@Valid InfraStudentContactDO studentContact);
/**
* 删除学生联系人
*
* @param id 编号
*/
void deleteStudentContact(Long id);
/**
* 获得学生联系人
*
* @param id 编号
* @return 学生联系人
*/
InfraStudentContactDO getStudentContact(Long id);
// ==================== 子表(学生班主任) ====================
/**
* 获得学生班主任分页
*
* @param pageReqVO 分页查询
* @param studentId 学生编号
* @return 学生班主任分页
*/
PageResult<InfraStudentTeacherDO> getStudentTeacherPage(PageParam pageReqVO, Long studentId);
/**
* 创建学生班主任
*
* @param studentTeacher 创建信息
* @return 编号
*/
Long createStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher);
/**
* 更新学生班主任
*
* @param studentTeacher 更新信息
*/
void updateStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher);
/**
* 删除学生班主任
*
* @param id 编号
*/
void deleteStudentTeacher(Long id);
/**
* 获得学生班主任
*
* @param id 编号
* @return 学生班主任
*/
InfraStudentTeacherDO getStudentTeacher(Long id);
}

View File

@ -0,0 +1,180 @@
package cn.iocoder.yudao.module.infra.service.demo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
/**
* 学生 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class InfraStudentServiceImpl implements InfraStudentService {
@Resource
private InfraStudentMapper studentMapper;
@Resource
private InfraStudentContactMapper studentContactMapper;
@Resource
private InfraStudentTeacherMapper studentTeacherMapper;
@Override
public Long createStudent(InfraStudentSaveReqVO createReqVO) {
// 插入
InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
studentMapper.insert(student);
// 返回
return student.getId();
}
@Override
public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
// 校验存在
validateStudentExists(updateReqVO.getId());
// 更新
InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
studentMapper.updateById(updateObj);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteStudent(Long id) {
// 校验存在
validateStudentExists(id);
// 删除
studentMapper.deleteById(id);
// 删除子表
deleteStudentContactByStudentId(id);
deleteStudentTeacherByStudentId(id);
}
private void validateStudentExists(Long id) {
if (studentMapper.selectById(id) == null) {
throw exception(STUDENT_NOT_EXISTS);
}
}
@Override
public InfraStudentDO getStudent(Long id) {
return studentMapper.selectById(id);
}
@Override
public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
return studentMapper.selectPage(pageReqVO);
}
// ==================== 子表(学生联系人) ====================
@Override
public PageResult<InfraStudentContactDO> getStudentContactPage(PageParam pageReqVO, Long studentId) {
return studentContactMapper.selectPage(pageReqVO, studentId);
}
@Override
public Long createStudentContact(InfraStudentContactDO studentContact) {
studentContactMapper.insert(studentContact);
return studentContact.getId();
}
@Override
public void updateStudentContact(InfraStudentContactDO studentContact) {
// 校验存在
validateStudentContactExists(studentContact.getId());
// 更新
studentContactMapper.updateById(studentContact);
}
@Override
public void deleteStudentContact(Long id) {
// 校验存在
validateStudentContactExists(id);
// 删除
studentContactMapper.deleteById(id);
}
@Override
public InfraStudentContactDO getStudentContact(Long id) {
return studentContactMapper.selectById(id);
}
private void validateStudentContactExists(Long id) {
if (studentContactMapper.selectById(id) == null) {
throw exception(STUDENT_CONTACT_NOT_EXISTS);
}
}
private void deleteStudentContactByStudentId(Long studentId) {
studentContactMapper.deleteByStudentId(studentId);
}
// ==================== 子表(学生班主任) ====================
@Override
public PageResult<InfraStudentTeacherDO> getStudentTeacherPage(PageParam pageReqVO, Long studentId) {
return studentTeacherMapper.selectPage(pageReqVO, studentId);
}
@Override
public Long createStudentTeacher(InfraStudentTeacherDO studentTeacher) {
// 校验是否已经存在
if (studentTeacherMapper.selectByStudentId(studentTeacher.getStudentId()) != null) {
throw exception(STUDENT_TEACHER_EXISTS);
}
// 插入
studentTeacherMapper.insert(studentTeacher);
return studentTeacher.getId();
}
@Override
public void updateStudentTeacher(InfraStudentTeacherDO studentTeacher) {
// 校验存在
validateStudentTeacherExists(studentTeacher.getId());
// 更新
studentTeacherMapper.updateById(studentTeacher);
}
@Override
public void deleteStudentTeacher(Long id) {
// 校验存在
validateStudentTeacherExists(id);
// 删除
studentTeacherMapper.deleteById(id);
}
@Override
public InfraStudentTeacherDO getStudentTeacher(Long id) {
return studentTeacherMapper.selectById(id);
}
private void validateStudentTeacherExists(Long id) {
if (studentTeacherMapper.selectById(id) == null) {
throw exception(STUDENT_TEACHER_NOT_EXISTS);
}
}
private void deleteStudentTeacherByStudentId(Long studentId) {
studentTeacherMapper.deleteByStudentId(studentId);
}
}

View File

@ -0,0 +1,146 @@
package cn.iocoder.yudao.module.infra.service.demo;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link InfraStudentServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(InfraStudentServiceImpl.class)
public class InfraStudentServiceImplTest extends BaseDbUnitTest {
@Resource
private InfraStudentServiceImpl studentService;
@Resource
private InfraStudentMapper studentMapper;
@Test
public void testCreateStudent_success() {
// 准备参数
InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
// 调用
Long studentId = studentService.createStudent(createReqVO);
// 断言
assertNotNull(studentId);
// 校验记录的属性是否正确
InfraStudentDO student = studentMapper.selectById(studentId);
assertPojoEquals(createReqVO, student, "id");
}
@Test
public void testUpdateStudent_success() {
// mock 数据
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
// 准备参数
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
o.setId(dbStudent.getId()); // 设置更新的 ID
});
// 调用
studentService.updateStudent(updateReqVO);
// 校验是否更新正确
InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, student);
}
@Test
public void testUpdateStudent_notExists() {
// 准备参数
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
}
@Test
public void testDeleteStudent_success() {
// mock 数据
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbStudent.getId();
// 调用
studentService.deleteStudent(id);
// 校验数据不存在了
assertNull(studentMapper.selectById(id));
}
@Test
public void testDeleteStudent_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetStudentPage() {
// mock 数据
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
o.setName(null);
o.setBirthday(null);
o.setSex(null);
o.setEnabled(null);
o.setCreateTime(null);
});
studentMapper.insert(dbStudent);
// 测试 name 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
// 测试 birthday 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
// 测试 sex 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
// 测试 enabled 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
// 测试 createTime 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
// 准备参数
InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
reqVO.setName(null);
reqVO.setBirthday(null);
reqVO.setSex(null);
reqVO.setEnabled(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbStudent, pageResult.getList().get(0));
}
}

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生班主任 DO
*
* @author 芋道源码
*/
@TableName("infra_student_teacher")
@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraStudentTeacherDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 学生编号
*/
private Long studentId;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 附件
*/
private String video;
/**
* 备注
*/
private String memo;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 学生班主任 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
default PageResult<InfraStudentTeacherDO> selectPage(PageParam reqVO, Long studentId) {
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentTeacherDO>()
.eq(InfraStudentTeacherDO::getStudentId, studentId)
.orderByDesc(InfraStudentTeacherDO::getId));
}
default int deleteByStudentId(Long studentId) {
return delete(InfraStudentTeacherDO::getStudentId, studentId);
}
}

View File

@ -0,0 +1,17 @@
-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
CREATE TABLE IF NOT EXISTS "infra_student" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar NOT NULL,
"description" varchar NOT NULL,
"birthday" varchar NOT NULL,
"sex" int NOT NULL,
"enabled" bit NOT NULL,
"avatar" varchar NOT NULL,
"video" varchar NOT NULL,
"memo" varchar NOT NULL,
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ("id")
) COMMENT '学生表';
-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
DELETE FROM "infra_student";

View File

@ -4,8 +4,8 @@ INSERT INTO system_menu(
path, icon, component, status, component_name
)
VALUES (
'用户管理', '', 2, 0, 10,
'user', '', 'system/user/index', 0, 'SystemUser'
'学生管理', '', 2, 0, 888,
'student', '', 'infra/demo/index', 0, 'InfraStudent'
);
-- 按钮父菜单ID
@ -18,7 +18,7 @@ INSERT INTO system_menu(
path, icon, component, status
)
VALUES (
'用户查询', 'system:user:query', 3, 1, @parentId,
'学生查询', 'infra:student:query', 3, 1, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
@ -26,7 +26,7 @@ INSERT INTO system_menu(
path, icon, component, status
)
VALUES (
'用户创建', 'system:user:create', 3, 2, @parentId,
'学生创建', 'infra:student:create', 3, 2, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
@ -34,7 +34,7 @@ INSERT INTO system_menu(
path, icon, component, status
)
VALUES (
'用户更新', 'system:user:update', 3, 3, @parentId,
'学生更新', 'infra:student:update', 3, 3, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
@ -42,7 +42,7 @@ INSERT INTO system_menu(
path, icon, component, status
)
VALUES (
'用户删除', 'system:user:delete', 3, 4, @parentId,
'学生删除', 'infra:student:delete', 3, 4, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
@ -50,6 +50,6 @@ INSERT INTO system_menu(
path, icon, component, status
)
VALUES (
'用户导出', 'system:user:export', 3, 5, @parentId,
'学生导出', 'infra:student:export', 3, 5, @parentId,
'', '', '', 0
);
);

View File

@ -0,0 +1,95 @@
import request from '@/config/axios'
export interface StudentVO {
id: number
name: string
description: string
birthday: Date
sex: number
enabled: boolean
avatar: string
video: string
memo: string
}
// 查询学生分页
export const getStudentPage = async (params) => {
return await request.get({ url: `/infra/student/page`, params })
}
// 查询学生详情
export const getStudent = async (id: number) => {
return await request.get({ url: `/infra/student/get?id=` + id })
}
// 新增学生
export const createStudent = async (data: StudentVO) => {
return await request.post({ url: `/infra/student/create`, data })
}
// 修改学生
export const updateStudent = async (data: StudentVO) => {
return await request.put({ url: `/infra/student/update`, data })
}
// 删除学生
export const deleteStudent = async (id: number) => {
return await request.delete({ url: `/infra/student/delete?id=` + id })
}
// 导出学生 Excel
export const exportStudent = async (params) => {
return await request.download({ url: `/infra/student/export-excel`, params })
}
// ==================== 子表(学生联系人) ====================
// 获得学生联系人分页
export const getStudentContactPage = async (params) => {
return await request.get({ url: `/infra/student/student-contact/page`, params })
}
// 新增学生联系人
export const createStudentContact = async (data) => {
return await request.post({ url: `/infra/student/student-contact/create`, data })
}
// 修改学生联系人
export const updateStudentContact = async (data) => {
return await request.put({ url: `/infra/student/student-contact/update`, data })
}
// 删除学生联系人
export const deleteStudentContact = async (id: number) => {
return await request.delete({ url: `/infra/student/student-contact/delete?id=` + id })
}
// 获得学生联系人
export const getStudentContact = async (id: number) => {
return await request.get({ url: `/infra/student/student-contact/get?id=` + id })
}
// ==================== 子表(学生班主任) ====================
// 获得学生班主任分页
export const getStudentTeacherPage = async (params) => {
return await request.get({ url: `/infra/student/student-teacher/page`, params })
}
// 新增学生班主任
export const createStudentTeacher = async (data) => {
return await request.post({ url: `/infra/student/student-teacher/create`, data })
}
// 修改学生班主任
export const updateStudentTeacher = async (data) => {
return await request.put({ url: `/infra/student/student-teacher/update`, data })
}
// 删除学生班主任
export const deleteStudentTeacher = async (id: number) => {
return await request.delete({ url: `/infra/student/student-teacher/delete?id=` + id })
}
// 获得学生班主任
export const getStudentTeacher = async (id: number) => {
return await request.get({ url: `/infra/student/student-teacher/get?id=` + id })
}

View File

@ -0,0 +1,155 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="简介" prop="description">
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="formData.sex" placeholder="请选择性别">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有效" prop="enabled">
<el-radio-group v-model="formData.enabled">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="头像" prop="avatar">
<UploadImg v-model="formData.avatar" />
</el-form-item>
<el-form-item label="附件" prop="video">
<UploadFile v-model="formData.video" />
</el-form-item>
<el-form-item label="备注" prop="memo">
<Editor v-model="formData.memo" height="150px" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StudentApi from '@/api/infra/demo'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
id: undefined,
studentId: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined
})
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, studentId: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.studentId = studentId
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await StudentApi.getStudentContact(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await StudentApi.createStudentContact(data)
message.success(t('common.createSuccess'))
} else {
await StudentApi.updateStudentContact(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
studentId: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,146 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column label="是否有效" align="center" prop="enabled">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
</template>
</el-table-column>
<el-table-column label="头像" align="center" prop="avatar" />
<el-table-column label="附件" align="center" prop="video" />
<el-table-column label="备注" align="center" prop="memo" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<StudentContactForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as StudentApi from '@/api/infra/demo'
import StudentContactForm from './StudentContactForm.vue'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
studentId: undefined
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
(val) => {
queryParams.studentId = val
handleQuery()
},
{ immediate: false }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StudentApi.getStudentContactPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.studentId) {
message.error('请选择一个学生')
return
}
formRef.value.open(type, id, props.studentId)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await StudentApi.deleteStudentContact(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
</script>

View File

@ -10,40 +10,8 @@
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="个人简介">
<Editor v-model="formData.description" height="150px" />
</el-form-item>
<el-form-item label="性别 1" prop="sex1">
<el-select v-model="formData.sex1" placeholder="请选择性别 1">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="性别 2" prop="sex2">
<el-checkbox-group v-model="formData.sex2">
<el-checkbox
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_SEX2)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="性别 3" prop="sex3">
<el-radio-group v-model="formData.sex3">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
<el-form-item label="简介" prop="description">
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
@ -53,16 +21,35 @@
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="备注" prop="memo">
<el-input v-model="formData.memo" type="textarea" placeholder="请输入备注" />
<el-form-item label="性别" prop="sex">
<el-select v-model="formData.sex" placeholder="请选择性别">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="formData.createTime"
type="date"
value-format="x"
placeholder="选择创建时间"
/>
<el-form-item label="是否有效" prop="enabled">
<el-radio-group v-model="formData.enabled">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="头像" prop="avatar">
<UploadImg v-model="formData.avatar" />
</el-form-item>
<el-form-item label="附件" prop="video">
<UploadFile v-model="formData.video" />
</el-form-item>
<el-form-item label="备注" prop="memo">
<Editor v-model="formData.memo" height="150px" />
</el-form-item>
</el-form>
<template #footer>
@ -72,8 +59,8 @@
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getStrDictOptions, getIntDictOptions, getBoolDictOptions } from '@/utils/dict'
import * as UserApi from '@/api/system/user'
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StudentApi from '@/api/infra/demo'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@ -85,18 +72,23 @@ const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
id: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
description: undefined,
sex1: undefined,
sex2: [],
sex3: undefined,
birthday: undefined,
memo: undefined,
createTime: undefined
memo: undefined
})
const formRules = reactive({
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }]
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
@ -110,7 +102,7 @@ const open = async (type: string, id?: number) => {
if (id) {
formLoading.value = true
try {
formData.value = await UserApi.getUser(id)
formData.value = await StudentApi.getStudent(id)
} finally {
formLoading.value = false
}
@ -122,18 +114,16 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as UserApi.UserVO
const data = formData.value as unknown as StudentApi.StudentVO
if (formType.value === 'create') {
await UserApi.createUser(data)
await StudentApi.createStudent(data)
message.success(t('common.createSuccess'))
} else {
await UserApi.updateUser(data)
await StudentApi.updateStudent(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
@ -149,15 +139,13 @@ const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
description: undefined,
sex1: undefined,
sex2: [],
sex3: undefined,
birthday: undefined,
memo: undefined,
createTime: undefined
memo: undefined
}
formRef.value?.resetFields()
}

View File

@ -0,0 +1,155 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="简介" prop="description">
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="formData.sex" placeholder="请选择性别">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有效" prop="enabled">
<el-radio-group v-model="formData.enabled">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="头像" prop="avatar">
<UploadImg v-model="formData.avatar" />
</el-form-item>
<el-form-item label="附件" prop="video">
<UploadFile v-model="formData.video" />
</el-form-item>
<el-form-item label="备注" prop="memo">
<Editor v-model="formData.memo" height="150px" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StudentApi from '@/api/infra/demo'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
id: undefined,
studentId: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined
})
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, studentId: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.studentId = studentId
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await StudentApi.getStudentTeacher(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await StudentApi.createStudentTeacher(data)
message.success(t('common.createSuccess'))
} else {
await StudentApi.updateStudentTeacher(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
studentId: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,146 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column label="是否有效" align="center" prop="enabled">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
</template>
</el-table-column>
<el-table-column label="头像" align="center" prop="avatar" />
<el-table-column label="附件" align="center" prop="video" />
<el-table-column label="备注" align="center" prop="memo" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<StudentTeacherForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as StudentApi from '@/api/infra/demo'
import StudentTeacherForm from './StudentTeacherForm.vue'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
studentId: undefined
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
(val) => {
queryParams.studentId = val
handleQuery()
},
{ immediate: false }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StudentApi.getStudentTeacherPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.studentId) {
message.error('请选择一个学生')
return
}
formRef.value.open(type, id, props.studentId)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await StudentApi.deleteStudentTeacher(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
</script>

View File

@ -0,0 +1,278 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名字" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名字"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="queryParams.birthday"
value-format="YYYY-MM-DD"
type="date"
placeholder="选择出生日期"
clearable
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select
v-model="queryParams.sex"
placeholder="请选择性别"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有效" prop="enabled">
<el-select
v-model="queryParams.enabled"
placeholder="请选择是否有效"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['infra:student:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column label="是否有效" align="center" prop="enabled">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
</template>
</el-table-column>
<el-table-column label="头像" align="center" prop="avatar" />
<el-table-column label="附件" align="center" prop="video" />
<el-table-column label="备注" align="center" prop="memo" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['infra:student:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['infra:student:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<StudentForm ref="formRef" @success="getList" />
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="studentContact">
<el-tab-pane label="学生联系人" name="studentContact">
<StudentContactList :student-id="currentRow.id" />
</el-tab-pane>
<el-tab-pane label="学生班主任" name="studentTeacher">
<StudentTeacherList :student-id="currentRow.id" />
</el-tab-pane>
</el-tabs>
</ContentWrap>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as StudentApi from '@/api/infra/demo'
import StudentForm from './StudentForm.vue'
import StudentContactList from './components/StudentContactList.vue'
import StudentTeacherList from './components/StudentTeacherList.vue'
defineOptions({ name: 'InfraStudent' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: null,
birthday: null,
birthday: [],
sex: null,
enabled: null,
createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StudentApi.getStudentPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await StudentApi.deleteStudent(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await StudentApi.exportStudent(queryParams)
download.excel(data, '学生.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中行操作 */
const currentRow = ref({}) // 选中行
const handleCurrentChange = (row) => {
currentRow.value = row
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03StudentMapper">
<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。

View File

@ -0,0 +1,73 @@
[ {
"contentPath" : "java/InfraStudentPageReqVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
}, {
"contentPath" : "java/InfraStudentRespVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
}, {
"contentPath" : "java/InfraStudentSaveReqVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
}, {
"contentPath" : "java/InfraStudentController",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
}, {
"contentPath" : "java/InfraStudentDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
}, {
"contentPath" : "java/InfraStudentContactDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
}, {
"contentPath" : "java/InfraStudentTeacherDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
}, {
"contentPath" : "java/InfraStudentMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
}, {
"contentPath" : "java/InfraStudentContactMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
}, {
"contentPath" : "java/InfraStudentTeacherMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
}, {
"contentPath" : "xml/InfraStudentMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
}, {
"contentPath" : "java/InfraStudentServiceImpl",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
}, {
"contentPath" : "java/InfraStudentService",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
}, {
"contentPath" : "java/InfraStudentServiceImplTest",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
}, {
"contentPath" : "java/ErrorCodeConstants_手动操作",
"filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
}, {
"contentPath" : "sql/sql",
"filePath" : "sql/sql.sql"
}, {
"contentPath" : "sql/h2",
"filePath" : "sql/h2.sql"
}, {
"contentPath" : "vue/index",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
}, {
"contentPath" : "vue/StudentForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
}, {
"contentPath" : "vue/StudentContactForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
}, {
"contentPath" : "vue/StudentTeacherForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
}, {
"contentPath" : "vue/StudentContactList",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue"
}, {
"contentPath" : "vue/StudentTeacherList",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue"
}, {
"contentPath" : "ts/index",
"filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
} ]

View File

@ -0,0 +1,3 @@
// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意请给“TODO 补充编号”设置一个错误码编号!!!
// ========== 学生 TODO 补充编号 ==========
ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生联系人 DO
*
* @author 芋道源码
*/
@TableName("infra_student_contact")
@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraStudentContactDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 学生编号
*/
private Long studentId;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 附件
*/
private String video;
/**
* 备注
*/
private String memo;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 学生联系人 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
default List<InfraStudentContactDO> selectListByStudentId(Long studentId) {
return selectList(InfraStudentContactDO::getStudentId, studentId);
}
default int deleteByStudentId(Long studentId) {
return delete(InfraStudentContactDO::getStudentId, studentId);
}
}

View File

@ -0,0 +1,117 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
@Tag(name = "管理后台 - 学生")
@RestController
@RequestMapping("/infra/student")
@Validated
public class InfraStudentController {
@Resource
private InfraStudentService studentService;
@PostMapping("/create")
@Operation(summary = "创建学生")
@PreAuthorize("@ss.hasPermission('infra:student:create')")
public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
return success(studentService.createStudent(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新学生")
@PreAuthorize("@ss.hasPermission('infra:student:update')")
public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
studentService.updateStudent(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除学生")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
studentService.deleteStudent(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得学生")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
InfraStudentDO student = studentService.getStudent(id);
return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得学生分页")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出学生 Excel")
@PreAuthorize("@ss.hasPermission('infra:student:export')")
@OperateLog(type = EXPORT)
public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
BeanUtils.toBean(list, InfraStudentRespVO.class));
}
// ==================== 子表(学生联系人) ====================
@GetMapping("/student-contact/list-by-student-id")
@Operation(summary = "获得学生联系人列表")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<List<InfraStudentContactDO>> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) {
return success(studentService.getStudentContactListByStudentId(studentId));
}
// ==================== 子表(学生班主任) ====================
@GetMapping("/student-teacher/get-by-student-id")
@Operation(summary = "获得学生班主任")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<InfraStudentTeacherDO> getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) {
return success(studentService.getStudentTeacherByStudentId(studentId));
}
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生 DO
*
* @author 芋道源码
*/
@TableName("infra_student")
@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraStudentDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 附件
*/
private String video;
/**
* 备注
*/
private String memo;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
/**
* 学生 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
.likeIfPresent(InfraStudentDO::getName, reqVO.getName())
.eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
.eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
.eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
.betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(InfraStudentDO::getId));
}
}

View File

@ -1,33 +1,32 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo;
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import java.time.LocalDateTime;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 用户 Excel 导出 Request VO参数和 SystemUserPageReqVO 是一致的")
@Schema(description = "管理后台 - 学生分页 Request VO")
@Data
public class SystemUserExportReqVO {
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfraStudentPageReqVO extends PageParam {
@Schema(description = "名字", example = "芋头")
private String name;
@Schema(description = "性别 1", example = "男")
private String sex1;
@Schema(description = "性别 2", example = "1")
private Integer sex2;
@Schema(description = "性别 3", example = "true")
private Boolean sex3;
@Schema(description = "出生日期")
private LocalDateTime birthday;
@Schema(description = "性别", example = "1")
private Integer sex;
@Schema(description = "是否有效", example = "true")
private Boolean enabled;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
@Schema(description = "管理后台 - 学生 Response VO")
@Data
@ExcelIgnoreUnannotated
public class InfraStudentRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("编号")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
@ExcelProperty("名字")
private String name;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
@ExcelProperty("简介")
private String description;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("出生日期")
private LocalDateTime birthday;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "性别", converter = DictConvert.class)
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Integer sex;
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@ExcelProperty(value = "是否有效", converter = DictConvert.class)
@DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Boolean enabled;
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@ExcelProperty("头像")
private String avatar;
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
@ExcelProperty("附件")
private String video;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
@ExcelProperty("备注")
private String memo;
@Schema(description = "创建时间")
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
@Data
public class InfraStudentSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
@NotEmpty(message = "名字不能为空")
private String name;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
@NotEmpty(message = "简介不能为空")
private String description;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "出生日期不能为空")
private LocalDateTime birthday;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "性别不能为空")
private Integer sex;
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否有效不能为空")
private Boolean enabled;
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@NotEmpty(message = "头像不能为空")
private String avatar;
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
@NotEmpty(message = "附件不能为空")
private String video;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
@NotEmpty(message = "备注不能为空")
private String memo;
@Schema(description = "学生联系人列表")
private List<InfraStudentContactDO> studentContacts;
@Schema(description = "学生班主任")
private InfraStudentTeacherDO studentTeacher;
}

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.infra.service.demo;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 学生 Service 接口
*
* @author 芋道源码
*/
public interface InfraStudentService {
/**
* 创建学生
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
/**
* 更新学生
*
* @param updateReqVO 更新信息
*/
void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
/**
* 删除学生
*
* @param id 编号
*/
void deleteStudent(Long id);
/**
* 获得学生
*
* @param id 编号
* @return 学生
*/
InfraStudentDO getStudent(Long id);
/**
* 获得学生分页
*
* @param pageReqVO 分页查询
* @return 学生分页
*/
PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
// ==================== 子表(学生联系人) ====================
/**
* 获得学生联系人列表
*
* @param studentId 学生编号
* @return 学生联系人列表
*/
List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId);
// ==================== 子表(学生班主任) ====================
/**
* 获得学生班主任
*
* @param studentId 学生编号
* @return 学生班主任
*/
InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId);
}

View File

@ -0,0 +1,147 @@
package cn.iocoder.yudao.module.infra.service.demo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
/**
* 学生 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class InfraStudentServiceImpl implements InfraStudentService {
@Resource
private InfraStudentMapper studentMapper;
@Resource
private InfraStudentContactMapper studentContactMapper;
@Resource
private InfraStudentTeacherMapper studentTeacherMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createStudent(InfraStudentSaveReqVO createReqVO) {
// 插入
InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
studentMapper.insert(student);
// 插入子表
createStudentContactList(student.getId(), createReqVO.getStudentContacts());
createStudentTeacher(student.getId(), createReqVO.getStudentTeacher());
// 返回
return student.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
// 校验存在
validateStudentExists(updateReqVO.getId());
// 更新
InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
studentMapper.updateById(updateObj);
// 更新子表
updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts());
updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteStudent(Long id) {
// 校验存在
validateStudentExists(id);
// 删除
studentMapper.deleteById(id);
// 删除子表
deleteStudentContactByStudentId(id);
deleteStudentTeacherByStudentId(id);
}
private void validateStudentExists(Long id) {
if (studentMapper.selectById(id) == null) {
throw exception(STUDENT_NOT_EXISTS);
}
}
@Override
public InfraStudentDO getStudent(Long id) {
return studentMapper.selectById(id);
}
@Override
public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
return studentMapper.selectPage(pageReqVO);
}
// ==================== 子表(学生联系人) ====================
@Override
public List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId) {
return studentContactMapper.selectListByStudentId(studentId);
}
private void createStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
list.forEach(o -> o.setStudentId(studentId));
studentContactMapper.insertBatch(list);
}
private void updateStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
deleteStudentContactByStudentId(studentId);
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下1id 冲突2updateTime 不更新
createStudentContactList(studentId, list);
}
private void deleteStudentContactByStudentId(Long studentId) {
studentContactMapper.deleteByStudentId(studentId);
}
// ==================== 子表(学生班主任) ====================
@Override
public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) {
return studentTeacherMapper.selectByStudentId(studentId);
}
private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
if (studentTeacher == null) {
return;
}
studentTeacher.setStudentId(studentId);
studentTeacherMapper.insert(studentTeacher);
}
private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
if (studentTeacher == null) {
return;
}
studentTeacher.setStudentId(studentId);
studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下updateTime 不更新
studentTeacherMapper.insertOrUpdate(studentTeacher);
}
private void deleteStudentTeacherByStudentId(Long studentId) {
studentTeacherMapper.deleteByStudentId(studentId);
}
}

View File

@ -0,0 +1,146 @@
package cn.iocoder.yudao.module.infra.service.demo;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link InfraStudentServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(InfraStudentServiceImpl.class)
public class InfraStudentServiceImplTest extends BaseDbUnitTest {
@Resource
private InfraStudentServiceImpl studentService;
@Resource
private InfraStudentMapper studentMapper;
@Test
public void testCreateStudent_success() {
// 准备参数
InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null);
// 调用
Long studentId = studentService.createStudent(createReqVO);
// 断言
assertNotNull(studentId);
// 校验记录的属性是否正确
InfraStudentDO student = studentMapper.selectById(studentId);
assertPojoEquals(createReqVO, student, "id");
}
@Test
public void testUpdateStudent_success() {
// mock 数据
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
// 准备参数
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> {
o.setId(dbStudent.getId()); // 设置更新的 ID
});
// 调用
studentService.updateStudent(updateReqVO);
// 校验是否更新正确
InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, student);
}
@Test
public void testUpdateStudent_notExists() {
// 准备参数
InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS);
}
@Test
public void testDeleteStudent_success() {
// mock 数据
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class);
studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbStudent.getId();
// 调用
studentService.deleteStudent(id);
// 校验数据不存在了
assertNull(studentMapper.selectById(id));
}
@Test
public void testDeleteStudent_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetStudentPage() {
// mock 数据
InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到
o.setName(null);
o.setBirthday(null);
o.setSex(null);
o.setEnabled(null);
o.setCreateTime(null);
});
studentMapper.insert(dbStudent);
// 测试 name 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null)));
// 测试 birthday 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null)));
// 测试 sex 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null)));
// 测试 enabled 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null)));
// 测试 createTime 不匹配
studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null)));
// 准备参数
InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO();
reqVO.setName(null);
reqVO.setBirthday(null);
reqVO.setSex(null);
reqVO.setEnabled(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbStudent, pageResult.getList().get(0));
}
}

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生班主任 DO
*
* @author 芋道源码
*/
@TableName("infra_student_teacher")
@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraStudentTeacherDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 学生编号
*/
private Long studentId;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 附件
*/
private String video;
/**
* 备注
*/
private String memo;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 学生班主任 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentTeacherMapper extends BaseMapperX<InfraStudentTeacherDO> {
default InfraStudentTeacherDO selectByStudentId(Long studentId) {
return selectOne(InfraStudentTeacherDO::getStudentId, studentId);
}
default int deleteByStudentId(Long studentId) {
return delete(InfraStudentTeacherDO::getStudentId, studentId);
}
}

View File

@ -0,0 +1,17 @@
-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里
CREATE TABLE IF NOT EXISTS "infra_student" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar NOT NULL,
"description" varchar NOT NULL,
"birthday" varchar NOT NULL,
"sex" int NOT NULL,
"enabled" bit NOT NULL,
"avatar" varchar NOT NULL,
"video" varchar NOT NULL,
"memo" varchar NOT NULL,
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ("id")
) COMMENT '学生表';
-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里
DELETE FROM "infra_student";

View File

@ -0,0 +1,55 @@
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status, component_name
)
VALUES (
'学生管理', '', 2, 0, 888,
'student', '', 'infra/demo/index', 0, 'InfraStudent'
);
-- 按钮父菜单ID
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'学生查询', 'infra:student:query', 3, 1, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'学生创建', 'infra:student:create', 3, 2, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'学生更新', 'infra:student:update', 3, 3, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'学生删除', 'infra:student:delete', 3, 4, @parentId,
'', '', '', 0
);
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'学生导出', 'infra:student:export', 3, 5, @parentId,
'', '', '', 0
);

View File

@ -0,0 +1,57 @@
import request from '@/config/axios'
export interface StudentVO {
id: number
name: string
description: string
birthday: Date
sex: number
enabled: boolean
avatar: string
video: string
memo: string
}
// 查询学生分页
export const getStudentPage = async (params) => {
return await request.get({ url: `/infra/student/page`, params })
}
// 查询学生详情
export const getStudent = async (id: number) => {
return await request.get({ url: `/infra/student/get?id=` + id })
}
// 新增学生
export const createStudent = async (data: StudentVO) => {
return await request.post({ url: `/infra/student/create`, data })
}
// 修改学生
export const updateStudent = async (data: StudentVO) => {
return await request.put({ url: `/infra/student/update`, data })
}
// 删除学生
export const deleteStudent = async (id: number) => {
return await request.delete({ url: `/infra/student/delete?id=` + id })
}
// 导出学生 Excel
export const exportStudent = async (params) => {
return await request.download({ url: `/infra/student/export-excel`, params })
}
// ==================== 子表(学生联系人) ====================
// 获得学生联系人列表
export const getStudentContactListByStudentId = async (studentId) => {
return await request.get({ url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId })
}
// ==================== 子表(学生班主任) ====================
// 获得学生班主任
export const getStudentTeacherByStudentId = async (studentId) => {
return await request.get({ url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId })
}

View File

@ -0,0 +1,174 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="名字" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
<el-input v-model="row.name" placeholder="请输入名字" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="简介" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.description`" :rules="formRules.description" class="mb-0px!">
<el-input v-model="row.description" type="textarea" placeholder="请输入简介" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="出生日期" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.birthday`" :rules="formRules.birthday" class="mb-0px!">
<el-date-picker
v-model="row.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="性别" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.sex`" :rules="formRules.sex" class="mb-0px!">
<el-select v-model="row.sex" placeholder="请选择性别">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="是否有效" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.enabled`" :rules="formRules.enabled" class="mb-0px!">
<el-radio-group v-model="row.enabled">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="头像" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.avatar`" :rules="formRules.avatar" class="mb-0px!">
<UploadImg v-model="row.avatar" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="附件" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.video`" :rules="formRules.video" class="mb-0px!">
<UploadFile v-model="row.video" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="备注" min-width="400">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.memo`" :rules="formRules.memo" class="mb-0px!">
<Editor v-model="row.memo" height="150px" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link>—</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加学生联系人</el-button>
</el-row>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StudentApi from '@/api/infra/demo'
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
async (val) => {
// 1. 重置表单
formData.value = []
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await StudentApi.getStudentContactListByStudentId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
id: undefined,
studentId: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined
}
row.studentId = props.studentId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,72 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column label="是否有效" align="center" prop="enabled">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
</template>
</el-table-column>
<el-table-column label="头像" align="center" prop="avatar" />
<el-table-column label="附件" align="center" prop="video" />
<el-table-column label="备注" align="center" prop="memo" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
</el-table>
</ContentWrap>
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as StudentApi from '@/api/infra/demo'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
list.value = await StudentApi.getStudentContactListByStudentId(props.studentId)
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,184 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="简介" prop="description">
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="formData.sex" placeholder="请选择性别">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有效" prop="enabled">
<el-radio-group v-model="formData.enabled">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="头像" prop="avatar">
<UploadImg v-model="formData.avatar" />
</el-form-item>
<el-form-item label="附件" prop="video">
<UploadFile v-model="formData.video" />
</el-form-item>
<el-form-item label="备注" prop="memo">
<Editor v-model="formData.memo" height="150px" />
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="学生联系人" name="studentContact">
<StudentContactForm ref="studentContactFormRef" :student-id="formData.id" />
</el-tab-pane>
<el-tab-pane label="学生班主任" name="studentTeacher">
<StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StudentApi from '@/api/infra/demo'
import StudentContactForm from './components/StudentContactForm.vue'
import StudentTeacherForm from './components/StudentTeacherForm.vue'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
id: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined
})
const formRules = reactive({
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 子表的表单 */
const subTabsName = ref('studentContact')
const studentContactFormRef = ref()
const studentTeacherFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await StudentApi.getStudent(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 校验子表单
try {
await studentContactFormRef.value.validate()
} catch (e) {
subTabsName.value = 'studentContact'
return
}
try {
await studentTeacherFormRef.value.validate()
} catch (e) {
subTabsName.value = 'studentTeacher'
return
}
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as StudentApi.StudentVO
// 拼接子表的数据
data.studentContacts = studentContactFormRef.value.getData()
data.studentTeacher = studentTeacherFormRef.value.getData()
if (formType.value === 'create') {
await StudentApi.createStudent(data)
message.success(t('common.createSuccess'))
} else {
await StudentApi.updateStudent(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,122 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名字" prop="name">
<el-input v-model="formData.name" placeholder="请输入名字" />
</el-form-item>
<el-form-item label="简介" prop="description">
<el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="x"
placeholder="选择出生日期"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select v-model="formData.sex" placeholder="请选择性别">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有效" prop="enabled">
<el-radio-group v-model="formData.enabled">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="头像" prop="avatar">
<UploadImg v-model="formData.avatar" />
</el-form-item>
<el-form-item label="附件" prop="video">
<UploadFile v-model="formData.video" />
</el-form-item>
<el-form-item label="备注" prop="memo">
<Editor v-model="formData.memo" height="150px" />
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StudentApi from '@/api/infra/demo'
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.studentId,
async (val) => {
// 1. 重置表单
formData.value = {
id: undefined,
studentId: undefined,
name: undefined,
description: undefined,
birthday: undefined,
sex: undefined,
enabled: undefined,
avatar: undefined,
video: undefined,
memo: undefined,
}
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
const data = await StudentApi.getStudentTeacherByStudentId(val)
if (!data) {
return
}
formData.value = data
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,76 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="出生日期"
align="center"
prop="birthday"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column label="是否有效" align="center" prop="enabled">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
</template>
</el-table-column>
<el-table-column label="头像" align="center" prop="avatar" />
<el-table-column label="附件" align="center" prop="video" />
<el-table-column label="备注" align="center" prop="memo" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
</el-table>
</ContentWrap>
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as StudentApi from '@/api/infra/demo'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
studentId: undefined // 学生编号(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StudentApi.getStudentTeacherByStudentId(props.studentId)
if (!data) {
return
}
list.value.push(data)
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -17,26 +17,6 @@
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别 1" prop="sex1">
<el-select v-model="queryParams.sex1" placeholder="请选择性别 1" clearable class="!w-240px">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="性别 3" prop="sex3">
<el-select v-model="queryParams.sex3" placeholder="请选择性别 3" clearable class="!w-240px">
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="queryParams.birthday"
@ -47,6 +27,36 @@
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-select
v-model="queryParams.sex"
placeholder="请选择性别"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有效" prop="enabled">
<el-select
v-model="queryParams.enabled"
placeholder="请选择是否有效"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
@ -61,7 +71,12 @@
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" @click="openForm('create')" v-hasPermi="['system:user:create']">
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['infra:student:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
@ -69,7 +84,7 @@
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['system:user:export']"
v-hasPermi="['infra:student:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
@ -80,46 +95,22 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编号" align="center" prop="id">
<!-- 子表的列表 -->
<el-table-column type="expand">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.id" />
</template>
</el-table-column>
<el-table-column label="名字" align="center" prop="name">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.name" />
</template>
</el-table-column>
<el-table-column label="头像" align="center" prop="avatar">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.avatar" />
</template>
</el-table-column>
<el-table-column label="视频" align="center" prop="video">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.video" />
</template>
</el-table-column>
<el-table-column label="个人简介" align="center" prop="description">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.description" />
</template>
</el-table-column>
<el-table-column label="性别 1" align="center" prop="sex1">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_SEX1" :value="scope.row.sex1" />
</template>
</el-table-column>
<el-table-column label="性别 2" align="center" prop="sex2">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_SEX2" :value="scope.row.sex2" />
</template>
</el-table-column>
<el-table-column label="性别 3" align="center" prop="sex3">
<template #default="scope">
<dict-tag :type="DICT_TYPE.SYSTEM_SEX3" :value="scope.row.sex3" />
<el-tabs model-value="studentContact">
<el-tab-pane label="学生联系人" name="studentContact">
<StudentContactList :student-id="scope.row.id" />
</el-tab-pane>
<el-tab-pane label="学生班主任" name="studentTeacher">
<StudentTeacherList :student-id="scope.row.id" />
</el-tab-pane>
</el-tabs>
</template>
</el-table-column>
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="简介" align="center" prop="description" />
<el-table-column
label="出生日期"
align="center"
@ -127,11 +118,19 @@
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="备注" align="center" prop="memo">
<el-table-column label="性别" align="center" prop="sex">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.memo" />
<dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
</template>
</el-table-column>
<el-table-column label="是否有效" align="center" prop="enabled">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
</template>
</el-table-column>
<el-table-column label="头像" align="center" prop="avatar" />
<el-table-column label="附件" align="center" prop="video" />
<el-table-column label="备注" align="center" prop="memo" />
<el-table-column
label="创建时间"
align="center"
@ -145,7 +144,7 @@
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['system:user:update']"
v-hasPermi="['infra:student:update']"
>
编辑
</el-button>
@ -153,7 +152,7 @@
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['system:user:delete']"
v-hasPermi="['infra:student:delete']"
>
删除
</el-button>
@ -170,33 +169,34 @@
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<UserForm ref="formRef" @success="getList" />
<StudentForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE, getStrDictOptions, getBoolDictOptions } from '@/utils/dict'
import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as UserApi from '@/api/system/user'
import UserForm from './UserForm.vue'
import * as StudentApi from '@/api/infra/demo'
import StudentForm from './StudentForm.vue'
import StudentContactList from './components/StudentContactList.vue'
import StudentTeacherList from './components/StudentTeacherList.vue'
defineOptions({ name: 'SystemUser' })
defineOptions({ name: 'InfraStudent' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: null,
sex1: null,
sex2: null,
sex3: null,
birthday: null,
birthday: [],
sex: null,
enabled: null,
createTime: []
})
const queryFormRef = ref() // 搜索的表单
@ -206,7 +206,7 @@ const exportLoading = ref(false) // 导出的加载中
const getList = async () => {
loading.value = true
try {
const data = await UserApi.getUserPage(queryParams)
const data = await StudentApi.getStudentPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
@ -238,7 +238,7 @@ const handleDelete = async (id: number) => {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await UserApi.deleteUser(id)
await StudentApi.deleteStudent(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
@ -252,8 +252,8 @@ const handleExport = async () => {
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await UserApi.exportUser(queryParams)
download.excel(data, '用户.xls')
const data = await StudentApi.exportStudent(queryParams)
download.excel(data, '学生.xls')
} catch {
} finally {
exportLoading.value = false

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.demo02.Demo02CategoryMapper">
<mapper namespace="cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。

View File

@ -1,4 +1,67 @@
[{
"filePath": "",
"contentPath": ""
}]
[ {
"contentPath" : "java/InfraStudentPageReqVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java"
}, {
"contentPath" : "java/InfraStudentRespVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java"
}, {
"contentPath" : "java/InfraStudentSaveReqVO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java"
}, {
"contentPath" : "java/InfraStudentController",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java"
}, {
"contentPath" : "java/InfraStudentDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java"
}, {
"contentPath" : "java/InfraStudentContactDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java"
}, {
"contentPath" : "java/InfraStudentTeacherDO",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java"
}, {
"contentPath" : "java/InfraStudentMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java"
}, {
"contentPath" : "java/InfraStudentContactMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java"
}, {
"contentPath" : "java/InfraStudentTeacherMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java"
}, {
"contentPath" : "xml/InfraStudentMapper",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml"
}, {
"contentPath" : "java/InfraStudentServiceImpl",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java"
}, {
"contentPath" : "java/InfraStudentService",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java"
}, {
"contentPath" : "java/InfraStudentServiceImplTest",
"filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java"
}, {
"contentPath" : "java/ErrorCodeConstants_手动操作",
"filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java"
}, {
"contentPath" : "sql/sql",
"filePath" : "sql/sql.sql"
}, {
"contentPath" : "sql/h2",
"filePath" : "sql/h2.sql"
}, {
"contentPath" : "vue/index",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue"
}, {
"contentPath" : "vue/StudentForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue"
}, {
"contentPath" : "vue/StudentContactForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue"
}, {
"contentPath" : "vue/StudentTeacherForm",
"filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue"
}, {
"contentPath" : "ts/index",
"filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts"
} ]

View File

@ -0,0 +1,3 @@
// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意请给“TODO 补充编号”设置一个错误码编号!!!
// ========== 学生 TODO 补充编号 ==========
ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在");

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生联系人 DO
*
* @author 芋道源码
*/
@TableName("infra_student_contact")
@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraStudentContactDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 学生编号
*/
private Long studentId;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 附件
*/
private String video;
/**
* 备注
*/
private String memo;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 学生联系人 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentContactMapper extends BaseMapperX<InfraStudentContactDO> {
default List<InfraStudentContactDO> selectListByStudentId(Long studentId) {
return selectList(InfraStudentContactDO::getStudentId, studentId);
}
default int deleteByStudentId(Long studentId) {
return delete(InfraStudentContactDO::getStudentId, studentId);
}
}

View File

@ -0,0 +1,117 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService;
@Tag(name = "管理后台 - 学生")
@RestController
@RequestMapping("/infra/student")
@Validated
public class InfraStudentController {
@Resource
private InfraStudentService studentService;
@PostMapping("/create")
@Operation(summary = "创建学生")
@PreAuthorize("@ss.hasPermission('infra:student:create')")
public CommonResult<Long> createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) {
return success(studentService.createStudent(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新学生")
@PreAuthorize("@ss.hasPermission('infra:student:update')")
public CommonResult<Boolean> updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) {
studentService.updateStudent(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除学生")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:student:delete')")
public CommonResult<Boolean> deleteStudent(@RequestParam("id") Long id) {
studentService.deleteStudent(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得学生")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<InfraStudentRespVO> getStudent(@RequestParam("id") Long id) {
InfraStudentDO student = studentService.getStudent(id);
return success(BeanUtils.toBean(student, InfraStudentRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得学生分页")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<PageResult<InfraStudentRespVO>> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) {
PageResult<InfraStudentDO> pageResult = studentService.getStudentPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出学生 Excel")
@PreAuthorize("@ss.hasPermission('infra:student:export')")
@OperateLog(type = EXPORT)
public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<InfraStudentDO> list = studentService.getStudentPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class,
BeanUtils.toBean(list, InfraStudentRespVO.class));
}
// ==================== 子表(学生联系人) ====================
@GetMapping("/student-contact/list-by-student-id")
@Operation(summary = "获得学生联系人列表")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<List<InfraStudentContactDO>> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) {
return success(studentService.getStudentContactListByStudentId(studentId));
}
// ==================== 子表(学生班主任) ====================
@GetMapping("/student-teacher/get-by-student-id")
@Operation(summary = "获得学生班主任")
@Parameter(name = "studentId", description = "学生编号")
@PreAuthorize("@ss.hasPermission('infra:student:query')")
public CommonResult<InfraStudentTeacherDO> getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) {
return success(studentService.getStudentTeacherByStudentId(studentId));
}
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.demo;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生 DO
*
* @author 芋道源码
*/
@TableName("infra_student")
@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InfraStudentDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 名字
*/
private String name;
/**
* 简介
*/
private String description;
/**
* 出生日期
*/
private LocalDateTime birthday;
/**
* 性别
*
* 枚举 {@link TODO system_user_sex 对应的类}
*/
private Integer sex;
/**
* 是否有效
*
* 枚举 {@link TODO infra_boolean_string 对应的类}
*/
private Boolean enabled;
/**
* 头像
*/
private String avatar;
/**
* 附件
*/
private String video;
/**
* 备注
*/
private String memo;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.dal.mysql.demo;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
/**
* 学生 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface InfraStudentMapper extends BaseMapperX<InfraStudentDO> {
default PageResult<InfraStudentDO> selectPage(InfraStudentPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<InfraStudentDO>()
.likeIfPresent(InfraStudentDO::getName, reqVO.getName())
.eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday())
.eqIfPresent(InfraStudentDO::getSex, reqVO.getSex())
.eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled())
.betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(InfraStudentDO::getId));
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 学生分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfraStudentPageReqVO extends PageParam {
@Schema(description = "名字", example = "芋头")
private String name;
@Schema(description = "出生日期")
private LocalDateTime birthday;
@Schema(description = "性别", example = "1")
private Integer sex;
@Schema(description = "是否有效", example = "true")
private Boolean enabled;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
@Schema(description = "管理后台 - 学生 Response VO")
@Data
@ExcelIgnoreUnannotated
public class InfraStudentRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("编号")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
@ExcelProperty("名字")
private String name;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
@ExcelProperty("简介")
private String description;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("出生日期")
private LocalDateTime birthday;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "性别", converter = DictConvert.class)
@DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Integer sex;
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@ExcelProperty(value = "是否有效", converter = DictConvert.class)
@DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Boolean enabled;
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@ExcelProperty("头像")
private String avatar;
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
@ExcelProperty("附件")
private String video;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
@ExcelProperty("备注")
private String memo;
@Schema(description = "创建时间")
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
@Schema(description = "管理后台 - 学生新增/修改 Request VO")
@Data
public class InfraStudentSaveReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头")
@NotEmpty(message = "名字不能为空")
private String name;
@Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍")
@NotEmpty(message = "简介不能为空")
private String description;
@Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "出生日期不能为空")
private LocalDateTime birthday;
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "性别不能为空")
private Integer sex;
@Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否有效不能为空")
private Boolean enabled;
@Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@NotEmpty(message = "头像不能为空")
private String avatar;
@Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4")
@NotEmpty(message = "附件不能为空")
private String video;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注")
@NotEmpty(message = "备注不能为空")
private String memo;
@Schema(description = "学生联系人列表")
private List<InfraStudentContactDO> studentContacts;
@Schema(description = "学生班主任")
private InfraStudentTeacherDO studentTeacher;
}

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.infra.service.demo;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 学生 Service 接口
*
* @author 芋道源码
*/
public interface InfraStudentService {
/**
* 创建学生
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createStudent(@Valid InfraStudentSaveReqVO createReqVO);
/**
* 更新学生
*
* @param updateReqVO 更新信息
*/
void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO);
/**
* 删除学生
*
* @param id 编号
*/
void deleteStudent(Long id);
/**
* 获得学生
*
* @param id 编号
* @return 学生
*/
InfraStudentDO getStudent(Long id);
/**
* 获得学生分页
*
* @param pageReqVO 分页查询
* @return 学生分页
*/
PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO);
// ==================== 子表(学生联系人) ====================
/**
* 获得学生联系人列表
*
* @param studentId 学生编号
* @return 学生联系人列表
*/
List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId);
// ==================== 子表(学生班主任) ====================
/**
* 获得学生班主任
*
* @param studentId 学生编号
* @return 学生班主任
*/
InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId);
}

View File

@ -0,0 +1,147 @@
package cn.iocoder.yudao.module.infra.service.demo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
/**
* 学生 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class InfraStudentServiceImpl implements InfraStudentService {
@Resource
private InfraStudentMapper studentMapper;
@Resource
private InfraStudentContactMapper studentContactMapper;
@Resource
private InfraStudentTeacherMapper studentTeacherMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createStudent(InfraStudentSaveReqVO createReqVO) {
// 插入
InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class);
studentMapper.insert(student);
// 插入子表
createStudentContactList(student.getId(), createReqVO.getStudentContacts());
createStudentTeacher(student.getId(), createReqVO.getStudentTeacher());
// 返回
return student.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateStudent(InfraStudentSaveReqVO updateReqVO) {
// 校验存在
validateStudentExists(updateReqVO.getId());
// 更新
InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class);
studentMapper.updateById(updateObj);
// 更新子表
updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts());
updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteStudent(Long id) {
// 校验存在
validateStudentExists(id);
// 删除
studentMapper.deleteById(id);
// 删除子表
deleteStudentContactByStudentId(id);
deleteStudentTeacherByStudentId(id);
}
private void validateStudentExists(Long id) {
if (studentMapper.selectById(id) == null) {
throw exception(STUDENT_NOT_EXISTS);
}
}
@Override
public InfraStudentDO getStudent(Long id) {
return studentMapper.selectById(id);
}
@Override
public PageResult<InfraStudentDO> getStudentPage(InfraStudentPageReqVO pageReqVO) {
return studentMapper.selectPage(pageReqVO);
}
// ==================== 子表(学生联系人) ====================
@Override
public List<InfraStudentContactDO> getStudentContactListByStudentId(Long studentId) {
return studentContactMapper.selectListByStudentId(studentId);
}
private void createStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
list.forEach(o -> o.setStudentId(studentId));
studentContactMapper.insertBatch(list);
}
private void updateStudentContactList(Long studentId, List<InfraStudentContactDO> list) {
deleteStudentContactByStudentId(studentId);
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下1id 冲突2updateTime 不更新
createStudentContactList(studentId, list);
}
private void deleteStudentContactByStudentId(Long studentId) {
studentContactMapper.deleteByStudentId(studentId);
}
// ==================== 子表(学生班主任) ====================
@Override
public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) {
return studentTeacherMapper.selectByStudentId(studentId);
}
private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
if (studentTeacher == null) {
return;
}
studentTeacher.setStudentId(studentId);
studentTeacherMapper.insert(studentTeacher);
}
private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) {
if (studentTeacher == null) {
return;
}
studentTeacher.setStudentId(studentId);
studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下updateTime 不更新
studentTeacherMapper.insertOrUpdate(studentTeacher);
}
private void deleteStudentTeacherByStudentId(Long studentId) {
studentTeacherMapper.deleteByStudentId(studentId);
}
}

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