Browse Source

admin: init

yaoll 4 years ago
parent
commit
51cfeda7ac
47 changed files with 3297 additions and 0 deletions
  1. 127 0
      dmp-admin/pom.xml
  2. 68 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/AdminApp.java
  3. 46 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/DmpMessageAspect.java
  4. 126 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/DmpAccessControlFilter.java
  5. 24 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/DmpAuthorizationFilter.java
  6. 75 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/DmpRealm.java
  7. 82 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/ShiroConfig.java
  8. 12 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/ShiroContants.java
  9. 26 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/ShiroExceptionHandler.java
  10. 21 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/UserModel.java
  11. 42 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/web/UserUtils.java
  12. 54 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/config/web/WebConfig.java
  13. 39 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/controller/AdminController.java
  14. 39 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/controller/AdminRoleController.java
  15. 39 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/controller/AdminUserController.java
  16. 71 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/controller/DmpGatewayController.java
  17. 30 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/controller/DmpTransController.java
  18. 74 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/controller/TransObjectInfoController.java
  19. 30 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminPermission.java
  20. 41 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminRole.java
  21. 47 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminUser.java
  22. 32 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminUserProject.java
  23. 33 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/entity/TransObjectInfo.java
  24. 58 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/jms/JmsConfig.java
  25. 14 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/jms/MessageExecutor.java
  26. 64 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/jms/MessageProcesser.java
  27. 87 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/jms/executor/TransObjectExecutor.java
  28. 13 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/model/DownloadModel.java
  29. 27 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminPermissionRepository.java
  30. 9 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminRoleRepository.java
  31. 9 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminUserProjectRepository.java
  32. 9 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminUserRepository.java
  33. 16 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/repository/TransObjectInfoRepository.java
  34. 152 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/AdminRoleService.java
  35. 129 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/AdminService.java
  36. 143 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/AdminUserService.java
  37. 247 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/DmpTransObjectService.java
  38. 85 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/TransObjectInfoService.java
  39. 336 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/GraphMapping.java
  40. 395 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/RwdTransUtils.java
  41. 42 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/TransObjectContext.java
  42. 74 0
      dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/TransUtils.java
  43. 40 0
      dmp-admin/src/main/resources/application.yml
  44. 55 0
      dmp-admin/src/main/resources/logback-spring.xml
  45. 77 0
      dmp-admin/src/test/java/com/persagy/dmp/admin/service/TestGraph.java
  46. 37 0
      dmp-admin/src/test/java/com/persagy/dmp/admin/service/trans/TransObjectInfoServiceTest.java
  47. 1 0
      pom.xml

+ 127 - 0
dmp-admin/pom.xml

@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dmp</artifactId>
+        <groupId>com.persagy</groupId>
+        <version>4.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.persagy</groupId>
+    <artifactId>dmp-admin</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.persagy</groupId>
+            <artifactId>dmp-common</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.persagy</groupId>
+            <artifactId>dmp-model</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.persagy</groupId>
+            <artifactId>dmp-rwd-funcid-parser</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-spring</artifactId>
+            <version>1.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.querydsl</groupId>
+            <artifactId>querydsl-apt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.querydsl</groupId>
+            <artifactId>querydsl-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+
+        <!-- rabbitmq -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>dmp-admin</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <fork>true</fork>
+                    <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <!--
+            -->
+            <plugin>
+                <groupId>com.mysema.maven</groupId>
+                <artifactId>apt-maven-plugin</artifactId>
+                <version>1.1.3</version>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>process</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>target/generated-sources</outputDirectory>
+                            <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 68 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/AdminApp.java

@@ -0,0 +1,68 @@
+package com.persagy.dmp.admin;
+
+import com.persagy.common.criteria.CriteriaUtils;
+import com.persagy.common.criteria.JpaUtils;
+import com.persagy.dmp.common.SpringUtils;
+import com.persagy.dmp.common.http.HttpUtils;
+import com.persagy.dmp.rwd.funcid.parse.parser.InfoCodeParserFactory;
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.mgt.SecurityManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+@Slf4j
+@SpringBootApplication
+public class AdminApp {
+
+	public static void main(String[] args) {
+		SpringApplication app = new SpringApplication(AdminApp.class);
+		ConfigurableApplicationContext ctx = app.run(args);
+
+		SecurityManager securityManager = ctx.getBean(SecurityManager.class);
+		SecurityUtils.setSecurityManager(securityManager);
+
+	}
+
+	@Bean
+	public InfoCodeParserFactory infoCodeParserFactory() {
+		return new InfoCodeParserFactory();
+	}
+
+	@Bean
+	public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
+		return new JPAQueryFactory(entityManager);
+	}
+
+	@Bean
+	public CriteriaUtils criteriaUtils(@Autowired JPAQueryFactory jpaQueryFactory) {
+		return new CriteriaUtils(jpaQueryFactory);
+	}
+
+	@Bean
+	public JpaUtils jpaUtils(@Autowired EntityManager entityManager) {
+		return new JpaUtils(entityManager);
+	}
+
+	@Bean
+	public HttpUtils httpUtils() {
+		return new HttpUtils();
+	}
+
+	@Bean
+	public SpringUtils springUtils() {
+		return new SpringUtils();
+	}
+
+}

+ 46 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/DmpMessageAspect.java

@@ -0,0 +1,46 @@
+package com.persagy.dmp.admin.config;
+
+import com.persagy.common.web.BaseResponse;
+import com.persagy.dmp.admin.jms.MessageProcesser;
+import com.persagy.dmp.rwd.model.DmpMessage;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author: yaoll
+ * @date: 2020-10-22
+ * @verison: 1.0
+ */
+@Aspect
+@Component
+public class DmpMessageAspect {
+
+	@Autowired
+	private MessageProcesser messageProcesser;
+
+	@Pointcut("execution(public * com.persagy.dmp.*.controller.*.*(..))")
+	public void controllerPoint() {
+	}
+
+	@AfterReturning(returning = "ret", pointcut = "controllerPoint()")
+	public void doAfterReturning(Object ret) {
+		if (ret != null) {
+			if (ret instanceof BaseResponse) {
+				BaseResponse resp = (BaseResponse) ret;
+				if (resp.success()) {
+					List<DmpMessage> messageList = resp.getMessageList();
+					if (messageList != null && messageList.size() > 0) {
+						for (DmpMessage message : messageList) {
+							messageProcesser.convertAndSend(message);
+						}
+					}
+				}
+			}
+		}
+	}
+}

+ 126 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/DmpAccessControlFilter.java

@@ -0,0 +1,126 @@
+package com.persagy.dmp.admin.config.shiro;
+
+import com.persagy.common.web.ServletUtils;
+import com.persagy.dmp.admin.entity.AdminUser;
+import com.persagy.dmp.admin.entity.QAdminUser;
+import com.persagy.dmp.admin.repository.AdminUserRepository;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.AccessControlFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Optional;
+
+@Component("authc")
+public class DmpAccessControlFilter extends AccessControlFilter {
+
+	public final Logger logger = LoggerFactory.getLogger(DmpAccessControlFilter.class);
+
+	private final static String HEADER_TOKEN = "dmp-token";
+
+	@Autowired
+	private StringRedisTemplate redis;
+
+	@Autowired
+	private AdminUserRepository userRepository;
+
+	//判断是否拦截,false为拦截,true为允许继续访问
+	@Override
+	protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception {
+		HttpServletRequest request = (HttpServletRequest) req;
+		HttpServletResponse response = (HttpServletResponse) resp;
+		logger.info("===================================== isAccessAllowed");
+		String uri = request.getRequestURI();
+		logger.info("开始请求地址拦截 {}", uri);
+		ServletUtils.showHeaders(request);
+		ServletUtils.showCookies(request);
+
+		if (uri.equals(this.getLoginUrl())) {
+			// 登录地址,直接放行
+			return true;
+		}
+
+		String token = request.getHeader(HEADER_TOKEN);
+		if (token == null) {
+			ServletUtils.writeJson(response, "{\"result\":\"no_token\",\"message\":\"no token\"}");
+			return false;
+		}
+
+		// token不存在
+		String key = ShiroContants.KEY_TOKEN_USER + token;
+		if (!redis.hasKey(key)) {
+			ServletUtils.writeJson(response, "{\"result\":\"unauthc\",\"message\":\"token invalid\"}");
+			return false;
+		}
+
+		try {
+			Subject subject = SecurityUtils.getSubject();
+			if (subject.isAuthenticated()) {
+				Object principal = subject.getPrincipal();
+				if (principal instanceof UserModel) {
+					// 防止前端切换用户, 用token做密码
+					UserModel userModel = (UserModel) principal;
+					if (!userModel.getToken().equalsIgnoreCase(token)) {
+						return checkToken(subject, token, response);
+					}
+				} else {
+					return checkToken(subject, token, response);
+				}
+			} else {
+				return checkToken(subject, token, response);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			logger.error("login check error: {}", e);
+			return false;
+		}
+		return true;
+	}
+
+	private boolean checkToken(Subject subject, String token, HttpServletResponse response) {
+
+		String key = ShiroContants.KEY_TOKEN_USER + token;
+		String userIdStr = redis.opsForValue().get(key);
+		Integer userId = Integer.valueOf(userIdStr);
+
+
+		Optional<AdminUser> one = userRepository.findOne(QAdminUser.adminUser.id.eq(userId));
+		if (!one.isPresent()) {
+			// 用户不存在
+			ServletUtils.writeJson(response, "{\"result\": \"no_user\"}");
+			return false;
+		}
+		AdminUser user = one.get();
+		if (user.getStatus() != 1) {
+			// 用户被禁用
+			ServletUtils.writeJson(response, "{\"result\": \"invalid_user\"}");
+			return false;
+		} else {
+			// 更新用户名
+			String name = user.getRealname() == null ? user.getUsername() : user.getRealname();
+
+			// 用ssoId作为用户名
+			UsernamePasswordToken shiroToken = new UsernamePasswordToken(user.getUsername(), token);
+			subject.login(shiroToken);
+		}
+		return true;
+	}
+
+	//上面的方法返回false后(被拦截),会进入这个方法;这个方法返回false表示处理完毕(不放行);返回true表示需要继续处理(放行)
+	// 身份认证逻辑已在isAccessAllowed处理,这里直接返回false
+	@Override
+	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
+		HttpServletRequest req = (HttpServletRequest) request;
+		logger.info("===================================== onAccessDenied {}", req.getRequestURI());
+		return false;
+	}
+}

+ 24 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/DmpAuthorizationFilter.java

@@ -0,0 +1,24 @@
+package com.persagy.dmp.admin.config.shiro;
+
+import com.persagy.common.web.ServletUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Slf4j
+public class DmpAuthorizationFilter extends PermissionsAuthorizationFilter {
+
+	private static final String ERROR_RESULT = "{\"result\": \"fail\", \"message\": \"no authorization info\"}";
+
+	@Override
+	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
+		log.error("======================= shiro authorization error");
+		ServletUtils.writeJson((HttpServletResponse) response, ERROR_RESULT);
+		return false;
+	}
+
+}

+ 75 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/DmpRealm.java

@@ -0,0 +1,75 @@
+package com.persagy.dmp.admin.config.shiro;
+
+import com.persagy.common.json.JacksonMapper;
+import com.persagy.dmp.admin.entity.AdminUser;
+import com.persagy.dmp.admin.entity.QAdminUser;
+import com.persagy.dmp.admin.repository.AdminPermissionRepository;
+import com.persagy.dmp.admin.repository.AdminUserRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Optional;
+
+@Slf4j
+@Component
+public class DmpRealm extends AuthorizingRealm {
+
+	@Autowired
+	private AdminUserRepository userRepository;
+
+	@Autowired
+	private AdminPermissionRepository permissionRepository;
+
+	/**
+	 * 校验身份信息
+	 *
+	 * @param authenticationToken
+	 * @return
+	 * @throws AuthenticationException
+	 */
+	@Override
+	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
+		UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
+		String ssoToken = new String(token.getPassword());
+		log.info("身份认证 --> {} {}", token.getUsername(), ssoToken);
+		Optional<AdminUser> one = userRepository.findOne(QAdminUser.adminUser.username.eq(token.getUsername()));
+		if (!one.isPresent()) {
+			return null;
+		}
+		AdminUser user = one.get();
+
+		UserModel userModel = new UserModel();
+		userModel.setId(user.getId());
+		userModel.setUsername(user.getUsername());
+		userModel.setToken(ssoToken);
+		List<String> permissions = permissionRepository.queryForUser(user.getId());
+		userModel.setPermissions(permissions);
+		log.info("身份认证 --> {}", JacksonMapper.toFormatJson(userModel));
+		SimpleAuthenticationInfo result = new SimpleAuthenticationInfo(userModel, ssoToken, "dmpRealm");
+		return result;
+	}
+
+	/**
+	 * 校验权限
+	 *
+	 * @param principals
+	 * @return
+	 */
+	@Override
+	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+		UserModel userModel = (UserModel) principals.getPrimaryPrincipal();
+		log.info("权限配置--> {} {}", userModel.getUsername(), JacksonMapper.toSimpleJson(userModel.getPermissions()));
+		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
+		authorizationInfo.addStringPermissions(userModel.getPermissions());
+		return authorizationInfo;
+	}
+
+}
+

+ 82 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/ShiroConfig.java

@@ -0,0 +1,82 @@
+package com.persagy.dmp.admin.config.shiro;
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.servlet.Cookie;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+
+import javax.servlet.Filter;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+@Configuration
+public class ShiroConfig {
+
+    @Bean
+    public SessionManager sessionManager() {
+        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
+        Cookie sessionIdCookie = sessionManager.getSessionIdCookie();
+        sessionIdCookie.setName("dmp-admin");
+        sessionManager.setGlobalSessionTimeout(120 * 1000); // 超时时间
+        sessionManager.setDeleteInvalidSessions(true);
+        return sessionManager;
+    }
+
+    @Bean
+    public SecurityManager securityManager(@Autowired DmpRealm sagacloudRealm) {
+        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+        securityManager.setRealm(sagacloudRealm);
+        securityManager.setSessionManager(sessionManager());
+        return securityManager;
+    }
+
+    @Bean("shiroFilter")
+    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
+        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+        shiroFilterFactoryBean.setSecurityManager(securityManager);
+        //拦截器.
+        Map<String, Filter> filters = new LinkedHashMap<>();
+        filters.put("perms", new DmpAuthorizationFilter());
+        shiroFilterFactoryBean.setFilters(filters);
+
+        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
+        filterChainDefinitionMap.put("/admin/login", "anon");
+        filterChainDefinitionMap.put("/system/user/update", "authc,perms[system:user:update]");
+        filterChainDefinitionMap.put("/**", "authc");
+        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+
+        shiroFilterFactoryBean.setLoginUrl("/admin/login");
+        return shiroFilterFactoryBean;
+    }
+
+
+    @Bean
+    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
+        advisor.setSecurityManager(securityManager);
+        return advisor;
+    }
+
+    @Bean
+    @DependsOn("lifecycleBeanPostProcessor")
+    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
+        creator.setProxyTargetClass(true);
+        return creator;
+    }
+
+    @Bean
+    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+        return new LifecycleBeanPostProcessor();
+    }
+
+}

+ 12 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/ShiroContants.java

@@ -0,0 +1,12 @@
+package com.persagy.dmp.admin.config.shiro;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+public class ShiroContants {
+
+	public static final String KEY_USER_TOKEN = "system_user_token_"; // + userId
+	public static final String KEY_TOKEN_USER = "system_token_user_"; // + token
+}

+ 26 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/ShiroExceptionHandler.java

@@ -0,0 +1,26 @@
+package com.persagy.dmp.admin.config.shiro;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.authz.AuthorizationException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+@RestControllerAdvice
+public class ShiroExceptionHandler {
+
+	@ResponseBody
+	@ExceptionHandler(AuthorizationException.class)
+	public Map<String, Object> businessInterfaceException(AuthorizationException e) {
+		log.error("exception handler : {} {}", e.getClass().getName(), e.getMessage());
+		Map<String, Object> result = new HashMap<>();
+		result.put("result", "unauthorization");
+		result.put("message", "无权操作");
+		return result;
+	}
+
+}

+ 21 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/shiro/UserModel.java

@@ -0,0 +1,21 @@
+package com.persagy.dmp.admin.config.shiro;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+@Data
+public class UserModel {
+
+	private Integer id;
+	private String token;
+	private String username;
+	private String password;
+	private List<String> permissions;
+
+}

+ 42 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/web/UserUtils.java

@@ -0,0 +1,42 @@
+package com.persagy.dmp.admin.config.web;
+
+import com.persagy.dmp.admin.config.shiro.UserModel;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class UserUtils extends HandlerInterceptorAdapter {
+
+    private static final ThreadLocal<Integer> THREAD_LOCAL_USER = new ThreadLocal<Integer>();
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        Subject currentUser = SecurityUtils.getSubject();
+        if (currentUser.isAuthenticated()) {
+            UserModel userModel = (UserModel) currentUser.getPrincipal();
+            THREAD_LOCAL_USER.set(userModel.getId());
+        }
+        return true;
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        clear();
+    }
+
+    public static Integer currentUserId() {
+        return THREAD_LOCAL_USER.get();
+    }
+
+    public static final void clear() {
+        THREAD_LOCAL_USER.remove();
+    }
+
+}

+ 54 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/config/web/WebConfig.java

@@ -0,0 +1,54 @@
+package com.persagy.dmp.admin.config.web;
+
+import com.persagy.common.json.JacksonMapper;
+import com.persagy.dmp.admin.config.shiro.DmpAccessControlFilter;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+	@Autowired
+	private UserUtils userUtils;
+
+	/**
+	 * 登录拦截器
+	 */
+	@Override
+	public void addInterceptors(InterceptorRegistry registry) { // 设置拦截的路径、不拦截的路径、优先级等等
+		registry.addInterceptor(userUtils).addPathPatterns("/**");
+	}
+
+	@Bean
+	public HttpMessageConverters customConverters() {
+		MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+		converter.setObjectMapper(JacksonMapper.nonEmptyMapper);
+		return new HttpMessageConverters(converter);
+	}
+
+	@Bean
+	public FilterRegistrationBean registration(DmpAccessControlFilter filter) {
+		FilterRegistrationBean registration = new FilterRegistrationBean(filter);
+		registration.setEnabled(false);
+		return registration;
+	}
+
+	@Bean
+	public MessageConverter customMessageConvert() {
+		return new Jackson2JsonMessageConverter();
+	}
+
+}

+ 39 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/controller/AdminController.java

@@ -0,0 +1,39 @@
+package com.persagy.dmp.admin.controller;
+
+import com.persagy.common.web.MapResponse;
+import com.persagy.dmp.admin.config.shiro.UserModel;
+import com.persagy.dmp.admin.service.AdminService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+@RestController
+@RequestMapping("/admin")
+public class AdminController {
+
+	@Autowired
+	private AdminService adminService;
+
+	@PostMapping("/login")
+	public MapResponse login(@RequestBody UserModel userModel){
+		System.out.println("controller : /admin/login");
+		return adminService.login(userModel);
+	}
+
+	@PostMapping("/logout")
+	public MapResponse login(){
+		return adminService.logout();
+	}
+
+	@PostMapping("/userInfo")
+	public MapResponse userInfo(){
+		return adminService.userInfo();
+	}
+}

+ 39 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/controller/AdminRoleController.java

@@ -0,0 +1,39 @@
+package com.persagy.dmp.admin.controller;
+
+import com.persagy.common.criteria.JacksonCriteria;
+import com.persagy.common.web.MapResponse;
+import com.persagy.common.web.PagedResponse;
+import com.persagy.dmp.admin.entity.AdminRole;
+import com.persagy.dmp.admin.service.AdminRoleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+@RestController
+@RequestMapping("/admin/system/role")
+public class AdminRoleController {
+	@Autowired
+	private AdminRoleService service;
+	
+	@PostMapping("/query")
+	public PagedResponse<AdminRole> query(@RequestBody JacksonCriteria criteria) {
+		return service.query(criteria);
+	}
+	
+	@PostMapping("/create")
+	public MapResponse create(@RequestBody AdminRole param){
+		return service.create(param);
+	}
+	
+	@PostMapping("/update")
+	public MapResponse update(@RequestBody AdminRole param){
+		return service.update(param);
+	}
+	
+	@PostMapping("/delete")
+	public MapResponse delete(@RequestBody AdminRole param){
+		return service.delete(param);
+	}
+	
+}

+ 39 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/controller/AdminUserController.java

@@ -0,0 +1,39 @@
+package com.persagy.dmp.admin.controller;
+
+import com.persagy.common.criteria.JacksonCriteria;
+import com.persagy.common.web.MapResponse;
+import com.persagy.common.web.PagedResponse;
+import com.persagy.dmp.admin.entity.AdminUser;
+import com.persagy.dmp.admin.service.AdminUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+@RestController
+@RequestMapping("/admin/system/user")
+public class AdminUserController {
+	@Autowired
+	private AdminUserService service;
+	
+	@PostMapping("/query")
+	public PagedResponse<AdminUser> query(@RequestBody JacksonCriteria criteria) {
+		return service.query(criteria);
+	}
+	
+	@PostMapping("/create")
+	public MapResponse create(@RequestBody AdminUser param){
+		return service.create(param);
+	}
+	
+	@PostMapping("/update")
+	public MapResponse update(@RequestBody AdminUser param){
+		return service.update(param);
+	}
+	
+	@PostMapping("/delete")
+	public MapResponse delete(@RequestBody AdminUser param){
+		return service.delete(param);
+	}
+
+}

+ 71 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/controller/DmpGatewayController.java

@@ -0,0 +1,71 @@
+package com.persagy.dmp.admin.controller;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.persagy.common.web.ServletUtils;
+import com.persagy.dmp.admin.config.web.UserUtils;
+import com.persagy.dmp.common.http.HttpUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+@RestController
+@RequestMapping("/dmp")
+public class DmpGatewayController {
+
+	@Autowired
+	private HttpUtils httpUtils;
+
+	@Value("${persagy.dmp.server}")
+	private String dmpServer;
+
+	@PostMapping("/dic/**")
+	public void dic(HttpServletRequest request, HttpServletResponse response, @RequestBody JsonNode param) {
+		dispatch(request, response, param);
+	}
+
+	@PostMapping("/org/**")
+	public void org(HttpServletRequest request, HttpServletResponse response, @RequestBody JsonNode param) {
+		dispatch(request, response, param);
+	}
+
+	@PostMapping("/rwd/**")
+	public void rwd(HttpServletRequest request, HttpServletResponse response, @RequestBody JsonNode param) {
+		dispatch(request, response, param);
+	}
+
+	private void dispatch(HttpServletRequest request, HttpServletResponse response, @RequestBody JsonNode param) {
+		StringBuilder url = new StringBuilder(dmpServer);
+		String uri = request.getRequestURI().replace("/dmp", "");
+		url.append(uri);
+		String queryString = request.getQueryString();
+		if (!"/rwd/def/class".equalsIgnoreCase(uri) && !"/rwd/def/funcid".equalsIgnoreCase(uri)) {
+			queryString = appendParamIfNotExists(queryString, "appId", "datautils");
+			queryString = appendParamIfNotExists(queryString, "userId", "admin" + UserUtils.currentUserId());
+		}
+		url.append("?").append(queryString);
+
+		HttpUtils.HttpResult post = httpUtils.post(url.toString(), param.toString(), 30000);
+		String content = post.getContent();
+		ServletUtils.writeJson(response, content);
+	}
+
+	private String appendParamIfNotExists(String queryString, String key, String value) {
+		if (queryString == null) {
+			return key + "=" + value;
+		} else {
+			return queryString + "&" + key + "=" + value;
+		}
+	}
+
+}

+ 30 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/controller/DmpTransController.java

@@ -0,0 +1,30 @@
+package com.persagy.dmp.admin.controller;
+
+import com.persagy.common.web.MapResponse;
+import com.persagy.dmp.admin.service.DmpTransObjectService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-30
+ * @verison: 1.0
+ */
+@RestController
+@RequestMapping("/dmp/rwd/trans")
+public class DmpTransController {
+
+	@Autowired
+	private DmpTransObjectService transObjectService;
+
+	@PostMapping("/object")
+	public MapResponse transObject(@RequestBody Map<String, Object> param) {
+		return transObjectService.trans(param);
+	}
+
+}

+ 74 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/controller/TransObjectInfoController.java

@@ -0,0 +1,74 @@
+package com.persagy.dmp.admin.controller;
+
+import com.persagy.common.criteria.JacksonCriteria;
+import com.persagy.common.web.MapResponse;
+import com.persagy.common.web.PagedResponse;
+import com.persagy.dmp.admin.entity.TransObjectInfo;
+import com.persagy.dmp.admin.model.DownloadModel;
+import com.persagy.dmp.admin.service.TransObjectInfoService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+
+/**
+ * @author: yaoll
+ * @date: 2021-01-04
+ * @verison: 1.0
+ */
+@Slf4j
+@RestController
+@RequestMapping("/dmp/rwd/trans/object/info")
+public class TransObjectInfoController {
+
+	@Autowired
+	private TransObjectInfoService service;
+
+	@PostMapping("/query")
+	public PagedResponse<TransObjectInfo> query(@RequestBody JacksonCriteria criteria) {
+		return service.query(criteria);
+	}
+
+	@PostMapping("/deleteByProjectId")
+	public MapResponse deleteByProjectId(@RequestParam String projectId) {
+		return service.deleteByProjectId(projectId);
+	}
+
+	@PostMapping("/download")
+	public void download(@RequestParam String projectId, HttpServletResponse response) {
+		DownloadModel result = service.download(projectId);
+		String fileName = result.getName();
+		downloadWorkbook(response, fileName, result.getWorkbook());
+	}
+
+	private void downloadWorkbook(HttpServletResponse resp, String fileName, Workbook workbook) {
+		OutputStream out = null;
+		try {
+			resp.reset();// 清空输出流
+			String resultFileName = URLEncoder.encode(fileName, "UTF-8");
+			resp.setCharacterEncoding("UTF-8");
+			resp.setHeader("Content-disposition", "attachment; filename=" + resultFileName);// 设定输出文件头
+			resp.setContentType("application/msexcel");// 定义输出类型
+			out = resp.getOutputStream();
+			workbook.write(out);
+			out.flush();
+			log.info("download over: {}", fileName);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				if (out != null) {
+					out.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+}

+ 30 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminPermission.java

@@ -0,0 +1,30 @@
+package com.persagy.dmp.admin.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "admin_permission")
+public class AdminPermission {
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	private Integer id;
+	private String sign;
+	private String name;
+	private String remark;
+	private Integer status;
+	@CreationTimestamp
+	@Column(updatable = false)
+	private Date createTime;
+	@UpdateTimestamp
+	private Date updateTime;
+
+}

+ 41 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminRole.java

@@ -0,0 +1,41 @@
+package com.persagy.dmp.admin.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import javax.persistence.*;
+import java.util.Date;
+import java.util.List;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "admin_role")
+public class AdminRole {
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	private Integer id;
+	private String name;
+	private String remark;
+	private Integer status;
+	@Column(updatable = false)
+	private Integer createUser;
+	@CreationTimestamp
+	@Column(updatable = false)
+	private Date createTime;
+	private Integer updateUser;
+	@UpdateTimestamp
+	private Date updateTime;
+
+	@JoinTable(name = "admin_role_permission", joinColumns = {
+			@JoinColumn(name = "role_id", referencedColumnName = "id")},
+			inverseJoinColumns = {
+					@JoinColumn(name = "permission_id", referencedColumnName = "id")
+			})
+	@ManyToMany(targetEntity = AdminPermission.class, fetch = FetchType.LAZY)
+	@OrderBy("id")
+	private List<AdminPermission> permissions;
+}

+ 47 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminUser.java

@@ -0,0 +1,47 @@
+package com.persagy.dmp.admin.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import javax.persistence.*;
+import java.util.Date;
+import java.util.List;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "admin_user")
+public class AdminUser {
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	private Integer id;
+	private String username;
+	private String password;
+	private String realname;
+	private String phone;
+	private String remark;
+	private Integer status;
+	@Column(updatable = false)
+	private Integer createUser;
+	@CreationTimestamp
+	@Column(updatable = false)
+	private Date createTime;
+	private Integer updateUser;
+	@UpdateTimestamp
+	private Date updateTime;
+
+	@JoinTable(name = "admin_user_role", joinColumns = {
+			@JoinColumn(name = "user_id", referencedColumnName = "id")},
+			inverseJoinColumns = {
+					@JoinColumn(name = "role_id", referencedColumnName = "id")
+			})
+	@ManyToMany(targetEntity = AdminRole.class, fetch = FetchType.LAZY)
+	@OrderBy("id")
+	private List<AdminRole> roles;
+
+	@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "user")
+	private List<AdminUserProject> projects;
+}

+ 32 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/entity/AdminUserProject.java

@@ -0,0 +1,32 @@
+package com.persagy.dmp.admin.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.*;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+@Setter
+@Getter
+@Entity
+@Table(name = "admin_user_project")
+public class AdminUserProject {
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	private Integer id;
+
+	@JsonIgnore
+	@ManyToOne
+	@JoinColumn(name = "user_id")
+	private AdminUser user;
+
+	private String groupCode;
+	private String projectId;
+
+}

+ 33 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/entity/TransObjectInfo.java

@@ -0,0 +1,33 @@
+package com.persagy.dmp.admin.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "admin_trans_object_info")
+public class TransObjectInfo {
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	private Integer id;
+	private String projectId;
+	private String type;
+	private String classCode;
+	private String objectId;
+	private String infoCode;
+	private String infoCodeValue;
+	private String message;
+
+	@CreationTimestamp
+	@Column(updatable = false)
+	private Date createTime;
+
+	public TransObjectInfo() {
+	}
+}

+ 58 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/jms/JmsConfig.java

@@ -0,0 +1,58 @@
+package com.persagy.dmp.admin.jms;
+
+import com.persagy.common.json.JacksonMapper;
+import com.persagy.dmp.rwd.model.DmpMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author: yaoll
+ * @date: 2020-10-22
+ * @verison: 1.0
+ */
+@Slf4j
+@Configuration
+public class JmsConfig {
+
+
+	@Value("${persagy.dmp.exchange}")
+	private String exchange;
+
+	private String adminRoutingKey = "routing-dmp-admin";
+
+	private String adminQueue = "queue-dmp-admin";
+
+	@Autowired
+	private MessageProcesser messageProcesser;
+
+	@Bean
+	public TopicExchange exchage() {
+		return new TopicExchange(exchange);
+	}
+
+	@Bean
+	public Queue queue() {
+		return new Queue(adminQueue, true);
+	}
+
+	// admin -> admin
+	@Bean
+	public Binding rwdBinding() {
+		return BindingBuilder.bind(queue()).to(exchage()).with(adminRoutingKey);
+	}
+
+	@RabbitListener(queues = "queue-dmp-admin")    //监听器监听指定的Queue
+	public void processC(DmpMessage message) {
+		log.info("============================== Receive {}: {}", adminQueue, JacksonMapper.toSimpleJson(message));
+		messageProcesser.listen(message);
+	}
+
+}

+ 14 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/jms/MessageExecutor.java

@@ -0,0 +1,14 @@
+package com.persagy.dmp.admin.jms;
+
+import com.persagy.dmp.rwd.model.DmpMessage;
+
+/**
+ * @author: yaoll
+ * @date: 2020-10-22
+ * @verison: 1.0
+ */
+public interface MessageExecutor {
+
+	void execute(DmpMessage message);
+
+}

+ 64 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/jms/MessageProcesser.java

@@ -0,0 +1,64 @@
+package com.persagy.dmp.admin.jms;
+
+import com.persagy.common.date.DateUtils;
+import com.persagy.dmp.common.SpringUtils;
+import com.persagy.dmp.config.DmpParameterStorage;
+import com.persagy.dmp.rwd.model.DmpMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * @author: yaoll
+ * @date: 2020-10-22
+ * @verison: 1.0
+ */
+@Slf4j
+@Component
+public class MessageProcesser {
+
+	@Value("${persagy.dmp.exchange}")
+	private String exchange;
+
+	private String adminRoutingKey = "routing-dmp-admin";
+
+	@Autowired
+	private RabbitTemplate rabbitTemplate;
+
+	public void convertAndSend(DmpMessage message) {
+		if (message.getSendTime() == null) {
+			message.setSendTime(DateUtils.format(new Date()));
+		}
+		rabbitTemplate.convertAndSend(exchange, adminRoutingKey, message);
+	}
+
+	public void listen(DmpMessage message) {
+		String type = message.getType();
+
+		String executorName = type + "Executor";
+		MessageExecutor executor = SpringUtils.getBean(executorName, MessageExecutor.class);
+		if (executor == null) {
+			log.error("bean for [" + executorName + "] not exists");
+		}
+
+		try {
+			DmpParameterStorage.ParameterData data = new DmpParameterStorage.ParameterData();
+			data.setGroupCode(message.getGroupCode());
+			data.setProjectId(message.getProjectId());
+			data.setAppId(message.getAppId());
+
+			DmpParameterStorage.set(data);
+
+			executor.execute(message);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			DmpParameterStorage.clear();
+		}
+	}
+
+}

+ 87 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/jms/executor/TransObjectExecutor.java

@@ -0,0 +1,87 @@
+package com.persagy.dmp.admin.jms.executor;
+
+import com.persagy.dmp.admin.jms.MessageExecutor;
+import com.persagy.dmp.admin.service.trans.TransObjectContext;
+import com.persagy.dmp.admin.service.DmpTransObjectService;
+import com.persagy.dmp.rwd.model.DmpMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-30
+ * @verison: 1.0
+ */
+@Slf4j
+@Component
+public class TransObjectExecutor implements MessageExecutor {
+
+	@Autowired
+	private DmpTransObjectService transObjectService;
+
+	@Override
+	public void execute(DmpMessage message) {
+
+		TransObjectContext ctx = prepareContext(message);
+
+		try {
+			// 启动
+			transObjectService.start(ctx);
+
+			// 加载中台类型定义
+			transObjectService.initClass(ctx);
+
+			// 传输项目
+			transObjectService.transProject(ctx);
+
+			// 传输建筑
+			transObjectService.transBuilding(ctx);
+
+			// 传输楼层
+			transObjectService.transFloor(ctx);
+
+			// 传输空间
+			transObjectService.transSpace(ctx);
+
+			// 传输系统设备部件
+			transObjectService.transEquipment(ctx);
+
+			// 传输竖井
+			transObjectService.transShaft(ctx);
+
+			// TODO 传输虚拟对象
+
+			// 传输关系
+			transObjectService.transRelation(ctx);
+
+			// 处理失效数据
+			transObjectService.transInvalidObject(ctx);
+
+
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			transObjectService.over(ctx);
+		}
+
+
+	}
+
+
+	private TransObjectContext prepareContext(DmpMessage message) {
+		String groupCode = message.getGroupCode();
+		String projectId = message.getProjectId();
+		String server = message.getStr1();
+		String secret = message.getStr2();
+
+		TransObjectContext context = new TransObjectContext();
+		context.setAppId("datautils");
+		context.setUserId("system");
+		context.setGroupCode(groupCode);
+		context.setProjectId(projectId);
+		context.setServer(server);
+		context.setSecret(secret);
+		return context;
+	}
+}

+ 13 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/model/DownloadModel.java

@@ -0,0 +1,13 @@
+package com.persagy.dmp.admin.model;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.poi.ss.usermodel.Workbook;
+
+@Getter
+@Setter
+public class DownloadModel {
+	private String type;
+	private String name;
+	private Workbook workbook;
+}

+ 27 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminPermissionRepository.java

@@ -0,0 +1,27 @@
+package com.persagy.dmp.admin.repository;
+
+import com.persagy.dmp.admin.entity.AdminPermission;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+
+import java.util.List;
+
+public interface AdminPermissionRepository extends JpaRepository<AdminPermission, Integer>, QuerydslPredicateExecutor<AdminPermission> {
+
+	@Query(nativeQuery = true,
+			value = "" +
+					" select distinct sign                                                   " +
+					"   from admin_permission p                                              " +
+					"   join admin_role_permission rp on p.id = rp.permission_id             " +
+					"   join admin_role r on rp.role_id = r.id                               " +
+					"   join admin_user_role ur on ur.role_id = r.id                         " +
+					"  where ur.user_id = ?                                                  " +
+					"    and p.status = 1                                                    " +
+					"    and r.status = 1                                                    " +
+					"  order by sign                                                         ")
+	List<String> queryForUser(Integer userId);
+
+
+}
+

+ 9 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminRoleRepository.java

@@ -0,0 +1,9 @@
+package com.persagy.dmp.admin.repository;
+
+import com.persagy.dmp.admin.entity.AdminRole;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+
+public interface AdminRoleRepository extends JpaRepository<AdminRole, Integer>, QuerydslPredicateExecutor<AdminRole>{
+}
+

+ 9 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminUserProjectRepository.java

@@ -0,0 +1,9 @@
+package com.persagy.dmp.admin.repository;
+
+import com.persagy.dmp.admin.entity.AdminUserProject;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+
+public interface AdminUserProjectRepository extends JpaRepository<AdminUserProject, Integer>, QuerydslPredicateExecutor<AdminUserProject>{
+}
+

+ 9 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/repository/AdminUserRepository.java

@@ -0,0 +1,9 @@
+package com.persagy.dmp.admin.repository;
+
+import com.persagy.dmp.admin.entity.AdminUser;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+
+public interface AdminUserRepository extends JpaRepository<AdminUser, Integer>, QuerydslPredicateExecutor<AdminUser>{
+}
+

+ 16 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/repository/TransObjectInfoRepository.java

@@ -0,0 +1,16 @@
+package com.persagy.dmp.admin.repository;
+
+import com.persagy.dmp.admin.entity.TransObjectInfo;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+
+public interface TransObjectInfoRepository extends JpaRepository<TransObjectInfo, Integer>, QuerydslPredicateExecutor<TransObjectInfo> {
+
+	@Modifying
+	@Query(nativeQuery = true, value = "delete from admin_trans_object_info where project_id = ?")
+	int deleteByProjectId(String projectId);
+
+}
+

+ 152 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/AdminRoleService.java

@@ -0,0 +1,152 @@
+package com.persagy.dmp.admin.service;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.common.criteria.CriteriaUtils;
+import com.persagy.common.criteria.JacksonCriteria;
+import com.persagy.common.web.MapResponse;
+import com.persagy.common.web.PagedResponse;
+import com.persagy.dmp.admin.config.web.UserUtils;
+import com.persagy.dmp.admin.entity.AdminPermission;
+import com.persagy.dmp.admin.entity.AdminRole;
+import com.persagy.dmp.admin.entity.QAdminPermission;
+import com.persagy.dmp.admin.entity.QAdminRole;
+import com.persagy.dmp.admin.repository.AdminPermissionRepository;
+import com.persagy.dmp.admin.repository.AdminRoleRepository;
+import com.querydsl.core.types.dsl.BooleanExpression;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class AdminRoleService {
+
+	@Autowired
+	private AdminRoleRepository adminRoleRepository;
+
+	@Autowired
+	private AdminPermissionRepository permissionRepository;
+
+	@Autowired
+	private CriteriaUtils criteriaUtils;
+
+	private List<BooleanExpression> parse(ObjectNode criteria) {
+		// TODO
+		return null;
+	}
+
+	public PagedResponse<AdminRole> query(JacksonCriteria criteria) {
+		PagedResponse<AdminRole> query = criteriaUtils.query(QAdminRole.adminRole, this::parse, criteria);
+
+		// permissions
+		PagedResponse<AdminRole> resp = new PagedResponse<>();
+		resp.setCount(query.getCount());
+		List<AdminRole> data = query.getData();
+		if (data != null) {
+			boolean withPermissions = criteria.withColumn("permissions");
+			List<AdminRole> list = new ArrayList<>(data.size());
+			for (AdminRole role : data) {
+				AdminRole model = new AdminRole();
+				BeanUtils.copyProperties(role,model,"permissions");
+				if (withPermissions) {
+					model.setPermissions(role.getPermissions());
+				}
+				list.add(model);
+			}
+			resp.setData(list);
+		}
+		return resp;
+	}
+
+	@Transactional
+	public MapResponse create(AdminRole param) {
+		MapResponse response = new MapResponse();
+		// TODO
+		String name = param.getName();
+		if (name == null) {
+			response.setFail("name is required");
+			return response;
+		}
+
+		long count = adminRoleRepository.count(QAdminRole.adminRole.name.eq(name));
+		if (count > 0) {
+			response.setFail("name is exists");
+			return response;
+		}
+
+		AdminRole role = new AdminRole();
+		role.setName(param.getName());
+		role.setRemark(param.getRemark());
+		role.setCreateUser(UserUtils.currentUserId());
+		role.setStatus(1);
+		adminRoleRepository.save(role);
+		response.add("id", role.getId());
+		return response;
+	}
+
+	@Transactional
+	public MapResponse update(AdminRole param) {
+		MapResponse response = new MapResponse();
+		// TODO
+		Integer roleId = param.getId();
+		Optional<AdminRole> opt = adminRoleRepository.findById(roleId);
+		if (!opt.isPresent()) {
+			response.setFail("data not exists");
+			return response;
+		}
+
+		AdminRole role = opt.get();
+		if (param.getRemark() != null) {
+			role.setRemark(param.getRemark());
+		}
+
+		// TODO
+		List<AdminPermission> permissions = param.getPermissions();
+		if (permissions != null) {
+			role.getPermissions().clear();
+			for (AdminPermission permission : permissions) {
+				if (permission.getSign() == null) {
+					continue;
+				}
+
+				AdminPermission entity;
+				Optional<AdminPermission> optp = permissionRepository.findOne(QAdminPermission.adminPermission.sign.eq(permission.getSign()));
+				if (!optp.isPresent()) {
+					entity = new AdminPermission();
+					entity.setSign(permission.getSign());
+					entity.setStatus(1);
+					permissionRepository.save(entity);
+				}else {
+					entity = optp.get();
+					if (entity.getStatus() != 1) {
+						continue;
+					}
+				}
+				role.getPermissions().add(entity);
+			}
+		}
+		role.setUpdateUser(UserUtils.currentUserId());
+		adminRoleRepository.save(role);
+		return response;
+	}
+
+	@Transactional
+	public MapResponse delete(AdminRole param) {
+		MapResponse response = new MapResponse();
+		// TODO
+		Integer userId = param.getId();
+		Optional<AdminRole> opt = adminRoleRepository.findById(userId);
+		if (opt.isPresent()) {
+			AdminRole role = opt.get();
+			role.setStatus(0);
+			role.setUpdateUser(UserUtils.currentUserId());
+			adminRoleRepository.save(role);
+		}
+		return response;
+	}
+}
+

+ 129 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/AdminService.java

@@ -0,0 +1,129 @@
+package com.persagy.dmp.admin.service;
+
+import com.persagy.common.security.MD5Utils;
+import com.persagy.common.web.MapResponse;
+import com.persagy.dmp.admin.config.shiro.ShiroContants;
+import com.persagy.dmp.admin.config.shiro.UserModel;
+import com.persagy.dmp.admin.config.web.UserUtils;
+import com.persagy.dmp.admin.entity.AdminUser;
+import com.persagy.dmp.admin.entity.QAdminUser;
+import com.persagy.dmp.admin.repository.AdminPermissionRepository;
+import com.persagy.dmp.admin.repository.AdminUserRepository;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-29
+ * @verison: 1.0
+ */
+@Service
+public class AdminService {
+
+	@Autowired
+	private AdminUserRepository userRepository;
+
+	@Autowired
+	private AdminPermissionRepository permissionRepository;
+
+	@Autowired
+	private StringRedisTemplate redis;
+
+	public MapResponse login(UserModel userModel) {
+		MapResponse resp = new MapResponse();
+
+		String username = userModel.getUsername();
+		String password = userModel.getPassword();
+		if (username == null || password == null) {
+			resp.setFail("username and password is required");
+			return resp;
+		}
+
+		Optional<AdminUser> one = userRepository.findOne(QAdminUser.adminUser.username.eq(username));
+		if (!one.isPresent()) {
+			resp.setFail("username or password error!");
+			return resp;
+		}
+		AdminUser user = one.get();
+		if (user.getStatus() != 1) {
+			resp.setFail("user is invalid!");
+			return resp;
+		}
+
+		if (!MD5Utils.getSign(password).equalsIgnoreCase(user.getPassword())) {
+			resp.setFail("username or password error!");
+			return resp;
+		}
+
+		String token = UUID.randomUUID().toString().replace("-", "");
+
+		redis.opsForValue().set(ShiroContants.KEY_TOKEN_USER + token, user.getId() + "");
+		redis.opsForValue().set(ShiroContants.KEY_USER_TOKEN + user.getId(), token);
+
+		Subject subject = SecurityUtils.getSubject();
+		UsernamePasswordToken shiroToken = new UsernamePasswordToken(user.getUsername(), token);
+		subject.login(shiroToken);
+
+		resp.add("token", token);
+		return resp;
+	}
+
+	public MapResponse logout() {
+		MapResponse resp = new MapResponse();
+		Integer userId = UserUtils.currentUserId();
+		if (userId == null) {
+			return resp;
+		}
+
+		String token = redis.opsForValue().get(ShiroContants.KEY_USER_TOKEN + userId);
+		if (token != null) {
+			redis.delete(ShiroContants.KEY_TOKEN_USER + token);
+		}
+		redis.delete(ShiroContants.KEY_USER_TOKEN + userId);
+
+		Subject subject = SecurityUtils.getSubject();
+		if (subject.isAuthenticated()) {
+			subject.logout();
+		}
+		return resp;
+	}
+
+	public MapResponse userInfo() {
+		MapResponse resp = new MapResponse();
+		Integer userId = UserUtils.currentUserId();
+		Optional<AdminUser> one = userRepository.findOne(QAdminUser.adminUser.id.eq(userId));
+		if (!one.isPresent()) {
+			resp.setFail("username or password error!");
+			return resp;
+		}
+		AdminUser user = one.get();
+		if (user.getStatus() != 1) {
+			resp.setFail("user is invalid!");
+			return resp;
+		}
+
+		resp.add("userId", user.getId());
+		resp.add("username", user.getUsername());
+		resp.add("realname", user.getRealname());
+		resp.add("projects", user.getProjects());
+
+		List<String> permissions = permissionRepository.queryForUser(userId);
+		resp.add("permissions", permissions);
+
+
+		return resp;
+	}
+
+	public static void main(String[] args) {
+		System.out.println(MD5Utils.getSign("123456"));
+	}
+}
+

+ 143 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/AdminUserService.java

@@ -0,0 +1,143 @@
+package com.persagy.dmp.admin.service;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.common.criteria.CriteriaUtils;
+import com.persagy.common.criteria.JacksonCriteria;
+import com.persagy.common.security.MD5Utils;
+import com.persagy.common.web.MapResponse;
+import com.persagy.common.web.PagedResponse;
+import com.persagy.dmp.admin.config.web.UserUtils;
+import com.persagy.dmp.admin.entity.AdminRole;
+import com.persagy.dmp.admin.entity.AdminUser;
+import com.persagy.dmp.admin.entity.AdminUserProject;
+import com.persagy.dmp.admin.entity.QAdminUser;
+import com.persagy.dmp.admin.repository.AdminUserRepository;
+import com.querydsl.core.types.dsl.BooleanExpression;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+@Service
+public class AdminUserService {
+
+	@Autowired
+	private AdminUserRepository adminUserRepository;
+
+	@Autowired
+	private CriteriaUtils criteriaUtils;
+
+	private List<BooleanExpression> parse(ObjectNode criteria) {
+		// TODO
+		return null;
+	}
+
+	public PagedResponse<AdminUser> query(JacksonCriteria criteria) {
+		PagedResponse<AdminUser> query = criteriaUtils.query(QAdminUser.adminUser, this::parse, criteria);
+		PagedResponse<AdminUser> resp = new PagedResponse<>();
+		resp.setCount(query.getCount());
+		List<AdminUser> data = query.getData();
+		if (data != null && data.size() > 0) {
+			Set<String> withColumns = criteria.getWithColumns();
+			List<AdminUser> list = new ArrayList<>(data.size());
+			boolean withRoles = withColumns != null && withColumns.contains("roles");
+			boolean withProjects = withColumns != null && withColumns.contains("projects");
+			for (AdminUser user : data) {
+				AdminUser model = new AdminUser();
+				BeanUtils.copyProperties(user, model, "password", "roles", "projects");
+				if (withRoles) {
+					model.setRoles(user.getRoles());
+				}
+				if (withProjects) {
+					model.setProjects(user.getProjects());
+				}
+				list.add(model);
+			}
+			resp.setData(list);
+		}
+		return resp;
+	}
+
+	@Transactional
+	public MapResponse create(AdminUser param) {
+		MapResponse response = new MapResponse();
+		// TODO
+		String username = param.getUsername();
+		if (username == null) {
+			response.setFail("账号不可为空!");
+			return response;
+		}
+		long count = adminUserRepository.count(QAdminUser.adminUser.username.eq(username));
+		if (count > 0) {
+			response.setFail("账号已存在!");
+			return response;
+		}
+
+		AdminUser entity = new AdminUser();
+		entity.setUsername(username);
+		entity.setRealname(param.getRealname());
+		entity.setPassword(MD5Utils.getSign("123456"));
+		entity.setCreateUser(UserUtils.currentUserId());
+		entity.setStatus(1);
+		adminUserRepository.save(entity);
+		response.add("id", entity.getId());
+		return response;
+	}
+
+	@Transactional
+	public MapResponse update(AdminUser param) {
+		MapResponse response = new MapResponse();
+		// TODO
+		Integer userId = param.getId();
+		AdminUser user = adminUserRepository.findById(userId).get();
+		String realname = param.getRealname();
+		if (realname != null) {
+			user.setRealname(realname);
+		}
+		String phone = param.getPhone();
+		if (phone != null) {
+			user.setPhone(phone);
+		}
+		String remark = param.getRemark();
+		if (remark != null) {
+			user.setRemark(remark);
+		}
+
+		List<AdminRole> roles = param.getRoles();
+		if (roles != null) {
+			user.getRoles().clear();
+			user.getRoles().addAll(roles);
+		}
+
+		List<AdminUserProject> projects = param.getProjects();
+		if (projects != null) {
+			user.getProjects().clear();
+			for (AdminUserProject project : projects) {
+				project.setUser(user);
+			}
+			user.getProjects().addAll(projects);
+		}
+
+		adminUserRepository.save(user);
+		response.add("id", userId);
+		return response;
+	}
+
+	@Transactional
+	public MapResponse delete(AdminUser param) {
+		MapResponse response = new MapResponse();
+		// TODO
+
+		Integer id = param.getId();
+		AdminUser user = adminUserRepository.findById(id).get();
+		user.setStatus(0);
+		user.setUpdateUser(UserUtils.currentUserId());
+		adminUserRepository.save(user);
+		return response;
+	}
+}
+

+ 247 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/DmpTransObjectService.java

@@ -0,0 +1,247 @@
+package com.persagy.dmp.admin.service;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.common.json.JacksonMapper;
+import com.persagy.common.web.MapResponse;
+import com.persagy.dmp.admin.repository.TransObjectInfoRepository;
+import com.persagy.dmp.admin.service.trans.RwdTransUtils;
+import com.persagy.dmp.admin.service.trans.TransObjectContext;
+import com.persagy.dmp.common.http.HttpUtils;
+import com.persagy.dmp.rwd.model.DmpMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.MapUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-30
+ * @verison: 1.0
+ */
+@Slf4j
+@Service
+public class DmpTransObjectService {
+
+	private static final String KEY_TRANS = "admin_trans_";
+
+	@Autowired
+	private RwdTransUtils transUtils;
+
+	@Autowired
+	private HttpUtils httpUtils;
+
+	@Value("${persagy.dmp.server}")
+	private String dmpServer;
+
+	@Autowired
+	private StringRedisTemplate redis;
+
+	@Autowired
+	private TransObjectInfoRepository objectInfoRepository;
+
+	// 开始迁移
+	@Transactional
+	public MapResponse trans(Map<String, Object> param) {
+		MapResponse resp = new MapResponse();
+		String groupCode = MapUtils.getString(param, "groupCode");
+		if (groupCode == null) {
+			resp.setFail("groupCode is required");
+			return resp;
+		}
+		String projectId = MapUtils.getString(param, "projectId");
+		if (projectId == null) {
+			resp.setFail("projectId is required");
+			return resp;
+		}
+		String server = MapUtils.getString(param, "server");
+		if (server == null) {
+			resp.setFail("server is required");
+			return resp;
+		}
+		String secret = MapUtils.getString(param, "secret");
+		if (secret == null) {
+			resp.setFail("secret is required");
+			return resp;
+		}
+		log.info("object trans start: {}", JacksonMapper.toSimpleJson(param));
+
+		String key = KEY_TRANS + projectId;
+		Long flag = redis.opsForValue().increment(key, 1L);
+		if (flag > 1) {
+			resp.setFail("正在处理中...");
+			return resp;
+		}
+		redis.expire(key, 24, TimeUnit.HOURS);
+
+		objectInfoRepository.deleteByProjectId(projectId);
+
+		DmpMessage message = new DmpMessage("transObject", projectId);
+		message.setGroupCode(groupCode);
+		message.setProjectId(projectId);
+		message.setStr1(server);
+		message.setStr2(secret);
+		resp.add(message);
+		return resp;
+	}
+
+	// 开始标记
+	public void start(TransObjectContext ctx) {
+		transUtils.writeInfo(ctx, "info", "start");
+	}
+
+	// 初始化类型
+	public void initClass(TransObjectContext ctx) {
+		transUtils.initClass(ctx);
+	}
+
+	// 迁移项目
+	public void transProject(TransObjectContext ctx) {
+		transByType(ctx, "project", "Pj");
+	}
+
+	// 迁移建筑
+	public void transBuilding(TransObjectContext ctx) {
+		transByType(ctx, "building", "Bd");
+	}
+
+	// 迁移楼层
+	public void transFloor(TransObjectContext ctx) {
+		transByType(ctx, "floor", "Fl");
+	}
+
+	// 迁移竖井
+	public void transShaft(TransObjectContext ctx) {
+		transByType(ctx, "shaft", "Sh");
+	}
+
+	private void transByType(TransObjectContext ctx, String objType, String type) {
+		String classCode = ctx.getClassCodeMapping().get(type);
+		if (classCode == null) {
+			transUtils.writeInfo(ctx, "error", "类型[" + type + "]未定义");
+			return;
+		}
+		List<ObjectNode> list = transUtils.queryObject(ctx, type);
+		if (list == null) {
+			return;
+		}
+		// 加载信息点
+		transUtils.initFuncidCache(ctx, classCode);
+		List<ObjectNode> objects = transUtils.toDmpObject(ctx, list, objType, classCode);
+		transUtils.save(ctx, objects, type);
+	}
+
+	// 迁移空间
+	public void transSpace(TransObjectContext ctx) {
+		String objType = "space";
+		List<ObjectNode> list = transUtils.queryObject(ctx, "Sp");
+		if (list == null) {
+			return;
+		}
+		Set<String> businessTypes = new HashSet<>();
+		for (ObjectNode obj : list) {
+			businessTypes.add(obj.get("businessType").asText());
+		}
+
+		for (String classCode : businessTypes) {
+			// 加载信息点
+			transUtils.initFuncidCache(ctx, classCode);
+
+			List<ObjectNode> data = new LinkedList<>();
+			for (ObjectNode obj : list) {
+				String businessType = JacksonMapper.getString(obj, "businessType");
+				if (classCode.equalsIgnoreCase(businessType)) {
+					obj.remove("businessType");
+					data.add(obj);
+				}
+			}
+			List<ObjectNode> objects = transUtils.toDmpObject(ctx, data, objType, classCode);
+			transUtils.save(ctx, objects, classCode);
+		}
+	}
+
+	// 迁移系统设备部件
+	public void transEquipment(TransObjectContext ctx) {
+		String url = ctx.getServer() + "/data-platform-3/dict/query/equipment_all?project_id=" + ctx.getProjectId();
+		HttpUtils.HttpResult httpResult = httpUtils.get(url, 300 * 1000);
+		if (!httpResult.success()) {
+			transUtils.writeInfo(ctx, "error", "查询系统设备部件类型失败");
+			return;
+		}
+		String content = httpResult.getContent();
+		ObjectNode objectNode = JacksonMapper.toObject(content, ObjectNode.class);
+		String result = JacksonMapper.getString(objectNode, "Result");
+		if (!"success".equalsIgnoreCase(result)) {
+			transUtils.writeInfo(ctx, "error", "查询系统设备部件类型失败: " + JacksonMapper.getString(objectNode, "ResultMsg"));
+			return;
+		}
+		// 专业
+		ArrayNode array = JacksonMapper.getArray(objectNode, "Content");
+		for (JsonNode majorNode : array) {
+			ObjectNode major = (ObjectNode) majorNode;
+			String majorCode = JacksonMapper.getString(major, "code");
+			String majorName = JacksonMapper.getString(major, "class");
+			transUtils.writeInfo(ctx, "info", "专业迁移开始: " + majorCode + " " + majorName);
+
+			// 系统
+			ArrayNode systemArray = JacksonMapper.getArray(major, "content", JsonNodeFactory.instance.arrayNode());
+			for (JsonNode systemNode : systemArray) {
+				ObjectNode system = (ObjectNode) systemNode;
+				String systemCode = JacksonMapper.getString(system, "code");
+				String systemName = JacksonMapper.getString(system, "system");
+				transUtils.writeInfo(ctx, "info", "系统迁移开始: " + systemCode + " " + systemName);
+				transByType(ctx, "system", systemCode);
+				transUtils.writeInfo(ctx, "info", "系统迁移完成: " + systemCode + " " + systemName);
+
+				// 设备
+				ArrayNode equipArray = JacksonMapper.getArray(system, "content", JsonNodeFactory.instance.arrayNode());
+				for (JsonNode eqiupNode : equipArray) {
+					ObjectNode equip = (ObjectNode) eqiupNode;
+					String equipCode = JacksonMapper.getString(equip, "code");
+					String equipName = JacksonMapper.getString(equip, "facility");
+					transUtils.writeInfo(ctx, "info", "设备迁移开始: " + equipCode + " " + equipName);
+					transByType(ctx, "equipment", equipCode);
+					transUtils.writeInfo(ctx, "info", "设备迁移完成: " + equipCode + " " + equipName);
+
+					// 部件
+					ArrayNode componentArray = JacksonMapper.getArray(system, "components", JsonNodeFactory.instance.arrayNode());
+					for (JsonNode componentNode : componentArray) {
+						ObjectNode component = (ObjectNode) componentNode;
+						String componentCode = JacksonMapper.getString(equip, "code");
+						String componentName = JacksonMapper.getString(equip, "component");
+
+						transUtils.writeInfo(ctx, "info", "部件迁移开始: " + componentCode + " " + componentName);
+						transByType(ctx, "component", componentCode);
+						transUtils.writeInfo(ctx, "info", "部件迁移完成: " + componentCode + " " + componentName);
+					}
+				}
+			}
+			transUtils.writeInfo(ctx, "info", "专业迁移完成: " + majorCode + " " + majorName);
+		}
+	}
+
+	// 迁移关系
+	public void transRelation(TransObjectContext ctx) {
+		transUtils.transRelation(ctx);
+	}
+
+	// 处理失效数据
+	public void transInvalidObject(TransObjectContext ctx) {
+		transUtils.transInvalidObject(ctx);
+	}
+
+	public void over(TransObjectContext context) {
+		transUtils.writeInfo(context, "over", null);
+		String key = KEY_TRANS + context.getProjectId();
+		redis.delete(key);
+	}
+
+}

+ 85 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/TransObjectInfoService.java

@@ -0,0 +1,85 @@
+package com.persagy.dmp.admin.service;
+
+import com.persagy.common.criteria.CriteriaUtils;
+import com.persagy.common.criteria.JacksonCriteria;
+import com.persagy.common.web.MapResponse;
+import com.persagy.common.web.PagedResponse;
+import com.persagy.dmp.admin.entity.QTransObjectInfo;
+import com.persagy.dmp.admin.entity.TransObjectInfo;
+import com.persagy.dmp.admin.model.DownloadModel;
+import com.persagy.dmp.admin.repository.TransObjectInfoRepository;
+import com.persagy.dmp.common.excel.ExcelUtils;
+import com.persagy.dmp.common.excel.SheetWriteInfo;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author: yaoll
+ * @date: 2021-01-04
+ * @verison: 1.0
+ */
+@Service
+public class TransObjectInfoService {
+
+	@Autowired
+	private CriteriaUtils criteriaUtils;
+
+	@Autowired
+	private TransObjectInfoRepository objectInfoRepository;
+
+	public PagedResponse<TransObjectInfo> query(JacksonCriteria criteria) {
+		return criteriaUtils.query(QTransObjectInfo.transObjectInfo, null, criteria);
+	}
+
+
+	public MapResponse deleteByProjectId(String projectId) {
+		MapResponse resp = new MapResponse();
+		if (projectId != null) {
+			objectInfoRepository.deleteByProjectId(projectId);
+		}
+		return resp;
+	}
+
+	public DownloadModel download(String projectId) {
+		DownloadModel result = new DownloadModel();
+		result.setName("异常数据-" + projectId + ".xlsx");
+		List<SheetWriteInfo> list = new ArrayList<>(1);
+		SheetWriteInfo<TransObjectInfo> info = new SheetWriteInfo<>();
+		JacksonCriteria criteria = JacksonCriteria.newInstance();
+		criteria.setWithoutCount(true);
+		criteria.setOrders(Arrays.asList(new JacksonCriteria.Order("id", true)));
+		criteria.add("projectId", projectId);
+		criteria.add("type", "error");
+		info.setData(query(criteria).getData());
+		info.setSheetName("异常数据");
+		info.addColumn("项目ID", "projectId", "string", 30, HorizontalAlignment.CENTER);
+		info.addColumn("对象类型", "classCode", "string", 30, HorizontalAlignment.CENTER);
+		info.addColumn("对象ID", "objectId", "string", 80, HorizontalAlignment.CENTER);
+		info.addColumn("信息点编码", "infoCode", "string", 30, HorizontalAlignment.CENTER);
+		info.addColumn("信息点值", "infoCodeValue", "string", 130, HorizontalAlignment.CENTER);
+		info.addColumn("类型", "type", "string", 30, HorizontalAlignment.CENTER);
+		info.addColumn("异常信息", "message", "string", 200, HorizontalAlignment.LEFT);
+		info.setDataHandler((data, prop) -> {
+			switch (prop){
+				case "projectId": return data.getProjectId();
+				case "type": return data.getType();
+				case "classCode": return data.getClassCode();
+				case "objectId": return data.getObjectId();
+				case "infoCode": return data.getInfoCode();
+				case "infoCodeValue": return data.getInfoCodeValue();
+				case "message": return data.getMessage();
+			}
+			return null;
+		});
+		list.add(info);
+		Workbook workbook = ExcelUtils.createExcel(list);
+		result.setWorkbook(workbook);
+		return result;
+	}
+}

+ 336 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/GraphMapping.java

@@ -0,0 +1,336 @@
+package com.persagy.dmp.admin.service.trans;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-01
+ * @verison: 1.0
+ */
+public class GraphMapping {
+
+	private static final List<Item> mappings = new LinkedList<>();
+
+	static {
+		init();
+	}
+
+	public static void init() {
+		// 新版定义,无映射
+		Map<String, Item> map = new HashMap<>();
+		List<Item> baseLise = getBaseLise();
+		mappings.addAll(baseLise);
+
+		// 映射
+		List<Item> oldList = getOldMappingList();
+		mappings.addAll(oldList);
+
+		// 特殊的
+		List<Item> oldMappingListWithRelValue = getOldMappingListWithRelValue();
+		mappings.addAll(oldMappingListWithRelValue);
+	}
+
+	private static List<Item> getBaseLise() {
+		List<Item> list = new LinkedList<>();
+		list.add(new Item("ArchSubset", "Pj2Bd"));
+		list.add(new Item("ArchSubset", "Bd2Fl"));
+		list.add(new Item("ArchSubset", "Bd2Sh"));
+		list.add(new Item("ArchSubset", "Bd2Sp"));
+		list.add(new Item("ArchSubset", "Fl2Sp"));
+		list.add(new Item("ArchSubset", "Sh2Sp"));
+		list.add(new Item("SpaceNeighborhood", "None"));
+		list.add(new Item("SpaceNeighborhood", "Door"));
+		list.add(new Item("SpaceNeighborhood", "Window"));
+		list.add(new Item("SpaceNeighborhood", "DoorWindow"));
+		list.add(new Item("SpaceNeighborhood", "Connect"));
+		list.add(new Item("ThroughRelationship", "Fl2Fl"));
+		list.add(new Item("ThroughRelationship", "Sh2Sh"));
+		list.add(new Item("TrafficNetwork", "Normal"));
+		list.add(new Item("TrafficNetwork", "FFOpen"));
+		list.add(new Item("TrafficNetwork", "FFClose"));
+		list.add(new Item("ConvectionNetwork", "Natural"));
+		list.add(new Item("ConvectionNetwork", "OnewayMech"));
+		list.add(new Item("ConvectionNetwork", "MixMech"));
+		list.add(new Item("RadiationNetwork", "Connect"));
+		list.add(new Item("RadiationNetwork", "Transparent"));
+		list.add(new Item("MechInArch", "Sy2Bd"));
+		list.add(new Item("MechInArch", "Sy2Fl"));
+		list.add(new Item("MechInArch", "Sy2Sh"));
+		list.add(new Item("MechInArch", "Sy2Sp"));
+		list.add(new Item("MechInArch", "Eq2Bd"));
+		list.add(new Item("MechInArch", "Eq2Fl"));
+		list.add(new Item("MechInArch", "Eq2Sh"));
+		list.add(new Item("MechInArch", "Eq2Sp"));
+		list.add(new Item("MechForArch", "Sy2Bd"));
+		list.add(new Item("MechForArch", "Sy2Fl"));
+		list.add(new Item("MechForArch", "Sy2Sh"));
+		list.add(new Item("MechForArch", "Sy2Sp"));
+		list.add(new Item("MechForArch", "Eq2Bd"));
+		list.add(new Item("MechForArch", "Eq2Fl"));
+		list.add(new Item("MechForArch", "Eq2Sh"));
+		list.add(new Item("MechForArch", "Eq2Sp"));
+		list.add(new Item("MechSubset", "Pj2Sy"));
+		list.add(new Item("MechSubset", "Pj2Eq"));
+		list.add(new Item("MechSubset", "Sy2Eq"));
+		list.add(new Item("MechSubset", "Eq2Ec"));
+		list.add(new Item("LUDistribution", "Normal"));
+		list.add(new Item("LUDistribution", "Backup"));
+		list.add(new Item("HUDistribution", "Normal"));
+		list.add(new Item("HUDistribution", "Backup"));
+		list.add(new Item("ChillWaterLoop", "Supply"));
+		list.add(new Item("ChillWaterLoop", "Return"));
+		list.add(new Item("ChillWaterLoop", "Bypass"));
+		list.add(new Item("ChillWaterLoop", "Fill"));
+		list.add(new Item("CoolingWaterLoop", "Supply"));
+		list.add(new Item("CoolingWaterLoop", "Return"));
+		list.add(new Item("CoolingWaterLoop", "Bypass"));
+		list.add(new Item("CoolingWaterLoop", "Fill"));
+		list.add(new Item("HeatWaterLoop", "Supply"));
+		list.add(new Item("HeatWaterLoop", "Return"));
+		list.add(new Item("HeatWaterLoop", "Bypass"));
+		list.add(new Item("HeatWaterLoop", "Fill"));
+		list.add(new Item("CondWaterNetwork", "Discharge"));
+		list.add(new Item("ACAirNetwork", "Supply"));
+		list.add(new Item("ACAirNetwork", "Return"));
+		list.add(new Item("ACAirNetwork", "Discharge"));
+		list.add(new Item("FreshAirNetwork", "Fresh"));
+		list.add(new Item("VentNetwork", "Supply"));
+		list.add(new Item("VentNetwork", "Discharge"));
+		list.add(new Item("VentNetwork", "Uncertain"));
+		list.add(new Item("VRFNetwork", "SupplyReturn"));
+		list.add(new Item("DomesticWaterNetwork", "Supply"));
+		list.add(new Item("DomesticWaterNetwork", "Bypass"));
+		list.add(new Item("DrainingWaterNetwork", "Discharge"));
+		list.add(new Item("DrainingWaterNetwork", "Bypass"));
+		list.add(new Item("RecycleWaterNetwork", "Supply"));
+		list.add(new Item("RecycleWaterNetwork", "Bypass"));
+		list.add(new Item("DrinkingWaterNetwork", "Supply"));
+		list.add(new Item("DrinkingWaterNetwork", "Bypass"));
+		list.add(new Item("DHWNetwork", "Supply"));
+		list.add(new Item("DHWNetwork", "Bypass"));
+		list.add(new Item("GasNetwork", "Supply"));
+		list.add(new Item("GasNetwork", "Bypass"));
+		list.add(new Item("FireWaterNetwork", "Supply"));
+		list.add(new Item("FireWaterNetwork", "Bypass"));
+		list.add(new Item("FireVentNetwork", "Discharge"));
+		list.add(new Item("WENetwork", "Normal"));
+		list.add(new Item("MechCtrl", "SyCtrl"));
+		list.add(new Item("MechCtrl", "EqCtrl"));
+		list.add(new Item("MechPower", "SyNormal"));
+		list.add(new Item("MechPower", "SyBackup"));
+		list.add(new Item("MechPower", "EqNormal"));
+		list.add(new Item("MechPower", "EqBackup"));
+		list.add(new Item("SensorRelationship", "Ss2Eq"));
+		list.add(new Item("SensorRelationship", "Ss2Sy"));
+		list.add(new Item("SensorRelationship", "Ss2Sp"));
+		list.add(new Item("ValveRelationship", "Vv2Eq"));
+		list.add(new Item("ValveRelationship", "Vv2Sy"));
+		list.add(new Item("EnergySubMeter", "Em2Bd"));
+		list.add(new Item("EnergySubMeter", "Sub2Em"));
+		list.add(new Item("EnergySubMeter", "SubTree"));
+		list.add(new Item("EnergySubMeter", "Br2Sub"));
+		list.add(new Item("EnergySubMeter", "Br2Eq"));
+		list.add(new Item("ScheduleRelationship", "Sch2Pj"));
+		list.add(new Item("ScheduleRelationship", "Sch2Bd"));
+		list.add(new Item("ScheduleRelationship", "Sch2Fl"));
+		list.add(new Item("ScheduleRelationship", "Sch2Sp"));
+		list.add(new Item("ScheduleRelationship", "Sch2Tn"));
+		list.add(new Item("MeteorologyRelationship", "Ms2Pj"));
+		list.add(new Item("TenentInArch", "Tn2Sp"));
+		list.add(new Item("Property2Mech", "Pe2Eq"));
+		list.add(new Item("Property2Mech", "Pe2Ec"));
+		list.add(new Item("PropertyInArch", "Pe2Pj"));
+		list.add(new Item("PropertyInArch", "Pe2Bd"));
+		list.add(new Item("PropertyInArch", "Pe2Fl"));
+		list.add(new Item("PropertyInArch", "Pe2Sh"));
+		list.add(new Item("PropertyInArch", "Pe2Sp"));
+		return list;
+	}
+
+	private static List<Item> getOldMappingList() {
+		List<Item> list = new LinkedList<>();
+		list.add(new Item("ArchSubset", "Bd2Fl", "Subset", "1", "1"));
+		list.add(new Item("ArchSubset", "Bd2Sh", "ShaftandBuilding", "1", "1"));
+		list.add(new Item("ArchSubset", "Bd2Sp", "Subset", "2", "1"));
+		list.add(new Item("ArchSubset", "Fl2Sp", "Subset", "4", "1"));
+		list.add(new Item("ArchSubset", "Sh2Sp", "ShaftandSpace", "1", "1"));
+		list.add(new Item("MechSubset", "Sy2Eq", "SystemEquip", "1", "1"));
+		list.add(new Item("MechSubset", "Eq2Ec", "Subset", "5", "1"));
+		list.add(new Item("SpaceNeighborhood", "None", "SpaceNeighborhood", "1", "1"));
+		list.add(new Item("SpaceNeighborhood", "Door", "SpaceNeighborhood", "2", "1"));
+		list.add(new Item("SpaceNeighborhood", "Window", "SpaceNeighborhood", "3", "1"));
+		list.add(new Item("SpaceNeighborhood", "DoorWindow", "SpaceNeighborhood", "4", "1"));
+		list.add(new Item("SpaceNeighborhood", "Connect", "SpaceNeighborhood", "5", "1"));
+		list.add(new Item("TrafficNetwork", "Normal", "TrafficNetwork", "1", "1"));
+		list.add(new Item("TrafficNetwork", "FFOpen", "TrafficNetwork", "2", "1"));
+		list.add(new Item("TrafficNetwork", "FFClose", "TrafficNetwork", "3", "1"));
+		list.add(new Item("ConvectionNetwork", "Natural", "ConvectionNetwork", "1", "1"));
+		list.add(new Item("ConvectionNetwork", "MixMech", "ConvectionNetwork", "2", "1"));
+		list.add(new Item("RadiationNetwork", "Connect", "RadiationNetwork", "1", "1"));
+		list.add(new Item("RadiationNetwork", "Transparent", "RadiationNetwork", "2", "1"));
+		list.add(new Item("LUDistribution", "Normal", "LUDistribution", "1", "1"));
+		list.add(new Item("LUDistribution", "Backup", "LUDistribution", "2", "1"));
+		list.add(new Item("HUDistribution", "Normal", "HUDistribution", "1", "1"));
+		list.add(new Item("HUDistribution", "Backup", "HUDistribution", "2", "1"));
+		list.add(new Item("ChillWaterLoop", "Supply", "ChillWaterLoop", "1", "1"));
+		list.add(new Item("ChillWaterLoop", "Return", "ChillWaterLoop", "2", "1"));
+		list.add(new Item("ChillWaterLoop", "Bypass", "ChillWaterLoop", "3", "1"));
+		list.add(new Item("ChillWaterLoop", "Fill", "ChillWaterLoop", "4", "1"));
+		list.add(new Item("CoolingWaterLoop", "Supply", "CoolingWaterLoop", "1", "1"));
+		list.add(new Item("CoolingWaterLoop", "Return", "CoolingWaterLoop", "2", "1"));
+		list.add(new Item("CoolingWaterLoop", "Bypass", "CoolingWaterLoop", "3", "1"));
+		list.add(new Item("CoolingWaterLoop", "Fill", "CoolingWaterLoop", "4", "1"));
+		list.add(new Item("HeatWaterLoop", "Supply", "HeatWaterLoop", "1", "1"));
+		list.add(new Item("HeatWaterLoop", "Return", "HeatWaterLoop", "2", "1"));
+		list.add(new Item("HeatWaterLoop", "Bypass", "HeatWaterLoop", "3", "1"));
+		list.add(new Item("HeatWaterLoop", "Fill", "HeatWaterLoop", "4", "1"));
+		list.add(new Item("CondWaterNetwork", "Discharge", "CondWaterNetwork", "1", "1"));
+		list.add(new Item("ACAirNetwork", "Supply", "ACAirNetwork", "1", "1"));
+		list.add(new Item("ACAirNetwork", "Return", "ACAirNetwork", "2", "1"));
+		list.add(new Item("FreshAirNetwork", "Fresh", "FreshAirNetwork", "1", "1"));
+		list.add(new Item("VentNetwork", "Supply", "VentNetwork", "1", "1"));
+		list.add(new Item("VentNetwork", "Discharge", "VentNetwork", "2", "1"));
+		list.add(new Item("VentNetwork", "Uncertain", "VentNetwork", "3", "1"));
+		list.add(new Item("VRFNetwork", "SupplyReturn", "VRFNetwork", "1", "1"));
+		list.add(new Item("DomesticWaterNetwork", "Supply", "SupplyWaterNetwork", "1", "1"));
+		list.add(new Item("DomesticWaterNetwork", "Bypass", "SupplyWaterNetwork", "2", "1"));
+		list.add(new Item("DrainingWaterNetwork", "Discharge", "DrainingWaterNetwork", "1", "1"));
+		list.add(new Item("DrainingWaterNetwork", "Bypass", "DrainingWaterNetwork", "2", "1"));
+		list.add(new Item("RecycleWaterNetwork", "Supply", "RecycleWaterNetwork", "1", "1"));
+		list.add(new Item("RecycleWaterNetwork", "Bypass", "RecycleWaterNetwork", "2", "1"));
+		list.add(new Item("DrinkingWaterNetwork", "Supply", "DrinkingWaterNetwork", "1", "1"));
+		list.add(new Item("DrinkingWaterNetwork", "Bypass", "DrinkingWaterNetwork", "2", "1"));
+		list.add(new Item("DHWNetwork", "Supply", "DHWNetwork", "1", "1"));
+		list.add(new Item("DHWNetwork", "Bypass", "DHWNetwork", "2", "1"));
+		list.add(new Item("GasNetwork", "Supply", "GasNetwork", "1", "1"));
+		list.add(new Item("GasNetwork", "Bypass", "GasNetwork", "2", "1"));
+		list.add(new Item("FireWaterNetwork", "Supply", "FireWaterNetwork", "1", "1"));
+		list.add(new Item("FireWaterNetwork", "Bypass", "FireWaterNetwork", "2", "1"));
+		list.add(new Item("FireVentNetwork", "Discharge", "FireVentNetwork", "1", "1"));
+		list.add(new Item("WENetwork", "Normal", "SensorNetwork", "1", "1"));
+		list.add(new Item("MechInArch", "Eq2Bd", "Subset", "3", "0"));
+		list.add(new Item("MechInArch", "Eq2Fl", "EquipinFloor", "1", "1"));
+
+		list.add(new Item("MechCtrl", "EqCtrl", "ControlRelation", "1", "1"));
+		list.add(new Item("MechPower", "EqNormal", "EquipPower", "1", "1"));
+		list.add(new Item("MechPower", "EqBackup", "EquipPower", "2", "1"));
+
+		list.add(new Item("Property2Mech", "Pe2Eq", "Pe2Eq", "1", "1"));
+		list.add(new Item("PropertyInArch", "Pe2Bd", "Subset", "6", "0"));
+		list.add(new Item("PropertyInArch", "Pe2Fl", "Subset", "7", "0"));
+		list.add(new Item("SubE", "Sub2Sub", "SubE", "1", "1"));
+		list.add(new Item("SubE", "Mt2Sub", "SubE", "2", "1"));
+		list.add(new Item("SubE", "Br2Sub", "SubE", "3", "1"));
+		list.add(new Item("SubE", "Un2Sub", "SubE", "4", "1"));
+		list.add(new Item("SubC", "Sub2Sub", "SubC", "1", "1"));
+		list.add(new Item("SubC", "Mt2Sub", "SubC", "2", "1"));
+		list.add(new Item("SubC", "Br2Sub", "SubC", "3", "1"));
+		list.add(new Item("SubC", "Un2Sub", "SubC", "4", "1"));
+		list.add(new Item("SubH", "Sub2Sub", "SubH", "1", "1"));
+		list.add(new Item("SubH", "Mt2Sub", "SubH", "2", "1"));
+		list.add(new Item("SubH", "Br2Sub", "SubH", "3", "1"));
+		list.add(new Item("SubH", "Un2Sub", "SubH", "4", "1"));
+		list.add(new Item("SubW", "Sub2Sub", "SubW", "1", "1"));
+		list.add(new Item("SubW", "Mt2Sub", "SubW", "2", "1"));
+		list.add(new Item("SubW", "Br2Sub", "SubW", "3", "1"));
+		list.add(new Item("SubW", "Un2Sub", "SubW", "4", "1"));
+		list.add(new Item("SubG", "Sub2Sub", "SubG", "1", "1"));
+		list.add(new Item("SubG", "Mt2Sub", "SubG", "2", "1"));
+		list.add(new Item("SubG", "Br2Sub", "SubG", "3", "1"));
+		list.add(new Item("SubG", "Un2Sub", "SubG", "4", "1"));
+		list.add(new Item("SubF", "Sub2Sub", "SubF", "1", "1"));
+		list.add(new Item("SubF", "Mt2Sub", "SubF", "2", "1"));
+		list.add(new Item("SubF", "Br2Sub", "SubF", "3", "1"));
+		list.add(new Item("SubF", "Un2Sub", "SubF", "4", "1"));
+		list.add(new Item("SubV", "Sub2Sub", "SubV", "1", "1"));
+		list.add(new Item("SubV", "Mt2Sub", "SubV", "2", "1"));
+		list.add(new Item("SubV", "Br2Sub", "SubV", "3", "1"));
+		list.add(new Item("SubV", "Un2Sub", "SubV", "4", "1"));
+		list.add(new Item("EnergyMonitorStructure", "Mt2Br", "EnergyMonitorStructure", "2", "1"));
+		list.add(new Item("EnergyMonitorStructure", "Mt2Un", "EnergyMonitorStructure", "3", "1"));
+		list.add(new Item("EnergyMonitorStructure", "Br2Un", "EnergyMonitorStructure", "4", "1"));
+		list.add(new Item("VRFNetwork", "SupplyReturn", "VRFNetwork", "2", "0"));
+		list.add(new Item("WENetwork", "Normal", "ControlEquipNetwork", "1", "1"));
+		list.add(new Item("PropertyInArch", "Pe2Bd", "Pe2Bd", "1", "1"));
+		list.add(new Item("PropertyInArch", "Pe2Fl", "Pe2Fl", "1", "1"));
+		list.add(new Item("SubE", "Sub2Sub", "EnergyItemTree", "1", "1"));
+		list.add(new Item("EnergyMonitorStructure", "Mt2Br", "EnergyMonitorStructure", "1", "1"));
+		return list;
+	}
+
+	private static List<Item> getOldMappingListWithRelValue(){
+		List<Item> list = new LinkedList<>();
+		list.add(new Item("EquipGroup", "Eq2Eq"));
+		list.add(new Item("MechInArch", "Eq2Sp", "EquipinSpace", "1", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "EquipforSpace", "1", "1"));
+
+		list.add(new Item("MechInArch", "Eq2Sp", "PowerSupplyZone", "EquipinSpace", "100", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "LightingZone", "EquipinSpace", "200", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "NetworkZone", "EquipinSpace", "300", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "AirConditioningZone", "EquipinSpace", "400", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "HeatingZone", "EquipinSpace", "500", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "CleanZone", "EquipinSpace", "600", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "DomesticWaterSupplyZone", "EquipinSpace", "700", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "FireZone", "EquipinSpace", "800", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "SecurityZone", "EquipinSpace", "900", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "TenantZone", "EquipinSpace", "1000", "1"));
+		list.add(new Item("MechInArch", "Eq2Sp", "FunctionZone", "EquipinSpace", "1100", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "PowerSupplyZone", "EquipforSpace", "100", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "LightingZone", "EquipforSpace", "200", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "NetworkZone", "EquipforSpace", "300", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "AirConditioningZone", "EquipforSpace", "400", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "HeatingZone", "EquipforSpace", "500", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "CleanZone", "EquipforSpace", "600", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "DomesticWaterSupplyZone", "EquipforSpace", "700", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "FireZone", "EquipforSpace", "800", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "SecurityZone", "EquipforSpace", "900", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "TenantZone", "EquipforSpace", "1000", "1"));
+		list.add(new Item("MechForArch", "Eq2Sp", "FunctionZone", "EquipforSpace", "1100", "1"));
+		return list;
+	}
+
+	public static Item getMapping(String graph, String relCode) {
+		for (Item mapping : mappings) {
+			if (mapping.oldGraph.equals(graph) && (mapping.oldRelcode.equalsIgnoreCase(relCode))) {
+				return mapping;
+			}
+		}
+		return null;
+	}
+
+	@Getter
+	@Setter
+	public static class Item {
+		private String newGraph;
+		private String newRelcode;
+		private String newRelValue;
+		private String oldGraph;
+		private String oldRelcode;
+		private Boolean same;
+
+		public Item(String newGraph, String newRelcode) {
+			this(newGraph, newRelcode, newGraph, newRelcode, "1");
+		}
+
+		public Item(String newGraph, String newRelcode, String oldGraph, String oldRelcode, String same) {
+			this(newGraph, newRelcode, null, oldGraph, oldRelcode, same);
+		}
+
+		public Item(String newGraph, String newRelcode, String newRelValue, String oldGraph, String oldRelcode, String same) {
+			this.newGraph = newGraph;
+			this.newRelcode = newRelcode;
+			this.newRelValue = newRelValue;
+			this.oldGraph = oldGraph;
+			this.oldRelcode = oldRelcode;
+			this.same = "1".equalsIgnoreCase(same);
+		}
+	}
+
+
+}

+ 395 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/RwdTransUtils.java

@@ -0,0 +1,395 @@
+package com.persagy.dmp.admin.service.trans;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.common.criteria.JacksonCriteria;
+import com.persagy.common.json.JacksonMapper;
+import com.persagy.dmp.admin.entity.TransObjectInfo;
+import com.persagy.dmp.admin.repository.TransObjectInfoRepository;
+import com.persagy.dmp.common.http.HttpUtils;
+import com.persagy.dmp.rwd.enums.FuncidCategory;
+import com.persagy.dmp.rwd.funcid.parse.parser.InfoCodeParser;
+import com.persagy.dmp.rwd.funcid.parse.parser.InfoCodeParserFactory;
+import com.persagy.dmp.rwd.funcid.parse.parser.ParserContext;
+import com.persagy.dmp.rwd.model.FuncidDefModel;
+import com.persagy.dmp.rwd.model.RelationInstanceModel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+
+/**
+ * @author: yaoll
+ * @date: 2021-01-04
+ * @verison: 1.0
+ */
+@Slf4j
+@Component
+public class RwdTransUtils {
+
+	@Autowired
+	private HttpUtils httpUtils;
+
+	@Value("${persagy.dmp.server}")
+	private String dmpServer;
+
+	@Autowired
+	private StringRedisTemplate redis;
+
+	@Autowired
+	private InfoCodeParserFactory infoCodeParserFactory;
+
+	@Autowired
+	private TransObjectInfoRepository objectInfoRepository;
+
+	// 初始化类型
+	public void initClass(TransObjectContext ctx) {
+		ArrayNode classes = queryClass(ctx);
+		ctx.getObjTypeMapping().put("Bd", "building");
+		ctx.getObjTypeMapping().put("Fl", "floor");
+		ctx.getObjTypeMapping().put("Sp", "space");
+		ctx.getObjTypeMapping().put("Eq", "equipment");
+		ctx.getObjTypeMapping().put("Ec", "component");
+		ctx.getObjTypeMapping().put("Sh", "shaft");
+
+		ctx.getClassCodeMapping().put("Pj", "project");
+		ctx.getClassCodeMapping().put("Bd", "building");
+		ctx.getClassCodeMapping().put("Fl", "floor");
+		ctx.getClassCodeMapping().put("Sy", "system");
+		ctx.getClassCodeMapping().put("Sh", "shaft");
+
+		for (JsonNode cla : classes) {
+			ObjectNode obj = (ObjectNode) cla;
+			String parentCode = JacksonMapper.getString(obj, "parentCode", "");
+			String code = JacksonMapper.getString(obj, "code");
+			if ("equipment".equals(parentCode) || "system".equals(parentCode) || "component".equals(parentCode)) {
+				ctx.getClassCodeMapping().put(code.substring(2), code);
+			} else if ("space".equals(parentCode)) {
+				ctx.getClassCodeMapping().put(code, code);
+			}
+		}
+	}
+
+	private ArrayNode queryClass(TransObjectContext ctx) {
+		String url = dmpServer + "/rwd/def/class?" + getQueryString(ctx);
+		JacksonCriteria criteria = JacksonCriteria.newInstance();
+		HttpUtils.HttpResult result = httpUtils.post(url, JacksonMapper.toSimpleJson(criteria), 30000);
+		if (result.success()) {
+			String content = result.getContent();
+			ObjectNode object = JacksonMapper.toObject(content, ObjectNode.class);
+			ArrayNode data = JacksonMapper.getArray(object, "data");
+			return data;
+		} else {
+			log.error("query class error: {}", result.getContent());
+		}
+		return JsonNodeFactory.instance.arrayNode();
+	}
+
+	// 初始化信息点
+	public void initFuncidCache(TransObjectContext ctx, String classCode) {
+		if (!ctx.getFuncidModelCache().containsKey(classCode)) {
+			Map<String, FuncidDefModel> funcidCache = new HashMap<>();
+			String url = dmpServer + "/rwd/def/funcid?" + getQueryString(ctx);
+			JacksonCriteria criteria = JacksonCriteria.newInstance();
+			criteria.add("classCode", classCode);
+			HttpUtils.HttpResult result = httpUtils.post(url, JacksonMapper.toSimpleJson(criteria), 300000);
+			if (result.success()) {
+				String content = result.getContent();
+				ObjectNode object = JacksonMapper.toObject(content, ObjectNode.class);
+				ArrayNode data = JacksonMapper.getArray(object, "data", JsonNodeFactory.instance.arrayNode());
+
+				for (JsonNode datum : data) {
+					ObjectNode funcJson = (ObjectNode) datum;
+					FuncidDefModel funcidDefModel = JacksonMapper.toObject(funcJson.toString(), FuncidDefModel.class);
+					funcidCache.put(funcidDefModel.getOrigCode(), funcidDefModel);
+				}
+			}
+			ctx.getFuncidModelCache().put(classCode, funcidCache);
+		}
+	}
+
+	// 查询数据平台数据
+	public List<ObjectNode> queryObject(TransObjectContext context, String types) {
+		String url = context.getServer() + "/data-platform-3/object/subset_query?debug&projectId=" + context.getProjectId() + "&secret=" + context.getSecret();
+		String param = "{\"customInfo\": true, \"valid\": null, \"linkInfos\": false, \"criteria\":{\"type\": [ \"" + types + "\"]}}";
+		HttpUtils.HttpResult post = httpUtils.post(url, param, 3600 * 1000);
+		if (!post.success()) {
+			writeInfo(context, "error", "查询对象" + JacksonMapper.toSimpleJson(types) + "失败");
+			return null;
+		}
+		String content = post.getContent();
+		ObjectNode objectNode = JacksonMapper.toObject(content, ObjectNode.class);
+		String result = JacksonMapper.getString(objectNode, "Result");
+		if (!"success".equalsIgnoreCase(result)) {
+			writeInfo(context, "error", "查询对象" + JacksonMapper.toSimpleJson(types) + "失败:" + JacksonMapper.getString(objectNode, "ResultMsg"));
+			return null;
+		}
+		ArrayNode array = JacksonMapper.getArray(objectNode, "Content", JsonNodeFactory.instance.arrayNode());
+
+		List<ObjectNode> objects = new LinkedList<>();
+		for (JsonNode jsonNode : array) {
+			ObjectNode obj = (ObjectNode) jsonNode;
+			ObjectNode infos = JacksonMapper.getObject(obj, "infos");
+			infos.put("id", JacksonMapper.getString(obj, "id"));
+//			infos.put("category", JacksonMapper.getString(obj, "category"));
+			if (obj.has("businessType")) {
+				infos.put("businessType", JacksonMapper.getString(obj, "businessType"));
+			}
+			infos.put("create_time", JacksonMapper.getString(obj, "create_time"));
+			objects.add(infos);
+		}
+		return objects;
+	}
+
+	private Set<String> baseInfoCodes = new HashSet<>(Arrays.asList("id", "classCode", "create_time"));
+
+	// 转换为数据中台数据格式
+	public List<ObjectNode> toDmpObject(TransObjectContext ctx, List<ObjectNode> list, String objType, String classCode) {
+		List<ObjectNode> objects = new ArrayList<>(list.size());
+		for (ObjectNode objectNode : list) {
+			String id = JacksonMapper.getString(objectNode, "id");
+			String createTime = JacksonMapper.getString(objectNode, "create_time");
+			ObjectNode obj = JsonNodeFactory.instance.objectNode();
+			objects.add(obj);
+
+			obj.put("id", id);
+			obj.put("objType", objType);
+			obj.put("classCode", objectNode.has("classCode") ? JacksonMapper.getString(objectNode, "classCode") : classCode);
+			obj.put("createTime", createTime);
+			Iterator<String> iterator = objectNode.fieldNames();
+			while (iterator.hasNext()) {
+				String origInfoCode = iterator.next();
+				if (baseInfoCodes.contains(origInfoCode)) {
+					continue;
+				}
+				JsonNode infoValue = objectNode.get(origInfoCode);
+				// 基本字段
+				if (TransUtils.baseColumnMapping.containsKey(origInfoCode)) {
+					obj.put(TransUtils.baseColumnMapping.get(origInfoCode), infoValue.asText());
+					continue;
+				}
+
+				Map<String, FuncidDefModel> funcidCache = ctx.getFuncidModelCache().get(classCode);
+				FuncidDefModel funcidDefModel = funcidCache.get(origInfoCode);
+				if (funcidDefModel == null) {
+					writeInfo(ctx, "error", classCode, "信息点不存在", id, origInfoCode, infoValue.isTextual() ? infoValue.asText() : infoValue.toString());
+					continue;
+				}
+				if (funcidDefModel.getCategory() == FuncidCategory.STATIC) {
+					Boolean isMultiple = funcidDefModel.getIsMultiple();
+					Boolean isRegion = funcidDefModel.getIsRegion();
+					InfoCodeParser parser = infoCodeParserFactory.getParser(funcidDefModel.getDataType());
+					ParserContext parserContext = new ParserContext(funcidDefModel, objectNode.get(origInfoCode));
+					parser.checkValue(parserContext);
+					if (parserContext.isHasError()) {
+						writeInfo(ctx, "error", classCode, parserContext.getError().toString(), id, origInfoCode, infoValue.isTextual() ? infoValue.asText() : infoValue.toString());
+					} else {
+						if (isRegion) {
+							if (isMultiple) {
+								obj.putPOJO(funcidDefModel.getCode(), parserContext.getRegionArray());
+							} else {
+								obj.putPOJO(funcidDefModel.getCode(), parserContext.getRegionValue());
+							}
+						} else {
+							if (isMultiple) {
+								obj.putPOJO(funcidDefModel.getCode(), parserContext.getArrayValue());
+							} else {
+								obj.putPOJO(funcidDefModel.getCode(), parserContext.getValue());
+							}
+						}
+					}
+				} else {
+					// 动态信息点
+					obj.put(funcidDefModel.getCode(), infoValue.asText());
+				}
+			}
+		}
+		return objects;
+	}
+
+	// 保存到数据中台
+	public void save(TransObjectContext ctx, List<ObjectNode> objects, String type) {
+		int begin = 0;
+		while (begin < objects.size()) {
+			int end = begin + 10000;
+			if (end > objects.size()) {
+				end = objects.size();
+			}
+			List<ObjectNode> objectNodes = objects.subList(begin, end);
+			String url = dmpServer + "/rwd/instance/object/create?" + getQueryString(ctx);
+			HttpUtils.HttpResult response = httpUtils.post(url, JacksonMapper.toSimpleJson(objectNodes), 3600000);
+			if (response.success()) {
+				writeInfo(ctx, "success", "对象保存到中台: 类型: " + type + ", 数量: " + objectNodes.size());
+			} else {
+				writeInfo(ctx, "error", "保存到中台时出错: 类型: " + type + ", 信息: " + response.getContent());
+			}
+			begin = end;
+		}
+	}
+
+	// 迁移关系数据
+	public void transRelation(TransObjectContext ctx) {
+
+		writeInfo(ctx, "success", "迁移关系数据开始");
+		// 查询图实例
+		String url = ctx.getServer() + "/data-platform-3/relation/graph_instance/query?projectId=" + ctx.getProjectId() + "&secret" + ctx.getSecret();
+		String requestBody = "{\"criteria\":{}}";
+		HttpUtils.HttpResult post = httpUtils.post(url, requestBody, 300 * 1000);
+		if (!post.success()) {
+			writeInfo(ctx, "error", "查询图实例失败: " + post.getContent());
+			return;
+		}
+		String content = post.getContent();
+		ObjectNode objectNode = JacksonMapper.toObject(content, ObjectNode.class);
+		String result = JacksonMapper.getString(objectNode, "Result");
+		if (!"success".equalsIgnoreCase(result)) {
+			writeInfo(ctx, "error", "查询图实例失败: " + JacksonMapper.getString(objectNode, "ResultMsg"));
+			return;
+		}
+
+		// 遍历图实例,查询关系,迁移关系
+		ArrayNode array = JacksonMapper.getArray(objectNode, "Content", JsonNodeFactory.instance.arrayNode());
+		Set<String> sets = new HashSet<>();
+		for (JsonNode jsonNode : array) {
+			ObjectNode item = (ObjectNode) jsonNode;
+			String graphId = JacksonMapper.getString(item, "graph_id");
+			if (graphId == null) {
+				continue;
+			}
+			sets.add(graphId);
+		}
+		for (String graphId : sets) {
+			transRelationByGraphId(ctx, graphId);
+		}
+		writeInfo(ctx, "success", "迁移关系数据完成");
+	}
+
+	private void transRelationByGraphId(TransObjectContext ctx, String graphId) {
+		String url = ctx.getServer() + "/data-platform-3/relation/query?projectId=" + ctx.getProjectId() + "&secret" + ctx.getSecret();
+		String requestBody = "{\"criteria\":{\"graph_id\":\"" + graphId + "\"}}";
+		HttpUtils.HttpResult post = httpUtils.post(url, requestBody, 300 * 1000);
+		if (!post.success()) {
+			writeInfo(ctx, "error", "查询关系数据失败: " + graphId + ":" + post.getContent());
+			return;
+		}
+		String content = post.getContent();
+		ObjectNode objectNode = JacksonMapper.toObject(content, ObjectNode.class);
+		String result = JacksonMapper.getString(objectNode, "Result");
+		if (!"success".equalsIgnoreCase(result)) {
+			writeInfo(ctx, "error", "查询关系数据失败: " + graphId + ":" + JacksonMapper.getString(objectNode, "ResultMsg"));
+			return;
+		}
+
+		ArrayNode array = JacksonMapper.getArray(objectNode, "Content", JsonNodeFactory.instance.arrayNode());
+		List<RelationInstanceModel> relationInstanceModelList = new ArrayList<>();
+		for (JsonNode jsonNode : array) {
+			ObjectNode item = (ObjectNode) jsonNode;
+			String relType = JacksonMapper.getString(item, "rel_type");
+			String objFrom = JacksonMapper.getString(item, "from_id");
+			String objTo = JacksonMapper.getString(item, "to_id");
+
+			String graphCode = graphId.substring(2, graphId.length() - 3);
+			GraphMapping.Item mapping = GraphMapping.getMapping(graphCode, relType);
+			if (mapping != null) {
+				RelationInstanceModel relation = new RelationInstanceModel();
+				relation.setGraphCode(mapping.getNewGraph());
+				relation.setRelCode(mapping.getNewRelcode());
+				if (mapping.getSame()) {
+					relation.setObjFrom(objFrom);
+					relation.setObjTo(objTo);
+				} else {
+					relation.setObjFrom(objTo);
+					relation.setObjTo(objFrom);
+				}
+				relationInstanceModelList.add(relation);
+			} else {
+				item.put("error", "图类型或边类型错误");
+				writeInfo(ctx, "error", item.toString());
+			}
+		}
+		url = dmpServer + "/rwd/instance/relation/create?" + getQueryString(ctx);
+		HttpUtils.HttpResult response = httpUtils.post(url, JacksonMapper.toSimpleJson(relationInstanceModelList), 3600000);
+		if (response.success()) {
+			writeInfo(ctx, "success", "迁移关系数据到中台成功: 图实例: " + graphId + ", 数量: " + relationInstanceModelList.size());
+		} else {
+			writeInfo(ctx, "error", "迁移关系数据到中台失败: 图实例: " + graphId + ", 信息: " + response.getContent());
+		}
+	}
+
+	// 迁移失效数据
+	public void transInvalidObject(TransObjectContext context) {
+		writeInfo(context, "success", "处理失效对象开始");
+		transInvalidObject(context, "Bd");// 建筑
+		transInvalidObject(context, "Fl");//楼层
+		transInvalidObject(context, "Sp");// 空间
+		transInvalidObject(context, "Sy");// 系统
+		transInvalidObject(context, "Eq");// 设备
+		transInvalidObject(context, "Ec");// 部件
+		transInvalidObject(context, "Sh");// 竖井
+		writeInfo(context, "success", "处理失效对象完成");
+	}
+
+	// 迁移失效数据
+	private void transInvalidObject(TransObjectContext context, String type) {
+		String url = context.getServer() + "/data-platform-3/object/subset_query?debug&projectId=" + context.getProjectId() + "&secret=" + context.getSecret();
+		String requestBody = "{\"customInfo\":true,\"valid\":false,\"criteria\":{\"type\":[\"" + type + "\"]},\"returnInfos\":[]}";
+		HttpUtils.HttpResult post = httpUtils.post(url, requestBody, 3600 * 1000);
+		if (!post.success()) {
+			writeInfo(context, "error", "查询失效对象失败: " + type);
+			return;
+		}
+		String content = post.getContent();
+		ObjectNode objectNode = JacksonMapper.toObject(content, ObjectNode.class);
+		String result = JacksonMapper.getString(objectNode, "Result");
+		if (!"success".equalsIgnoreCase(result)) {
+			writeInfo(context, "error", "查询失效对象失败: " + type + ",  " + JacksonMapper.getString(objectNode, "ResultMsg"));
+			return;
+		}
+
+		ArrayNode array = JacksonMapper.getArray(objectNode, "Content", JsonNodeFactory.instance.arrayNode());
+		List<String> ids = new LinkedList<>();
+		for (JsonNode jsonNode : array) {
+			ObjectNode item = (ObjectNode) jsonNode;
+			String id = JacksonMapper.getString(item, "id");
+			if (id != null) {
+				ids.add(id);
+			}
+		}
+		if (ids.size() > 0) {
+			url = dmpServer + "/rwd/instance/object/delete?" + getQueryString(context);
+			HttpUtils.HttpResult resp = httpUtils.post(url, JacksonMapper.toSimpleJson(ids), 3600 * 1000);
+			writeInfo(context, "success", "处理失效对象成功: " + type + ", " + ids.size() + ", " + resp.getContent());
+		}
+	}
+
+	private String getQueryString(TransObjectContext context) {
+		return "groupCode=" + context.getGroupCode() + "&projectId=" + context.getProjectId() + "&appId=" + context.getAppId() + "&userId=" + context.getUserId();
+	}
+
+	public void writeInfo(TransObjectContext ctx, String type, String msg) {
+		writeInfo(ctx, type, null, msg, null, null, null);
+	}
+
+	public void writeInfo(TransObjectContext ctx, String type, String classCode, String msg, String objectId, String infoCode, String value) {
+		TransObjectInfo info = new TransObjectInfo();
+		info.setProjectId(ctx.getProjectId());
+		info.setType(type);
+		info.setClassCode(classCode);
+		info.setObjectId(objectId);
+		info.setInfoCode(infoCode);
+		info.setInfoCodeValue(value);
+		info.setMessage(msg);
+		ctx.getLogs().add(info);
+
+		if (!"error".equalsIgnoreCase(type) || ctx.getLogs().size() == TransObjectContext.LOGS_CACHE_SIZE) {
+			objectInfoRepository.saveAll(ctx.getLogs());
+			ctx.getLogs().clear();
+		}
+	}
+
+}

+ 42 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/TransObjectContext.java

@@ -0,0 +1,42 @@
+package com.persagy.dmp.admin.service.trans;
+
+import com.persagy.dmp.admin.entity.TransObjectInfo;
+import com.persagy.dmp.rwd.model.FuncidDefModel;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-30
+ * @verison: 1.0
+ */
+@Data
+public class TransObjectContext {
+
+	public static final Integer LOGS_CACHE_SIZE = 1000;
+
+	private String server;
+
+	private String secret;
+
+	private String groupCode;
+
+	private String projectId;
+
+	private String appId = "datautils";
+
+	private String userId = "system";
+
+	private Map<String, String> classCodeMapping = new HashMap<>();
+
+	private Map<String, String> objTypeMapping = new HashMap<>();
+
+	private Map<String, Map<String, FuncidDefModel>> funcidModelCache = new HashMap<>(); // key = classCode
+
+	private List<TransObjectInfo> logs = new ArrayList<>(LOGS_CACHE_SIZE);
+
+}

+ 74 - 0
dmp-admin/src/main/java/com/persagy/dmp/admin/service/trans/TransUtils.java

@@ -0,0 +1,74 @@
+package com.persagy.dmp.admin.service.trans;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: yaoll
+ * @date: 2020-12-31
+ * @verison: 1.0
+ */
+public class TransUtils {
+
+
+	public static final Map<String, String> baseColumnMapping = new HashMap<>();
+
+	static {
+		baseColumnMapping.put("ProjID", "id");
+		baseColumnMapping.put("ProjName", "name");
+		baseColumnMapping.put("ProjLocalID", "localId");
+		baseColumnMapping.put("ProjLocalName", "localName");
+		baseColumnMapping.put("BuildID", "id");
+		baseColumnMapping.put("BuildName", "name");
+		baseColumnMapping.put("BuildLocalID", "localId");
+		baseColumnMapping.put("BuildLocalName", "localName");
+		baseColumnMapping.put("FloorID", "id");
+		baseColumnMapping.put("FloorName", "name");
+		baseColumnMapping.put("FloorLocalID", "localId");
+		baseColumnMapping.put("FloorLocalName", "localName");
+		baseColumnMapping.put("RoomID", "id");
+		baseColumnMapping.put("RoomName", "name");
+		baseColumnMapping.put("RoomLocalID", "localId");
+		baseColumnMapping.put("RoomLocalName", "localName");
+		baseColumnMapping.put("ShaftID", "id");
+		baseColumnMapping.put("ShaftName", "name");
+		baseColumnMapping.put("ShaftLocalID", "localId");
+		baseColumnMapping.put("ShaftLocalName", "localName");
+		baseColumnMapping.put("SysID", "id");
+		baseColumnMapping.put("SysName", "name");
+		baseColumnMapping.put("SysLocalID", "localId");
+		baseColumnMapping.put("SysLocalName", "localName");
+		baseColumnMapping.put("EquipID", "id");
+		baseColumnMapping.put("EquipName", "name");
+		baseColumnMapping.put("EquipLocalID", "localId");
+		baseColumnMapping.put("EquipLocalName", "localName");
+		baseColumnMapping.put("ToolID", "id");
+		baseColumnMapping.put("ToolName", "name");
+		baseColumnMapping.put("ToolLocalID", "localId");
+		baseColumnMapping.put("ToolLocalName", "localName");
+		baseColumnMapping.put("ConsumID", "id");
+		baseColumnMapping.put("ConsumName", "name");
+		baseColumnMapping.put("ConsumLocalID", "localId");
+		baseColumnMapping.put("ConsumLocalName", "localName");
+		baseColumnMapping.put("ECModelID", "id");
+		baseColumnMapping.put("ECModelName", "name");
+		baseColumnMapping.put("ECModelLocalID", "localId");
+		baseColumnMapping.put("ECModelLocalName", "localName");
+		baseColumnMapping.put("SubentryID", "id");
+		baseColumnMapping.put("SubentryName", "name");
+		baseColumnMapping.put("SubentryLocalID", "localId");
+		baseColumnMapping.put("SubentryLocalName", "localName");
+		baseColumnMapping.put("BranchID", "id");
+		baseColumnMapping.put("BranchName", "name");
+		baseColumnMapping.put("BranchLocalID", "localId");
+		baseColumnMapping.put("BranchLocalName", "localName");
+		baseColumnMapping.put("BeaconID", "id");
+		baseColumnMapping.put("BeaconlName", "name");
+		baseColumnMapping.put("BeaconLocalID", "localId");
+		baseColumnMapping.put("BeaconLocalName", "localName");
+		baseColumnMapping.put("TenantID", "id");
+		baseColumnMapping.put("TenantName", "name");
+		baseColumnMapping.put("TenantLocalID", "localId");
+		baseColumnMapping.put("TenantLocalName", "localName");
+	}
+}

+ 40 - 0
dmp-admin/src/main/resources/application.yml

@@ -0,0 +1,40 @@
+server:
+  port: 8839
+persagy:
+  dmp:
+    server: http://192.168.64.18:9930
+#    server: http://39.102.40.239:9970
+    exchange: exchange-dmp
+spring:
+  application:
+    name: dmp-admin
+  profiles:
+    active:
+    - dev,log-dev
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://192.168.64.15:9934/dmp_admin?useUnicode=true&characterEncoding=utf-8&mysqlEncoding=utf8&useSSL=false
+    username: root
+    password: brzj123456
+    type: com.alibaba.druid.pool.DruidDataSource
+  jpa:
+    show-sql: true
+    hibernate:
+      ddl-auto: none
+  rabbitmq:
+    host: 192.168.64.15
+    port: 9936
+    username: admin
+    password: brzj123456
+    virtrul-host: /test
+  redis:
+    database: 10
+    host: 192.168.64.15
+    password: brzj123456
+    port: 9944
+    timeout: 6000
+    pool:
+      max-idle: 200
+      min-idle: 5
+      max-active: 1024
+      max-wait: 1000

+ 55 - 0
dmp-admin/src/main/resources/logback-spring.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+
+    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+    <property name="log_pattern" value="%-30thread %d{yyyyMMdd HH:mm:ss.SSS} %-5level %logger{140} - %msg%n"/>
+    <property name="app_name" value="admin"/>
+    <springProperty scope="context" name="log_path" source="persagy.log.path"/>
+    <property name="log_file" value="${log_path}/${app_name}"/>
+    <contextName>${app_name}</contextName>
+
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>${log_pattern}</pattern>
+        </layout>
+    </appender>
+
+    <!-- 日志文件 -->
+    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${log_file}-%d{yyyyMMdd}.log</fileNamePattern>
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log_pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="org.hibernate" level="INFO"/>
+    <logger name="org.springframework" level="INFO"/>
+    <logger name="com.netflix" level="WARN"/>
+    <logger name="org.apache.http" level="INFO"/>
+
+    <springProfile name="log-dev">
+        <logger name="org.hibernate.SQL" level="DEBUG"/>
+        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
+        <root level="info">
+            <appender-ref ref="stdout"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="log-test">
+        <logger name="org.hibernate.SQL" level="DEBUG"/>
+        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
+        <root level="info">
+            <appender-ref ref="file"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="log-prod">
+        <root level="info">
+            <appender-ref ref="file"/>
+        </root>
+    </springProfile>
+
+</configuration> 

+ 77 - 0
dmp-admin/src/test/java/com/persagy/dmp/admin/service/TestGraph.java

@@ -0,0 +1,77 @@
+package com.persagy.dmp.admin.service;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.persagy.common.json.JacksonMapper;
+import com.persagy.dmp.admin.service.trans.GraphMapping;
+import com.persagy.dmp.common.http.HttpUtils;
+import com.persagy.dmp.rwd.model.RelationInstanceModel;
+import org.junit.Test;
+
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author: yaoll
+ * @date: 2021-01-05
+ * @verison: 1.0
+ */
+public class TestGraph {
+
+
+	@Test
+	public void test1() {
+		String graphId = "GtSubset001";
+		System.out.println(graphId.substring(2, graphId.length() -3));
+	}
+
+
+	@Test
+	public void test2() throws Exception {
+
+		String file = "/Users/devsaga/workspace/sublime/relation.txt";
+		PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file)));
+		String graphId = "GtSubset001";
+		HttpUtils httpUtils = new HttpUtils();
+		String url = "http://39.97.179.199:8888/data-platform-3/relation/query?projectId=Pj1101050029&secret=saga123456";
+		String requestBody = "{\"criteria\":{\"graph_id\":\"" + graphId + "\"}}";
+		HttpUtils.HttpResult post = httpUtils.post(url, requestBody, 300 * 1000);
+
+		String content = post.getContent();
+		ObjectNode objectNode = JacksonMapper.toObject(content, ObjectNode.class);
+
+		ArrayNode array = JacksonMapper.getArray(objectNode, "Content", JsonNodeFactory.instance.arrayNode());
+		List<RelationInstanceModel> relationInstanceModelList = new ArrayList<>();
+		Set<String> errors = new HashSet<>();
+		int i = 0;
+		for (JsonNode jsonNode : array) {
+			ObjectNode item = (ObjectNode) jsonNode;
+			String relType = JacksonMapper.getString(item, "rel_type");
+			String objFrom = JacksonMapper.getString(item, "from_id");
+			String objTo = JacksonMapper.getString(item, "to_id");
+
+			String graphCode = graphId.substring(2, graphId.length() - 3);
+			GraphMapping.Item mapping = GraphMapping.getMapping(graphCode, relType);
+			if (mapping == null) {
+				errors.add(graphCode + "-" + relType);
+			}
+			writer.println(jsonNode.toString());
+			if (i % 1000 == 0) {
+				writer.flush();
+			}
+		}
+		writer.flush();
+		writer.close();
+		for (String error : errors) {
+			System.out.println(error);
+		}
+
+	}
+}

+ 37 - 0
dmp-admin/src/test/java/com/persagy/dmp/admin/service/trans/TransObjectInfoServiceTest.java

@@ -0,0 +1,37 @@
+package com.persagy.dmp.admin.service.trans;
+
+import com.persagy.dmp.admin.service.DmpTransObjectService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author: yaoll
+ * @date: 2021-01-05
+ * @verison: 1.0
+ */
+@ActiveProfiles(profiles = {"dev", "log-dev"})
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class TransObjectInfoServiceTest {
+
+	@Autowired
+	private DmpTransObjectService service;
+
+
+	@Test
+	public void test1() {
+
+		TransObjectContext ctx = new TransObjectContext();
+		ctx.setGroupCode("WD");
+		ctx.setProjectId("Pj1101050029");
+		ctx.setAppId("datautils");
+		ctx.setUserId("system");
+		ctx.setServer("http://39.97.179.199:8888");
+		ctx.setSecret("saga123456");
+		service.transRelation(ctx);
+	}
+}

+ 1 - 0
pom.xml

@@ -18,6 +18,7 @@
         <module>dmp-rwd-datautils</module>
         <module>dmp-task</module>
         <module>dmp-alarm</module>
+        <module>dmp-admin</module>
     </modules>
 
     <packaging>pom</packaging>