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", | 
					  "name": "io.sc.platform.developer.frontend", | 
				
			||||
    "version": "8.1.11", | 
					  "version": "8.1.12", | 
				
			||||
    "description": "", | 
					  "description": "", | 
				
			||||
    "private": false, | 
					  "private": false, | 
				
			||||
    "keywords": [ | 
					  "keywords": [], | 
				
			||||
         | 
					  "author": "", | 
				
			||||
    ], | 
					  "license": "ISC", | 
				
			||||
    "author": "", | 
					  "scripts": { | 
				
			||||
    "license": "ISC", | 
					    "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
				
			||||
    "scripts": { | 
					    "dev": "nodemon", | 
				
			||||
        "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
					    "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			||||
        "dev": "nodemon", | 
					    "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			||||
        "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
					    "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			||||
        "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
					    "sync": "platform sync" | 
				
			||||
        "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
					  }, | 
				
			||||
        "sync": "platform sync" | 
					  "engines": { | 
				
			||||
    }, | 
					    "node": ">=18", | 
				
			||||
    "engines": { | 
					    "pnpm": ">=7" | 
				
			||||
        "node": ">=18", | 
					  }, | 
				
			||||
        "pnpm": ">=7" | 
					  "publishConfig": { | 
				
			||||
    }, | 
					    "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			||||
    "publishConfig": { | 
					    "access": "public" | 
				
			||||
        "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
					  }, | 
				
			||||
        "access": "public" | 
					  "devDependencies": { | 
				
			||||
    }, | 
					    "@babel/core": "7.23.2", | 
				
			||||
    "devDependencies": { | 
					    "@babel/preset-env": "7.23.2", | 
				
			||||
        "@babel/core": "7.23.2", | 
					    "@babel/preset-typescript": "7.23.2", | 
				
			||||
        "@babel/preset-env": "7.23.2", | 
					    "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			||||
        "@babel/preset-typescript": "7.23.2", | 
					    "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			||||
        "@babel/plugin-transform-class-properties": "7.22.5", | 
					    "@quasar/app-webpack": "3.11.2", | 
				
			||||
        "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
					    "@quasar/cli": "2.3.0", | 
				
			||||
        "@quasar/app-webpack": "3.11.2", | 
					    "@types/mockjs": "1.0.9", | 
				
			||||
        "@quasar/cli": "2.3.0", | 
					    "@types/node": "20.8.9", | 
				
			||||
        "@types/mockjs": "1.0.9", | 
					    "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			||||
        "@types/node": "20.8.9", | 
					    "@typescript-eslint/parser": "6.9.0", | 
				
			||||
        "@typescript-eslint/eslint-plugin": "6.9.0", | 
					    "@vue/compiler-sfc": "3.3.7", | 
				
			||||
        "@typescript-eslint/parser": "6.9.0", | 
					    "@webpack-cli/serve": "2.0.5", | 
				
			||||
        "@vue/compiler-sfc": "3.3.7", | 
					    "autoprefixer": "10.4.16", | 
				
			||||
        "@webpack-cli/serve": "2.0.5", | 
					    "babel-loader": "9.1.3", | 
				
			||||
        "autoprefixer": "10.4.16", | 
					    "clean-webpack-plugin": "4.0.0", | 
				
			||||
        "babel-loader": "9.1.3", | 
					    "copy-webpack-plugin": "11.0.0", | 
				
			||||
        "clean-webpack-plugin": "4.0.0", | 
					    "cross-env": "7.0.3", | 
				
			||||
        "copy-webpack-plugin": "11.0.0", | 
					    "css-loader": "6.8.1", | 
				
			||||
        "cross-env": "7.0.3", | 
					    "eslint": "8.52.0", | 
				
			||||
        "css-loader": "6.8.1", | 
					    "eslint-config-prettier": "9.0.0", | 
				
			||||
        "eslint": "8.52.0", | 
					    "eslint-plugin-prettier": "5.0.1", | 
				
			||||
        "eslint-config-prettier": "9.0.0", | 
					    "eslint-plugin-vue": "9.18.0", | 
				
			||||
        "eslint-plugin-prettier": "5.0.1", | 
					    "eslint-webpack-plugin": "4.0.1", | 
				
			||||
        "eslint-plugin-vue": "9.18.0", | 
					    "html-webpack-plugin": "5.5.3", | 
				
			||||
        "eslint-webpack-plugin": "4.0.1", | 
					    "json5": "2.2.3", | 
				
			||||
        "html-webpack-plugin": "5.5.3", | 
					    "mini-css-extract-plugin": "2.7.6", | 
				
			||||
        "json5": "2.2.3", | 
					    "nodemon": "3.0.1", | 
				
			||||
        "mini-css-extract-plugin": "2.7.6", | 
					    "postcss": "8.4.31", | 
				
			||||
        "nodemon": "3.0.1", | 
					    "postcss-import": "15.1.0", | 
				
			||||
        "postcss": "8.4.31", | 
					    "postcss-loader": "7.3.3", | 
				
			||||
        "postcss-import": "15.1.0", | 
					    "postcss-preset-env": "9.2.0", | 
				
			||||
        "postcss-loader": "7.3.3", | 
					    "prettier": "3.0.3", | 
				
			||||
        "postcss-preset-env": "9.2.0", | 
					    "sass": "1.69.5", | 
				
			||||
        "prettier": "3.0.3", | 
					    "sass-loader": "13.3.2", | 
				
			||||
        "sass": "1.69.5", | 
					    "typescript": "5.2.2", | 
				
			||||
        "sass-loader": "13.3.2", | 
					    "vue-loader": "17.3.0", | 
				
			||||
        "typescript": "5.2.2", | 
					    "webpack": "5.89.0", | 
				
			||||
        "vue-loader": "17.3.0", | 
					    "webpack-bundle-analyzer": "4.9.1", | 
				
			||||
        "webpack": "5.89.0", | 
					    "webpack-cli": "5.1.4", | 
				
			||||
        "webpack-bundle-analyzer": "4.9.1", | 
					    "webpack-dev-server": "4.15.1", | 
				
			||||
        "webpack-cli": "5.1.4", | 
					    "webpack-merge": "5.10.0" | 
				
			||||
        "webpack-dev-server": "4.15.1", | 
					  }, | 
				
			||||
        "webpack-merge": "5.10.0" | 
					  "dependencies": { | 
				
			||||
    }, | 
					    "@quasar/extras": "1.16.7", | 
				
			||||
    "dependencies": { | 
					    "@vueuse/core": "10.3.0", | 
				
			||||
        "@quasar/extras": "1.16.7", | 
					    "axios": "1.5.1", | 
				
			||||
        "@vueuse/core": "10.3.0", | 
					    "dayjs": "1.11.10", | 
				
			||||
        "axios": "1.5.1", | 
					    "echarts": "5.4.1", | 
				
			||||
        "dayjs": "1.11.10", | 
					    "exceljs": "4.3.0", | 
				
			||||
        "echarts": "5.4.1", | 
					    "file-saver": "2.0.5", | 
				
			||||
        "exceljs": "4.3.0", | 
					    "luckyexcel": "1.0.1", | 
				
			||||
        "file-saver": "2.0.5", | 
					    "mockjs": "1.1.0", | 
				
			||||
        "luckyexcel": "1.0.1", | 
					    "pinia": "2.1.7", | 
				
			||||
        "mockjs": "1.1.0", | 
					    "platform-core": "8.1.37", | 
				
			||||
        "pinia": "2.1.7", | 
					    "quasar": "2.13.0", | 
				
			||||
        "platform-core": "8.1.27", | 
					    "tailwindcss": "3.3.5", | 
				
			||||
        "quasar": "2.13.0", | 
					    "vue": "3.3.7", | 
				
			||||
        "tailwindcss": "3.3.5", | 
					    "vue-dompurify-html": "4.1.4", | 
				
			||||
        "vue": "3.3.7", | 
					    "vue-i18n": "9.6.0", | 
				
			||||
        "vue-dompurify-html": "4.1.4", | 
					    "vue-router": "4.2.5", | 
				
			||||
        "vue-i18n": "9.6.0", | 
					    "@codemirror/autocomplete": "6.11.1", | 
				
			||||
        "vue-router": "4.2.5", | 
					    "@codemirror/commands": "6.3.2", | 
				
			||||
        "@codemirror/autocomplete": "6.11.1", | 
					    "@codemirror/lang-html": "6.4.7", | 
				
			||||
        "@codemirror/commands": "6.3.2", | 
					    "@codemirror/lang-java": "6.0.1", | 
				
			||||
        "@codemirror/lang-html": "6.4.7", | 
					    "@codemirror/lang-javascript": "6.2.1", | 
				
			||||
        "@codemirror/lang-java": "6.0.1", | 
					    "@codemirror/lang-json": "6.0.1", | 
				
			||||
        "@codemirror/lang-javascript": "6.2.1", | 
					    "@codemirror/lang-sql": "6.5.4", | 
				
			||||
        "@codemirror/lang-json": "6.0.1", | 
					    "@codemirror/lang-xml": "6.0.2", | 
				
			||||
        "@codemirror/lang-sql": "6.5.4", | 
					    "@codemirror/language": "6.9.3", | 
				
			||||
        "@codemirror/lang-xml": "6.0.2", | 
					    "@codemirror/search": "6.5.5", | 
				
			||||
        "@codemirror/language": "6.9.3", | 
					    "@codemirror/state": "6.3.3", | 
				
			||||
        "@codemirror/search": "6.5.5", | 
					    "@codemirror/view": "6.22.1", | 
				
			||||
        "@codemirror/state": "6.3.3", | 
					    "codemirror": "6.0.1", | 
				
			||||
        "@codemirror/view": "6.22.1", | 
					    "vue-codemirror6": "1.1.31" | 
				
			||||
        "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 { | 
					dependencies { | 
				
			||||
	api( | 
						api( | 
				
			||||
		"com.oracle.database.jdbc:ojdbc8", | 
							"oracle:oracle:12.2.0.1", | 
				
			||||
		"com.oracle.database.nls:orai18n" | 
					 | 
				
			||||
	) | 
						) | 
				
			||||
} | 
					} | 
				
			||||
@ -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", | 
					  "name": "io.sc.platform.lcdp.frontend", | 
				
			||||
    "version": "8.1.11", | 
					  "version": "8.1.12", | 
				
			||||
    "description": "", | 
					  "description": "", | 
				
			||||
    "private": false, | 
					  "private": false, | 
				
			||||
    "keywords": [ | 
					  "keywords": [], | 
				
			||||
         | 
					  "author": "", | 
				
			||||
    ], | 
					  "license": "ISC", | 
				
			||||
    "author": "", | 
					  "scripts": { | 
				
			||||
    "license": "ISC", | 
					    "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
				
			||||
    "scripts": { | 
					    "dev": "nodemon", | 
				
			||||
        "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml", | 
					    "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			||||
        "dev": "nodemon", | 
					    "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			||||
        "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
					    "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			||||
        "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
					    "sync": "platform sync" | 
				
			||||
        "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
					  }, | 
				
			||||
        "sync": "platform sync" | 
					  "engines": { | 
				
			||||
    }, | 
					    "node": ">=18", | 
				
			||||
    "engines": { | 
					    "pnpm": ">=7" | 
				
			||||
        "node": ">=18", | 
					  }, | 
				
			||||
        "pnpm": ">=7" | 
					  "publishConfig": { | 
				
			||||
    }, | 
					    "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			||||
    "publishConfig": { | 
					    "access": "public" | 
				
			||||
        "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
					  }, | 
				
			||||
        "access": "public" | 
					  "devDependencies": { | 
				
			||||
    }, | 
					    "@babel/core": "7.23.2", | 
				
			||||
    "devDependencies": { | 
					    "@babel/preset-env": "7.23.2", | 
				
			||||
        "@babel/core": "7.23.2", | 
					    "@babel/preset-typescript": "7.23.2", | 
				
			||||
        "@babel/preset-env": "7.23.2", | 
					    "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			||||
        "@babel/preset-typescript": "7.23.2", | 
					    "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			||||
        "@babel/plugin-transform-class-properties": "7.22.5", | 
					    "@quasar/app-webpack": "3.11.2", | 
				
			||||
        "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
					    "@quasar/cli": "2.3.0", | 
				
			||||
        "@quasar/app-webpack": "3.11.2", | 
					    "@types/mockjs": "1.0.9", | 
				
			||||
        "@quasar/cli": "2.3.0", | 
					    "@types/node": "20.8.9", | 
				
			||||
        "@types/mockjs": "1.0.9", | 
					    "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			||||
        "@types/node": "20.8.9", | 
					    "@typescript-eslint/parser": "6.9.0", | 
				
			||||
        "@typescript-eslint/eslint-plugin": "6.9.0", | 
					    "@vue/compiler-sfc": "3.3.7", | 
				
			||||
        "@typescript-eslint/parser": "6.9.0", | 
					    "@webpack-cli/serve": "2.0.5", | 
				
			||||
        "@vue/compiler-sfc": "3.3.7", | 
					    "autoprefixer": "10.4.16", | 
				
			||||
        "@webpack-cli/serve": "2.0.5", | 
					    "babel-loader": "9.1.3", | 
				
			||||
        "autoprefixer": "10.4.16", | 
					    "clean-webpack-plugin": "4.0.0", | 
				
			||||
        "babel-loader": "9.1.3", | 
					    "copy-webpack-plugin": "11.0.0", | 
				
			||||
        "clean-webpack-plugin": "4.0.0", | 
					    "cross-env": "7.0.3", | 
				
			||||
        "copy-webpack-plugin": "11.0.0", | 
					    "css-loader": "6.8.1", | 
				
			||||
        "cross-env": "7.0.3", | 
					    "eslint": "8.52.0", | 
				
			||||
        "css-loader": "6.8.1", | 
					    "eslint-config-prettier": "9.0.0", | 
				
			||||
        "eslint": "8.52.0", | 
					    "eslint-plugin-prettier": "5.0.1", | 
				
			||||
        "eslint-config-prettier": "9.0.0", | 
					    "eslint-plugin-vue": "9.18.0", | 
				
			||||
        "eslint-plugin-prettier": "5.0.1", | 
					    "eslint-webpack-plugin": "4.0.1", | 
				
			||||
        "eslint-plugin-vue": "9.18.0", | 
					    "html-webpack-plugin": "5.5.3", | 
				
			||||
        "eslint-webpack-plugin": "4.0.1", | 
					    "json5": "2.2.3", | 
				
			||||
        "html-webpack-plugin": "5.5.3", | 
					    "mini-css-extract-plugin": "2.7.6", | 
				
			||||
        "json5": "2.2.3", | 
					    "nodemon": "3.0.1", | 
				
			||||
        "mini-css-extract-plugin": "2.7.6", | 
					    "postcss": "8.4.31", | 
				
			||||
        "nodemon": "3.0.1", | 
					    "postcss-import": "15.1.0", | 
				
			||||
        "postcss": "8.4.31", | 
					    "postcss-loader": "7.3.3", | 
				
			||||
        "postcss-import": "15.1.0", | 
					    "postcss-preset-env": "9.2.0", | 
				
			||||
        "postcss-loader": "7.3.3", | 
					    "prettier": "3.0.3", | 
				
			||||
        "postcss-preset-env": "9.2.0", | 
					    "sass": "1.69.5", | 
				
			||||
        "prettier": "3.0.3", | 
					    "sass-loader": "13.3.2", | 
				
			||||
        "sass": "1.69.5", | 
					    "typescript": "5.2.2", | 
				
			||||
        "sass-loader": "13.3.2", | 
					    "vue-loader": "17.3.0", | 
				
			||||
        "typescript": "5.2.2", | 
					    "webpack": "5.89.0", | 
				
			||||
        "vue-loader": "17.3.0", | 
					    "webpack-bundle-analyzer": "4.9.1", | 
				
			||||
        "webpack": "5.89.0", | 
					    "webpack-cli": "5.1.4", | 
				
			||||
        "webpack-bundle-analyzer": "4.9.1", | 
					    "webpack-dev-server": "4.15.1", | 
				
			||||
        "webpack-cli": "5.1.4", | 
					    "webpack-merge": "5.10.0" | 
				
			||||
        "webpack-dev-server": "4.15.1", | 
					  }, | 
				
			||||
        "webpack-merge": "5.10.0" | 
					  "dependencies": { | 
				
			||||
    }, | 
					    "@codemirror/autocomplete": "6.11.1", | 
				
			||||
    "dependencies": { | 
					    "@codemirror/commands": "6.3.2", | 
				
			||||
        "@codemirror/autocomplete": "6.11.1", | 
					    "@codemirror/lang-html": "6.4.7", | 
				
			||||
        "@codemirror/commands": "6.3.2", | 
					    "@codemirror/lang-java": "6.0.1", | 
				
			||||
        "@codemirror/lang-html": "6.4.7", | 
					    "@codemirror/lang-javascript": "6.2.1", | 
				
			||||
        "@codemirror/lang-java": "6.0.1", | 
					    "@codemirror/lang-json": "6.0.1", | 
				
			||||
        "@codemirror/lang-javascript": "6.2.1", | 
					    "@codemirror/lang-sql": "6.5.4", | 
				
			||||
        "@codemirror/lang-json": "6.0.1", | 
					    "@codemirror/lang-xml": "6.0.2", | 
				
			||||
        "@codemirror/lang-sql": "6.5.4", | 
					    "@codemirror/language": "6.9.3", | 
				
			||||
        "@codemirror/lang-xml": "6.0.2", | 
					    "@codemirror/search": "6.5.5", | 
				
			||||
        "@codemirror/language": "6.9.3", | 
					    "@codemirror/state": "6.3.3", | 
				
			||||
        "@codemirror/search": "6.5.5", | 
					    "@codemirror/view": "6.22.1", | 
				
			||||
        "@codemirror/state": "6.3.3", | 
					    "@quasar/extras": "1.16.7", | 
				
			||||
        "@codemirror/view": "6.22.1", | 
					    "@vueuse/core": "10.3.0", | 
				
			||||
        "@quasar/extras": "1.16.7", | 
					    "axios": "1.5.1", | 
				
			||||
        "@vueuse/core": "10.3.0", | 
					    "codemirror": "6.0.1", | 
				
			||||
        "axios": "1.5.1", | 
					    "dayjs": "1.11.10", | 
				
			||||
        "codemirror": "6.0.1", | 
					    "echarts": "5.4.1", | 
				
			||||
        "dayjs": "1.11.10", | 
					    "exceljs": "4.3.0", | 
				
			||||
        "echarts": "5.4.1", | 
					    "file-saver": "2.0.5", | 
				
			||||
        "exceljs": "4.3.0", | 
					    "luckyexcel": "1.0.1", | 
				
			||||
        "file-saver": "2.0.5", | 
					    "mockjs": "1.1.0", | 
				
			||||
        "luckyexcel": "1.0.1", | 
					    "pinia": "2.1.7", | 
				
			||||
        "mockjs": "1.1.0", | 
					    "platform-core": "8.1.37", | 
				
			||||
        "pinia": "2.1.7", | 
					    "quasar": "2.13.0", | 
				
			||||
        "platform-core": "8.1.27", | 
					    "tailwindcss": "3.3.5", | 
				
			||||
        "quasar": "2.13.0", | 
					    "vue": "3.3.7", | 
				
			||||
        "tailwindcss": "3.3.5", | 
					    "vue-dompurify-html": "4.1.4", | 
				
			||||
        "vue": "3.3.7", | 
					    "vue-i18n": "9.6.0", | 
				
			||||
        "vue-dompurify-html": "4.1.4", | 
					    "vue-router": "4.2.5", | 
				
			||||
        "vue-i18n": "9.6.0", | 
					    "vue-codemirror6": "1.1.31" | 
				
			||||
        "vue-router": "4.2.5", | 
					  } | 
				
			||||
        "vue-codemirror6": "1.1.31" | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
} | 
					} | 
				
			||||
@ -1,104 +1,102 @@ | 
				
			|||||
{ | 
					{ | 
				
			||||
    "name": "io.sc.platform.mvc.frontend", | 
					  "name": "io.sc.platform.mvc.frontend", | 
				
			||||
    "version": "8.1.11", | 
					  "version": "8.1.12", | 
				
			||||
    "description": "", | 
					  "description": "", | 
				
			||||
    "private": false, | 
					  "private": false, | 
				
			||||
    "keywords": [ | 
					  "keywords": [], | 
				
			||||
         | 
					  "author": "", | 
				
			||||
    ], | 
					  "license": "ISC", | 
				
			||||
    "author": "", | 
					  "scripts": { | 
				
			||||
    "license": "ISC", | 
					    "dev": "nodemon", | 
				
			||||
    "scripts": { | 
					    "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
				
			||||
        "dev": "nodemon", | 
					    "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
				
			||||
        "serve": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack serve --config webpack.env.serve.cjs", | 
					    "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
				
			||||
        "build": "node ./util-components-generator.cjs && cross-env NODE_ENV=development  webpack       --config webpack.env.build.cjs", | 
					    "sync": "platform sync", | 
				
			||||
        "prod": "node ./util-components-generator.cjs && cross-env  NODE_ENV=production   webpack       --config webpack.env.prod.cjs", | 
					    "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml" | 
				
			||||
        "sync": "platform sync", | 
					  }, | 
				
			||||
        "clean": "rm -rf ./node_modules && rm -rf pnpm-lock.yaml" | 
					  "engines": { | 
				
			||||
    }, | 
					    "node": ">=18", | 
				
			||||
    "engines": { | 
					    "pnpm": ">=7" | 
				
			||||
        "node": ">=18", | 
					  }, | 
				
			||||
        "pnpm": ">=7" | 
					  "publishConfig": { | 
				
			||||
    }, | 
					    "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
				
			||||
    "publishConfig": { | 
					    "access": "public" | 
				
			||||
        "registry": "http://nexus.sc.io:8000/repository/npm-releases/", | 
					  }, | 
				
			||||
        "access": "public" | 
					  "devDependencies": { | 
				
			||||
    }, | 
					    "@babel/core": "7.23.2", | 
				
			||||
    "devDependencies": { | 
					    "@babel/preset-env": "7.23.2", | 
				
			||||
        "@babel/core": "7.23.2", | 
					    "@babel/preset-typescript": "7.23.2", | 
				
			||||
        "@babel/preset-env": "7.23.2", | 
					    "@babel/plugin-transform-class-properties": "7.22.5", | 
				
			||||
        "@babel/preset-typescript": "7.23.2", | 
					    "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
				
			||||
        "@babel/plugin-transform-class-properties": "7.22.5", | 
					    "@quasar/app-webpack": "3.11.2", | 
				
			||||
        "@babel/plugin-transform-object-rest-spread": "7.22.15", | 
					    "@quasar/cli": "2.3.0", | 
				
			||||
        "@quasar/app-webpack": "3.11.2", | 
					    "@types/mockjs": "1.0.9", | 
				
			||||
        "@quasar/cli": "2.3.0", | 
					    "@types/node": "20.8.9", | 
				
			||||
        "@types/mockjs": "1.0.9", | 
					    "@typescript-eslint/eslint-plugin": "6.9.0", | 
				
			||||
        "@types/node": "20.8.9", | 
					    "@typescript-eslint/parser": "6.9.0", | 
				
			||||
        "@typescript-eslint/eslint-plugin": "6.9.0", | 
					    "@vue/compiler-sfc": "3.3.7", | 
				
			||||
        "@typescript-eslint/parser": "6.9.0", | 
					    "@webpack-cli/serve": "2.0.5", | 
				
			||||
        "@vue/compiler-sfc": "3.3.7", | 
					    "autoprefixer": "10.4.16", | 
				
			||||
        "@webpack-cli/serve": "2.0.5", | 
					    "babel-loader": "9.1.3", | 
				
			||||
        "autoprefixer": "10.4.16", | 
					    "clean-webpack-plugin": "4.0.0", | 
				
			||||
        "babel-loader": "9.1.3", | 
					    "copy-webpack-plugin": "11.0.0", | 
				
			||||
        "clean-webpack-plugin": "4.0.0", | 
					    "cross-env": "7.0.3", | 
				
			||||
        "copy-webpack-plugin": "11.0.0", | 
					    "css-loader": "6.8.1", | 
				
			||||
        "cross-env": "7.0.3", | 
					    "eslint": "8.52.0", | 
				
			||||
        "css-loader": "6.8.1", | 
					    "eslint-config-prettier": "9.0.0", | 
				
			||||
        "eslint": "8.52.0", | 
					    "eslint-plugin-prettier": "5.0.1", | 
				
			||||
        "eslint-config-prettier": "9.0.0", | 
					    "eslint-plugin-vue": "9.18.0", | 
				
			||||
        "eslint-plugin-prettier": "5.0.1", | 
					    "eslint-webpack-plugin": "4.0.1", | 
				
			||||
        "eslint-plugin-vue": "9.18.0", | 
					    "html-webpack-plugin": "5.5.3", | 
				
			||||
        "eslint-webpack-plugin": "4.0.1", | 
					    "json5": "2.2.3", | 
				
			||||
        "html-webpack-plugin": "5.5.3", | 
					    "mini-css-extract-plugin": "2.7.6", | 
				
			||||
        "json5": "2.2.3", | 
					    "nodemon": "3.0.1", | 
				
			||||
        "mini-css-extract-plugin": "2.7.6", | 
					    "postcss": "8.4.31", | 
				
			||||
        "nodemon": "3.0.1", | 
					    "postcss-import": "15.1.0", | 
				
			||||
        "postcss": "8.4.31", | 
					    "postcss-loader": "7.3.3", | 
				
			||||
        "postcss-import": "15.1.0", | 
					    "postcss-preset-env": "9.2.0", | 
				
			||||
        "postcss-loader": "7.3.3", | 
					    "prettier": "3.0.3", | 
				
			||||
        "postcss-preset-env": "9.2.0", | 
					    "sass": "1.69.5", | 
				
			||||
        "prettier": "3.0.3", | 
					    "sass-loader": "13.3.2", | 
				
			||||
        "sass": "1.69.5", | 
					    "typescript": "5.2.2", | 
				
			||||
        "sass-loader": "13.3.2", | 
					    "vue-loader": "17.3.0", | 
				
			||||
        "typescript": "5.2.2", | 
					    "webpack": "5.89.0", | 
				
			||||
        "vue-loader": "17.3.0", | 
					    "webpack-bundle-analyzer": "4.9.1", | 
				
			||||
        "webpack": "5.89.0", | 
					    "webpack-cli": "5.1.4", | 
				
			||||
        "webpack-bundle-analyzer": "4.9.1", | 
					    "webpack-dev-server": "4.15.1", | 
				
			||||
        "webpack-cli": "5.1.4", | 
					    "webpack-merge": "5.10.0" | 
				
			||||
        "webpack-dev-server": "4.15.1", | 
					  }, | 
				
			||||
        "webpack-merge": "5.10.0" | 
					  "dependencies": { | 
				
			||||
    }, | 
					    "@quasar/extras": "1.16.7", | 
				
			||||
    "dependencies": { | 
					    "@vueuse/core": "10.3.0", | 
				
			||||
        "@quasar/extras": "1.16.7", | 
					    "axios": "1.5.1", | 
				
			||||
        "@vueuse/core": "10.3.0", | 
					    "dayjs": "1.11.10", | 
				
			||||
        "axios": "1.5.1", | 
					    "echarts": "5.4.1", | 
				
			||||
        "dayjs": "1.11.10", | 
					    "exceljs": "4.3.0", | 
				
			||||
        "echarts": "5.4.1", | 
					    "file-saver": "2.0.5", | 
				
			||||
        "exceljs": "4.3.0", | 
					    "luckyexcel": "1.0.1", | 
				
			||||
        "file-saver": "2.0.5", | 
					    "mockjs": "1.1.0", | 
				
			||||
        "luckyexcel": "1.0.1", | 
					    "pinia": "2.1.7", | 
				
			||||
        "mockjs": "1.1.0", | 
					    "platform-core": "8.1.37", | 
				
			||||
        "pinia": "2.1.7", | 
					    "quasar": "2.13.0", | 
				
			||||
        "platform-core": "8.1.27", | 
					    "tailwindcss": "3.3.5", | 
				
			||||
        "quasar": "2.13.0", | 
					    "vue": "3.3.7", | 
				
			||||
        "tailwindcss": "3.3.5", | 
					    "vue-dompurify-html": "4.1.4", | 
				
			||||
        "vue": "3.3.7", | 
					    "vue-i18n": "9.6.0", | 
				
			||||
        "vue-dompurify-html": "4.1.4", | 
					    "vue-router": "4.2.5", | 
				
			||||
        "vue-i18n": "9.6.0", | 
					    "@codemirror/autocomplete": "6.11.1", | 
				
			||||
        "vue-router": "4.2.5", | 
					    "@codemirror/commands": "6.3.2", | 
				
			||||
        "@codemirror/autocomplete": "6.11.1", | 
					    "@codemirror/lang-html": "6.4.7", | 
				
			||||
        "@codemirror/commands": "6.3.2", | 
					    "@codemirror/lang-java": "6.0.1", | 
				
			||||
        "@codemirror/lang-html": "6.4.7", | 
					    "@codemirror/lang-javascript": "6.2.1", | 
				
			||||
        "@codemirror/lang-java": "6.0.1", | 
					    "@codemirror/lang-json": "6.0.1", | 
				
			||||
        "@codemirror/lang-javascript": "6.2.1", | 
					    "@codemirror/lang-sql": "6.5.4", | 
				
			||||
        "@codemirror/lang-json": "6.0.1", | 
					    "@codemirror/lang-xml": "6.0.2", | 
				
			||||
        "@codemirror/lang-sql": "6.5.4", | 
					    "@codemirror/language": "6.9.3", | 
				
			||||
        "@codemirror/lang-xml": "6.0.2", | 
					    "@codemirror/search": "6.5.5", | 
				
			||||
        "@codemirror/language": "6.9.3", | 
					    "@codemirror/state": "6.3.3", | 
				
			||||
        "@codemirror/search": "6.5.5", | 
					    "@codemirror/view": "6.22.1", | 
				
			||||
        "@codemirror/state": "6.3.3", | 
					    "codemirror": "6.0.1", | 
				
			||||
        "@codemirror/view": "6.22.1", | 
					    "vue-codemirror6": "1.1.31" | 
				
			||||
        "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}, | 
						{"id":"parameter.system","order":0}, | 
				
			||||
		/*系统/首页 Thymeleaf 视图模板*/ | 
							/*系统/首页路由*/ | 
				
			||||
		{ | 
							{ | 
				
			||||
			"id"			: "parameter.system.indexPageTemplate", | 
								"id"			: "parameter.system.homePage", | 
				
			||||
			"parentId"		: "parameter.system", | 
								"parentId"		: "parameter.system", | 
				
			||||
			"code"			: "parameter.system.indexPageTemplate", | 
								"code"			: "parameter.system.homePage", | 
				
			||||
			"defaultValue"	: "io.sc.platform.mvc.frontend.html", | 
								"defaultValue"	: "/home", | 
				
			||||
			"order"			: 100 | 
								"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