Pārlūkot izejas kodu

********labsl VS meiku***********************************
首次提交

zhangweixin 4 gadi atpakaļ
revīzija
954b631b4b
76 mainītis faili ar 5374 papildinājumiem un 0 dzēšanām
  1. 6 0
      .gitignore
  2. 62 0
      build.gradle
  3. 102 0
      labsl/build.gradle
  4. 77 0
      labsl/src/main/kotlin/com/persagy/labsl/LaBSLApp.kt
  5. 79 0
      labsl/src/main/kotlin/com/persagy/labsl/Swagger2Config.kt
  6. 140 0
      labsl/src/main/kotlin/com/persagy/labsl/Swagger3Config.kt
  7. 46 0
      labsl/src/main/kotlin/com/persagy/labsl/WebMvcConfg.kt
  8. 37 0
      labsl/src/main/kotlin/com/persagy/labsl/controller/GraphCategoryController.kt
  9. 192 0
      labsl/src/main/kotlin/com/persagy/labsl/controller/GraphController.kt
  10. 76 0
      labsl/src/main/kotlin/com/persagy/labsl/controller/MarkersController.kt
  11. 76 0
      labsl/src/main/kotlin/com/persagy/labsl/controller/NodeController.kt
  12. 94 0
      labsl/src/main/kotlin/com/persagy/labsl/controller/PictureController.kt
  13. 76 0
      labsl/src/main/kotlin/com/persagy/labsl/controller/RelationController.kt
  14. 57 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Anchor.kt
  15. 48 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/AttachObjectIds.kt
  16. 24 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Elements.kt
  17. 110 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Graph.kt
  18. 44 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/GraphCategory.kt
  19. 80 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Markers.kt
  20. 107 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Node.kt
  21. 25 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Pos.kt
  22. 91 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Relation.kt
  23. 21 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/Size.kt
  24. 19 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/auxiliary/CategoryCode.kt
  25. 33 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pic/Picture.kt
  26. 16 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/AnchorPub.kt
  27. 49 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/AttachObjectIdsPub.kt
  28. 24 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/ElementsPub.kt
  29. 110 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/GraphPub.kt
  30. 16 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/MarkersPub.kt
  31. 108 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/NodePub.kt
  32. 16 0
      labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/RelationPub.kt
  33. 17 0
      labsl/src/main/kotlin/com/persagy/labsl/models/request/GraphCategoryRequest.kt
  34. 32 0
      labsl/src/main/kotlin/com/persagy/labsl/models/response/SCommonResponse.kt
  35. 13 0
      labsl/src/main/kotlin/com/persagy/labsl/services/AnchorService.kt
  36. 15 0
      labsl/src/main/kotlin/com/persagy/labsl/services/AttachObjectIdsServices.kt
  37. 41 0
      labsl/src/main/kotlin/com/persagy/labsl/services/CustomService.kt
  38. 163 0
      labsl/src/main/kotlin/com/persagy/labsl/services/GraphCategoryService.kt
  39. 864 0
      labsl/src/main/kotlin/com/persagy/labsl/services/GraphService.kt
  40. 120 0
      labsl/src/main/kotlin/com/persagy/labsl/services/MarkersService.kt
  41. 132 0
      labsl/src/main/kotlin/com/persagy/labsl/services/NodeService.kt
  42. 133 0
      labsl/src/main/kotlin/com/persagy/labsl/services/RelationService.kt
  43. 26 0
      labsl/src/main/kotlin/com/persagy/labsl/services/mappers/CustomMapper.kt
  44. 21 0
      labsl/src/main/kotlin/com/persagy/labsl/services/pic/PictureService.kt
  45. 12 0
      labsl/src/main/kotlin/com/persagy/labsl/services/pub/AnchorPubService.kt
  46. 14 0
      labsl/src/main/kotlin/com/persagy/labsl/services/pub/GraphPubService.kt
  47. 236 0
      labsl/src/main/kotlin/com/persagy/labsl/utils/IdUtils.kt
  48. 98 0
      labsl/src/main/kotlin/com/persagy/labsl/utils/LoggerUtils.kt
  49. 18 0
      labsl/src/main/resources/application-dev.yml
  50. 17 0
      labsl/src/main/resources/application-prod.yml
  51. 71 0
      labsl/src/main/resources/application.yml
  52. 38 0
      labsl/src/main/resources/logback-spring.xml
  53. 17 0
      labsl/src/test/kotlin/com/persagy/server/test/base/CaseBase.kt
  54. 28 0
      labsl/src/test/kotlin/com/persagy/server/test/services/GraphServiceTest.kt
  55. 108 0
      meiku/build.gradle
  56. 78 0
      meiku/src/main/kotlin/com/persagy/meiku/MeiKuApp.kt
  57. 141 0
      meiku/src/main/kotlin/com/persagy/meiku/Swagger3Config.kt
  58. 46 0
      meiku/src/main/kotlin/com/persagy/meiku/WebMvcConfg.kt
  59. 74 0
      meiku/src/main/kotlin/com/persagy/meiku/controller/MeiKuAnchorController.kt
  60. 88 0
      meiku/src/main/kotlin/com/persagy/meiku/controller/MeiKuController.kt
  61. 73 0
      meiku/src/main/kotlin/com/persagy/meiku/controller/MeiKuStateController.kt
  62. 14 0
      meiku/src/main/kotlin/com/persagy/meiku/controller/Test/Controller.kt
  63. 50 0
      meiku/src/main/kotlin/com/persagy/meiku/models/entities/MeiKu.kt
  64. 37 0
      meiku/src/main/kotlin/com/persagy/meiku/models/entities/MeiKuAnchor.kt
  65. 41 0
      meiku/src/main/kotlin/com/persagy/meiku/models/entities/MeiKuState.kt
  66. 31 0
      meiku/src/main/kotlin/com/persagy/meiku/models/entities/ObjectCategory.kt
  67. 25 0
      meiku/src/main/kotlin/com/persagy/meiku/models/entities/Pos.kt
  68. 31 0
      meiku/src/main/kotlin/com/persagy/meiku/models/response/SCommonResponse.kt
  69. 22 0
      meiku/src/main/kotlin/com/persagy/meiku/services/MeiKuAnchorService.kt
  70. 157 0
      meiku/src/main/kotlin/com/persagy/meiku/services/MeiKuService.kt
  71. 21 0
      meiku/src/main/kotlin/com/persagy/meiku/services/MeiKuStateService.kt
  72. 21 0
      meiku/src/main/resources/application-dev.yml
  73. 14 0
      meiku/src/main/resources/application-prod.yml
  74. 71 0
      meiku/src/main/resources/application.yml
  75. 38 0
      meiku/src/main/resources/logback-spring.xml
  76. 6 0
      settings.gradle

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+.idea
+*.iml
+.gradle
+build
+out
+gradle.properties

+ 62 - 0
build.gradle

@@ -0,0 +1,62 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*             
+ *         =@$    ;;;!=%@@@@=!           =@!      
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;                              
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+
+group 'com.persagy.server'
+version '2.0.0'
+
+buildscript {
+    repositories {
+        maven{url MAVEN_REPO_PUBLIC_URL}
+        maven{ url "http://maven.aliyun.com/nexus/content/groups/public/"}
+        mavenCentral()
+        jcenter()
+    }
+    dependencies {
+        classpath group: 'org.springframework.boot', name: 'spring-boot-gradle-plugin', version: SPRING_BOOT_VERSION
+        classpath group: 'org.jetbrains.kotlin', name: 'kotlin-gradle-plugin', version: KOTLIN_VERSION
+        classpath group: 'org.jetbrains.dokka', name: 'dokka-gradle-plugin', version: DOKKA_VERSION
+        classpath group: 'com.google.protobuf', name: 'protobuf-gradle-plugin', version: PROTOBUF_GRADLE_VERSION
+        // ssh插件, 用于部署
+        classpath 'org.hidetake:gradle-ssh-plugin:2.10.1'
+    }
+}
+
+allprojects {
+    repositories {
+        maven{ url "http://maven.aliyun.com/nexus/content/groups/public/"}
+        maven{
+            url MAVEN_REPO_PUBLIC_URL
+            credentials {
+                username = NEXUS_USERNAME
+                password = NEXUS_PASSWORD
+            }
+        }
+        maven { url "https://repo.spring.io/milestone" }
+        mavenCentral()
+        jcenter()
+    }
+    tasks.withType(Javadoc) {
+        options{ encoding "UTF-8"
+            charSet "UTF-8"
+            links "http://docs.oracle.com/javase/8/docs/api"
+        }
+    }
+}

+ 102 - 0
labsl/build.gradle

@@ -0,0 +1,102 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*             
+ *         =@$    ;;;!=%@@@@=!           =@!      
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;                              
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+group rootProject.group
+version rootProject.version
+
+apply plugin: "kotlin"
+apply plugin: "org.jetbrains.dokka"
+apply plugin: "war"
+apply plugin: 'org.springframework.boot'
+apply plugin: 'io.spring.dependency-management'
+
+sourceCompatibility = JVM_TARGET
+
+compileKotlin {
+    kotlinOptions.jvmTarget = JVM_TARGET
+}
+compileTestKotlin {
+    kotlinOptions.jvmTarget = JVM_TARGET
+}
+
+dependencies {
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // kotlin 依赖
+    compile group: "org.jetbrains.kotlin", name: "kotlin-stdlib-jdk8", version: KOTLIN_VERSION
+    compile group: "org.jetbrains.kotlin", name: "kotlin-reflect", version: KOTLIN_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // spring boot 依赖
+    compile group: "org.springframework.boot", name: "spring-boot-starter-web", version: SPRING_BOOT_VERSION
+    compile group: "org.springframework.boot", name: "spring-boot-configuration-processor", version: SPRING_BOOT_VERSION
+    compile group: "org.springframework.boot", name: "spring-boot-starter-actuator", version: SPRING_BOOT_VERSION
+    compile group: "org.springframework.boot", name: "spring-boot-starter-logging", version: SPRING_BOOT_VERSION
+    //消息
+//    compile group: "org.springframework.boot", name: "spring-boot-starter-activemq", version: SPRING_BOOT_VERSION
+    providedCompile group: "org.springframework.boot", name:"spring-boot-starter-tomcat", version: SPRING_BOOT_VERSION
+    // spring boot 缓存
+    compile group:"org.springframework.boot", name:"spring-boot-starter-cache", version: SPRING_BOOT_VERSION
+    // 单元测试
+    compile group:"org.springframework.boot", name:"spring-boot-starter-test", version: SPRING_BOOT_VERSION
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // spring cloud 依赖
+//    compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka', version: SPRING_CLOUD_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // RESTful API 文档生成工具
+    // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui
+    compile group: 'org.springdoc', name: 'springdoc-openapi-ui', version: SPRING_DOC_VERSION
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Sybotan依赖
+
+
+
+    compile group: "com.persagy", name: "persagy-kotlin-base", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-kotlin-database", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-kotlin-mybatis", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-kotlin-postgresql", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-service-base", version: PERSAGY_SERVICE_VERSION
+    compile group: "com.persagy", name: "persagy-service-mybatis", version: PERSAGY_SERVICE_VERSION
+    compile group: "com.persagy", name: "persagy-service-postgresql", version: PERSAGY_SERVICE_VERSION
+
+
+    // TestNG 测试框架
+    compile group: "org.testng", name: "testng", version: TESTNG_VERSION
+    // Log 工具
+    compile group: "org.projectlombok", name: "lombok", version: LOMBOK_VERSION
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    //Gson
+    compile 'com.google.code.gson:gson:2.8.0'
+
+
+//    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//    // 二维码与条形码
+//    // https://mvnrepository.com/artifact/com.google.zxing/core
+//    compile group: "com.google.zxing", name: "core", version: ZXING_VERSION
+    
+}

+ 77 - 0
labsl/src/main/kotlin/com/persagy/labsl/LaBSLApp.kt

@@ -0,0 +1,77 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*
+ *         =@$    ;;;!=%@@@@=!           =@!
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+package com.persagy.labsl
+
+import org.mybatis.spring.annotation.MapperScan
+import org.slf4j.LoggerFactory
+import org.springframework.boot.SpringApplication
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.builder.SpringApplicationBuilder
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.ComponentScan
+
+/**
+ * 应用配置
+ *
+ * @author  Andy
+ */
+@ComponentScan(basePackages = ["com.persagy"])           // 配置组件扫描路径
+@MapperScan("com.persagy")                       // Mapper组件扫描路径
+@SpringBootApplication
+open class LaBSLApp : SpringBootServletInitializer() {
+    companion object {
+        // 日志
+        private val logger = LoggerFactory.getLogger(LaBSLApp::class.java)
+    } // Companion object
+
+    /**
+     * 配置应用
+     *
+     * @param   application     应用构建对象
+     */
+    override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
+        return application.sources(LaBSLApp::class.java)
+    } // Function configure
+
+//    /**
+//     * 配置FastJson
+//     *
+//     * @return  HttpMessageConverters
+//     */
+//    @Bean
+//    @Suppress("MoveLambdaOutsideParentheses")
+//    open fun jsonHttpMessageConverters(): SJsonHttpMessageConverter {
+//        val fastConverter = SJsonHttpMessageConverter()
+//        fastConverter.propertyNamingStrategy = com.alibaba.fastjson.PropertyNamingStrategy.CamelCase
+//        return fastConverter
+//    } // Function fastJsonHttpMessageConverters()
+} // Class Application
+
+/**
+ * Web应用入口
+ *
+ * @param   args        命令行参数
+ */
+fun main(args: Array<String>) {
+    SpringApplication.run(LaBSLApp::class.java, *args)
+    return
+} // Function main()

+ 79 - 0
labsl/src/main/kotlin/com/persagy/labsl/Swagger2Config.kt

@@ -0,0 +1,79 @@
+///*
+// * ********************************************************************************************************************
+// *
+// *                     :*$@@%$*:                         ;:                ;;    ;;
+// *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+// *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+// *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+// *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+// *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+// *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+// *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+// *         $@*   ;@@@%=!:                *@*
+// *         =@$    ;;;!=%@@@@=!           =@!
+// *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+// *           ;%@@$=$@@%*       *@@@$=%@@%;
+// *              ::;::             ::;::                                              All rights reserved.
+// *
+// * ********************************************************************************************************************
+// */
+//
+//package com.persagy.labsl
+//
+//import org.slf4j.LoggerFactory
+//import org.springframework.context.annotation.Bean
+//import org.springframework.context.annotation.Configuration
+//
+//
+///**
+// * RESTful API文档生成器Swagger2配置
+// *
+// * @author  PLX
+// */
+//@Configuration
+//@EnableSwagger2
+//open class Swagger2Config {
+//    companion object {
+//        // 日志
+//        private val logger = LoggerFactory.getLogger(Swagger2Config::class.java)
+//    } // Companion object
+//
+//    /**
+//     * 创建RestApi文档生成器
+//     *
+//     * @return  返回文档生成器对象
+//     */
+//    @Bean
+//    open fun createRestApi(): Docket {
+//        logger.debug("createRestApi")
+//        val builder = ParameterBuilder()
+//        val builderComming = ParameterBuilder()
+//        val pars = ArrayList<Parameter>()
+//        builderComming.name("coming").description("应用来源").modelRef(ModelRef("string")).parameterType("header").required(false)
+//        builder.name("projectId").description("项目ID").modelRef(ModelRef("string")).parameterType("header").required(false)
+//        pars.add(builder.build())
+//        pars.add(builderComming.build())
+//        return Docket(DocumentationType.SWAGGER_2)
+//                .apiInfo(apiInfo())
+//                .select()
+//                .apis(RequestHandlerSelectors.basePackage("com.persagy"))
+//                .paths(PathSelectors.any())
+//                .build()
+//                .globalOperationParameters(pars)
+//    } // Function createRestApi()
+//
+//    /**
+//     * 返回API信息基本
+//     *
+//     * @return  返回Api基本信息
+//     */
+//    private fun apiInfo(): ApiInfo {
+//        return ApiInfoBuilder()
+//                .title("蜡笔森林-图形API")
+//                .description("")
+//                .termsOfServiceUrl("http://www.persagy.com/")
+//                .contact(Contact("张维新", "", "plx3000@163.com"))
+//                .version("2.0")
+//                .build()
+//    } // Function apiInfo()
+//} // Class Swagger2Config

+ 140 - 0
labsl/src/main/kotlin/com/persagy/labsl/Swagger3Config.kt

@@ -0,0 +1,140 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*
+ *         =@$    ;;;!=%@@@@=!           =@!
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+package com.persagy.labsl
+
+import io.swagger.v3.oas.annotations.enums.ParameterIn
+import io.swagger.v3.oas.models.Components
+import io.swagger.v3.oas.models.OpenAPI
+import io.swagger.v3.oas.models.Operation
+import io.swagger.v3.oas.models.info.Contact
+import io.swagger.v3.oas.models.info.Info
+import io.swagger.v3.oas.models.info.License
+import io.swagger.v3.oas.models.media.StringSchema
+import io.swagger.v3.oas.models.parameters.Parameter
+import io.swagger.v3.oas.models.security.SecurityScheme
+import org.springdoc.core.GroupedOpenApi
+import org.springdoc.core.customizers.OperationCustomizer
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.ApplicationContext
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.web.method.HandlerMethod
+
+
+/**
+ * RESTful API文档生成器Swagger2配置
+ *
+ * @author  PLX
+ */
+@Configuration
+open class Swagger3Config {
+    /** 注入的 ApplicationContext */
+    @Autowired
+    lateinit var applicationContext: ApplicationContext
+
+    /** 标题 */
+    private val title = "数据管理平台 API"
+    /** API 版本号 */
+    private val version = "1.0"
+
+    val operationCustomizer = GlobalHeaderOperationCustomizer()
+
+
+
+    /**
+     * API 信息
+     */
+    @Bean
+    open fun openApi(): OpenAPI {
+        val contact = Contact().name("张维新").email("zhangweixin@sagacloud.cn")
+        return OpenAPI()
+            .components(
+                Components()
+                .addSecuritySchemes("basicScheme", SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")))
+            .info(
+                Info()
+                .title(title)
+                .version(version)
+                .termsOfService("http://www.persagy.com")
+                .contact(contact)
+                .license(
+                    License()
+                    .name("Apache 2.0")
+                    .url("http://www.persagy.com")))
+    }
+
+
+    @Bean
+    open fun publicApi(): GroupedOpenApi? {
+        return GroupedOpenApi.builder()
+            .group("默认")
+            .pathsToMatch("/**")
+            .addOperationCustomizer(operationCustomizer)
+            .build()
+    }
+
+    /**
+     * 字典 API 组
+     */
+//    @Bean
+//    open fun dictApiGroup(): GroupedOpenApi {
+//        return GroupedOpenApi.builder().group("asf").pathsToMatch("")
+//            .build()
+//
+//    }
+
+//    /**
+//     * 对象 API 组
+//     */
+//    @Bean
+//    open fun objectApiGroup(): GroupedOpenApi {
+//        return GroupedOpenApi.builder()
+//            .group("对象")
+//            .pathsToMatch("/object/**")
+//            .addOperationCustomizer(operationCustomizer)
+//            .build()
+//    }
+
+
+
+} // Class Swagger2Config
+
+/**
+ * 全局参数
+ *
+ * @author  庞利祥 <sybotan@126.com>
+ */
+class GlobalHeaderOperationCustomizer : OperationCustomizer {
+    /**
+     * 接口定义器
+     *
+     * @param   operation       接口
+     * @param   handlerMethod   原接口方法
+     * @return  新定义的接口
+     */
+    override fun customize(operation: Operation, handlerMethod: HandlerMethod): Operation {
+        val projectId = Parameter().`in`(ParameterIn.HEADER.toString())
+            .name("projectId").description("项目 id")
+            .schema(StringSchema()).required(false)
+        operation.addParametersItem(projectId)
+        return operation
+    }
+}

+ 46 - 0
labsl/src/main/kotlin/com/persagy/labsl/WebMvcConfg.kt

@@ -0,0 +1,46 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*
+ *         =@$    ;;;!=%@@@@=!           =@!
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+package com.persagy.labsl
+
+import com.persagy.service.interceptors.SPageInterceptor
+import org.slf4j.LoggerFactory
+import org.springframework.context.annotation.Configuration
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
+
+@Configuration
+open class WebMvcConfg: WebMvcConfigurerAdapter() {
+    companion object {
+        // 日志
+        private val logger = LoggerFactory.getLogger(WebMvcConfg::class.java)
+    } // Companion object
+    /**
+     * 配置拦截器
+     *
+     * @param   registry        拦截器注册器
+     */
+    override fun addInterceptors(registry : InterceptorRegistry) {
+        //registry.addInterceptor(AccessControlAllowOriginInterceptor()).addPathPatterns("/**")
+        registry.addInterceptor(SPageInterceptor()).addPathPatterns("/**")
+        super.addInterceptors(registry)
+
+    } // Function addInterceptors()
+} // Class WebMvcConf()

+ 37 - 0
labsl/src/main/kotlin/com/persagy/labsl/controller/GraphCategoryController.kt

@@ -0,0 +1,37 @@
+package com.persagy.labsl.controller
+
+import com.persagy.labsl.models.entities.GraphCategory
+import com.persagy.labsl.models.request.GraphCategoryRequest
+import com.persagy.labsl.services.GraphCategoryService
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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 wx  <zhangweixin@sagacloud.com>
+ * @date  2020/9/15 11:40
+ */
+@Tag(name = "005、系统图类型")
+@RestController
+@RequestMapping("/graph-category")
+class GraphCategoryController {
+
+    /**
+     * 查询系统图类型信息
+     *
+     * @param request   查询条件
+     * @return 查询结果
+     */
+   @Operation(summary = "查询系统图类型信息", description = "类型开关 true  获取所有 false 获取已有图形的类型")
+    @PostMapping(value = ["/query"])
+    fun graphCategoryQuery(@RequestBody request: GraphCategoryRequest): SQueryResponse<GraphCategory> {
+        return GraphCategoryService.graphCategoryQuery(request)
+    } // Fun graphCategoryQuery()
+
+} // Class GraphCategoryController

+ 192 - 0
labsl/src/main/kotlin/com/persagy/labsl/controller/GraphController.kt

@@ -0,0 +1,192 @@
+package com.persagy.labsl.controller
+
+import com.persagy.database.SFilter
+import com.persagy.labsl.models.entities.Graph
+import com.persagy.labsl.models.entities.pub.GraphPub
+import com.persagy.labsl.models.response.SCommonResponse
+import com.persagy.labsl.services.GraphService
+import com.persagy.labsl.services.pub.GraphPubService
+import com.persagy.service.SPageContext
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.requests.SQueryRequest
+import com.persagy.service.models.requests.SUpdateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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 wx  <zhangweixin@sagacloud.com>
+ */
+@Tag(name = "001、系统图")
+@RestController
+@RequestMapping("/graph")
+class GraphController {
+
+    /**
+     * 创建图
+     *
+     * @param request     待图对象列表
+     * @return 创建完成图对象列表
+     */
+   @Operation(summary ="草稿箱-创建图", description = "id和graphId为必填,图中会包含多个节点,详细节点结构见示例")
+    @PostMapping("/drafts/create")
+    fun create(@RequestBody request: SCreateRequest<Graph>): SCreateResponse<Graph> {
+        return GraphService.createList(request)
+    } // Function create()
+
+    /**
+     * 提交图形
+     *
+     * @param  graph   待图对象
+     * @return  图对象列表
+     */
+   @Operation(summary = "草稿箱-保存图形", description = "")
+    @PostMapping("/drafts/save")
+    fun save(@RequestBody graph: Graph): SCreateResponse<Graph> {
+        return GraphService.save(graph)
+    } // Function save()
+
+    /**
+     * 发布图形
+     *
+     * @param graph     待发布的图对象
+     * @return 发布结果
+     */
+   @Operation(summary="草稿箱-发布图形", description =" Id 和 GraphId 必须填写")
+    @PostMapping("/drafts/publish")
+    fun pubDrawings(@RequestBody graph: GraphPub): SCreateResponse<GraphPub>{
+        return GraphService.pubDrawings(graph)
+    } // Function pubDrawings()
+
+
+    /**
+     * 图、移至或移出回收站
+     *
+     * @param idList    图例列表
+     * @return 移出结果
+     */
+   @Operation(summary = "草稿箱-移至回收站", description = " Id 和 GraphId 必填")
+    @PostMapping(value = ["/drafts/recycle"])
+    fun recycle(@RequestBody idList: ArrayList<Graph>): SBaseResponse {
+        return GraphService.recycle(idList)
+    } // Function recycle()
+
+    /**
+     * 已发布图形移至回收站
+     *
+     * @param idList    图列表
+     * @return 移出结果
+     */
+   @Operation(summary = "已发布-图形移至回收站", description = "Id 和 GraphId 必填")
+    @PostMapping(value = ["/pub/recycle"])
+    fun recyclePub(@RequestBody idList: ArrayList<Graph>): SBaseResponse{
+        return GraphService.recyclePub(idList)
+    } // Function recyclePub()
+
+    /**
+     * 更新图形信息
+     *
+     * @param request   更新的内容对象
+     * @return 更新的结果
+     */
+   @Operation(summary = "草稿箱-更新图形信息", description = "Id 和 GraphId 必填")
+    @PostMapping(value = ["/drafts/update"])
+    fun update(@RequestBody request: SUpdateRequest<Graph>): SBaseResponse {
+        return GraphService.updateList(request)
+    } // Function update()
+
+    /**
+     * 查询图形信息
+     *
+     * @param  request  查询条件
+     * @return 查询结果
+     */
+   @Operation(summary = "草稿箱-查询图形信息", description = "state 1(草稿箱),state 4(回收站) ,Id 和 GraphId 必填")
+    @PostMapping(value = ["/drafts/query"])
+    fun query(@RequestBody request: SQueryRequest): SQueryResponse<Graph> {
+        val projectId = SPageContext.getHeader("projectId")
+        return GraphService.pageQuery(request, arrayListOf(SFilter.eq("projectId",projectId!!)))
+    } // Function query()
+
+    /**
+     * 草稿箱 - 读取图形所有节点
+     *
+     * @param graph  图例对象
+     * @return 查询结果
+     */
+   @Operation(summary = "草稿箱-查询图形以及所有节点信息", description = "Id 和 GraphId 必填")
+    @PostMapping(value = ["/drafts/read"])
+    fun readDrafts(@RequestBody graph: Graph): SCommonResponse<Graph> {
+        return GraphService.readDrafts(graph)
+    } // Fun readDrafts()
+
+    /**
+     * 已发布 - 读取图形所有节点
+     *
+     * @param graph  图例对象】
+     * @return 查询结果
+     */
+   @Operation(summary = "已发布-查询图形以及所有节点信息", description = "Id 和 GraphId 必填")
+    @PostMapping(value = ["/pub/read"])
+    fun readPub(@RequestBody graph: GraphPub): SCommonResponse<GraphPub> {
+        return GraphService.readPub(graph)
+    } // Fun readPub()
+
+    /**
+     * 已发布图形查询
+     *
+     * @param request  查询条件
+     * @return 查询结果
+     */
+   @Operation(summary = "已发布-查询图形信息", description = "Id 和 GraphId 必填")
+    @PostMapping(value = ["/pub/query"])
+    fun querPub(@RequestBody request: SQueryRequest): SQueryResponse<GraphPub> {
+        val projectId = SPageContext.getHeader("projectId")
+        return GraphPubService.pageQuery(request, arrayListOf(SFilter.eq("projectId",projectId!!)))
+    } // Function querPub()
+
+    /**
+     * 更新图形信息
+     *
+     * @param request  更新的内容对象
+     * @return 更新的结果
+     */
+   @Operation(summary = "已发布-更新图形信息", description = "")
+    @PostMapping(value = ["/pub/update"])
+    fun updatePub(@RequestBody request: SUpdateRequest<GraphPub>): SBaseResponse {
+        return GraphPubService.updateList(request)
+    } // Function update()
+
+    /**
+     * 回收站- 恢复图形
+     *
+     * @param graph  图对象
+     * @return 恢复结果
+     */
+   @Operation(summary = "回收站- 恢复图形", description = "Id 和 GraphId 必填 ")
+    @PostMapping(value = ["recycle/recovery"])
+    fun recovery(@RequestBody graph: Graph): SBaseResponse{
+    return GraphService.recovery(graph)
+    } // Fun recovery()
+
+    /**
+     * 根据id删除图形
+     *
+     * @param idList      图对象数组
+     * @return 删除的结果信息
+     */
+   @Operation(summary = "回收站-根据id删除图形信息,删除草稿箱图形", description = "Id 和 GraphId 必填 ")
+    @PostMapping(value = ["recycle/delete"])
+    fun delete(@RequestBody idList: ArrayList<Graph>): SBaseResponse {
+        return GraphService.deleteByKeysList(idList)
+    } // Function delete()
+
+} // Class GraphController

+ 76 - 0
labsl/src/main/kotlin/com/persagy/labsl/controller/MarkersController.kt

@@ -0,0 +1,76 @@
+package com.persagy.labsl.controller
+
+import com.persagy.labsl.models.entities.Markers
+import com.persagy.labsl.services.MarkersService
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.requests.SQueryRequest
+import com.persagy.service.models.requests.SUpdateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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 wx  <zhangweixin@sagacloud.com>
+ */
+@Tag(name = "003、系统图内标识信息,文本注释,图上的图片说明- 系统图下子对象")
+@RestController
+@RequestMapping("/marker")
+class MarkersController {
+
+    /**
+     * 注释说明
+     *
+     * @param request   待创建注释说明对象列表
+     * @return  创建完成注释说明对象列表
+     */
+   @Operation(summary="注释说明创建", description ="id 为系统图的图对象id,graphId 为系统图的图 id ,markerId 为当前标识的id,id 和 graphId 必须填为某一个系统图中的 id,markerId 是当前要创建的对象id不传会自动生成(32位uuid)")
+    @PostMapping("/create")
+    fun create(@RequestBody request: SCreateRequest<Markers>): SCreateResponse<Markers> {
+        return MarkersService.creates(request)
+    } // Function create()
+
+    /**
+     * 根据id删除图注释说明
+     *
+     * @param idList    id数组
+     * @return  删除的结果信息
+     */
+   @Operation(summary = "根据批量删除标识信息对象", description = "创建中有介绍id的说明请查看,删除时必须传入 id、graphId、markerId 才能确认删除的是当前的标识对象")
+    @PostMapping(value = ["/delete"])
+    fun delete(@RequestBody idList: ArrayList<Markers>): SBaseResponse {
+        return MarkersService.deletes(idList)
+    } // Function delete()
+
+    /**
+     * 更新注释说明信息
+     *
+     * @param request   更新的内容对象
+     * @return 更新的结果
+     */
+   @Operation(summary = "批量更新标识信息", description = "创建中有介绍id的说明请查看,id、graphId、markerId 为必填信息点,参考创建后的对象信息点,修改哪个信息点直接写在对象里面即可,详细的使用方式参考 web 端接口使用规范")
+    @PostMapping(value = ["/update"])
+    fun update(@RequestBody request: SUpdateRequest<Markers>): SBaseResponse {
+        return MarkersService.updateList(request)
+    } // Function update()
+
+    /**
+     * 查询注释说明信息
+     *
+     * @param request   查询条件
+     * @return 查询结果
+     */
+   @Operation(summary = "查询标识信息", description = "创建中有介绍id的说明请查看,注意 id、graphId、markerId 的区别,示例 查询某一个标识信息:filters = id ='值';graphId='值';markerId='值'    (其他的组合方式详见后端开发文档 web 端接口使用规范)")
+    @PostMapping(value = ["/query"])
+    fun query(@RequestBody request: SQueryRequest): SQueryResponse<Markers> {
+        return MarkersService.pageQuery(request)
+    } // Function query()
+
+} // Class NodeController

+ 76 - 0
labsl/src/main/kotlin/com/persagy/labsl/controller/NodeController.kt

@@ -0,0 +1,76 @@
+package com.persagy.labsl.controller
+
+import com.persagy.labsl.models.entities.Node
+import com.persagy.labsl.services.NodeService
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.requests.SQueryRequest
+import com.persagy.service.models.requests.SUpdateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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 wx  <zhangweixin@sagacloud.com>
+ */
+@Tag(name = "002、系统图设备节点,与数据中台设备实例对应关系(绑定信息点在该设备上进行)- 系统图下子对象")
+@RestController
+@RequestMapping("/node")
+class NodeController {
+
+    /**
+     * 图例节点
+     *
+     * @param request   待创建图对象列表
+     * @return  创建完成图例节点对象列表
+     */
+   @Operation(summary="创建设备节点", description ="id 为系统图的图对象id,graphId 为系统图的图id ,nodeId 为当前节点的id,id 和 graphId 必须填为某一个系统图中的 id,nodeId 是当前要创建的对象id不传会自动生成(32位uuid)")
+    @PostMapping("/create")
+    fun create(@RequestBody request: SCreateRequest<Node>): SCreateResponse<Node> {
+        return NodeService.creates(request)
+    } // Function create()
+
+    /**
+     * 根据id删除图例节点
+     *
+     * @param idList  id数组
+     * @return 删除的结果信息
+     */
+   @Operation(summary = "根据id删除图例节点信息", description = "创建中有介绍id的说明请查看,删除时必须传入 id、graphId、nodeId 才能确认删除的是当前的设备节点")
+    @PostMapping(value = ["/delete"])
+    fun delete(@RequestBody idList: ArrayList<Node>): SBaseResponse {
+        return NodeService.deletes(idList)
+    } // Function delete()
+
+    /**
+     * 更新图例节点信息
+     *
+     * @param  request   更新的内容对象
+     * @return 更新的结果
+     */
+   @Operation(summary = "更新图例节点信息", description = "创建中有介绍 id 的说明请查看,id、graphId、nodeId 为必填信息点,参考创建后的对象信息点,然后修改了哪个信息点传哪个信息点,详细的使用方式参考 web 端接口使用规范")
+    @PostMapping(value = ["/update"])
+    fun update(@RequestBody request: SUpdateRequest<Node>): SBaseResponse {
+        return NodeService.updateList(request)
+    } // Function update()
+
+    /**
+     * 查询图例节点信息
+     *
+     * @param  request 查询条件
+     * @return 查询结果
+     */
+   @Operation(summary = "查询图例节点信息", description = "创建中有介绍 id 的说明请查看,注意 id、graphId、nodeId 的区别,示例 查询某一个对象:filters = id ='值';graphId='值';nodeId='值' (其他的组合方式详见后端开发文档 web 端接口使用规范)")
+    @PostMapping(value = ["/query"])
+    fun query(@RequestBody request: SQueryRequest): SQueryResponse<Node> {
+        return NodeService.pageQuery(request)
+    } // Function query()
+
+} // Class NodeController

+ 94 - 0
labsl/src/main/kotlin/com/persagy/labsl/controller/PictureController.kt

@@ -0,0 +1,94 @@
+//package com.persagy.server.labsl.controller
+//
+//import com.persagy.base.extensions.toJson
+//import com.persagy.database.SFilter
+//import com.persagy.server.labsl.models.entities.pic.Picture
+//import com.persagy.server.labsl.services.pic.PictureService
+//import com.persagy.service.models.enums.SResponseType
+//import com.persagy.service.models.responses.SBaseResponse
+//import com.persagy.service.models.responses.SCreateResponse
+//import io.swagger.annotations.Api
+//import io.swagger.annotations.ApiOperation
+//import lombok.extern.slf4j.Slf4j
+//import org.slf4j.LoggerFactory
+//import org.springframework.web.bind.annotation.*
+//import org.springframework.web.multipart.MultipartFile
+//import java.util.*
+//
+///**
+// * 图片接口
+// *
+// * @author wx
+// */
+//@Api(tags = ["006、图片接口"])
+//@RestController
+//@RequestMapping("/picture")
+//@Slf4j
+//class PictureController {
+//
+//    companion object {
+//        /** 日志 */
+//        private val logger = LoggerFactory.getLogger(PictureController::class.java)
+//    } // Companion object
+//
+//    /**
+//     * 上传图片
+//     *
+//     * @param   file         图片文件
+//     * @param   uid          图片id
+//     * @return              创建结果信息
+//     */
+//   @Operation(summary = "上传图片", notes = "")
+//    @PostMapping(value = ["/create"])
+//    fun create(@RequestParam(value = "file", required = true) file: MultipartFile, @RequestParam(required = false) uid: String?): SCreateResponse<String> {
+//        var response = SCreateResponse<String>()
+//        try {
+//            val picture = Picture()
+//            if(uid.isNullOrEmpty()){
+//                picture.id = UUID.randomUUID().toString().replace("-","")
+//            }else{
+//                PictureService.delete(SFilter.eq("id",uid!!))
+//                picture.id = uid
+//            }
+//            picture.pic = file.bytes
+//            logger.debug("name:"+file.name)
+//            logger.debug("长度:"+file.size)
+////            PictureService.insert(picture)
+//            response.result = SResponseType.success
+//            response.entityList = arrayListOf(picture.id!!)
+//        } catch (e: Exception) {
+//            response.result = SResponseType.failure
+//            response.message = e.message.toString()
+//            e.printStackTrace()
+//        }
+//        return response
+//    } // Function create()
+//
+//    /**
+//     * 根据id删除图片
+//     *
+//     * @param   idList      id数组
+//     * @return              删除的结果信息
+//     */
+//   @Operation(summary = "根据id删除图片信息", notes = "")
+//    @PostMapping(value = ["/delete"])
+//    fun delete(@RequestBody idList: ArrayList<Picture>): SBaseResponse {
+//        return PictureService.deleteByKeysList(idList)
+//    } // Function delete()
+//
+//    /**
+//     * 查询图片信息
+//     *
+//     * @param   id             查询条件id
+//     * @return                 查询结果
+//     */
+//   @Operation(summary = "查询图片信息", notes = "")
+//    @GetMapping(value = ["/query"])
+//    fun query(@RequestParam id: String) {
+//        val picture = PictureService.select(SFilter.eq("id", id)).entity()
+//
+//            logger.debug(picture?.toJson())
+//
+//    } // Function query()
+//
+//} //

+ 76 - 0
labsl/src/main/kotlin/com/persagy/labsl/controller/RelationController.kt

@@ -0,0 +1,76 @@
+package com.persagy.labsl.controller
+
+import com.persagy.labsl.models.entities.Relation
+import com.persagy.labsl.services.RelationService
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.requests.SQueryRequest
+import com.persagy.service.models.requests.SUpdateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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 wx  <zhangweixin@sagacloud.com>
+ */
+@Tag(name = "004、系统图管线信息(对应中台中的关系)- 系统图下子对象")
+@RestController
+@RequestMapping("/relation")
+class RelationController {
+
+    /**
+     * 管线创建
+     *
+     * @param request    待创建管线对象列表
+     * @return  创建完成图例节点对象列表
+     */
+   @Operation(summary="管线创建", description ="id 为系统图的图对象id,graphId 为系统图的图id ,relationId 为当前管线对象的id,id 和 graphId 必须填为某一个系统图中的id,relationId 是当前要创建的对象 id 不传会自动生成(32位uuid)")
+    @PostMapping("/create")
+    fun create(@RequestBody request: SCreateRequest<Relation>): SCreateResponse<Relation> {
+        return RelationService.creates(request)
+    } // Function create()
+
+    /**
+     * 根据id删除管线
+     *
+     * @param  idList    id数组
+     * @return 删除的结果信息
+     */
+   @Operation(summary = "根据id删除管线信息", description = "创建中有介绍id的说明请查看,删除时必须传入 id、graphId、relationId 才能确认删除的是当前的标识对象")
+    @PostMapping(value = ["/delete"])
+    fun delete(@RequestBody idList: ArrayList<Relation>): SBaseResponse {
+        return RelationService.deletes(idList)
+    } // Function delete()
+
+    /**
+     * 更新管线信息
+     *
+     * @param  request   更新的内容对象
+     * @return 更新的结果
+     */
+   @Operation(summary = "更新管线信息", description = "创建中有介绍id的说明请查看,id、graphId、relationId 为必填信息点,参考创建后的对象信息点,修改哪个信息点直接写在对象里面即可,详细的使用方式参考 web 端接口使用规范")
+    @PostMapping(value = ["/update"])
+    fun update(@RequestBody request: SUpdateRequest<Relation>): SBaseResponse {
+        return RelationService.updateList(request)
+    } // Function update()
+
+    /**
+     * 查询管线信息
+     *
+     * @param  request     查询条件
+     * @return  查询结果
+     */
+   @Operation(summary = "查询管线信息", description = "创建中有介绍id的说明请查看,注意 id、graphId、relationId 的区别,示例 查询某一个对象:filters = id ='值';graphId='值';relationId='值' (其他的组合方式详见后端开发文档 web 端接口使用规范)")
+    @PostMapping(value = ["/query"])
+    fun query(@RequestBody request: SQueryRequest): SQueryResponse<Relation> {
+        return RelationService.pageQuery(request)
+    } // Function query()
+
+} // Class NodeController

+ 57 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Anchor.kt

@@ -0,0 +1,57 @@
+package com.persagy.labsl.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 锚点
+ *
+ * @author wx
+ */
+@Schema(description = "锚点")
+@Table(name = "labsl.anchor")
+open class Anchor : SBaseEntity(), Serializable {
+
+    /** 全局id */
+    @Schema(description = "全局id")
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 锚点id */
+    @Schema(description = "锚点id")
+    @Id
+    @Column(name = "anchor_id")
+    var anchorId: String? = null
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Id
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 图例节点 */
+    @Schema(description = "图例节点")
+    @Column(name = "node_id")
+    var nodeId: String? = null
+
+    /** 锚点的坐标 */
+    @Schema(description = "锚点的坐标")
+    @Column(name = "pos")
+    var pos: Pos? = null
+
+    /** 项目id */
+    @Schema(description = "项目id")
+    @Column(name = "project_id")
+    var projectId: String? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,4回收站 ,0发布)")
+    @Column(name = "state")
+    var state: Int? = 1
+
+} // Class Anchor

+ 48 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/AttachObjectIds.kt

@@ -0,0 +1,48 @@
+package com.persagy.labsl.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 图例节点与对象的关系
+ *
+ * @author  wx
+ * @date  2020/9/17 16:35
+ */
+@Schema(description = "图例节点与对象的关系")
+@Table(name = "labsl.attach_object_ids")
+class AttachObjectIds : SBaseEntity(), Serializable {
+
+    /** 全局id */
+    @Schema(description = "全局id")
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 图例节点id */
+    @Schema(description = "图例节点id",required = true )
+    @Id
+    @Column(name = "node_id")
+    var nodeId: String? = null
+
+    /** 对象id */
+    @Schema(description = "对象id",required = true )
+    @Id
+    @Column(name = "object_id")
+    var objectId: String? = null
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,4回收站 ,0发布)")
+    @Column(name = "state")
+    var state: Int? = 1
+
+} // Class AttachObjectIds

+ 24 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Elements.kt

@@ -0,0 +1,24 @@
+package com.persagy.labsl.models.entities
+
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.validation.Valid
+
+/**
+ * 系统图展示所需数据
+ *
+ * @author wx
+ */
+class Elements : Serializable {
+
+    @Schema(description = "图例节点")
+    @Valid
+    var nodes : ArrayList<Node>? = null
+
+    @Schema(description = "文本注释,图上的图片说明")
+    var markers : ArrayList<Markers>? = null
+
+    @Schema(description = "管线对象")
+    var relations : ArrayList<Relation>? = null
+
+} // Class Elements

+ 110 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Graph.kt

@@ -0,0 +1,110 @@
+package com.persagy.labsl.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import java.util.*
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 系统图
+ *
+ * @author wx  <zhangweixin@sagacloud.cn>
+ */
+@Schema(description = "系统图")
+@Table(name = "labsl.graph")
+open class Graph : SBaseEntity(), Serializable {
+
+    /** 图对象id */
+    @Schema(description = "图对象id", required = true)
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 图id */
+    @Schema(description = "图id", required = true)
+    @Id
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 图名称 */
+    @Schema(description = "图名称", required = true)
+    @Column(name = "name")
+    var name: String? = null
+
+    /** 图分类id */
+    @Schema(description = "图分类id",required = true )
+    @Column(name = "category_id")
+    var categoryId: String? = null
+
+    /** 项目id */
+    @Schema(description = "项目id",required = true )
+    @Column(name = "project_id")
+    var projectId: String? = null
+
+    /** 建筑id */
+    @Schema(description = "建筑id")
+    @Column(name = "building_id")
+    var buildingId: String? = null
+
+    /** 楼层id */
+    @Schema(description = "楼层id")
+    @Column(name = "floor_id")
+    var floorId: String? = null
+
+    /** 说明 */
+    @Schema(description = "说明")
+    @Column(name = "note")
+    var note: String? = null
+
+    /** 版本号 */
+    @Schema(description = "版本号")
+    @Column(name = "version")
+    var version: String? = null
+
+    @Schema(description = "系统图展示所需数据")
+    open var elements: Elements? = null
+
+    /** 移至回收站时间 */
+    @Schema(description = "移至回收站时间",example = "2020-09-20 08:30:00")
+    @Column(name = "del_time")
+    var delTime: Date? = null
+
+    /** 是否移至回收站 */
+    @Schema(description = "是否移至回收站 , false 正常,true 以至回收站")
+    @Column(name = "is_available")
+    var isAvailable: Boolean? = false
+
+    /** 内部版本号 */
+    @Schema(description = "内部版本号")
+    @Column(name = "tag_version")
+    var tagVersion: Int? = null
+
+//    /** 内部版本号 */
+//    @Schema(description = "是否发布(true 发布、false 未发布)")
+//    @Column(name = "is_pub")
+//    var isPub: Boolean = false
+
+    /** 图片Key */
+    @Schema(description = "图片Key")
+    @Column(name = "pic")
+    var pic: String? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,4回收站 ,0发布)")
+    @Column(name = "state")
+    var state: Int? = 1
+
+    /** 页面尺寸 */
+    @Schema(description = "页面尺寸")
+    @Column(name = "page_size")
+    var pageSize: HashMap<String,Any?>? = null
+
+    /** 标签 */
+    @Schema(description = " 标签 ")
+    @Column(name = "label")
+    var label: ArrayList<String>? = null
+
+} // Class Graph

+ 44 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/GraphCategory.kt

@@ -0,0 +1,44 @@
+package com.persagy.labsl.models.entities
+
+import com.alibaba.fastjson.annotation.JSONField
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 图分类
+ *
+ * @author  wx
+ * @date  2020/9/15 11:33
+ */
+@Schema(description = "图分类")
+@Table(name = "labsl.graph_category")
+class GraphCategory : SBaseEntity(), Serializable {
+
+    /** 分类编码Code */
+    @Schema(description = "分类编码Code")
+    @Id
+    @Column(name = "id")
+    @JSONField(name = "code")
+    var id: String? = null
+
+    /** 分类名称 */
+    @Schema(description = "分类名称")
+    @Column(name = "name")
+    var name: String? = null
+
+    /** 上级节点 */
+    @Schema(description = "上级节点")
+    @Column(name = "parent_id")
+    var parentId: String? = null
+
+    @Schema(description = "子节点列表")
+    var categoryList: ArrayList<GraphCategory>? = null
+
+    @JSONField(name = "categoryList",serialize = false)
+    var sign: Boolean = false
+
+} //  Class GraphCategory

+ 80 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Markers.kt

@@ -0,0 +1,80 @@
+package com.persagy.labsl.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 文本注释,图上的图片说明
+ *
+ * @author wx
+ */
+@Schema(description = "文本注释,图上的图片说明")
+@Table(name = "labsl.marker")
+open class Markers : SBaseEntity(), Serializable {
+
+    /** 图对象id */
+    @Schema(description = "图对象id" ,required = true)
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 标识id */
+    @Schema(description = "标识id",required = true )
+    @Id
+    @Column(name = "marker_id")
+    var markerId: String? = null
+
+    /** 标识名称 */
+    @Schema(description = "标识名称" ,required = true)
+    @Column(name = "name")
+    var name: String? = null
+
+    /** 图标(Image),线类型(Line),文本(Text) */
+    @Schema(description = "图标(Image),线类型(Line),文本(Text)")
+    @Column(name = "type")
+    var type: String? = null
+
+    /** 位置信息 */
+    @Schema(description = "位置信息")
+    @Column(name = "pos")
+    var pos: Pos? = null
+
+    /** 缩放 */
+    @Schema(description = "缩放")
+    @Column(name = "scale")
+    var scale: Pos? = null
+
+    /** 旋转 */
+    @Schema(description = "旋转")
+    @Column(name = "rotate")
+    var rotate: Pos? = null
+
+    /** 大小 */
+    @Schema(description = "大小")
+    @Column(name = "size")
+    var size: Size? = null
+
+    @Schema(description = "应用自定义")
+    @Column(name = "properties")
+    var properties : HashMap<String,Any?>? = null
+
+    /** 图id */
+    @Schema(description = "图id" ,required = true)
+    @Id
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,4回收站 ,0发布)")
+    @Column(name = "state")
+    var state: Int? = 1
+
+    @Schema(description = "线的绘图样式")
+    @Column(name = "style")
+    var style : HashMap<String,Any?>? = null
+
+} // Class Markers

+ 107 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Node.kt

@@ -0,0 +1,107 @@
+package com.persagy.labsl.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 设备节点
+ *
+ * @author wx
+ */
+@Schema(description = "设备节点")
+@Table(name = "labsl.node")
+open class Node : SBaseEntity(), Serializable {
+
+    /** 系统图对象id */
+    @Schema(description = "系统图对象id",required = true )
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 节点id */
+    @Schema(description = "节点id",required = true )
+    @Id
+    @Column(name = "node_id")
+    var nodeId: String? = null
+
+    /** 节点名称 */
+    @Schema(description = "图例节点名称",required = true )
+    @Column(name = "name")
+    var name: String? = null
+
+    /** 图例类型 None/Line/Zone/Image:非图例/线条/区域类型/图标 */
+    @Schema(description = "图例类型 None/Line/Zone/Image:非图例/线条/区域类型/图标")
+    @Column(name = "graph_element_type")
+    var graphElementType: String? = null
+
+    /** 图元ID */
+    @Schema(description = "图元ID")
+    @Column(name = "graph_element_id")
+    var graphElementId: String? = null
+
+//    /** 图例数量 */
+//    @Schema(description = "图例数量")
+//    @Column(name = "num")
+//    var num: Int? = null
+
+    /** 节点类型(image / zone) */
+    @Schema(description = "节点类型(image / zone)")
+    @Column(name = "type")
+    var type: String? = null
+
+    /** 位置信息 */
+    @Schema(description = "位置信息")
+    @Column(name = "pos")
+    var pos: Pos? = null
+
+    /** 缩放 */
+    @Schema(description = "缩放")
+    @Column(name = "scale")
+    var scale: Pos? = null
+
+    /** 旋转 */
+    @Schema(description = "旋转")
+    @Column(name = "rotate")
+    var rotate: Pos? = null
+
+    /** 大小 */
+    @Schema(description = "大小")
+    @Column(name = "size")
+    var size: Size? = null
+
+    /** 轮廓线 */
+    @Schema(description = "轮廓线")
+    @Column(name = "outline")
+    var outline: ArrayList<ArrayList<Pos>>? = null
+
+    @Schema(description = "应用自定义")
+    @Column(name = "properties")
+    var properties : HashMap<String,Any?>? = null
+
+    /** 系统图 id */
+    @Schema(description = "系统图 id",required = true)
+    @Id
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 锚点列表 */
+    @Schema(description = "锚点列表")
+    var anchorList: ArrayList<Anchor>? = null
+
+    @Schema(description = "图例节点与对象的关系")
+    var attachObjectIds: ArrayList<AttachObjectIds>? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,4回收站 ,0发布)")
+    @Column(name = "state")
+    var state: Int? = 1
+
+    @Schema(description = "线的绘图样式")
+    @Column(name = "style")
+    var style : HashMap<String,Any?>? = null
+
+} // Class node

+ 25 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Pos.kt

@@ -0,0 +1,25 @@
+package com.persagy.labsl.models.entities
+
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+
+/**
+ * 位置信息
+ *
+ * @author wx
+ */
+class Pos : Serializable {
+
+    /** X坐标 */
+    @Schema(description = "X坐标")
+    var x: Double? = null
+
+    /** Y坐标 */
+    @Schema(description = "Y坐标")
+    var y: Double? = null
+
+    /** Z坐标 */
+    @Schema(description = "Z坐标")
+    var z: Double? = null
+
+} // Class Pos

+ 91 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Relation.kt

@@ -0,0 +1,91 @@
+package com.persagy.labsl.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 管线对象
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ */
+@Schema(description = "管线对象")
+@Table(name = "labsl.relation")
+open class Relation : SBaseEntity(), Serializable {
+
+    /** 系统图对象id */
+    @Schema(description = "系统图对象id",required = true )
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 关系id */
+    @Schema(description = "关系id",required = true )
+    @Id
+    @Column(name = "relation_id")
+    var relationId: String? = null
+
+    /** 关系名称 */
+    @Schema(description = "关系名称",required = true)
+    @Column(name = "name")
+    var name: String? = null
+
+    /** 图元id */
+    @Schema(description = "图元id")
+    @Column(name = "graph_element_id")
+    var graphElementId: String? = null
+
+    /** 关联节点1_id */
+    @Schema(description = "关联节点1_id")
+    @Column(name = "node1_id")
+    var node1Id: String? = null
+
+    /** 关联节点2_id */
+    @Schema(description = "关联节点2_id")
+    @Column(name = "node2_id")
+    var node2Id: String? = null
+
+    /** 关联锚点1_id */
+    @Schema(description = "关联锚点1_id")
+    @Column(name = "anchor1_id")
+    var anchor1Id: String? = null
+
+    /** 关联锚点2_id */
+    @Schema(description = "关联锚点2_id")
+    @Column(name = "anchor2_id")
+    var anchor2Id: String? = null
+
+    /** 方向(0:无向,1:节点1到节点2,2:节点2到节点1) */
+    @Schema(description = "方向(0:无向,1:节点1到节点2,2:节点2到节点1)")
+    @Column(name = "dir")
+    var dir: Int? = null
+
+    /** 直线(Line),水平垂直 */
+    @Schema(description = "直线(Line),水平垂直")
+    @Column(name = "line_type")
+    var lineType: String? = null
+
+    /** 线的顶点坐标 */
+    @Schema(description = "线的顶点坐标")
+    @Column(name = "point_list")
+    var pointList: ArrayList<Pos>? = null
+
+    @Schema(description = "线的绘图样式")
+    @Column(name = "style")
+    var style : HashMap<String,Any?>? = null
+
+    /** 系统图 id */
+    @Schema(description = "系统图 id",required = true)
+    @Id
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,4回收站 ,0发布)")
+    @Column(name = "state")
+    var state: Int? = 1
+
+} // Class Relation

+ 21 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/Size.kt

@@ -0,0 +1,21 @@
+package com.persagy.labsl.models.entities
+
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+
+/**
+ * 大小
+ *
+ * @author wx
+ */
+class Size : Serializable {
+
+    /** Width宽 */
+    @Schema(description = "Width宽")
+    var width: Double? = null
+
+    /** Height高 */
+    @Schema(description = "Height高")
+    var height: Double? = null
+
+} // Class Size

+ 19 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/auxiliary/CategoryCode.kt

@@ -0,0 +1,19 @@
+package com.persagy.labsl.models.entities.auxiliary
+
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Table
+
+/**
+ * 图类型
+ *
+ * @author  wx
+ * @date  2020/9/17 12:05
+ */
+@Schema(description = "类型")
+class CategoryCode : Serializable {
+    /** 类型 id */
+    @Schema(description = "类型 id")
+    var categoryId: String? = null
+
+} // Class CategoryCode

+ 33 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pic/Picture.kt

@@ -0,0 +1,33 @@
+package com.persagy.labsl.models.entities.pic
+
+import com.alibaba.fastjson.annotation.JSONField
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 图片实体
+ *
+ * @author  wx
+ */
+@Schema(description = "图片实体")
+@Table(name = "labsl_pic.picture")
+open class Picture : SBaseEntity(), Serializable {
+
+    private val serialVersionUID = 1L
+    /** id */
+    @Schema(description = "id")
+    @Id
+    @Column(name = "id")
+    @JSONField(name = "Id")
+    var id: String? = null
+
+    /** 图片 */
+    @Schema(description = "图片")
+    @JSONField(name = "Pic")
+    @Column(name = "pic")
+    var pic: ByteArray? = null
+}

+ 16 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/AnchorPub.kt

@@ -0,0 +1,16 @@
+package com.persagy.labsl.models.entities.pub
+
+import com.persagy.labsl.models.entities.Anchor
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Table
+
+/**
+ * 锚点
+ *
+ * @author wx
+ */
+@Schema(description = "锚点")
+@Table(name = "labsl.anchor_pub")
+class AnchorPub : Anchor(), Serializable
+

+ 49 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/AttachObjectIdsPub.kt

@@ -0,0 +1,49 @@
+package com.persagy.labsl.models.entities.pub
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 图例节点与对象的关系
+ *
+ * @author  wx
+ * @date  2020/9/17 16:35
+ */
+@Schema(description = "图例节点与对象的关系")
+@Table(name = "labsl.attach_object_ids_pub")
+class AttachObjectIdsPub : SBaseEntity(), Serializable {
+
+    /** 全局id */
+    @Schema(description = "全局id")
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 图例节点id */
+    @Schema(description = "图例节点id",required = true )
+    @Id
+    @Column(name = "node_id")
+    var nodeId: String? = null
+
+    /** 对象id */
+    @Schema(description = "对象id",required = true )
+    @Id
+    @Column(name = "object_id")
+    var objectId: String? = null
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,4回收站 ,0发布)")
+    @Column(name = "state")
+    var state: Int? = 1
+
+
+} // Class AttachObjectIds

+ 24 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/ElementsPub.kt

@@ -0,0 +1,24 @@
+package com.persagy.labsl.models.entities.pub
+
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.validation.Valid
+
+/**
+ * 系统图展示所需数据
+ *
+ * @author wx
+ */
+class ElementsPub : Serializable {
+
+    @Schema(description = "图例节点")
+    @Valid
+    var nodes : ArrayList<NodePub>? = null
+
+    @Schema(description = "文本注释,图上的图片说明")
+    var markers : ArrayList<MarkersPub>? = null
+
+    @Schema(description = "管线对象")
+    var relations : ArrayList<RelationPub>? = null
+
+} // Class Elements

+ 110 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/GraphPub.kt

@@ -0,0 +1,110 @@
+package com.persagy.labsl.models.entities.pub
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import java.util.*
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 图例
+ *
+ * @author wx
+ */
+@Schema(description = "图例")
+@Table(name = "labsl.graph_pub")
+class GraphPub : SBaseEntity(), Serializable {
+
+    /** 全局id */
+    @Schema(description = "全局id" )
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 图类型id */
+    @Schema(description = "图类型id",required = true )
+    @Id
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 图名称 */
+    @Schema(description = "图名称")
+    @Column(name = "name")
+    var name: String? = null
+
+    /** 图分类id */
+    @Schema(description = "图分类id")
+    @Column(name = "category_id")
+    var categoryId: String? = null
+
+    /** 项目id */
+    @Schema(description = "项目id")
+    @Column(name = "project_id")
+    var projectId: String? = null
+
+    /** 建筑id */
+    @Schema(description = "建筑id")
+    @Column(name = "building_id")
+    var buildingId: String? = null
+
+    /** 楼层id */
+    @Schema(description = "楼层id")
+    @Column(name = "floor_id")
+    var floorId: String? = null
+
+    /** 说明 */
+    @Schema(description = "说明")
+    @Column(name = "note")
+    var note: String? = null
+
+    /** 版本号 */
+    @Schema(description = "版本号")
+    @Column(name = "version")
+    var version: String? = null
+
+    @Schema(description = "系统图展示所需数据")
+    var elements: ElementsPub? = null
+
+    /** 移至回收站时间 */
+    @Schema(description = "移至回收站时间")
+    @Column(name = "del_time")
+    var delTime: Date? = null
+
+    /** 移至回收站时间 */
+    @Schema(description = "移至回收站时间 , false 正常,true 以至回收站")
+    @Column(name = "is_available")
+    var isAvailable: Boolean? = false
+
+    /** 内部版本号 */
+    @Schema(description = "内部版本号")
+    @Column(name = "tag_version")
+    var tagVersion: Int? = null
+
+//    /** 内部版本号 */
+//    @Schema(description = "是否发布(true 发布、false 未发布)")
+//    @Column(name = "is_pub")
+//    var isPub: Boolean = false
+
+    /** 图片Key */
+    @Schema(description = "图片Key")
+    @Column(name = "pic")
+    var pic: String? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,0发布)")
+    @Column(name = "state")
+    var state: Int? = null
+
+    /** 页面尺寸 */
+    @Schema(description = "页面尺寸")
+    @Column(name = "page_size")
+    var pageSize: HashMap<String, Any?>? = null
+
+    /** 标签 */
+    @Schema(description = " 标签 ")
+    @Column(name = "label")
+    var label: ArrayList<String>? = null
+
+} // Class Graph

+ 16 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/MarkersPub.kt

@@ -0,0 +1,16 @@
+package com.persagy.labsl.models.entities.pub
+
+import com.persagy.labsl.models.entities.Markers
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Table
+
+/**
+ * 文本注释,图上的图片说明
+ *
+ * @author wx
+ */
+@Schema(description = "文本注释,图上的图片说明")
+@Table(name = "labsl.marker_pub")
+class MarkersPub : Markers(), Serializable
+

+ 108 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/NodePub.kt

@@ -0,0 +1,108 @@
+package com.persagy.labsl.models.entities.pub
+
+import com.persagy.labsl.models.entities.Pos
+import com.persagy.labsl.models.entities.Size
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 图例节点
+ *
+ * @author wx
+ */
+@Schema(description = "图例节点")
+@Table(name = "labsl.node_pub")
+class NodePub : SBaseEntity(), Serializable {
+
+    /** 全局id */
+    @Schema(description = "全局id" )
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 图例节点id */
+    @Schema(description = "图例节点id",required = true )
+    @Id
+    @Column(name = "node_id")
+    var nodeId: String? = null
+
+    /** 图例节点名称 */
+    @Schema(description = "图例节点名称")
+    @Column(name = "name")
+    var name: String? = null
+
+    /** 图例类型 None/Line/Zone/Image:非图例/线条/区域类型/图标 */
+    @Schema(description = "图例类型 None/Line/Zone/Image:非图例/线条/区域类型/图标")
+    @Column(name = "graph_element_type")
+    var graphElementType: String? = null
+
+    /** 图元ID */
+    @Schema(description = "图元ID")
+    @Column(name = "graph_element_id")
+    var graphElementId: String? = null
+
+    /** 图例数量 */
+    @Schema(description = "图例数量")
+    @Column(name = "num")
+    var num: Int? = null
+
+    /** 节点类型(image / zone) */
+    @Schema(description = "节点类型(image / zone)")
+    @Column(name = "type")
+    var type: String? = null
+
+    /** 位置信息 */
+    @Schema(description = "位置信息")
+    @Column(name = "pos")
+    var pos: Pos? = null
+
+    /** 缩放 */
+    @Schema(description = "缩放")
+    @Column(name = "scale")
+    var scale: Pos? = null
+
+    /** 旋转 */
+    @Schema(description = "旋转")
+    @Column(name = "rolate")
+    var rolate: Pos? = null
+
+    /** 大小 */
+    @Schema(description = "大小")
+    @Column(name = "size")
+    var size: Size? = null
+
+    /** 轮廓线 */
+    @Schema(description = "轮廓线")
+    @Column(name = "outline")
+    var outline: ArrayList<ArrayList<Pos>>? = null
+
+    @Schema(description = "应用自定义")
+    @Column(name = "properties")
+    var properties : HashMap<String,Any?>? = null
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Column(name = "graph_id")
+    var graphId: String? = null
+
+    /** 锚点列表 */
+    @Schema(description = "锚点列表")
+    var anchorList: ArrayList<AnchorPub>? = null
+
+    @Schema(description = "图例节点与对象的关系")
+    var attachObjectIds: ArrayList<AttachObjectIdsPub>? = null
+
+    /** 图状态(1一般,2待审核,3审核完成,0发布) */
+    @Schema(description = "图状态(1一般,2待审核,3审核完成,0发布)")
+    @Column(name = "state")
+    var state: Int? = null
+
+    @Schema(description = "线的绘图样式")
+    @Column(name = "style")
+    var style : HashMap<String,Any?>? = null
+
+} // Class

+ 16 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/entities/pub/RelationPub.kt

@@ -0,0 +1,16 @@
+package com.persagy.labsl.models.entities.pub
+
+import com.persagy.labsl.models.entities.Relation
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Table
+
+/**
+ * 管线对象
+ *
+ * @author wx
+ */
+@Schema(description = "管线对象")
+@Table(name = "labsl.relation_pub")
+class RelationPub : Relation(), Serializable
+

+ 17 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/request/GraphCategoryRequest.kt

@@ -0,0 +1,17 @@
+package com.persagy.labsl.models.request
+
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+
+/**
+ * 系统图类型
+ * @author  wx
+ * @date  2020/9/17 10:42
+ */
+class GraphCategoryRequest : Serializable {
+
+    /** 类型开关 true  获取所有 false 获取已有图形的类型 */
+    @Schema(description = "类型开关 true  获取所有 false 获取已有图形的类型")
+    var switch: Boolean = true
+
+} // Class GraphCategoryRequest

+ 32 - 0
labsl/src/main/kotlin/com/persagy/labsl/models/response/SCommonResponse.kt

@@ -0,0 +1,32 @@
+package com.persagy.labsl.models.response
+
+import com.persagy.service.models.enums.SResponseType
+import io.swagger.v3.oas.annotations.media.Schema
+
+/**
+ * 返回体
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ * @date  2020/6/9 14:56
+ */
+open class SCommonResponse<ENTITY: Any>(result: SResponseType? = SResponseType.success, message: String? = null) {
+
+    /** 结果 */
+    @Schema(description = "结果")
+    var result: SResponseType? = SResponseType.failure
+    /** 消息 */
+    @Schema(description = "消息")
+    var message: String? = ""
+
+    /** 结果 */
+    @Schema(description = "结果")
+    var content: ENTITY? = null
+
+    /** 初始化 */
+    init {
+        this.result = result
+        this.message = message
+    } // init()
+
+
+}

+ 13 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/AnchorService.kt

@@ -0,0 +1,13 @@
+package com.persagy.labsl.services
+
+import com.persagy.labsl.models.entities.Anchor
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+
+/**
+ * 锚点服务
+ *
+ * @author wx
+ */
+object AnchorService  : SObjectService<Anchor>(SMybatisDao(Anchor::class.java)) {
+} // Object AnchorService

+ 15 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/AttachObjectIdsServices.kt

@@ -0,0 +1,15 @@
+package com.persagy.labsl.services
+
+import com.persagy.labsl.models.entities.AttachObjectIds
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+
+/**
+ * 图例节点与对象的关系服务
+ *
+ * @author  wx
+ * @date  2020/9/17 17:02
+ */
+object AttachObjectIdsServices : SObjectService<AttachObjectIds>(SMybatisDao(AttachObjectIds::class.java)){
+
+} // Object AttachObjectIdsServices

+ 41 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/CustomService.kt

@@ -0,0 +1,41 @@
+package com.persagy.labsl.services
+
+import com.persagy.labsl.models.entities.auxiliary.CategoryCode
+import com.persagy.labsl.services.mappers.CustomMapper
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+
+/**
+ * 自定义SQL 服务
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ * @date  2020/9/17 12:09
+ */
+@Service
+class CustomService {
+
+    /** 实例化 mapper 对象 */
+    @Autowired
+    lateinit var customMapper: CustomMapper
+
+    /**
+     * 草稿箱 已有类型
+     *
+     * @param projectId     项目id
+     * @return 类型列表
+     */
+    fun draftsCategory(projectId: String): ArrayList<CategoryCode>?{
+        return customMapper.calcAffected(projectId)
+    }  // Fun draftsCategory()
+
+    /**
+     * 已发布 类型
+     *
+     * @param projectId     项目id
+     * @return 类型列表
+     */
+    fun pubCategory(projectId: String): ArrayList<CategoryCode>?{
+        return customMapper.pubCategory(projectId)
+    } // Fun pubCategory()
+
+} // Class CustomService

+ 163 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/GraphCategoryService.kt

@@ -0,0 +1,163 @@
+package com.persagy.labsl.services
+
+import com.persagy.database.SFilter
+import com.persagy.labsl.models.entities.GraphCategory
+import com.persagy.labsl.models.request.GraphCategoryRequest
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+import com.persagy.service.SPageContext
+import com.persagy.service.models.enums.SResponseType
+import com.persagy.service.models.responses.SQueryResponse
+import com.persagy.service.utils.SSpringContextUtil
+
+/**
+ * 分类服务
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ * @date  2020/9/15 11:38
+ */
+object GraphCategoryService : SObjectService<GraphCategory>(SMybatisDao(GraphCategory::class.java)) {
+
+    /** 自定义sql */
+    private val customMapper by lazy {
+        SSpringContextUtil.getBean(CustomService::class.java) as CustomService
+    } // customMapper
+
+    /**
+     * 系统图分类查询
+     *
+     * @param request   查询条件对象
+     * @return 查询结果
+     */
+    fun graphCategoryQuery(request: GraphCategoryRequest): SQueryResponse<GraphCategory> {
+        /** 项目id */
+        val projectId = SPageContext.getHeader("projectId")
+        val sQueryResponse = SQueryResponse<GraphCategory>()
+        return try {
+            if (request.switch) {
+                val graphCategoryList = select(SFilter.isNull("parentId")).exec()
+                for (graphCategory in graphCategoryList) {
+                    val treeClimate = treeClimate(graphCategory.id!!, true)
+                    if (treeClimate.size > 0) {
+                        graphCategory.categoryList = treeClimate
+                    }
+                }
+                sQueryResponse.content = graphCategoryList
+                sQueryResponse.total = graphCategoryList.size.toLong()
+                sQueryResponse.result = SResponseType.success
+                sQueryResponse
+            } else {
+                val calcAffectedList = customMapper.draftsCategory(projectId!!)
+                val pubCategoryList = customMapper.pubCategory(projectId)
+                val set = HashSet<String>()
+                if (!pubCategoryList.isNullOrEmpty() || !calcAffectedList.isNullOrEmpty()) {
+                    if (!pubCategoryList.isNullOrEmpty()) {
+                        for (pubCategory in pubCategoryList) {
+                            set.add(pubCategory.categoryId!!)
+                        }
+                    }
+                    if (!calcAffectedList.isNullOrEmpty()) {
+                        for (calcAffected in calcAffectedList) {
+                            set.add(calcAffected.categoryId!!)
+                        }
+                    }
+                    val graphCategoryList = select(SFilter.isNull("parentId")).exec()
+                    for (graphCategory in graphCategoryList) {
+                        val treeClimate = treeClimate(graphCategory.id!!, true)
+                        if (treeClimate.size > 0) {
+                            graphCategory.categoryList = treeClimate
+                        }
+                    }
+                    for (id in set) {
+                        for (graphCategory in graphCategoryList) {
+                            if (graphCategory.id == id) {
+                                graphCategory.sign = true
+                            }
+                            if (!graphCategory.categoryList.isNullOrEmpty()) {
+                                val categoryList = graphCategory.categoryList!!
+                                for (category in categoryList) {
+                                    if (category.id == id) {
+                                        category.sign = true
+                                        graphCategory.sign = true
+                                    }
+                                    if (!category.categoryList.isNullOrEmpty()) {
+                                        val categoryList1 = category.categoryList!!
+                                        for (category2 in categoryList1) {
+                                            if (category2.id == id) {
+                                                category2.sign = true
+                                                category.sign = true
+                                                graphCategory.sign = true
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    val iterator = graphCategoryList.iterator()
+                    while (iterator.hasNext()) {
+                        val next = iterator.next()
+                        if (next.sign) {
+                            if (!next.categoryList.isNullOrEmpty()) {
+                                val iterator1 = next.categoryList!!.iterator()
+                                while (iterator1.hasNext()) {
+                                    val next1 = iterator1.next()
+                                    if (next1.sign) {
+                                        if (!next1.categoryList.isNullOrEmpty()) {
+                                            val iterator2 = next1.categoryList!!.iterator()
+                                            while (iterator2.hasNext()) {
+                                                val next2 = iterator2.next()
+                                                if (!next2.sign) {
+                                                    iterator2.remove()
+                                                }
+                                            }
+                                        }
+                                    } else {
+                                        iterator1.remove()
+                                    }
+                                }
+                            }
+                        } else {
+                            iterator.remove()
+                        }
+                    }
+                    sQueryResponse.content = graphCategoryList
+                    sQueryResponse.total = graphCategoryList.size.toLong()
+                } else {
+                    sQueryResponse.content = ArrayList()
+                }
+                sQueryResponse.result = SResponseType.success
+                sQueryResponse
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            sQueryResponse.result = SResponseType.failure
+            sQueryResponse
+        }
+    } // Fun graphCategoryQuery()
+
+    /**
+     * 气候区 递归查询
+     *
+     * @param  parent        外键关系值
+     * @param  hasChildren  是否进行递归查询
+     * @return 类型列表
+     */
+    private fun treeClimate(parent: String, hasChildren: Boolean = true): ArrayList<GraphCategory> {
+        val content = select("parentId" to parent).exec()
+        if (hasChildren) {
+            for (item in content) {
+                try {
+                    val children = treeClimate(item.id!!)
+                    if (children.size > 0) {
+                        item.categoryList = children
+                    }
+                } catch (e: Exception) {
+                    // DO NOTHING
+                }
+            }
+        }
+        return content
+    } // Function treeClimate()
+
+} // Object GraphCategoryService

+ 864 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/GraphService.kt

@@ -0,0 +1,864 @@
+package com.persagy.labsl.services
+
+import cn.sagacloud.server.datacenter.utils.IdUtils
+import com.persagy.base.extensions.toJson
+import com.persagy.database.SFilter
+import com.persagy.labsl.models.entities.Elements
+import com.persagy.labsl.models.entities.Graph
+import com.persagy.labsl.models.entities.pub.*
+import com.persagy.labsl.models.response.SCommonResponse
+import com.persagy.labsl.services.pub.GraphPubService
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+import com.persagy.service.SPageContext
+import com.persagy.service.models.enums.SResponseType
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import org.slf4j.LoggerFactory
+import java.text.SimpleDateFormat
+import java.util.*
+import kotlin.collections.ArrayList
+
+/**
+ * 图服务
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ */
+object GraphService : SObjectService<Graph>(SMybatisDao(Graph::class.java)) {
+
+    /** 日志 */
+    private val logger = LoggerFactory.getLogger(GraphService::class.java)
+    /** 发布的图例节点服务 */
+    private val nodePubService = SObjectService(SMybatisDao(NodePub::class.java))
+    /** 注释、说明 */
+    private val markersPubService = SObjectService(SMybatisDao(MarkersPub::class.java))
+    /** 管线对象 */
+    private val relationPubService = SObjectService(SMybatisDao(RelationPub::class.java))
+    /** 锚点 */
+    private val anchorPubService = SObjectService(SMybatisDao(AnchorPub::class.java))
+    /** 图例节点与对象的关系 */
+    private val attachObjectIdsPubService = SObjectService(SMybatisDao(AttachObjectIdsPub::class.java))
+
+    /**
+     * 创建之前回调
+     *
+     * @param entity    图例对象
+     */
+    override fun onCreateBefore(entity: Graph): Boolean {
+        /** 项目id */
+        val projectId = SPageContext.getHeader("projectId")
+        // id 赋值
+        if (entity.id.isNullOrEmpty()){
+            entity.id = IdUtils.uuidCreate()
+        }
+        if (entity.graphId.isNullOrEmpty()){
+            entity.graphId = IdUtils.uuidCreate()
+        }
+        if (entity.version.isNullOrEmpty())
+            entity.version = "2.0.1"
+
+        if (entity.projectId.isNullOrEmpty()){
+            entity.projectId = projectId
+        }
+        return super.onCreateBefore(entity)
+    } // Fun onCreateBefore()
+
+    /**
+     * 创建图
+     *
+     * @param graph   图对象
+     * @return 图形对象列表
+     */
+    fun save(graph: Graph): SCreateResponse<Graph> {
+        logger.debug("保存图形:${graph.toJson()}")
+        val sCreateResponse = SCreateResponse<Graph>()
+        /** 项目id */
+        val projectId = SPageContext.getHeader("projectId")
+        //开启事务
+        openTransaction()
+        // 未发布
+        if (graph.id.isNullOrEmpty()) {
+            // id赋值
+            graph.id = UUID.randomUUID().toString().replace("-", "")
+        }
+        if (graph.graphId.isNullOrEmpty()){
+            graph.graphId = UUID.randomUUID().toString().replace("-", "")
+        }
+        graph.projectId = projectId!!
+        /** 清除以前的版本 */
+        delOldData(graph)
+        /** 版本号 */
+        if (graph.version.isNullOrEmpty()) {
+            graph.version = "2.0.1"
+        } else {
+            val listVersion = graph.version!!.split(".")
+            val num = listVersion[2].toInt() + 1
+            graph.version = listVersion[0] + "." + listVersion[1] + "." + num
+        }
+        graph.state = 1
+        val insertGraph = insert(graph)
+        if (!insertGraph) {
+            // 事务回滚
+            backTransaction()
+            sCreateResponse.result = SResponseType.failure
+            return  sCreateResponse
+        }
+        if (graph.elements != null) {
+            val nodesList = graph.elements!!.nodes
+            if (!nodesList.isNullOrEmpty()) {
+                for (nodes in nodesList) {
+                    nodes.graphId = graph.graphId
+                    nodes.id = graph.id
+                    if (nodes.nodeId.isNullOrEmpty()) {
+                        // id赋值
+                        nodes.nodeId = UUID.randomUUID().toString().replace("-", "")
+                    }
+                    val insertNode = NodeService.insert(nodes)
+                    if (!insertNode) {
+                        // 事务回滚
+                        backTransaction()
+                        sCreateResponse.result = SResponseType.failure
+                        return  sCreateResponse
+                    }
+                    val anchorList = nodes.anchorList
+                    if (!anchorList.isNullOrEmpty()) {
+                        for (anchor in anchorList) {
+                            anchor.graphId = graph.graphId
+                            anchor.id = graph.id
+                            anchor.nodeId = nodes.id
+                            if (anchor.anchorId.isNullOrEmpty()) {
+                                // id赋值
+                                anchor.anchorId = UUID.randomUUID().toString().replace("-", "")
+                            }
+                            val insertAnchor = AnchorService.insert(anchor)
+                            if (!insertAnchor) {
+                                // 事务回滚
+                                backTransaction()
+                                sCreateResponse.result = SResponseType.failure
+                                return  sCreateResponse
+                            }
+                        }
+                    }
+                    val attachObjectIdsList = nodes.attachObjectIds
+                    if (!attachObjectIdsList.isNullOrEmpty()){
+                        for (attachObjectIds in attachObjectIdsList){
+                            attachObjectIds.graphId = graph.graphId
+                            attachObjectIds.id = graph.id
+                            AttachObjectIdsServices.insert(attachObjectIds)
+                        }
+                    }
+                }
+            }
+            val markersList = graph.elements!!.markers
+            if (!markersList.isNullOrEmpty()) {
+                for (markers in markersList) {
+                    markers.graphId = graph.graphId
+                    markers.id = graph.id
+                    markers.state = 1
+                    if (markers.markerId.isNullOrEmpty()) {
+                        // id赋值
+                        markers.markerId = UUID.randomUUID().toString().replace("-", "")
+                    }
+                    val insertMarkers = MarkersService.insert(markers)
+                    if (!insertMarkers) {
+                        // 事务回滚
+                        backTransaction()
+                        sCreateResponse.result = SResponseType.failure
+                        return  sCreateResponse
+                    }
+                }
+            }
+            val relationsList = graph.elements!!.relations
+            if (!relationsList.isNullOrEmpty()) {
+                for (relations in relationsList) {
+                    relations.graphId = graph.graphId
+                    relations.state = 1
+                    relations.relationId = graph.id
+                    if (relations.relationId.isNullOrEmpty()) {
+                        // id赋值
+                        relations.relationId = UUID.randomUUID().toString().replace("-", "")
+                    }
+                    val insertRelation = RelationService.insert(relations)
+                    if (!insertRelation) {
+                        // 事务回滚
+                        backTransaction()
+                        sCreateResponse.result = SResponseType.failure
+                        return  sCreateResponse
+                    }
+                }
+            }
+        }
+        // 提交事务
+        commitTransaction()
+        sCreateResponse.result = SResponseType.success
+        sCreateResponse.entityList = arrayListOf(graph)
+        return sCreateResponse
+    } // Fun save()
+
+    /**
+     * 发布图形 回收站和草稿箱在一个表中,导致同一个图会有多个在回收站中需要配备多主键
+     *
+     * @param graphPub  待发布的图对象
+     * @return 已发布的图对象列表
+     */
+    fun pubDrawings(graphPub: GraphPub): SCreateResponse<GraphPub> {
+        return try {
+            val sCreateResponse = SCreateResponse<GraphPub>()
+            /** 项目id */
+            val projectId = SPageContext.getHeader("projectId")
+            val graph1 = Graph()
+            graph1.projectId = projectId!!
+            graph1.id = graphPub.id
+            graph1.graphId = graphPub.graphId
+            /** 查询草稿箱 */
+            val squeryBuilder = GraphPubService.select(
+                SFilter.eq("projectId", projectId!!),
+                SFilter.eq("id", graphPub.id!!),
+                SFilter.eq("graphId", graphPub.graphId!!),
+                SFilter.eq("state", 1)
+            )
+            val graph = squeryBuilder.table("labsl.graph").entity()
+            if (graph!=null){
+                //开启事务
+                openTransaction()
+                /** 清除已发布的老数据 */
+                delOldDataPub(graph1)
+                /** 版本号 */
+                val listVersion = graph.version!!.split(".")
+                val num = listVersion[1].toInt() + 1
+                graph.version = listVersion[0] + "." + num + "." + 0
+                graph.state = 0
+                graph.isAvailable = true
+    //            graph.isPub = true
+                val insert = GraphPubService.insert(graph)
+                if (!insert) {
+                    // 回滚
+                    backTransaction()
+                    sCreateResponse.result = SResponseType.failure
+                    return  sCreateResponse
+                }
+                /** 子节点 */
+                val nodebuilder = nodePubService.select(
+    //                SFilter.eq("projectId", projectId!!),
+                    SFilter.eq("graphId", graph.graphId!!),
+                    SFilter.eq("id", graphPub.id!!),
+                    SFilter.eq("state", 1)
+                )
+                val nodePubList = nodebuilder.table("labsl.node").exec()
+                if (nodePubList.size>0){
+                    for (nodePub in nodePubList){
+                        nodePub.id = graph.id
+                        nodePub.graphId = graph.graphId
+                        nodePub.state = 0
+                        val insert1 = nodePubService.insert(nodePub)
+                        if (!insert1){
+                            // 回滚
+                            backTransaction()
+                            sCreateResponse.result = SResponseType.failure
+                            return  sCreateResponse
+                        }
+                    }
+                }
+                val markersbuilder = markersPubService.select(
+    //                SFilter.eq("projectId", projectId!!),
+                    SFilter.eq("graphId", graph.graphId!!),
+                    SFilter.eq("id", graphPub.id!!),
+                    SFilter.eq("state", 1)
+                )
+                val markersPubList = markersbuilder.table("labsl.marker").exec()
+                if (markersPubList.size>0){
+                    for (markersPub in markersPubList){
+                        markersPub.id = graph.id
+                        markersPub.graphId = graph.graphId
+                        markersPub.state = 0
+                        val insert1 = markersPubService.insert(markersPub)
+                        if (!insert1){
+                            // 回滚
+                            backTransaction()
+                            sCreateResponse.result = SResponseType.failure
+                            return  sCreateResponse
+                        }
+                    }
+                }
+                val relationBuilder = relationPubService.select(
+    //                SFilter.eq("projectId", projectId!!),
+                    SFilter.eq("graphId", graph.graphId!!),
+                    SFilter.eq("id", graphPub.id!!),
+                    SFilter.eq("state", 1)
+                )
+                val relationList = relationBuilder.table("labsl.relation").exec()
+                if (relationList.size>0){
+                    for (relation in relationList){
+                        relation.id = graph.id
+                        relation.graphId = graph.graphId
+                        relation.state = 0
+                        val insert1 = relationPubService.insert(relation)
+                        if (!insert1){
+                            // 回滚
+                            backTransaction()
+                            sCreateResponse.result = SResponseType.failure
+                            return  sCreateResponse
+                        }
+                    }
+                }
+                val anchorBuilder = anchorPubService.select(
+    //                SFilter.eq("projectId", projectId!!),
+                    SFilter.eq("graphId", graph.graphId!!),
+                    SFilter.eq("id", graphPub.id!!),
+                    SFilter.eq("state", 1)
+                )
+                val anchorList = anchorBuilder.table("labsl.anchor").exec()
+                if (anchorList.size>0){
+                    for (anchor in anchorList){
+                        anchor.id = graph.id
+                        anchor.graphId = graph.graphId
+                        anchor.state = 0
+                        val insert1 = anchorPubService.insert(anchor)
+                        if (!insert1){
+                            // 回滚
+                            backTransaction()
+                            sCreateResponse.result = SResponseType.failure
+                            return  sCreateResponse
+                        }
+                    }
+                }
+
+                val attachObjectIdsBuilder = attachObjectIdsPubService.select(
+    //                SFilter.eq("projectId", projectId!!),
+                    SFilter.eq("graphId", graph.graphId!!),
+                    SFilter.eq("id", graphPub.id!!),
+                    SFilter.eq("state", 1)
+                )
+                val attachObjectIdsList = attachObjectIdsBuilder.table("labsl.attach_object_ids").exec()
+                if (attachObjectIdsList.size>0){
+                    for (attachObjectIds in attachObjectIdsList){
+                        attachObjectIds.id = graph.id
+                        attachObjectIds.graphId = graph.graphId
+                        attachObjectIds.state = 0
+                        val insert1 = attachObjectIdsPubService.insert(attachObjectIds)
+                        if (!insert1){
+                            // 回滚
+                            backTransaction()
+                            sCreateResponse.result = SResponseType.failure
+                            return  sCreateResponse
+                        }
+                    }
+                }
+
+                /** 清除草稿箱图 */
+                delOldData(graph1)
+                // 提交事务
+                commitTransaction()
+                sCreateResponse.entityList = arrayListOf(graph)
+                sCreateResponse.result = SResponseType.success
+            }else{
+                sCreateResponse.result = SResponseType.failure
+                sCreateResponse.message = "草稿箱中没有待发布图形"
+            }
+            return sCreateResponse
+        } catch (e: Exception) {
+            e.printStackTrace()
+            SCreateResponse(SResponseType.failure,e.message!!)
+        }
+    } // Fun pubDrawings()
+
+    /**
+     * 清除草稿箱以前数据
+     *
+     * @param  graph   图对象
+     */
+    private fun delOldData(graph: Graph) {
+        logger.debug("保存图形:${graph.toJson()}")
+        /** 清除以前的版本 */
+        val entity = select(
+            SFilter.eq("projectId", graph.projectId!!),
+            SFilter.eq("id", graph.id!!),
+            SFilter.eq("graphId", graph.graphId!!)
+        ).entity()
+
+        if (entity != null) {
+            /** 清除之前的草稿记录 */
+            val delete = delete(
+                SFilter.eq("projectId", graph.projectId!!),
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            )
+            if (delete){
+                /** 清除图下子集 */
+                NodeService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+                MarkersService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+                RelationService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+                AnchorService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+                AttachObjectIdsServices.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+            }
+        }
+    } // Fun delOldData()
+
+    /**
+     * 草稿箱 - 清除草稿箱正在使用的草稿
+     *
+     * @param graph  图对象
+     */
+    private fun delOldDataTwo(graph: Graph) {
+        /** 清除以前的版本 */
+        val entity = select(
+            SFilter.eq("projectId", graph.projectId!!),
+            SFilter.eq("state", 1),
+            SFilter.eq("graphId", graph.graphId!!)
+        ).entity()
+
+        if (entity != null) {
+            /** 清除之前的草稿记录 */
+            val delete = delete(
+                SFilter.eq("projectId", graph.projectId!!),
+                SFilter.eq("state", 1),
+                SFilter.eq("graphId", graph.graphId!!)
+            )
+            if (delete){
+                /** 清除图下子集 */
+                NodeService.delete(
+                    SFilter.eq("state", 1),
+                    SFilter.eq("graphId", graph.graphId!!))
+                MarkersService.delete(
+                    SFilter.eq("state", 1),
+                    SFilter.eq("graphId", graph.graphId!!))
+                RelationService.delete(
+                    SFilter.eq("state", 1),
+                    SFilter.eq("graphId", graph.graphId!!))
+                AnchorService.delete(
+                    SFilter.eq("state", 1),
+                    SFilter.eq("graphId", graph.graphId!!))
+                AttachObjectIdsServices.delete(
+                    SFilter.eq("state", 1),
+                    SFilter.eq("graphId", graph.graphId!!))
+            }
+        }
+    } // Fun delOldData()
+
+    /**
+     * 清除已发布的老数据
+     *
+     * @param   graph   图对象
+     */
+    private fun delOldDataPub(graph: Graph) {
+        /** 清除以前的版本 */
+        val entity = GraphPubService.select(
+            SFilter.eq("projectId", graph.projectId!!),
+            SFilter.eq("id", graph.id!!),
+            SFilter.eq("graphId", graph.graphId!!)
+        ).entity()
+
+        if (entity != null) {
+            /** 清除之前的草稿记录 */
+            val delete = GraphPubService.delete(
+                SFilter.eq("projectId", graph.projectId!!),
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            )
+            if (delete){
+                /** 清除图下子集 */
+                nodePubService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+                markersPubService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+                relationPubService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+                anchorPubService.delete(
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!))
+            }
+        }
+    } // Fun delOldDataPub()
+
+    /**
+     * 开启事务
+     */
+    private fun openTransaction() {
+
+    } // Fun openTransaction()
+
+    /**
+     * 回滚事务
+     */
+    private fun backTransaction() {
+
+    } // Fun backTransaction()
+
+    /**
+     * 提交事务
+     */
+    private fun commitTransaction() {
+
+    } // Fun commitTransaction()
+
+
+    /**
+     * 草稿图、移至回收站 或移出回收站
+     *
+     * @param idList    图对象列表
+     * @return 操作结果
+     */
+    fun recycle(idList: ArrayList<Graph>): SBaseResponse {
+        val sBaseResponse = SBaseResponse()
+        if (!idList.isNullOrEmpty()) {
+            for (graph in idList) {
+                graph.delTime = time()
+                graph.state = 4
+                val list = ArrayList<String>()
+                list.add("delTime")
+                list.add("state")
+                update(graph, list)
+            }
+            sBaseResponse.result = SResponseType.success
+        } else {
+            sBaseResponse.result = SResponseType.failure
+        }
+        return sBaseResponse
+    } // Fun recycle()
+
+    /**
+     * 已发布图形移至回收站
+     *
+     * @param idList    图对象列表
+     * @return  操作结果
+     */
+    fun recyclePub(idList: ArrayList<Graph>): SBaseResponse{
+        val sBaseResponse = SBaseResponse()
+        /** 项目id */
+        val projectId = SPageContext.getHeader("projectId")
+        /** 开启事务 */
+        openTransaction()
+        if (!idList.isNullOrEmpty()){
+            for (graph in idList){
+                graph.projectId = projectId
+                val graphBuilder = GraphService.select(
+                    SFilter.eq("projectId", projectId!!),
+                    SFilter.eq("id", graph.id!!),
+                    SFilter.eq("graphId", graph.graphId!!)
+                )
+                val graphPub = graphBuilder.table("labsl.graph_pub").entity()
+                if (graphPub!=null){
+                    graphPub.id = IdUtils.uuidCreate()
+                    graphPub.state = 4
+                    val insert = GraphService.insert(graphPub)
+                    if (!insert){
+                        /** 回滚处理 */
+                        backTransaction()
+                        sBaseResponse.result = SResponseType.failure
+                        return sBaseResponse
+                    }
+                    val nodeBuilder = NodeService.select(
+                        SFilter.eq("id", graph.id!!),
+                        SFilter.eq("graphId", graph.graphId!!)
+                    )
+                    val nodeList = nodeBuilder.table("labsl.node_pub").exec()
+                    if (nodeList.size>0){
+                        for (node in nodeList){
+                            node.id = graphPub.id
+                            node.state = 4
+                            NodeService.insert(node)
+                        }
+                        val anchorBuilder = AnchorService.select(
+                            SFilter.eq("id", graph.id!!),
+                            SFilter.eq("graphId", graph.graphId!!)
+                        )
+                        val anchorList = anchorBuilder.table("labsl.anchor_pub").exec()
+                        if (anchorList.size>0){
+                            for (anchor in anchorList){
+                                anchor.id = graphPub.id
+                                anchor.state = 4
+                                AnchorService.insert(anchor)
+                            }
+                        }
+                        val attachObjectIdsBuilder = AttachObjectIdsServices.select(
+                            SFilter.eq("id", graph.id!!),
+                            SFilter.eq("graphId", graph.graphId!!)
+                        )
+                        val attachObjectIdsList = attachObjectIdsBuilder.table("labsl.attach_object_ids_pub").exec()
+                        if (attachObjectIdsList.size>0){
+                            for (attachObjectIds in attachObjectIdsList){
+                                attachObjectIds.id = graphPub.id
+                                attachObjectIds.state = 4
+                                AttachObjectIdsServices.insert(attachObjectIds)
+                            }
+                        }
+                    }
+
+                    val markersBuilder = MarkersService.select(
+                        SFilter.eq("id", graph.id!!),
+                        SFilter.eq("graphId", graph.graphId!!)
+                    )
+                    val markersList = markersBuilder.table("labsl.marker_pub").exec()
+                    if (markersList.size>0){
+                        for (markers in markersList){
+                            markers.id = graphPub.id
+                            markers.state = 4
+                            MarkersService.insert(markers)
+                        }
+                    }
+                    val relationBuilder = RelationService.select(
+                        SFilter.eq("id", graph.id!!),
+                        SFilter.eq("graphId", graph.graphId!!)
+                    )
+                    val relationList = relationBuilder.table("labsl.relation_pub").exec()
+                    if (relationList.size>0){
+                        for (relation in relationList ){
+                            relation.id = graphPub.id
+                            relation.state = 4
+                            RelationService.insert(relation)
+                        }
+                    }
+                    delOldDataPub(graph)
+                }
+
+            }
+            sBaseResponse.result = SResponseType.success
+        }else{
+            sBaseResponse.result = SResponseType.failure
+        }
+        return sBaseResponse
+    } // Fun recyclePub()
+
+    /**
+     * 草稿箱图形数据读取所有节点
+     *
+     * @param graphs    图对象
+     * @return 查询结果
+     */
+    fun readDrafts(graphs: Graph): SCommonResponse<Graph> {
+        val sQueryResponse = SCommonResponse<Graph>()
+        /** 项目id */
+        val projectId = SPageContext.getHeader("projectId")
+        val graph = select(
+            SFilter.eq("projectId", projectId!!),
+            SFilter.eq("id", graphs.id!!),
+            SFilter.eq("graphId", graphs.graphId!!)
+        ).entity()
+        if (graph!=null){
+
+            val nodeList = NodeService.select(
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            ).exec()
+            val elements = Elements()
+            if (nodeList.size>0){
+                for (node in nodeList){
+                    try {
+                        val attachObjectIdsList = AttachObjectIdsServices.select(
+                            SFilter.eq("id", graph.id!!),
+                            SFilter.eq("graphId", graph.graphId!!),
+                            SFilter.eq("nodeId", node.nodeId!!)
+                        ).exec()
+                        if (attachObjectIdsList.size>0){
+                            node.attachObjectIds = attachObjectIdsList
+                        }
+                        val anchorList = AnchorService.select(
+                            SFilter.eq("id", graph.id!!),
+                            SFilter.eq("graphId", graph.graphId!!),
+                            SFilter.eq("nodeId", node.nodeId!!)
+                        ).exec()
+                        if (anchorList.size>0){
+                            node.anchorList = anchorList
+                        }
+                    } catch (e: Exception) {
+                        e.printStackTrace()
+                    }
+                }
+                elements.nodes = nodeList
+            }
+            val markersList = MarkersService.select(
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            ).exec()
+            val relationList = RelationService.select(
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            ).exec()
+            if (relationList.size>0){
+                elements.relations = relationList
+            }
+            if (markersList.size>0){
+                elements.markers = markersList
+            }
+            graph.elements = elements
+            sQueryResponse.result = SResponseType.success
+            sQueryResponse.content = graph
+        }else{
+            sQueryResponse.result = SResponseType.failure
+        }
+        return sQueryResponse
+    } // Fun readDrafts()
+
+    /**
+     * 已发布图形数据读取所有节点
+     *
+     * @param graphPub  图对象
+     * @return 查询结果
+     */
+    fun readPub(graphPub: GraphPub): SCommonResponse<GraphPub>{
+        val sQueryResponse = SCommonResponse<GraphPub>()
+        /** 项目id */
+        val projectId = SPageContext.getHeader("projectId")
+        val graph = GraphPubService.select(
+            SFilter.eq("projectId", projectId!!),
+            SFilter.eq("id", graphPub.id!!),
+            SFilter.eq("graphId", graphPub.graphId!!)
+        ).entity()
+        if (graph!=null){
+
+            val nodeList = nodePubService.select(
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            ).exec()
+            val elements = ElementsPub()
+            if (nodeList.size>0){
+                for (node in nodeList){
+                    try {
+                        val attachObjectIdsList = attachObjectIdsPubService.select(
+                            SFilter.eq("id", graph.id!!),
+                            SFilter.eq("graphId", graph.graphId!!),
+                            SFilter.eq("nodeId", node.nodeId!!)
+                        ).exec()
+                        if (attachObjectIdsList.size>0){
+                            node.attachObjectIds = attachObjectIdsList
+                        }
+                        val anchorList = anchorPubService.select(
+                            SFilter.eq("id", graph.id!!),
+                            SFilter.eq("graphId", graph.graphId!!),
+                            SFilter.eq("nodeId", node.nodeId!!)
+                        ).exec()
+                        if (anchorList.size>0){
+                            node.anchorList = anchorList
+                        }
+                    } catch (e: Exception) {
+                        e.printStackTrace()
+                    }
+                }
+                elements.nodes = nodeList
+            }
+            val markersList = markersPubService.select(
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            ).exec()
+            val relationList = relationPubService.select(
+                SFilter.eq("id", graph.id!!),
+                SFilter.eq("graphId", graph.graphId!!)
+            ).exec()
+            if (relationList.size>0){
+                elements.relations = relationList
+            }
+            if (markersList.size>0){
+                elements.markers = markersList
+            }
+            graph.elements = elements
+            sQueryResponse.result = SResponseType.success
+            sQueryResponse.content = graph
+        }else{
+            sQueryResponse.result = SResponseType.failure
+        }
+        return sQueryResponse
+    } // Fun readPub()
+
+    /**
+     * 回收站-恢复
+     *
+     * @param graphs    图对象
+     * @return 处理结果
+     */
+    fun recovery(graphs: Graph): SBaseResponse{
+        /** 项目id */
+        val projectId = SPageContext.getHeader("projectId")
+        graphs.projectId = projectId
+        val graph = select(
+            SFilter.eq("projectId", projectId!!),
+            SFilter.eq("id", graphs.id!!),
+            SFilter.eq("graphId", graphs.graphId!!)
+        ).entity()
+        if (graph!=null){
+            val markersList = MarkersService.select(
+                SFilter.eq("id", graphs.id!!),
+                SFilter.eq("graphId", graphs.graphId!!)
+            ).exec()
+            val nodeList = NodeService.select(
+                SFilter.eq("id", graphs.id!!),
+                SFilter.eq("graphId", graphs.graphId!!)
+            ).exec()
+            val anchorList = AnchorService.select(
+                SFilter.eq("id", graphs.id!!),
+                SFilter.eq("graphId", graphs.graphId!!)
+            ).exec()
+            val attachObjectIdsList = AttachObjectIdsServices.select(
+                SFilter.eq("id", graphs.id!!),
+                SFilter.eq("graphId", graphs.graphId!!)
+            ).exec()
+            val relationList = RelationService.select(
+                SFilter.eq("id", graphs.id!!),
+                SFilter.eq("graphId", graphs.graphId!!)
+            ).exec()
+            /** 清除草稿箱数据 */
+            delOldDataTwo(graphs)
+
+            val listState = ArrayList<String>()
+            listState.add("State")
+            graph.state = 1
+            update(graph,listState)
+            if (!markersList.isNullOrEmpty()){
+                for (markers in markersList){
+                    markers.state = 1
+                    MarkersService.update(markers,listState)
+                }
+            }
+            if (!nodeList.isNullOrEmpty()){
+                for (node in nodeList){
+                    node.state = 1
+                    NodeService.update(node,listState)
+                }
+            }
+            if (!anchorList.isNullOrEmpty()){
+                for (anchor in anchorList){
+                    anchor.state = 1
+                    AnchorService.update(anchor,listState)
+                }
+            }
+            if (!attachObjectIdsList.isNullOrEmpty()){
+                for (attachObjectIds in attachObjectIdsList){
+                    attachObjectIds.state = 1
+                    AttachObjectIdsServices.update(attachObjectIds,listState)
+                }
+            }
+            if (!relationList.isNullOrEmpty()){
+                for (relation in relationList){
+                    relation.state = 1
+                    RelationService.update(relation,listState)
+                }
+            }
+        }
+        return SBaseResponse(SResponseType.success)
+    } // Fun recovery()
+
+    /**
+     * 当前时间
+     *
+     * @return 当前时间
+     */
+    private fun time():Date {
+        val df = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") //设置日期格式
+        println(df.format(Date())) // new Date()为获取当前系统时间
+        val format = df.format(Date())
+        return df.parse(format)
+    } // Fun time()
+
+} // Object GraphService

+ 120 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/MarkersService.kt

@@ -0,0 +1,120 @@
+package com.persagy.labsl.services
+
+import com.persagy.database.SFilter
+import com.persagy.labsl.models.entities.Markers
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+import com.persagy.service.models.enums.SResponseType
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import org.springframework.web.bind.annotation.RequestBody
+import java.util.*
+
+/**
+ * 文本注释,图上的图片说明
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ */
+object MarkersService : SObjectService<Markers>(SMybatisDao(Markers::class.java)) {
+    /**
+     * 创建说明
+     *
+     * @param request   创建的对象列表
+     * @return 返回结果
+     */
+    fun creates(request: SCreateRequest<Markers>): SCreateResponse<Markers> {
+        /** 返回结果对象 */
+        val sCreateResponse = SCreateResponse<Markers>()
+        /** 返回结果中的状态 */
+        sCreateResponse.result = SResponseType.failure
+        return try {
+            /** 项目 id */
+//            val projectId = SPageContext.getHeader("projectId")
+            /** 列表不可以为空 */
+            if (!request.content.isNullOrEmpty()) {
+                /** 遍历标记列表 */
+                for (markers in request.content) {
+                    /** 判断必传字段不可以为空 */
+                    if (markers.id.isNullOrEmpty() || markers.graphId.isNullOrEmpty() || markers.name.isNullOrEmpty()) {
+                        sCreateResponse.message = "注意必填字段不可以为空如 id、graphId、name"
+                        return sCreateResponse
+                    }
+                    /** 查询 id 和 graphId 是否存在,是否可以定位一个系统图 */
+                    val graphList =
+                        GraphService.select(SFilter.eq("id", markers.id!!), SFilter.eq("graphId", markers.graphId!!))
+                            .exec()
+                    /** 图 id 和 graphId 不存在*/
+                    if (graphList.size == 0) {
+                        sCreateResponse.message = "请检查 id 和 graphId 是否为已有系统图中的 id"
+                        return sCreateResponse
+                    }
+                }
+
+                /** 遍历标记列表 */
+                for (markers in request.content) {
+                    /** 判断标记id是否没有,为空赋值 */
+                    if (markers.markerId.isNullOrEmpty()) {
+                        markers.markerId = UUID.randomUUID().toString().replace("-", "")
+                    }
+
+                    /** 插入数据 */
+                    insert(markers)
+                }
+
+                sCreateResponse.entityList = request.content
+                sCreateResponse.result = SResponseType.success
+                sCreateResponse
+            } else {
+                sCreateResponse.message = "不可以传空列表"
+                return sCreateResponse
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            sCreateResponse.message = e.message!!
+            sCreateResponse
+        }
+    } // Fun creates()
+
+    /**
+     * 批量删除标识信息
+     *
+     * @param idList    标识信息对象列表
+     * @return 返回结果
+     */
+    fun deletes(@RequestBody idList: ArrayList<Markers>): SBaseResponse {
+        /** 返回结果对象 */
+        val sBaseResponse = SBaseResponse()
+        /** 返回结果状态 */
+        sBaseResponse.result = SResponseType.failure
+        return try {
+            /** 列表不可以为空 */
+            if (!idList.isNullOrEmpty()) {
+                /** 遍历标签信息列表 */
+                for (markers in idList) {
+                    /** 校验必填信息点 */
+                    if (markers.id.isNullOrEmpty() || markers.markerId.isNullOrEmpty()) {
+                        sBaseResponse.message = "注意接口说明必填字段"
+                        return sBaseResponse
+                    }
+                }
+
+                /** 遍历标签信息列表 */
+                for (markers in idList) {
+                    /** 删除对象 */
+                    delete(SFilter.eq("id",markers.id!!),SFilter.eq("markerId",markers.markerId!!))
+                }
+
+                /** 返回结果状态 */
+                sBaseResponse.result = SResponseType.success
+            }
+            /** 返回结果对象 */
+            sBaseResponse
+        } catch (e: Exception) {
+            e.printStackTrace()
+            /** 返回结果,状态、以及报错信息 */
+            SBaseResponse(SResponseType.failure,e.message!!)
+        }
+    } // Fun deletes()
+
+} // Object MarkersService

+ 132 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/NodeService.kt

@@ -0,0 +1,132 @@
+package com.persagy.labsl.services
+
+import com.persagy.database.SFilter
+import com.persagy.labsl.models.entities.Node
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+import com.persagy.service.models.enums.SResponseType
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import org.springframework.web.bind.annotation.RequestBody
+import java.util.*
+
+/**
+ * 图例节点服务
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ */
+object NodeService : SObjectService<Node>(SMybatisDao(Node::class.java)) {
+    /**
+     * 创建之前
+     *
+     * @param entity    图例节点
+     * @return 是否处理
+     */
+    override fun onCreateBefore(entity: Node): Boolean {
+        entity.id = UUID.randomUUID().toString().replace("-", "")
+        return super.onCreateBefore(entity)
+    } // Fun onCreateBefore()
+
+    /**
+     * 创建设备节点
+     *
+     * @param request   创建设备节点对象列表
+     * @return 返回结果
+     */
+    fun creates(request: SCreateRequest<Node>): SCreateResponse<Node> {
+        /** 返回结果对象 */
+        val sCreateResponse = SCreateResponse<Node>()
+        /** 返回结果中的状态 */
+        sCreateResponse.result = SResponseType.failure
+        return try {
+            /** 项目 id */
+//            val projectId = SPageContext.getHeader("projectId")
+            /** 列表不可以为空 */
+            if (!request.content.isNullOrEmpty()) {
+                /** 遍历标记列表 */
+                for (node in request.content) {
+                    /** 判断必传字段不可以为空 */
+                    if (node.id.isNullOrEmpty() || node.graphId.isNullOrEmpty() || node.name.isNullOrEmpty()) {
+                        sCreateResponse.message = "注意必填字段不可以为空如 id、graphId、name"
+                        return sCreateResponse
+                    }
+                    /** 查询 id 和 graphId 是否存在,是否可以定位一个系统图 */
+                    val graphList =
+                        GraphService.select(SFilter.eq("id", node.id!!), SFilter.eq("graphId", node.graphId!!))
+                            .exec()
+                    /** 图 id 和 graphId 不存在*/
+                    if (graphList.size == 0) {
+                        sCreateResponse.message = "请检查 id 和 graphId 是否为已有系统图中的 id"
+                        return sCreateResponse
+                    }
+                }
+
+                /** 遍历标记列表 */
+                for (node in request.content) {
+                    /** 判断标记id是否没有,为空赋值 */
+                    if (node.nodeId.isNullOrEmpty()) {
+                        node.nodeId = UUID.randomUUID().toString().replace("-", "")
+                    }
+
+                    /** 插入数据 */
+                   insert(node)
+                }
+
+                sCreateResponse.entityList = request.content
+                sCreateResponse.result = SResponseType.success
+                sCreateResponse
+            } else {
+                sCreateResponse.message = "不可以传空列表"
+                return sCreateResponse
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            sCreateResponse.message = e.message!!
+            sCreateResponse
+        }
+    } // Fun creates()
+
+    /**
+     * 批量删除设备节点
+     *
+     * @param idList    设备节点对象列表
+     * @return 返回结果
+     */
+    fun deletes(@RequestBody idList: ArrayList<Node>): SBaseResponse {
+        /** 返回结果对象 */
+        val sBaseResponse = SBaseResponse()
+        /** 返回结果状态 */
+        sBaseResponse.result = SResponseType.failure
+        return try {
+            /** 列表不可以为空 */
+            if (!idList.isNullOrEmpty()) {
+                /** 遍历设备节点列表 */
+                for (node in idList) {
+                    /** 校验必填信息点 */
+                    if (node.id.isNullOrEmpty() || node.nodeId.isNullOrEmpty()) {
+                        sBaseResponse.message = "注意接口说明必填字段"
+                        return sBaseResponse
+                    }
+                }
+
+                /** 遍历设备节点列表 */
+                for (node in idList) {
+                    /** 删除对象 */
+                    delete(SFilter.eq("id", node.id!!), SFilter.eq("nodeId", node.nodeId!!))
+                }
+
+                /** 返回结果状态 */
+                sBaseResponse.result = SResponseType.success
+            }
+            /** 返回结果对象 */
+            sBaseResponse
+        } catch (e: Exception) {
+            e.printStackTrace()
+            /** 返回结果,状态、以及报错信息 */
+            SBaseResponse(SResponseType.failure,e.message!!)
+        }
+    } // Fun deletes()
+
+
+} // Object NodeService

+ 133 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/RelationService.kt

@@ -0,0 +1,133 @@
+package com.persagy.labsl.services
+
+import com.persagy.database.SFilter
+import com.persagy.labsl.models.entities.Relation
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+import com.persagy.service.models.enums.SResponseType
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import org.springframework.web.bind.annotation.RequestBody
+import java.util.*
+
+/**
+ * 管线对象
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ */
+object RelationService : SObjectService<Relation>(SMybatisDao(Relation::class.java)){
+    /**
+     * 创建之前的操作
+     *
+     * @param entity    管线对象
+     * @return 是否处理
+     */
+    override fun onCreateBefore(entity: Relation): Boolean {
+        entity.id = UUID.randomUUID().toString().replace("-", "")
+        return super.onCreateBefore(entity)
+    } //
+
+
+    /**
+     * 创建管线对象
+     *
+     * @param request   创建管线对象列表
+     * @return 返回结果
+     */
+    fun creates(request: SCreateRequest<Relation>): SCreateResponse<Relation> {
+        /** 返回结果对象 */
+        val sCreateResponse = SCreateResponse<Relation>()
+        /** 返回结果中的状态 */
+        sCreateResponse.result = SResponseType.failure
+        return try {
+            /** 项目 id */
+//            val projectId = SPageContext.getHeader("projectId")
+            /** 列表不可以为空 */
+            if (!request.content.isNullOrEmpty()) {
+                /** 遍历管线列表 */
+                for (relation in request.content) {
+                    /** 判断必传字段不可以为空 */
+                    if (relation.id.isNullOrEmpty() || relation.graphId.isNullOrEmpty() || relation.name.isNullOrEmpty()) {
+                        sCreateResponse.message = "注意必填字段不可以为空如 id、graphId、name"
+                        return sCreateResponse
+                    }
+                    /** 查询 id 和 graphId 是否存在,是否可以定位一个系统图 */
+                    val graphList =
+                        GraphService.select(SFilter.eq("id", relation.id!!), SFilter.eq("graphId", relation.graphId!!))
+                            .exec()
+                    /** 图 id 和 graphId 不存在*/
+                    if (graphList.size == 0) {
+                        sCreateResponse.message = "请检查 id 和 graphId 是否为已有系统图中的 id"
+                        return sCreateResponse
+                    }
+                }
+
+                /** 遍历管线列表 */
+                for (relation in request.content) {
+                    /** 判断标记id是否没有,为空赋值 */
+                    if (relation.relationId.isNullOrEmpty()) {
+                        relation.relationId = UUID.randomUUID().toString().replace("-", "")
+                    }
+
+                    /** 插入数据 */
+                    insert(relation)
+                }
+
+                sCreateResponse.entityList = request.content
+                sCreateResponse.result = SResponseType.success
+                sCreateResponse
+            } else {
+                sCreateResponse.message = "不可以传空列表"
+                return sCreateResponse
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            sCreateResponse.message = e.message!!
+            sCreateResponse
+        }
+    } // Fun creates()
+
+    /**
+     * 批量删除管线信息
+     *
+     * @param idList    管线对象列表
+     * @return 返回结果
+     */
+    fun deletes(@RequestBody idList: ArrayList<Relation>): SBaseResponse {
+        /** 返回结果对象 */
+        val sBaseResponse = SBaseResponse()
+        /** 返回结果状态 */
+        sBaseResponse.result = SResponseType.failure
+        return try {
+            /** 列表不可以为空 */
+            if (!idList.isNullOrEmpty()) {
+                /** 遍历管线信息列表 */
+                for (relation in idList) {
+                    /** 校验必填信息点 */
+                    if (relation.id.isNullOrEmpty() || relation.relationId.isNullOrEmpty()) {
+                        sBaseResponse.message = "注意接口说明必填字段"
+                        return sBaseResponse
+                    }
+                }
+
+                /** 遍历管线信息列表 */
+                for (relation in idList) {
+                    /** 删除对象 */
+                    delete(SFilter.eq("id", relation.id!!), SFilter.eq("relationId", relation.relationId!!))
+                }
+
+                /** 返回结果状态 */
+                sBaseResponse.result = SResponseType.success
+            }
+            /** 返回结果对象 */
+            sBaseResponse
+        } catch (e: Exception) {
+            e.printStackTrace()
+            /** 返回结果,状态、以及报错信息 */
+            SBaseResponse(SResponseType.failure,e.message!!)
+        }
+    } // Fun deletes()
+
+
+} // Object RelationService

+ 26 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/mappers/CustomMapper.kt

@@ -0,0 +1,26 @@
+package com.persagy.labsl.services.mappers
+
+import com.persagy.labsl.models.entities.auxiliary.CategoryCode
+import org.apache.ibatis.annotations.Mapper
+import org.apache.ibatis.annotations.Param
+import org.apache.ibatis.annotations.Select
+import org.springframework.stereotype.Repository
+
+/**
+ * 自定义SQL
+ *
+ * @author  wx
+ * @date  2020/9/17 12:01
+ */
+@Repository
+@Mapper
+interface CustomMapper {
+    /** 未发布 */
+    @Select("SELECT category_id as categoryId FROM labsl.graph  WHERE project_id = #{projectId} AND state =1 GROUP BY category_id")
+    fun calcAffected(@Param("projectId") projectId: String) : ArrayList<CategoryCode>?
+
+    /** 已发布 */
+    @Select("SELECT category_id as categoryId FROM labsl.graph_pub  WHERE project_id = #{projectId} AND state =0 GROUP BY category_id")
+    fun pubCategory(@Param("projectId") projectId: String) : ArrayList<CategoryCode>?
+
+} // Interface CustomMapper

+ 21 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/pic/PictureService.kt

@@ -0,0 +1,21 @@
+package com.persagy.labsl.services.pic
+
+import com.persagy.labsl.models.entities.pic.Picture
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+import java.util.*
+
+/**
+ *
+ * @author  wx
+ * @date  2020/9/9 16:28
+ */
+object PictureService :  SObjectService<Picture>(SMybatisDao(Picture::class.java)) {
+
+    override fun onCreateBefore(entity: Picture): Boolean {
+        entity.id = UUID.randomUUID().toString().replace("-","")
+        return super.onCreateBefore(entity)
+    } // Fun
+
+
+} // Object PictureService

+ 12 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/pub/AnchorPubService.kt

@@ -0,0 +1,12 @@
+package com.persagy.labsl.services.pub
+
+import com.persagy.labsl.models.entities.pub.AnchorPub
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+
+/**
+ * 锚点服务
+ *
+ * @author wx
+ */
+object AnchorPubService  : SObjectService<AnchorPub>(SMybatisDao(AnchorPub::class.java))

+ 14 - 0
labsl/src/main/kotlin/com/persagy/labsl/services/pub/GraphPubService.kt

@@ -0,0 +1,14 @@
+package com.persagy.labsl.services.pub
+
+import com.persagy.labsl.models.entities.pub.GraphPub
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+
+/**
+ * 已发布图
+ *
+ * @author  wx
+ * @date  2020/9/14 18:15
+ */
+object GraphPubService : SObjectService<GraphPub>(SMybatisDao(
+    GraphPub::class.java))

+ 236 - 0
labsl/src/main/kotlin/com/persagy/labsl/utils/IdUtils.kt

@@ -0,0 +1,236 @@
+package cn.sagacloud.server.datacenter.utils
+
+import java.text.SimpleDateFormat
+import java.util.*
+
+
+/**
+ * id生成帮助类
+ *
+ * @author 张维新
+ */
+object IdUtils {
+
+    /**
+     * 生成项目id
+     *
+     * @param   code    城市六位编码
+     * @param   num     城市存在建筑的数量
+     * @return          返回项目id
+     */
+    fun projectIdCreate(code: String, num: Int): String {
+        try {
+            if (num + 1 > 9999) {
+                throw  SecurityException("建筑数量已超出最大值")
+            }
+            val nums = num + 1
+            val genId = String.format("%1$4s", nums).replace(' ', '0')
+            val sb = StringBuilder()
+            val appendId = sb.append("Pj").append(code).append(genId)
+
+            return appendId.toString()
+        } catch (e: Throwable) {
+            e.printStackTrace()
+        }
+        throw  SecurityException("id生成失败")
+    } // Function ProjectId
+
+    /**
+     * 生成建筑Id
+     *
+     * @param   projectId   项目id
+     * @return              建筑id
+     */
+    fun buildIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Bd")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val buildId = sb.append(bdid).append(uuId)
+        return buildId.toString()
+    } // Function buildIdCreate
+
+    /**
+     * 生成楼层Id
+     *
+     * @param   projectId   项目id
+     * @return              楼层id
+     */
+    fun floorIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Fl")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val floorId = sb.append(bdid).append(uuId)
+        return floorId.toString()
+    } // Function floorIdCreate
+
+    /**
+     * 生成空间Id
+     *
+     * @param   projectId   项目id
+     * @return              空间id
+     */
+    fun spaceIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Sp")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val spaceId = sb.append(bdid).append(uuId)
+        return spaceId.toString()
+    } // Function spaceIdCreate
+
+    /**
+     * 生成元空间Id
+     *
+     * @param   projectId   项目id
+     * @return              元空间id
+     */
+    fun iSpaceIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Si")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val siId = sb.append(bdid).append(uuId)
+        return siId.toString()
+    } // Function iSpaceIdCreate
+
+    /**
+     * 生成系统Id
+     *
+     * @param   projectId   项目id
+     * @return              系统id
+     */
+    fun systemIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Sy")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val systemId = sb.append(bdid).append(uuId)
+        return systemId.toString()
+    } // Function systemIdCreate
+
+    /**
+     * 生成设备Id
+     *
+     * @param   projectId   项目id
+     * @return              设备id
+     */
+    fun equipmentIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Eq")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val eqId = sb.append(bdid).append(uuId)
+        return eqId.toString()
+    } // Function equipmentIdCreate
+
+    /**
+     * 生成设备部件Id
+     *
+     * @param   projectId   项目id
+     * @return              设备部件id
+     */
+    fun equipmentComponentIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Ec")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val ecId = sb.append(bdid).append(uuId)
+        return ecId.toString()
+    } // Function equipmentComponentIdCreate
+
+    /**
+     * 生成设施Id
+     *
+     * @param   projectId   项目id
+     * @return              设施id
+     */
+    fun structureIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "St")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val stId = sb.append(bdid).append(uuId)
+        return stId.toString()
+    } // Function structureIdCreate
+
+    /**
+     * 生成设施部件Id
+     *
+     * @param   projectId   项目id
+     * @return              设施部件id
+     */
+    fun structureComponentIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Sc")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val scId = sb.append(bdid).append(uuId)
+        return scId.toString()
+    } // Function structureComponentIdCreate
+
+    /**
+     * 生成资产编码Id
+     *
+     * @param   projectId   项目id
+     * @return              设备资产编码id
+     */
+    fun peIdCreate(projectId: String): String {
+        val bdid = "Pe"
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val peId = sb.append(bdid).append(uuId)
+        return peId.toString()
+    } // Function peIdCreate
+
+    /**
+     * 生成竖井Id
+     *
+     * @param   projectId   项目id
+     * @return              竖井id
+     */
+    fun shaftIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "Sh")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val shId = sb.append(bdid).append(uuId)
+        return shId.toString()
+    } // Function shaftIdCreate
+
+    /**
+     * 生成租户Id
+     *
+     * @param   projectId   项目id
+     * @return              租户id
+     */
+    fun tenantIdCreate(projectId: String): String {
+        val bdid = projectId.replace("Pj", "VOTn")
+        val sb = StringBuilder()
+        val uuid = UUID.randomUUID().toString()
+        val uuId = uuid.replace("-", "")
+        val shId = sb.append(bdid).append(uuId)
+        return shId.toString()
+    } // Function shaftIdCreate
+
+    /**
+     * 生成uuid
+     *
+     * @return              uuid
+     */
+    fun uuidCreate(): String {
+        val uuid = UUID.randomUUID().toString()
+        return uuid.replace("-", "")
+    } // Function uuidCreate
+
+
+    fun time():String {
+        val df = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") //设置日期格式
+        println(df.format(Date())) // new Date()为获取当前系统时间
+        return df.format(Date())
+    }
+
+
+} // Object IdUtils

+ 98 - 0
labsl/src/main/kotlin/com/persagy/labsl/utils/LoggerUtils.kt

@@ -0,0 +1,98 @@
+package com.persagy.labsl.utils
+
+import org.slf4j.LoggerFactory
+
+/**
+ * 日志工具
+ *
+ * @author  wx
+ * @date  2020/9/9 16:47
+ */
+object LoggerUtils {
+
+      var logSign = true
+    /**
+     * debug 模式日志
+     */
+    fun debug( clazz: Class<Any>,content: String){
+        if (logSign){
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.debug(content)
+        }
+    } // Fun
+
+    /**
+     * debug 模式日志
+     */
+    fun debug( clazz: Class<Any>,key: String, content: String){
+        if (logSign) {
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.debug(key, content)
+        }
+    } // Fun
+
+    /**
+     * error 模式日志
+     */
+    fun error( clazz: Class<Any>,content: String){
+        if (logSign) {
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.error(content)
+        }
+    } // Fun
+
+    /**
+     * error 模式日志
+     */
+    fun error( clazz: Class<Any>,key: String, content: String){
+        if (logSign) {
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.error(key, content)
+        }
+    } // Fun
+
+    /**
+     * info 模式日志
+     */
+    fun info( clazz: Class<Any>,content: String){
+        if (logSign) {
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.info(content)
+        }
+    } // Fun
+
+    /**
+     * info 模式日志
+     */
+    fun info( clazz: Class<Any>,key: String, content: String){
+        if (logSign) {
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.info(key, content)
+        }
+    } // Fun
+
+    /**
+     * warn 模式日志
+     */
+    fun warn( clazz: Class<Any>,content: String){
+        if (logSign) {
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.warn(content)
+        }
+    } // Fun
+
+    /**
+     * warn 模式日志
+     */
+    fun warn( clazz: Class<Any>,key: String, content: String){
+        if (logSign) {
+            val logger = LoggerFactory.getLogger(clazz)
+            logger.warn(key, content)
+        }
+    } // Fun
+
+
+
+
+
+} // Object LoggerUtils

+ 18 - 0
labsl/src/main/resources/application-dev.yml

@@ -0,0 +1,18 @@
+server:
+  port: 8084
+
+spring:
+  datasource:
+#    url:                                jdbc:postgresql://172.16.44.234:5432/datacenter
+#    username:                           postgres
+#    password:                           123456
+#   url:                                jdbc:postgresql://60.205.177.43:5432/datacenter
+#   username:                           postgres
+#   password:                           123qwe!@#
+    url:                                jdbc:postgresql://39.102.40.239:5432/datacenter
+    username:                           postgres
+#    password:                           persagy_2020qwe!@#
+    password:                           cGVyc2FneV8yMDIwcXdlIUAj
+
+  activemq:
+    broker-url:                         tcp://172.16.42.210:61616

+ 17 - 0
labsl/src/main/resources/application-prod.yml

@@ -0,0 +1,17 @@
+server:
+  port: 8080
+
+spring:
+#  datasource:
+#    url:                                jdbc:postgresql://172.17.11.228:5432/datacenter
+#    username:                           postgres
+#    password:                           123qwe!@#
+
+  datasource:
+    url:                                jdbc:postgresql://172.17.100.16:5432/datacenter
+    username:                           postgres
+#    password:                           persagy_2020qwe!@#
+    password:                           cGVyc2FneV8yMDIwcXdlIUAj
+
+  activemq:
+    broker-url:                         tcp://activemq:61616

+ 71 - 0
labsl/src/main/resources/application.yml

@@ -0,0 +1,71 @@
+###############################################################################################################
+# spring-cloud相关配置
+eureka:
+  client:                                   #客户端注册进eureka服务列表内
+    service-url:
+      defaultZone:                          http://eureka-service:8761/eureka
+#启用监控
+management:
+  endpoints:
+    web:
+      exposure:
+        include:
+          - "*"  # 开放所有端点health,info,metrics,通过actuator/+端点名就可以获取相应的信息。默认打开health和info
+  endpoint:
+    health:
+      #未开启actuator/health时,我们获取到的信息是{"status":"UP"},status的值还有可能是 DOWN。开启后打印详细信息
+      show-details:                       always
+###############################################################################################################
+
+spring:
+  servlet:
+    multipart:
+      enabled: true
+      max-file-size: 10000MB
+      max-request-size: 10000MB
+
+  application:
+    name:                               labsl
+  mvc:
+    favicon:
+      enabled:                          true
+
+  jmx:
+    default-domain:                     labsl
+
+  datasource:
+    name:                               labsl
+    type:                               com.alibaba.druid.pool.DruidDataSource
+    driver-class-name:                  org.postgresql.Driver
+#    url:                                jdbc:postgresql://60.205.177.43:5432/datacenter
+#    username:                           postgres
+#    password:                           123qwe!@#
+
+  jackson:
+    date-format:                        yyyy-MM-dd HH:mm:ss
+    time-zone:                          Asia/Shanghai
+    default-property-inclusion:         non_null
+    # 首字母大写
+#    property-naming-strategy:           com.fasterxml.jackson.databind.PropertyNamingStrategy.PascalCaseStrategy
+    # 以下划线分隔全小写的单词
+    property-naming-strategy:           com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy
+    mapper:
+      # 属性按字母顺序输出
+     sort_properties_alphabetically:   true
+
+# spring-doc 配置
+springdoc:
+  # springdoc 扫描的包,多个包之间使用逗号分隔
+  packagesToScan:                           com.persagy.labsl
+  swagger-ui:
+    # API 组排序方式:asc 升序,desc 降序
+    groups-order:                           asc
+    # 标识排序方式:alpha 按字母升序排列
+    tags-sorter:                            alpha
+    # API 接口排序方式:alpha 按字母升序排列,method 按方法的定义顺序。
+    operations-sorter:                      alpha
+
+mybatis:
+  typeAliasesPackage:                   cn.sagacloud.server.datacenter.entities
+
+

+ 38 - 0
labsl/src/main/resources/logback-spring.xml

@@ -0,0 +1,38 @@
+<!--
+  ~ *********************************************************************************************************************
+  ~
+  ~                     :*$@@%$*:                         ;:                ;;    ;;
+  ~                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+  ~                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+  ~                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+  ~                  =@*                                  %!              @ $= % %@=   =%@!      %=
+  ~             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+  ~           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+  ~         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+  ~         $@*   ;@@@%=!:                *@*
+  ~         =@$    ;;;!=%@@@@=!           =@!
+  ~          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+  ~           ;%@@$=$@@%*       *@@@$=%@@%;
+  ~              ::;::             ::;::                                              All rights reserved.
+  ~
+  ~ *********************************************************************************************************************
+  -->
+
+<configuration scan="true" debug="false">
+    <contextName>scanbuilding</contextName>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{10}) - %cyan(%msg%n)</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 定义cn.sagacloud包的日志级别 -->
+    <logger name="com.persagy" level="debug" additivity="false">
+        <appender-ref ref="STDOUT"/>
+    </logger>
+
+    <!-- 定义日志级别 -->
+    <root level="ERROR">
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>

+ 17 - 0
labsl/src/test/kotlin/com/persagy/server/test/base/CaseBase.kt

@@ -0,0 +1,17 @@
+package com.persagy.server.test.base
+
+import com.persagy.server.labsl.LaBSLApp
+import lombok.extern.slf4j.Slf4j
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.testng.AbstractTestNGSpringContextTests
+import org.springframework.test.context.web.WebAppConfiguration
+
+/**
+ *
+ */
+@SpringBootTest(classes = [LaBSLApp::class])
+@WebAppConfiguration
+@Slf4j
+open class CaseBase : AbstractTestNGSpringContextTests() {
+
+} // Class CaseBase

+ 28 - 0
labsl/src/test/kotlin/com/persagy/server/test/services/GraphServiceTest.kt

@@ -0,0 +1,28 @@
+package com.persagy.server.test.services
+
+import com.persagy.server.test.base.CaseBase
+import org.testng.annotations.Test
+
+/**
+ * 图、测试
+ *
+ * @author wx
+ */
+//@RunWith(SpringRunner::class) //
+//@SpringBootTest(classes = [LaBSLApp::class])  // 加载spring  boot 配置
+//@Slf4j
+open class GraphServiceTest : CaseBase() {
+
+
+        @Test
+        fun graphCreate(){
+            System.out.println("测试中***********************************")
+            logger.info("test from logger...");
+
+
+        } // Fun
+
+
+
+
+} // Class GraphServiceTest

+ 108 - 0
meiku/build.gradle

@@ -0,0 +1,108 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*             
+ *         =@$    ;;;!=%@@@@=!           =@!      
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;                              
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+group rootProject.group
+version rootProject.version
+
+apply plugin: "kotlin"
+apply plugin: "org.jetbrains.dokka"
+apply plugin: "war"
+apply plugin: 'org.springframework.boot'
+apply plugin: 'io.spring.dependency-management'
+
+sourceCompatibility = JVM_TARGET
+
+compileKotlin {
+    kotlinOptions.jvmTarget = JVM_TARGET
+}
+compileTestKotlin {
+    kotlinOptions.jvmTarget = JVM_TARGET
+}
+
+dependencies {
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // kotlin 依赖
+    compile group: "org.jetbrains.kotlin", name: "kotlin-stdlib-jdk8", version: KOTLIN_VERSION
+    compile group: "org.jetbrains.kotlin", name: "kotlin-reflect", version: KOTLIN_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // spring boot 依赖
+    compile group: "org.springframework.boot", name: "spring-boot-starter-web", version: SPRING_BOOT_VERSION
+    compile group: "org.springframework.boot", name: "spring-boot-configuration-processor", version: SPRING_BOOT_VERSION
+    compile group: "org.springframework.boot", name: "spring-boot-starter-actuator", version: SPRING_BOOT_VERSION
+    compile group: "org.springframework.boot", name: "spring-boot-starter-logging", version: SPRING_BOOT_VERSION
+    //消息
+//    compile group: "org.springframework.boot", name: "spring-boot-starter-activemq", version: SPRING_BOOT_VERSION
+    providedCompile group: "org.springframework.boot", name:"spring-boot-starter-tomcat", version: SPRING_BOOT_VERSION
+    // spring boot 缓存
+    compile group:"org.springframework.boot", name:"spring-boot-starter-cache", version: SPRING_BOOT_VERSION
+    // 单元测试
+    compile group:"org.springframework.boot", name:"spring-boot-starter-test", version: SPRING_BOOT_VERSION
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // spring cloud 依赖
+//    compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka', version: SPRING_CLOUD_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // MySQL
+    // https://mvnrepository.com/artifact/mysql/mysql-connector-java
+//    compile group: 'mysql', name: 'mysql-connector-java', version: MYSQL_VERSION
+
+//    // PostgreSQL
+//    //https://mvnrepository.com/artifact/org.postgresql/postgresql
+//    compile group: 'org.postgresql',    name: 'postgresql',     version: POSTGRESQL_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // RESTful API 文档生成工具
+    // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui
+    compile group: 'org.springdoc', name: 'springdoc-openapi-ui', version: SPRING_DOC_VERSION
+//     https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-common
+    compile group: "org.springdoc", name: "springdoc-openapi-common", version: SPRING_DOC_VERSION
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // persagy依赖
+    compile group: "com.persagy", name: "persagy-kotlin-base", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-kotlin-database", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-kotlin-mybatis", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-kotlin-postgresql", version: PERSAGY_KOTLIN_VERSION
+    compile group: "com.persagy", name: "persagy-service-base", version: PERSAGY_SERVICE_VERSION
+    compile group: "com.persagy", name: "persagy-service-mybatis", version: PERSAGY_SERVICE_VERSION
+
+
+    // TestNG 测试框架
+    compile group: "org.testng", name: "testng", version: TESTNG_VERSION
+    // Log 工具
+    compile group: "org.projectlombok", name: "lombok", version: LOMBOK_VERSION
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+    //Gson
+    compile 'com.google.code.gson:gson:2.8.0'
+
+
+//    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//    // 二维码与条形码
+//    // https://mvnrepository.com/artifact/com.google.zxing/core
+//    compile group: "com.google.zxing", name: "core", version: ZXING_VERSION
+    
+}

+ 78 - 0
meiku/src/main/kotlin/com/persagy/meiku/MeiKuApp.kt

@@ -0,0 +1,78 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*
+ *         =@$    ;;;!=%@@@@=!           =@!
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+package com.persagy.meiku
+
+import org.mybatis.spring.annotation.MapperScan
+import org.slf4j.LoggerFactory
+import org.springframework.boot.SpringApplication
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.builder.SpringApplicationBuilder
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
+import org.springframework.context.annotation.ComponentScan
+
+
+/**
+ * 应用配置
+ *
+ * @author  Andy
+ */
+@ComponentScan(basePackages = ["com.persagy", "com.persagy.meiku"])           // 配置组件扫描路径
+@MapperScan("com.persagy", "com.persagy.meiku")                       // Mapper组件扫描路径
+@SpringBootApplication
+open class MeiKuApp : SpringBootServletInitializer() {
+    companion object {
+        // 日志
+        private val logger = LoggerFactory.getLogger(MeiKuApp::class.java)
+    } // Companion object
+
+    /**
+     * 配置应用
+     *
+     * @param   application     应用构建对象
+     */
+    override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
+        return application.sources(MeiKuApp::class.java)
+    } // Function configure
+
+//    /**
+//     * 配置FastJson
+//     *
+//     * @return  HttpMessageConverters
+//     */
+//    @Bean
+//    @Suppress("MoveLambdaOutsideParentheses")
+//    open fun jsonHttpMessageConverters(): SJsonHttpMessageConverter {
+//        val fastConverter = SJsonHttpMessageConverter()
+//        fastConverter.propertyNamingStrategy = com.alibaba.fastjson.PropertyNamingStrategy.CamelCase
+//        return fastConverter
+//    } // Function fastJsonHttpMessageConverters()
+
+} // Class Application
+
+/**
+ * Web应用入口
+ *
+ * @param   args        命令行参数
+ */
+fun main(args: Array<String>) {
+    SpringApplication.run(MeiKuApp::class.java, *args)
+    return
+} // Function main()

+ 141 - 0
meiku/src/main/kotlin/com/persagy/meiku/Swagger3Config.kt

@@ -0,0 +1,141 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*
+ *         =@$    ;;;!=%@@@@=!           =@!
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+package com.persagy.meiku
+
+import io.swagger.v3.oas.annotations.enums.ParameterIn
+import io.swagger.v3.oas.models.Components
+import io.swagger.v3.oas.models.OpenAPI
+import io.swagger.v3.oas.models.Operation
+import io.swagger.v3.oas.models.info.Contact
+import io.swagger.v3.oas.models.info.Info
+import io.swagger.v3.oas.models.info.License
+import io.swagger.v3.oas.models.media.StringSchema
+import io.swagger.v3.oas.models.parameters.Parameter
+import io.swagger.v3.oas.models.security.SecurityScheme
+import org.springdoc.core.GroupedOpenApi
+import org.springdoc.core.customizers.OperationCustomizer
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.ApplicationContext
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.web.method.HandlerMethod
+
+
+/**
+ * RESTful API文档生成器Swagger2配置
+ *
+ * @author  PLX
+ */
+@Configuration
+open class Swagger3Config {
+    /** 注入的 ApplicationContext */
+    @Autowired
+    lateinit var applicationContext: ApplicationContext
+
+    /** 标题 */
+    private val title = "数据管理平台 API"
+    /** API 版本号 */
+    private val version = "1.0"
+
+    val operationCustomizer = GlobalHeaderOperationCustomizer()
+
+
+
+    /**
+     * API 信息
+     */
+    @Bean
+    open fun openApi(): OpenAPI {
+        val contact = Contact().name("张维新").email("zhangweixin@sagacloud.cn")
+        return OpenAPI()
+            .components(
+                Components()
+                .addSecuritySchemes("basicScheme", SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")))
+            .info(
+                Info()
+                .title(title)
+                .version(version)
+                .termsOfService("http://www.persagy.com")
+                .contact(contact)
+                .license(
+                    License()
+                    .name("Apache 2.0")
+                    .url("http://www.persagy.com")))
+    }
+
+
+    @Bean
+    open fun publicApi(): GroupedOpenApi? {
+        return GroupedOpenApi.builder()
+            .group("默认")
+            .pathsToMatch("/**")
+            .addOperationCustomizer(operationCustomizer)
+            .build()
+    }
+
+
+    /**
+     * 字典 API 组
+     */
+//    @Bean
+//    open fun dictApiGroup(): GroupedOpenApi {
+//        return GroupedOpenApi.builder().group("asf").pathsToMatch("")
+//            .build()
+//
+//    }
+
+//    /**
+//     * 对象 API 组
+//     */
+//    @Bean
+//    open fun objectApiGroup(): GroupedOpenApi {
+//        return GroupedOpenApi.builder()
+//            .group("对象")
+//            .pathsToMatch("/object/**")
+//            .addOperationCustomizer(operationCustomizer)
+//            .build()
+//    }
+
+
+
+} // Class Swagger2Config
+
+/**
+ * 全局参数
+ *
+ * @author  庞利祥 <sybotan@126.com>
+ */
+class GlobalHeaderOperationCustomizer : OperationCustomizer {
+    /**
+     * 接口定义器
+     *
+     * @param   operation       接口
+     * @param   handlerMethod   原接口方法
+     * @return  新定义的接口
+     */
+    override fun customize(operation: Operation, handlerMethod: HandlerMethod): Operation {
+        val projectId = Parameter().`in`(ParameterIn.HEADER.toString())
+            .name("projectId").description("项目 id")
+            .schema(StringSchema()).required(false)
+        operation.addParametersItem(projectId)
+        return operation
+    }
+}

+ 46 - 0
meiku/src/main/kotlin/com/persagy/meiku/WebMvcConfg.kt

@@ -0,0 +1,46 @@
+/*
+ * ********************************************************************************************************************
+ *
+ *                     :*$@@%$*:                         ;:                ;;    ;;
+ *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+ *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+ *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+ *                  =@*                                  %!              @ $= % %@=   =%@!      %=
+ *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+ *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+ *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+ *         $@*   ;@@@%=!:                *@*
+ *         =@$    ;;;!=%@@@@=!           =@!
+ *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+ *           ;%@@$=$@@%*       *@@@$=%@@%;
+ *              ::;::             ::;::                                              All rights reserved.
+ *
+ * ********************************************************************************************************************
+ */
+
+package com.persagy.meiku
+
+//import com.persagy.service.interceptors.SPageInterceptor
+import org.slf4j.LoggerFactory
+import org.springframework.context.annotation.Configuration
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
+
+@Configuration
+open class WebMvcConfg: WebMvcConfigurerAdapter() {
+    companion object {
+        // 日志
+        private val logger = LoggerFactory.getLogger(WebMvcConfg::class.java)
+    } // Companion object
+    /**
+     * 配置拦截器
+     *
+     * @param   registry        拦截器注册器
+     */
+    override fun addInterceptors(registry : InterceptorRegistry) {
+        //registry.addInterceptor(AccessControlAllowOriginInterceptor()).addPathPatterns("/**")
+//        registry.addInterceptor(SPageInterceptor()).addPathPatterns("/**")
+        super.addInterceptors(registry)
+
+    } // Function addInterceptors()
+} // Class WebMvcConf()

+ 74 - 0
meiku/src/main/kotlin/com/persagy/meiku/controller/MeiKuAnchorController.kt

@@ -0,0 +1,74 @@
+package com.persagy.meiku.controller
+
+import com.persagy.meiku.models.entities.MeiKuAnchor
+import com.persagy.meiku.services.MeiKuAnchorService
+import com.persagy.service.models.requests.SCountRequest
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.requests.SQueryRequest
+import com.persagy.service.models.requests.SUpdateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCountResponse
+import com.persagy.service.models.responses.SCreateResponse
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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  wx
+ * @date  2020/9/21 14:50
+ */
+@Tag(name = "002、锚点")
+@RestController
+@RequestMapping("/anchor")
+class MeiKuAnchorController {
+
+    /**
+     * 创建图例
+     */
+    @Operation(summary = "创建锚点-批量", description= "")
+    @PostMapping("/create")
+    fun create(@RequestBody request: SCreateRequest<MeiKuAnchor>): SCreateResponse<MeiKuAnchor> {
+        return MeiKuAnchorService.createList(request)
+    } // Function create()
+
+    /**
+     * 更新锚点
+     */
+    @Operation(summary = "锚点修改-批量", description = "")
+    @PostMapping(value = ["/update"])
+    fun update(@RequestBody request: SUpdateRequest<MeiKuAnchor>): SBaseResponse {
+        return MeiKuAnchorService.updateList(request)
+    } // Function update()
+
+    /**
+     * 根据id删除锚点
+     */
+    @Operation(summary = "锚点删除", description = "")
+    @PostMapping(value = ["/delete"])
+    fun delete(@RequestBody idList: ArrayList<MeiKuAnchor>): SBaseResponse {
+        return MeiKuAnchorService.deleteByKeysList(idList)
+    } // Function delete()
+
+    /**
+     * 查询锚点信息
+     */
+    @Operation(summary = "查询锚点-批量", description = "")
+    @PostMapping(value = ["/query"])
+    fun query(@RequestBody request: SQueryRequest): SQueryResponse<MeiKuAnchor> {
+        return MeiKuAnchorService.pageQuery(request)
+    } // Function query()
+
+    @Operation(summary = "查询锚点统计", description = "")
+    @PostMapping(value = ["/count"])
+    fun count(@RequestBody request: SCountRequest): SCountResponse {
+        return MeiKuAnchorService.count(request)
+    } // Function count()
+
+
+} // Class MeiKuAnchorController

+ 88 - 0
meiku/src/main/kotlin/com/persagy/meiku/controller/MeiKuController.kt

@@ -0,0 +1,88 @@
+package com.persagy.meiku.controller
+
+import com.persagy.meiku.models.entities.MeiKu
+import com.persagy.meiku.models.response.SCommonResponse
+import com.persagy.meiku.services.MeiKuService
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.requests.SQueryRequest
+import com.persagy.service.models.requests.SUpdateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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  wx
+ * @date  2020/9/18 21:53
+ */
+@Tag(name = "001、图例库")
+@RestController
+@RequestMapping("/legend")
+class MeiKuController {
+
+    /**
+     * 创建图例
+     */
+    @Operation(summary= "创建图例-批量", description = "不包含状态和锚点")
+    @PostMapping("/create")
+    fun create(@RequestBody request: SCreateRequest<MeiKu>): SCreateResponse<MeiKu> {
+        return MeiKuService.createList(request)
+    } // Function create()
+
+    /**
+     * 创建图例-单个
+     */
+    @Operation(summary="创建图例-单个", description ="包含状态和锚点")
+    @PostMapping("/save")
+    fun save(@RequestBody meiku: MeiKu): SCreateResponse<MeiKu> {
+        return MeiKuService.save(meiku)
+    } // Function create()
+
+    /**
+     * 更新图例
+     */
+    @Operation(summary = "图例修改-批量", description = "不包含状态和锚点")
+    @PostMapping(value = ["/update"])
+    fun update(@RequestBody request: SUpdateRequest<MeiKu>): SBaseResponse {
+        return MeiKuService.updateList(request)
+    } // Function update()
+
+    @Operation(summary = "图例修改-单个", description = "包含状态和锚点")
+    @PostMapping(value = ["/revise"])
+    fun revise(@RequestBody meiku: MeiKu): SBaseResponse{
+        return MeiKuService.revise(meiku)
+    } // revise
+
+    /**
+     * 根据id删除图形
+     */
+    @Operation(summary = "图例删除", description = "")
+    @PostMapping(value = ["/delete"])
+    fun delete(@RequestBody idList: ArrayList<MeiKu>): SBaseResponse {
+        return MeiKuService.deleteByKeysList(idList)
+    } // Function delete()
+
+    /**
+     * 查询图形信息
+     */
+    @Operation(summary = "查询图例-批量", description = " 类型:category   级联:锚点(anchorList)状态:(state)  ")
+    @PostMapping(value = ["/query"])
+    fun query(@RequestBody request: SQueryRequest): SQueryResponse<MeiKu> {
+        return MeiKuService.pageQuery(request)
+    } // Function query()
+
+    @Operation(summary = "查询图例-单量", description = "包含状态和锚点")
+    @PostMapping(value = ["/read"])
+    fun read(@RequestBody meiku: MeiKu): SCommonResponse<MeiKu> {
+        return  MeiKuService.read(meiku)
+    } //
+
+
+} // Class MeiKuController

+ 73 - 0
meiku/src/main/kotlin/com/persagy/meiku/controller/MeiKuStateController.kt

@@ -0,0 +1,73 @@
+package com.persagy.meiku.controller
+
+import com.persagy.meiku.models.entities.MeiKuState
+import com.persagy.meiku.services.MeiKuStateService
+import com.persagy.service.models.requests.SCountRequest
+import com.persagy.service.models.requests.SCreateRequest
+import com.persagy.service.models.requests.SQueryRequest
+import com.persagy.service.models.requests.SUpdateRequest
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCountResponse
+import com.persagy.service.models.responses.SCreateResponse
+import com.persagy.service.models.responses.SQueryResponse
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+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  wx
+ * @date  2020/9/21 14:50
+ */
+@Tag(name = "003、状态")
+@RestController
+@RequestMapping("/state")
+class MeiKuStateController {
+
+    /**
+     * 创建图例
+     */
+    @Operation(summary="创建状态-批量", description = "")
+    @PostMapping("/create")
+    fun create(@RequestBody request: SCreateRequest<MeiKuState>): SCreateResponse<MeiKuState> {
+        return MeiKuStateService.createList(request)
+    } // Function create()
+
+    /**
+     * 更新状态
+     */
+    @Operation(summary = "状态修改-批量", description = "")
+    @PostMapping(value = ["/update"])
+    fun update(@RequestBody request: SUpdateRequest<MeiKuState>): SBaseResponse {
+        return MeiKuStateService.updateList(request)
+    } // Function update()
+
+    /**
+     * 根据id删除状态
+     */
+    @Operation(summary = "状态删除", description = "")
+    @PostMapping(value = ["/delete"])
+    fun delete(@RequestBody idList: ArrayList<MeiKuState>): SBaseResponse {
+        return MeiKuStateService.deleteByKeysList(idList)
+    } // Function delete()
+
+    /**
+     * 查询状态信息
+     */
+    @Operation(summary = "查询状态-批量", description = "")
+    @PostMapping(value = ["/query"])
+    fun query(@RequestBody request: SQueryRequest): SQueryResponse<MeiKuState> {
+        return MeiKuStateService.pageQuery(request)
+    } // Function query()
+
+    @Operation(summary = "查询状态统计", description = "")
+    @PostMapping(value = ["/count"])
+    fun count(@RequestBody request: SCountRequest): SCountResponse {
+        return MeiKuStateService.count(request)
+    } // Function count()
+
+} // Class MeiKuStateController

+ 14 - 0
meiku/src/main/kotlin/com/persagy/meiku/controller/Test/Controller.kt

@@ -0,0 +1,14 @@
+package com.persagy.meiku.controller.Test
+
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+/**
+ *
+ * @author wx  <zhangweixin@sagacloud.com>
+ * @date  2020/10/31 18:00
+ */
+@RestController
+@RequestMapping("/test")
+class Controller {
+}

+ 50 - 0
meiku/src/main/kotlin/com/persagy/meiku/models/entities/MeiKu.kt

@@ -0,0 +1,50 @@
+package com.persagy.meiku.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import com.persagy.service.models.annotations.SCascade
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 图库-美库
+ * @author  wx
+ * @date  2020/9/21 10:45
+ */
+@Schema(description = "锚点")
+@Table(name = "labsl_meiku.meiku")
+class MeiKu : Serializable, SBaseEntity() {
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 分类 */
+    @Schema(description = "分类")
+    @Column(name = "category")
+    var category: String? = null
+
+    /** 品牌 */
+    @Schema(description = "品牌")
+    @Column(name = "brand")
+    var brand: String? = null
+
+    /** 型号 */
+    @Schema(description = "型号")
+    @Column(name = "specification")
+    var specification: String? = null
+
+    /** 锚点列表 */
+    @Schema(description = "锚点列表")
+    @SCascade(table="labsl_meiku.meiku_anchor", idColumn="meiku_id", childIdColumn="id")
+    var anchorList: ArrayList<MeiKuAnchor>? = null
+
+    @Schema(description = "状态")
+    @SCascade(table="labsl_meiku.meiku_state", idColumn="meiku_id", childIdColumn="id")
+    var state: ArrayList<MeiKuState>? = null
+
+} // Class MeiKu

+ 37 - 0
meiku/src/main/kotlin/com/persagy/meiku/models/entities/MeiKuAnchor.kt

@@ -0,0 +1,37 @@
+package com.persagy.meiku.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 锚点
+ *
+ * @author  wx
+ * @date  2020/9/21 10:52
+ */
+@Schema(description = "锚点")
+@Table(name = "labsl_meiku.meiku_anchor")
+class MeiKuAnchor: Serializable, SBaseEntity() {
+
+    /** 锚点id */
+    @Schema(description = "锚点id")
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Id
+    @Column(name = "meiku_id")
+    var meiKuId: String? = null
+
+    /** 锚点坐标 */
+    @Schema(description = "锚点坐标")
+    @Column(name = "pos")
+    var pos: Pos? = null
+
+} // Class MeiKuAnchor

+ 41 - 0
meiku/src/main/kotlin/com/persagy/meiku/models/entities/MeiKuState.kt

@@ -0,0 +1,41 @@
+package com.persagy.meiku.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 状态
+ * @author  wx
+ * @date  2020/9/21 11:08
+ */
+@Schema(description = "锚点")
+@Table(name = "labsl_meiku.meiku_state")
+class MeiKuState: Serializable, SBaseEntity() {
+
+    /** 状态id */
+    @Schema(description = "状态id")
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Id
+    @Column(name = "meiku_id")
+    var meiKuId: String? = null
+
+    /** 状态内容 */
+    @Schema(description = "状态内容")
+    @Column(name = "state")
+    var state: String? = null
+
+    /** 图片key */
+    @Schema(description = "图片key")
+    @Column(name = "pic")
+    var pic: String? = null
+
+} // class MeiKuState

+ 31 - 0
meiku/src/main/kotlin/com/persagy/meiku/models/entities/ObjectCategory.kt

@@ -0,0 +1,31 @@
+package com.persagy.meiku.models.entities
+
+import com.persagy.service.models.SBaseEntity
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+import javax.persistence.Column
+import javax.persistence.Id
+import javax.persistence.Table
+
+/**
+ * 对象类型
+ *
+ * @author  wx
+ * @date  2020/9/21 11:13
+ */
+@Schema(description = "对象类型")
+@Table(name = "labsl_meiku.object_category")
+class ObjectCategory: Serializable, SBaseEntity() {
+
+    /** 图id */
+    @Schema(description = "图id")
+    @Id
+    @Column(name = "id")
+    var id: String? = null
+
+    /** 名称 */
+    @Schema(description = "名称")
+    @Column(name = "name")
+    var name: String? = null
+
+} // Class ObjectCategory

+ 25 - 0
meiku/src/main/kotlin/com/persagy/meiku/models/entities/Pos.kt

@@ -0,0 +1,25 @@
+package com.persagy.meiku.models.entities
+
+import io.swagger.v3.oas.annotations.media.Schema
+import java.io.Serializable
+
+/**
+ * 位置信息
+ *
+ * @author wx
+ */
+class Pos : Serializable {
+
+    /** X坐标 */
+    @Schema(description = "X坐标")
+    var x: Double? = null
+
+    /** Y坐标 */
+    @Schema(description = "Y坐标")
+    var y: Double? = null
+
+    /** Z坐标 */
+    @Schema(description = "Z坐标")
+    var z: Double? = null
+
+} // Class Pos

+ 31 - 0
meiku/src/main/kotlin/com/persagy/meiku/models/response/SCommonResponse.kt

@@ -0,0 +1,31 @@
+package com.persagy.meiku.models.response
+
+import com.persagy.service.models.enums.SResponseType
+import io.swagger.v3.oas.annotations.media.Schema
+
+/**
+ * 返回体
+ * @author  蔡云飞
+ * @date  2020/6/9 14:56
+ */
+open class SCommonResponse<ENTITY: Any>(result: SResponseType? = SResponseType.success, message: String? = null) {
+
+    /** 结果 */
+    @Schema(description = "结果")
+    var result: SResponseType? = SResponseType.failure
+    /** 消息 */
+    @Schema(description = "消息")
+    var message: String? = ""
+
+    /** 结果 */
+    @Schema(description = "结果")
+    var content: ENTITY? = null
+
+    /** 初始化 */
+    init {
+        this.result = result
+        this.message = message
+    } // init()
+
+
+}

+ 22 - 0
meiku/src/main/kotlin/com/persagy/meiku/services/MeiKuAnchorService.kt

@@ -0,0 +1,22 @@
+package com.persagy.meiku.services
+
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.meiku.models.entities.MeiKuAnchor
+import com.persagy.service.SObjectService
+import java.util.*
+
+/**
+ *
+ * @author  wx
+ * @date  2020/9/21 11:31
+ */
+object MeiKuAnchorService: SObjectService<MeiKuAnchor>(SMybatisDao(MeiKuAnchor::class.java)) {
+
+    override fun onCreateBefore(entity: MeiKuAnchor): Boolean {
+        if (entity.id.isNullOrEmpty()){
+            entity.id = UUID.randomUUID().toString().replace("-", "")
+        }
+        return super.onCreateBefore(entity)
+    }
+
+} // Object MeiKuAnchorService

+ 157 - 0
meiku/src/main/kotlin/com/persagy/meiku/services/MeiKuService.kt

@@ -0,0 +1,157 @@
+package com.persagy.meiku.services
+
+import com.persagy.database.SFilter
+import com.persagy.meiku.models.entities.MeiKu
+import com.persagy.meiku.models.response.SCommonResponse
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.service.SObjectService
+import com.persagy.service.models.enums.SResponseType
+import com.persagy.service.models.responses.SBaseResponse
+import com.persagy.service.models.responses.SCreateResponse
+import java.util.*
+
+/**
+ *
+ * @author  wx
+ * @date  2020/9/21 11:21
+ */
+object MeiKuService : SObjectService<MeiKu>(SMybatisDao(MeiKu::class.java)) {
+
+    override fun onCreateBefore(entity: MeiKu): Boolean {
+        if (entity.id.isNullOrEmpty()) {
+            entity.id = UUID.randomUUID().toString().replace("-", "")
+        }
+        return super.onCreateBefore(entity)
+    }
+
+    /**
+     * 保存
+     */
+    fun save(meiKu: MeiKu): SCreateResponse<MeiKu> {
+        val sCreateResponse = SCreateResponse<MeiKu>()
+        return try {
+            if (meiKu.id.isNullOrEmpty()) {
+                meiKu.id = UUID.randomUUID().toString().replace("-", "")
+            }
+            val insert = insert(meiKu)
+            if (!meiKu.anchorList.isNullOrEmpty()) {
+                for (anchor in meiKu.anchorList!!) {
+                    anchor.meiKuId = meiKu.id
+                    if (anchor.id.isNullOrEmpty()) {
+                        anchor.id = UUID.randomUUID().toString().replace("-", "")
+                    }
+                    val insert1 = MeiKuAnchorService.insert(anchor)
+                }
+            }
+            if (!meiKu.state .isNullOrEmpty()) {
+                val stateList = meiKu.state
+                for (state in stateList!!){
+                    state!!.meiKuId = meiKu.id
+                    if (state!!.id.isNullOrEmpty()) {
+                        state!!.id = UUID.randomUUID().toString().replace("-", "")
+                    }
+                    MeiKuStateService.insert(state)
+                }
+
+            }
+            sCreateResponse.entityList = arrayListOf(meiKu)
+            sCreateResponse.result = SResponseType.success
+            sCreateResponse
+        } catch (e: Exception) {
+            e.printStackTrace()
+            sCreateResponse.result = SResponseType.failure
+            sCreateResponse
+        }
+    } // Fun save()
+
+    /**
+     * 单个对象修改,包括下面节点
+     */
+    fun revise(meiKu: MeiKu): SBaseResponse {
+        val sBaseResponse = SBaseResponse()
+        return try {
+            if (!meiKu.id.isNullOrEmpty()) {
+                delete(SFilter.eq("id", meiKu.id!!))
+                MeiKuAnchorService.delete(SFilter.eq("id", meiKu.id!!))
+                MeiKuStateService.delete(SFilter.eq("id", meiKu.id!!))
+                val insert = insert(meiKu)
+                if (!meiKu.anchorList.isNullOrEmpty()){
+                    for (anchor in meiKu.anchorList!!) {
+                        anchor.meiKuId = meiKu.id
+                        if (anchor.id.isNullOrEmpty()) {
+                            anchor.id = UUID.randomUUID().toString().replace("-", "")
+                        }
+                        val insert1 = MeiKuAnchorService.insert(anchor)
+                    }
+                }
+                if (!meiKu.state.isNullOrEmpty()) {
+                    val stateList = meiKu.state
+                    for (state in stateList!!){
+                        state!!.meiKuId = meiKu.id
+                        if (state!!.id.isNullOrEmpty()) {
+                            state!!.id = UUID.randomUUID().toString().replace("-", "")
+                        }
+                        val insert1 = MeiKuStateService.insert(state)
+                    }
+
+                }
+                sBaseResponse.result = SResponseType.success
+            } else {
+                sBaseResponse.result = SResponseType.failure
+            }
+            sBaseResponse
+        } catch (e: Exception) {
+            e.printStackTrace()
+            sBaseResponse.result = SResponseType.failure
+            sBaseResponse.message = e.message.toString()
+            sBaseResponse
+        }
+    } // Fun revise()
+
+    /**
+     * 清除节点
+     */
+    override fun onDeleteSuccess(entityList: ArrayList<MeiKu>) {
+        for (entity in entityList){
+            MeiKuAnchorService.delete(SFilter.eq("id", entity.id!!))
+            MeiKuStateService.delete(SFilter.eq("id", entity.id!!))
+        }
+        super.onDeleteSuccess(entityList)
+    }
+
+    /**
+     * 读取图下面所有节点
+     */
+    fun read(meiKu: MeiKu): SCommonResponse<MeiKu> {
+        val sQueryResponse = SCommonResponse<MeiKu>()
+        return try {
+            if (!meiKu.id.isNullOrEmpty()){
+                val entity = select(SFilter.eq("id", meiKu.id!!)).entity()
+                if (entity!=null){
+                    val meiKuAnchorList = MeiKuAnchorService.select(SFilter.eq("id", meiKu.id!!)).exec()
+                    if (meiKuAnchorList.size>0){
+                        entity.anchorList = meiKuAnchorList
+                    }
+                    val meiKuState = MeiKuStateService.select(SFilter.eq("id", meiKu.id!!)).exec()
+                    if (!meiKuState.isNullOrEmpty()){
+                        entity.state = meiKuState
+                    }
+                    sQueryResponse.content = entity
+                    sQueryResponse.result = SResponseType.success
+                }else{
+                    sQueryResponse.result = SResponseType.failure
+                }
+            }else{
+                sQueryResponse.result = SResponseType.failure
+            }
+             sQueryResponse
+        } catch (e: Exception) {
+            e.printStackTrace()
+            sQueryResponse.result = SResponseType.failure
+            sQueryResponse.message = e.message.toString()
+            sQueryResponse
+        }
+    } // read()
+
+
+} // Object MeiKuService

+ 21 - 0
meiku/src/main/kotlin/com/persagy/meiku/services/MeiKuStateService.kt

@@ -0,0 +1,21 @@
+package com.persagy.meiku.services
+
+import com.persagy.mybatis.SMybatisDao
+import com.persagy.meiku.models.entities.MeiKuState
+import com.persagy.service.SObjectService
+import java.util.*
+
+/**
+ * 状态
+ * @author  wx
+ * @date  2020/9/21 11:35
+ */
+object MeiKuStateService : SObjectService<MeiKuState>(SMybatisDao(MeiKuState::class.java)) {
+
+    override fun onCreateBefore(entity: MeiKuState): Boolean {
+        if (entity.id.isNullOrEmpty()){
+            entity.id = UUID.randomUUID().toString().replace("-", "")
+        }
+        return super.onCreateBefore(entity)
+    } //
+} // Object MeiKuStateService

+ 21 - 0
meiku/src/main/resources/application-dev.yml

@@ -0,0 +1,21 @@
+server:
+  port: 8083
+
+spring:
+  datasource:
+#   url:                                jdbc:postgresql://60.205.177.43:5432/datacenter
+#   username:                           postgres
+#   password:                           123qwe!@#
+   url:                                jdbc:postgresql://39.102.40.239:5432/datacenter
+   username:                           postgres
+#   password:                           persagy_2020qwe!@#
+   password:                           cGVyc2FneV8yMDIwcXdlIUAj
+
+
+  activemq:
+    broker-url:                         tcp://172.16.42.210:61616
+
+
+
+# persagy_2020labsl%#$
+# cGVyc2FneV8yMDIwbGFic2wlIyQ=

+ 14 - 0
meiku/src/main/resources/application-prod.yml

@@ -0,0 +1,14 @@
+server:
+  port: 8080
+
+spring:
+#  datasource:
+#    url:                                jdbc:postgresql://172.17.11.228:5432/datacenter
+#    username:                           postgres
+#    password:                           123qwe!@#
+
+  datasource:
+    url:                                jdbc:postgresql://172.17.100.16:5432/datacenter
+    username:                           postgres
+#    password:                           persagy_2020qwe!@#
+    password:                           cGVyc2FneV8yMDIwcXdlIUAj

+ 71 - 0
meiku/src/main/resources/application.yml

@@ -0,0 +1,71 @@
+###############################################################################################################
+# spring-cloud相关配置
+#eureka:
+#  client:                                   #客户端注册进eureka服务列表内
+#    service-url:
+#      defaultZone:                          http://eureka-service:8761/eureka
+#启用监控
+management:
+  endpoints:
+    web:
+      exposure:
+        include:
+          - "*"  # 开放所有端点health,info,metrics,通过actuator/+端点名就可以获取相应的信息。默认打开health和info
+  endpoint:
+    health:
+      #未开启actuator/health时,我们获取到的信息是{"status":"UP"},status的值还有可能是 DOWN。开启后打印详细信息
+      show-details:                       always
+###############################################################################################################
+
+spring:
+  servlet:
+    multipart:
+      enabled: true
+      max-file-size: 10000MB
+      max-request-size: 10000MB
+
+  application:
+    name:                               meiku
+  mvc:
+    favicon:
+      enabled:                          true
+
+  jmx:
+    default-domain:                     meiku
+
+  datasource:
+    name:                               meiku
+    type:                               com.alibaba.druid.pool.DruidDataSource
+    driver-class-name:                  org.postgresql.Driver
+#    url:                                jdbc:postgresql://60.205.177.43:5432/datacenter
+#    username:                           postgres
+#    password:                           123qwe!@#
+
+  jackson:
+    date-format:                        yyyy-MM-dd HH:mm:ss
+    time-zone:                          Asia/Shanghai
+    default-property-inclusion:         non_null
+    # 首字母大写
+#    property-naming-strategy:           com.fasterxml.jackson.databind.PropertyNamingStrategy.PascalCaseStrategy
+    # 以下划线分隔全小写的单词
+    property-naming-strategy:           com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy
+    mapper:
+      # 属性按字母顺序输出
+     sort_properties_alphabetically:   true
+
+# spring-doc 配置
+springdoc:
+  # springdoc 扫描的包,多个包之间使用逗号分隔
+  packagesToScan:                           com.persagy.meiku
+  swagger-ui:
+    # API 组排序方式:asc 升序,desc 降序
+    groups-order:                           asc
+    # 标识排序方式:alpha 按字母升序排列
+    tags-sorter:                            alpha
+    # API 接口排序方式:alpha 按字母升序排列,method 按方法的定义顺序。
+    operations-sorter:                      alpha
+
+mybatis:
+  typeAliasesPackage:                   cn.sagacloud.server.datacenter.entities
+
+

+ 38 - 0
meiku/src/main/resources/logback-spring.xml

@@ -0,0 +1,38 @@
+<!--
+  ~ *********************************************************************************************************************
+  ~
+  ~                     :*$@@%$*:                         ;:                ;;    ;;
+  ~                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
+  ~                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
+  ~                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
+  ~                  =@*                                  %!              @ $= % %@=   =%@!      %=
+  ~             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
+  ~           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
+  ~         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
+  ~         $@*   ;@@@%=!:                *@*
+  ~         =@$    ;;;!=%@@@@=!           =@!
+  ~          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
+  ~           ;%@@$=$@@%*       *@@@$=%@@%;
+  ~              ::;::             ::;::                                              All rights reserved.
+  ~
+  ~ *********************************************************************************************************************
+  -->
+
+<configuration scan="true" debug="false">
+    <contextName>scanbuilding</contextName>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{10}) - %cyan(%msg%n)</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 定义cn.sagacloud包的日志级别 -->
+    <logger name="com.persagy" level="debug" additivity="false">
+        <appender-ref ref="STDOUT"/>
+    </logger>
+
+    <!-- 定义日志级别 -->
+    <root level="ERROR">
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>

+ 6 - 0
settings.gradle

@@ -0,0 +1,6 @@
+rootProject.name = 'da-vinci'
+
+include 'labsl'             // 蜡笔森林
+include 'meiku'             // 美库
+
+