diff --git a/core/core-backend/pom.xml b/core/core-backend/pom.xml
index 72a5f97b9e..d5cf204747 100644
--- a/core/core-backend/pom.xml
+++ b/core/core-backend/pom.xml
@@ -101,6 +101,21 @@
com.h2database
h2
+
+ io.dataease
+ xpack-base
+ ${dataease.version}
+
+
+ io.dataease
+ xpack-permissions
+ ${dataease.version}
+
+
+ io.dataease
+ xpack-sync
+ ${dataease.version}
+
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/bo/PerMonitorCheckBO.java b/core/core-backend/src/main/java/io/dataease/rmonitor/bo/PerMonitorCheckBO.java
new file mode 100644
index 0000000000..aab6e1ed4e
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/bo/PerMonitorCheckBO.java
@@ -0,0 +1,12 @@
+package io.dataease.rmonitor.bo;
+
+import lombok.Data;
+import java.io.Serializable;
+
+@Data
+public class PerMonitorCheckBO implements Serializable {
+
+ private boolean valid;
+
+ private boolean emptyPermission;
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/bo/PerMonitorNodeBO.java b/core/core-backend/src/main/java/io/dataease/rmonitor/bo/PerMonitorNodeBO.java
new file mode 100644
index 0000000000..ea2e91720c
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/bo/PerMonitorNodeBO.java
@@ -0,0 +1,24 @@
+package io.dataease.rmonitor.bo;
+
+import io.dataease.model.TreeBaseModel;
+import io.dataease.model.TreeResultModel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class PerMonitorNodeBO implements TreeBaseModel, TreeResultModel, Serializable {
+
+ private Long id;
+
+ private String name;
+
+ private Long pid;
+
+ private boolean leaf;
+
+ private int extraFlag;
+
+ private List children;
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/manage/ResourceMonitorManage.java b/core/core-backend/src/main/java/io/dataease/rmonitor/manage/ResourceMonitorManage.java
new file mode 100644
index 0000000000..920e90cd3b
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/manage/ResourceMonitorManage.java
@@ -0,0 +1,118 @@
+package io.dataease.rmonitor.manage;
+
+import io.dataease.exception.DEException;
+import io.dataease.rmonitor.bo.PerMonitorCheckBO;
+import io.dataease.rmonitor.bo.PerMonitorNodeBO;
+import io.dataease.rmonitor.mapper.ResourceMonitorMapper;
+import io.dataease.rmonitor.mapper.entity.DatasetFreeResource;
+import io.dataease.rmonitor.mapper.entity.DsFreeResource;
+import io.dataease.rmonitor.mapper.entity.VisualFreeResource;
+import io.dataease.utils.BeanUtils;
+import io.dataease.utils.TreeUtils;
+import jakarta.annotation.Resource;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Component("resourceMonitorManage")
+public class ResourceMonitorManage {
+
+
+ @Resource(name = "resourceMonitorSyncManage")
+ private ResourceMonitorSyncManage resourceMonitorSyncManage;
+
+ @Resource
+ private ResourceMonitorMapper resourceMonitorMapper;
+
+
+ private boolean existFreeResource() {
+ int rCount = resourceMonitorMapper.dsCount() + resourceMonitorMapper.datasetCount() + resourceMonitorMapper.vCount();
+ return rCount > 0;
+ }
+
+ private Map> freeResource() {
+ Map> result = new HashMap<>();
+
+ List dsFreeResources = resourceMonitorMapper.queryFreeDs();
+ if (CollectionUtils.isNotEmpty(dsFreeResources)) {
+ List dsBos = dsFreeResources.stream().map(node -> {
+ PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
+ bo.setLeaf(StringUtils.equals("folder", node.getType()));
+ return bo;
+ }).collect(Collectors.toList());
+ List dsTree = TreeUtils.mergeTree(dsBos, PerMonitorNodeBO.class, false);
+ result.put("datasource", dsTree);
+ }
+
+ List datasetFreeResources = resourceMonitorMapper.queryFreeDataset();
+ if (CollectionUtils.isNotEmpty(datasetFreeResources)) {
+ List datasetBos = datasetFreeResources.stream().map(node -> {
+ PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
+ bo.setLeaf(StringUtils.equals("folder", node.getNodeType()));
+ return bo;
+ }).collect(Collectors.toList());
+ List datasetTree = TreeUtils.mergeTree(datasetBos, PerMonitorNodeBO.class, false);
+ result.put("dataset", datasetTree);
+ }
+
+ List visualFreeResources = resourceMonitorMapper.queryFreeVusial();
+ if (CollectionUtils.isNotEmpty(visualFreeResources)) {
+ Map> baseMap = visualFreeResources.stream().collect(Collectors.groupingBy(VisualFreeResource::getType));
+ for (Map.Entry> entry : baseMap.entrySet()) {
+ List freeResource = entry.getValue();
+ List visualBos = freeResource.stream().map(node -> {
+ PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
+ bo.setLeaf(StringUtils.equals("folder", node.getNodeType()));
+ return bo;
+ }).collect(Collectors.toList());
+ result.put(convertBusiFlag(entry.getKey()), TreeUtils.mergeTree(visualBos, PerMonitorNodeBO.class, false));
+ }
+ }
+ return result;
+ }
+
+ private String convertBusiFlag(String key) {
+ if (StringUtils.equals("dashboard", key)){
+ return "panel";
+ } else if (StringUtils.equals("dataV", key)) {
+ return "screen";
+ } else return key;
+ }
+
+ public boolean check() {
+ PerMonitorCheckBO checkBO = resourceMonitorSyncManage.checkXpackResource();
+ return checkBO.isValid() && checkBO.isEmptyPermission() && existFreeResource();
+ }
+
+ @Transactional
+ public void delete() {
+ boolean existFree = existFreeResource();
+ if (!existFree) DEException.throwException("无未同步资源!");
+ resourceMonitorMapper.delFreeDs();
+ resourceMonitorMapper.delFreeDataset();
+ resourceMonitorMapper.delFreeVisual();
+ }
+
+ public void sync() {
+ //1、从xpack获取资源 如果xpack不存在 或者资源不为空 则直接返回 并且抛出异常“仅支持首次导入lic同步”
+ //2、从core获取资源
+ //3、根据类型分组 并组织成树形结构
+ //4、分别遍历每一棵树 从上到下 同步到权限体系 给默认组织
+ PerMonitorCheckBO checkBO = resourceMonitorSyncManage.checkXpackResource();
+ if (!checkBO.isValid()) DEException.throwException("缺少许可证");
+ if (!checkBO.isEmptyPermission()) DEException.throwException("仅支持license首次导入同步");
+ Map> freeResourceMap = freeResource();
+ if (MapUtils.isEmpty(freeResourceMap)) DEException.throwException("无未同步资源!");
+ for (Map.Entry> entry : freeResourceMap.entrySet()) {
+ resourceMonitorSyncManage.sync(entry.getKey(), entry.getValue());
+ }
+ }
+
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/manage/ResourceMonitorSyncManage.java b/core/core-backend/src/main/java/io/dataease/rmonitor/manage/ResourceMonitorSyncManage.java
new file mode 100644
index 0000000000..dc875acded
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/manage/ResourceMonitorSyncManage.java
@@ -0,0 +1,28 @@
+package io.dataease.rmonitor.manage;
+
+import io.dataease.exception.DEException;
+import io.dataease.license.config.XpackInteract;
+import io.dataease.rmonitor.bo.PerMonitorCheckBO;
+import io.dataease.rmonitor.bo.PerMonitorNodeBO;
+import io.dataease.rmonitor.mapper.ResourceMonitorMapper;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component("resourceMonitorSyncManage")
+public class ResourceMonitorSyncManage {
+
+ @Resource(name = "resourceMonitorMapper")
+ private ResourceMonitorMapper resourceMonitorMapper;
+
+ @XpackInteract(value = "resourceMonitorSyncManage", replace = true)
+ public void sync(String flag, List treeNodes) {
+ DEException.throwException("缺失许可证");
+ }
+
+ @XpackInteract(value = "resourceMonitorSyncManage", replace = true)
+ public PerMonitorCheckBO checkXpackResource() {
+ return new PerMonitorCheckBO();
+ }
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/ResourceMonitorMapper.java b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/ResourceMonitorMapper.java
new file mode 100644
index 0000000000..0b2ae83575
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/ResourceMonitorMapper.java
@@ -0,0 +1,41 @@
+package io.dataease.rmonitor.mapper;
+
+import io.dataease.rmonitor.mapper.entity.DatasetFreeResource;
+import io.dataease.rmonitor.mapper.entity.DsFreeResource;
+import io.dataease.rmonitor.mapper.entity.VisualFreeResource;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+@Mapper
+public interface ResourceMonitorMapper {
+
+ @Select("select count(id) from core_datasource")
+ int dsCount();
+
+ @Select("select count(id) from core_dataset_group")
+ int datasetCount();
+
+ @Select("select count(id) from data_visualization_info")
+ int vCount();
+
+ @Select("select id, name, pid, type, status from core_datasource")
+ List queryFreeDs();
+
+ @Select("select id, name, pid, node_type from core_dataset_group")
+ List queryFreeDataset();
+
+ @Select("select id, name, pid, node_type, type from data_visualization_info")
+ List queryFreeVusial();
+
+ @Delete("delete from core_datasource")
+ void delFreeDs();
+
+ @Delete("delete from core_dataset_group")
+ void delFreeDataset();
+ @Delete("delete from data_visualization_info")
+ void delFreeVisual();
+
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/BaseFreeResource.java b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/BaseFreeResource.java
new file mode 100644
index 0000000000..390acb6e10
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/BaseFreeResource.java
@@ -0,0 +1,15 @@
+package io.dataease.rmonitor.mapper.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class BaseFreeResource implements Serializable {
+
+ private Long id;
+
+ private String name;
+
+ private Long pid;
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/DatasetFreeResource.java b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/DatasetFreeResource.java
new file mode 100644
index 0000000000..1d4f85c00a
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/DatasetFreeResource.java
@@ -0,0 +1,13 @@
+package io.dataease.rmonitor.mapper.entity;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DatasetFreeResource extends BaseFreeResource implements Serializable {
+
+ private String nodeType;
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/DsFreeResource.java b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/DsFreeResource.java
new file mode 100644
index 0000000000..a8dc0fd1a0
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/DsFreeResource.java
@@ -0,0 +1,16 @@
+package io.dataease.rmonitor.mapper.entity;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DsFreeResource extends BaseFreeResource implements Serializable {
+
+ private String type;
+
+ private String status;
+
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/VisualFreeResource.java b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/VisualFreeResource.java
new file mode 100644
index 0000000000..d3302b84c5
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/mapper/entity/VisualFreeResource.java
@@ -0,0 +1,15 @@
+package io.dataease.rmonitor.mapper.entity;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class VisualFreeResource extends BaseFreeResource implements Serializable {
+
+ private String nodeType;
+
+ private String type;
+}
diff --git a/core/core-backend/src/main/java/io/dataease/rmonitor/server/ResourceMonitorServer.java b/core/core-backend/src/main/java/io/dataease/rmonitor/server/ResourceMonitorServer.java
new file mode 100644
index 0000000000..1289ba3a79
--- /dev/null
+++ b/core/core-backend/src/main/java/io/dataease/rmonitor/server/ResourceMonitorServer.java
@@ -0,0 +1,30 @@
+package io.dataease.rmonitor.server;
+
+import io.dataease.api.rmonitor.ResourceMonitorApi;
+import io.dataease.rmonitor.manage.ResourceMonitorManage;
+import jakarta.annotation.Resource;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/rmonitor")
+public class ResourceMonitorServer implements ResourceMonitorApi {
+
+ @Resource(name = "resourceMonitorManage")
+ private ResourceMonitorManage resourceMonitorManage;
+
+ @Override
+ public boolean existFree() {
+ return resourceMonitorManage.check();
+ }
+
+ @Override
+ public void delete() {
+ resourceMonitorManage.delete();
+ }
+
+ @Override
+ public void sync() {
+ resourceMonitorManage.sync();
+ }
+}