Merge branch 'master' of ssh://172.16.8.100:29418/iailab-plat
已修改36个文件
已重命名2个文件
已添加36个文件
| | |
| | | -- config |
| | | INSERT INTO `iailab_plat_system`.`infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (13, 'model', 2, 'model文件备份路径', 'mpkBakFilePath', 'C:\\DLUT\\mpkBakFile', b'1', 'model文件备份路径', '1', '2024-09-12 11:10:25', '1', '2024-09-12 11:10:25', b'0'); |
| | | |
| | | -- ---------------------------- |
| | | -- Table structure for t_mpk_file |
| | | -- ---------------------------- |
| | | -- dist |
| | | INSERT INTO `iailab_plat_system`.`system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (618, '模型方法', 'model_method', 0, '', '1', '2024-09-09 16:11:55', '1', '2024-09-09 16:11:55', b'0', '1970-01-01 00:00:00'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (619, '模型类型', 'model_type', 0, '', '1', '2024-09-13 14:14:26', '1', '2024-09-13 14:14:26', b'0', '1970-01-01 00:00:00'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (620, '模型方法输入类型', 'model_method_setting_type', 0, '', '1', '2024-09-13 15:41:38', '1', '2024-09-13 15:41:38', b'0', '1970-01-01 00:00:00'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (621, '模型方法参数类型', 'model_method_setting_value_type', 0, '', '1', '2024-09-13 15:42:27', '1', '2024-09-13 15:42:27', b'0', '1970-01-01 00:00:00'); |
| | | |
| | | |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1536, 1, 'train', 'train', 'model_method', 0, '', '', '', '1', '2024-09-09 16:12:42', '1', '2024-09-09 16:12:42', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1537, 3, 'control', 'control', 'model_method', 0, '', '', '', '1', '2024-09-09 16:12:54', '1', '2024-09-09 16:13:10', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1538, 2, 'predict', 'predict', 'model_method', 0, '', '', '', '1', '2024-09-09 16:13:05', '1', '2024-09-09 16:13:05', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1539, 1, '预测模型', 'predict', 'model_type', 0, '', '', '', '1', '2024-09-13 14:14:58', '1', '2024-09-13 14:14:58', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1540, 2, '调度模型', 'schedul', 'model_type', 0, '', '', '', '1', '2024-09-13 14:17:53', '1', '2024-09-13 14:17:53', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1541, 1, 'input', 'input', 'model_method_setting_type', 0, '', '', '', '1', '2024-09-13 15:44:08', '1', '2024-09-13 15:44:08', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1542, 2, 'select', 'select', 'model_method_setting_type', 0, '', '', '', '1', '2024-09-13 15:44:17', '1', '2024-09-13 15:44:17', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1543, 3, 'file', 'file', 'model_method_setting_type', 0, '', '', '', '1', '2024-09-13 15:44:24', '1', '2024-09-13 15:44:24', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1544, 1, 'int', 'int', 'model_method_setting_value_type', 0, '', '', '', '1', '2024-09-13 15:44:42', '1', '2024-09-13 15:44:42', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1545, 5, 'file', 'file', 'model_method_setting_value_type', 0, '', '', '', '1', '2024-09-13 15:44:57', '1', '2024-09-14 14:16:24', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1546, 3, 'decimal', 'decimal', 'model_method_setting_value_type', 0, '', '', '', '1', '2024-09-13 15:45:21', '1', '2024-09-13 15:45:21', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1547, 4, 'decimalArray', 'decimalArray', 'model_method_setting_value_type', 0, '', '', '', '1', '2024-09-13 15:45:26', '1', '2024-09-13 15:45:26', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1548, 2, 'string', 'string', 'model_method_setting_value_type', 0, '', '', '', '1', '2024-09-13 15:45:36', '1', '2024-09-14 14:16:30', b'0'); |
| | | INSERT INTO `iailab_plat_system`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1549, 4, 'schedul', 'schedul', 'model_method', 0, '', '', '', '1', '2024-09-14 14:56:44', '1', '2024-09-14 14:56:44', b'0'); |
| | | |
| | | |
| | | -- 业务表 |
| | | DROP TABLE IF EXISTS `t_mpk_file`; |
| | | CREATE TABLE `t_mpk_file` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `py_name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型名称', |
| | | `py_chinese_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型中文名称', |
| | | `file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '源文件保存路径', |
| | | `py_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型类型', |
| | | `pkg_name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '包名', |
| | | `class_name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '类名', |
| | | `py_module` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型路径', |
| | | `icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'icon图片名', |
| | | `menu_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所属菜单', |
| | | `group_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所属组', |
| | | `remark` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注', |
| | | `creator` bigint NULL DEFAULT NULL COMMENT '创建者', |
| | | `create_date` datetime NULL DEFAULT NULL COMMENT '创建时间', |
| | |
| | | INDEX `idx_create_date`(`create_date` ASC) USING BTREE |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'MDK模型文件' ROW_FORMAT = DYNAMIC; |
| | | |
| | | |
| | | -- ---------------------------- |
| | | -- Table structure for t_mpk_generator_code_history |
| | | -- ---------------------------- |
| | | DROP TABLE IF EXISTS `t_mpk_generator_code_history`; |
| | | CREATE TABLE `t_mpk_generator_code_history` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `mdk_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'mdk_id', |
| | | `mdk_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'mdk_id', |
| | | `file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件名', |
| | | `file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件保存路径', |
| | | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注', |
| | | `create_time` timestamp NULL DEFAULT NULL COMMENT '生成时间', |
| | | PRIMARY KEY (`id`) USING BTREE |
| | | PRIMARY KEY (`id`, `mdk_id`) USING BTREE, |
| | | INDEX `del_code_history`(`mdk_id` ASC) USING BTREE, |
| | | CONSTRAINT `del_code_history` FOREIGN KEY (`mdk_id`) REFERENCES `t_mpk_file` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '生成代码记录表' ROW_FORMAT = DYNAMIC; |
| | | |
| | | -- ---------------------------- |
| | | -- Table structure for t_mpk_method_setting |
| | | -- ---------------------------- |
| | | DROP TABLE IF EXISTS `t_mpk_method_setting`; |
| | | CREATE TABLE `t_mpk_method_setting` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `method_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '方法id', |
| | | `setting_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'key', |
| | | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '参数名称', |
| | | `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '参数默认值', |
| | | `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '输入类型', |
| | | `value_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '参数类型', |
| | | `max` int NULL DEFAULT NULL COMMENT '最大值', |
| | | `min` int NULL DEFAULT NULL COMMENT '最小值', |
| | | PRIMARY KEY (`id`, `method_id`) USING BTREE, |
| | | INDEX `del_setting`(`method_id` ASC) USING BTREE, |
| | | INDEX `id`(`id` ASC) USING BTREE, |
| | | CONSTRAINT `del_setting` FOREIGN KEY (`method_id`) REFERENCES `t_mpk_model_method` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '方法参数关联表' ROW_FORMAT = Dynamic; |
| | | |
| | | -- ---------------------------- |
| | | -- Table structure for t_mpk_model_method |
| | |
| | | DROP TABLE IF EXISTS `t_mpk_model_method`; |
| | | CREATE TABLE `t_mpk_model_method` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `mpk_file_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型文件id', |
| | | `mpk_file_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '模型文件id', |
| | | `method_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型方法名', |
| | | `data_length` int NULL DEFAULT 1 COMMENT '输入个数', |
| | | `model` int NULL DEFAULT 0 COMMENT '是否有model(0:否,1:是)', |
| | | PRIMARY KEY (`id`) USING BTREE |
| | | `result_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '结果key', |
| | | PRIMARY KEY (`id`, `mpk_file_id`) USING BTREE, |
| | | INDEX `id`(`id` ASC) USING BTREE, |
| | | INDEX `del_method`(`mpk_file_id` ASC) USING BTREE, |
| | | CONSTRAINT `del_method` FOREIGN KEY (`mpk_file_id`) REFERENCES `t_mpk_file` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; |
| | | |
| | | -- ---------------------------- |
| | |
| | | DROP TABLE IF EXISTS `t_mpk_project_model`; |
| | | CREATE TABLE `t_mpk_project_model` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `project_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '项目id', |
| | | `model_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型id', |
| | | PRIMARY KEY (`id`) USING BTREE |
| | | `project_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '项目id', |
| | | `model_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '模型id', |
| | | PRIMARY KEY (`id`, `project_id`, `model_id`) USING BTREE, |
| | | INDEX `del_p`(`project_id` ASC) USING BTREE, |
| | | INDEX `del_m`(`model_id` ASC) USING BTREE, |
| | | CONSTRAINT `del_m` FOREIGN KEY (`model_id`) REFERENCES `t_mpk_file` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT, |
| | | CONSTRAINT `del_p` FOREIGN KEY (`project_id`) REFERENCES `t_mpk_project` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '项目模型关联表' ROW_FORMAT = DYNAMIC; |
| | | |
| | | -- ---------------------------- |
| | |
| | | DROP TABLE IF EXISTS `t_mpk_project_package_history`; |
| | | CREATE TABLE `t_mpk_project_package_history` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `project_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '项目id', |
| | | `project_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '项目id', |
| | | `file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件名', |
| | | `file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '文件路径', |
| | | `version` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '版本号', |
| | | `log` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新日志', |
| | | `model_names` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '打包模型名称(“,”分割)', |
| | | `create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间', |
| | | PRIMARY KEY (`id`) USING BTREE |
| | | PRIMARY KEY (`id`, `project_id`) USING BTREE, |
| | | INDEX `del_package_history`(`project_id` ASC) USING BTREE, |
| | | CONSTRAINT `del_package_history` FOREIGN KEY (`project_id`) REFERENCES `t_mpk_project` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '项目打包历史记录表' ROW_FORMAT = DYNAMIC; |
| | | |
| | | -- ---------------------------- |
| | |
| | | DROP TABLE IF EXISTS `t_mpk_project_package_history_model`; |
| | | CREATE TABLE `t_mpk_project_package_history_model` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `project_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '项目id', |
| | | `project_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '项目id', |
| | | `package_history_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '打包历史id', |
| | | `py_name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型名称', |
| | | `pkg_name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '包名', |
| | | `py_module` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型路径', |
| | | `remark` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型备注', |
| | | `method_info` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模型方法信息', |
| | | PRIMARY KEY (`id`) USING BTREE |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '打包历史模型关联表' ROW_FORMAT = Dynamic; |
| | | `method_info` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '模型方法信息', |
| | | PRIMARY KEY (`id`, `project_id`) USING BTREE, |
| | | INDEX `del_package_model`(`project_id` ASC) USING BTREE, |
| | | CONSTRAINT `del_package_model` FOREIGN KEY (`project_id`) REFERENCES `t_mpk_project` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '打包历史模型关联表' ROW_FORMAT = Dynamic; |
| | | |
| | | -- ---------------------------- |
| | | -- Table structure for t_mpk_setting_select |
| | | -- ---------------------------- |
| | | DROP TABLE IF EXISTS `t_mpk_setting_select`; |
| | | CREATE TABLE `t_mpk_setting_select` ( |
| | | `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id', |
| | | `setting_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '参数id', |
| | | `select_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'key', |
| | | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名称', |
| | | PRIMARY KEY (`id`, `setting_id`) USING BTREE, |
| | | INDEX `del_select`(`setting_id` ASC) USING BTREE, |
| | | CONSTRAINT `del_select` FOREIGN KEY (`setting_id`) REFERENCES `t_mpk_method_setting` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT |
| | | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '参数选项关联表' ROW_FORMAT = Dynamic; |
| | |
| | | package com.iailab.module.model.mpk.controller.admin; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.iailab.framework.common.page.PageData; |
| | | import com.iailab.framework.common.pojo.CommonResult; |
| | | import com.iailab.framework.common.util.date.DateUtils; |
| | | import com.iailab.module.model.mpk.common.utils.Readtxt; |
| | | import com.iailab.module.model.mpk.dto.MpkFileDTO; |
| | | import com.iailab.module.model.mpk.service.MdkFileService; |
| | | import com.iailab.module.model.mpk.service.MpkFileService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import org.apache.commons.io.IOUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | |
| | | @RequestMapping("/model/mpk/file") |
| | | public class MpkFileController { |
| | | @Autowired |
| | | private MdkFileService mdkFileService; |
| | | private MpkFileService mpkFileService; |
| | | |
| | | @GetMapping("page") |
| | | @Operation(summary = "分页") |
| | | public CommonResult<PageData<MpkFileDTO>> page(@RequestParam Map<String, Object> params) { |
| | | PageData<MpkFileDTO> page = mdkFileService.page(params); |
| | | PageData<MpkFileDTO> page = mpkFileService.page(params); |
| | | |
| | | return success(page); |
| | | } |
| | | |
| | | @GetMapping("{id}") |
| | | public CommonResult<MpkFileDTO> info(@PathVariable("id") String id) { |
| | | MpkFileDTO schedule = mdkFileService.get(id); |
| | | MpkFileDTO schedule = mpkFileService.get(id); |
| | | |
| | | return success(schedule); |
| | | } |
| | | |
| | | @GetMapping("list") |
| | | public CommonResult<List<MpkFileDTO>> list() { |
| | | List<MpkFileDTO> list = mdkFileService.list(new HashMap<>()); |
| | | List<MpkFileDTO> list = mpkFileService.list(new HashMap<>()); |
| | | |
| | | return success(list); |
| | | } |
| | | |
| | | @PostMapping |
| | | public CommonResult save(@RequestBody MpkFileDTO dto) { |
| | | mdkFileService.save(dto); |
| | | mpkFileService.save(dto); |
| | | return CommonResult.success(); |
| | | } |
| | | |
| | | @DeleteMapping |
| | | public CommonResult delete(String id) { |
| | | mdkFileService.delete(id); |
| | | mpkFileService.delete(id); |
| | | return CommonResult.success(); |
| | | } |
| | | |
| | | @PutMapping |
| | | public CommonResult update(@RequestBody MpkFileDTO dto) { |
| | | mdkFileService.update(dto); |
| | | mpkFileService.update(dto); |
| | | return CommonResult.success(); |
| | | } |
| | | |
| | | @GetMapping("generat") |
| | | public void generat(String id, String remark,String zipFileName, HttpServletResponse response) throws IOException { |
| | | byte[] data = mdkFileService.generatorCode(id, remark,zipFileName); |
| | | byte[] data = mpkFileService.generatorCode(id, remark,zipFileName); |
| | | |
| | | response.reset(); |
| | | response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(zipFileName, "UTF-8") + "\""); |
| | |
| | | public void packageModel(String ids ,String projectId,String log ,String projectName,String version,String zipFileName,HttpServletResponse response) throws IOException { |
| | | byte[] data; |
| | | try { |
| | | data = mdkFileService.packageModel(Arrays.asList(ids.split(",")),projectId,projectName,zipFileName,log,version); |
| | | data = mpkFileService.packageModel(Arrays.asList(ids.split(",")),projectId,projectName,zipFileName,log,version); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException("模型打包失败",e); |
| | | } |
| | |
| | | @PostMapping("/upload") |
| | | @Operation(summary = "python文件上传") |
| | | public CommonResult<Map<String,String>> importExcel(@RequestParam("file") MultipartFile file) throws Exception { |
| | | Map<String,String> result = mdkFileService.savePyFile(file); |
| | | Map<String,String> result = mpkFileService.savePyFile(file); |
| | | return success(result); |
| | | } |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.dao; |
| | | |
| | | import com.iailab.framework.common.dao.BaseDao; |
| | | import com.iailab.module.model.mpk.entity.MethodSettingEntity; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * @description: |
| | | * @author: dzd |
| | | * @date: 2024/9/14 15:11 |
| | | **/ |
| | | @Mapper |
| | | public interface MethodSettingDao extends BaseDao<MethodSettingEntity> { |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.dao; |
| | | |
| | | import com.iailab.framework.common.dao.BaseDao; |
| | | import com.iailab.module.model.mpk.entity.SettingSelectEntity; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * @description: |
| | | * @author: dzd |
| | | * @date: 2024/9/14 15:11 |
| | | **/ |
| | | @Mapper |
| | | public interface SettingSelectDao extends BaseDao<SettingSelectEntity> { |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.dto; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @description: 方法参数关联表 |
| | | * @author: dzd |
| | | * @date: 2024/9/13 15:49 |
| | | **/ |
| | | @Data |
| | | public class MethodSettingDTO implements Serializable { |
| | | |
| | | /** |
| | | * id |
| | | */ |
| | | private String id; |
| | | |
| | | /** |
| | | * '方法id' |
| | | */ |
| | | private String methodId; |
| | | |
| | | /** |
| | | * key |
| | | */ |
| | | private String settingKey; |
| | | |
| | | /** |
| | | * 参数名称 |
| | | */ |
| | | private String name; |
| | | |
| | | /** |
| | | * 参数默认值 |
| | | */ |
| | | private String value; |
| | | |
| | | /** |
| | | * 输入类型 |
| | | */ |
| | | private String type; |
| | | |
| | | /** |
| | | * 参数类型 |
| | | */ |
| | | private String valueType; |
| | | |
| | | /** |
| | | * 最大值 |
| | | */ |
| | | private Integer max; |
| | | |
| | | /** |
| | | * 最小值 |
| | | */ |
| | | private Integer min; |
| | | |
| | | private List<SettingSelectDTO> settingSelects; |
| | | } |
| | |
| | | package com.iailab.module.model.mpk.dto; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @description: MPK模型方法 |
| | |
| | | private Integer dataLength; |
| | | |
| | | private Integer model; |
| | | |
| | | private String resultKey; |
| | | |
| | | private List<MethodSettingDTO> methodSettings; |
| | | } |
| | |
| | | |
| | | private String pyName; |
| | | |
| | | private String pyChineseName; |
| | | |
| | | private String filePath; |
| | | |
| | | private String pyType; |
| | |
| | | private String className; |
| | | |
| | | private String pyModule; |
| | | |
| | | private String icon; |
| | | |
| | | private String menuName; |
| | | |
| | | private String groupName; |
| | | |
| | | private String remark; |
| | | |
| | |
| | | |
| | | private Date createDate; |
| | | |
| | | private List<ModelMethodEntity> modelMethods; |
| | | private List<ModelMethodDTO> modelMethods; |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.dto; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @description: 参数选项关联表 |
| | | * @author: dzd |
| | | * @date: 2024/9/13 15:49 |
| | | **/ |
| | | @Data |
| | | public class SettingSelectDTO implements Serializable { |
| | | |
| | | /** |
| | | * id |
| | | */ |
| | | private String id; |
| | | |
| | | /** |
| | | * '参数id' |
| | | */ |
| | | private String settingId; |
| | | |
| | | /** |
| | | * key |
| | | */ |
| | | private String selectKey; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | private String name; |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | import org.checkerframework.checker.units.qual.min; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @description: 方法参数关联表 |
| | | * @author: dzd |
| | | * @date: 2024/9/13 15:49 |
| | | **/ |
| | | @Data |
| | | @TableName("t_mpk_method_setting") |
| | | public class MethodSettingEntity implements Serializable { |
| | | |
| | | /** |
| | | * id |
| | | */ |
| | | @TableId |
| | | private String id; |
| | | |
| | | /** |
| | | * 方法id |
| | | */ |
| | | private String methodId; |
| | | |
| | | /** |
| | | * key |
| | | */ |
| | | private String settingKey; |
| | | |
| | | /** |
| | | * 参数名称 |
| | | */ |
| | | private String name; |
| | | |
| | | /** |
| | | * 参数默认值 |
| | | */ |
| | | private String value; |
| | | |
| | | /** |
| | | * 输入类型 |
| | | */ |
| | | private String type; |
| | | |
| | | /** |
| | | * 参数类型 |
| | | */ |
| | | private String valueType; |
| | | |
| | | /** |
| | | * 最大值 |
| | | */ |
| | | private Integer max; |
| | | |
| | | /** |
| | | * 最小值 |
| | | */ |
| | | private Integer min; |
| | | } |
| | |
| | | * 是否有model(0:否,1:是) |
| | | */ |
| | | private Integer model; |
| | | /** |
| | | * 结果key |
| | | */ |
| | | private String resultKey; |
| | | } |
| | |
| | | private String pyName; |
| | | |
| | | /** |
| | | * 模型中文名称 |
| | | */ |
| | | private String pyChineseName; |
| | | |
| | | /** |
| | | * 源文件保存路径 |
| | | */ |
| | | private String filePath; |
| | |
| | | private String pyModule; |
| | | |
| | | /** |
| | | * icon图片名 |
| | | */ |
| | | private String icon; |
| | | |
| | | /** |
| | | * 所属菜单 |
| | | */ |
| | | private String menuName; |
| | | |
| | | /** |
| | | * 所属组 |
| | | */ |
| | | private String groupName; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | private String remark; |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * @description: 参数选项关联表 |
| | | * @author: dzd |
| | | * @date: 2024/9/13 15:49 |
| | | **/ |
| | | @Data |
| | | @TableName("t_mpk_setting_select") |
| | | public class SettingSelectEntity implements Serializable { |
| | | |
| | | /** |
| | | * id |
| | | */ |
| | | @TableId |
| | | private String id; |
| | | |
| | | /** |
| | | * '参数id' |
| | | */ |
| | | private String settingId; |
| | | |
| | | /** |
| | | * key |
| | | */ |
| | | private String selectKey; |
| | | |
| | | /** |
| | | * 名称 |
| | | */ |
| | | private String name; |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.service; |
| | | |
| | | import com.iailab.framework.common.service.BaseService; |
| | | import com.iailab.module.model.mpk.entity.MethodSettingEntity; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @description: |
| | | * @author: dzd |
| | | * @date: 2024/9/14 15:10 |
| | | **/ |
| | | public interface MethodSettingService extends BaseService<MethodSettingEntity> { |
| | | } |
文件名从 iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/MdkFileService.java 修改 |
| | |
| | | * @Description |
| | | * @createTime 2024年08月14日 |
| | | */ |
| | | public interface MdkFileService extends BaseService<MpkFileEntity> { |
| | | public interface MpkFileService extends BaseService<MpkFileEntity> { |
| | | |
| | | PageData<MpkFileDTO> page(Map<String, Object> params); |
| | | |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.service; |
| | | |
| | | import com.iailab.framework.common.service.BaseService; |
| | | import com.iailab.module.model.mpk.entity.SettingSelectEntity; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @description: |
| | | * @author: dzd |
| | | * @date: 2024/9/14 15:10 |
| | | **/ |
| | | public interface SettingSelectService extends BaseService<SettingSelectEntity> { |
| | | |
| | | void deleteByMap(Map<String, Object> map); |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.iailab.framework.common.service.impl.BaseServiceImpl; |
| | | import com.iailab.module.model.mpk.dao.MethodSettingDao; |
| | | import com.iailab.module.model.mpk.entity.MethodSettingEntity; |
| | | import com.iailab.module.model.mpk.service.MethodSettingService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @description: |
| | | * @author: dzd |
| | | * @date: 2024/9/14 15:12 |
| | | **/ |
| | | @Slf4j |
| | | @Service |
| | | public class MethodSettingServiceImpl extends BaseServiceImpl<MethodSettingDao, MethodSettingEntity> implements MethodSettingService { |
| | | } |
文件名从 iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/impl/MdkFileServiceImpl.java 修改 |
| | |
| | | import com.iailab.module.model.mpk.common.MdkConstant; |
| | | import com.iailab.module.model.mpk.common.utils.GenUtils; |
| | | import com.iailab.module.model.mpk.dao.MpkFileDao; |
| | | import com.iailab.module.model.mpk.dto.GeneratorCodeHistoryDTO; |
| | | import com.iailab.module.model.mpk.dto.MpkFileDTO; |
| | | import com.iailab.module.model.mpk.dto.ProjectPackageHistoryDTO; |
| | | import com.iailab.module.model.mpk.entity.GeneratorCodeHistoryEntity; |
| | | import com.iailab.module.model.mpk.entity.ModelMethodEntity; |
| | | import com.iailab.module.model.mpk.entity.MpkFileEntity; |
| | | import com.iailab.module.model.mpk.entity.ProjectPackageHistoryModelEntity; |
| | | import com.iailab.module.model.mpk.dto.*; |
| | | import com.iailab.module.model.mpk.entity.*; |
| | | import com.iailab.module.model.mpk.service.*; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FileUtils; |
| | |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | import javax.annotation.Resource; |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class MdkFileServiceImpl extends BaseServiceImpl<MpkFileDao, MpkFileEntity> implements MdkFileService { |
| | | public class MpkFileServiceImpl extends BaseServiceImpl<MpkFileDao, MpkFileEntity> implements MpkFileService { |
| | | |
| | | @Autowired |
| | | private GeneratorCodeHistoryService generatorCodeHistoryService; |
| | |
| | | private ProjectPackageHistoryService projectPackageHistoryService; |
| | | @Autowired |
| | | private ModelMethodService modelMethodService; |
| | | @Autowired |
| | | private MethodSettingService methodSettingService; |
| | | @Autowired |
| | | private SettingSelectService settingSelectService; |
| | | @Autowired |
| | | private ProjectPackageHistoryModelService projectPackageHistoryModelService; |
| | | |
| | |
| | | updateById(entity); |
| | | |
| | | String mpkId = dto.getId(); |
| | | // 删除模型方法 |
| | | // 删除模型方法 会级联删除setting和select |
| | | deleteModelMethod(mpkId); |
| | | |
| | | // 添加模型方法 |
| | | insertModelMethod(dto.getModelMethods(),mpkId); |
| | | } |
| | | |
| | | private void insertModelMethod(List<ModelMethodEntity> modelMethods,String mpkId) { |
| | | private void insertModelMethod(List<ModelMethodDTO> modelMethods, String mpkId) { |
| | | List<MethodSettingDTO> methodSettingList = new ArrayList<>(); |
| | | if (!CollectionUtils.isEmpty(modelMethods)) { |
| | | modelMethods.forEach(e -> { |
| | | e.setId(UUID.randomUUID().toString()); |
| | | String methodId = UUID.randomUUID().toString(); |
| | | e.setId(methodId); |
| | | e.setMpkFileId(mpkId); |
| | | |
| | | e.getMethodSettings().forEach(s -> { |
| | | s.setId(UUID.randomUUID().toString()); |
| | | s.setMethodId(methodId); |
| | | methodSettingList.add(s); |
| | | }); |
| | | |
| | | }); |
| | | modelMethodService.insertBatch(modelMethods); |
| | | modelMethodService.insertBatch(ConvertUtils.sourceToTarget(modelMethods, ModelMethodEntity.class)); |
| | | |
| | | //添加setting |
| | | insertMethodSetting(methodSettingList); |
| | | } |
| | | } |
| | | |
| | | private void insertMethodSetting(List<MethodSettingDTO> methodSettings) { |
| | | List<SettingSelectEntity> settingSelectList = new ArrayList<>(); |
| | | if (!CollectionUtils.isEmpty(methodSettings)) { |
| | | methodSettings.forEach(e -> { |
| | | String settingId = UUID.randomUUID().toString(); |
| | | e.setId(settingId); |
| | | |
| | | e.getSettingSelects().forEach(s -> { |
| | | s.setId(UUID.randomUUID().toString()); |
| | | s.setSettingId(settingId); |
| | | settingSelectList.add(ConvertUtils.sourceToTarget(s,SettingSelectEntity.class)); |
| | | }); |
| | | |
| | | }); |
| | | methodSettingService.insertBatch(ConvertUtils.sourceToTarget(methodSettings, MethodSettingEntity.class)); |
| | | |
| | | //添加select |
| | | settingSelectService.insertBatch(settingSelectList); |
| | | } |
| | | } |
| | | |
| | | private void deleteModelMethod(String mpkId) { |
| | | Map<String,Object> map = new HashMap<>(); |
| | | map.put("mpkFileId", mpkId); |
| | |
| | | } |
| | | } |
| | | |
| | | //删除 |
| | | deleteById(id); |
| | | |
| | | //删除备份文件 |
| | | Map<String,Object> map1 = new HashMap<>(); |
| | | map1.put("mdkId",id); |
| | |
| | | } |
| | | }); |
| | | |
| | | //删除生成历史 |
| | | //删除 会级联删除掉关联表 |
| | | deleteById(id); |
| | | |
| | | generatorCodeHistoryService.deleteByMap(map1); |
| | | //删除生成历史 |
| | | // generatorCodeHistoryService.deleteByMap(map1); |
| | | |
| | | //删除关联项目 |
| | | Map<String,Object> map = new HashMap<>(); |
| | | map.put("modelId",id); |
| | | projectModelService.deleteByMap(map); |
| | | // Map<String,Object> map = new HashMap<>(); |
| | | // map.put("modelId",id); |
| | | // projectModelService.deleteByMap(map); |
| | | |
| | | //删除模型方法 |
| | | deleteModelMethod(id); |
| | | // deleteModelMethod(id); |
| | | |
| | | } |
| | | |
| | |
| | | entity.setPkgName(e.getPkgName()); |
| | | entity.setPyModule(e.getPyModule()); |
| | | entity.setRemark(e.getRemark()); |
| | | List<ModelMethodEntity> methods = e.getModelMethods(); |
| | | List<ModelMethodDTO> methods = e.getModelMethods(); |
| | | if (!CollectionUtils.isEmpty(methods)) { |
| | | entity.setMethodInfo(JSON.toJSONString(methods)); |
| | | } |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void delete(String id) { |
| | | |
| | | //删除 |
| | | baseDao.deleteById(id); |
| | | |
| | | //删除模型关联 |
| | | //删除备份文件 |
| | | Map<String,Object> map = new HashMap<>(); |
| | | map.put("projectId",id); |
| | | projectModelService.deleteByMap(map); |
| | | |
| | | //删除备份文件 |
| | | List<ProjectPackageHistoryDTO> list = projectPackageHistoryService.list(map); |
| | | list.forEach(e -> { |
| | | File file = new File(e.getFilePath()); |
| | |
| | | } |
| | | }); |
| | | |
| | | //删除 (级联删除) |
| | | baseDao.deleteById(id); |
| | | |
| | | //删除模型关联 |
| | | // projectModelService.deleteByMap(map); |
| | | |
| | | //删除打包历史 |
| | | projectPackageHistoryService.deleteByMap(map); |
| | | // projectPackageHistoryService.deleteByMap(map); |
| | | |
| | | //删除打包历史模型关联 |
| | | projectPackageHistoryModelService.deleteByMap(map); |
| | | // projectPackageHistoryModelService.deleteByMap(map); |
| | | } |
| | | |
| | | @Override |
对比新文件 |
| | |
| | | package com.iailab.module.model.mpk.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.iailab.framework.common.service.impl.BaseServiceImpl; |
| | | import com.iailab.module.model.mpk.dao.SettingSelectDao; |
| | | import com.iailab.module.model.mpk.entity.SettingSelectEntity; |
| | | import com.iailab.module.model.mpk.service.SettingSelectService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @description: |
| | | * @author: dzd |
| | | * @date: 2024/9/14 15:13 |
| | | **/ |
| | | @Slf4j |
| | | @Service |
| | | public class SettingSelectServiceImpl extends BaseServiceImpl<SettingSelectDao, SettingSelectEntity> implements SettingSelectService { |
| | | |
| | | |
| | | @Override |
| | | public void deleteByMap(Map<String, Object> map) { |
| | | baseDao.delete(getWrapper(map)); |
| | | } |
| | | |
| | | private QueryWrapper<SettingSelectEntity> getWrapper(Map<String, Object> params) { |
| | | String settingId = (String) params.get("settingId"); |
| | | |
| | | QueryWrapper<SettingSelectEntity> wrapper = new QueryWrapper<>(); |
| | | wrapper.eq(StringUtils.isNotBlank(settingId), "setting_id", settingId); |
| | | |
| | | return wrapper; |
| | | } |
| | | } |
| | |
| | | <resultMap id="mpkFile" type="com.iailab.module.model.mpk.dto.MpkFileDTO"> |
| | | <id property="id" column="id"/> |
| | | <result property="pyName" column="py_name"/> |
| | | <result property="pyChineseName" column="py_chinese_name"/> |
| | | <result property="filePath" column="file_path"/> |
| | | <result property="pyType" column="py_type"/> |
| | | <result property="pkgName" column="pkg_name"/> |
| | | <result property="className" column="class_name"/> |
| | | <result property="pyModule" column="py_module"/> |
| | | <result property="icon" column="icon"/> |
| | | <result property="menuName" column="menu_name"/> |
| | | <result property="groupName" column="group_name"/> |
| | | <result property="remark" column="remark"/> |
| | | <result property="creator" column="creator"/> |
| | | <result property="createDate" column="create_date"/> |
| | | <result property="updater" column="updater"/> |
| | | <result property="updateDate" column="update_date"/> |
| | | <collection property="modelMethods" ofType="com.iailab.module.model.mpk.entity.ModelMethodEntity"> |
| | | <collection property="modelMethods" ofType="com.iailab.module.model.mpk.dto.ModelMethodDTO"> |
| | | <id property="id" column="method_id"/> |
| | | <result property="methodName" column="method_name"/> |
| | | <result property="dataLength" column="data_length"/> |
| | | <result property="model" column="model"/> |
| | | <result property="resultKey" column="result_key"/> |
| | | <collection property="methodSettings" ofType="com.iailab.module.model.mpk.dto.MethodSettingDTO"> |
| | | <id property="id" column="setting_id"/> |
| | | <result property="settingKey" column="setting_key"/> |
| | | <result property="name" column="setting_name"/> |
| | | <result property="value" column="value"/> |
| | | <result property="type" column="type"/> |
| | | <result property="valueType" column="value_type"/> |
| | | <result property="max" column="max"/> |
| | | <result property="min" column="min"/> |
| | | <collection property="settingSelects" ofType="com.iailab.module.model.mpk.dto.SettingSelectDTO"> |
| | | <id property="id" column="select_id"/> |
| | | <result property="selectKey" column="select_key"/> |
| | | <result property="name" column="select_name"/> |
| | | </collection> |
| | | </collection> |
| | | </collection> |
| | | </resultMap> |
| | | |
| | |
| | | b.id method_id, |
| | | b.method_name, |
| | | b.data_length, |
| | | b.model |
| | | b.model, |
| | | b.result_key, |
| | | c.id setting_id, |
| | | c.setting_key, |
| | | c.name setting_name, |
| | | c.value, |
| | | c.type, |
| | | c.value_type, |
| | | c.max, |
| | | c.min, |
| | | d.id select_id, |
| | | d.select_key, |
| | | d.name select_name |
| | | FROM |
| | | t_mpk_file a |
| | | LEFT JOIN t_mpk_model_method b ON a.id = b.mpk_file_id |
| | | LEFT JOIN t_mpk_method_setting c ON b.id = c.method_id |
| | | LEFT JOIN t_mpk_setting_select d ON c.id = d.setting_id |
| | | WHERE a.id = #{id} |
| | | </select> |
| | | <select id="selectByIds" resultMap="mpkFile"> |
| | |
| | | b.id method_id, |
| | | b.method_name, |
| | | b.data_length, |
| | | b.model |
| | | b.model, |
| | | b.result_key, |
| | | c.id setting_id, |
| | | c.setting_key, |
| | | c.name setting_name, |
| | | c.value, |
| | | c.type, |
| | | c.value_type, |
| | | c.max, |
| | | c.min, |
| | | d.id select_id, |
| | | d.select_key, |
| | | d.name select_name |
| | | FROM |
| | | t_mpk_file a |
| | | LEFT JOIN t_mpk_model_method b ON a.id = b.mpk_file_id |
| | | LEFT JOIN t_mpk_method_setting c ON b.id = c.method_id |
| | | LEFT JOIN t_mpk_setting_select d ON c.id = d.setting_id |
| | | WHERE a.id in |
| | | <foreach collection="ids" item="item" open="(" close=")" separator=","> |
| | | #{item} |
| | |
| | | </select> |
| | | <select id="getProjectModel" resultMap="mpkFile"> |
| | | SELECT |
| | | t3.*,t4.method_name,t4.data_length,t4.model |
| | | t3.*, |
| | | t4.method_name, |
| | | t4.data_length, |
| | | t4.model, |
| | | t4.result_key, |
| | | t5.id setting_id, |
| | | t5.setting_key, |
| | | t5.name setting_name, |
| | | t5.value, |
| | | t5.type, |
| | | t5.value_type, |
| | | t5.max, |
| | | t5.min, |
| | | t6.id select_id, |
| | | t6.select_key, |
| | | t6.name select_name |
| | | FROM |
| | | ( |
| | | SELECT |
| | |
| | | LIMIT #{params.offset},#{params.pageSize} |
| | | ) t3 |
| | | LEFT JOIN t_mpk_model_method t4 ON t3.id = t4.mpk_file_id |
| | | LEFT JOIN t_mpk_method_setting t5 ON t4.id = t5.method_id |
| | | LEFT JOIN t_mpk_setting_select t6 ON t5.id = t6.setting_id |
| | | </select> |
| | | </mapper> |
对比新文件 |
| | |
| | | package com.iailab.module.system.api.app; |
| | | |
| | | import com.iailab.framework.common.pojo.CommonResult; |
| | | import com.iailab.module.system.api.app.dto.AppMenuRespDTO; |
| | | import com.iailab.module.system.api.app.dto.AppRespDTO; |
| | | import com.iailab.module.system.enums.ApiConstants; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | | import java.util.List; |
| | | |
| | | @FeignClient(name = ApiConstants.NAME) |
| | | @Tag(name = "RPC 服务 - 应用菜单") |
| | | public interface AppApi { |
| | | |
| | | String PREFIX = ApiConstants.PREFIX + "/app"; |
| | | |
| | | // @GetMapping(PREFIX + "/get-menu") |
| | | // @Operation(summary = "获得应用信息") |
| | | // @Parameter(name = "id", description = "应用编号", example = "1024", required = true) |
| | | // CommonResult<List<AppMenuRespDTO>> getAppMenuList(@RequestParam("id") Long id); |
| | | |
| | | @GetMapping(PREFIX + "/list") |
| | | @Operation(summary = "获得应用菜单列表") |
| | | CommonResult<List<AppRespDTO>> getAppList(); |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.api.app; |
| | | |
| | | import com.iailab.framework.common.pojo.CommonResult; |
| | | import com.iailab.module.system.api.app.dto.AppMenuRespDTO; |
| | | import com.iailab.module.system.api.app.dto.AppRespDTO; |
| | | import com.iailab.module.system.enums.ApiConstants; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.util.List; |
| | | |
| | | @FeignClient(name = ApiConstants.NAME) |
| | | @Tag(name = "RPC 服务 - 应用菜单") |
| | | public interface AppMenuApi { |
| | | |
| | | String PREFIX = ApiConstants.PREFIX + "/app-menu"; |
| | | |
| | | @GetMapping(PREFIX + "/get-menu") |
| | | @Operation(summary = "获得应用信息") |
| | | @Parameter(name = "id", description = "应用编号", example = "1024", required = true) |
| | | CommonResult<List<AppMenuRespDTO>> getAppMenuList(@RequestParam("id") Long id); |
| | | |
| | | @GetMapping(PREFIX + "/list") |
| | | @Operation(summary = "获得应用菜单列表") |
| | | CommonResult<List<AppRespDTO>> getAppList(); |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.api.app.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import javax.validation.constraints.Size; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "RPC 服务 - 应用菜单 Response DTO") |
| | | @Data |
| | | public class AppMenuRespDTO { |
| | | |
| | | @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "平台") |
| | | @NotBlank(message = "菜单名称不能为空") |
| | | @Size(max = 50, message = "菜单名称长度不能超过50个字符") |
| | | private String name; |
| | | |
| | | @Schema(description = "权限标识,仅菜单类型为按钮时,才需要传递", example = "sys:menu:add") |
| | | @Size(max = 100) |
| | | private String permission; |
| | | |
| | | @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "菜单类型不能为空") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "显示顺序不能为空") |
| | | private Integer sort; |
| | | |
| | | @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "父菜单 ID 不能为空") |
| | | private Long parentId; |
| | | |
| | | @Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post") |
| | | @Size(max = 200, message = "路由地址不能超过200个字符") |
| | | private String path; |
| | | |
| | | @Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list") |
| | | private String icon; |
| | | |
| | | @Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index") |
| | | @Size(max = 200, message = "组件路径不能超过255个字符") |
| | | private String component; |
| | | |
| | | @Schema(description = "组件名", example = "SystemUser") |
| | | private String componentName; |
| | | |
| | | @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "状态不能为空") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "是否可见", example = "false") |
| | | private Boolean visible; |
| | | |
| | | @Schema(description = "是否缓存", example = "false") |
| | | private Boolean keepAlive; |
| | | |
| | | @Schema(description = "是否总是显示", example = "false") |
| | | private Boolean alwaysShow; |
| | | |
| | | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") |
| | | private LocalDateTime createTime; |
| | | |
| | | /** |
| | | * 应用类型(1-系统菜单, 2-应用菜单) |
| | | */ |
| | | private Integer appType; |
| | | |
| | | /** |
| | | * 子路由 |
| | | */ |
| | | private List<AppMenuRespDTO> children; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.api.app.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | @Schema(description = "应用菜单精简信息 Response VO") |
| | | @Data |
| | | public class AppMenuSimpleRespDTO { |
| | | |
| | | @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "平台") |
| | | private String name; |
| | | |
| | | @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long parentId; |
| | | |
| | | @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | private Integer type; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.api.app.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * @author PanZhibao |
| | | * @Description |
| | | * @createTime 2024年08月18日 |
| | | */ |
| | | @Schema(description = "管理后台 - 应用 Response VO") |
| | | @Data |
| | | public class AppRespDTO { |
| | | |
| | | @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用编号") |
| | | private String appCode; |
| | | |
| | | @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用名称") |
| | | private String appName; |
| | | |
| | | @Schema(description = "应用域名", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用域名") |
| | | private String appDomain; |
| | | |
| | | @Schema(description = "接口域名", requiredMode = Schema.RequiredMode.REQUIRED, example = "接口域名") |
| | | private String apiDomain; |
| | | |
| | | @Schema(description = "应用账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用账号") |
| | | private String appKey; |
| | | |
| | | @Schema(description = "应用密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用密码") |
| | | private String appSecret; |
| | | |
| | | @Schema(description = "应用分组", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用分组") |
| | | private String appGroup; |
| | | |
| | | @Schema(description = "应用加载类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用加载类型") |
| | | private Integer loadType; |
| | | |
| | | @Schema(description = "应用图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用图标") |
| | | private String icon; |
| | | |
| | | @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "排序") |
| | | private Integer orderNum; |
| | | |
| | | @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "状态") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "开发者ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "开发者ID") |
| | | private String devId; |
| | | |
| | | @Schema(description = "开发者名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "开发者名称") |
| | | private String devName; |
| | | |
| | | @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "备注") |
| | | private String remark; |
| | | |
| | | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private LocalDateTime createTime; |
| | | |
| | | @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "租户ID") |
| | | private Long tenantId; |
| | | |
| | | @Schema(description = "应用菜单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用菜单ID") |
| | | private Long appMenuId; |
| | | |
| | | /** |
| | | * 应用类型(1-系统菜单, 2-应用菜单) |
| | | */ |
| | | private Integer appType; |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.api.app; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import com.iailab.framework.common.pojo.CommonResult; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.module.system.api.app.dto.AppMenuRespDTO; |
| | | import com.iailab.module.system.api.app.dto.AppRespDTO; |
| | | import com.iailab.module.system.convert.app.AppConvert; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppMenuDO; |
| | | import com.iailab.module.system.service.app.AppMenuService; |
| | | import com.iailab.module.system.service.app.AppService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.*; |
| | | |
| | | import static com.iailab.framework.common.pojo.CommonResult.success; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; |
| | | |
| | | @RestController // 提供 RESTful API 接口,给 Feign 调用 |
| | | @Validated |
| | | public class AppApiImpl implements AppApi { |
| | | |
| | | @Resource |
| | | private AppService appService; |
| | | |
| | | // @Override |
| | | // public CommonResult<List<AppMenuRespDTO>> getAppMenuList(Long id) { |
| | | // List<AppMenuDO> children = new LinkedList<>(); |
| | | // // 遍历每一层 |
| | | // Collection<Long> parentIds = Collections.singleton(id); |
| | | // for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环 |
| | | // // 查询当前层,所有的子应用菜单 |
| | | // List<AppMenuDO> menus = appMenuService.selectListByParentId(parentIds); |
| | | // // 1. 如果没有子菜单,则结束遍历 |
| | | // if (CollUtil.isEmpty(menus)) { |
| | | // break; |
| | | // } |
| | | // // 2. 如果有子应用菜单,继续遍历 |
| | | // children.addAll(menus); |
| | | // parentIds = convertSet(menus, AppMenuDO::getId); |
| | | // } |
| | | //// children = appMenuService.filterDisableMenus(children); |
| | | // return success(AppConvert.INSTANCE.buildMenuTree(id, children)); |
| | | // } |
| | | |
| | | @Override |
| | | public CommonResult<List<AppRespDTO>> getAppList() { |
| | | List<AppDO> list = appService.getList(); |
| | | list.sort(Comparator.comparing(AppDO::getOrderNum)); |
| | | return success(BeanUtils.toBean(list, AppRespDTO.class)); |
| | | } |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.api.app; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import com.iailab.framework.common.pojo.CommonResult; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.module.system.api.app.dto.AppMenuRespDTO; |
| | | import com.iailab.module.system.api.app.dto.AppRespDTO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppRespVO; |
| | | import com.iailab.module.system.convert.app.AppConvert; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppMenuDO; |
| | | import com.iailab.module.system.service.app.AppMenuService; |
| | | import com.iailab.module.system.service.app.AppService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.*; |
| | | |
| | | import static com.iailab.framework.common.pojo.CommonResult.success; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; |
| | | |
| | | @RestController // 提供 RESTful API 接口,给 Feign 调用 |
| | | @Validated |
| | | public class AppMenuApiImpl implements AppMenuApi { |
| | | |
| | | @Resource |
| | | private AppMenuService appMenuService; |
| | | |
| | | @Resource |
| | | private AppService appService; |
| | | |
| | | @Override |
| | | public CommonResult<List<AppMenuRespDTO>> getAppMenuList(Long id) { |
| | | List<AppMenuDO> children = new LinkedList<>(); |
| | | // 遍历每一层 |
| | | Collection<Long> parentIds = Collections.singleton(id); |
| | | for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环 |
| | | // 查询当前层,所有的子应用菜单 |
| | | List<AppMenuDO> menus = appMenuService.selectListByParentId(parentIds); |
| | | // 1. 如果没有子菜单,则结束遍历 |
| | | if (CollUtil.isEmpty(menus)) { |
| | | break; |
| | | } |
| | | // 2. 如果有子应用菜单,继续遍历 |
| | | children.addAll(menus); |
| | | parentIds = convertSet(menus, AppMenuDO::getId); |
| | | } |
| | | // children = appMenuService.filterDisableMenus(children); |
| | | return success(AppConvert.INSTANCE.buildMenuTree(id, children)); |
| | | } |
| | | |
| | | @Override |
| | | public CommonResult<List<AppRespDTO>> getAppList() { |
| | | List<AppDO> list = appService.getList(); |
| | | list.sort(Comparator.comparing(AppDO::getOrderNum)); |
| | | return success(BeanUtils.toBean(list, AppRespDTO.class)); |
| | | } |
| | | } |
| | |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.framework.excel.core.util.ExcelUtils; |
| | | import com.iailab.module.system.api.app.dto.AppMenuRespDTO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppPageReqVO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppRespVO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppSaveReqVO; |
| | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "获得分页") |
| | | @PreAuthorize("@ss.hasPermission('system:app:query')") |
| | | public CommonResult<PageResult<AppRespVO>> getTenantPage(@Valid AppPageReqVO pageVO) { |
| | | public CommonResult<PageResult<AppRespVO>> getAppPage(@Valid AppPageReqVO pageVO) { |
| | | PageResult<AppDO> pageResult = appService.getPage(pageVO); |
| | | return success(BeanUtils.toBean(pageResult, AppRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/getAppList") |
| | | @Operation(summary = "获得应用列表") |
| | | @PreAuthorize("@ss.hasPermission('system:app-menu:query')") |
| | | public CommonResult<List<AppRespVO>> getAppList() { |
| | | List<AppDO> appDOS = appService.getList(); |
| | | return success(BeanUtils.toBean(appDOS, AppRespVO.class)); |
| | | } |
| | | |
| | | // @GetMapping("/getAppMenu") |
| | | // @Operation(summary = "获得应用菜单列表") |
| | | // @PreAuthorize("@ss.hasPermission('system:app-menu:query')") |
| | | // @Parameter(name = "id", description = "ID", required = true, example = "1024") |
| | | // public CommonResult<List<AppRespVO>> getAppMenu(@RequestParam("id") Long id) { |
| | | // List<AppMenuRespDTO> appDOS = appService.getAppMenu(id); |
| | | // return success(BeanUtils.toBean(appDOS, AppRespVO.class)); |
| | | // } |
| | | |
| | | @GetMapping("/export-excel") |
| | | @Operation(summary = "导出租户 Excel") |
| | | @PreAuthorize("@ss.hasPermission('system:tenant:export')") |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app; |
| | | |
| | | import com.iailab.framework.common.pojo.CommonResult; |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.module.system.controller.admin.app.vo.*; |
| | | import com.iailab.module.system.dal.dataobject.app.AppGroupDO; |
| | | import com.iailab.module.system.service.app.AppGroupService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.validation.Valid; |
| | | |
| | | import java.util.List; |
| | | |
| | | import static com.iailab.framework.common.pojo.CommonResult.success; |
| | | |
| | | /** |
| | | * @author Houzhongjian |
| | | * @Description |
| | | * @createTime 2024年09月20日 |
| | | */ |
| | | @Tag(name = "管理后台 - 应用分组") |
| | | @RestController |
| | | @RequestMapping("/system/app-group") |
| | | public class AppGroupController { |
| | | |
| | | @Resource |
| | | private AppGroupService appGroupService; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "创建应用分组") |
| | | @PreAuthorize("@ss.hasPermission('system:app-group:create')") |
| | | public CommonResult<Long> createApp(@Valid @RequestBody AppGroupSaveReqVO createReqVO) { |
| | | return success(appGroupService.create(createReqVO)); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Operation(summary = "更新应用分组") |
| | | @PreAuthorize("@ss.hasPermission('system:app-group:update')") |
| | | public CommonResult<Boolean> updateApp(@Valid @RequestBody AppGroupSaveReqVO updateReqVO) { |
| | | appGroupService.update(updateReqVO); |
| | | return success(true); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | | @Operation(summary = "删除应用分组") |
| | | @Parameter(name = "id", description = "ID", required = true, example = "1024") |
| | | @PreAuthorize("@ss.hasPermission('system:app-group:delete')") |
| | | public CommonResult<Boolean> deleteAppGroup(@RequestParam("id") Long id) { |
| | | appGroupService.delete(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @GetMapping("/get") |
| | | @Operation(summary = "获得应用分组") |
| | | @Parameter(name = "id", description = "ID", required = true, example = "1024") |
| | | @PreAuthorize("@ss.hasPermission('system:app-group:query')") |
| | | public CommonResult<AppGroupRespVO> getInfo(@RequestParam("id") Long id) { |
| | | AppGroupDO data = appGroupService.getInfo(id); |
| | | return success(BeanUtils.toBean(data, AppGroupRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "获得分页") |
| | | @PreAuthorize("@ss.hasPermission('system:app-group:query')") |
| | | public CommonResult<PageResult<AppGroupRespVO>> getAppGroupPage(@Valid AppGroupPageReqVO pageVO) { |
| | | PageResult<AppGroupDO> pageResult = appGroupService.getPage(pageVO); |
| | | return success(BeanUtils.toBean(pageResult, AppGroupRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/getAppGroupList") |
| | | @Operation(summary = "获得应用分组列表") |
| | | @PreAuthorize("@ss.hasPermission('system:app-group:query')") |
| | | public CommonResult<List<AppGroupRespVO>> getAppList() { |
| | | List<AppGroupDO> appGroupDOS = appGroupService.getList(); |
| | | return success(BeanUtils.toBean(appGroupDOS, AppGroupRespVO.class)); |
| | | } |
| | | } |
对比新文件 |
| | |
| | | //package com.iailab.module.system.controller.admin.app; |
| | | // |
| | | //import com.iailab.framework.common.enums.CommonStatusEnum; |
| | | //import com.iailab.framework.common.pojo.CommonResult; |
| | | //import com.iailab.framework.common.util.object.BeanUtils; |
| | | //import com.iailab.module.system.controller.admin.app.vo.AppMenuRespVO; |
| | | //import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | //import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSaveVO; |
| | | //import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSimpleRespVO; |
| | | //import com.iailab.module.system.dal.dataobject.app.AppMenuDO; |
| | | //import com.iailab.module.system.service.app.AppMenuService; |
| | | //import io.swagger.v3.oas.annotations.Operation; |
| | | //import io.swagger.v3.oas.annotations.Parameter; |
| | | //import io.swagger.v3.oas.annotations.tags.Tag; |
| | | //import org.springframework.security.access.prepost.PreAuthorize; |
| | | //import org.springframework.validation.annotation.Validated; |
| | | //import org.springframework.web.bind.annotation.*; |
| | | // |
| | | //import javax.annotation.Resource; |
| | | //import javax.validation.Valid; |
| | | //import java.util.Comparator; |
| | | //import java.util.List; |
| | | // |
| | | //import static com.iailab.framework.common.pojo.CommonResult.success; |
| | | // |
| | | //@Tag(name = "应用菜单") |
| | | //@RestController |
| | | //@RequestMapping("/system/app-menu") |
| | | //@Validated |
| | | //public class AppMenuController { |
| | | // |
| | | // @Resource |
| | | // private AppMenuService appMenuService; |
| | | // |
| | | // @PostMapping("/create") |
| | | // @Operation(summary = "创建菜单") |
| | | // @PreAuthorize("@ss.hasPermission('system:app-menu:create')") |
| | | // public CommonResult<Long> createMenu(@Valid @RequestBody MenuSaveVO createReqVO) { |
| | | // Long menuId = appMenuService.createMenu(createReqVO); |
| | | // return success(menuId); |
| | | // } |
| | | // |
| | | // @PutMapping("/update") |
| | | // @Operation(summary = "修改菜单") |
| | | // @PreAuthorize("@ss.hasPermission('system:app-menu:update')") |
| | | // public CommonResult<Boolean> updateMenu(@Valid @RequestBody MenuSaveVO updateReqVO) { |
| | | // appMenuService.updateMenu(updateReqVO); |
| | | // return success(true); |
| | | // } |
| | | // |
| | | // @DeleteMapping("/delete") |
| | | // @Operation(summary = "删除菜单") |
| | | // @Parameter(name = "id", description = "菜单编号", required= true, example = "1024") |
| | | // @PreAuthorize("@ss.hasPermission('system:app-menu:delete')") |
| | | // public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) { |
| | | // appMenuService.deleteMenu(id); |
| | | // return success(true); |
| | | // } |
| | | // |
| | | // @GetMapping("/list") |
| | | // @Operation(summary = "获取菜单列表", description = "用于【菜单管理】界面") |
| | | // @PreAuthorize("@ss.hasPermission('system:app-menu:query')") |
| | | // public CommonResult<List<AppMenuRespVO>> getMenuList(MenuListReqVO reqVO) { |
| | | // List<AppMenuDO> list = appMenuService.getMenuList(reqVO); |
| | | // list.sort(Comparator.comparing(AppMenuDO::getSort)); |
| | | // return success(BeanUtils.toBean(list, AppMenuRespVO.class)); |
| | | // } |
| | | // |
| | | // @GetMapping({"/list-all-simple", "simple-list"}) |
| | | // @Operation(summary = "获取菜单精简信息列表", description = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" + |
| | | // "在多租户的场景下,会只返回租户所在套餐有的菜单") |
| | | // public CommonResult<List<MenuSimpleRespVO>> getSimpleMenuList() { |
| | | // List<AppMenuDO> list = appMenuService.getMenuListByTenant( |
| | | // new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); |
| | | // list.sort(Comparator.comparing(AppMenuDO::getSort)); |
| | | // return success(BeanUtils.toBean(list, MenuSimpleRespVO.class)); |
| | | // } |
| | | // |
| | | // @GetMapping("/get") |
| | | // @Operation(summary = "获取菜单信息") |
| | | // @PreAuthorize("@ss.hasPermission('system:app-menu:query')") |
| | | // public CommonResult<AppMenuRespVO> getMenu(Long id) { |
| | | // AppMenuDO menu = appMenuService.getMenu(id); |
| | | // return success(BeanUtils.toBean(menu, AppMenuRespVO.class)); |
| | | // } |
| | | // |
| | | //} |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import com.iailab.framework.common.pojo.PageParam; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.ToString; |
| | | |
| | | /** |
| | | * @author Houzhongjian |
| | | * @Description |
| | | * @createTime 2024年09月20日 |
| | | */ |
| | | @Schema(description = "管理后台 - 应用分组分页 Request VO") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | public class AppGroupPageReqVO extends PageParam { |
| | | |
| | | private String code; |
| | | |
| | | private String name; |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * @author Houzhongjian |
| | | * @Description |
| | | * @createTime 2024年09月20日 |
| | | */ |
| | | @Schema(description = "管理后台 - 应用分组 Response VO") |
| | | @Data |
| | | @ExcelIgnoreUnannotated |
| | | public class AppGroupRespVO { |
| | | |
| | | @Schema(description = "应用分组id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @ExcelProperty("应用分组id") |
| | | private Long id; |
| | | |
| | | @Schema(description = "应用分组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用分组编号") |
| | | @ExcelProperty("应用分组编号") |
| | | private String code; |
| | | |
| | | @Schema(description = "应用分组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用分组名称") |
| | | @ExcelProperty("应用分组名称") |
| | | private String name; |
| | | |
| | | @Schema(description = "应用分组图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用分组图标") |
| | | @ExcelProperty("应用分组图标") |
| | | private String icon; |
| | | |
| | | @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "排序") |
| | | @ExcelProperty("排序") |
| | | private Integer sort; |
| | | |
| | | @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "备注") |
| | | @ExcelProperty("备注") |
| | | private String remark; |
| | | |
| | | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @ExcelProperty("创建时间") |
| | | private LocalDateTime createTime; |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotNull; |
| | | |
| | | /** |
| | | * @author PanZhibao |
| | | * @Description |
| | | * @createTime 2024年08月17日 |
| | | */ |
| | | @Schema(description = "管理后台 - 应用创建/修改 Request VO") |
| | | @Data |
| | | public class AppGroupSaveReqVO { |
| | | |
| | | @Schema(description = "ID") |
| | | private Long id; |
| | | |
| | | @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "应用编号不能为空") |
| | | private String code; |
| | | |
| | | @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "应用名称不能为空") |
| | | private String name; |
| | | |
| | | @Schema(description = "应用图标", example = "") |
| | | private String icon; |
| | | |
| | | @Schema(description = "排序", example = "") |
| | | private Integer sort; |
| | | |
| | | @Schema(description = "备注", example = "") |
| | | private String remark; |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | @Schema(description = "应用菜单列表 Request VO") |
| | | @Data |
| | | public class AppMenuListReqVO { |
| | | |
| | | @Schema(description = "菜单名称,模糊匹配", example = "平台") |
| | | private String name; |
| | | |
| | | @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") |
| | | private Integer status; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import javax.validation.constraints.Size; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Schema(description = "应用菜单信息 Response VO") |
| | | @Data |
| | | public class AppMenuRespVO { |
| | | |
| | | @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "平台") |
| | | @NotBlank(message = "菜单名称不能为空") |
| | | @Size(max = 50, message = "菜单名称长度不能超过50个字符") |
| | | private String name; |
| | | |
| | | @Schema(description = "权限标识,仅菜单类型为按钮时,才需要传递", example = "sys:menu:add") |
| | | @Size(max = 100) |
| | | private String permission; |
| | | |
| | | @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "菜单类型不能为空") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "显示顺序不能为空") |
| | | private Integer sort; |
| | | |
| | | @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "父菜单 ID 不能为空") |
| | | private Long parentId; |
| | | |
| | | @Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post") |
| | | @Size(max = 200, message = "路由地址不能超过200个字符") |
| | | private String path; |
| | | |
| | | @Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list") |
| | | private String icon; |
| | | |
| | | @Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index") |
| | | @Size(max = 200, message = "组件路径不能超过255个字符") |
| | | private String component; |
| | | |
| | | @Schema(description = "组件名", example = "SystemUser") |
| | | private String componentName; |
| | | |
| | | @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "状态不能为空") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "是否可见", example = "false") |
| | | private Boolean visible; |
| | | |
| | | @Schema(description = "是否缓存", example = "false") |
| | | private Boolean keepAlive; |
| | | |
| | | @Schema(description = "是否总是显示", example = "false") |
| | | private Boolean alwaysShow; |
| | | |
| | | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") |
| | | private LocalDateTime createTime; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import javax.validation.constraints.Size; |
| | | |
| | | @Schema(description = "应用菜单创建/修改 Request VO") |
| | | @Data |
| | | public class AppMenuSaveVO { |
| | | |
| | | @Schema(description = "菜单编号", example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "平台") |
| | | @NotBlank(message = "菜单名称不能为空") |
| | | @Size(max = 50, message = "菜单名称长度不能超过50个字符") |
| | | private String name; |
| | | |
| | | @Schema(description = "权限标识,仅菜单类型为按钮时,才需要传递", example = "sys:menu:add") |
| | | @Size(max = 100) |
| | | private String permission; |
| | | |
| | | @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "菜单类型不能为空") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "显示顺序不能为空") |
| | | private Integer sort; |
| | | |
| | | @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "父菜单 ID 不能为空") |
| | | private Long parentId; |
| | | |
| | | @Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post") |
| | | @Size(max = 200, message = "路由地址不能超过200个字符") |
| | | private String path; |
| | | |
| | | @Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list") |
| | | private String icon; |
| | | |
| | | @Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index") |
| | | @Size(max = 200, message = "组件路径不能超过255个字符") |
| | | private String component; |
| | | |
| | | @Schema(description = "组件名", example = "SystemUser") |
| | | private String componentName; |
| | | |
| | | @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "状态不能为空") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "是否可见", example = "false") |
| | | private Boolean visible; |
| | | |
| | | @Schema(description = "是否缓存", example = "false") |
| | | private Boolean keepAlive; |
| | | |
| | | @Schema(description = "是否总是显示", example = "false") |
| | | private Boolean alwaysShow; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | @Schema(description = "应用菜单精简信息 Response VO") |
| | | @Data |
| | | public class AppMenuSimpleRespVO { |
| | | |
| | | @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "平台") |
| | | private String name; |
| | | |
| | | @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long parentId; |
| | | |
| | | @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | private Integer type; |
| | | |
| | | } |
| | |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | |
| | | @ExcelIgnoreUnannotated |
| | | public class AppRespVO { |
| | | |
| | | @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @ExcelProperty("应用编号") |
| | | @Schema(description = "应用ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @ExcelProperty("应用ID") |
| | | private Long id; |
| | | |
| | | @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用编号") |
| | |
| | | @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用名称") |
| | | @ExcelProperty("应用名称") |
| | | private String appName; |
| | | |
| | | @Schema(description = "应用类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用类型") |
| | | @ExcelProperty("应用类型") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "应用域名", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用域名") |
| | | @ExcelProperty("应用域名") |
| | |
| | | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @ExcelProperty("创建时间") |
| | | private LocalDateTime createTime; |
| | | |
| | | @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "租户ID") |
| | | @ExcelProperty("开发者ID") |
| | | private Long tenantId; |
| | | |
| | | @Schema(description = "应用菜单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用菜单ID") |
| | | private Long appMenuId; |
| | | |
| | | @Schema(description = "应用分组ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "应用分组ID") |
| | | private Long groupId; |
| | | |
| | | /** |
| | | * 应用类型(1-系统菜单, 2-应用菜单) |
| | | */ |
| | | @TableField(exist = false) |
| | | private Integer appType; |
| | | |
| | | } |
| | |
| | | package com.iailab.module.system.controller.admin.app.vo; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | |
| | | @Schema(description = "应用名称", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "应用名称不能为空") |
| | | private String appName; |
| | | |
| | | @Schema(description = "应用类型", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @ExcelProperty("应用类型") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "应用域名", example = "") |
| | | private String appDomain; |
| | |
| | | |
| | | @Schema(description = "备注", example = "") |
| | | private String remark; |
| | | |
| | | @Schema(description = "租户ID", example = "") |
| | | private Long tenantId; |
| | | |
| | | @Schema(description = "分组ID", example = "") |
| | | private Long groupId; |
| | | } |
| | |
| | | import com.iailab.framework.security.config.SecurityProperties; |
| | | import com.iailab.framework.security.core.util.SecurityFrameworkUtils; |
| | | import com.iailab.module.system.controller.admin.auth.vo.*; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | import com.iailab.module.system.convert.auth.AuthConvert; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.MenuDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.RoleDO; |
| | | import com.iailab.module.system.dal.dataobject.user.AdminUserDO; |
| | | import com.iailab.module.system.enums.logger.LoginLogTypeEnum; |
| | | import com.iailab.module.system.service.app.AppService; |
| | | import com.iailab.module.system.service.auth.AdminAuthService; |
| | | import com.iailab.module.system.service.permission.MenuService; |
| | | import com.iailab.module.system.service.permission.PermissionService; |
| | |
| | | import static com.iailab.framework.common.pojo.CommonResult.success; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | import static com.iailab.framework.tenant.core.context.TenantContextHolder.getTenantId; |
| | | |
| | | |
| | | @Tag(name = "管理后台 - 认证") |
| | |
| | | private PermissionService permissionService; |
| | | @Resource |
| | | private SocialClientService socialClientService; |
| | | |
| | | @Resource |
| | | private SecurityProperties securityProperties; |
| | | @Resource |
| | | private AppService appService; |
| | | |
| | | @PostMapping("/login") |
| | | @PermitAll |
| | |
| | | return success(AuthConvert.INSTANCE.convert(user, roles, menuList)); |
| | | } |
| | | |
| | | @GetMapping("/get-app-permission-info") |
| | | @Operation(summary = "获取登录用户的app权限信息") |
| | | public CommonResult<AuthPermissionInfoRespVO> getAppPermissionInfo() { |
| | | // 1.1 获得用户信息 |
| | | AdminUserDO user = userService.getUser(getLoginUserId()); |
| | | if (user == null) { |
| | | return success(null); |
| | | } |
| | | |
| | | // 1.2 获得角色列表 |
| | | Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
| | | if (CollUtil.isEmpty(roleIds)) { |
| | | return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList())); |
| | | } |
| | | List<RoleDO> roles = roleService.getRoleList(roleIds); |
| | | roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
| | | |
| | | // 1.3 获得应用菜单列表 |
| | | MenuListReqVO reqVO = new MenuListReqVO(); |
| | | List<MenuDO> appMenuList = menuService.getAppMenuList(reqVO); |
| | | Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
| | | List<MenuDO> menuList = menuService.getMenuList(menuIds); |
| | | menuList.retainAll(appMenuList); |
| | | menuList = menuService.filterDisableMenus(menuList); |
| | | // 2. 拼接结果返回 |
| | | return success(AuthConvert.INSTANCE.convertAppMenu(user, roles, menuList)); |
| | | } |
| | | |
| | | // ========== 短信登录相关 ========== |
| | | |
| | | @PostMapping("/sms-login") |
| | |
| | | import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO; |
| | | import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO; |
| | | import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO; |
| | | import com.iailab.module.system.controller.admin.oauth2.vo.open.OAuth2OpenLoginReqVO; |
| | | import com.iailab.module.system.convert.oauth2.OAuth2OpenConvert; |
| | | import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; |
| | | import com.iailab.module.system.dal.dataobject.oauth2.OAuth2ApproveDO; |
| | |
| | | @PostMapping("/token") |
| | | @PermitAll |
| | | @Operation(summary = "获得访问令牌", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用") |
| | | @Parameters({ |
| | | @Parameter(name = "grant_type", required = true, description = "授权类型", example = "code"), |
| | | @Parameter(name = "code", description = "授权范围", example = "userinfo.read"), |
| | | @Parameter(name = "redirect_uri", description = "重定向 URI", example = "https://www.baidu.com"), |
| | | @Parameter(name = "state", description = "状态", example = "1"), |
| | | @Parameter(name = "username", example = "tudou"), |
| | | @Parameter(name = "password", example = "cai"), // 多个使用空格分隔 |
| | | @Parameter(name = "scope", example = "user_info"), |
| | | @Parameter(name = "refresh_token", example = "123424233"), |
| | | }) |
| | | public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(HttpServletRequest request, |
| | | @RequestParam("grant_type") String grantType, |
| | | @RequestParam(value = "code", required = false) String code, // 授权码模式 |
| | | @RequestParam(value = "redirect_uri", required = false) String redirectUri, // 授权码模式 |
| | | @RequestParam(value = "state", required = false) String state, // 授权码模式 |
| | | @RequestParam(value = "username", required = false) String username, // 密码模式 |
| | | @RequestParam(value = "password", required = false) String password, // 密码模式 |
| | | @RequestParam(value = "scope", required = false) String scope, // 密码模式 |
| | | @RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式 |
| | | @RequestBody OAuth2OpenLoginReqVO openLoginReqVO) { |
| | | String code = openLoginReqVO.getCode(); |
| | | String scope = openLoginReqVO.getScope(); |
| | | String grantType = openLoginReqVO.getGrantType(); |
| | | String redirectUri = openLoginReqVO.getRedirectUri(); |
| | | String state = openLoginReqVO.getState(); |
| | | String username = openLoginReqVO.getUsername(); |
| | | String password = openLoginReqVO.getPassword(); |
| | | String refreshToken = openLoginReqVO.getRefreshToken(); |
| | | List<String> scopes = OAuth2Utils.buildScopes(scope); |
| | | // 1.1 校验授权类型 |
| | | OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGrantType(grantType); |
| | |
| | | @AllArgsConstructor |
| | | public class OAuth2OpenAccessTokenRespVO { |
| | | |
| | | @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | private Long userId; |
| | | |
| | | @Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou") |
| | | @JsonProperty("access_token") |
| | | private String accessToken; |
| | | |
| | | @Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice") |
| | | @JsonProperty("refresh_token") |
| | | private String refreshToken; |
| | | |
| | | @Schema(description = "令牌类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "bearer") |
| | | @JsonProperty("token_type") |
| | | private String tokenType; |
| | | |
| | | @Schema(description = "过期时间,单位:秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "42430") |
| | | @JsonProperty("expires_in") |
| | | private Long expiresIn; |
| | | private Long expiresTime; |
| | | |
| | | @Schema(description = "授权范围,如果多个授权范围,使用空格分隔", example = "user_info") |
| | | private String scope; |
对比新文件 |
| | |
| | | package com.iailab.module.system.controller.admin.oauth2.vo.open; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.iailab.framework.common.validation.InEnum; |
| | | import com.iailab.module.system.enums.social.SocialTypeEnum; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | import org.hibernate.validator.constraints.Length; |
| | | |
| | | import javax.validation.constraints.AssertTrue; |
| | | import javax.validation.constraints.NotEmpty; |
| | | import javax.validation.constraints.Pattern; |
| | | |
| | | @Schema(description = "管理后台 - 账号密码授权登录 Request VO") |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @Builder |
| | | public class OAuth2OpenLoginReqVO { |
| | | |
| | | @Schema(description = "授权类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "password") |
| | | private String grantType; |
| | | |
| | | //授权码模式 |
| | | @Schema(description = "授权范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String code; |
| | | |
| | | @Schema(description = "重定向 URI", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String redirectUri; |
| | | |
| | | @Schema(description = "状态", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String state; |
| | | |
| | | //密码模式 |
| | | @Schema(description = "授权范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String scope; |
| | | |
| | | @Schema(description = "账号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "iailabyuanma") |
| | | @Length(min = 4, max = 16, message = "账号长度为 4-16 位") |
| | | @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母") |
| | | private String username; |
| | | |
| | | @Schema(description = "密码", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "buzhidao") |
| | | @Length(min = 4, max = 16, message = "密码长度为 4-16 位") |
| | | private String password; |
| | | |
| | | //刷新模式 |
| | | @Schema(description = "刷新token", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String refreshToken; |
| | | |
| | | } |
| | |
| | | return success(menuId); |
| | | } |
| | | |
| | | @PostMapping("/createAppMenu") |
| | | @Operation(summary = "创建菜单") |
| | | @PreAuthorize("@ss.hasPermission('system:app-menu:create')") |
| | | public CommonResult<Long> createAppMenu(@Valid @RequestBody MenuSaveVO createReqVO) { |
| | | Long menuId = menuService.createMenu(createReqVO); |
| | | return success(menuId); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Operation(summary = "修改菜单") |
| | | @PreAuthorize("@ss.hasPermission('system:menu:update')") |
| | | public CommonResult<Boolean> updateMenu(@Valid @RequestBody MenuSaveVO updateReqVO) { |
| | | menuService.updateMenu(updateReqVO); |
| | | return success(true); |
| | | } |
| | | |
| | | @PutMapping("/updateAppMenu") |
| | | @Operation(summary = "修改菜单") |
| | | @PreAuthorize("@ss.hasPermission('system:app-menu:update')") |
| | | public CommonResult<Boolean> updateAppMenu(@Valid @RequestBody MenuSaveVO updateReqVO) { |
| | | menuService.updateMenu(updateReqVO); |
| | | return success(true); |
| | | } |
| | |
| | | return success(true); |
| | | } |
| | | |
| | | @DeleteMapping("/deleteAppMenu") |
| | | @Operation(summary = "删除菜单") |
| | | @Parameter(name = "id", description = "菜单编号", required= true, example = "1024") |
| | | @PreAuthorize("@ss.hasPermission('system:app-menu:delete')") |
| | | public CommonResult<Boolean> deleteAppMenu(@RequestParam("id") Long id) { |
| | | menuService.deleteMenu(id); |
| | | return success(true); |
| | | } |
| | | |
| | | |
| | | @GetMapping("/list") |
| | | @Operation(summary = "获取菜单列表", description = "用于【菜单管理】界面") |
| | | @PreAuthorize("@ss.hasPermission('system:menu:query')") |
| | | public CommonResult<List<MenuRespVO>> getMenuList(MenuListReqVO reqVO) { |
| | | List<MenuDO> list = menuService.getMenuList(reqVO); |
| | | list.sort(Comparator.comparing(MenuDO::getSort)); |
| | | return success(BeanUtils.toBean(list, MenuRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/app-menu-list") |
| | | @Operation(summary = "获取应用菜单列表", description = "用于【应用菜单】界面") |
| | | @PreAuthorize("@ss.hasPermission('system:app-menu:query')") |
| | | public CommonResult<List<MenuRespVO>> getAppMenuList(MenuListReqVO reqVO) { |
| | | List<MenuDO> list = menuService.getAppMenuList(reqVO); |
| | | list.sort(Comparator.comparing(MenuDO::getSort)); |
| | | return success(BeanUtils.toBean(list, MenuRespVO.class)); |
| | | } |
| | |
| | | return success(BeanUtils.toBean(list, MenuSimpleRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping({"simple-app-menus"}) |
| | | @Operation(summary = "获取应用菜单精简信息列表", description = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" + |
| | | "在多租户的场景下,会只返回租户所在套餐有的菜单") |
| | | public CommonResult<List<MenuSimpleRespVO>> getSimpleAppMenuList() { |
| | | List<MenuDO> list = menuService.getAppMenuListByTenant( |
| | | new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); |
| | | list.sort(Comparator.comparing(MenuDO::getSort)); |
| | | return success(BeanUtils.toBean(list, MenuSimpleRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/get") |
| | | @Operation(summary = "获取菜单信息") |
| | | @PreAuthorize("@ss.hasPermission('system:menu:query')") |
| | |
| | | return success(BeanUtils.toBean(menu, MenuRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/getAppMenu") |
| | | @Operation(summary = "获取菜单信息") |
| | | @PreAuthorize("@ss.hasPermission('system:app-menu:query')") |
| | | public CommonResult<MenuRespVO> getAppMenu(Long id) { |
| | | MenuDO menu = menuService.getMenu(id); |
| | | return success(BeanUtils.toBean(menu, MenuRespVO.class)); |
| | | } |
| | | |
| | | } |
| | |
| | | return success(permissionService.getRoleMenuListByRoleId(roleId)); |
| | | } |
| | | |
| | | @Operation(summary = "获得角色拥有的菜单编号") |
| | | @Parameter(name = "roleId", description = "角色编号", required = true) |
| | | @GetMapping("/list-role-app-menus") |
| | | @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')") |
| | | public CommonResult<Set<Long>> getRoleAppMenuList(Long roleId) { |
| | | return success(permissionService.getRoleAppMenuListByRoleId(roleId)); |
| | | } |
| | | |
| | | @PostMapping("/assign-role-menu") |
| | | @Operation(summary = "赋予角色菜单") |
| | | @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')") |
| | |
| | | return success(true); |
| | | } |
| | | |
| | | @PostMapping("/assign-role-app-menu") |
| | | @Operation(summary = "赋予角色菜单") |
| | | @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')") |
| | | public CommonResult<Boolean> assignRoleAppMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) { |
| | | // 执行菜单的分配 |
| | | permissionService.assignRoleAppMenu(reqVO.getRoleId(), reqVO.getMenuIds()); |
| | | return success(true); |
| | | } |
| | | |
| | | @PostMapping("/assign-role-data-scope") |
| | | @Operation(summary = "赋予角色数据权限") |
| | | @PreAuthorize("@ss.hasPermission('system:permission:assign-role-data-scope')") |
| | |
| | | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") |
| | | private LocalDateTime createTime; |
| | | |
| | | @Schema(description = "应用ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |
| | | private Long appId; |
| | | |
| | | } |
| | |
| | | @Schema(description = "是否总是显示", example = "false") |
| | | private Boolean alwaysShow; |
| | | |
| | | @Schema(description = "应用ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |
| | | private Long appId; |
| | | |
| | | } |
| | |
| | | return success(BeanUtils.toBean(pageResult, TenantRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/simple-list") |
| | | @Operation(summary = "获得租户精简列表") |
| | | @PreAuthorize("@ss.hasPermission('system:tenant:query')") |
| | | public CommonResult<List<TenantSimpleRespVO>> getSimpleTenant() { |
| | | List<TenantDO> listResult = tenantService.getSimpleTenant(); |
| | | return success(BeanUtils.toBean(listResult, TenantSimpleRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/export-excel") |
| | | @Operation(summary = "导出租户 Excel") |
| | | @PreAuthorize("@ss.hasPermission('system:tenant:export')") |
对比新文件 |
| | |
| | | package com.iailab.module.system.convert.app; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import com.iailab.module.system.api.app.dto.AppMenuRespDTO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppMenuDO; |
| | | import com.iailab.module.system.enums.permission.MenuTypeEnum; |
| | | import org.mapstruct.Mapper; |
| | | import org.mapstruct.factory.Mappers; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.*; |
| | | |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.filterList; |
| | | |
| | | @Mapper |
| | | public interface AppConvert { |
| | | |
| | | AppConvert INSTANCE = Mappers.getMapper(AppConvert.class); |
| | | |
| | | AppMenuRespDTO convertTreeNode(AppMenuDO menu); |
| | | |
| | | /** |
| | | * 将菜单列表,构建成菜单树 |
| | | * |
| | | * @param menuList 菜单列表 |
| | | * @return 菜单树 |
| | | */ |
| | | default List<AppMenuRespDTO> buildMenuTree(Long id, List<AppMenuDO> menuList) { |
| | | if (CollUtil.isEmpty(menuList)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | // 移除按钮 |
| | | menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); |
| | | // 排序,保证菜单的有序性 |
| | | menuList.sort(Comparator.comparing(AppMenuDO::getSort)); |
| | | |
| | | // 构建菜单树 |
| | | // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 |
| | | Map<Long, AppMenuRespDTO> treeNodeMap = new LinkedHashMap<>(); |
| | | menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AppConvert.INSTANCE.convertTreeNode(menu))); |
| | | // 处理父子关系 |
| | | treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(id)).forEach(childNode -> { |
| | | // 获得父节点 |
| | | AppMenuRespDTO parentNode = treeNodeMap.get(childNode.getParentId()); |
| | | if (parentNode == null) { |
| | | LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", |
| | | childNode.getId(), childNode.getParentId()); |
| | | return; |
| | | } |
| | | // 将自己添加到父节点中 |
| | | if (parentNode.getChildren() == null) { |
| | | parentNode.setChildren(new ArrayList<>()); |
| | | } |
| | | parentNode.getChildren().add(childNode); |
| | | }); |
| | | // 获得到所有的根节点 |
| | | return filterList(treeNodeMap.values(), node -> id.equals(node.getParentId())); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | AuthLoginRespVO convert(OAuth2AccessTokenDO bean); |
| | | |
| | | default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) { |
| | | default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) { |
| | | return AuthPermissionInfoRespVO.builder() |
| | | .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) |
| | | .roles(convertSet(roleList, RoleDO::getCode)) |
| | |
| | | .permissions(convertSet(menuList, MenuDO::getPermission)) |
| | | // 菜单树 |
| | | .menus(buildMenuTree(menuList)) |
| | | .build(); |
| | | } |
| | | |
| | | default AuthPermissionInfoRespVO convertAppMenu(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) { |
| | | return AuthPermissionInfoRespVO.builder() |
| | | .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) |
| | | .roles(convertSet(roleList, RoleDO::getCode)) |
| | | // 权限标识信息 |
| | | .permissions(convertSet(menuList, MenuDO::getPermission)) |
| | | // 菜单树 |
| | | .menus(buildAppMenuTree(menuList)) |
| | | .build(); |
| | | } |
| | | |
| | |
| | | if (CollUtil.isEmpty(menuList)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | // 移除按钮 |
| | | // 移除按钮和应用菜单 |
| | | menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); |
| | | // 排序,保证菜单的有序性 |
| | | menuList.sort(Comparator.comparing(MenuDO::getSort)); |
| | |
| | | return filterList(treeNodeMap.values(), node -> ID_ROOT.equals(node.getParentId())); |
| | | } |
| | | |
| | | /** |
| | | * 将菜单列表,构建成菜单树 |
| | | * |
| | | * @param menuList 菜单列表 |
| | | * @return 菜单树 |
| | | */ |
| | | default List<AuthPermissionInfoRespVO.MenuVO> buildAppMenuTree(List<MenuDO> menuList) { |
| | | if (CollUtil.isEmpty(menuList)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | // 移除按钮和应用菜单 |
| | | menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); |
| | | // 排序,保证菜单的有序性 |
| | | menuList.sort(Comparator.comparing(MenuDO::getSort)); |
| | | |
| | | // 构建菜单树 |
| | | // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 |
| | | Map<Long, AuthPermissionInfoRespVO.MenuVO> treeNodeMap = new LinkedHashMap<>(); |
| | | menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AuthConvert.INSTANCE.convertTreeNode(menu))); |
| | | // 处理父子关系 |
| | | treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(ID_ROOT)).forEach(childNode -> { |
| | | // 获得父节点 |
| | | AuthPermissionInfoRespVO.MenuVO parentNode = treeNodeMap.get(childNode.getParentId()); |
| | | if (parentNode == null) { |
| | | LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", |
| | | childNode.getId(), childNode.getParentId()); |
| | | return; |
| | | } |
| | | // 将自己添加到父节点中 |
| | | if (parentNode.getChildren() == null) { |
| | | parentNode.setChildren(new ArrayList<>()); |
| | | } |
| | | parentNode.getChildren().add(childNode); |
| | | }); |
| | | // 获得到所有的根节点 |
| | | return filterList(treeNodeMap.values(), node -> ID_ROOT.equals(node.getParentId())); |
| | | } |
| | | |
| | | /** |
| | | * 将菜单列表,构建成菜单树 |
| | | * |
| | | * @param menuList 菜单列表 |
| | | * @return 菜单树 |
| | | */ |
| | | default List<AuthPermissionInfoRespVO.MenuVO> buildMenuTree(List<MenuDO> menuList, Long id, String parentPath) { |
| | | if (CollUtil.isEmpty(menuList)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | // 移除按钮 |
| | | menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); |
| | | // 排序,保证菜单的有序性 |
| | | menuList.sort(Comparator.comparing(MenuDO::getSort)); |
| | | |
| | | // 构建菜单树 |
| | | // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 |
| | | Map<Long, AuthPermissionInfoRespVO.MenuVO> treeNodeMap = new LinkedHashMap<>(); |
| | | menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AuthConvert.INSTANCE.convertTreeNode(menu))); |
| | | // 处理父子关系 |
| | | treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(id)).forEach(childNode -> { |
| | | // 获得父节点 |
| | | AuthPermissionInfoRespVO.MenuVO parentNode = treeNodeMap.get(childNode.getParentId()); |
| | | if (parentNode == null) { |
| | | LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", |
| | | childNode.getId(), childNode.getParentId()); |
| | | return; |
| | | } |
| | | // 将自己添加到父节点中 |
| | | if (parentNode.getChildren() == null) { |
| | | parentNode.setChildren(new ArrayList<>()); |
| | | } |
| | | parentNode.getChildren().add(childNode); |
| | | |
| | | }); |
| | | // 获得到所有的根节点 |
| | | List<AuthPermissionInfoRespVO.MenuVO> menuVOS = filterList(treeNodeMap.values(), node -> id.equals(node.getParentId())); |
| | | menuVOS.stream().forEach(menuVO -> { |
| | | menuVO.setPath(parentPath + "/" + menuVO.getPath()); |
| | | }); |
| | | return menuVOS; |
| | | } |
| | | |
| | | SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO); |
| | | |
| | | SmsCodeSendReqDTO convert(AuthSmsSendReqVO reqVO); |
| | |
| | | default OAuth2OpenAccessTokenRespVO convert(OAuth2AccessTokenDO bean) { |
| | | OAuth2OpenAccessTokenRespVO respVO = BeanUtils.toBean(bean, OAuth2OpenAccessTokenRespVO.class); |
| | | respVO.setTokenType(SecurityFrameworkUtils.AUTHORIZATION_BEARER.toLowerCase()); |
| | | respVO.setExpiresIn(OAuth2Utils.getExpiresIn(bean.getExpiresTime())); |
| | | respVO.setScope(OAuth2Utils.buildScopeStr(bean.getScopes())); |
| | | return respVO; |
| | | } |
| | |
| | | package com.iailab.module.system.dal.dataobject.app; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.iailab.framework.mybatis.core.dataobject.BaseDO; |
| | |
| | | * 应用名称 |
| | | */ |
| | | private String appName; |
| | | |
| | | /** |
| | | * 应用类型 |
| | | */ |
| | | private Integer type; |
| | | |
| | | /** |
| | | * 应用域名 |
| | |
| | | */ |
| | | private String remark; |
| | | |
| | | /** |
| | | * 租户ID |
| | | */ |
| | | private Long tenantId; |
| | | |
| | | /** |
| | | * 分组ID |
| | | */ |
| | | private Long groupId; |
| | | |
| | | /** |
| | | * 应用类型(1-系统菜单, 2-应用菜单) |
| | | */ |
| | | @TableField(exist = false) |
| | | private Integer appType; |
| | | |
| | | /** |
| | | * 应用菜单id |
| | | */ |
| | | @TableField(exist = false) |
| | | private Long appMenuId; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.dal.dataobject.app; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.iailab.framework.mybatis.core.dataobject.BaseDO; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 分组分组表 |
| | | * |
| | | * @author Houzhongjian |
| | | * @Description |
| | | * @createTime 2024年09月20日 |
| | | */ |
| | | @TableName("system_app_group") |
| | | @KeySequence("system_app_group_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class AppGroupDO extends BaseDO { |
| | | |
| | | public static final Long PARENT_ID_ROOT = 0L; |
| | | |
| | | /** |
| | | * ID |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | |
| | | /** |
| | | * 分组编号 |
| | | */ |
| | | private String code; |
| | | |
| | | /** |
| | | * 分组名称 |
| | | */ |
| | | private String name; |
| | | |
| | | /** |
| | | * 分组图标 |
| | | */ |
| | | private String icon; |
| | | |
| | | /** |
| | | * 排序 |
| | | */ |
| | | private Integer sort; |
| | | |
| | | /** |
| | | * 备注 |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.dal.dataobject.app; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.iailab.framework.common.enums.CommonStatusEnum; |
| | | import com.iailab.framework.mybatis.core.dataobject.BaseDO; |
| | | import com.iailab.framework.tenant.core.db.TenantBaseDO; |
| | | import com.iailab.module.system.enums.permission.MenuTypeEnum; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 菜单 DO |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @TableName("system_app_menu") |
| | | @KeySequence("system_app_menu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class AppMenuDO extends BaseDO { |
| | | |
| | | /** |
| | | * 菜单编号 - 根节点 |
| | | */ |
| | | public static final Long ID_ROOT = 0L; |
| | | |
| | | /** |
| | | * 菜单编号 |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | /** |
| | | * 菜单名称 |
| | | */ |
| | | private String name; |
| | | /** |
| | | * 权限标识 |
| | | * |
| | | * 一般格式为:${系统}:${模块}:${操作} |
| | | * 例如说:system:admin:add,即 system 服务的添加管理员。 |
| | | * |
| | | * 当我们把该 MenuDO 赋予给角色后,意味着该角色有该资源: |
| | | * - 对于后端,配合 @PreAuthorize 注解,配置 API 接口需要该权限,从而对 API 接口进行权限控制。 |
| | | * - 对于前端,配合前端标签,配置按钮是否展示,避免用户没有该权限时,结果可以看到该操作。 |
| | | */ |
| | | private String permission; |
| | | /** |
| | | * 菜单类型 |
| | | * |
| | | * 枚举 {@link MenuTypeEnum} |
| | | */ |
| | | private Integer type; |
| | | /** |
| | | * 显示顺序 |
| | | */ |
| | | private Integer sort; |
| | | /** |
| | | * 父菜单ID |
| | | */ |
| | | private Long parentId; |
| | | /** |
| | | * 路由地址 |
| | | * |
| | | * 如果 path 为 http(s) 时,则它是外链 |
| | | */ |
| | | private String path; |
| | | /** |
| | | * 菜单图标 |
| | | */ |
| | | private String icon; |
| | | /** |
| | | * 组件路径 |
| | | */ |
| | | private String component; |
| | | /** |
| | | * 组件名 |
| | | */ |
| | | private String componentName; |
| | | /** |
| | | * 状态 |
| | | * |
| | | * 枚举 {@link CommonStatusEnum} |
| | | */ |
| | | private Integer status; |
| | | /** |
| | | * 是否可见 |
| | | * |
| | | * 只有菜单、目录使用 |
| | | * 当设置为 true 时,该菜单不会展示在侧边栏,但是路由还是存在。例如说,一些独立的编辑页面 /edit/1024 等等 |
| | | */ |
| | | private Boolean visible; |
| | | /** |
| | | * 是否缓存 |
| | | * |
| | | * 只有菜单、目录使用,否使用 Vue 路由的 keep-alive 特性 |
| | | * 注意:如果开启缓存,则必须填写 {@link #componentName} 属性,否则无法缓存 |
| | | */ |
| | | private Boolean keepAlive; |
| | | /** |
| | | * 是否总是显示 |
| | | * |
| | | * 如果为 false 时,当该菜单只有一个子菜单时,不展示自己,直接展示子菜单 |
| | | */ |
| | | private Boolean alwaysShow; |
| | | |
| | | /** |
| | | * 应用ID |
| | | */ |
| | | private Long appId; |
| | | |
| | | |
| | | } |
| | |
| | | */ |
| | | private Boolean alwaysShow; |
| | | |
| | | /** |
| | | * 应用ID |
| | | */ |
| | | private Long appId; |
| | | |
| | | /** |
| | | * 租户ID |
| | | */ |
| | | private Long tenantId; |
| | | |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.dal.mysql.app; |
| | | |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | | import com.iailab.framework.mybatis.core.mapper.BaseMapperX; |
| | | import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import com.iailab.framework.tenant.core.aop.TenantIgnore; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppGroupPageReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppGroupDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * @author Houzhongjian |
| | | * @Description |
| | | * @createTime 2024年09月10日 |
| | | */ |
| | | @Mapper |
| | | public interface AppGroupMapper extends BaseMapperX<AppGroupDO> { |
| | | default PageResult<AppGroupDO> selectPage(AppGroupPageReqVO reqVO) { |
| | | return selectPage(reqVO, new LambdaQueryWrapperX<AppGroupDO>() |
| | | .likeIfPresent(AppGroupDO::getCode, reqVO.getCode()) |
| | | .likeIfPresent(AppGroupDO::getName, reqVO.getName()) |
| | | .orderByDesc(AppGroupDO::getId)); |
| | | } |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.dal.mysql.app; |
| | | |
| | | import com.iailab.framework.mybatis.core.mapper.BaseMapperX; |
| | | import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppMenuDO; |
| | | import com.iailab.module.system.dal.dataobject.dept.DeptDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | @Mapper |
| | | public interface AppMenuMapper extends BaseMapperX<AppMenuDO> { |
| | | |
| | | default AppMenuDO selectByParentIdAndName(Long parentId, String name) { |
| | | return selectOne(AppMenuDO::getParentId, parentId, AppMenuDO::getName, name); |
| | | } |
| | | |
| | | default Long selectCountByParentId(Long parentId) { |
| | | return selectCount(AppMenuDO::getParentId, parentId); |
| | | } |
| | | |
| | | default List<AppMenuDO> selectListByParentId(Collection<Long> parentIds) { |
| | | return selectList(AppMenuDO::getParentId, parentIds); |
| | | } |
| | | |
| | | default List<AppMenuDO> selectList(MenuListReqVO reqVO) { |
| | | return selectList(new LambdaQueryWrapperX<AppMenuDO>() |
| | | .likeIfPresent(AppMenuDO::getName, reqVO.getName()) |
| | | .eqIfPresent(AppMenuDO::getStatus, reqVO.getStatus())); |
| | | } |
| | | |
| | | default List<AppMenuDO> selectListByPermission(String permission) { |
| | | return selectList(AppMenuDO::getPermission, permission); |
| | | } |
| | | } |
| | |
| | | import com.iailab.module.system.dal.dataobject.permission.MenuDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | @Mapper |
| | |
| | | .eqIfPresent(MenuDO::getStatus, reqVO.getStatus())); |
| | | } |
| | | |
| | | default List<MenuDO> selectAppMenuList(Long tenantId, MenuListReqVO reqVO) { |
| | | return selectList(new LambdaQueryWrapperX<MenuDO>() |
| | | .likeIfPresent(MenuDO::getName, reqVO.getName()) |
| | | .eqIfPresent(MenuDO::getStatus, reqVO.getStatus()) |
| | | .eq(MenuDO::getTenantId, tenantId)); |
| | | } |
| | | |
| | | default List<MenuDO> selectListByPermission(String permission) { |
| | | return selectList(MenuDO::getPermission, permission); |
| | | } |
| | | |
| | | default List<MenuDO> selectListByParentId(Collection<Long> parentIds) { |
| | | return selectList(MenuDO::getParentId, parentIds); |
| | | } |
| | | } |
| | |
| | | package com.iailab.module.system.dal.mysql.user; |
| | | |
| | | import com.baomidou.dynamic.datasource.annotation.Master; |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | | import com.iailab.framework.mybatis.core.mapper.BaseMapperX; |
| | | import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import com.iailab.framework.tenant.core.db.dynamic.TenantDS; |
| | | import com.iailab.module.system.controller.admin.user.vo.user.UserPageReqVO; |
| | | import com.iailab.module.system.dal.dataobject.user.AdminUserDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | |
| | | import java.util.List; |
| | | |
| | | @Mapper |
| | | @Master |
| | | public interface AdminUserMapper extends BaseMapperX<AdminUserDO> { |
| | | |
| | | default AdminUserDO selectByUsername(String username) { |
对比新文件 |
| | |
| | | package com.iailab.module.system.service.app; |
| | | |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppGroupPageReqVO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppGroupSaveReqVO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppPageReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppGroupDO; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author Houzhongjian |
| | | * @Description |
| | | * @createTime 2024年09月20日 |
| | | */ |
| | | public interface AppGroupService { |
| | | |
| | | Long create(AppGroupSaveReqVO createReqVO); |
| | | |
| | | Long update(AppGroupSaveReqVO createReqVO); |
| | | |
| | | void delete(Long id); |
| | | |
| | | AppGroupDO getInfo(Long id); |
| | | |
| | | PageResult<AppGroupDO> getPage(AppGroupPageReqVO pageReqVO); |
| | | |
| | | List<AppGroupDO> getList(); |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.service.app; |
| | | |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.framework.tenant.core.aop.TenantIgnore; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppGroupPageReqVO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppGroupSaveReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppGroupDO; |
| | | import com.iailab.module.system.dal.mysql.app.AppGroupMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author Houzhongjian |
| | | * @Description |
| | | * @createTime 2024年09月20日 |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class AppGroupServiceImpl implements AppGroupService { |
| | | |
| | | @Resource |
| | | private AppGroupMapper appGroupMapper; |
| | | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @TenantIgnore |
| | | public Long create(AppGroupSaveReqVO createReqVO) { |
| | | AppGroupDO appGroup = BeanUtils.toBean(createReqVO, AppGroupDO.class); |
| | | appGroupMapper.insert(appGroup); |
| | | return appGroup.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @TenantIgnore |
| | | public Long update(AppGroupSaveReqVO createReqVO) { |
| | | AppGroupDO appGroup = BeanUtils.toBean(createReqVO, AppGroupDO.class); |
| | | appGroupMapper.updateById(appGroup); |
| | | return appGroup.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @TenantIgnore |
| | | public void delete(Long id) { |
| | | AppGroupDO appGroup = new AppGroupDO(); |
| | | appGroup.setId(id); |
| | | appGroupMapper.deleteById(id); |
| | | } |
| | | |
| | | @Override |
| | | public AppGroupDO getInfo(Long id) { |
| | | return appGroupMapper.selectById(id); |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<AppGroupDO> getPage(AppGroupPageReqVO pageReqVO) { |
| | | return appGroupMapper.selectPage(pageReqVO); |
| | | } |
| | | |
| | | @Override |
| | | public List<AppGroupDO> getList(){ |
| | | return appGroupMapper.selectList(); |
| | | } |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.service.app; |
| | | |
| | | |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSaveVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppMenuDO; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 应用菜单 Service 接口 |
| | | * |
| | | * @author iailab |
| | | */ |
| | | public interface AppMenuService { |
| | | |
| | | /** |
| | | * 创建应用菜单 |
| | | * |
| | | * @param createReqVO 应用菜单信息 |
| | | * @return 创建出来的应用菜单编号 |
| | | */ |
| | | Long createMenu(MenuSaveVO createReqVO); |
| | | |
| | | /** |
| | | * 更新应用菜单 |
| | | * |
| | | * @param updateReqVO 应用菜单信息 |
| | | */ |
| | | void updateMenu(MenuSaveVO updateReqVO); |
| | | |
| | | /** |
| | | * 删除应用菜单 |
| | | * |
| | | * @param id 应用菜单编号 |
| | | */ |
| | | void deleteMenu(Long id); |
| | | |
| | | /** |
| | | * 获得所有应用菜单列表 |
| | | * |
| | | * @return 应用菜单列表 |
| | | */ |
| | | List<AppMenuDO> getMenuList(); |
| | | |
| | | /** |
| | | * 获得所有应用菜单列表 |
| | | * |
| | | * @return 应用菜单列表(API使用) |
| | | */ |
| | | List<AppMenuDO> getMenuList(Integer type); |
| | | |
| | | /** |
| | | * 基于租户,筛选应用菜单列表 |
| | | * 注意,如果是系统租户,返回的还是全应用菜单 |
| | | * |
| | | * @return 应用菜单列表(API使用) |
| | | */ |
| | | List<AppMenuDO> getMenuListByTenant(Integer type); |
| | | |
| | | /** |
| | | * 根据父菜单ID查询所有子菜单 |
| | | * |
| | | * @return 应用菜单列表(API使用) |
| | | */ |
| | | List<AppMenuDO> selectListByParentId(Collection<Long> parentIds); |
| | | |
| | | /** |
| | | * 基于租户,筛选应用菜单列表 |
| | | * 注意,如果是系统租户,返回的还是全应用菜单 |
| | | * |
| | | * @param reqVO 筛选条件请求 VO |
| | | * @return 应用菜单列表 |
| | | */ |
| | | List<AppMenuDO> getMenuListByTenant(MenuListReqVO reqVO); |
| | | |
| | | /** |
| | | * 过滤掉关闭的应用菜单及其子应用菜单 |
| | | * |
| | | * @param list 应用菜单列表 |
| | | * @return 过滤后的应用菜单列表 |
| | | */ |
| | | List<AppMenuDO> filterDisableMenus(List<AppMenuDO> list); |
| | | |
| | | /** |
| | | * 筛选应用菜单列表 |
| | | * |
| | | * @param reqVO 筛选条件请求 VO |
| | | * @return 应用菜单列表 |
| | | */ |
| | | List<AppMenuDO> getMenuList(MenuListReqVO reqVO); |
| | | |
| | | /** |
| | | * 获得权限对应的应用菜单编号数组 |
| | | * |
| | | * @param permission 权限标识 |
| | | * @return 数组 |
| | | */ |
| | | List<Long> getMenuIdListByPermissionFromCache(String permission); |
| | | |
| | | /** |
| | | * 获得应用菜单 |
| | | * |
| | | * @param id 应用菜单编号 |
| | | * @return 应用菜单 |
| | | */ |
| | | AppMenuDO getMenu(Long id); |
| | | |
| | | /** |
| | | * 获得应用菜单数组 |
| | | * |
| | | * @param ids 应用菜单编号数组 |
| | | * @return 应用菜单数组 |
| | | */ |
| | | List<AppMenuDO> getMenuList(Collection<Long> ids); |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.system.service.app; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.google.common.annotations.VisibleForTesting; |
| | | import com.google.common.collect.Lists; |
| | | import com.iailab.framework.common.enums.CommonStatusEnum; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSaveVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppMenuDO; |
| | | import com.iailab.module.system.dal.mysql.app.AppMenuMapper; |
| | | import com.iailab.module.system.dal.redis.RedisKeyConstants; |
| | | import com.iailab.module.system.enums.permission.MenuTypeEnum; |
| | | import com.iailab.module.system.service.tenant.TenantService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.cache.annotation.CacheEvict; |
| | | import org.springframework.cache.annotation.Cacheable; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.*; |
| | | |
| | | import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertList; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertMap; |
| | | import static com.iailab.module.system.dal.dataobject.app.AppMenuDO.ID_ROOT; |
| | | import static com.iailab.module.system.enums.ErrorCodeConstants.*; |
| | | |
| | | |
| | | /** |
| | | * 菜单 Service 实现 |
| | | * |
| | | * @author iailab |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class AppMenuServiceImpl implements AppMenuService { |
| | | |
| | | @Resource |
| | | private AppMenuMapper appMenuMapper; |
| | | @Resource |
| | | @Lazy // 延迟,避免循环依赖报错 |
| | | private TenantService tenantService; |
| | | |
| | | @Override |
| | | @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#createReqVO.permission", |
| | | condition = "#createReqVO.permission != null") |
| | | public Long createMenu(MenuSaveVO createReqVO) { |
| | | // 校验父菜单存在 |
| | | validateParentMenu(createReqVO.getParentId(), null); |
| | | // 校验菜单(自己) |
| | | validateMenu(createReqVO.getParentId(), createReqVO.getName(), null); |
| | | |
| | | // 插入数据库 |
| | | AppMenuDO menu = BeanUtils.toBean(createReqVO, AppMenuDO.class); |
| | | initMenuProperty(menu); |
| | | appMenuMapper.insert(menu); |
| | | // 返回 |
| | | return menu.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, |
| | | allEntries = true) // allEntries 清空所有缓存,因为 permission 如果变更,涉及到新老两个 permission。直接清理,简单有效 |
| | | public void updateMenu(MenuSaveVO updateReqVO) { |
| | | // 校验更新的菜单是否存在 |
| | | if (appMenuMapper.selectById(updateReqVO.getId()) == null) { |
| | | throw exception(MENU_NOT_EXISTS); |
| | | } |
| | | // 校验父菜单存在 |
| | | validateParentMenu(updateReqVO.getParentId(), updateReqVO.getId()); |
| | | // 校验菜单(自己) |
| | | validateMenu(updateReqVO.getParentId(), updateReqVO.getName(), updateReqVO.getId()); |
| | | |
| | | // 更新到数据库 |
| | | AppMenuDO updateObj = BeanUtils.toBean(updateReqVO, AppMenuDO.class); |
| | | initMenuProperty(updateObj); |
| | | appMenuMapper.updateById(updateObj); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, |
| | | allEntries = true) // allEntries 清空所有缓存,因为此时不知道 id 对应的 permission 是多少。直接清理,简单有效 |
| | | public void deleteMenu(Long id) { |
| | | // 校验是否还有子菜单 |
| | | if (appMenuMapper.selectCountByParentId(id) > 0) { |
| | | throw exception(MENU_EXISTS_CHILDREN); |
| | | } |
| | | // 校验删除的菜单是否存在 |
| | | if (appMenuMapper.selectById(id) == null) { |
| | | throw exception(MENU_NOT_EXISTS); |
| | | } |
| | | // 标记删除 |
| | | appMenuMapper.deleteById(id); |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> getMenuList() { |
| | | return appMenuMapper.selectList(); |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> getMenuList(Integer type) { |
| | | LambdaQueryWrapper<AppMenuDO> queryWrapper = new LambdaQueryWrapper<>(); |
| | | if (type == 1) { |
| | | queryWrapper.eq(AppMenuDO::getType, type); |
| | | } |
| | | return appMenuMapper.selectList(queryWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> getMenuListByTenant(Integer type) { |
| | | // 查询所有菜单,并过滤掉关闭的节点 |
| | | List<AppMenuDO> menus = getMenuList(type); |
| | | // 开启多租户的情况下,需要过滤掉未开通的菜单 |
| | | tenantService.handleTenantMenu(menuIds -> menus.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId()))); |
| | | return menus; |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> selectListByParentId(Collection<Long> parentIds) { |
| | | return appMenuMapper.selectListByParentId(parentIds); |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> getMenuListByTenant(MenuListReqVO reqVO) { |
| | | // 查询所有菜单,并过滤掉关闭的节点 |
| | | List<AppMenuDO> menus = getMenuList(reqVO); |
| | | // 开启多租户的情况下,需要过滤掉未开通的菜单 |
| | | tenantService.handleTenantMenu(menuIds -> menus.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId()))); |
| | | return menus; |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> filterDisableMenus(List<AppMenuDO> menuList) { |
| | | if (CollUtil.isEmpty(menuList)){ |
| | | return Collections.emptyList(); |
| | | } |
| | | Map<Long, AppMenuDO> menuMap = convertMap(menuList, AppMenuDO::getId); |
| | | |
| | | // 遍历 menu 菜单,查找不是禁用的菜单,添加到 enabledMenus 结果 |
| | | List<AppMenuDO> enabledMenus = new ArrayList<>(); |
| | | Set<Long> disabledMenuCache = new HashSet<>(); // 存下递归搜索过被禁用的菜单,防止重复的搜索 |
| | | for (AppMenuDO menu : menuList) { |
| | | if (isMenuDisabled(menu, menuMap, disabledMenuCache)) { |
| | | continue; |
| | | } |
| | | enabledMenus.add(menu); |
| | | } |
| | | return enabledMenus; |
| | | } |
| | | |
| | | private boolean isMenuDisabled(AppMenuDO node, Map<Long, AppMenuDO> menuMap, Set<Long> disabledMenuCache) { |
| | | // 如果已经判定是禁用的节点,直接结束 |
| | | if (disabledMenuCache.contains(node.getId())) { |
| | | return true; |
| | | } |
| | | |
| | | // 1. 遍历到 parentId 为根节点,则无需判断 |
| | | Long parentId = node.getParentId(); |
| | | if (ObjUtil.equal(parentId, ID_ROOT)) { |
| | | if (CommonStatusEnum.isDisable(node.getStatus())) { |
| | | disabledMenuCache.add(node.getId()); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // 2. 继续遍历 parent 节点 |
| | | AppMenuDO parent = menuMap.get(parentId); |
| | | if (parent == null || isMenuDisabled(parent, menuMap, disabledMenuCache)) { |
| | | disabledMenuCache.add(node.getId()); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> getMenuList(MenuListReqVO reqVO) { |
| | | return appMenuMapper.selectList(reqVO); |
| | | } |
| | | |
| | | @Override |
| | | @Cacheable(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#permission") |
| | | public List<Long> getMenuIdListByPermissionFromCache(String permission) { |
| | | List<AppMenuDO> menus = appMenuMapper.selectListByPermission(permission); |
| | | return convertList(menus, AppMenuDO::getId); |
| | | } |
| | | |
| | | @Override |
| | | public AppMenuDO getMenu(Long id) { |
| | | return appMenuMapper.selectById(id); |
| | | } |
| | | |
| | | @Override |
| | | public List<AppMenuDO> getMenuList(Collection<Long> ids) { |
| | | // 当 ids 为空时,返回一个空的实例对象 |
| | | if (CollUtil.isEmpty(ids)) { |
| | | return Lists.newArrayList(); |
| | | } |
| | | return appMenuMapper.selectBatchIds(ids); |
| | | } |
| | | |
| | | /** |
| | | * 校验父菜单是否合法 |
| | | * <p> |
| | | * 1. 不能设置自己为父菜单 |
| | | * 2. 父菜单不存在 |
| | | * 3. 父菜单必须是 {@link MenuTypeEnum#MENU} 菜单类型 |
| | | * |
| | | * @param parentId 父菜单编号 |
| | | * @param childId 当前菜单编号 |
| | | */ |
| | | @VisibleForTesting |
| | | void validateParentMenu(Long parentId, Long childId) { |
| | | if (parentId == null || ID_ROOT.equals(parentId)) { |
| | | return; |
| | | } |
| | | // 不能设置自己为父菜单 |
| | | if (parentId.equals(childId)) { |
| | | throw exception(MENU_PARENT_ERROR); |
| | | } |
| | | AppMenuDO menu = appMenuMapper.selectById(parentId); |
| | | // 父菜单不存在 |
| | | if (menu == null) { |
| | | throw exception(MENU_PARENT_NOT_EXISTS); |
| | | } |
| | | // 父菜单必须是目录或者菜单类型 |
| | | if (!MenuTypeEnum.DIR.getType().equals(menu.getType()) |
| | | && !MenuTypeEnum.MENU.getType().equals(menu.getType())) { |
| | | throw exception(MENU_PARENT_NOT_DIR_OR_MENU); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 校验菜单是否合法 |
| | | * <p> |
| | | * 1. 校验相同父菜单编号下,是否存在相同的菜单名 |
| | | * |
| | | * @param name 菜单名字 |
| | | * @param parentId 父菜单编号 |
| | | * @param id 菜单编号 |
| | | */ |
| | | @VisibleForTesting |
| | | void validateMenu(Long parentId, String name, Long id) { |
| | | AppMenuDO menu = appMenuMapper.selectByParentIdAndName(parentId, name); |
| | | if (menu == null) { |
| | | return; |
| | | } |
| | | // 如果 id 为空,说明不用比较是否为相同 id 的菜单 |
| | | if (id == null) { |
| | | throw exception(MENU_NAME_DUPLICATE); |
| | | } |
| | | if (!menu.getId().equals(id)) { |
| | | throw exception(MENU_NAME_DUPLICATE); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化菜单的通用属性。 |
| | | * <p> |
| | | * 例如说,只有目录或者菜单类型的菜单,才设置 icon |
| | | * |
| | | * @param menu 菜单 |
| | | */ |
| | | private void initMenuProperty(AppMenuDO menu) { |
| | | // 菜单为按钮类型时,无需 component、icon、path 属性,进行置空 |
| | | if (MenuTypeEnum.BUTTON.getType().equals(menu.getType())) { |
| | | menu.setComponent(""); |
| | | menu.setComponentName(""); |
| | | menu.setIcon(""); |
| | | menu.setPath(""); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | import com.iailab.module.system.controller.admin.app.vo.AppSaveReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author PanZhibao |
| | | * @Description |
| | |
| | | AppDO getInfo(Long id); |
| | | |
| | | PageResult<AppDO> getPage(AppPageReqVO pageReqVO); |
| | | |
| | | List<AppDO> getList(); |
| | | |
| | | AppDO getAppByTenantId(Long tenantId); |
| | | |
| | | // List<AppMenuRespDTO> getAppMenu(Long id); |
| | | |
| | | } |
| | |
| | | package com.iailab.module.system.service.app; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import com.iailab.framework.security.core.util.SecurityFrameworkUtils; |
| | | import com.iailab.framework.tenant.core.aop.TenantIgnore; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppPageReqVO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppSaveReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.MenuDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.RoleDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.RoleMenuDO; |
| | | import com.iailab.module.system.dal.dataobject.tenant.TenantDO; |
| | | import com.iailab.module.system.dal.dataobject.tenant.TenantPackageDO; |
| | | import com.iailab.module.system.dal.mysql.app.AppMapper; |
| | | import com.iailab.module.system.dal.mysql.permission.MenuMapper; |
| | | import com.iailab.module.system.dal.mysql.permission.RoleMapper; |
| | | import com.iailab.module.system.dal.mysql.permission.RoleMenuMapper; |
| | | import com.iailab.module.system.dal.mysql.tenant.TenantMapper; |
| | | import com.iailab.module.system.dal.mysql.tenant.TenantPackageMapper; |
| | | import com.iailab.module.system.enums.permission.MenuTypeEnum; |
| | | import com.iailab.module.system.service.permission.PermissionService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.ObjectUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.*; |
| | | |
| | | import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static com.iailab.framework.tenant.core.context.TenantContextHolder.getTenantId; |
| | | import static com.iailab.module.system.enums.ErrorCodeConstants.MENU_EXISTS_CHILDREN; |
| | | import static com.iailab.module.system.enums.ErrorCodeConstants.MENU_NOT_EXISTS; |
| | | |
| | | /** |
| | | * @author PanZhibao |
| | |
| | | @Resource |
| | | private AppMapper appMapper; |
| | | |
| | | @Resource |
| | | private MenuMapper menuMapper; |
| | | |
| | | @Resource |
| | | private RoleMapper roleMapper; |
| | | |
| | | @Resource |
| | | private RoleMenuMapper roleMenuMapper; |
| | | |
| | | @Resource |
| | | private PermissionService permissionService; |
| | | |
| | | @Resource |
| | | private TenantPackageMapper tenantPackageMapper; |
| | | |
| | | @Resource |
| | | private TenantMapper tenantMapper; |
| | | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @TenantIgnore |
| | | public Long create(AppSaveReqVO createReqVO) { |
| | | AppDO app = BeanUtils.toBean(createReqVO, AppDO.class); |
| | | appMapper.insert(app); |
| | | // //为应用创建默认菜单并授权 |
| | | dealAppMenu(1, app); |
| | | return app.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @TenantIgnore |
| | | public Long update(AppSaveReqVO createReqVO) { |
| | | AppDO app = BeanUtils.toBean(createReqVO, AppDO.class); |
| | | appMapper.updateById(app); |
| | | // //修改默认菜单并授权 |
| | | dealAppMenu(2, app); |
| | | return app.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @TenantIgnore |
| | | public void delete(Long id) { |
| | | AppDO appDO = new AppDO(); |
| | | appDO.setId(id); |
| | | dealAppMenu(3, appDO); |
| | | appMapper.deleteById(id); |
| | | } |
| | | |
| | |
| | | return appMapper.selectPage(pageReqVO); |
| | | } |
| | | |
| | | @Override |
| | | public List<AppDO> getList() { |
| | | Long tenantId = getTenantId(); |
| | | LambdaQueryWrapperX<MenuDO> menuDOLambdaQueryWrapperX = new LambdaQueryWrapperX<>(); |
| | | menuDOLambdaQueryWrapperX.eq(MenuDO::getParentId, 0) |
| | | .eq(MenuDO::getAppId, 0); |
| | | if (tenantId != 1) { |
| | | //非系统租户查租户套餐 |
| | | TenantDO tenantDO = tenantMapper.selectById(tenantId); |
| | | TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(tenantDO.getPackageId()); |
| | | menuDOLambdaQueryWrapperX.in(MenuDO::getId, tenantPackageDO.getMenuIds()); |
| | | } |
| | | //查询系统应用菜单 |
| | | // List<MenuDO> menuDOS = menuMapper.selectList(menuDOLambdaQueryWrapperX); |
| | | // List<AppDO> systemApps = convertMenuToApp(menuDOS); |
| | | //创建一个系统管理应用菜单 |
| | | AppDO aDo = new AppDO(); |
| | | aDo.setAppType(1); |
| | | aDo.setAppName("系统管理"); |
| | | aDo.setOrderNum(0); |
| | | List<AppDO> systemApps = new ArrayList<>(); |
| | | systemApps.add(aDo); |
| | | List<AppDO> appDOS = appMapper.selectList(); |
| | | //暂时先遍历处理应用菜单和应用类型 |
| | | appDOS.stream().forEach(appDO -> { |
| | | List<MenuDO> menuDOS = menuMapper.selectList(new LambdaQueryWrapper<MenuDO>().eq(MenuDO::getParentId, 0) |
| | | .eq(MenuDO::getAppId, appDO.getId())); |
| | | appDO.setAppMenuId(menuDOS.get(0).getId()); |
| | | appDO.setAppType(2); |
| | | }); |
| | | systemApps.addAll(appDOS); |
| | | return systemApps; |
| | | } |
| | | |
| | | @Override |
| | | public AppDO getAppByTenantId(Long tenantId) { |
| | | //暂时支持一个租户对应一个应用 |
| | | List<AppDO> appDOS = appMapper.selectList(new LambdaQueryWrapper<AppDO>().eq(AppDO::getTenantId, tenantId)); |
| | | if(ObjectUtils.isNotEmpty(appDOS)) { |
| | | return appDOS.get(0); |
| | | } else { |
| | | AppDO appDO = new AppDO(); |
| | | appDO.setTenantId(tenantId); |
| | | appDO.setId(0L); |
| | | return appDO; |
| | | } |
| | | } |
| | | |
| | | // @Override |
| | | // public List<MenuRespDTO> getAppMenu(Long id) { |
| | | // |
| | | // List<MenuDO> children = new LinkedList<>(); |
| | | // // 遍历每一层 |
| | | // Collection<Long> parentIds = Collections.singleton(id); |
| | | // for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环 |
| | | // // 查询当前层,所有的子应用菜单 |
| | | // List<MenuDO> menus = menuMapper.selectListByParentId(parentIds); |
| | | // // 1. 如果没有子菜单,则结束遍历 |
| | | // if (CollUtil.isEmpty(menus)) { |
| | | // break; |
| | | // } |
| | | // // 2. 如果有子应用菜单,继续遍历 |
| | | // children.addAll(menus); |
| | | // parentIds = convertSet(menus, MenuDO::getId); |
| | | // } |
| | | // children = menuService.filterDisableMenus(children); |
| | | // return AuthConvert.INSTANCE.buildMenuTree(id, children); |
| | | // |
| | | // } |
| | | |
| | | private void dealAppMenu(Integer type, AppDO app){ |
| | | String loginUserNickname = SecurityFrameworkUtils.getLoginUserNickname(); |
| | | MenuDO menuDO = new MenuDO(); |
| | | menuDO.setAppId(app.getId()); |
| | | menuDO.setName(app.getAppName()); |
| | | menuDO.setType(MenuTypeEnum.DIR.getType()); |
| | | menuDO.setSort(app.getOrderNum()); |
| | | menuDO.setPath("/" + app.getAppCode()); |
| | | menuDO.setTenantId(app.getTenantId()); |
| | | if(type == 1){ |
| | | menuDO.setCreator(loginUserNickname); |
| | | menuDO.setCreateTime(app.getCreateTime()); |
| | | menuMapper.insert(menuDO); |
| | | //内置租户角色分配菜单 |
| | | assignRoleMenu(menuDO.getId(), app.getTenantId()); |
| | | } else if(type == 2){ |
| | | LambdaUpdateWrapper<MenuDO> updateWrapper = new LambdaUpdateWrapper<>(); |
| | | updateWrapper.eq(MenuDO::getAppId, app.getId()); |
| | | updateWrapper.eq(MenuDO::getParentId, 0L); |
| | | List<MenuDO> menuDOS = menuMapper.selectList(updateWrapper); |
| | | if(menuDOS.size() > 0){ |
| | | menuDO.setUpdater(loginUserNickname); |
| | | menuDO.setUpdateTime(app.getUpdateTime()); |
| | | menuMapper.update(menuDO, updateWrapper); |
| | | } else { |
| | | menuDO.setCreator(loginUserNickname); |
| | | menuDO.setCreateTime(app.getCreateTime()); |
| | | menuMapper.insert(menuDO); |
| | | //内置租户角色分配菜单 |
| | | assignRoleMenu(menuDO.getId(), app.getTenantId()); |
| | | } |
| | | } else if(type == 3){ |
| | | //删除租户、角色权限 |
| | | app = appMapper.selectById(app.getId()); |
| | | LambdaQueryWrapperX<MenuDO> menuWrapper = new LambdaQueryWrapperX<>(); |
| | | menuWrapper.eq(MenuDO::getAppId, app.getId()); |
| | | menuWrapper.eq(MenuDO::getType, MenuTypeEnum.DIR.getType()); |
| | | MenuDO menu = menuMapper.selectOne(menuWrapper); |
| | | TenantDO tenantDO = tenantMapper.selectById(app.getTenantId()); |
| | | TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(tenantDO.getPackageId()); |
| | | Set<Long> menuIds = tenantPackageDO.getMenuIds(); |
| | | menuIds.remove(menu.getId()); |
| | | // 校验是否还有子菜单 |
| | | if (menuMapper.selectCountByParentId(menu.getId()) > 0) { |
| | | throw exception(MENU_EXISTS_CHILDREN); |
| | | } |
| | | // 校验删除的菜单是否存在 |
| | | if (menuMapper.selectById(menu.getId()) == null) { |
| | | throw exception(MENU_NOT_EXISTS); |
| | | } |
| | | // 标记删除 |
| | | menuMapper.deleteById(menu.getId()); |
| | | // 删除授予给角色的权限 |
| | | permissionService.processMenuDeleted(menu.getId()); |
| | | //删除菜单 |
| | | menuMapper.delete(menuWrapper); |
| | | } |
| | | } |
| | | |
| | | private void assignRoleMenu(Long menuId, Long tenantId) { |
| | | //查询内置租户管理员 |
| | | LambdaQueryWrapperX<RoleDO> roleQueryWrapper = new LambdaQueryWrapperX<>(); |
| | | roleQueryWrapper.eq(RoleDO::getCode, "tenant_admin"); |
| | | roleQueryWrapper.eq(RoleDO::getTenantId, tenantId); |
| | | RoleDO roleDO = roleMapper.selectOne(roleQueryWrapper); |
| | | RoleMenuDO entity = new RoleMenuDO(); |
| | | entity.setRoleId(roleDO.getId()); |
| | | entity.setMenuId(menuId); |
| | | entity.setTenantId(tenantId); |
| | | roleMenuMapper.insert(entity); |
| | | TenantDO tenantDO = tenantMapper.selectById(tenantId); |
| | | TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(tenantDO.getPackageId()); |
| | | Set<Long> menuIds = tenantPackageDO.getMenuIds(); |
| | | menuIds.add(menuId); |
| | | tenantPackageMapper.updateById(tenantPackageDO); |
| | | } |
| | | |
| | | private List<AppDO> convertMenuToApp(List<MenuDO> menuDOS) { |
| | | List<AppDO> appDOS = new ArrayList<>(); |
| | | menuDOS.stream().forEach(menuDO -> { |
| | | AppDO appDO = new AppDO(); |
| | | appDO.setAppName(menuDO.getName()); |
| | | appDO.setOrderNum(menuDO.getSort()); |
| | | appDO.setAppMenuId(menuDO.getId()); |
| | | appDO.setAppType(1); |
| | | appDOS.add(appDO); |
| | | }); |
| | | return appDOS; |
| | | } |
| | | |
| | | } |
| | |
| | | List<MenuDO> getMenuListByTenant(MenuListReqVO reqVO); |
| | | |
| | | /** |
| | | * 基于租户,筛选应用菜单列表 |
| | | * 注意,如果是系统租户,返回的还是全菜单 |
| | | * |
| | | * @param reqVO 筛选条件请求 VO |
| | | * @return 应用菜单列表 |
| | | */ |
| | | List<MenuDO> getAppMenuListByTenant(MenuListReqVO reqVO); |
| | | |
| | | /** |
| | | * 过滤掉关闭的菜单及其子菜单 |
| | | * |
| | | * @param list 菜单列表 |
| | |
| | | List<MenuDO> getMenuList(MenuListReqVO reqVO); |
| | | |
| | | /** |
| | | * 筛选菜单列表 |
| | | * |
| | | * @param reqVO 筛选条件请求 VO |
| | | * @return 菜单列表 |
| | | */ |
| | | List<MenuDO> getAppMenuList(MenuListReqVO reqVO); |
| | | |
| | | /** |
| | | * 获得权限对应的菜单编号数组 |
| | | * |
| | | * @param permission 权限标识 |
| | |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSaveVO; |
| | | import com.iailab.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.MenuDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.RoleDO; |
| | | import com.iailab.module.system.dal.dataobject.tenant.TenantDO; |
| | | import com.iailab.module.system.dal.dataobject.tenant.TenantPackageDO; |
| | | import com.iailab.module.system.dal.mysql.permission.MenuMapper; |
| | | import com.iailab.module.system.dal.redis.RedisKeyConstants; |
| | | import com.iailab.module.system.enums.permission.MenuTypeEnum; |
| | | import com.iailab.module.system.service.app.AppService; |
| | | import com.iailab.module.system.service.tenant.TenantPackageService; |
| | | import com.iailab.module.system.service.tenant.TenantService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.ObjectUtils; |
| | | import org.springframework.cache.annotation.CacheEvict; |
| | | import org.springframework.cache.annotation.Cacheable; |
| | | import org.springframework.context.annotation.Lazy; |
| | |
| | | import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertList; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertMap; |
| | | import static com.iailab.framework.tenant.core.context.TenantContextHolder.getTenantId; |
| | | import static com.iailab.module.system.dal.dataobject.permission.MenuDO.ID_ROOT; |
| | | import static com.iailab.module.system.enums.ErrorCodeConstants.*; |
| | | |
| | |
| | | @Lazy // 延迟,避免循环依赖报错 |
| | | private TenantService tenantService; |
| | | |
| | | @Resource |
| | | private TenantPackageService tenantPackageService; |
| | | |
| | | @Resource |
| | | private AppService appService; |
| | | |
| | | @Resource |
| | | private RoleService roleService; |
| | | |
| | | @Override |
| | | @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#createReqVO.permission", |
| | | condition = "#createReqVO.permission != null") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createMenu(MenuSaveVO createReqVO) { |
| | | // 校验父菜单存在 |
| | | validateParentMenu(createReqVO.getParentId(), null); |
| | |
| | | // 插入数据库 |
| | | MenuDO menu = BeanUtils.toBean(createReqVO, MenuDO.class); |
| | | initMenuProperty(menu); |
| | | |
| | | //菜单归属租户和应用 |
| | | Long tenantId = getTenantId(); |
| | | menu.setTenantId(tenantId); |
| | | menu.setAppId(createReqVO.getAppId()); |
| | | menuMapper.insert(menu); |
| | | if(tenantId != 1L) { |
| | | dealPermission(menu); |
| | | } |
| | | // 返回 |
| | | return menu.getId(); |
| | | } |
| | |
| | | @Override |
| | | @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, |
| | | allEntries = true) // allEntries 清空所有缓存,因为 permission 如果变更,涉及到新老两个 permission。直接清理,简单有效 |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateMenu(MenuSaveVO updateReqVO) { |
| | | // 校验更新的菜单是否存在 |
| | | if (menuMapper.selectById(updateReqVO.getId()) == null) { |
| | |
| | | // 更新到数据库 |
| | | MenuDO updateObj = BeanUtils.toBean(updateReqVO, MenuDO.class); |
| | | initMenuProperty(updateObj); |
| | | //菜单归属租户和应用 |
| | | Long tenantId = getTenantId(); |
| | | AppDO appDO = appService.getAppByTenantId(tenantId); |
| | | updateObj.setTenantId(tenantId); |
| | | updateObj.setAppId(appDO.getId()); |
| | | menuMapper.updateById(updateObj); |
| | | } |
| | | |
| | |
| | | public List<MenuDO> getMenuListByTenant(MenuListReqVO reqVO) { |
| | | // 查询所有菜单,并过滤掉关闭的节点 |
| | | List<MenuDO> menus = getMenuList(reqVO); |
| | | // 开启多租户的情况下,需要过滤掉未开通的菜单 |
| | | tenantService.handleTenantMenu(menuIds -> menus.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId()))); |
| | | return menus; |
| | | } |
| | | |
| | | @Override |
| | | public List<MenuDO> getAppMenuListByTenant(MenuListReqVO reqVO) { |
| | | // 查询所有菜单,并过滤掉关闭的节点 |
| | | List<MenuDO> menus = getAppMenuList(reqVO); |
| | | // 开启多租户的情况下,需要过滤掉未开通的菜单 |
| | | tenantService.handleTenantMenu(menuIds -> menus.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId()))); |
| | | return menus; |
| | |
| | | @Override |
| | | public List<MenuDO> getMenuList(MenuListReqVO reqVO) { |
| | | return menuMapper.selectList(reqVO); |
| | | } |
| | | |
| | | @Override |
| | | public List<MenuDO> getAppMenuList(MenuListReqVO reqVO) { |
| | | // 获取 tenantId |
| | | Long tenantId = getTenantId(); |
| | | return menuMapper.selectAppMenuList(tenantId, reqVO); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 新创建菜单赋权给租户管理员 |
| | | */ |
| | | |
| | | private void dealPermission(MenuDO menu) { |
| | | Long tenantId = menu.getTenantId(); |
| | | RoleDO role = roleService.getTenantAdminRole(tenantId); |
| | | TenantDO tenant = tenantService.getTenant(tenantId); |
| | | TenantPackageDO tenantPackage = tenantPackageService.getTenantPackage(tenant.getPackageId()); |
| | | Set<Long> menuIds = tenantPackage.getMenuIds(); |
| | | menuIds.add(menu.getId()); |
| | | tenantPackage.setMenuIds(menuIds); |
| | | tenantPackageService.updateTenantPackage(BeanUtils.toBean(tenantPackage, TenantPackageSaveReqVO.class)); |
| | | permissionService.assignRoleMenu(role.getId(), menuIds); |
| | | } |
| | | |
| | | } |
| | |
| | | void assignRoleMenu(Long roleId, Set<Long> menuIds); |
| | | |
| | | /** |
| | | * 设置角色应用菜单 |
| | | * |
| | | * @param roleId 角色编号 |
| | | * @param menuIds 菜单编号集合 |
| | | */ |
| | | void assignRoleAppMenu(Long roleId, Set<Long> menuIds); |
| | | |
| | | /** |
| | | * 处理角色删除时,删除关联授权数据 |
| | | * |
| | | * @param roleId 角色编号 |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获得角色拥有的应用菜单编号集合 |
| | | * |
| | | * @param roleId 角色编号 |
| | | * @return 菜单编号集合 |
| | | */ |
| | | default Set<Long> getRoleAppMenuListByRoleId(Long roleId) { |
| | | return getRoleAppMenuListByRoleId(singleton(roleId)); |
| | | } |
| | | |
| | | /** |
| | | * 获得角色们拥有的菜单编号集合 |
| | | * |
| | | * @param roleIds 角色编号数组 |
| | |
| | | Set<Long> getRoleMenuListByRoleId(Collection<Long> roleIds); |
| | | |
| | | /** |
| | | * 获得角色们拥有的应用菜单编号集合 |
| | | * |
| | | * @param roleIds 角色编号数组 |
| | | * @return 菜单编号集合 |
| | | */ |
| | | Set<Long> getRoleAppMenuListByRoleId(Collection<Long> roleIds); |
| | | |
| | | /** |
| | | * 获得拥有指定菜单的角色编号数组,从缓存中获取 |
| | | * |
| | | * @param menuId 菜单编号 |
| | |
| | | import com.iailab.framework.common.util.collection.CollectionUtils; |
| | | import com.iailab.framework.datapermission.core.annotation.DataPermission; |
| | | import com.iailab.module.system.api.permission.dto.DeptDataPermissionRespDTO; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.MenuDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.RoleDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.RoleMenuDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.UserRoleDO; |
| | | import com.iailab.module.system.dal.dataobject.tenant.TenantDO; |
| | | import com.iailab.module.system.dal.dataobject.tenant.TenantPackageDO; |
| | | import com.iailab.module.system.dal.mysql.permission.RoleMenuMapper; |
| | | import com.iailab.module.system.dal.mysql.permission.UserRoleMapper; |
| | | import com.iailab.module.system.dal.redis.RedisKeyConstants; |
| | | import com.iailab.module.system.enums.permission.DataScopeEnum; |
| | | import com.iailab.module.system.service.app.AppService; |
| | | import com.iailab.module.system.service.dept.DeptService; |
| | | import com.iailab.module.system.service.tenant.TenantPackageService; |
| | | import com.iailab.module.system.service.tenant.TenantService; |
| | | import com.iailab.module.system.service.user.AdminUserService; |
| | | import com.baomidou.dynamic.datasource.annotation.DSTransactional; |
| | | import com.google.common.annotations.VisibleForTesting; |
| | |
| | | |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static com.iailab.framework.common.util.json.JsonUtils.toJsonString; |
| | | import static com.iailab.framework.tenant.core.context.TenantContextHolder.getTenantId; |
| | | |
| | | /** |
| | | * 权限 Service 实现类 |
| | |
| | | private DeptService deptService; |
| | | @Resource |
| | | private AdminUserService userService; |
| | | @Resource |
| | | private TenantService tenantService; |
| | | @Resource |
| | | private TenantPackageService tenantPackageService; |
| | | @Resource |
| | | private AppService appService; |
| | | |
| | | |
| | | @Override |
| | | public boolean hasAnyPermissions(Long userId, String... permissions) { |
| | |
| | | } |
| | | } |
| | | |
| | | // ========== 角色-菜单的相关方法 ========== |
| | | |
| | | @Override |
| | | @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 |
| | | @CacheEvict(value = RedisKeyConstants.MENU_ROLE_ID_LIST, |
| | | allEntries = true) // allEntries 清空所有缓存,主要一次更新涉及到的 menuIds 较多,反倒批量会更快 |
| | | public void assignRoleAppMenu(Long roleId, Set<Long> menuIds) { |
| | | // 获得角色拥有应用菜单编号 |
| | | MenuListReqVO reqVO = new MenuListReqVO(); |
| | | List<MenuDO> appMenuList = menuService.getAppMenuList(reqVO); |
| | | Set<Long> appMenuIds = convertSet(appMenuList, MenuDO::getId); |
| | | Set<Long> dbMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleId), RoleMenuDO::getMenuId); |
| | | dbMenuIds.retainAll(appMenuIds); |
| | | // 计算新增和删除的菜单编号 |
| | | Set<Long> menuIdList = CollUtil.emptyIfNull(menuIds); |
| | | Collection<Long> createMenuIds = CollUtil.subtract(menuIdList, dbMenuIds); |
| | | Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIdList); |
| | | // 执行新增和删除。对于已经授权的菜单,不用做任何处理 |
| | | if (CollUtil.isNotEmpty(createMenuIds)) { |
| | | roleMenuMapper.insertBatch(CollectionUtils.convertList(createMenuIds, menuId -> { |
| | | RoleMenuDO entity = new RoleMenuDO(); |
| | | entity.setRoleId(roleId); |
| | | entity.setMenuId(menuId); |
| | | return entity; |
| | | })); |
| | | } |
| | | if (CollUtil.isNotEmpty(deleteMenuIds)) { |
| | | roleMenuMapper.deleteListByRoleIdAndMenuIds(roleId, deleteMenuIds); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Caching(evict = { |
| | |
| | | if (CollUtil.isEmpty(roleIds)) { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | // 如果是管理员的情况下,获取全部菜单编号 |
| | | if (roleService.hasAnySuperAdmin(roleIds)) { |
| | | return convertSet(menuService.getMenuList(), MenuDO::getId); |
| | | } |
| | | // 如果是非管理员的情况下,获得拥有的菜单编号 |
| | | return convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId); |
| | | } |
| | | |
| | | @Override |
| | | public Set<Long> getRoleAppMenuListByRoleId(Collection<Long> roleIds) { |
| | | if (CollUtil.isEmpty(roleIds)) { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | // 如果是管理员的情况下,获取全部应用菜单编号 |
| | | if (roleService.hasAnySuperAdmin(roleIds)) { |
| | | MenuListReqVO reqVO = new MenuListReqVO(); |
| | | return convertSet(menuService.getAppMenuList(reqVO), MenuDO::getId); |
| | | } |
| | | // 如果是非管理员的情况下,获得拥有的应用菜单编号 |
| | | // 获取 tenantId |
| | | Long tenantId = getTenantId(); |
| | | TenantDO tenant = tenantService.getTenant(tenantId); |
| | | TenantPackageDO tenantPackage = tenantPackageService.getTenantPackage(tenant.getPackageId()); |
| | | Set<Long> menuIds = tenantPackage.getMenuIds(); |
| | | Set<Long> longs = convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId); |
| | | longs.retainAll(menuIds); |
| | | return longs; |
| | | } |
| | | |
| | | @Override |
| | | @Cacheable(value = RedisKeyConstants.MENU_ROLE_ID_LIST, key = "#menuId") |
| | | public Set<Long> getMenuRoleIdListByMenuIdFromCache(Long menuId) { |
| | | return convertSet(roleMenuMapper.selectListByMenuId(menuId), RoleMenuDO::getRoleId); |
| | |
| | | RoleDO getRoleByName(String name); |
| | | |
| | | void insert(RoleDO role); |
| | | |
| | | RoleDO getTenantAdminRole(Long tenantId); |
| | | } |
| | |
| | | return SpringUtil.getBean(getClass()); |
| | | } |
| | | |
| | | /** |
| | | * 查询租户管理员 |
| | | */ |
| | | public RoleDO getTenantAdminRole(Long tenantId) { |
| | | RoleDO roleDO = roleMapper.selectOne(new LambdaQueryWrapperX<RoleDO>().eq(RoleDO::getType, 1L).eq(RoleDO::getTenantId, tenantId)); |
| | | return roleDO; |
| | | } |
| | | |
| | | } |
| | |
| | | PageResult<TenantDO> getTenantPage(TenantPageReqVO pageReqVO); |
| | | |
| | | /** |
| | | * 获得租户列表 |
| | | * |
| | | * @return 租户列表 |
| | | */ |
| | | List<TenantDO> getSimpleTenant(); |
| | | |
| | | /** |
| | | * 获得名字对应的租户 |
| | | * |
| | | * @param name 租户名 |
| | |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<TenantDO> getSimpleTenant() { |
| | | return tenantMapper.selectList(); |
| | | } |
| | | |
| | | @Override |
| | | public TenantDO getTenantByName(String name) { |
| | | return tenantMapper.selectByName(name); |
| | | } |
| | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.io.IoUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.dynamic.datasource.annotation.DSTransactional; |
| | | import com.iailab.framework.common.enums.CommonStatusEnum; |
| | | import com.iailab.framework.common.exception.ServiceException; |
| | | import com.iailab.framework.common.pojo.PageResult; |
| | |
| | | private ConfigApi configApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @DSTransactional |
| | | @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}", |
| | | success = SYSTEM_USER_CREATE_SUCCESS) |
| | | public Long createUser(UserSaveReqVO createReqVO) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @DSTransactional |
| | | @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", |
| | | success = SYSTEM_USER_UPDATE_SUCCESS) |
| | | public void updateUser(UserSaveReqVO updateReqVO) { |