技术标签: 开发随笔
介绍:给平台开发一个全局的系统目录树结构,可根据不同的目录属性自定义目录
@Service
@Slf4j
public class CatalogServiceImpl extends ServiceImpl<CatalogMapper, Catalog> implements CatalogService {
@Resource
private CatalogMapper catalogMapper;
private final int LEVEL = 4;
/**
* 功能描述 创建实时项目时自动创建系统根目录
* 如果有多个目录 根据需求将目录加到list
* @param * @param projectType
* @param * @param projectId
* @return
* @author ZhiWen
*/
@Override
@Transactional(rollbackFor = CustomException.class)
public void initRootCatalogByProject(String projectType, Long projectId) {
//新增系统目录
//用户的信息
User user = (User) SecurityUtils.getSubject().getPrincipal();
Long userId = user.getId();
try {
//list根据自己需求确定是否需要使用
ArrayList<Catalog> list = new ArrayList<>();
//离线项目
if (projectType.equals(CatalogEnum.BATCH.getMsg())) {
//新建 "离线数据同步目录"
Catalog b1 = new Catalog()
.setCatalogUrl(CatalogEnum.BATCH_SYNC.getMsg())
.setCatalogType(CatalogEnum.CONTENT.getMsg())
.setCatalogProperty(CatalogEnum.ROOT.getMsg())
.setFatherCatalogId(0L)
.setModuleType(CatalogEnum.BATCH_SYNC_MODULE.getMsg())
.setProjectId(projectId)
.setCreateBy(userId);
list.add(b1);
} else if (projectType.equals(CatalogEnum.STREAM.getMsg())) {
//新建 "实时数据同步目录"
Catalog s1 = new Catalog()
.setCatalogUrl(CatalogEnum.STREAM_SYNC.getMsg())
.setCatalogType(CatalogEnum.CONTENT.getMsg())
.setCatalogProperty(CatalogEnum.ROOT.getMsg())
.setFatherCatalogId(0L)
.setModuleType(CatalogEnum.STREAM_SYNC_MODULE.getMsg())
.setProjectId(projectId)
.setCreateBy(userId);
list.add(s1);
}
//批量保存
saveBatch(list);
} catch (Exception e) {
log.error("创建项目新增系统根目录失败" + e);
throw new CustomException(CatalogEnum.CATALOG_ERROR_08.getCode(), CatalogEnum.CATALOG_ERROR_08.getMsg());
}
}
/**
* 功能描述 新建文件夹
*
* @param folderDTO
* @return
* @author ZhiWen
*/
@Override
public void addFolder(CatalogAddFolderDTO folderDTO) {
if (!folderDTO.getAddOrUpdate()) {
throw new CustomException(-1, "入参异常");
}
checkName(folderDTO);
Catalog fc = catalogMapper.selectById(folderDTO.getCatalogId());
if (fc == null) {
throw new CustomException(CatalogEnum.CATALOG_ERROR_01.getCode(), CatalogEnum.CATALOG_ERROR_01.getMsg());
}
String fcCatalogUrl = fc.getCatalogUrl();
String[] urlArr = fcCatalogUrl.split("/");
if (LEVEL == urlArr.length) {
throw new CustomException(CatalogEnum.CATALOG_ERROR_02.getCode(), CatalogEnum.CATALOG_ERROR_02.getMsg());
}
boolean isFile = CatalogEnum.FILE.getMsg().equals(fc.getCatalogType());
if (isFile) {
log.error("该目录不支持创建文件夹");
throw new CustomException(CatalogEnum.CATALOG_ERROR_03.getCode(), CatalogEnum.CATALOG_ERROR_03.getMsg());
}
User user = (User) SecurityUtils.getSubject().getPrincipal();
Catalog catalog = new Catalog()
.setCatalogUrl(fcCatalogUrl + "/" + folderDTO.getName())
.setCatalogType(CatalogEnum.CONTENT.getMsg())
.setCatalogProperty(CatalogEnum.FOLDER.getMsg())
.setModuleType(fc.getModuleType())
.setFatherCatalogId(fc.getId())
.setProjectId(fc.getProjectId())
.setCreateBy(user.getId());
try {
catalogMapper.insert(catalog);
} catch (Exception e) {
log.error("新增文件夹失败" + e);
throw new CustomException(CatalogEnum.CATALOG_ERROR_05.getCode(), CatalogEnum.CATALOG_ERROR_05.getMsg());
}
}
/**
* 功能描述 名称重名校验
*
* @param folderDTO
* @return
* @author ZhiWen
*/
@Override
public void checkName(CatalogAddFolderDTO folderDTO) {
Catalog fc = catalogMapper.selectById(folderDTO.getCatalogId());
if (fc == null) {
throw new CustomException(CatalogEnum.CATALOG_ERROR_01.getCode(), CatalogEnum.CATALOG_ERROR_01.getMsg());
}
String newName;
if (folderDTO.getAddOrUpdate()) {
newName = fc.getCatalogUrl() + "/" + folderDTO.getName();
} else {
//获取全路径名
String allUrl = fc.getCatalogUrl();
//作切割 最后一级名用新名代替
newName = allUrl.substring(0, allUrl.lastIndexOf("/") + 1) + folderDTO.getName();
}
QueryWrapper<Catalog> wrapper = new QueryWrapper<>();
wrapper.eq("catalog_url", newName)
.eq("module_type", fc.getModuleType())
.ne("id", fc.getId());
if (fc.getProjectId() != null) {
wrapper.eq("project_id", fc.getProjectId());
}
Integer count = catalogMapper.selectCount(wrapper);
if (count > 0) {
throw new CustomException(CatalogEnum.CATALOG_ERROR_04.getCode(), CatalogEnum.CATALOG_ERROR_04.getMsg());
}
}
@Override
public List<CatalogTreeDTO> listCatalogTree(CatalogByModuleDTO moduleDTO) {
//TODO 先确定目录展示跟项目是否有关
String moduleType = moduleDTO.getModuleType();
Long projectId = moduleDTO.getProjectId();
//目前数据服务开发不跟项目挂钩
boolean isDataService = moduleType.equals(CatalogEnum.DATA_SERVICE_DEV_MODULE.getMsg());
if (!isDataService) {
if (projectId == null) {
throw new CustomException(-1, "入参异常");
}
}
// 查询指定模块下的所有目录
QueryWrapper<Catalog> wrapper = new QueryWrapper<>();
wrapper.eq("module_type", moduleType);
if (projectId != null) {
wrapper.eq("project_id", projectId);
}
List<Catalog> catalogList = catalogMapper.selectList(wrapper);
if (CollectionUtils.isEmpty(catalogList)) {
throw new CustomException(CatalogEnum.CATALOG_ERROR_06.getCode(), CatalogEnum.CATALOG_ERROR_06.getMsg());
}
//转换成树结构
List<CatalogTreeDTO> catalogTreeList = BeanUtil.copyListProperties(catalogList, CatalogTreeDTO.class);
try {
//添加作业信息
log.info("添加作业信息>>>>>>>>>>>>>>>>");
//获取目录树
log.info("开始获取目录树结构>>>>>>>>>>>");
List<CatalogTreeDTO> catalogTree = listToTree(catalogTreeList);
//将目录树的数据结构化成前端展示数据
for (CatalogTreeDTO treeDTO : catalogTree) {
dataStructure(treeDTO);
}
return catalogTree;
} catch (Exception e) {
log.error("获取目录树失败" + e);
throw new CustomException(CatalogEnum.CATALOG_ERROR_07.getCode(), CatalogEnum.CATALOG_ERROR_07.getMsg());
}
}
/**
*功能描述 删除当前目录及所有子目录
* @author ZhiWen
* @param * @param id
* @return
*/
@Override
public void deleteCatalog(Long id){
Catalog fc = catalogMapper.selectById(id);
if (fc == null){
throw new CustomException(CatalogEnum.CATALOG_ERROR_01.getCode(),CatalogEnum.CATALOG_ERROR_01.getMsg());
}
//这里考虑根目录不可以删除
boolean isRoot = CatalogEnum.ROOT.getMsg().equals(fc.getCatalogProperty());
if (isRoot){
throw new CustomException(CatalogEnum.CATALOG_ERROR_09.getCode(),CatalogEnum.CATALOG_ERROR_09.getMsg());
}
boolean isFile = CatalogEnum.FILE.getMsg().equals(fc.getCatalogType());
//删除单个目录和层级目录
if (isFile){
catalogMapper.deleteById(id);
}else {
QueryWrapper<Catalog> wrapper = new QueryWrapper<>();
wrapper.eq("module_type",fc.getModuleType())
.likeRight("catalog_url",fc.getCatalogUrl());
if (fc.getProjectId()!=null){
wrapper.eq("project_id",fc.getProjectId());
}
catalogMapper.delete(wrapper);
}
}
/**
*功能描述 获取当前文件下所有的子目录
* @author ZhiWen
* @param * @param id
* @return
*/
@Override
public List<Catalog> selectSubcatalogList(Long id){
Catalog fc = catalogMapper.selectById(id);
if (fc == null){
throw new CustomException(CatalogEnum.CATALOG_ERROR_01.getCode(),CatalogEnum.CATALOG_ERROR_01.getMsg());
}
QueryWrapper<Catalog> wrapper = new QueryWrapper<>();
wrapper.eq("module_type",fc.getModuleType())
.likeRight("catalog_url",fc.getCatalogUrl());
if (fc.getProjectId()!=null){
wrapper.eq("project_id",fc.getProjectId());
}
return catalogMapper.selectList(wrapper);
}
/**
*功能描述 获取当前文件夹下所有的 moduleId(对应的任务id)
* @author ZhiWen
* @param * @param id
* @return
*/
@Override
public List<Long> getModuleIdList(Long id){
List<Catalog> catalogList = selectSubcatalogList(id);
return catalogList.stream().map(Catalog::getModuleId).filter(moduleId -> moduleId != null)
.collect(Collectors.toList());
}
/**
*功能描述 目录重命名
* @author ZhiWen
* @param * @param folderDTO
* @return
*/
@Override
public void updateCatalog(CatalogAddFolderDTO folderDTO){
//名称校验
if (folderDTO.getAddOrUpdate()){
throw new CustomException(-1,"入参异常");
}
checkName(folderDTO);
Catalog fc = catalogMapper.selectById(folderDTO.getCatalogId());
if (fc == null){
throw new CustomException(CatalogEnum.CATALOG_ERROR_01.getCode(),CatalogEnum.CATALOG_ERROR_01.getMsg());
}
//根据目录类型更改
User user = (User) SecurityUtils.getSubject().getPrincipal();
if (CatalogEnum.FILE.getMsg().equals(fc.getCatalogType())){
//获取全路径名
String allUrl = fc.getCatalogUrl();
//作切割 最后一级名用新名代替
String newCatalogUrl = allUrl.substring(0, allUrl.lastIndexOf("/") + 1) + folderDTO.getName();
fc.setCatalogUrl(newCatalogUrl);
fc.setUpdateBy(user.getId());
catalogMapper.updateById(fc);
}else {
//获取修改前全路径名
String oldUrl = fc.getCatalogUrl();
int length = oldUrl.split("/").length;
//查出所有需要修改的子目录集
List<Catalog> catalogList = selectSubcatalogList(folderDTO.getCatalogId());
//遍历操作每个子目录
for (Catalog catalog : catalogList) {
//每级目录的全路径名称
String allUrl = catalog.getCatalogUrl();
//子目录切割
String[] split = allUrl.split("/");
//对应目录名替换
split[length - 1] = folderDTO.getName();
String catalogUrl = String.join("/", split);
catalog.setCatalogUrl(catalogUrl);
catalog.setUpdateBy(user.getId());
}
updateBatchById(catalogList);
}
}
/*-------------------------------------------私有方法------------------------------------------*/
/**
* 功能描述 目录列表生成目录树
*
* @param * @param list
* @return
* @author ZhiWen
*/
private List<CatalogTreeDTO> listToTree(List<CatalogTreeDTO> list) {
//最好如果有多个根目录再启用
List<CatalogTreeDTO> treeList = new ArrayList<CatalogTreeDTO>();
for (CatalogTreeDTO tree : list) {
//首先判断找根目录,根目录长度
if (tree.getCatalogUrl().split("/").length == 2) {
//去找该根目录下的所有子目录,并把此根目录及其子目录添加到结果集
treeList.add(findChildren(tree, list));
//如果根目录只有一个 启用
//break;
}
}
return treeList;
}
/**
* 功能描述 找该树目录下的所有子目录
*
* @param * @param tree
* @param list
* @return
* @author ZhiWen
*/
private CatalogTreeDTO findChildren(CatalogTreeDTO tree, List<CatalogTreeDTO> list) {
for (CatalogTreeDTO node : list) {
//目录的全路径名称
String urlAll = node.getCatalogUrl();
//最后一级目录的父目录的全路径名称
String url = urlAll.substring(0, node.getCatalogUrl().lastIndexOf("/"));
//判断是否是传入目录的子目录
if (url.equals(tree.getCatalogUrl())) {
//初始空间
if (tree.getChildCatalogTree() == null) {
tree.setChildCatalogTree(new ArrayList<CatalogTreeDTO>());
}
//添加子目录,并继续找子目录的子目录
tree.getChildCatalogTree().add(findChildren(node, list));
}
}
return tree;
}
/**
* 功能描述 数据结构化 转换成前端展示数据格式
*
* @param * @param treeNode
* @return
* @author ZhiWen
*/
private void dataStructure(CatalogTreeDTO treeNode) {
//全路径
String allUrl = treeNode.getCatalogUrl();
//最后一级目录的名称
String substring = allUrl.substring(allUrl.lastIndexOf("/") + 1);
//转换数据 去掉了/ 及其父目录
treeNode.setCatalogUrl(substring);
List<CatalogTreeDTO> childTree = treeNode.getChildCatalogTree();
//子目录的数据格式化
if (childTree != null) {
for (CatalogTreeDTO node : childTree) {
dataStructure(node);
}
}
}
}
/**
* @description 目录相关枚举
* @author: ZhiWen
* @create: 2020-04-14 14:39
**/
@Getter
public enum CatalogEnum {
/**项目类型*/
/**
* 离线
*/
BATCH("batch"),
/**
* 实时
*/
STREAM("stream"),
/**默认根目录*/
/**
* 离线同步
*/
BATCH_SYNC("/离线数据同步目录"),
/**
* 实时同步
*/
STREAM_SYNC("/实时数据同步目录"),
/**catalogType*/
/**
* 目录
*/
CONTENT("content"),
/**
* 文件
*/
FILE("file"),
/**请自定义module*/
/**
* 数据服务开发模块
*/
DATA_SERVICE_DEV_MODULE("development"),
/**
* 离线同步模块
*/
BATCH_SYNC_MODULE("batchSync"),
/**
* 实时同步模块
*/
STREAM_SYNC_MODULE("streamSync"),
/**请自定义 catalog_property*/
/**
* 根目录
*/
ROOT("root"),
/**
* 普通文件夹
*/
FOLDER("folder"),
/**
* API
*/
API("api"),
/**
* 任务类JOB
*/
JOB("job"),
SYNC_FOLDER("syncFolder"),
/**目录表错误信息*/
CATALOG_ERROR_01(6301,"目录不存在"),
CATALOG_ERROR_02(6302,"目录不可以超过三层"),
CATALOG_ERROR_03(6303,"不支持创建目录"),
CATALOG_ERROR_04(6304,"名称不可以重复"),
CATALOG_ERROR_05(6305,"新建目录失败"),
CATALOG_ERROR_06(6306,"查询目录列表为空"),
CATALOG_ERROR_07(6307,"获取目录树失败"),
CATALOG_ERROR_08(6308,"创建项目新增根目录失败"),
CATALOG_ERROR_09(6309,"根目录不可以删除"),
;
private Integer code;
private String msg;
CatalogEnum() {
}
CatalogEnum(String msg) {
this.msg = msg;
}
CatalogEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
CREATE TABLE `sys_catalog` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` int(10) DEFAULT '1' COMMENT '乐观锁版本',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段(0:未删除,1:已删除)',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建人',
`update_by` bigint(20) DEFAULT NULL COMMENT '修改人',
`catalog_url` varchar(255) DEFAULT NULL COMMENT '目录的全路径',
`module_type` varchar(32) DEFAULT NULL COMMENT '模块类型,(服务开发:development,...)',
`catalog_type` varchar(32) NOT NULL COMMENT '目录类型,(目录型:content,文件型:file)',
`catalog_property` varchar(32) NOT NULL COMMENT '目录属性,(根目录:root,文件夹:folder,API:api,...)',
`module_id` bigint(20) DEFAULT NULL COMMENT '该节点指向的关联表的主键id',
`father_catalog_id` bigint(20) NOT NULL COMMENT '父目录id,根目录为0',
`project_id` bigint(20) DEFAULT NULL COMMENT '所属项目id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=455 DEFAULT CHARSET=utf8 COMMENT='系统目录表';
文章浏览阅读3.9k次,点赞42次,收藏32次。共同学习,加入粉丝群哈喽大家好,我是iecne,本期为大家带来的是CPP/C++【游戏引擎Easy2D】炫酷动画来这学,动画入门之位移动画,构造函数让节点执行动画。包教包会,快来看看吧!引擎支持 Visual Studio 2013 及以上版本,如果你使用的是较低版本的 VS,那么你需要考虑一下更新你的编译器了什么是动画直接修改节点的属性会立即生效,体现不出时间的概念,也没有渐变的效果。想让一个精灵执行一段连贯的动画,需要用到 Action 动画类。动画分为普通动画和组合动画。_easy2d 人物移动
文章浏览阅读1.7k次。我是在安装使用Date Picker这个插件时报的这个错Error: EPERM: operation not permitted, rename 'C:\Users\tad\.config\configstore\cordova-config.json.670455402' -> 'C:\Users\tad\.config\configstore\cordova-config.jso..._用fs eperm: operation not permitted, rename
文章浏览阅读1.5k次,点赞4次,收藏16次。一、网站1、http://msdn.microsoft.com/zh-CN/微软的官方网站,C#程序员必去的地方。那里有API开发文档,还有各种代码、资源下载。2、http://social.msdn.microsoft.com/Forums/zh-CN/home微软msdn论坛。定位于微软技术的传播和技术问题的解决,是学习微软技术的好去处。3、https://referenc..._c#学习网站
文章浏览阅读2.2k次。前言本篇博客所写的算法对应于吴恩达教授的机器学习教程里的多元伯努利事件模型的朴素贝叶斯。多元伯努利事件模型的Python代码#!/usr/bin/env python# -*- coding: utf-8 -*-# @Time : 2018/9/415:55# @Author : DaiPuWei# E-Mail : [email protected]#..._python手写实现伯努利贝叶斯分类器
文章浏览阅读3.2w次,点赞18次,收藏219次。ipmitool命令ipmitool –I [open|lan|lanplus] commandOpenIPMI接口,command有以下项: raw:发送一个原始的IPMI请求,并且打印回复信息。 Lan:配置网络(lan)信道(channel) chassis :查看底盘的状态和设置电源 event:向BMC发送一个已经定义的事件(event),可用于测试配置的SNMP是否成功 mc:查看MC(..._ipmitool命令详解
文章浏览阅读9.6k次,点赞9次,收藏39次。功能需求:遍历数组,并求出数组中元素的最大元素,最小元素,及其相应的索引等问题,要求用方法完成. 思路:分别创建不同的方法,然后再调用方法.代码展示:public class Array{ public static void main(String[] args){ int[] arr={13,45,7,3,9,468,4589,76,4}; //声明数组并赋值..._java、 编写两个方法,分别求出数组中最大和最小元素的下标。如果这样的元素个数大
文章浏览阅读956次,点赞2次,收藏11次。FICO模块: FB01创建会计凭证:BAPI_ACC_DOCUMENT_POST 检查会计凭证:BAPI_ACC_DOCUMENT_CHECK FB02修改会计凭证:FI_ITEMS_MASS_CHANGE FB08冲销会计凭证:BAPI_ACC_DOCUMENT_REV_POST FS00创建总账科目:GL_ACCT_MASTER_SAVE AS01创建固定资产:BAPI_FIXEDASSET_CREATE1 AS02更改固定资产转移:BAPI_FIXEDASSET_CHANGE._sap me01 me04货源清单 bapi
文章浏览阅读220次。在`JSONHandler`中,我们定义了几个核心组件:- **JSON Parser (JSON 解析器)**:负责读取和解析JSON数据。- **JSON Writer (JSON 写入器)**:负责将JSON数据写入文件或其他输出流。- **JSON Manipulator (JSON 操作器)**:提供了一系列方法来修改、查询和操作JSON数据。这三个组件是`JSONHandler`的基石,它们确保了数据的正确读取、写入和操作。
文章浏览阅读543次。Algorithm Gossip: 阿姆斯壮数_actan算法 c++
文章浏览阅读429次。本篇文章的主要主要讲述的是对PHP导出的海量数据进行优化,具有一定的参考价值,有需要的朋友可以看看。导出数据量很大的情况下,生成excel的内存需求非常庞大,服务器吃不消,这个时候考虑生成csv来解决问题,cvs读写性能比excel高。测试表student 数据(大家可以脚本插入300多万测数据。这里只给个简单的示例了)SET NAMES utf8mb4;SET FOREIGN_KEY_CHECK..._php大数据优化
文章浏览阅读905次。有道云笔记如何保存网页 有道笔记保存页面教程网页剪报功能支持哪些浏览器?IE,360安全,Firefox,Chrome,搜狗,遨游等主流浏览器。不能收藏网页,原因是没有安装浏览器剪报插件:②点击如下图部门网页剪报”立即体验“。③在弹出”有道云笔记网页剪报“网页对话框,点击如下图”添加到浏览器“。④然后在弹出”确认新增扩展程序“网页对话框中,点击”添加“即可。⑤现在,在浏览器右上角多了一个标记,只需..._有道云笔记装扩展
文章浏览阅读63次。转自:http://www.jeasyui.net/tutorial/23.html本实例演示如何取得选中行数据。数据网格(datagrid)组件包含两种方法来检索选中行数据:getSelected:取得第一个选中行数据,如果没有选中行,则返回 null,否则返回记录。getSelections:取得所有选中行数据,返回元素记录的数组数据。创建数据网格(DataGrid)<..._easyui 获取table选中的一行的值