You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							911 lines
						
					
					
						
							39 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							911 lines
						
					
					
						
							39 KiB
						
					
					
				| import org.gradle.api.artifacts.DependencyResolveDetails | |
| 
 | |
| import java.util.zip.GZIPOutputStream | |
| 
 | |
| apply from: "build-version.gradle" | |
| 
 | |
| // 判断项目是否是普通前端项目 | |
| def isFrontendProject(currentDir){ | |
|     return file(currentDir.getAbsolutePath() + '/package.json').exists() | |
|             && !file(currentDir.getAbsolutePath() + '/webpack.env.lib.cjs').exists(); | |
| } | |
| 
 | |
| /*********************************************************************** | |
|  * gradle 插件 | |
|  **********************************************************************/ | |
| buildscript { | |
|     repositories { | |
|         maven { | |
|             allowInsecureProtocol = true | |
|             url "${repository_url}" | |
|         } | |
|     } | |
|     dependencies { | |
|         classpath "com.gradleup.shadow:shadow-gradle-plugin:${shadow_gradle_plugin_version}" | |
|         classpath "org.springframework.boot:org.springframework.boot.gradle.plugin:${spring_boot_version}" | |
|         //classpath "io.sc:io.sc.platform.gradle:${platform_plugin_version}" | |
|         classpath "org.asciidoctor:asciidoctor-gradle-jvm:${asciidoctor_version}" | |
|         classpath "com.google.cloud.tools:jib-gradle-plugin:${jib_version}" | |
|     } | |
| } | |
| 
 | |
| /*********************************************************************** | |
|  * 所有项目(根项目及其子项目)都应用的插件 | |
|  **********************************************************************/ | |
| allprojects { | |
|     apply plugin: 'idea' | |
|     //apply plugin: 'io.sc.platform.gradle' | |
| } | |
| 
 | |
| /*********************************************************************** | |
|  * 所有子项目应用的插件 | |
|  **********************************************************************/ | |
| subprojects { | |
|     apply plugin: 'java' | |
|     apply plugin: 'java-library' | |
|     apply plugin: 'eclipse' | |
|     apply plugin: 'maven-publish' | |
|     apply plugin: 'org.springframework.boot' | |
|     apply plugin: 'io.spring.dependency-management' | |
|     apply plugin: 'org.asciidoctor.jvm.convert' | |
| 
 | |
| 	configurations.all { | |
| 	    //设置 gradle 拉取依赖包的缓存策略为不进行缓存,可保证每次拉取最新的依赖包 | |
| 	    //resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'     //动态版本: 1.1.+ | |
| 	    //resolutionStrategy.cacheChangingModulesFor 0, 'seconds'     //静态版本: 1.1.2 | |
| 
 | |
|         //排除不需要的外部依赖 | |
| //	    exclude group: "org.apache.logging.log4j",  module: "log4j-api" | |
| //      exclude group: "org.apache.logging.log4j",  module: "log4j-to-slf4j" | |
| //      exclude group: "org.slf4j",                 module: "slf4j-jdk14" | |
|         exclude group: "org.slf4j",                 module: "slf4j-nop" | |
|         //exclude group: "com.mysql",                 module: "mysql-connector-j" | |
| 
 | |
|         if(PlatformDependencyVersions!=null && PlatformDependencyVersions.size()>0) { | |
|             resolutionStrategy.eachDependency { DependencyResolveDetails detail -> | |
|                 def requested = detail.requested; | |
|                 def groupAndName = requested.group + ":" + requested.name; | |
|                 String version = PlatformDependencyVersions[groupAndName]; | |
|                 if (version != null) { | |
|                     detail.useVersion(version); | |
|                 } | |
|             } | |
|         } | |
| 	} | |
| 
 | |
| 	dependencyManagement { | |
| 	    resolutionStrategy { | |
| 	        //设置 gradle 拉取依赖包的缓存策略为不进行缓存,可保证每次拉取最新的依赖包 | |
| 	        //cacheDynamicVersionsFor 0, 'seconds'                    //动态版本: 1.1.+ | |
|             //cacheChangingModulesFor 0, 'seconds'                    //静态版本: 1.1.2 | |
|         } | |
| 		imports { | |
| 			//mavenBom "org.springframework.cloud:spring-cloud-dependencies:${spring_cloud_version}" | |
|             mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${spring_cloud_alibaba_version}" | |
|             mavenBom "org.springframework.statemachine:spring-statemachine-bom:${spring_statemachine_version}" | |
| 		} | |
| 	} | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * 配置构建时所需依赖的仓库 url | |
|      * 将仓库 url 都定位到 ${repository_url} 指定的本地私有仓库地址 | |
|      *----------------------------------------------------------------*/ | |
| 	repositories { | |
| 		all { ArtifactRepository repo -> | |
|             if(repo instanceof MavenArtifactRepository){ | |
|                 def url = repo.url.toString() | |
|                 if ( | |
|                 	   url.startsWith('https://repo1.maven.org/maven2') | |
|                 	|| url.startsWith('https://jcenter.bintray.com/') | |
|                 	|| url.startsWith('https://maven.aliyun.com') | |
|                 ) { | |
|                     remove repo | |
|                 } | |
|             } | |
|         } | |
| 		maven { | |
| 			allowInsecureProtocol = true | |
| 			url "${repository_url}" | |
| 		} | |
| 	} | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * java 编译时选项 | |
|      *----------------------------------------------------------------*/ | |
|     sourceCompatibility ="${java_version}" | |
| 	targetCompatibility ="${java_version}" | |
| 	compileJava.options.encoding ="${java_encoding}" | |
| 	compileTestJava.options.encoding ="${java_encoding}" | |
| 
 | |
| 	tasks.withType(JavaCompile) { | |
|     	options.compilerArgs += ["-Xlint:deprecation","-Xlint:unchecked"] | |
| 	} | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * 配置项目基本信息 | |
|      *----------------------------------------------------------------*/ | |
| 	group ="${platform_group}" | |
| 	version ="${platform_version}" | |
| 
 | |
|     if(file('package.json').exists()){ | |
|         mkdir 'java-src/main/java'; | |
|         mkdir 'java-src/main/resources'; | |
|         mkdir 'dist'; | |
|         sourceSets.main.java.srcDir 'java-src/main/java' | |
|         sourceSets.main.resources.srcDir 'java-src/main/resources' | |
|     	sourceSets.main.resources.srcDir 'dist' | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 源代码打包配置 | |
|      *----------------------------------------------------------------*/ | |
|     task sourcesJar (type : Jar) { | |
|         from sourceSets.main.allJava | |
|         archiveClassifier = 'sources' | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * Java 文档打包配置 | |
|      *----------------------------------------------------------------*/ | |
|     javadoc { | |
|         options.encoding = 'UTF-8' | |
|         // 为了能够尽量规范 java doc 文档编写, 指定如果 java doc 中有错误,会报错,并且无法发布到仓库中 | |
|         failOnError=false | |
|     } | |
| 
 | |
|     task javadocJar (type: Jar) { | |
|         from javadoc | |
|         archiveClassifier = 'javadoc' | |
|     } | |
| 
 | |
|     clean { | |
|         delete 'bin'										//删除 eclipse 编译的 bin 目录 | |
|         delete 'build'										//删除 gradle 构建目录 | |
|         delete 'dist'                                       //删除前端打包后的目录 | |
|         delete 'node_modules'                               //删除前端 node_modules 目录 | |
|         delete 'pnpm-lock.yaml'                             //删除前端 pnpm 文件 | |
|         delete 'package-lock.json'                          //删除前端 npm 文件 | |
|     } | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * 配置 eclipse 插件 | |
|      *----------------------------------------------------------------*/ | |
|     eclipse{ | |
| 		jdt{ | |
| 			sourceCompatibility ="${java_version}" | |
| 			targetCompatibility ="${java_version}" | |
| 		} | |
| 	} | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * springboot 插件配置 | |
|      *----------------------------------------------------------------*/ | |
|     jar { | |
|     	//可以生成普通的 jar | |
| 		enabled = true | |
| 		archiveClassifier.set("") | |
| 		manifest { | |
|             attributes 	'Manifest-Version'		: '1.0', | |
|                         'Implementation-Title'	: name, | |
|                         'Implementation-Vendor'	: group, | |
|                         'Implementation-Version': archiveVersion | |
|         } | |
|     } | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * asciidoctor 插件配置,用于生成 asciidoc 文档,用于打包到 jar 中 | |
|      *----------------------------------------------------------------*/ | |
| 	asciidoctor { | |
| 		baseDirFollowsSourceDir() | |
| 		outputs.upToDateWhen { true } | |
| 
 | |
| 		logDocuments = true | |
|     	sourceDir = file('asciidoc') | |
|     	sources { | |
|     		include '*.adoc' | |
|     	} | |
|         outputDir = file("dist/help/" + project.name) | |
|         resources { | |
|             from(sourceDir) { | |
|                 include 'resources/**' | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     asciidoctorj { | |
| 	    modules { | |
| 	       diagram.use() | |
| 	    } | |
| 	} | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 自定义任务,用于生成 asciidoc 文档到 web 服务器,以便实时查看效果 | |
|      *----------------------------------------------------------------*/ | |
|     task doc(type: org.asciidoctor.gradle.jvm.AsciidoctorTask){ | |
|     	baseDirFollowsSourceDir() | |
| 		outputs.upToDateWhen { true } | |
| 
 | |
| 		logDocuments = true | |
|     	sourceDir = file('asciidoc') | |
|     	sources { | |
|     		include '*.adoc' | |
|     	} | |
|     	outputDir = file("$asciidoc_deploy_dir" + project.name) | |
| 
 | |
|         // 拷贝 asciidoc 自定义资源 | |
|         // 设置方式: 通过命令行 -D 传入目标环境参数 | |
|         // gradle doc -DdocResource=true     # 需要拷贝自定义资源 | |
|         // gradle doc -DdocResource=false    # 不需要拷贝自定义资源 | |
|         def docResource =System.getProperty("docResource")?:"true"; | |
|         if(docResource=="true"){ | |
|             resources { | |
|                 from(sourceDir) { | |
|                     include 'resources/**' | |
|                 } | |
|             } | |
|         } | |
| 	} | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 资源处理前执行 asciidoctor | |
|      *----------------------------------------------------------------*/ | |
|     processResources { | |
|     	dependsOn asciidoctor | |
|     	doLast{ | |
|     		//打包时移除 jrebel 相关的文件 | |
|     		delete "$buildDir/resources/main/rebel.xml" | |
|     	} | |
| 	} | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 用于自动生成 jrebel.xml 文件的自定义任务(eclipse) | |
|      *----------------------------------------------------------------*/ | |
| 	task jrebelEclipse() {} | |
| 	tasks.jrebelEclipse.doLast { | |
| 		File resourcesFile =file('src/main/resources') | |
| 		if(resourcesFile!=null && resourcesFile.exists()){ | |
| 			File rebelFile = file('src/main/resources/rebel.xml') | |
| 			rebelFile.withWriter('UTF-8') { writer -> | |
| 				writer.write('<?xml version="1.0" encoding="UTF-8"?>\n'); | |
| 				writer.write('<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd">\n'); | |
| 				writer.write('\t<classpath>\n'); | |
| 				if(file(project.name + '/src/main').exists()){ | |
| 					writer.write('\t\t<dir name="' + project.projectDir + '/bin/main"/>\n'); | |
| 				} | |
| 				if(file(project.name + '/src/generated').exists()){ | |
| 					writer.write('\t\t<dir name="' + project.projectDir + '/bin/generated"/>\n'); | |
| 				} | |
| 				writer.write('\t</classpath>\n'); | |
| 				writer.write('</application>'); | |
| 			} | |
| 		} | |
| 	} | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 用于自动生成 jrebel.xml 文件的自定义任务(idea) | |
|      *----------------------------------------------------------------*/ | |
| 	task jrebelIdea() {} | |
| 	tasks.jrebelIdea.doLast { | |
|         if(isFrontendProject(file('.'))) { | |
|             File resourcesFile = file('java-src/main/resources') | |
|             if (resourcesFile != null && resourcesFile.exists()) { | |
|                 File rebelFile = file('java-src/main/resources/rebel.xml') | |
|                 rebelFile.withWriter('UTF-8') { writer -> | |
|                     writer.write('<?xml version="1.0" encoding="UTF-8"?>\n'); | |
|                     writer.write('<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd">\n'); | |
|                     writer.write('\t<classpath>\n'); | |
|                     if (file(project.name + '/java-src/main').exists()) { | |
|                         writer.write('\t\t<dir name="' + project.rootProject.projectDir + '/out/production/' + project.name + '"/>\n'); | |
|                     } | |
|                     writer.write('\t</classpath>\n'); | |
|                     writer.write('</application>'); | |
|                 } | |
|             } | |
|         }else { | |
|             File resourcesFile = file('src/main/resources') | |
|             if (resourcesFile != null && resourcesFile.exists()) { | |
|                 File rebelFile = file('src/main/resources/rebel.xml') | |
|                 rebelFile.withWriter('UTF-8') { writer -> | |
|                     writer.write('<?xml version="1.0" encoding="UTF-8"?>\n'); | |
|                     writer.write('<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd">\n'); | |
|                     writer.write('\t<classpath>\n'); | |
|                     if (file(project.name + '/src/main').exists()) { | |
|                         writer.write('\t\t<dir name="' + project.rootProject.projectDir + '/out/production/' + project.name + '"/>\n'); | |
|                     } | |
|                     writer.write('\t</classpath>\n'); | |
|                     writer.write('</application>'); | |
|                 } | |
|             } | |
|         } | |
| 	} | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * maven publish 插件配置 | |
|      *----------------------------------------------------------------*/ | |
|     publishing { | |
|         repositories { | |
|             maven { | |
|             	allowInsecureProtocol = true        //允许采用 http 协议发布 | |
|                 url = version.contains('SNAPSHOT') ? "${repository_snapshot_url}" : "${repository_release_url}" | |
|                 credentials { | |
|                     username = (version.contains('SNAPSHOT') ? "${repository_snapshot_username}" : "${repository_release_username}") | |
|                     password = (version.contains('SNAPSHOT') ? "${repository_snapshot_password}" : "${repository_release_password}") | |
| 				} | |
|             } | |
|         } | |
|         publications{ | |
|             publication(MavenPublication){ | |
|                 from components.java | |
|                 //artifact sourcesJar | |
|                 //artifact javadocJar | |
|                 versionMapping { | |
| 	                usage('java-api') { | |
| 	                    fromResolutionOf('runtimeClasspath') | |
| 	                } | |
| 	                usage('java-runtime') { | |
| 	                    fromResolutionResult() | |
| 	                } | |
| 	            } | |
|             } | |
|         } | |
|     } | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * 更新前端模块的 package.json 文件,同步其中的 name 和 version | |
|      *----------------------------------------------------------------*/ | |
|     task frontendUpdatePackageJson(){} | |
|     tasks.frontendUpdatePackageJson.doFirst { | |
|         if(isFrontendProject(file('.'))) { | |
|             println '开始执行 frontendUpdatePackageJson ......' | |
|         } | |
|     } | |
|     tasks.frontendUpdatePackageJson.doLast { | |
|         if(isFrontendProject(file('.'))){ | |
|             String content =file('package.json').text; | |
|             def packageJson = new groovy.json.JsonSlurper().parseText(content); | |
|             if(packageJson!=null){ | |
|                 println packageJson.dependencies; | |
|                 packageJson.name =project.name; | |
|                 packageJson.version =project.version; | |
|                 packageJson.dependencies['platform-core']=platform_core_frontend_version; | |
|                 def json = groovy.json.JsonOutput.toJson(packageJson); | |
|                 file('package.json').withWriter('UTF-8') { writer -> | |
|                     writer.write(groovy.json.JsonOutput.prettyPrint(json)); | |
|                 } | |
|             } | |
|         } | |
|     } | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * pnpm install | |
|      *----------------------------------------------------------------*/ | |
|     task frontendNpmInstall(type:Exec){ | |
|         if(isFrontendProject(file('.'))){ | |
|             workingDir '.' | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'pnpm', 'install' | |
|             }else{ | |
|                 commandLine 'pnpm', 'install' | |
|             } | |
|         }else{ | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'cd', '.' | |
|             }else{ | |
|                 commandLine 'cd', '.' | |
|             } | |
|         } | |
|     } | |
|     tasks.frontendNpmInstall.doFirst { | |
|         if(isFrontendProject(file('.'))) { | |
|             println '开始执行 pnpm install ......'; | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * pnpm sync | |
|      *----------------------------------------------------------------*/ | |
|     task frontendNpmSync(type:Exec){ | |
|         if(isFrontendProject(file('.')) && !project.name.contains("io.sc.platform.security.frontend")){ | |
|             workingDir '.' | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'pnpm', 'sync' | |
|             }else{ | |
|                 commandLine 'pnpm', 'sync' | |
|             } | |
|         }else{ | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'cd', '.' | |
|             }else{ | |
|                 commandLine 'cd', '.' | |
|             } | |
|         } | |
|     } | |
|     tasks.frontendNpmSync.doFirst { | |
|         if(isFrontendProject(file('.'))) { | |
|             println '开始执行 pnpm sync ......'; | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * pnpm re install | |
|      *----------------------------------------------------------------*/ | |
|     task frontendNpmReInstall(type:Exec){ | |
|         if(isFrontendProject(file('.'))){ | |
|             workingDir '.' | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'pnpm', 'install' | |
|             }else{ | |
|                 commandLine 'pnpm', 'install' | |
|             } | |
|         }else{ | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'cd', '.' | |
|             }else{ | |
|                 commandLine 'cd', '.' | |
|             } | |
|         } | |
|     } | |
|     tasks.frontendNpmReInstall.doFirst { | |
|         if(isFrontendProject(file('.'))) { | |
|             println '开始执行 pnpm re install ......'; | |
|         } | |
|     } | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * pnpm run build | |
|      *----------------------------------------------------------------*/ | |
|     task frontendNpmBuild(type:Exec) { | |
|         if(isFrontendProject(file('.'))){ | |
|             workingDir '.' | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'pnpm', 'run', 'build' | |
|             }else{ | |
|                 commandLine 'pnpm', 'run', 'build' | |
|             } | |
|         }else{ | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'cd', '.' | |
|             }else{ | |
|                 commandLine 'cd', '.' | |
|             } | |
|         } | |
|     } | |
|     tasks.frontendNpmBuild.doFirst { | |
|         if (isFrontendProject(file('.'))) { | |
|             println '开始执行 pnpm run build ......' | |
|         } | |
|     } | |
| 
 | |
| 	/*----------------------------------------------------------------- | |
|      * pnpm run prod | |
|      *----------------------------------------------------------------*/ | |
|     task frontendNpmProd(type:Exec) { | |
|         if(isFrontendProject(file('.'))){ | |
|             workingDir '.' | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'pnpm', 'run', 'prod' | |
|             }else{ | |
|                 commandLine 'pnpm', 'run', 'prod' | |
|             } | |
|         }else{ | |
|             if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ | |
|                 commandLine 'cmd', '/c', 'cd', '.' | |
|             }else{ | |
|                 commandLine 'cd', '.' | |
|             } | |
|         } | |
|     } | |
|     tasks.frontendNpmProd.doFirst { | |
|         if(isFrontendProject(file('.'))){ | |
|             println '开始执行 pnpm run prod ......' | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 将入口前端 dist/public/模块名 目录下 index.html 文件复制到 classpath:/templates/模块名.html | |
|      * 提供给 thymeleaf 作为视图模板使用 | |
|      *----------------------------------------------------------------*/ | |
|     task frontendGenerateThymeleafTemplate {} | |
|     tasks.frontendGenerateThymeleafTemplate.doFirst { | |
|         if(isFrontendProject(file('.'))) { | |
|             println '开始执行 frontendGenerateThymeleafTemplate ......' | |
|             delete "java-src/main/resources/templates" | |
|             mkdir "java-src/main/resources/templates" | |
|         } | |
|     } | |
|     tasks.frontendGenerateThymeleafTemplate.doLast { | |
|         if(isFrontendProject(file('.'))) { | |
|             if(!file("dist/public/${project.name}/index.html").exists()){ | |
|                 return; | |
|             } | |
|             def content = file("dist/public/${project.name}/index.html").text; | |
|             content = content.replace('<script defer src="javascript/main', """<script defer src="${project.name}/javascript/main"""); | |
|             def output = file("java-src/main/resources/templates/${project.name}.html"); | |
|             output.withWriter('utf-8') { writer -> | |
|                 writer.write content; | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 根据前端定义的多语言 json 文件生成后端 properties 文件 | |
|      *----------------------------------------------------------------*/ | |
|     task frontendGenerateI18n {} | |
|     tasks.frontendGenerateI18n.doFirst { | |
|         if(isFrontendProject(file('.'))){ | |
|             println '开始执行 frontendGenerateI18n ......' | |
|             delete 'java-src/main/resources/' + project.name.replace('.', '/') + '/i18n'; | |
|             delete 'java-src/main/resources/META-INF/platform/plugins/messages.json'; | |
| 
 | |
|             mkdir 'java-src/main/resources/' + project.name.replace('.', '/') + '/i18n'; | |
|             mkdir 'java-src/main/resources/META-INF/platform/plugins'; | |
|         } | |
|     } | |
|     tasks.frontendGenerateI18n.doLast { | |
|         if(isFrontendProject(file('.'))){ | |
|             def messagesDir ='java-src/main/resources/' + project.name.replace('.', '/') + '/i18n'; | |
|             def pluginDir ='java-src/main/resources/META-INF/platform/plugins'; | |
|             def jsonDir ='src/i18n'; | |
| 
 | |
|             // 获取所有的多语言消息文件 | |
|             def tree = fileTree(jsonDir) { include '**/*.json' } | |
|             def i18nMessageFileList =new ArrayList<String>(); | |
|             tree.each { File jsonFile -> i18nMessageFileList.add(jsonFile.getName()) } | |
| 
 | |
|             if(i18nMessageFileList.size()>0){ | |
|                 // 生成 java-src/main/resources/META-INF/platform/plugins/messages.json 文件 | |
|                 def content =''; | |
|                 content +='{\n'; | |
|                 content +='    includes:[\n'; | |
|                 content +='        "' + project.name.replace('.','/') + '/i18n/messages"' + '\n'; | |
|                 content +='    ]\n'; | |
|                 content +='}\n'; | |
|                 def output =file(pluginDir + '/messages.json'); | |
|                 output.withWriter('utf-8') { writer -> | |
|                     writer.write content; | |
|                 } | |
|                 // 生成 java-src/main/resources/{project.name}/messages_{locale}.properties | |
|                 for(String fileName : i18nMessageFileList){ | |
|                     def json = new groovy.json.JsonSlurper().parseText(file(jsonDir + '/' + fileName).text); | |
|                     def sb =new StringBuilder(); | |
|                     json.keySet().each { String key -> | |
|                         sb.append(key).append("=").append(groovy.json.StringEscapeUtils.escapeJava(json.get(key))).append("\n"); | |
|                     }; | |
|                     def outputFilePath =messagesDir + '/' + fileName.replace('.json','.properties'); | |
|                     file(outputFilePath).withWriter('utf-8') { writer -> | |
|                         writer.write sb.toString(); | |
|                     } | |
|                 } | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 根据前端定义的菜单 json 文件生成后端插件 json 文件 | |
|      *----------------------------------------------------------------*/ | |
|     task frontendGenerateMenus {} | |
|     tasks.frontendGenerateMenus.doFirst { | |
|         if(isFrontendProject(file('.'))){ | |
|             println '开始执行 frontendGenerateMenus ......' | |
|             delete 'java-src/main/resources/META-INF/platform/plugins/menus.json'; | |
|         } | |
|     } | |
|     tasks.frontendGenerateMenus.doLast { | |
|         if(isFrontendProject(file('.'))) { | |
|             if(!file('src/menus/menus.json').exists()) { | |
|                 return; | |
|             } | |
|             java.nio.file.Files.copy(file('src/menus/menus.json').toPath(), file('java-src/main/resources/META-INF/platform/plugins/menus.json').toPath()); | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 根据前端定义的路由 json 文件生成后端插件 json 文件 | |
|      *----------------------------------------------------------------*/ | |
|     task frontendGenerateRoutes {} | |
|     tasks.frontendGenerateRoutes.doFirst { | |
|         if(isFrontendProject(file('.'))){ | |
|             println '开始执行 frontendGenerateRoutes ......' | |
|             delete 'java-src/main/resources/META-INF/platform/plugins/frontend-routes.json'; | |
|         } | |
|     } | |
|     tasks.frontendGenerateRoutes.doLast { | |
|         if(isFrontendProject(file('.'))) { | |
|             if(!file("src/routes/routes.json").exists()) { | |
|                 return; | |
|             } | |
|             def routes = new groovy.json.JsonSlurper().parseText(file("src/routes/routes.json").text); | |
|             for (def route : routes) { | |
|                 route.module = project.name; | |
|             } | |
|             def json = groovy.json.JsonOutput.toJson(routes); | |
|             def outputFile = file("java-src/main/resources/META-INF/platform/plugins/frontend-routes.json"); | |
|             outputFile.withWriter('UTF-8') { writer -> | |
|                 writer.write(groovy.json.JsonOutput.prettyPrint(json)); | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 为后端生成前端资源清单,以便可通过一键导出成独立的前端系统 | |
|      *----------------------------------------------------------------*/ | |
|     task frontendModule {} | |
|     tasks.frontendModule.doFirst { | |
|         if(isFrontendProject(file('.'))) { | |
|             println '开始执行 frontendModule ......' | |
|             delete 'java-src/main/resources/META-INF/platform/plugins/frontend-module.json' | |
|         } | |
|     } | |
|     tasks.frontendModule.doLast { | |
|         if(isFrontendProject(file('.'))) { | |
|             //components--------------------------------------- | |
|             List<String> components =new ArrayList<String>(); | |
|             if(file("java-src/main/resources/META-INF/platform/plugins/frontend-routes.json").exists()) { | |
|                 def routes = new groovy.json.JsonSlurper().parseText(file("java-src/main/resources/META-INF/platform/plugins/frontend-routes.json").text); | |
|                 for (def route : routes) { | |
|                     components.add(route.component); | |
|                 } | |
|             } | |
| 
 | |
|             //resources---------------------------------------- | |
|             List<String> resources = new ArrayList<String>(); | |
|             def dirPath = file('dist').absolutePath; | |
|             if(project.name.contains('io.sc.platform.mvc.frontend')){ | |
|                 def tree = fileTree('dist') { | |
|                     include '**/*.*' | |
|                     exclude "public/${project.name}/configure.js" | |
|                     exclude "public/${project.name}/favicon.svg" | |
|                     exclude "public/${project.name}/index.html" | |
|                     exclude "public/${project.name}/login-bg.jpg" | |
|                     exclude "public/${project.name}/logo.svg" | |
|                 } | |
|                 tree.each { File file -> | |
|                     resources.add(file.absolutePath.substring(dirPath.length())); | |
|                 } | |
|             }else{ | |
|                 def tree = fileTree('dist') { | |
|                     include '**/*.*' | |
| //                    exclude '**/webjars/**/*.*' | |
| //                    exclude "public/${project.name}/configure.js" | |
| //                    exclude "public/${project.name}/favicon.svg" | |
| //                    exclude "public/${project.name}/index.html" | |
| //                    exclude "public/${project.name}/login-bg.jpg" | |
| //                    exclude "public/${project.name}/logo.svg" | |
|                 } | |
|                 tree.each { File file -> | |
|                     resources.add(file.absolutePath.substring(dirPath.length())); | |
|                 } | |
|             } | |
| 
 | |
| 
 | |
|             //all-in-one------------------------------------ | |
|             Map<String,Object> allInOne =new LinkedHashMap<>(); | |
|             allInOne.put("name",project.name); | |
|             allInOne.put("components",components); | |
|             allInOne.put("resources",resources); | |
| 
 | |
|             def json = groovy.json.JsonOutput.toJson(allInOne); | |
|             def outputFile =file('java-src/main/resources/META-INF/platform/plugins/frontend-module.json'); | |
|             outputFile.withWriter('UTF-8') { writer -> | |
|                 writer.write(groovy.json.JsonOutput.prettyPrint(json)); | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     /*----------------------------------------------------------------- | |
|      * 打包 jar 之前处理前端资源 | |
|      *----------------------------------------------------------------*/ | |
|     task frontend() {} | |
|     tasks.frontend.doFirst { | |
|         if(isFrontendProject(file('.'))){ | |
|             println '开始执行 frontend ......' | |
|         } | |
|     } | |
| 
 | |
|     // 定义前端构建任务的依赖及执行顺序 | |
|     frontendNpmInstall.dependsOn(frontendUpdatePackageJson) | |
|     frontendNpmSync.dependsOn(frontendNpmInstall) | |
|     frontendNpmReInstall.dependsOn(frontendNpmSync) | |
|     frontendNpmBuild.dependsOn(frontendNpmReInstall) | |
|     frontendNpmProd.dependsOn(frontendNpmReInstall) | |
| 
 | |
|     // 资源处理前进行前端模块的构建 | |
|     // 设置方式: 通过命令行 -D 传入目标环境参数 | |
|     // gradle bootwar -Dfrontend=dev      # 采用 pnpm build 构建前端 | |
|     // gradle bootwar -Dfrontend=prod     # 采用 pnpm prod 构建前端 | |
|     // gradle bootwar -Dfrontend=none     # 不构建前端, 仅生成后端需要的文件 | |
|     def isFrontend =System.getProperty("frontend")?:"prod"; | |
|     if(isFrontend=="dev"){ | |
|         frontendGenerateThymeleafTemplate.dependsOn(frontendNpmBuild); | |
|     }else if(isFrontend=="prod"){ | |
|         frontendGenerateThymeleafTemplate.dependsOn(frontendNpmProd); | |
|     } | |
|     frontendGenerateI18n.dependsOn(frontendGenerateThymeleafTemplate); | |
|     frontendGenerateMenus.dependsOn(frontendGenerateI18n); | |
|     frontendGenerateRoutes.dependsOn(frontendGenerateMenus); | |
|     frontendModule.dependsOn(frontendGenerateRoutes); | |
|     frontend.dependsOn(frontendModule); | |
| 
 | |
|     processResources.dependsOn(frontend) | |
| 
 | |
|     processResources { | |
|         if(isFrontendProject(file('.'))) { | |
|             if(project.name!='io.sc.platform.mvc.frontend'){ | |
|                 exclude("**/${project.name}/*.*"); | |
|                 exclude("**/${project.name}/javascript/codemirror.*"); | |
|                 exclude("**/${project.name}/javascript/echarts.*"); | |
|                 exclude("**/${project.name}/javascript/maxgraph.*"); | |
|                 exclude("**/${project.name}/javascript/platform-core.*"); | |
|                 exclude("**/${project.name}/javascript/quasar.*"); | |
|                 exclude("**/${project.name}/javascript/vue.*"); | |
|                 exclude("**/${project.name}/fonts/*.*"); | |
|                 exclude("**/${project.name}/webjars/**/*.*"); | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     // 对每个前端项目在 idea 中排除 node_modules 目录, 避免大量耗时的 idea 索引 | |
|     idea { | |
|         module { | |
|             excludeDirs += file('node_modules') | |
|             excludeDirs += file('dist') | |
|         } | |
|     } | |
| } | |
| 
 | |
| /*********************************************************************** | |
|  * 根(Root)项目配置, 该部分仅用于根项目 | |
|  **********************************************************************/ | |
| /*----------------------------------------------------------------- | |
|  * idea 配置 | |
|  *----------------------------------------------------------------*/ | |
| tasks.ideaProject.enabled=true      //在根工程中执行 ideaProject 任务,用于生成 ipr 文件 | |
| tasks.ideaModule.enabled=false       //在根工程中不执行 ideaModule 任务 | |
| tasks.ideaWorkspace.enabled=true    //在根工程中执行 ideaWorkspace 任务,用于修改 iws 文件 | |
| 
 | |
| tasks.ideaProject.doFirst { | |
|     delete project.name + '.ipr' | |
| } | |
| 
 | |
| /*----------------------------------------------------------------- | |
|  * 定制生成的 idea xml 文件内容 | |
|  *----------------------------------------------------------------*/ | |
| idea { | |
|     workspace { | |
|         iws { | |
|             // 自动化配置生成的 iws 文件内容,减少手工操作 | |
|             // 1. 设置 Automatically show first error in editor 属性为 false,避免在编辑代码时,总是打开其他有错误的文件,导致混乱 | |
|             withXml { | |
|                 // 1. 设置 Automatically show first error in editor 属性为 false,避免在编辑代码时,总是打开其他有错误的文件,导致混乱 | |
|                 def node = it.asNode(); | |
|                 def compilerWorkspaceConfigurationNode =node.find{it.@name=='CompilerWorkspaceConfiguration'} | |
|                 if(compilerWorkspaceConfigurationNode==null){ | |
|                     compilerWorkspaceConfigurationNode =node.appendNode("component",[name:"CompilerWorkspaceConfiguration"]); | |
|                 } | |
|                 def autoShowErrorsInEditorNode =compilerWorkspaceConfigurationNode.find{it.@name=='AUTO_SHOW_ERRORS_IN_EDITOR'} | |
|                 if(autoShowErrorsInEditorNode==null){ | |
|                     autoShowErrorsInEditorNode =compilerWorkspaceConfigurationNode.appendNode("option",[name:"AUTO_SHOW_ERRORS_IN_EDITOR"]); | |
|                 } | |
|                 autoShowErrorsInEditorNode.@value ="false"; | |
|             } | |
|         } | |
|     } | |
| 	project { | |
|         vcs = 'Git' | |
|         ipr { | |
|             // 自动化配置生成的 ipr 文件内容,减少手工操作 | |
|             // 1. 移除根项目模块 | |
|             // <component name="ProjectModuleManager"> | |
|             //   <modules> | |
|             //     <module fileurl="file://$PROJECT_DIR$/projectName.iml" filepath="$PROJECT_DIR$/projectName.iml"/>  #移除 | |
|             //     ...... | |
|             //   </modules> | |
|             // </component> | |
|             // 2. 设置打开 .properties 文件时的转码功能(可显示中文) | |
|             // 将 | |
|             // <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false"/> | |
|             // 替换为: | |
|             // <component name="Encoding" native2AsciiForPropertiesFiles="true" /> | |
|             // 3. 使 idea 编译器支持注解(enable annotation processing) | |
|             // 将 | |
|             // <annotationProcessing enabled="false" useClasspath="true"/> | |
|             // 替换为: | |
|             // <annotationProcessing> | |
|             //     <profile default="true" name="" enabled="true" /> | |
|             // </annotationProcessing> | |
|             withXml { | |
|                 // 1. 移除根项目模块 | |
|                 def node = it.asNode() | |
|                 def projectModuleManagerNode = node.find { it.@name == 'ProjectModuleManager' } | |
|                 def rootImlNode = projectModuleManagerNode.modules.module.find { it.@fileurl == 'file://$PROJECT_DIR$/' + project.name + '.iml' } | |
|                 def rootImlParentNode = rootImlNode.parent() | |
|                 rootImlParentNode.remove(rootImlNode) | |
| 
 | |
|                 // 2. 替换 Encoding | |
|                 def encodingNode = node.find { it.@name == 'Encoding' } | |
|                 encodingNode.@native2AsciiForPropertiesFiles = "true" | |
| 
 | |
|                 // 3. 使 idea 编译器支持注解(enable annotation processing) | |
|                 def compilerConfigurationNode = node.find { it.@name == 'CompilerConfiguration' } | |
|                 def annotationProcessingNode = compilerConfigurationNode.annotationProcessing[0] | |
|                 def annotationProcessingParentNode = annotationProcessingNode.parent() | |
|                 annotationProcessingParentNode.remove(annotationProcessingNode) | |
|                 annotationProcessingNode = annotationProcessingParentNode.appendNode("annotationProcessing") | |
|                 annotationProcessingNode.appendNode("profile", [default: true, enabled: true]) | |
| 
 | |
|                 // 4. 激活 SaveActions 插件, 修改文件后自动编译并发布, 在 .ipr 文件中生成以下 xml 片段 | |
|                 //    <component name="SaveActionSettings"> | |
|                 //      <option name="actions"> | |
|                 //        <set> | |
|                 //          <option value="activate" /> | |
|                 //          <option value="reload" /> | |
|                 //        </set> | |
|                 //      </option> | |
|                 //      <option name="configurationPath" value="" /> | |
|                 //    </component> | |
| 
 | |
|                 // <component name="SaveActionSettings"> | |
|                 def saveActionSettingsNode = node.find { it.@name == 'SaveActionSettings' } | |
|                 if (saveActionSettingsNode == null) { | |
|                     saveActionSettingsNode = node.appendNode("component", [name: "SaveActionSettings"]) | |
|                 } | |
| 
 | |
|                 // <option name="actions"> | |
|                 def actionsNode = saveActionSettingsNode.find { it.@name == 'actions' } | |
|                 if (actionsNode == null) { | |
|                     actionsNode = saveActionSettingsNode.appendNode("option", [name: "actions"]) | |
|                 } | |
| 
 | |
|                 // <set> | |
|                 def setNode = actionsNode.set[0] | |
| 
 | |
|                 if (setNode == null) { | |
|                     setNode = actionsNode.appendNode("set") | |
|                 } | |
| 
 | |
|                 // <option value="activate" /> | |
|                 // <option value="reload" /> | |
|                 def options = setNode.option | |
|                 if (options != null && options.size() > 0) { | |
|                     // 先移除 | |
|                     for (int i = 0; i < options.size(); i++) { | |
|                         setNode.remove(options.get(i)); | |
|                     } | |
|                 } | |
|                 // 再添加 | |
|                 setNode.appendNode("option", [value: "activate"]) | |
|                 setNode.appendNode("option", [value: "reload"]) | |
|             } | |
|         } | |
|     } | |
| } | |
| 
 | |
| /*----------------------------------------------------------------- | |
|  * 覆盖根项目的 clean 任务 | |
|  * 删除 idea 编译的 out 目录,实际上 out 目录并不在每个子模块中,而在根工程目录中 | |
|  * 但是 gradle 对根项目并没有提供 clean 任务, 在此单独为根项目提供 clean 任务 | |
|  *----------------------------------------------------------------*/ | |
| task clean { | |
|     doFirst{ | |
|         delete 'out' | |
|     } | |
| } | |
| 
 | |
| /*----------------------------------------------------------------- | |
|  * 覆盖根工程的 cleanIdea 任务,由于默认 cleanIdea 任务只执行: | |
|  * cleanIdeaProject, cleanIdeaModule 两个任务, | |
|  * gradle 也单独提供了一个 cleanIdeaWorkspace 任务,用于删除 .iws 文件。 | |
|  * 为了方便, 我们将 cleanIdea 任务的默认行为改为同时执行 3 两个任务 | |
|  * cleanIdeaProject, cleanIdeaModule, cleanIdeaWorkspace | |
|  *----------------------------------------------------------------*/ | |
| cleanIdea { | |
|     dependsOn cleanIdeaWorkspace | |
| } | |
| 
 | |
| task github { | |
|     println '' | |
| } | |
| 
 | |
| tasks.named('wrapper') { | |
|     distributionUrl = "http://nexus.sc.io:8000/repository/maven-releases/gradle/gradle/${gradleVersion}/gradle-${gradleVersion}-bin.zip" | |
| }
 | |
| 
 |