168 changed files with 5732 additions and 1178 deletions
			
			
		@ -0,0 +1,223 @@ | 
				
			|||
########################################################################## | 
				
			|||
#(100) excluded auto configuration - io.sc.platform.core | 
				
			|||
########################################################################## | 
				
			|||
spring.autoconfigure.exclude = | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(150) application configuration - io.sc.platform.core | 
				
			|||
########################################################################## | 
				
			|||
# - io.sc.platform.core | 
				
			|||
application.audit-log-mode = none | 
				
			|||
#application.audit-log-mode = none | 
				
			|||
#application.audit-log-mode = log | 
				
			|||
#application.audit-log-mode = database | 
				
			|||
# - io.sc.platform.installer | 
				
			|||
application.installer.enabled = true | 
				
			|||
# - io.sc.platform.jdbc.liquibase | 
				
			|||
application.updater.enabled = true | 
				
			|||
# - io.sc.platform.security | 
				
			|||
application.default-password = password | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(200) spring.main configuration - io.sc.platform.core | 
				
			|||
########################################################################## | 
				
			|||
spring.main.allow-bean-definition-overriding = false | 
				
			|||
spring.main.banner-mode = console | 
				
			|||
spring.main.lazy-initialization = false | 
				
			|||
spring.main.log-startup-info = true | 
				
			|||
spring.main.register-shutdown-hook = true | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(210) jasypt encryptor configuration - io.sc.platform.core | 
				
			|||
########################################################################## | 
				
			|||
jasypt.encryptor.bean = platformJasyptStringEncryptor | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(300) web server configuration - io.sc.platform.mvc | 
				
			|||
########################################################################## | 
				
			|||
#server.address = 127.0.0.1 | 
				
			|||
server.port = 8080 | 
				
			|||
server.servlet.context-path = / | 
				
			|||
server.servlet.session.timeout = 30m | 
				
			|||
server.error.path = /error | 
				
			|||
server.error.whitelabel.enabled = true | 
				
			|||
server.error.include-exception = true | 
				
			|||
server.error.include-binding-errors = always | 
				
			|||
server.error.include-message = always | 
				
			|||
server.error.include-stacktrace = always | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(1000) dataSource configuration - io.sc.platform.jdbc | 
				
			|||
########################################################################## | 
				
			|||
spring.datasource.items[primary].driver-class-name = org.h2.Driver | 
				
			|||
spring.datasource.items[primary].url = jdbc:h2:mem:DB_PLATFORM;DB_CLOSE_DELAY=-1 | 
				
			|||
spring.datasource.items[primary].username = platform | 
				
			|||
spring.datasource.items[primary].password = platform | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(1100) jpa configuration - io.sc.platform.orm.jpa | 
				
			|||
########################################################################## | 
				
			|||
spring.jpa.open-in-view = false | 
				
			|||
spring.jpa.show-sql = false | 
				
			|||
spring.jpa.generate-ddl = false | 
				
			|||
spring.jpa.hibernate.ddl-auto = none | 
				
			|||
spring.jpa.hibernate.jdbc.batch_size = 25 | 
				
			|||
spring.jpa.properties.hibernate.enable_lazy_load_no_trans =true | 
				
			|||
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.H2Dialect | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(1500) hikari configuration - io.sc.platform.jdbc | 
				
			|||
########################################################################## | 
				
			|||
#spring.datasource.items[primary].hikari.autoCommit = true | 
				
			|||
#spring.datasource.items[primary].hikari.connectionTimeout = 10000 | 
				
			|||
#spring.datasource.items[primary].hikari.idleTimeout = 600000 | 
				
			|||
#spring.datasource.items[primary].hikari.maxLifetime = 1800000 | 
				
			|||
#spring.datasource.items[primary].hikari.minimumIdle = 10 | 
				
			|||
#spring.datasource.items[primary].hikari.maximumPoolSize = 10 | 
				
			|||
#spring.datasource.items[primary].hikari.metricRegistry = | 
				
			|||
#spring.datasource.items[primary].hikari.healthCheckRegistry = | 
				
			|||
#spring.datasource.items[primary].hikari.poolName = | 
				
			|||
#spring.datasource.items[primary].hikari.initializationFailTimeout = 1 | 
				
			|||
#spring.datasource.items[primary].hikari.isolateInternalQueries = false | 
				
			|||
#spring.datasource.items[primary].hikari.allowPoolSuspension = false | 
				
			|||
#spring.datasource.items[primary].hikari.readOnly = false | 
				
			|||
#spring.datasource.items[primary].hikari.registerMbeans = false | 
				
			|||
#spring.datasource.items[primary].hikari.catalog = | 
				
			|||
#spring.datasource.items[primary].hikari.connectionInitSql = | 
				
			|||
#spring.datasource.items[primary].hikari.driverClassName = | 
				
			|||
#spring.datasource.items[primary].hikari.transactionIsolation = | 
				
			|||
#spring.datasource.items[primary].hikari.validationTimeout = 5000 | 
				
			|||
#spring.datasource.items[primary].hikari.leakDetectionThreshold = 0 | 
				
			|||
#spring.datasource.items[primary].hikari.dataSource = | 
				
			|||
#spring.datasource.items[primary].hikari.schema = | 
				
			|||
#spring.datasource.items[primary].hikari.threadFactory = | 
				
			|||
#spring.datasource.items[primary].hikari.scheduledExecutor = | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(2100) spring.session configuration - io.sc.platform.mvc | 
				
			|||
########################################################################## | 
				
			|||
spring.session.store-type = none | 
				
			|||
#spring.session.store-type = jdbc | 
				
			|||
#spring.session.store-type = redis | 
				
			|||
spring.session.jdbc.initializer.enabled = false | 
				
			|||
spring.session.jdbc.cleanup-cron = 0 */5 * * * * | 
				
			|||
spring.session.redis.namespace = spring:session | 
				
			|||
spring.session.redis.cleanupCron = 0 */5 * * * * | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(2200) spring web configuration (WebProperties) - io.sc.platform.mvc | 
				
			|||
########################################################################## | 
				
			|||
spring.web.resources.add-mappings = true | 
				
			|||
spring.web.resources.cache.cachecontrol.cache-public = true | 
				
			|||
spring.web.resources.cache.cachecontrol.must-revalidate = true | 
				
			|||
spring.web.resources.chain.cache = true | 
				
			|||
spring.web.resources.chain.compressed = true | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(2300) management http server configuration - io.sc.platform.mvc | 
				
			|||
########################################################################## | 
				
			|||
management.endpoints.enabled-by-default = true | 
				
			|||
management.endpoints.web.exposure.include = * | 
				
			|||
management.context-path = /actuator | 
				
			|||
management.security.enabled = false | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(2400) thymeleaf configuration - io.sc.platform.mvc | 
				
			|||
########################################################################## | 
				
			|||
spring.thymeleaf.enabled = true | 
				
			|||
spring.thymeleaf.cache = false | 
				
			|||
spring.thymeleaf.encoding = UTF-8 | 
				
			|||
spring.thymeleaf.mode = HTML | 
				
			|||
spring.thymeleaf.prefix = classpath:/templates/ | 
				
			|||
spring.thymeleaf.check-template = false | 
				
			|||
spring.thymeleaf.check-template-location = false | 
				
			|||
spring.thymeleaf.servlet.content-type = text/html | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(2500) jackson configuration - io.sc.platform.mvc | 
				
			|||
########################################################################## | 
				
			|||
spring.jackson.time-zone = Asia/Shanghai | 
				
			|||
spring.jackson.date-format = yyyy-MM-dd HH:mm:ss | 
				
			|||
spring.jackson.serialization.indent_output = true | 
				
			|||
spring.jackson.serialization.fail_on_empty_beans = false | 
				
			|||
spring.jackson.deserialization.fail_on_ignored_properties = false | 
				
			|||
spring.jackson.parser.allow_comments = true | 
				
			|||
spring.jackson.parser.allow_single_quotes = true | 
				
			|||
spring.jackson.parser.allow_trailing_comma = true | 
				
			|||
spring.jackson.parser.allow_unquoted_field_names = true | 
				
			|||
spring.jackson.parser.ignore_undefined = true | 
				
			|||
spring.jackson.parser.allow_unquoted_control_chars = true | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(2600) i18n message source configuration - io.sc.platform.mvc | 
				
			|||
########################################################################## | 
				
			|||
spring.messages.alwaysUseMessageFormat = false | 
				
			|||
spring.messages.cacheDuration = -1 | 
				
			|||
spring.messages.encoding = UTF-8 | 
				
			|||
spring.messages.fallbackToSystemLocale = false | 
				
			|||
spring.messages.useCodeAsDefaultMessage = true | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(3000) platform security configuration - io.sc.platform.security.loginform | 
				
			|||
########################################################################## | 
				
			|||
spring.security.formLogin.loginPage = /login | 
				
			|||
spring.security.formLogin.loginProcessingUrl = /login | 
				
			|||
spring.security.formLogin.failureUrl = /login-error | 
				
			|||
spring.security.logout.logoutUrl = /logout | 
				
			|||
spring.security.logout.logoutSuccessUrl = / | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(4000) email configuration - io.sc.platform.communication | 
				
			|||
########################################################################## | 
				
			|||
spring.mail.host=zzz.xxx.yyy | 
				
			|||
spring.mail.port=25 | 
				
			|||
spring.mail.protocol=smtp | 
				
			|||
spring.mail.test-connection=false | 
				
			|||
spring.mail.default-encoding=UTF-8 | 
				
			|||
spring.mail.properties.mail.smtp.auth=true | 
				
			|||
spring.mail.username=xxx | 
				
			|||
spring.mail.password=yyy | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(5000) flowable bpm configuration - io.sc.platform.flowable | 
				
			|||
########################################################################## | 
				
			|||
# core | 
				
			|||
flowable.asyncExecutorActivate =false | 
				
			|||
flowable.asyncHistoryExecutorActivate = false | 
				
			|||
flowable.check-process-definitions=false | 
				
			|||
flowable.custom-mybatis-mappers= | 
				
			|||
flowable.custom-mybatis-x-m-l-mappers= | 
				
			|||
flowable.database-schema= | 
				
			|||
flowable.database-schema-update=true | 
				
			|||
flowable.db-history-used=true | 
				
			|||
flowable.deployment-name=SpringBootAutoDeployment | 
				
			|||
flowable.history-level= | 
				
			|||
flowable.process-definition-location-prefix=classpath*:/processes/ | 
				
			|||
flowable.process-definition-location-suffixes=**.bpmn20.xml,**.bpmn | 
				
			|||
# process | 
				
			|||
flowable.process.definition-cache-limit=-1 | 
				
			|||
flowable.process.enable-safe-xml=true | 
				
			|||
flowable.process.servlet.load-on-startup=-1 | 
				
			|||
flowable.process.servlet.name=Flowable BPMN Rest API | 
				
			|||
flowable.process.servlet.path=/process-api | 
				
			|||
# cmmn | 
				
			|||
flowable.cmmn.enabled=false | 
				
			|||
# content | 
				
			|||
flowable.content.enabled=false | 
				
			|||
# dmn | 
				
			|||
flowable.dmn.enabled=false | 
				
			|||
# form | 
				
			|||
flowable.form.enabled=false | 
				
			|||
# idm | 
				
			|||
flowable.idm.enabled=false | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(8000) cxf configuration - io.sc.platform.ws.cxf | 
				
			|||
########################################################################## | 
				
			|||
cxf.path = /webservices | 
				
			|||
 | 
				
			|||
########################################################################## | 
				
			|||
#(9000) p6spy configuration - io.sc.platform.jdbc | 
				
			|||
########################################################################## | 
				
			|||
p6spy.enabled = true | 
				
			|||
p6spy.ignorePattern = false | 
				
			|||
@ -0,0 +1,48 @@ | 
				
			|||
************************************************************************************** | 
				
			|||
    Name: app.platform | 
				
			|||
    Version: ${application.version} | 
				
			|||
    Base on Spring Boot ${spring-boot.version} | 
				
			|||
************************************************************************************** | 
				
			|||
System.environment: | 
				
			|||
-------------------------------------------------------------------------------------- | 
				
			|||
    java.specification.version                = 1.8 | 
				
			|||
    java.specification.vendor                 = Oracle Corporation | 
				
			|||
    java.specification.name                   = Java Platform API Specification | 
				
			|||
    java.vm.specification.version             = 1.8 | 
				
			|||
    java.vm.specification.vendor              = Oracle Corporation | 
				
			|||
    java.vm.specification.name                = Java Virtual Machine Specification | 
				
			|||
    java.home                                 = /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre | 
				
			|||
    java.version                              = 1.8.0_332 | 
				
			|||
    java.vendor                               = Azul Systems, Inc. | 
				
			|||
    java.vendor.url                           = http://www.azul.com/ | 
				
			|||
    java.vm.version                           = 25.332-b09 | 
				
			|||
    java.vm.vendor                            = Azul Systems, Inc. | 
				
			|||
    java.vm.name                              = OpenJDK 64-Bit Server VM | 
				
			|||
    java.class.version                        = 52.0 | 
				
			|||
    java.class.path                           = ${java.class.path2} | 
				
			|||
    java.library.path                         = /Users/wangshaoping/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:. | 
				
			|||
    java.io.tmpdir                            = /var/folders/82/6m96_g610hj1v1tcpvhtjysr0000gn/T/ | 
				
			|||
    java.ext.dirs                             = /Users/wangshaoping/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java | 
				
			|||
    os.name                                   = Mac OS X | 
				
			|||
    os.arch                                   = aarch64 | 
				
			|||
    os.version                                = 13.5.1 | 
				
			|||
    user.name                                 = wangshaoping | 
				
			|||
    user.home                                 = /Users/wangshaoping | 
				
			|||
    user.dir                                  = /Users/wangshaoping/wspsc/workspace/wangshaoping/v8/platform | 
				
			|||
     | 
				
			|||
Application.environment | 
				
			|||
-------------------------------------------------------------------------------------- | 
				
			|||
    application.name                          = app.platform | 
				
			|||
    application.is-running-in-development     = false | 
				
			|||
    application.is-running-in-web-container   = false | 
				
			|||
 | 
				
			|||
    application.home.dir                      = /Users/wangshaoping/wspsc/workspace/wangshaoping/v8/platform | 
				
			|||
    application.installer.enabled             = ${application.installer.enabled} | 
				
			|||
    application.updater.enabled               = ${application.updater.enabled} | 
				
			|||
    application.audit-log-mode                = ${application.audit-log-mode} | 
				
			|||
    spring.config.location                    = file:/Users/wangshaoping/wspsc/workspace/wangshaoping/v8/platform/config/application.properties | 
				
			|||
    spring.banner.location                    = file:/Users/wangshaoping/wspsc/workspace/wangshaoping/v8/platform/config/banner.txt | 
				
			|||
    logging.config                            = file:/Users/wangshaoping/wspsc/workspace/wangshaoping/v8/platform/config/logback-spring.xml | 
				
			|||
    p6spy.enabled                             = ${p6spy.enabled} | 
				
			|||
    p6spy.ignorePattern                       = ${p6spy.ignorePattern} | 
				
			|||
************************************************************************************** | 
				
			|||
@ -0,0 +1,216 @@ | 
				
			|||
                                 Apache License | 
				
			|||
                           Version 2.0, January 2004 | 
				
			|||
                        https://www.apache.org/licenses/ | 
				
			|||
 | 
				
			|||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | 
				
			|||
 | 
				
			|||
   1. Definitions. | 
				
			|||
 | 
				
			|||
      "License" shall mean the terms and conditions for use, reproduction, | 
				
			|||
      and distribution as defined by Sections 1 through 9 of this document. | 
				
			|||
 | 
				
			|||
      "Licensor" shall mean the copyright owner or entity authorized by | 
				
			|||
      the copyright owner that is granting the License. | 
				
			|||
 | 
				
			|||
      "Legal Entity" shall mean the union of the acting entity and all | 
				
			|||
      other entities that control, are controlled by, or are under common | 
				
			|||
      control with that entity. For the purposes of this definition, | 
				
			|||
      "control" means (i) the power, direct or indirect, to cause the | 
				
			|||
      direction or management of such entity, whether by contract or | 
				
			|||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the | 
				
			|||
      outstanding shares, or (iii) beneficial ownership of such entity. | 
				
			|||
 | 
				
			|||
      "You" (or "Your") shall mean an individual or Legal Entity | 
				
			|||
      exercising permissions granted by this License. | 
				
			|||
 | 
				
			|||
      "Source" form shall mean the preferred form for making modifications, | 
				
			|||
      including but not limited to software source code, documentation | 
				
			|||
      source, and configuration files. | 
				
			|||
 | 
				
			|||
      "Object" form shall mean any form resulting from mechanical | 
				
			|||
      transformation or translation of a Source form, including but | 
				
			|||
      not limited to compiled object code, generated documentation, | 
				
			|||
      and conversions to other media types. | 
				
			|||
 | 
				
			|||
      "Work" shall mean the work of authorship, whether in Source or | 
				
			|||
      Object form, made available under the License, as indicated by a | 
				
			|||
      copyright notice that is included in or attached to the work | 
				
			|||
      (an example is provided in the Appendix below). | 
				
			|||
 | 
				
			|||
      "Derivative Works" shall mean any work, whether in Source or Object | 
				
			|||
      form, that is based on (or derived from) the Work and for which the | 
				
			|||
      editorial revisions, annotations, elaborations, or other modifications | 
				
			|||
      represent, as a whole, an original work of authorship. For the purposes | 
				
			|||
      of this License, Derivative Works shall not include works that remain | 
				
			|||
      separable from, or merely link (or bind by name) to the interfaces of, | 
				
			|||
      the Work and Derivative Works thereof. | 
				
			|||
 | 
				
			|||
      "Contribution" shall mean any work of authorship, including | 
				
			|||
      the original version of the Work and any modifications or additions | 
				
			|||
      to that Work or Derivative Works thereof, that is intentionally | 
				
			|||
      submitted to Licensor for inclusion in the Work by the copyright owner | 
				
			|||
      or by an individual or Legal Entity authorized to submit on behalf of | 
				
			|||
      the copyright owner. For the purposes of this definition, "submitted" | 
				
			|||
      means any form of electronic, verbal, or written communication sent | 
				
			|||
      to the Licensor or its representatives, including but not limited to | 
				
			|||
      communication on electronic mailing lists, source code control systems, | 
				
			|||
      and issue tracking systems that are managed by, or on behalf of, the | 
				
			|||
      Licensor for the purpose of discussing and improving the Work, but | 
				
			|||
      excluding communication that is conspicuously marked or otherwise | 
				
			|||
      designated in writing by the copyright owner as "Not a Contribution." | 
				
			|||
 | 
				
			|||
      "Contributor" shall mean Licensor and any individual or Legal Entity | 
				
			|||
      on behalf of whom a Contribution has been received by Licensor and | 
				
			|||
      subsequently incorporated within the Work. | 
				
			|||
 | 
				
			|||
   2. Grant of Copyright License. Subject to the terms and conditions of | 
				
			|||
      this License, each Contributor hereby grants to You a perpetual, | 
				
			|||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable | 
				
			|||
      copyright license to reproduce, prepare Derivative Works of, | 
				
			|||
      publicly display, publicly perform, sublicense, and distribute the | 
				
			|||
      Work and such Derivative Works in Source or Object form. | 
				
			|||
 | 
				
			|||
   3. Grant of Patent License. Subject to the terms and conditions of | 
				
			|||
      this License, each Contributor hereby grants to You a perpetual, | 
				
			|||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable | 
				
			|||
      (except as stated in this section) patent license to make, have made, | 
				
			|||
      use, offer to sell, sell, import, and otherwise transfer the Work, | 
				
			|||
      where such license applies only to those patent claims licensable | 
				
			|||
      by such Contributor that are necessarily infringed by their | 
				
			|||
      Contribution(s) alone or by combination of their Contribution(s) | 
				
			|||
      with the Work to which such Contribution(s) was submitted. If You | 
				
			|||
      institute patent litigation against any entity (including a | 
				
			|||
      cross-claim or counterclaim in a lawsuit) alleging that the Work | 
				
			|||
      or a Contribution incorporated within the Work constitutes direct | 
				
			|||
      or contributory patent infringement, then any patent licenses | 
				
			|||
      granted to You under this License for that Work shall terminate | 
				
			|||
      as of the date such litigation is filed. | 
				
			|||
 | 
				
			|||
   4. Redistribution. You may reproduce and distribute copies of the | 
				
			|||
      Work or Derivative Works thereof in any medium, with or without | 
				
			|||
      modifications, and in Source or Object form, provided that You | 
				
			|||
      meet the following conditions: | 
				
			|||
 | 
				
			|||
      (a) You must give any other recipients of the Work or | 
				
			|||
          Derivative Works a copy of this License; and | 
				
			|||
 | 
				
			|||
      (b) You must cause any modified files to carry prominent notices | 
				
			|||
          stating that You changed the files; and | 
				
			|||
 | 
				
			|||
      (c) You must retain, in the Source form of any Derivative Works | 
				
			|||
          that You distribute, all copyright, patent, trademark, and | 
				
			|||
          attribution notices from the Source form of the Work, | 
				
			|||
          excluding those notices that do not pertain to any part of | 
				
			|||
          the Derivative Works; and | 
				
			|||
 | 
				
			|||
      (d) If the Work includes a "NOTICE" text file as part of its | 
				
			|||
          distribution, then any Derivative Works that You distribute must | 
				
			|||
          include a readable copy of the attribution notices contained | 
				
			|||
          within such NOTICE file, excluding those notices that do not | 
				
			|||
          pertain to any part of the Derivative Works, in at least one | 
				
			|||
          of the following places: within a NOTICE text file distributed | 
				
			|||
          as part of the Derivative Works; within the Source form or | 
				
			|||
          documentation, if provided along with the Derivative Works; or, | 
				
			|||
          within a display generated by the Derivative Works, if and | 
				
			|||
          wherever such third-party notices normally appear. The contents | 
				
			|||
          of the NOTICE file are for informational purposes only and | 
				
			|||
          do not modify the License. You may add Your own attribution | 
				
			|||
          notices within Derivative Works that You distribute, alongside | 
				
			|||
          or as an addendum to the NOTICE text from the Work, provided | 
				
			|||
          that such additional attribution notices cannot be construed | 
				
			|||
          as modifying the License. | 
				
			|||
 | 
				
			|||
      You may add Your own copyright statement to Your modifications and | 
				
			|||
      may provide additional or different license terms and conditions | 
				
			|||
      for use, reproduction, or distribution of Your modifications, or | 
				
			|||
      for any such Derivative Works as a whole, provided Your use, | 
				
			|||
      reproduction, and distribution of the Work otherwise complies with | 
				
			|||
      the conditions stated in this License. | 
				
			|||
 | 
				
			|||
   5. Submission of Contributions. Unless You explicitly state otherwise, | 
				
			|||
      any Contribution intentionally submitted for inclusion in the Work | 
				
			|||
      by You to the Licensor shall be under the terms and conditions of | 
				
			|||
      this License, without any additional terms or conditions. | 
				
			|||
      Notwithstanding the above, nothing herein shall supersede or modify | 
				
			|||
      the terms of any separate license agreement you may have executed | 
				
			|||
      with Licensor regarding such Contributions. | 
				
			|||
 | 
				
			|||
   6. Trademarks. This License does not grant permission to use the trade | 
				
			|||
      names, trademarks, service marks, or product names of the Licensor, | 
				
			|||
      except as required for reasonable and customary use in describing the | 
				
			|||
      origin of the Work and reproducing the content of the NOTICE file. | 
				
			|||
 | 
				
			|||
   7. Disclaimer of Warranty. Unless required by applicable law or | 
				
			|||
      agreed to in writing, Licensor provides the Work (and each | 
				
			|||
      Contributor provides its Contributions) on an "AS IS" BASIS, | 
				
			|||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 
				
			|||
      implied, including, without limitation, any warranties or conditions | 
				
			|||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | 
				
			|||
      PARTICULAR PURPOSE. You are solely responsible for determining the | 
				
			|||
      appropriateness of using or redistributing the Work and assume any | 
				
			|||
      risks associated with Your exercise of permissions under this License. | 
				
			|||
 | 
				
			|||
   8. Limitation of Liability. In no event and under no legal theory, | 
				
			|||
      whether in tort (including negligence), contract, or otherwise, | 
				
			|||
      unless required by applicable law (such as deliberate and grossly | 
				
			|||
      negligent acts) or agreed to in writing, shall any Contributor be | 
				
			|||
      liable to You for damages, including any direct, indirect, special, | 
				
			|||
      incidental, or consequential damages of any character arising as a | 
				
			|||
      result of this License or out of the use or inability to use the | 
				
			|||
      Work (including but not limited to damages for loss of goodwill, | 
				
			|||
      work stoppage, computer failure or malfunction, or any and all | 
				
			|||
      other commercial damages or losses), even if such Contributor | 
				
			|||
      has been advised of the possibility of such damages. | 
				
			|||
 | 
				
			|||
   9. Accepting Warranty or Additional Liability. While redistributing | 
				
			|||
      the Work or Derivative Works thereof, You may choose to offer, | 
				
			|||
      and charge a fee for, acceptance of support, warranty, indemnity, | 
				
			|||
      or other liability obligations and/or rights consistent with this | 
				
			|||
      License. However, in accepting such obligations, You may act only | 
				
			|||
      on Your own behalf and on Your sole responsibility, not on behalf | 
				
			|||
      of any other Contributor, and only if You agree to indemnify, | 
				
			|||
      defend, and hold each Contributor harmless for any liability | 
				
			|||
      incurred by, or claims asserted against, such Contributor by reason | 
				
			|||
      of your accepting any such warranty or additional liability. | 
				
			|||
 | 
				
			|||
   END OF TERMS AND CONDITIONS | 
				
			|||
 | 
				
			|||
   APPENDIX: How to apply the Apache License to your work. | 
				
			|||
 | 
				
			|||
      To apply the Apache License to your work, attach the following | 
				
			|||
      boilerplate notice, with the fields enclosed by brackets "[]" | 
				
			|||
      replaced with your own identifying information. (Don't include | 
				
			|||
      the brackets!)  The text should be enclosed in the appropriate | 
				
			|||
      comment syntax for the file format. We also recommend that a | 
				
			|||
      file or class name and description of purpose be included on the | 
				
			|||
      same "printed page" as the copyright notice for easier | 
				
			|||
      identification within third-party archives. | 
				
			|||
 | 
				
			|||
   Copyright [yyyy] [name of copyright owner] | 
				
			|||
 | 
				
			|||
   Licensed under the Apache License, Version 2.0 (the "License"); | 
				
			|||
   you may not use this file except in compliance with the License. | 
				
			|||
   You may obtain a copy of the License at | 
				
			|||
 | 
				
			|||
       https://www.apache.org/licenses/LICENSE-2.0 | 
				
			|||
 | 
				
			|||
   Unless required by applicable law or agreed to in writing, software | 
				
			|||
   distributed under the License is distributed on an "AS IS" BASIS, | 
				
			|||
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
				
			|||
   See the License for the specific language governing permissions and | 
				
			|||
   limitations under the License. | 
				
			|||
 | 
				
			|||
=======================================================================    | 
				
			|||
 | 
				
			|||
To the extent any open source subcomponents are licensed under the EPL and/or other  | 
				
			|||
similar licenses that require the source code and/or modifications to  | 
				
			|||
source code to be made available (as would be noted above), you may obtain a  | 
				
			|||
copy of the source code corresponding to the binaries for such open source  | 
				
			|||
components and modifications thereto, if any, (the "Source Files"), by  | 
				
			|||
downloading the Source Files from https://www.springsource.org/download,  | 
				
			|||
or by sending a request, with your name and address to: VMware, Inc., 3401 Hillview  | 
				
			|||
Avenue, Palo Alto, CA 94304, United States of America or email info@vmware.com.  All  | 
				
			|||
such requests should clearly specify:  OPEN SOURCE FILES REQUEST, Attention General  | 
				
			|||
Counsel.  VMware shall mail a copy of the Source Files to you on a CD or equivalent  | 
				
			|||
physical medium.  This offer to obtain a copy of the Source Files is valid for three  | 
				
			|||
years from the date you acquired this Software product. | 
				
			|||
@ -0,0 +1,66 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			|||
<!-- 自动扫描本文件,如果发生变化,则重新初始化日志系统,并设置每隔5秒钟扫描一次 --> | 
				
			|||
<configuration debug="false" scan="true" scanPeriod="5 seconds"> | 
				
			|||
	<!--  | 
				
			|||
		以下为 logback 的 spring 扩展支持的功能,即支持从 application.properties 文件中获取属性,并在此文件中采用 ${} 方式使用。 | 
				
			|||
		要使用此功能,必须使用 logback-ext-spring 扩展 jar 包,以 gradle 构建系统,则需要加入以下依赖 | 
				
			|||
		dependencies { | 
				
			|||
			compile( | 
				
			|||
				"org.logback-extensions:logback-ext-spring:0.1.2" | 
				
			|||
			) | 
				
			|||
		} | 
				
			|||
	--> | 
				
			|||
	<property name="homedir" value="/Users/wangshaoping/wspsc/workspace/wangshaoping/v8/platform"/> | 
				
			|||
	<property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n"/> | 
				
			|||
	 | 
				
			|||
	<!-- 在控制台中输出日志 --> | 
				
			|||
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | 
				
			|||
        <encoder><pattern>${pattern}</pattern></encoder> | 
				
			|||
    </appender> | 
				
			|||
 | 
				
			|||
	<!-- 在磁盘文件中输出日志 --> | 
				
			|||
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | 
				
			|||
    	<encoder><pattern>${pattern}</pattern></encoder> | 
				
			|||
        <file>${homedir}/logs/log.log</file> | 
				
			|||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | 
				
			|||
            <fileNamePattern>${homedir}/logs/log.%d.log</fileNamePattern> | 
				
			|||
            <maxHistory>30</maxHistory> | 
				
			|||
        </rollingPolicy> | 
				
			|||
    </appender> | 
				
			|||
     | 
				
			|||
    <root level="info"> | 
				
			|||
        <appender-ref ref="STDOUT" /> | 
				
			|||
        <appender-ref ref="FILE" /> | 
				
			|||
    </root> | 
				
			|||
     | 
				
			|||
    <logger name="org.wsp.engine.model.core.code" level="info" additivity="false"/> | 
				
			|||
     | 
				
			|||
    <logger name="org.wsp.engine.rule.core.code" level="debug" additivity="false"> | 
				
			|||
        <appender-ref ref="STDOUT" /> | 
				
			|||
        <appender-ref ref="FILE" /> | 
				
			|||
    </logger> | 
				
			|||
 | 
				
			|||
    <logger name="org.springframework.security" level="info" additivity="false"> | 
				
			|||
        <appender-ref ref="STDOUT" /> | 
				
			|||
        <appender-ref ref="FILE" /> | 
				
			|||
    </logger> | 
				
			|||
     | 
				
			|||
     | 
				
			|||
    <!-- 可对不同的日志写入不同的文件示例 --> | 
				
			|||
    <!--  | 
				
			|||
    <appender name="RULE_ENGINE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | 
				
			|||
    	<encoder><pattern>${pattern}</pattern></encoder> | 
				
			|||
        <file>${homedir}/logs/rule-engine.log</file> | 
				
			|||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | 
				
			|||
            <fileNamePattern>${homedir}/logs/rule-engine.%d.log</fileNamePattern> | 
				
			|||
            <maxHistory>30</maxHistory> | 
				
			|||
        </rollingPolicy> | 
				
			|||
    </appender> | 
				
			|||
     | 
				
			|||
    <logger name="org.wsp.engine.rule.core.code" level="debug" additivity="false"> | 
				
			|||
        <appender-ref ref="STDOUT" /> | 
				
			|||
        <appender-ref ref="FILE" /> | 
				
			|||
        <appender-ref ref="RULE_ENGINE_FILE" /> | 
				
			|||
    </logger> | 
				
			|||
    --> | 
				
			|||
</configuration> | 
				
			|||
@ -0,0 +1,167 @@ | 
				
			|||
import { laBell } from '@quasar/extras/line-awesome'; import { mergeProps } from 'vue'; import { pushScopeId } from 'vue'; import { clear } from 'console'; | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <div class="flex justify-between"> | 
				
			|||
      <div class="text-h6">{{ title }}</div> | 
				
			|||
      <div class="flex justify-end gap-4"> | 
				
			|||
        <template v-for="(btn, index) in actions as any" :key="index"> | 
				
			|||
          <q-btn v-if="typeof btn === 'object'" :loading="btn.loading ? btn.loading : false" :label="btn.label" :icon="btn.icon" outline @click="btn.click()"> | 
				
			|||
          </q-btn> | 
				
			|||
        </template> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
    <q-tree | 
				
			|||
      ref="tree" | 
				
			|||
      v-bind="attrs" | 
				
			|||
      v-model:selected="selectedRef" | 
				
			|||
      v-model:ticked="tickedRef" | 
				
			|||
      v-model:expanded="expandedRef" | 
				
			|||
      class="w-full" | 
				
			|||
      :nodes="nodesRef" | 
				
			|||
      node-key="id" | 
				
			|||
      label-key="i18nLabel" | 
				
			|||
    /> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { ref, useAttrs, toRaw } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { TreeBuilder } from '@/platform'; | 
				
			|||
 | 
				
			|||
const attrs = useAttrs(); | 
				
			|||
const props = defineProps({ | 
				
			|||
  title: { type: String, default: '' }, | 
				
			|||
  labelI18n: { type: Boolean, default: false }, | 
				
			|||
  labelEmpty: { type: String, default: '' }, | 
				
			|||
  actions: { type: Array, default: () => [] }, | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const tree = ref(); | 
				
			|||
 | 
				
			|||
const nodesCache = new Map<string, object>(); | 
				
			|||
const nodesRef = ref(TreeBuilder.build(attrs.nodes)); | 
				
			|||
const selectedRef = ref([]); | 
				
			|||
const tickedRef = ref([]); | 
				
			|||
const expandedRef = ref([]); | 
				
			|||
 | 
				
			|||
const getNodeById = (id: string) => { | 
				
			|||
  return nodesCache.get(id); | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const setNodes = (nodes) => { | 
				
			|||
  nodesCache.clear(); | 
				
			|||
  const tickeds = []; | 
				
			|||
  if (nodes && nodes.length > 0) { | 
				
			|||
    const labelKey = attrs['label-key']; | 
				
			|||
    for (const node of nodes) { | 
				
			|||
      const label = node[labelKey]; | 
				
			|||
      if (props.labelI18n) { | 
				
			|||
        if (label) { | 
				
			|||
          node.i18nLabel = t(label); | 
				
			|||
        } else { | 
				
			|||
          if (props.labelEmpty) { | 
				
			|||
            node.i18nLabel = t(props.labelEmpty); | 
				
			|||
          } else { | 
				
			|||
            node.i18nLabel = label; | 
				
			|||
          } | 
				
			|||
        } | 
				
			|||
      } else { | 
				
			|||
        node.i18nLabel = label; | 
				
			|||
      } | 
				
			|||
      nodesCache.set(node.id, node); | 
				
			|||
      if (node.selected) { | 
				
			|||
        tickeds.push(node.id); | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
  nodesRef.value = TreeBuilder.build(nodes); | 
				
			|||
  tickedRef.value = tickeds; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const getSelectedNode = () => { | 
				
			|||
  return nodesCache.get(selectedRef.value); | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const getSelected = () => { | 
				
			|||
  return selectedRef.value; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const setSelected = (selected) => { | 
				
			|||
  selectedRef.value = selected; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const setTicked = (ticked) => { | 
				
			|||
  tickedRef.value = ticked; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const getTicked = () => { | 
				
			|||
  const result = new Set<string>(); | 
				
			|||
  const tickeds = toRaw(tickedRef.value); | 
				
			|||
  if (tickeds && tickeds.length > 0) { | 
				
			|||
    for (const ticked of tickeds) { | 
				
			|||
      result.add(ticked); | 
				
			|||
    } | 
				
			|||
    for (const ticked of tickeds) { | 
				
			|||
      getAllParentIds(nodesCache.get(ticked).parentId, result); | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
  return [...result]; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const getAllParentIds = (parentId, result) => { | 
				
			|||
  if (parentId) { | 
				
			|||
    const parent = nodesCache.get(parentId); | 
				
			|||
    if (parent) { | 
				
			|||
      result.add(parent.id); | 
				
			|||
      getAllParentIds(parent.parentId, result); | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const getCascadeParentIds = (id) => { | 
				
			|||
  const result = []; | 
				
			|||
  let node = nodesCache.get(id); | 
				
			|||
  if (node) { | 
				
			|||
    result.push(id); | 
				
			|||
    while (node.parentId) { | 
				
			|||
      result.push(node.parentId); | 
				
			|||
      node = nodesCache.get(node.parentId); | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
  return result; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const getCascadeChildrenIds = (id) => { | 
				
			|||
  const result = []; | 
				
			|||
  let node = nodesCache.get(id); | 
				
			|||
  if (node) { | 
				
			|||
    if (node.children && node.children.length > 0) { | 
				
			|||
      for (const child of node.children) { | 
				
			|||
        result.push(child.id); | 
				
			|||
        const childResult = getCascadeChildrenIds(child.id); | 
				
			|||
        if (childResult && childResult.length > 0) { | 
				
			|||
          result.push(...childResult); | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
  return result; | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
defineExpose({ | 
				
			|||
  getNodeById, | 
				
			|||
  setNodes, | 
				
			|||
 | 
				
			|||
  getTicked, | 
				
			|||
  setTicked, | 
				
			|||
 | 
				
			|||
  getSelectedNode, | 
				
			|||
  getSelected, | 
				
			|||
  setSelected, | 
				
			|||
 | 
				
			|||
  getCascadeParentIds, | 
				
			|||
  getCascadeChildrenIds, | 
				
			|||
}); | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,58 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <w-tree-grid | 
				
			|||
      ref="treeGrid" | 
				
			|||
      title="机构树" | 
				
			|||
      :nodes="nodes" | 
				
			|||
      label-key="titleI18nKey" | 
				
			|||
      label-i18n | 
				
			|||
      label-empty="--------------------" | 
				
			|||
      :actions="actions" | 
				
			|||
      tick-strategy="leaf" | 
				
			|||
    /> | 
				
			|||
    <q-btn label="ok" @click="ok"></q-btn> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { ref, toRaw, onMounted } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { Environment, axios, BackendTools } from '@/platform'; | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const treeGrid = ref(); | 
				
			|||
const nodes = ref([]); | 
				
			|||
const selected = []; | 
				
			|||
const ticked = []; | 
				
			|||
const expanded = []; | 
				
			|||
const actions = [ | 
				
			|||
  { | 
				
			|||
    name: 'refresh', | 
				
			|||
    label: '刷新', | 
				
			|||
  }, | 
				
			|||
  { | 
				
			|||
    name: 'expandAll', | 
				
			|||
    label: '全部展开', | 
				
			|||
  }, | 
				
			|||
  { | 
				
			|||
    name: 'selectAll', | 
				
			|||
    label: '全部选择', | 
				
			|||
  }, | 
				
			|||
  { | 
				
			|||
    name: 'save', | 
				
			|||
    label: '保存', | 
				
			|||
  }, | 
				
			|||
]; | 
				
			|||
 | 
				
			|||
onMounted(() => { | 
				
			|||
  axios.get(Environment.apiContextPath('/api/system/menu?pageable=false')).then((response) => { | 
				
			|||
    treeGrid.value.setNodes(response.data.content); | 
				
			|||
  }); | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
const ok = () => { | 
				
			|||
  console.log(treeGrid.value.getCascadeParentIds(treeGrid.value.getSelected())); | 
				
			|||
  console.log(treeGrid.value.getCascadeChildrenIds(treeGrid.value.getSelected())); | 
				
			|||
  console.log(treeGrid.value.getSelectedNode(treeGrid.value.getSelected())); | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,58 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <w-tree-grid | 
				
			|||
      ref="treeGrid" | 
				
			|||
      title="机构树" | 
				
			|||
      :nodes="nodes" | 
				
			|||
      label-key="titleI18nKey" | 
				
			|||
      label-i18n | 
				
			|||
      label-empty="--------------------" | 
				
			|||
      :actions="actions" | 
				
			|||
      tick-strategy="leaf" | 
				
			|||
    /> | 
				
			|||
    <q-btn label="ok" @click="ok"></q-btn> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { ref, toRaw, onMounted } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { Environment, axios, BackendTools } from '@/platform'; | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const treeGrid = ref(); | 
				
			|||
const nodes = ref([]); | 
				
			|||
const selected = []; | 
				
			|||
const ticked = []; | 
				
			|||
const expanded = []; | 
				
			|||
const actions = [ | 
				
			|||
  { | 
				
			|||
    name: 'refresh', | 
				
			|||
    label: '刷新', | 
				
			|||
  }, | 
				
			|||
  { | 
				
			|||
    name: 'expandAll', | 
				
			|||
    label: '全部展开', | 
				
			|||
  }, | 
				
			|||
  { | 
				
			|||
    name: 'selectAll', | 
				
			|||
    label: '全部选择', | 
				
			|||
  }, | 
				
			|||
  { | 
				
			|||
    name: 'save', | 
				
			|||
    label: '保存', | 
				
			|||
  }, | 
				
			|||
]; | 
				
			|||
 | 
				
			|||
onMounted(() => { | 
				
			|||
  axios.get(Environment.apiContextPath('/api/system/menu?pageable=false')).then((response) => { | 
				
			|||
    treeGrid.value.setNodes(response.data.content); | 
				
			|||
  }); | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
const ok = () => { | 
				
			|||
  console.log(treeGrid.value.getCascadeParentIds(treeGrid.value.getSelected())); | 
				
			|||
  console.log(treeGrid.value.getCascadeChildrenIds(treeGrid.value.getSelected())); | 
				
			|||
  console.log(treeGrid.value.getSelectedNode(treeGrid.value.getSelected())); | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
@ -1,104 +1,102 @@ | 
				
			|||
{ | 
				
			|||
    "name": "io.sc.platform.developer.frontend", | 
				
			|||
    "version": "8.1.11", | 
				
			|||
    "description": "", | 
				
			|||
    "private": false, | 
				
			|||
    "keywords": [ | 
				
			|||
         | 
				
			|||
    ], | 
				
			|||
    "author": "", | 
				
			|||
    "license": "ISC", | 
				
			|||
    "scripts": { | 
				
			|||
        "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
				
			|||
        "dev": "nodemon", | 
				
			|||
        "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			|||
        "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			|||
        "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			|||
        "sync": "platform sync" | 
				
			|||
    }, | 
				
			|||
    "engines": { | 
				
			|||
        "node": ">=18", | 
				
			|||
        "pnpm": ">=7" | 
				
			|||
    }, | 
				
			|||
    "publishConfig": { | 
				
			|||
        "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			|||
        "access": "public" | 
				
			|||
    }, | 
				
			|||
    "devDependencies": { | 
				
			|||
        "@babel/core": "7.23.2", | 
				
			|||
        "@babel/preset-env": "7.23.2", | 
				
			|||
        "@babel/preset-typescript": "7.23.2", | 
				
			|||
        "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			|||
        "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			|||
        "@quasar/app-webpack": "3.11.2", | 
				
			|||
        "@quasar/cli": "2.3.0", | 
				
			|||
        "@types/mockjs": "1.0.9", | 
				
			|||
        "@types/node": "20.8.9", | 
				
			|||
        "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			|||
        "@typescript-eslint/parser": "6.9.0", | 
				
			|||
        "@vue/compiler-sfc": "3.3.7", | 
				
			|||
        "@webpack-cli/serve": "2.0.5", | 
				
			|||
        "autoprefixer": "10.4.16", | 
				
			|||
        "babel-loader": "9.1.3", | 
				
			|||
        "clean-webpack-plugin": "4.0.0", | 
				
			|||
        "copy-webpack-plugin": "11.0.0", | 
				
			|||
        "cross-env": "7.0.3", | 
				
			|||
        "css-loader": "6.8.1", | 
				
			|||
        "eslint": "8.52.0", | 
				
			|||
        "eslint-config-prettier": "9.0.0", | 
				
			|||
        "eslint-plugin-prettier": "5.0.1", | 
				
			|||
        "eslint-plugin-vue": "9.18.0", | 
				
			|||
        "eslint-webpack-plugin": "4.0.1", | 
				
			|||
        "html-webpack-plugin": "5.5.3", | 
				
			|||
        "json5": "2.2.3", | 
				
			|||
        "mini-css-extract-plugin": "2.7.6", | 
				
			|||
        "nodemon": "3.0.1", | 
				
			|||
        "postcss": "8.4.31", | 
				
			|||
        "postcss-import": "15.1.0", | 
				
			|||
        "postcss-loader": "7.3.3", | 
				
			|||
        "postcss-preset-env": "9.2.0", | 
				
			|||
        "prettier": "3.0.3", | 
				
			|||
        "sass": "1.69.5", | 
				
			|||
        "sass-loader": "13.3.2", | 
				
			|||
        "typescript": "5.2.2", | 
				
			|||
        "vue-loader": "17.3.0", | 
				
			|||
        "webpack": "5.89.0", | 
				
			|||
        "webpack-bundle-analyzer": "4.9.1", | 
				
			|||
        "webpack-cli": "5.1.4", | 
				
			|||
        "webpack-dev-server": "4.15.1", | 
				
			|||
        "webpack-merge": "5.10.0" | 
				
			|||
    }, | 
				
			|||
    "dependencies": { | 
				
			|||
        "@quasar/extras": "1.16.7", | 
				
			|||
        "@vueuse/core": "10.3.0", | 
				
			|||
        "axios": "1.5.1", | 
				
			|||
        "dayjs": "1.11.10", | 
				
			|||
        "echarts": "5.4.1", | 
				
			|||
        "exceljs": "4.3.0", | 
				
			|||
        "file-saver": "2.0.5", | 
				
			|||
        "luckyexcel": "1.0.1", | 
				
			|||
        "mockjs": "1.1.0", | 
				
			|||
        "pinia": "2.1.7", | 
				
			|||
        "platform-core": "8.1.27", | 
				
			|||
        "quasar": "2.13.0", | 
				
			|||
        "tailwindcss": "3.3.5", | 
				
			|||
        "vue": "3.3.7", | 
				
			|||
        "vue-dompurify-html": "4.1.4", | 
				
			|||
        "vue-i18n": "9.6.0", | 
				
			|||
        "vue-router": "4.2.5", | 
				
			|||
        "@codemirror/autocomplete": "6.11.1", | 
				
			|||
        "@codemirror/commands": "6.3.2", | 
				
			|||
        "@codemirror/lang-html": "6.4.7", | 
				
			|||
        "@codemirror/lang-java": "6.0.1", | 
				
			|||
        "@codemirror/lang-javascript": "6.2.1", | 
				
			|||
        "@codemirror/lang-json": "6.0.1", | 
				
			|||
        "@codemirror/lang-sql": "6.5.4", | 
				
			|||
        "@codemirror/lang-xml": "6.0.2", | 
				
			|||
        "@codemirror/language": "6.9.3", | 
				
			|||
        "@codemirror/search": "6.5.5", | 
				
			|||
        "@codemirror/state": "6.3.3", | 
				
			|||
        "@codemirror/view": "6.22.1", | 
				
			|||
        "codemirror": "6.0.1", | 
				
			|||
        "vue-codemirror6": "1.1.31" | 
				
			|||
    } | 
				
			|||
  "name": "io.sc.platform.developer.frontend", | 
				
			|||
  "version": "8.1.12", | 
				
			|||
  "description": "", | 
				
			|||
  "private": false, | 
				
			|||
  "keywords": [], | 
				
			|||
  "author": "", | 
				
			|||
  "license": "ISC", | 
				
			|||
  "scripts": { | 
				
			|||
    "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
				
			|||
    "dev": "nodemon", | 
				
			|||
    "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			|||
    "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			|||
    "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			|||
    "sync": "platform sync" | 
				
			|||
  }, | 
				
			|||
  "engines": { | 
				
			|||
    "node": ">=18", | 
				
			|||
    "pnpm": ">=7" | 
				
			|||
  }, | 
				
			|||
  "publishConfig": { | 
				
			|||
    "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			|||
    "access": "public" | 
				
			|||
  }, | 
				
			|||
  "devDependencies": { | 
				
			|||
    "@babel/core": "7.23.2", | 
				
			|||
    "@babel/preset-env": "7.23.2", | 
				
			|||
    "@babel/preset-typescript": "7.23.2", | 
				
			|||
    "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			|||
    "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			|||
    "@quasar/app-webpack": "3.11.2", | 
				
			|||
    "@quasar/cli": "2.3.0", | 
				
			|||
    "@types/mockjs": "1.0.9", | 
				
			|||
    "@types/node": "20.8.9", | 
				
			|||
    "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			|||
    "@typescript-eslint/parser": "6.9.0", | 
				
			|||
    "@vue/compiler-sfc": "3.3.7", | 
				
			|||
    "@webpack-cli/serve": "2.0.5", | 
				
			|||
    "autoprefixer": "10.4.16", | 
				
			|||
    "babel-loader": "9.1.3", | 
				
			|||
    "clean-webpack-plugin": "4.0.0", | 
				
			|||
    "copy-webpack-plugin": "11.0.0", | 
				
			|||
    "cross-env": "7.0.3", | 
				
			|||
    "css-loader": "6.8.1", | 
				
			|||
    "eslint": "8.52.0", | 
				
			|||
    "eslint-config-prettier": "9.0.0", | 
				
			|||
    "eslint-plugin-prettier": "5.0.1", | 
				
			|||
    "eslint-plugin-vue": "9.18.0", | 
				
			|||
    "eslint-webpack-plugin": "4.0.1", | 
				
			|||
    "html-webpack-plugin": "5.5.3", | 
				
			|||
    "json5": "2.2.3", | 
				
			|||
    "mini-css-extract-plugin": "2.7.6", | 
				
			|||
    "nodemon": "3.0.1", | 
				
			|||
    "postcss": "8.4.31", | 
				
			|||
    "postcss-import": "15.1.0", | 
				
			|||
    "postcss-loader": "7.3.3", | 
				
			|||
    "postcss-preset-env": "9.2.0", | 
				
			|||
    "prettier": "3.0.3", | 
				
			|||
    "sass": "1.69.5", | 
				
			|||
    "sass-loader": "13.3.2", | 
				
			|||
    "typescript": "5.2.2", | 
				
			|||
    "vue-loader": "17.3.0", | 
				
			|||
    "webpack": "5.89.0", | 
				
			|||
    "webpack-bundle-analyzer": "4.9.1", | 
				
			|||
    "webpack-cli": "5.1.4", | 
				
			|||
    "webpack-dev-server": "4.15.1", | 
				
			|||
    "webpack-merge": "5.10.0" | 
				
			|||
  }, | 
				
			|||
  "dependencies": { | 
				
			|||
    "@quasar/extras": "1.16.7", | 
				
			|||
    "@vueuse/core": "10.3.0", | 
				
			|||
    "axios": "1.5.1", | 
				
			|||
    "dayjs": "1.11.10", | 
				
			|||
    "echarts": "5.4.1", | 
				
			|||
    "exceljs": "4.3.0", | 
				
			|||
    "file-saver": "2.0.5", | 
				
			|||
    "luckyexcel": "1.0.1", | 
				
			|||
    "mockjs": "1.1.0", | 
				
			|||
    "pinia": "2.1.7", | 
				
			|||
    "platform-core": "8.1.37", | 
				
			|||
    "quasar": "2.13.0", | 
				
			|||
    "tailwindcss": "3.3.5", | 
				
			|||
    "vue": "3.3.7", | 
				
			|||
    "vue-dompurify-html": "4.1.4", | 
				
			|||
    "vue-i18n": "9.6.0", | 
				
			|||
    "vue-router": "4.2.5", | 
				
			|||
    "@codemirror/autocomplete": "6.11.1", | 
				
			|||
    "@codemirror/commands": "6.3.2", | 
				
			|||
    "@codemirror/lang-html": "6.4.7", | 
				
			|||
    "@codemirror/lang-java": "6.0.1", | 
				
			|||
    "@codemirror/lang-javascript": "6.2.1", | 
				
			|||
    "@codemirror/lang-json": "6.0.1", | 
				
			|||
    "@codemirror/lang-sql": "6.5.4", | 
				
			|||
    "@codemirror/lang-xml": "6.0.2", | 
				
			|||
    "@codemirror/language": "6.9.3", | 
				
			|||
    "@codemirror/search": "6.5.5", | 
				
			|||
    "@codemirror/state": "6.3.3", | 
				
			|||
    "@codemirror/view": "6.22.1", | 
				
			|||
    "codemirror": "6.0.1", | 
				
			|||
    "vue-codemirror6": "1.1.31" | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,11 @@ | 
				
			|||
{ | 
				
			|||
    "name": "app.platform", | 
				
			|||
    "components": [ | 
				
			|||
    ], | 
				
			|||
    "resources": [ | 
				
			|||
        "/public/configure.js", | 
				
			|||
        "/public/favicon.svg", | 
				
			|||
        "/public/login-bg.jpg", | 
				
			|||
        "/public/logo.svg" | 
				
			|||
    ] | 
				
			|||
} | 
				
			|||
@ -0,0 +1,7 @@ | 
				
			|||
//ext['oracle-database.version'] = '12.2.0.1' | 
				
			|||
 | 
				
			|||
dependencies { | 
				
			|||
	api( | 
				
			|||
		"oracle:oracle:12.2.0.1", | 
				
			|||
	) | 
				
			|||
} | 
				
			|||
@ -0,0 +1,10 @@ | 
				
			|||
{ | 
				
			|||
	"installerEnable"	: true, | 
				
			|||
	"type"				: "Oracle", | 
				
			|||
	"version"			: "12.2", | 
				
			|||
	"driver"			: "oracle.jdbc.OracleDriver", | 
				
			|||
	"url"				: "jdbc:oracle:thin:@${host}:${port}:${sid}", | 
				
			|||
	"urlSample"			: "jdbc:oracle:thin:@localhost:1521:EE", | 
				
			|||
	"hibernateDialect"	: "org.hibernate.dialect.Oracle10gDialect", | 
				
			|||
	"validationQuery"   : "select 1 from dual" | 
				
			|||
} | 
				
			|||
@ -1,6 +1,7 @@ | 
				
			|||
//ext['oracle-database.version'] = '12.2.0.1' | 
				
			|||
 | 
				
			|||
dependencies { | 
				
			|||
	api( | 
				
			|||
		"com.oracle.database.jdbc:ojdbc8", | 
				
			|||
		"com.oracle.database.nls:orai18n" | 
				
			|||
		"oracle:oracle:12.2.0.1", | 
				
			|||
	) | 
				
			|||
} | 
				
			|||
@ -0,0 +1,12 @@ | 
				
			|||
dependencies { | 
				
			|||
	api( | 
				
			|||
		project(":io.sc.platform.jdbc"), | 
				
			|||
 | 
				
			|||
		"us.fatehi:schemacrawler:${schemacrawler_version}", | 
				
			|||
		"us.fatehi:schemacrawler-mysql:${schemacrawler_version}", | 
				
			|||
		"us.fatehi:schemacrawler-oracle:${schemacrawler_version}", | 
				
			|||
		"us.fatehi:schemacrawler-db2:${schemacrawler_version}", | 
				
			|||
		"us.fatehi:schemacrawler-postgresql:${schemacrawler_version}", | 
				
			|||
		"us.fatehi:schemacrawler-sqlite:${schemacrawler_version}", | 
				
			|||
	) | 
				
			|||
} | 
				
			|||
@ -0,0 +1 @@ | 
				
			|||
 | 
				
			|||
@ -0,0 +1,218 @@ | 
				
			|||
package io.sc.platform.jdbc.schemacrawler; | 
				
			|||
 | 
				
			|||
import io.sc.platform.jdbc.DatabaseType; | 
				
			|||
import io.sc.platform.jdbc.meta.MetaDataLoader; | 
				
			|||
import io.sc.platform.jdbc.meta.support.*; | 
				
			|||
import org.springframework.jdbc.datasource.DataSourceUtils; | 
				
			|||
import schemacrawler.schema.Catalog; | 
				
			|||
import schemacrawler.schema.TableRelationshipType; | 
				
			|||
import schemacrawler.schemacrawler.*; | 
				
			|||
import schemacrawler.utility.SchemaCrawlerUtility; | 
				
			|||
 | 
				
			|||
import javax.sql.DataSource; | 
				
			|||
import java.sql.Connection; | 
				
			|||
import java.sql.SQLException; | 
				
			|||
import java.util.*; | 
				
			|||
 | 
				
			|||
public class MetaDataLoaderImpl implements MetaDataLoader { | 
				
			|||
    private Map<DataSource, Catalog> catalogs =new HashMap<DataSource,Catalog>(); | 
				
			|||
    private Object lock =new Object(); | 
				
			|||
 | 
				
			|||
    public void crawler(DataSource dataSource) throws SQLException { | 
				
			|||
        crawler(dataSource,getDefaultOptions(dataSource)); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void crawler(DataSource dataSource, SchemaCrawlerOptions options) throws SQLException { | 
				
			|||
        //catalogs.clear();
 | 
				
			|||
        Connection connection = null; | 
				
			|||
        try { | 
				
			|||
            connection = DataSourceUtils.getConnection(dataSource); | 
				
			|||
            synchronized (lock) { | 
				
			|||
                catalogs.put(dataSource, SchemaCrawlerUtility.getCatalog(connection,getDefaultOptions(dataSource))); | 
				
			|||
            } | 
				
			|||
        }catch (SchemaCrawlerException e) { | 
				
			|||
            throw new SQLException(e); | 
				
			|||
        }finally { | 
				
			|||
            DataSourceUtils.releaseConnection(connection, dataSource); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public Catalog getCatalog(DataSource dataSource) throws SQLException{ | 
				
			|||
        return getCatalog(dataSource,getDefaultOptions(dataSource)); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public Catalog getCatalog(DataSource dataSource, SchemaCrawlerOptions options) throws SQLException{ | 
				
			|||
        synchronized (lock) { | 
				
			|||
            if(!catalogs.containsKey(dataSource)) { | 
				
			|||
                crawler(dataSource,options); | 
				
			|||
            } | 
				
			|||
            return catalogs.get(dataSource); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public List<Schema> getSchemas(DataSource dataSource) throws MetaDataAccessException { | 
				
			|||
        Catalog catalog = null; | 
				
			|||
        try { | 
				
			|||
            catalog = getCatalog(dataSource); | 
				
			|||
        } catch (SQLException e) { | 
				
			|||
            throw new MetaDataAccessException(e); | 
				
			|||
        } | 
				
			|||
        if(catalog!=null) { | 
				
			|||
            Collection<schemacrawler.schema.Schema> schemas =catalog.getSchemas(); | 
				
			|||
            if(schemas!=null && schemas.size()>0) { | 
				
			|||
                List<Schema> result =new ArrayList<>(); | 
				
			|||
                for(schemacrawler.schema.Schema schema : schemas){ | 
				
			|||
                    result.add(from(schema)); | 
				
			|||
                } | 
				
			|||
                return result; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        return null; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public List<TableSummary> getTableSummary(DataSource dataSource, String schemaName) throws MetaDataAccessException { | 
				
			|||
        List<Table> tables =getTables(dataSource,schemaName); | 
				
			|||
        List<TableSummary> result =new ArrayList<>(); | 
				
			|||
        for(Table table : tables){ | 
				
			|||
            TableSummary summary =new TableSummary(); | 
				
			|||
            summary.setName(table.getName()); | 
				
			|||
            summary.setRemarks(table.getRemarks()); | 
				
			|||
            result.add(summary); | 
				
			|||
        } | 
				
			|||
        return result; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public List<TableSummary> getTableSummary(DataSource dataSource, String schemaName, boolean isCount) throws MetaDataAccessException { | 
				
			|||
        return getTableSummary(dataSource,schemaName,false); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public List<Table> getTables(DataSource dataSource, String schemaName, String... tableNames) throws MetaDataAccessException { | 
				
			|||
        Catalog catalog = null; | 
				
			|||
        try { | 
				
			|||
            catalog = getCatalog(dataSource); | 
				
			|||
        } catch (SQLException e) { | 
				
			|||
            throw new MetaDataAccessException(e); | 
				
			|||
        } | 
				
			|||
        if(catalog!=null) { | 
				
			|||
            schemacrawler.schema.Schema schema =findSchema(catalog,schemaName); | 
				
			|||
            if(schema!=null) { | 
				
			|||
                Collection<schemacrawler.schema.Table> tables =catalog.getTables(schema); | 
				
			|||
                if(tables!=null && tables.size()>0) { | 
				
			|||
                    List<Table> result =new ArrayList<Table>(); | 
				
			|||
                    for(schemacrawler.schema.Table table : tables){ | 
				
			|||
                        result.add(from(table)); | 
				
			|||
                    } | 
				
			|||
                    return result; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        return null; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public boolean isSelfReference(schemacrawler.schema.Table table) { | 
				
			|||
        Collection<schemacrawler.schema.Table> parentTables =table.getRelatedTables(TableRelationshipType.parent); | 
				
			|||
        if(parentTables!=null && !parentTables.isEmpty()) { | 
				
			|||
            for(schemacrawler.schema.Table parentTable : parentTables) { | 
				
			|||
                if(parentTable.equals(table)) { | 
				
			|||
                    return true; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        return false; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private Schema from(schemacrawler.schema.Schema schema){ | 
				
			|||
        Schema result =new Schema(); | 
				
			|||
        result.setName(schema.getName()==null?schema.getCatalogName():schema.getName()); | 
				
			|||
        return result; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private Table from(schemacrawler.schema.Table table){ | 
				
			|||
        Table result =new Table(); | 
				
			|||
        result.setName(table.getName()); | 
				
			|||
        result.setRemarks(table.getRemarks()); | 
				
			|||
        // 处理列
 | 
				
			|||
        for(schemacrawler.schema.Column column : table.getColumns()) { | 
				
			|||
            result.getColumns().add(from(column)); | 
				
			|||
        } | 
				
			|||
        return result; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private Column from(schemacrawler.schema.Column column){ | 
				
			|||
        Column result =new Column(); | 
				
			|||
        result.setName(column.getName()); | 
				
			|||
        result.setRemarks(column.getRemarks()); | 
				
			|||
        result.setJavaType(column.getType().getTypeMappedClass()); | 
				
			|||
        result.setSqlType(column.getColumnDataType().getJavaSqlType().getName()); | 
				
			|||
        result.setVendorTypeNumber(column.getColumnDataType().getJavaSqlType().getVendorTypeNumber()); | 
				
			|||
        result.setNullable(column.isNullable()); | 
				
			|||
        result.setDefaultValue(column.getDefaultValue()); | 
				
			|||
        result.setGenerated(column.isGenerated()); | 
				
			|||
        result.setHidden(column.isHidden()); | 
				
			|||
        result.setAutoIncremented(column.isAutoIncremented()); | 
				
			|||
        result.setPartOfIndex(column.isPartOfIndex()); | 
				
			|||
        result.setPartOfUniqueIndex(column.isPartOfUniqueIndex()); | 
				
			|||
        result.setPartOfPrimaryKey(column.isPartOfPrimaryKey()); | 
				
			|||
        result.setSize(column.getSize()); | 
				
			|||
        result.setWidth(column.getWidth()); | 
				
			|||
        return result; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private SchemaCrawlerOptions getDefaultOptions(DataSource dataSource) { | 
				
			|||
        final SchemaCrawlerOptions options = new SchemaCrawlerOptions(); | 
				
			|||
        options.setSchemaInfoLevel(SchemaInfoLevelBuilder.standard()); | 
				
			|||
        options.setRoutineInclusionRule(new ExcludeAll()); | 
				
			|||
        options.setTableInclusionRule(new IncludeAll()); | 
				
			|||
 | 
				
			|||
 | 
				
			|||
        options.setSchemaInclusionRule(new RegularExpressionInclusionRule("I9")); | 
				
			|||
        //options.setSchemaInclusionRule(new RegularExpressionInclusionRule("FRAMEWORK"));
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
        DatabaseType type =null; | 
				
			|||
        try { | 
				
			|||
            type = DatabaseType.fromMetaData(dataSource); | 
				
			|||
        } catch (org.springframework.jdbc.support.MetaDataAccessException e) { | 
				
			|||
            throw new RuntimeException(e); | 
				
			|||
        } | 
				
			|||
        switch(type) { | 
				
			|||
            case DB2: | 
				
			|||
                options.setSchemaInclusionRule(new RegularExpressionExclusionRule("NULLID|SQLJ|SYSCAT|SYSFUN|SYSIBM|SYSIBMADM|SYSIBMINTERNAL|SYSIBMTS|SYSPROC|SYSPUBLIC|SYSSTAT|SYSTOOLS")); | 
				
			|||
                break; | 
				
			|||
            case ORACLE: | 
				
			|||
                options.setSchemaInclusionRule(new RegularExpressionExclusionRule("ANONYMOUS|APEX_PUBLIC_USER|APPQOSSYS|BI|CTXSYS|DBSNMP|DIP|EXFSYS|FLOWS_30000|FLOWS_FILES|GSMADMIN_INTERNAL|HR|IX|LBACSYS|MDDATA|MDSYS|MGMT_VIEW|OE|OLAPSYS|ORACLE_OCM|ORDDATA|ORDPLUGINS|ORDSYS|OUTLN|OWBSYS|OWBSYS_AUDIT|PM|RDSADMIN|SCOTT|SH|SI_INFORMTN_SCHEMA|SPATIAL_CSW_ADMIN_USR|SPATIAL_WFS_ADMIN_USR|SYS|SYSMAN|\\\"SYSTEM\\\"|TSMSYS|WKPROXY|WKSYS|WK_TEST|WMSYS|XDB|APEX_[0-9]{6}|FLOWS_[0-9]{5,6}|XS\\$NULL|\\\"XS\\$NULL\\\"")); | 
				
			|||
                break; | 
				
			|||
            case MYSQL: | 
				
			|||
                options.setSchemaInclusionRule(new RegularExpressionExclusionRule("sys|mysql|performance_schema|information_schema")); | 
				
			|||
                break; | 
				
			|||
            case POSTGRESQL: | 
				
			|||
                options.setSchemaInclusionRule(new RegularExpressionExclusionRule("pg_catalog|information_schema")); | 
				
			|||
                break; | 
				
			|||
            default: | 
				
			|||
        } | 
				
			|||
        return options; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private schemacrawler.schema.Schema findSchema(Catalog catalog,String schemaName) { | 
				
			|||
        Collection<schemacrawler.schema.Schema> schemas =catalog.getSchemas(); | 
				
			|||
        if(schemas!=null && schemas.size()>0) { | 
				
			|||
            for(schemacrawler.schema.Schema schema : schemas) { | 
				
			|||
                DatabaseType type =DatabaseType.fromProductName(catalog.getDatabaseInfo().getProductName()); | 
				
			|||
                if(DatabaseType.MYSQL.equals(type)) {//mysql 没有 schema,只有 catalog
 | 
				
			|||
                    if(schema.getCatalogName().equalsIgnoreCase(schemaName)) { | 
				
			|||
                        return schema; | 
				
			|||
                    } | 
				
			|||
                }else { | 
				
			|||
                    if(schema.getName().equalsIgnoreCase(schemaName)) { | 
				
			|||
                        return schema; | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        return null; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
package io.sc.platform.jdbc.schemacrawler; | 
				
			|||
 | 
				
			|||
import schemacrawler.schema.Table; | 
				
			|||
import schemacrawler.schema.TableRelationshipType; | 
				
			|||
 | 
				
			|||
import java.util.Collection; | 
				
			|||
import java.util.Comparator; | 
				
			|||
 | 
				
			|||
public class ParentAndChildrenTableComparator implements Comparator<Table> { | 
				
			|||
    @Override | 
				
			|||
    public int compare(Table o1, Table o2) { | 
				
			|||
        Collection<Table> parentTables =o1.getRelatedTables(TableRelationshipType.parent); | 
				
			|||
        Collection<schemacrawler.schema.Table> childrenTables =o1.getRelatedTables(TableRelationshipType.child); | 
				
			|||
        if(parentTables!=null && !parentTables.isEmpty() && parentTables.contains(o2)) { | 
				
			|||
            return 1; | 
				
			|||
        }else if(childrenTables!=null && !childrenTables.isEmpty() && childrenTables.contains(o2)) { | 
				
			|||
            return -1; | 
				
			|||
        }else { | 
				
			|||
            return o1.getName().compareTo(o2.getName()); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1 @@ | 
				
			|||
io.sc.platform.jdbc.schemacrawler.MetaDataLoaderImpl | 
				
			|||
@ -1,104 +1,102 @@ | 
				
			|||
{ | 
				
			|||
    "name": "io.sc.platform.lcdp.frontend", | 
				
			|||
    "version": "8.1.11", | 
				
			|||
    "description": "", | 
				
			|||
    "private": false, | 
				
			|||
    "keywords": [ | 
				
			|||
         | 
				
			|||
    ], | 
				
			|||
    "author": "", | 
				
			|||
    "license": "ISC", | 
				
			|||
    "scripts": { | 
				
			|||
        "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
				
			|||
        "dev": "nodemon", | 
				
			|||
        "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			|||
        "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			|||
        "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			|||
        "sync": "platform sync" | 
				
			|||
    }, | 
				
			|||
    "engines": { | 
				
			|||
        "node": ">=18", | 
				
			|||
        "pnpm": ">=7" | 
				
			|||
    }, | 
				
			|||
    "publishConfig": { | 
				
			|||
        "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			|||
        "access": "public" | 
				
			|||
    }, | 
				
			|||
    "devDependencies": { | 
				
			|||
        "@babel/core": "7.23.2", | 
				
			|||
        "@babel/preset-env": "7.23.2", | 
				
			|||
        "@babel/preset-typescript": "7.23.2", | 
				
			|||
        "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			|||
        "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			|||
        "@quasar/app-webpack": "3.11.2", | 
				
			|||
        "@quasar/cli": "2.3.0", | 
				
			|||
        "@types/mockjs": "1.0.9", | 
				
			|||
        "@types/node": "20.8.9", | 
				
			|||
        "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			|||
        "@typescript-eslint/parser": "6.9.0", | 
				
			|||
        "@vue/compiler-sfc": "3.3.7", | 
				
			|||
        "@webpack-cli/serve": "2.0.5", | 
				
			|||
        "autoprefixer": "10.4.16", | 
				
			|||
        "babel-loader": "9.1.3", | 
				
			|||
        "clean-webpack-plugin": "4.0.0", | 
				
			|||
        "copy-webpack-plugin": "11.0.0", | 
				
			|||
        "cross-env": "7.0.3", | 
				
			|||
        "css-loader": "6.8.1", | 
				
			|||
        "eslint": "8.52.0", | 
				
			|||
        "eslint-config-prettier": "9.0.0", | 
				
			|||
        "eslint-plugin-prettier": "5.0.1", | 
				
			|||
        "eslint-plugin-vue": "9.18.0", | 
				
			|||
        "eslint-webpack-plugin": "4.0.1", | 
				
			|||
        "html-webpack-plugin": "5.5.3", | 
				
			|||
        "json5": "2.2.3", | 
				
			|||
        "mini-css-extract-plugin": "2.7.6", | 
				
			|||
        "nodemon": "3.0.1", | 
				
			|||
        "postcss": "8.4.31", | 
				
			|||
        "postcss-import": "15.1.0", | 
				
			|||
        "postcss-loader": "7.3.3", | 
				
			|||
        "postcss-preset-env": "9.2.0", | 
				
			|||
        "prettier": "3.0.3", | 
				
			|||
        "sass": "1.69.5", | 
				
			|||
        "sass-loader": "13.3.2", | 
				
			|||
        "typescript": "5.2.2", | 
				
			|||
        "vue-loader": "17.3.0", | 
				
			|||
        "webpack": "5.89.0", | 
				
			|||
        "webpack-bundle-analyzer": "4.9.1", | 
				
			|||
        "webpack-cli": "5.1.4", | 
				
			|||
        "webpack-dev-server": "4.15.1", | 
				
			|||
        "webpack-merge": "5.10.0" | 
				
			|||
    }, | 
				
			|||
    "dependencies": { | 
				
			|||
        "@codemirror/autocomplete": "6.11.1", | 
				
			|||
        "@codemirror/commands": "6.3.2", | 
				
			|||
        "@codemirror/lang-html": "6.4.7", | 
				
			|||
        "@codemirror/lang-java": "6.0.1", | 
				
			|||
        "@codemirror/lang-javascript": "6.2.1", | 
				
			|||
        "@codemirror/lang-json": "6.0.1", | 
				
			|||
        "@codemirror/lang-sql": "6.5.4", | 
				
			|||
        "@codemirror/lang-xml": "6.0.2", | 
				
			|||
        "@codemirror/language": "6.9.3", | 
				
			|||
        "@codemirror/search": "6.5.5", | 
				
			|||
        "@codemirror/state": "6.3.3", | 
				
			|||
        "@codemirror/view": "6.22.1", | 
				
			|||
        "@quasar/extras": "1.16.7", | 
				
			|||
        "@vueuse/core": "10.3.0", | 
				
			|||
        "axios": "1.5.1", | 
				
			|||
        "codemirror": "6.0.1", | 
				
			|||
        "dayjs": "1.11.10", | 
				
			|||
        "echarts": "5.4.1", | 
				
			|||
        "exceljs": "4.3.0", | 
				
			|||
        "file-saver": "2.0.5", | 
				
			|||
        "luckyexcel": "1.0.1", | 
				
			|||
        "mockjs": "1.1.0", | 
				
			|||
        "pinia": "2.1.7", | 
				
			|||
        "platform-core": "8.1.27", | 
				
			|||
        "quasar": "2.13.0", | 
				
			|||
        "tailwindcss": "3.3.5", | 
				
			|||
        "vue": "3.3.7", | 
				
			|||
        "vue-dompurify-html": "4.1.4", | 
				
			|||
        "vue-i18n": "9.6.0", | 
				
			|||
        "vue-router": "4.2.5", | 
				
			|||
        "vue-codemirror6": "1.1.31" | 
				
			|||
    } | 
				
			|||
  "name": "io.sc.platform.lcdp.frontend", | 
				
			|||
  "version": "8.1.12", | 
				
			|||
  "description": "", | 
				
			|||
  "private": false, | 
				
			|||
  "keywords": [], | 
				
			|||
  "author": "", | 
				
			|||
  "license": "ISC", | 
				
			|||
  "scripts": { | 
				
			|||
    "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
				
			|||
    "dev": "nodemon", | 
				
			|||
    "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			|||
    "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			|||
    "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			|||
    "sync": "platform sync" | 
				
			|||
  }, | 
				
			|||
  "engines": { | 
				
			|||
    "node": ">=18", | 
				
			|||
    "pnpm": ">=7" | 
				
			|||
  }, | 
				
			|||
  "publishConfig": { | 
				
			|||
    "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			|||
    "access": "public" | 
				
			|||
  }, | 
				
			|||
  "devDependencies": { | 
				
			|||
    "@babel/core": "7.23.2", | 
				
			|||
    "@babel/preset-env": "7.23.2", | 
				
			|||
    "@babel/preset-typescript": "7.23.2", | 
				
			|||
    "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			|||
    "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			|||
    "@quasar/app-webpack": "3.11.2", | 
				
			|||
    "@quasar/cli": "2.3.0", | 
				
			|||
    "@types/mockjs": "1.0.9", | 
				
			|||
    "@types/node": "20.8.9", | 
				
			|||
    "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			|||
    "@typescript-eslint/parser": "6.9.0", | 
				
			|||
    "@vue/compiler-sfc": "3.3.7", | 
				
			|||
    "@webpack-cli/serve": "2.0.5", | 
				
			|||
    "autoprefixer": "10.4.16", | 
				
			|||
    "babel-loader": "9.1.3", | 
				
			|||
    "clean-webpack-plugin": "4.0.0", | 
				
			|||
    "copy-webpack-plugin": "11.0.0", | 
				
			|||
    "cross-env": "7.0.3", | 
				
			|||
    "css-loader": "6.8.1", | 
				
			|||
    "eslint": "8.52.0", | 
				
			|||
    "eslint-config-prettier": "9.0.0", | 
				
			|||
    "eslint-plugin-prettier": "5.0.1", | 
				
			|||
    "eslint-plugin-vue": "9.18.0", | 
				
			|||
    "eslint-webpack-plugin": "4.0.1", | 
				
			|||
    "html-webpack-plugin": "5.5.3", | 
				
			|||
    "json5": "2.2.3", | 
				
			|||
    "mini-css-extract-plugin": "2.7.6", | 
				
			|||
    "nodemon": "3.0.1", | 
				
			|||
    "postcss": "8.4.31", | 
				
			|||
    "postcss-import": "15.1.0", | 
				
			|||
    "postcss-loader": "7.3.3", | 
				
			|||
    "postcss-preset-env": "9.2.0", | 
				
			|||
    "prettier": "3.0.3", | 
				
			|||
    "sass": "1.69.5", | 
				
			|||
    "sass-loader": "13.3.2", | 
				
			|||
    "typescript": "5.2.2", | 
				
			|||
    "vue-loader": "17.3.0", | 
				
			|||
    "webpack": "5.89.0", | 
				
			|||
    "webpack-bundle-analyzer": "4.9.1", | 
				
			|||
    "webpack-cli": "5.1.4", | 
				
			|||
    "webpack-dev-server": "4.15.1", | 
				
			|||
    "webpack-merge": "5.10.0" | 
				
			|||
  }, | 
				
			|||
  "dependencies": { | 
				
			|||
    "@codemirror/autocomplete": "6.11.1", | 
				
			|||
    "@codemirror/commands": "6.3.2", | 
				
			|||
    "@codemirror/lang-html": "6.4.7", | 
				
			|||
    "@codemirror/lang-java": "6.0.1", | 
				
			|||
    "@codemirror/lang-javascript": "6.2.1", | 
				
			|||
    "@codemirror/lang-json": "6.0.1", | 
				
			|||
    "@codemirror/lang-sql": "6.5.4", | 
				
			|||
    "@codemirror/lang-xml": "6.0.2", | 
				
			|||
    "@codemirror/language": "6.9.3", | 
				
			|||
    "@codemirror/search": "6.5.5", | 
				
			|||
    "@codemirror/state": "6.3.3", | 
				
			|||
    "@codemirror/view": "6.22.1", | 
				
			|||
    "@quasar/extras": "1.16.7", | 
				
			|||
    "@vueuse/core": "10.3.0", | 
				
			|||
    "axios": "1.5.1", | 
				
			|||
    "codemirror": "6.0.1", | 
				
			|||
    "dayjs": "1.11.10", | 
				
			|||
    "echarts": "5.4.1", | 
				
			|||
    "exceljs": "4.3.0", | 
				
			|||
    "file-saver": "2.0.5", | 
				
			|||
    "luckyexcel": "1.0.1", | 
				
			|||
    "mockjs": "1.1.0", | 
				
			|||
    "pinia": "2.1.7", | 
				
			|||
    "platform-core": "8.1.37", | 
				
			|||
    "quasar": "2.13.0", | 
				
			|||
    "tailwindcss": "3.3.5", | 
				
			|||
    "vue": "3.3.7", | 
				
			|||
    "vue-dompurify-html": "4.1.4", | 
				
			|||
    "vue-i18n": "9.6.0", | 
				
			|||
    "vue-router": "4.2.5", | 
				
			|||
    "vue-codemirror6": "1.1.31" | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -1,104 +1,102 @@ | 
				
			|||
{ | 
				
			|||
    "name": "io.sc.platform.mvc.frontend", | 
				
			|||
    "version": "8.1.11", | 
				
			|||
    "description": "", | 
				
			|||
    "private": false, | 
				
			|||
    "keywords": [ | 
				
			|||
         | 
				
			|||
    ], | 
				
			|||
    "author": "", | 
				
			|||
    "license": "ISC", | 
				
			|||
    "scripts": { | 
				
			|||
        "dev": "nodemon", | 
				
			|||
        "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			|||
        "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			|||
        "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			|||
        "sync": "platform sync", | 
				
			|||
        "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml" | 
				
			|||
    }, | 
				
			|||
    "engines": { | 
				
			|||
        "node": ">=18", | 
				
			|||
        "pnpm": ">=7" | 
				
			|||
    }, | 
				
			|||
    "publishConfig": { | 
				
			|||
        "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			|||
        "access": "public" | 
				
			|||
    }, | 
				
			|||
    "devDependencies": { | 
				
			|||
        "@babel/core": "7.23.2", | 
				
			|||
        "@babel/preset-env": "7.23.2", | 
				
			|||
        "@babel/preset-typescript": "7.23.2", | 
				
			|||
        "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			|||
        "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			|||
        "@quasar/app-webpack": "3.11.2", | 
				
			|||
        "@quasar/cli": "2.3.0", | 
				
			|||
        "@types/mockjs": "1.0.9", | 
				
			|||
        "@types/node": "20.8.9", | 
				
			|||
        "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			|||
        "@typescript-eslint/parser": "6.9.0", | 
				
			|||
        "@vue/compiler-sfc": "3.3.7", | 
				
			|||
        "@webpack-cli/serve": "2.0.5", | 
				
			|||
        "autoprefixer": "10.4.16", | 
				
			|||
        "babel-loader": "9.1.3", | 
				
			|||
        "clean-webpack-plugin": "4.0.0", | 
				
			|||
        "copy-webpack-plugin": "11.0.0", | 
				
			|||
        "cross-env": "7.0.3", | 
				
			|||
        "css-loader": "6.8.1", | 
				
			|||
        "eslint": "8.52.0", | 
				
			|||
        "eslint-config-prettier": "9.0.0", | 
				
			|||
        "eslint-plugin-prettier": "5.0.1", | 
				
			|||
        "eslint-plugin-vue": "9.18.0", | 
				
			|||
        "eslint-webpack-plugin": "4.0.1", | 
				
			|||
        "html-webpack-plugin": "5.5.3", | 
				
			|||
        "json5": "2.2.3", | 
				
			|||
        "mini-css-extract-plugin": "2.7.6", | 
				
			|||
        "nodemon": "3.0.1", | 
				
			|||
        "postcss": "8.4.31", | 
				
			|||
        "postcss-import": "15.1.0", | 
				
			|||
        "postcss-loader": "7.3.3", | 
				
			|||
        "postcss-preset-env": "9.2.0", | 
				
			|||
        "prettier": "3.0.3", | 
				
			|||
        "sass": "1.69.5", | 
				
			|||
        "sass-loader": "13.3.2", | 
				
			|||
        "typescript": "5.2.2", | 
				
			|||
        "vue-loader": "17.3.0", | 
				
			|||
        "webpack": "5.89.0", | 
				
			|||
        "webpack-bundle-analyzer": "4.9.1", | 
				
			|||
        "webpack-cli": "5.1.4", | 
				
			|||
        "webpack-dev-server": "4.15.1", | 
				
			|||
        "webpack-merge": "5.10.0" | 
				
			|||
    }, | 
				
			|||
    "dependencies": { | 
				
			|||
        "@quasar/extras": "1.16.7", | 
				
			|||
        "@vueuse/core": "10.3.0", | 
				
			|||
        "axios": "1.5.1", | 
				
			|||
        "dayjs": "1.11.10", | 
				
			|||
        "echarts": "5.4.1", | 
				
			|||
        "exceljs": "4.3.0", | 
				
			|||
        "file-saver": "2.0.5", | 
				
			|||
        "luckyexcel": "1.0.1", | 
				
			|||
        "mockjs": "1.1.0", | 
				
			|||
        "pinia": "2.1.7", | 
				
			|||
        "platform-core": "8.1.27", | 
				
			|||
        "quasar": "2.13.0", | 
				
			|||
        "tailwindcss": "3.3.5", | 
				
			|||
        "vue": "3.3.7", | 
				
			|||
        "vue-dompurify-html": "4.1.4", | 
				
			|||
        "vue-i18n": "9.6.0", | 
				
			|||
        "vue-router": "4.2.5", | 
				
			|||
        "@codemirror/autocomplete": "6.11.1", | 
				
			|||
        "@codemirror/commands": "6.3.2", | 
				
			|||
        "@codemirror/lang-html": "6.4.7", | 
				
			|||
        "@codemirror/lang-java": "6.0.1", | 
				
			|||
        "@codemirror/lang-javascript": "6.2.1", | 
				
			|||
        "@codemirror/lang-json": "6.0.1", | 
				
			|||
        "@codemirror/lang-sql": "6.5.4", | 
				
			|||
        "@codemirror/lang-xml": "6.0.2", | 
				
			|||
        "@codemirror/language": "6.9.3", | 
				
			|||
        "@codemirror/search": "6.5.5", | 
				
			|||
        "@codemirror/state": "6.3.3", | 
				
			|||
        "@codemirror/view": "6.22.1", | 
				
			|||
        "codemirror": "6.0.1", | 
				
			|||
        "vue-codemirror6": "1.1.31" | 
				
			|||
    } | 
				
			|||
  "name": "io.sc.platform.mvc.frontend", | 
				
			|||
  "version": "8.1.12", | 
				
			|||
  "description": "", | 
				
			|||
  "private": false, | 
				
			|||
  "keywords": [], | 
				
			|||
  "author": "", | 
				
			|||
  "license": "ISC", | 
				
			|||
  "scripts": { | 
				
			|||
    "dev": "nodemon", | 
				
			|||
    "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			|||
    "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			|||
    "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			|||
    "sync": "platform sync", | 
				
			|||
    "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml" | 
				
			|||
  }, | 
				
			|||
  "engines": { | 
				
			|||
    "node": ">=18", | 
				
			|||
    "pnpm": ">=7" | 
				
			|||
  }, | 
				
			|||
  "publishConfig": { | 
				
			|||
    "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			|||
    "access": "public" | 
				
			|||
  }, | 
				
			|||
  "devDependencies": { | 
				
			|||
    "@babel/core": "7.23.2", | 
				
			|||
    "@babel/preset-env": "7.23.2", | 
				
			|||
    "@babel/preset-typescript": "7.23.2", | 
				
			|||
    "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			|||
    "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			|||
    "@quasar/app-webpack": "3.11.2", | 
				
			|||
    "@quasar/cli": "2.3.0", | 
				
			|||
    "@types/mockjs": "1.0.9", | 
				
			|||
    "@types/node": "20.8.9", | 
				
			|||
    "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			|||
    "@typescript-eslint/parser": "6.9.0", | 
				
			|||
    "@vue/compiler-sfc": "3.3.7", | 
				
			|||
    "@webpack-cli/serve": "2.0.5", | 
				
			|||
    "autoprefixer": "10.4.16", | 
				
			|||
    "babel-loader": "9.1.3", | 
				
			|||
    "clean-webpack-plugin": "4.0.0", | 
				
			|||
    "copy-webpack-plugin": "11.0.0", | 
				
			|||
    "cross-env": "7.0.3", | 
				
			|||
    "css-loader": "6.8.1", | 
				
			|||
    "eslint": "8.52.0", | 
				
			|||
    "eslint-config-prettier": "9.0.0", | 
				
			|||
    "eslint-plugin-prettier": "5.0.1", | 
				
			|||
    "eslint-plugin-vue": "9.18.0", | 
				
			|||
    "eslint-webpack-plugin": "4.0.1", | 
				
			|||
    "html-webpack-plugin": "5.5.3", | 
				
			|||
    "json5": "2.2.3", | 
				
			|||
    "mini-css-extract-plugin": "2.7.6", | 
				
			|||
    "nodemon": "3.0.1", | 
				
			|||
    "postcss": "8.4.31", | 
				
			|||
    "postcss-import": "15.1.0", | 
				
			|||
    "postcss-loader": "7.3.3", | 
				
			|||
    "postcss-preset-env": "9.2.0", | 
				
			|||
    "prettier": "3.0.3", | 
				
			|||
    "sass": "1.69.5", | 
				
			|||
    "sass-loader": "13.3.2", | 
				
			|||
    "typescript": "5.2.2", | 
				
			|||
    "vue-loader": "17.3.0", | 
				
			|||
    "webpack": "5.89.0", | 
				
			|||
    "webpack-bundle-analyzer": "4.9.1", | 
				
			|||
    "webpack-cli": "5.1.4", | 
				
			|||
    "webpack-dev-server": "4.15.1", | 
				
			|||
    "webpack-merge": "5.10.0" | 
				
			|||
  }, | 
				
			|||
  "dependencies": { | 
				
			|||
    "@quasar/extras": "1.16.7", | 
				
			|||
    "@vueuse/core": "10.3.0", | 
				
			|||
    "axios": "1.5.1", | 
				
			|||
    "dayjs": "1.11.10", | 
				
			|||
    "echarts": "5.4.1", | 
				
			|||
    "exceljs": "4.3.0", | 
				
			|||
    "file-saver": "2.0.5", | 
				
			|||
    "luckyexcel": "1.0.1", | 
				
			|||
    "mockjs": "1.1.0", | 
				
			|||
    "pinia": "2.1.7", | 
				
			|||
    "platform-core": "8.1.37", | 
				
			|||
    "quasar": "2.13.0", | 
				
			|||
    "tailwindcss": "3.3.5", | 
				
			|||
    "vue": "3.3.7", | 
				
			|||
    "vue-dompurify-html": "4.1.4", | 
				
			|||
    "vue-i18n": "9.6.0", | 
				
			|||
    "vue-router": "4.2.5", | 
				
			|||
    "@codemirror/autocomplete": "6.11.1", | 
				
			|||
    "@codemirror/commands": "6.3.2", | 
				
			|||
    "@codemirror/lang-html": "6.4.7", | 
				
			|||
    "@codemirror/lang-java": "6.0.1", | 
				
			|||
    "@codemirror/lang-javascript": "6.2.1", | 
				
			|||
    "@codemirror/lang-json": "6.0.1", | 
				
			|||
    "@codemirror/lang-sql": "6.5.4", | 
				
			|||
    "@codemirror/lang-xml": "6.0.2", | 
				
			|||
    "@codemirror/language": "6.9.3", | 
				
			|||
    "@codemirror/search": "6.5.5", | 
				
			|||
    "@codemirror/state": "6.3.3", | 
				
			|||
    "@codemirror/view": "6.22.1", | 
				
			|||
    "codemirror": "6.0.1", | 
				
			|||
    "vue-codemirror6": "1.1.31" | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
package io.sc.platform.mvc.support; | 
				
			|||
 | 
				
			|||
public class OrderItem<ID,ORDER> { | 
				
			|||
    private ID id; | 
				
			|||
    private ORDER order; | 
				
			|||
 | 
				
			|||
    public ID getId() { | 
				
			|||
        return id; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setId(ID id) { | 
				
			|||
        this.id = id; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public ORDER getOrder() { | 
				
			|||
        return order; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setOrder(ORDER order) { | 
				
			|||
        this.order = order; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,12 +1,12 @@ | 
				
			|||
[ | 
				
			|||
	/*系统*/ | 
				
			|||
	{"id":"parameter.system","order":0}, | 
				
			|||
		/*系统/首页 Thymeleaf 视图模板*/ | 
				
			|||
		/*系统/首页路由*/ | 
				
			|||
		{ | 
				
			|||
			"id"			: "parameter.system.indexPageTemplate", | 
				
			|||
			"id"			: "parameter.system.homePage", | 
				
			|||
			"parentId"		: "parameter.system", | 
				
			|||
			"code"			: "parameter.system.indexPageTemplate", | 
				
			|||
			"defaultValue"	: "io.sc.platform.mvc.frontend.html", | 
				
			|||
			"code"			: "parameter.system.homePage", | 
				
			|||
			"defaultValue"	: "/home", | 
				
			|||
			"order"			: 100 | 
				
			|||
		} | 
				
			|||
] | 
				
			|||
@ -0,0 +1,44 @@ | 
				
			|||
package io.sc.platform.system.api.announcement; | 
				
			|||
 | 
				
			|||
import com.fasterxml.jackson.annotation.JsonPropertyOrder; | 
				
			|||
import io.sc.platform.orm.api.vo.AuditorVo; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
@JsonPropertyOrder({ | 
				
			|||
        "id", | 
				
			|||
        "title", | 
				
			|||
        "content", | 
				
			|||
        "creator", | 
				
			|||
        "createDate", | 
				
			|||
        "lastModifier", | 
				
			|||
        "lastModifyDate" | 
				
			|||
}) | 
				
			|||
public class AnnouncementVo extends AuditorVo { | 
				
			|||
    private String id; | 
				
			|||
    private String title; | 
				
			|||
    private String content; | 
				
			|||
 | 
				
			|||
    public String getId() { | 
				
			|||
        return id; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setId(String id) { | 
				
			|||
        this.id = id; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public String getTitle() { | 
				
			|||
        return title; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setTitle(String title) { | 
				
			|||
        this.title = title; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public String getContent() { | 
				
			|||
        return content; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setContent(String content) { | 
				
			|||
        this.content = content; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,4 +0,0 @@ | 
				
			|||
package io.sc.platform.system.api.parameter; | 
				
			|||
 | 
				
			|||
public class Parameter { | 
				
			|||
} | 
				
			|||
@ -0,0 +1,40 @@ | 
				
			|||
package io.sc.platform.system.api.parameter; | 
				
			|||
 | 
				
			|||
public class ParameterVo { | 
				
			|||
    private String id; | 
				
			|||
    private String code; | 
				
			|||
    private String value; | 
				
			|||
    private String parentId; | 
				
			|||
 | 
				
			|||
    public String getId() { | 
				
			|||
        return id; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setId(String id) { | 
				
			|||
        this.id = id; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public String getCode() { | 
				
			|||
        return code; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setCode(String code) { | 
				
			|||
        this.code = code; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public String getValue() { | 
				
			|||
        return value; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setValue(String value) { | 
				
			|||
        this.value = value; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public String getParentId() { | 
				
			|||
        return parentId; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public void setParentId(String parentId) { | 
				
			|||
        this.parentId = parentId; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,4 +0,0 @@ | 
				
			|||
<template> | 
				
			|||
  <div>Corporation</div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"></script> | 
				
			|||
@ -1,4 +0,0 @@ | 
				
			|||
<template> | 
				
			|||
  <div>Dictionary</div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"></script> | 
				
			|||
@ -1,4 +0,0 @@ | 
				
			|||
<template> | 
				
			|||
  <div>Parameter</div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"></script> | 
				
			|||
@ -0,0 +1,70 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <platform-grid | 
				
			|||
      ref="announcementGridRef" | 
				
			|||
      :table-props="{ borderded: false, flat: true }" | 
				
			|||
      :query-form-cols-number="announcementConfigure.queryFormColsNumber" | 
				
			|||
      :query-form-cols-auto="announcementConfigure.queryFormColsAuto" | 
				
			|||
      :table-title="announcementConfigure.tableTitle" | 
				
			|||
      :table-row-key="announcementConfigure.tableRowKey" | 
				
			|||
      :table-init-load-data="announcementConfigure.tableInitLoadData" | 
				
			|||
      :table-data-url="announcementConfigure.tableDataUrl" | 
				
			|||
      :table-show-sort-no="false" | 
				
			|||
      :table-columns="announcementConfigure.tableColumns" | 
				
			|||
      :table-left-column-sticky-number="announcementConfigure.tableLeftColumnStickyNumber" | 
				
			|||
      :table-buttons="announcementConfigure.tableButtons" | 
				
			|||
      :query-form-fields="announcementConfigure.queryFormFields" | 
				
			|||
      :table-pagination="announcementConfigure.tablePagination" | 
				
			|||
      :add-form-props="announcementConfigure.addFormProps" | 
				
			|||
      :table-dense="false" | 
				
			|||
      @row-click="announcementConfigure.rowClickFun" | 
				
			|||
    > | 
				
			|||
    </platform-grid> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { ref } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { Environment, axios } from 'platform-core'; | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const announcementConfigure = { | 
				
			|||
  queryFormColsNumber: 4, | 
				
			|||
  queryFormColsAuto: false, | 
				
			|||
  hideBottom: false, | 
				
			|||
  tableInitLoadData: true, | 
				
			|||
  tableLeftColumnStickyNumber: 0, | 
				
			|||
  tableTitle: t('system.announcement.gridTitle'), | 
				
			|||
  tableRowKey: 'id', | 
				
			|||
  tableDataUrl: Environment.apiContextPath('/api/system/announcement'), | 
				
			|||
  tablePagination: { | 
				
			|||
    sortBy: 'lastModifyDate', | 
				
			|||
    descending: true, | 
				
			|||
    reqPageStart: 0, | 
				
			|||
    rowsPerPage: 10, | 
				
			|||
  }, | 
				
			|||
  queryFormFields: [ | 
				
			|||
    { width: 100, name: 'title', label: t('title') }, | 
				
			|||
    { width: 110, name: 'lastModifier', label: t('lastModifier') }, | 
				
			|||
    { width: 115, name: 'lastModifyDate', label: t('lastModifyDate') }, | 
				
			|||
  ], | 
				
			|||
  tableButtons: ['add', 'edit', 'delete', 'separator', 'view', 'inFullscreen'], | 
				
			|||
  tableColumns: [ | 
				
			|||
    { width: 100, name: 'title', label: t('title') }, | 
				
			|||
    { width: 100, name: 'content', label: t('content') }, | 
				
			|||
    { width: 110, name: 'lastModifier', label: t('lastModifier') }, | 
				
			|||
    { width: 115, name: 'lastModifyDate', label: t('lastModifyDate') }, | 
				
			|||
  ], | 
				
			|||
  addFormProps: { | 
				
			|||
    dialogInitWidth: '50%', | 
				
			|||
    dialogInitHeight: '90%', | 
				
			|||
    formColsNumber: 1, | 
				
			|||
    formColsAuto: false, | 
				
			|||
    formFields: [ | 
				
			|||
      { modelName: 'title', label: t('title'), type: 'text', required: true }, | 
				
			|||
      { modelName: 'content', label: t('content'), type: 'textarea', required: true }, | 
				
			|||
    ], | 
				
			|||
  }, | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,51 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <w-tree-grid ref="corporationTreeGridRef" title="法人树" label-key="name" :actions="corporationConfigure.actions" /> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { ref, onMounted } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { Environment, axios } from 'platform-core'; | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const corporationTreeGridRef = ref(); | 
				
			|||
 | 
				
			|||
const corporationConfigure = { | 
				
			|||
  actions: [ | 
				
			|||
    { | 
				
			|||
      name: 'refresh', | 
				
			|||
      label: t('refresh'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    { | 
				
			|||
      name: 'addRoot', | 
				
			|||
      label: t('system.corporation.action.addTop'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'addChild', | 
				
			|||
      label: t('system.corporation.action.addChild'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'edit', | 
				
			|||
      label: t('edit'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'delete', | 
				
			|||
      label: t('delete'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
  ], | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
onMounted(() => { | 
				
			|||
  axios.get(Environment.apiContextPath('/api/system/corporation?pageable=false&sortBy=name')).then((response) => { | 
				
			|||
    corporationTreeGridRef.value.setNodes(response.data.content); | 
				
			|||
  }); | 
				
			|||
}); | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,70 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <platform-grid | 
				
			|||
      ref="dictionaryGridRef" | 
				
			|||
      :table-props="{ borderded: false, flat: true }" | 
				
			|||
      :table-title="dictionaryConfigure.tableTitle" | 
				
			|||
      :table-init-load-data="dictionaryConfigure.tableInitLoadData" | 
				
			|||
      :table-row-key="dictionaryConfigure.tableRowKey" | 
				
			|||
      :table-data-url="dictionaryConfigure.tableDataUrl" | 
				
			|||
      :table-columns="dictionaryConfigure.tableColumns" | 
				
			|||
      :table-buttons="dictionaryConfigure.tableButtons" | 
				
			|||
      :add-form-props="dictionaryConfigure.addFormProps" | 
				
			|||
      :table-show-sort-no="false" | 
				
			|||
      :table-dense="true" | 
				
			|||
      :table-row-drag="true" | 
				
			|||
      :table-pagination="dictionaryConfigure.tablePagination" | 
				
			|||
      @row-drag-drop-after="rowDragDropAfter" | 
				
			|||
    > | 
				
			|||
    </platform-grid> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { onMounted, ref } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { Environment, axios } from 'platform-core'; | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const dictionaryGridRef = ref(); | 
				
			|||
const dictionaryConfigure = { | 
				
			|||
  tableTitle: '数据字典列表', | 
				
			|||
  tableInitLoadData: true, | 
				
			|||
  tableRowKey: 'id', | 
				
			|||
  tableDataUrl: Environment.apiContextPath('/api/system/dictionary'), | 
				
			|||
  tablePagination: { | 
				
			|||
    sortBy: 'order', | 
				
			|||
    descending: false, | 
				
			|||
    reqPageStart: 0, | 
				
			|||
    rowsPerPage: 0, | 
				
			|||
  }, | 
				
			|||
  tableColumns: [ | 
				
			|||
    { name: 'code', label: t('code') }, | 
				
			|||
    { name: 'value', label: t('value') }, | 
				
			|||
    { name: 'value', label: t('displayValue'), format: (value) => t(value) }, | 
				
			|||
    { name: 'order', label: t('order') }, | 
				
			|||
  ], | 
				
			|||
  tableButtons: ['refresh', 'add', 'edit', 'delete'], | 
				
			|||
  addFormProps: { | 
				
			|||
    dialogInitWidth: '50%', | 
				
			|||
    dialogInitHeight: '90%', | 
				
			|||
    formColsNumber: 1, | 
				
			|||
    formColsAuto: false, | 
				
			|||
    formFields: [ | 
				
			|||
      { modelName: 'code', label: t('code'), type: 'text', required: true }, | 
				
			|||
      { modelName: 'value', label: t('value'), type: 'text', required: true }, | 
				
			|||
      { modelName: 'order', label: t('order'), type: 'text', required: true }, | 
				
			|||
    ], | 
				
			|||
  }, | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const rowDragDropAfter = () => { | 
				
			|||
  const rows = dictionaryGridRef.value.getRowsFun(); | 
				
			|||
  for (let i = 0; i < rows.length; i++) { | 
				
			|||
    rows[i].order = i; | 
				
			|||
  } | 
				
			|||
  axios.post(Environment.apiContextPath('/api/system/dictionary/updateDictionariesOrder'), rows).then(() => { | 
				
			|||
    //dictionaryGridRef.value.refreshTable(); | 
				
			|||
  }); | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,70 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <platform-grid | 
				
			|||
      ref="i18nGridRef" | 
				
			|||
      :table-props="{ borderded: false, flat: true }" | 
				
			|||
      :table-title="i18nConfigure.tableTitle" | 
				
			|||
      :table-init-load-data="i18nConfigure.tableInitLoadData" | 
				
			|||
      :table-row-key="i18nConfigure.tableRowKey" | 
				
			|||
      :table-data-url="i18nConfigure.tableDataUrl" | 
				
			|||
      :table-columns="i18nConfigure.tableColumns" | 
				
			|||
      :table-buttons="i18nConfigure.tableButtons" | 
				
			|||
      :add-form-props="i18nConfigure.addFormProps" | 
				
			|||
      :table-show-sort-no="false" | 
				
			|||
      :table-dense="true" | 
				
			|||
      :table-row-drag="true" | 
				
			|||
      :table-pagination="i18nConfigure.tablePagination" | 
				
			|||
    > | 
				
			|||
    </platform-grid> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { onMounted, ref } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { Environment, axios } from 'platform-core'; | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const Language = { | 
				
			|||
  en: '英文', | 
				
			|||
  zh_CN: '简体中文', | 
				
			|||
  tw_CN: '繁体中文', | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const LanguageOptions = [ | 
				
			|||
  { label: '英文', value: 'en' }, | 
				
			|||
  { label: '简体中文', value: 'zh_CN' }, | 
				
			|||
  { label: '繁体中文', value: 'tw_CN' }, | 
				
			|||
]; | 
				
			|||
 | 
				
			|||
const i18nGridRef = ref(); | 
				
			|||
const i18nConfigure = { | 
				
			|||
  tableTitle: '多语言消息列表', | 
				
			|||
  tableInitLoadData: true, | 
				
			|||
  tableRowKey: 'id', | 
				
			|||
  tableDataUrl: Environment.apiContextPath('/api/system/i18n'), | 
				
			|||
  tablePagination: { | 
				
			|||
    sortBy: 'code', | 
				
			|||
    descending: false, | 
				
			|||
    reqPageStart: 0, | 
				
			|||
    rowsPerPage: 20, | 
				
			|||
  }, | 
				
			|||
  tableColumns: [ | 
				
			|||
    { name: 'code', label: t('code') }, | 
				
			|||
    { name: 'lang', label: t('lang'), format: (value) => Language[value] }, | 
				
			|||
    { name: 'message', label: t('message') }, | 
				
			|||
  ], | 
				
			|||
  tableButtons: ['refresh', 'add', 'edit', 'delete'], | 
				
			|||
  addFormProps: { | 
				
			|||
    dialogInitWidth: '50%', | 
				
			|||
    dialogInitHeight: '90%', | 
				
			|||
    formColsNumber: 1, | 
				
			|||
    formColsAuto: false, | 
				
			|||
    formFields: [ | 
				
			|||
      { modelName: 'code', label: t('code'), type: 'text', required: true }, | 
				
			|||
      { modelName: 'lang', label: t('lang'), type: 'select', required: true, options: LanguageOptions }, | 
				
			|||
      { modelName: 'message', label: t('message'), type: 'text', required: true }, | 
				
			|||
    ], | 
				
			|||
  }, | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,248 @@ | 
				
			|||
<template> | 
				
			|||
  <q-splitter :model-value="70" class="w-full h-full"> | 
				
			|||
    <template #before> | 
				
			|||
      <w-tree-grid | 
				
			|||
        ref="menuTreeGridRef" | 
				
			|||
        title="菜单树" | 
				
			|||
        label-key="titleI18nKey" | 
				
			|||
        label-i18n | 
				
			|||
        label-empty="--------------------" | 
				
			|||
        :actions="menuConfigure.actions" | 
				
			|||
        tick-strategy="none" | 
				
			|||
        @update:selected="menuSelected" | 
				
			|||
      /> | 
				
			|||
    </template> | 
				
			|||
    <template #after> | 
				
			|||
      <q-tabs v-model="selectedTabRef" inline-label align="left" :breakpoint="0"> | 
				
			|||
        <q-tab name="role" icon="bi-diagram-3" :label="$t('role')" /> | 
				
			|||
        <q-tab name="org" icon="bi-people" :label="$t('org')" /> | 
				
			|||
      </q-tabs> | 
				
			|||
 | 
				
			|||
      <q-tab-panels v-model="selectedTabRef" animated swipeable keep-alive> | 
				
			|||
        <q-tab-panel name="user"> | 
				
			|||
          <platform-grid | 
				
			|||
            ref="roleGridRef" | 
				
			|||
            :table-props="{ borderded: false, flat: true }" | 
				
			|||
            :query-form-cols-number="roleConfigure.queryFormColsNumber" | 
				
			|||
            :hide-bottom="roleConfigure.hideBottom" | 
				
			|||
            :query-form-cols-auto="roleConfigure.queryFormColsAuto" | 
				
			|||
            :table-title="roleConfigure.tableTitle" | 
				
			|||
            :table-row-key="roleConfigure.tableRowKey" | 
				
			|||
            :table-init-load-data="roleConfigure.tableInitLoadData" | 
				
			|||
            :table-data-url="roleConfigure.tableDataUrl" | 
				
			|||
            :table-show-sort-no="false" | 
				
			|||
            :table-columns="roleConfigure.tableColumns" | 
				
			|||
            :table-left-column-sticky-number="roleConfigure.tableLeftColumnStickyNumber" | 
				
			|||
            :table-buttons="roleConfigure.tableButtons" | 
				
			|||
            :query-form-fields="roleConfigure.queryFormFields" | 
				
			|||
            :table-pagination="roleConfigure.tablePagination" | 
				
			|||
            table-selection="multiple" | 
				
			|||
            :table-dense="false" | 
				
			|||
          > | 
				
			|||
          </platform-grid> | 
				
			|||
        </q-tab-panel> | 
				
			|||
 | 
				
			|||
        <q-tab-panel name="org"> | 
				
			|||
          <w-tree-grid | 
				
			|||
            ref="orgTreeGridRef" | 
				
			|||
            title="机构树" | 
				
			|||
            label-key="titleI18nKey" | 
				
			|||
            label-i18n | 
				
			|||
            label-empty="--------------------" | 
				
			|||
            :actions="orgConfigure.actions" | 
				
			|||
          /> | 
				
			|||
        </q-tab-panel> | 
				
			|||
      </q-tab-panels> | 
				
			|||
    </template> | 
				
			|||
    <SelectRoleDialog ref="selectRoleDialog" title="可选角色列表" :maximized="false" width="50%" height="500px"></SelectRoleDialog> | 
				
			|||
  </q-splitter> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { ref, onMounted } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { Environment, axios } from 'platform-core'; | 
				
			|||
import SelectRoleDialog from './SelectRoleDialog.vue'; | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const menuTreeGridRef = ref(); | 
				
			|||
const roleGridRef = ref(); | 
				
			|||
const orgTreeGridRef = ref(); | 
				
			|||
 | 
				
			|||
const selectRoleDialog = ref(); | 
				
			|||
const selectedTabRef = ref('user'); | 
				
			|||
let selectedMenuId = ''; | 
				
			|||
 | 
				
			|||
const roleConfigure = { | 
				
			|||
  queryFormColsNumber: 4, | 
				
			|||
  queryFormColsAuto: false, | 
				
			|||
  queryFormFields: [], | 
				
			|||
  hideBottom: true, | 
				
			|||
  tableInitLoadData: false, | 
				
			|||
  tableLeftColumnStickyNumber: 0, | 
				
			|||
  tableTitle: t('system.role.gridTitle'), | 
				
			|||
  tableRowKey: 'id', | 
				
			|||
  tableDataUrl: '', | 
				
			|||
  tablePagination: { | 
				
			|||
    sortBy: 'lastModifyDate', | 
				
			|||
    descending: true, | 
				
			|||
    reqPageStart: 0, | 
				
			|||
    rowsPerPage: 0, | 
				
			|||
  }, | 
				
			|||
  tableButtons: [ | 
				
			|||
    'refresh', | 
				
			|||
    'inFullscreen', | 
				
			|||
    { | 
				
			|||
      name: 'addRole', | 
				
			|||
      label: t('system.role.action.addRole'), | 
				
			|||
      icon: '', | 
				
			|||
      enable: () => {}, | 
				
			|||
      click: () => { | 
				
			|||
        selectRoleDialog.value.show({ roleGridRef: roleGridRef, menuTreeGridRef: menuTreeGridRef }); | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'addAllRole', | 
				
			|||
      label: t('system.role.action.addAllRole'), | 
				
			|||
      icon: '', | 
				
			|||
      enable: () => {}, | 
				
			|||
      click: () => { | 
				
			|||
        const menuId = menuTreeGridRef.value.getSelected(); | 
				
			|||
        axios | 
				
			|||
          .post(Environment.apiContextPath('/api/system/menu/addAllRoles'), { | 
				
			|||
            source: menuId, | 
				
			|||
            sourceParents: menuTreeGridRef.value.getCascadeParentIds(menuId), | 
				
			|||
            sourceChildren: menuTreeGridRef.value.getCascadeChildrenIds(menuId), | 
				
			|||
            targets: [], | 
				
			|||
          }) | 
				
			|||
          .then((response) => { | 
				
			|||
            axios.get(Environment.apiContextPath('/api/system/role/queryRolesByMenu?menuId=') + menuId).then((response) => { | 
				
			|||
              roleGridRef.value.replaceRowsFun(response.data.content); | 
				
			|||
            }); | 
				
			|||
          }); | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'removeRole', | 
				
			|||
      label: t('system.role.action.removeRole'), | 
				
			|||
      icon: '', | 
				
			|||
      enable: () => {}, | 
				
			|||
      click: () => { | 
				
			|||
        const menuId = menuTreeGridRef.value.getSelected(); | 
				
			|||
        const roleIds = []; | 
				
			|||
        for (const role of roleGridRef.value.getSelectedRows()) { | 
				
			|||
          roleIds.push(role.id); | 
				
			|||
        } | 
				
			|||
        axios | 
				
			|||
          .post(Environment.apiContextPath('/api/system/menu/removeRoles'), { | 
				
			|||
            source: menuId, | 
				
			|||
            sourceParents: menuTreeGridRef.value.getCascadeParentIds(menuId), | 
				
			|||
            sourceChildren: menuTreeGridRef.value.getCascadeChildrenIds(menuId), | 
				
			|||
            targets: roleIds, | 
				
			|||
          }) | 
				
			|||
          .then((response) => { | 
				
			|||
            axios.get(Environment.apiContextPath('/api/system/role/queryRolesByMenu?menuId=') + menuId).then((response) => { | 
				
			|||
              roleGridRef.value.replaceRowsFun(response.data.content); | 
				
			|||
            }); | 
				
			|||
          }); | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'removeAllRole', | 
				
			|||
      label: t('system.role.action.removeAllRole'), | 
				
			|||
      icon: '', | 
				
			|||
      enable: () => {}, | 
				
			|||
      click: () => { | 
				
			|||
        const menuId = menuTreeGridRef.value.getSelected(); | 
				
			|||
        axios | 
				
			|||
          .post(Environment.apiContextPath('/api/system/menu/removeAllRoles'), { | 
				
			|||
            source: menuId, | 
				
			|||
            sourceParents: menuTreeGridRef.value.getCascadeParentIds(menuId), | 
				
			|||
            sourceChildren: menuTreeGridRef.value.getCascadeChildrenIds(menuId), | 
				
			|||
            targets: [], | 
				
			|||
          }) | 
				
			|||
          .then((response) => { | 
				
			|||
            axios.get(Environment.apiContextPath('/api/system/role/queryRolesByMenu?menuId=') + menuId).then((response) => { | 
				
			|||
              roleGridRef.value.replaceRowsFun(response.data.content); | 
				
			|||
            }); | 
				
			|||
          }); | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
  ], | 
				
			|||
  tableColumns: [ | 
				
			|||
    { width: 100, name: 'code', label: t('code') }, | 
				
			|||
    { width: 100, name: 'name', label: t('name') }, | 
				
			|||
    { width: 80, name: 'enable', label: t('isEnable'), format: (value) => (value ? t('yes') : t('no')) }, | 
				
			|||
  ], | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const menuConfigure = { | 
				
			|||
  actions: [ | 
				
			|||
    { | 
				
			|||
      name: 'refresh', | 
				
			|||
      label: t('refresh'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
 | 
				
			|||
    { | 
				
			|||
      name: 'addRoot', | 
				
			|||
      label: t('system.menu.action.addTop'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'addChild', | 
				
			|||
      label: t('system.menu.action.addChild'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'edit', | 
				
			|||
      label: t('edit'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      name: 'delete', | 
				
			|||
      label: t('delete'), | 
				
			|||
      click: () => {}, | 
				
			|||
    }, | 
				
			|||
  ], | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const orgConfigure = { | 
				
			|||
  actions: [ | 
				
			|||
    { | 
				
			|||
      name: 'save', | 
				
			|||
      label: '保存', | 
				
			|||
      click: () => { | 
				
			|||
        const orgId = menuTreeGridRef.value.getSelected()[0]; | 
				
			|||
        axios | 
				
			|||
          .post(Environment.apiContextPath('/api/system/menu/updateOrgs'), { | 
				
			|||
            one: orgId, | 
				
			|||
            many: menuTreeGridRef.value.getTicked(), | 
				
			|||
          }) | 
				
			|||
          .then((response) => {}); | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
  ], | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const menuSelected = (target) => { | 
				
			|||
  selectedMenuId = target; | 
				
			|||
  if (roleGridRef.value) { | 
				
			|||
    axios.get(Environment.apiContextPath('/api/system/role/queryRolesByMenu?menuId=') + selectedMenuId).then((response) => { | 
				
			|||
      roleGridRef.value.replaceRowsFun(response.data.content); | 
				
			|||
    }); | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  // if (orgTreeGridRef.value) { | 
				
			|||
  //   axios.get(Environment.apiContextPath('/api/system/org/listAllOrgsWithSelectedStatusByMenu?menuId=') + selectedMenuId).then((response) => { | 
				
			|||
  //     orgTreeGridRef.value.setNodes(response.data); | 
				
			|||
  //   }); | 
				
			|||
  // } | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
onMounted(() => { | 
				
			|||
  axios.get(Environment.apiContextPath('/api/system/menu?pageable=false&sortBy=order')).then((response) => { | 
				
			|||
    menuTreeGridRef.value.setNodes(response.data.content); | 
				
			|||
  }); | 
				
			|||
}); | 
				
			|||
</script> | 
				
			|||
@ -0,0 +1,155 @@ | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <q-dialog ref="dialogRef" allow-focus-outside v-bind="attrs"> | 
				
			|||
      <q-card | 
				
			|||
        :style="{ | 
				
			|||
          width: attrs.maximized ? '100vw' : width, | 
				
			|||
          'max-width': '100vw', | 
				
			|||
          height: attrs.maximized ? '100vh' : height, | 
				
			|||
          'max-height': '100vh', | 
				
			|||
        }" | 
				
			|||
      > | 
				
			|||
        <q-card-section :style="headerStyle"> | 
				
			|||
          <div class="flex justify-between"> | 
				
			|||
            <div class="text-h6">{{ title }}</div> | 
				
			|||
            <div class="flex justify-end q-gutter-md"> | 
				
			|||
              <q-btn :label="$t('confirm')" dense color="primary" style="width: 100px" @click="addRoles" /> | 
				
			|||
              <q-btn v-close-popup dense flat icon="close" :title="$t('close')"> </q-btn> | 
				
			|||
            </div> | 
				
			|||
          </div> | 
				
			|||
        </q-card-section> | 
				
			|||
        <q-card-section class="q-pt-none" :style="bodyStyle"> | 
				
			|||
          <platform-grid | 
				
			|||
            ref="gridRef" | 
				
			|||
            :table-props="{ borderded: false, flat: true }" | 
				
			|||
            :query-form-cols-number="roleConfigure.queryFormColsNumber" | 
				
			|||
            :hide-bottom="roleConfigure.hideBottom" | 
				
			|||
            :query-form-cols-auto="roleConfigure.queryFormColsAuto" | 
				
			|||
            :table-title="roleConfigure.tableTitle" | 
				
			|||
            :table-row-key="roleConfigure.tableRowKey" | 
				
			|||
            :table-init-load-data="roleConfigure.tableInitLoadData" | 
				
			|||
            :table-data-url="roleConfigure.tableDataUrl" | 
				
			|||
            :table-show-sort-no="false" | 
				
			|||
            :table-columns="roleConfigure.tableColumns" | 
				
			|||
            :table-left-column-sticky-number="roleConfigure.tableLeftColumnStickyNumber" | 
				
			|||
            :table-buttons="roleConfigure.tableButtons" | 
				
			|||
            :query-form-fields="roleConfigure.queryFormFields" | 
				
			|||
            :table-pagination="roleConfigure.tablePagination" | 
				
			|||
            table-selection="multiple" | 
				
			|||
            :table-dense="false" | 
				
			|||
          > | 
				
			|||
          </platform-grid> | 
				
			|||
        </q-card-section> | 
				
			|||
      </q-card> | 
				
			|||
    </q-dialog> | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { useAttrs, ref, onMounted, nextTick } from 'vue'; | 
				
			|||
import { useI18n } from 'vue-i18n'; | 
				
			|||
import { axios, Environment } from 'platform-core'; | 
				
			|||
 | 
				
			|||
const attrs = useAttrs(); | 
				
			|||
 | 
				
			|||
const props = defineProps({ | 
				
			|||
  headerStyle: { type: String, default: 'width:100%;padding: 16px 8px 4px 16px' }, | 
				
			|||
  bodyStyle: { type: String, default: 'padding: 0px 8px 0px 8px;height:calc(100%)' }, | 
				
			|||
  title: { type: String, default: '' }, | 
				
			|||
  width: { type: String, default: '70%' }, | 
				
			|||
  height: { type: String, default: '70%' }, | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
const { t } = useI18n(); | 
				
			|||
 | 
				
			|||
const dialogRef = ref(); | 
				
			|||
const gridRef = ref(); | 
				
			|||
let menuTreeGridRef, roleGridRef; | 
				
			|||
 | 
				
			|||
const roleConfigure = { | 
				
			|||
  queryFormColsNumber: 4, | 
				
			|||
  queryFormColsAuto: false, | 
				
			|||
  hideBottom: true, | 
				
			|||
  tableInitLoadData: false, | 
				
			|||
  tableLeftColumnStickyNumber: 0, | 
				
			|||
  tableTitle: '', | 
				
			|||
  tableRowKey: 'id', | 
				
			|||
  tableDataUrl: '', | 
				
			|||
  tablePagination: { | 
				
			|||
    sortBy: 'lastModifyDate', | 
				
			|||
    descending: true, | 
				
			|||
    reqPageStart: 0, | 
				
			|||
    rowsPerPage: 0, | 
				
			|||
  }, | 
				
			|||
  tableButtons: ['query', 'refresh'], | 
				
			|||
  queryFormFields: [ | 
				
			|||
    { label: t('code'), modelName: 'code', type: 'text' }, | 
				
			|||
    { label: t('name'), modelName: 'name', type: 'text' }, | 
				
			|||
    { | 
				
			|||
      label: t('enable'), | 
				
			|||
      modelName: 'enable', | 
				
			|||
      type: 'select', | 
				
			|||
      options: [ | 
				
			|||
        { value: true, label: '是' }, | 
				
			|||
        { value: false, label: '否' }, | 
				
			|||
      ], | 
				
			|||
    }, | 
				
			|||
    { | 
				
			|||
      label: t('dataComeFrom'), | 
				
			|||
      modelName: 'dataComeFrom', | 
				
			|||
      type: 'select', | 
				
			|||
      options: [ | 
				
			|||
        { value: 'MANUAL', label: t('io.sc.platform.orm.api.enums.DataComeFrom.MANUAL') }, | 
				
			|||
        { value: 'AUTO', label: t('io.sc.platform.orm.api.enums.DataComeFrom.AUTO') }, | 
				
			|||
      ], | 
				
			|||
    }, | 
				
			|||
  ], | 
				
			|||
  tableColumns: [ | 
				
			|||
    { width: 100, name: 'code', label: t('code') }, | 
				
			|||
    { width: 100, name: 'name', label: t('name') }, | 
				
			|||
    { width: 80, name: 'enable', label: t('isEnable'), format: (value) => (value ? t('yes') : t('no')) }, | 
				
			|||
  ], | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const addRoles = () => { | 
				
			|||
  const menuId = menuTreeGridRef.value.getSelected(); | 
				
			|||
  const roleIds = []; | 
				
			|||
  for (const role of gridRef.value.getSelectedRows()) { | 
				
			|||
    roleIds.push(role.id); | 
				
			|||
  } | 
				
			|||
  axios | 
				
			|||
    .post(Environment.apiContextPath('/api/system/menu/addRoles'), { | 
				
			|||
      source: menuId, | 
				
			|||
      sourceParents: menuTreeGridRef.value.getCascadeParentIds(menuId), | 
				
			|||
      sourceChildren: menuTreeGridRef.value.getCascadeChildrenIds(menuId), | 
				
			|||
      targets: roleIds, | 
				
			|||
    }) | 
				
			|||
    .then((response) => { | 
				
			|||
      axios.get(Environment.apiContextPath('/api/system/role/queryRolesByMenu?menuId=') + menuId).then((response) => { | 
				
			|||
        roleGridRef.value.replaceRowsFun(response.data.content); | 
				
			|||
      }); | 
				
			|||
      dialogRef.value.hide(); | 
				
			|||
    }); | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const show = (param: object) => { | 
				
			|||
  menuTreeGridRef = param.menuTreeGridRef; | 
				
			|||
  roleGridRef = param.roleGridRef; | 
				
			|||
  const currentMenuId = menuTreeGridRef.value.getSelected()[0]; | 
				
			|||
 | 
				
			|||
  dialogRef.value.show(); | 
				
			|||
  nextTick(() => { | 
				
			|||
    axios.get(Environment.apiContextPath('/api/system/role/queryOtherRolesByMenu?menuId=') + currentMenuId).then((response) => { | 
				
			|||
      gridRef.value.replaceRowsFun(response.data.content); | 
				
			|||
    }); | 
				
			|||
  }); | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
const hide = () => { | 
				
			|||
  dialogRef.value.hide(); | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
defineExpose({ | 
				
			|||
  show, | 
				
			|||
  hide, | 
				
			|||
}); | 
				
			|||
</script> | 
				
			|||
Some files were not shown because too many files changed in this diff
					Loading…
					
					
				
		Reference in new issue