初始化
This commit is contained in:
		
							
								
								
									
										155
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <parent> | ||||
|         <groupId>org.springframework.boot</groupId> | ||||
|         <artifactId>spring-boot-starter-parent</artifactId> | ||||
|         <version>2.5.4</version> | ||||
|         <relativePath/> | ||||
|     </parent> | ||||
|     <artifactId>temp-clipboard</artifactId> | ||||
|     <groupId>com.pomelotea</groupId> | ||||
|     <version>1.0-SNAPSHOT</version> | ||||
|     <packaging>jar</packaging> | ||||
|  | ||||
|     <name>consoleApp</name> | ||||
|  | ||||
|     <properties> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <kotlin.code.style>official</kotlin.code.style> | ||||
|         <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget> | ||||
|         <kotlin.version>1.7.0</kotlin.version> | ||||
|     </properties> | ||||
|  | ||||
|     <repositories> | ||||
|         <repository> | ||||
|             <id>mavenCentral</id> | ||||
|             <url>https://repo1.maven.org/maven2/</url> | ||||
|         </repository> | ||||
|     </repositories> | ||||
|  | ||||
|  | ||||
|     <build> | ||||
|         <sourceDirectory>src/main/kotlin</sourceDirectory> | ||||
|         <testSourceDirectory>src/test/kotlin</testSourceDirectory> | ||||
|         <plugins> | ||||
|             <plugin> | ||||
|                 <groupId>org.springframework.boot</groupId> | ||||
|                 <artifactId>spring-boot-maven-plugin</artifactId> | ||||
|                 <configuration> | ||||
|                     <fork>true</fork> | ||||
|                     <outputDirectory>./target</outputDirectory> | ||||
|                     <classifier>executable</classifier> | ||||
|                 </configuration> | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <goals> | ||||
|                             <goal>repackage</goal> | ||||
|                         </goals> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|             </plugin> | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-compiler-plugin</artifactId> | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <id>compile</id> | ||||
|                         <phase>compile</phase> | ||||
|                         <goals> | ||||
|                             <goal>compile</goal> | ||||
|                         </goals> | ||||
|                     </execution> | ||||
|                     <execution> | ||||
|                         <id>testCompile</id> | ||||
|                         <phase>test-compile</phase> | ||||
|                         <goals> | ||||
|                             <goal>testCompile</goal> | ||||
|                         </goals> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|             </plugin> | ||||
|  | ||||
|             <plugin> | ||||
|                 <groupId>org.jetbrains.kotlin</groupId> | ||||
|                 <artifactId>kotlin-maven-plugin</artifactId> | ||||
|                 <version>${kotlin.version}</version> | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <id>compile</id> | ||||
|                         <phase>compile</phase> | ||||
|                         <goals> | ||||
|                             <goal>compile</goal> | ||||
|                         </goals> | ||||
|                     </execution> | ||||
|                     <execution> | ||||
|                         <id>test-compile</id> | ||||
|                         <phase>test-compile</phase> | ||||
|                         <goals> | ||||
|                             <goal>test-compile</goal> | ||||
|                         </goals> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|                 <configuration> | ||||
|                     <jvmTarget>1.8</jvmTarget> | ||||
|                 </configuration> | ||||
|             </plugin> | ||||
|         </plugins> | ||||
|     </build> | ||||
|  | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>org.jetbrains.kotlin</groupId> | ||||
|             <artifactId>kotlin-test-junit5</artifactId> | ||||
|             <version>1.7.0</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.junit.jupiter</groupId> | ||||
|             <artifactId>junit-jupiter-engine</artifactId> | ||||
|             <version>5.8.2</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.jetbrains.kotlin</groupId> | ||||
|             <artifactId>kotlin-stdlib-jdk8</artifactId> | ||||
|             <version>1.7.0</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-web</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.alibaba</groupId> | ||||
|             <artifactId>fastjson</artifactId> | ||||
|             <version>2.0.7</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.parkingwang</groupId> | ||||
|             <artifactId>okhttp3-loginterceptor</artifactId> | ||||
|             <version>0.5</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.squareup.okhttp3</groupId> | ||||
|             <artifactId>okhttp</artifactId> | ||||
|             <version>4.2.2</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.fasterxml.jackson.module</groupId> | ||||
|             <artifactId>jackson-module-kotlin</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-logging</artifactId> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
| </project> | ||||
							
								
								
									
										23
									
								
								src/main/kotlin/com/pomelotea/BootApplication.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/main/kotlin/com/pomelotea/BootApplication.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package com.pomelotea | ||||
|  | ||||
| import org.slf4j.LoggerFactory | ||||
| import org.springframework.boot.SpringApplication | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication | ||||
| import java.text.SimpleDateFormat | ||||
| import java.util.* | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @version 0.0.1 | ||||
|  * @author jimlee | ||||
|  * date 2022-07-15 10:53 | ||||
|  * 启动入口 | ||||
|  **/ | ||||
| @SpringBootApplication | ||||
| open class BootApplication { | ||||
| } | ||||
| private val logger = LoggerFactory.getLogger("APPLICATION-STARTER") | ||||
| fun main(args: Array<String>) { | ||||
|     SpringApplication.run(BootApplication::class.java, *args) | ||||
|     logger.info("临时粘贴板服务启动成功:{}", SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(Date())) | ||||
| } | ||||
							
								
								
									
										72
									
								
								src/main/kotlin/com/pomelotea/api/ClipboardController.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/main/kotlin/com/pomelotea/api/ClipboardController.kt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										66
									
								
								src/main/kotlin/com/pomelotea/api/HealthCodeController.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/main/kotlin/com/pomelotea/api/HealthCodeController.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| package com.pomelotea.api | ||||
|  | ||||
| import okhttp3.FormBody | ||||
| import okhttp3.Headers | ||||
| import okhttp3.OkHttpClient | ||||
| import okhttp3.Request | ||||
| import org.springframework.web.bind.annotation.PostMapping | ||||
| import org.springframework.web.bind.annotation.RequestParam | ||||
| import org.springframework.web.bind.annotation.RestController | ||||
| import java.time.Duration | ||||
| import javax.servlet.http.HttpServletRequest | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @version 0.0.1 | ||||
|  * @author jimlee | ||||
|  * date 2022-11-02 10:29 | ||||
|  * | ||||
|  **/ | ||||
| @RestController | ||||
| class HealthCodeController { | ||||
|  | ||||
|     val json = """ | ||||
|         { | ||||
|         	"success": true, | ||||
|         	"errorCode": null, | ||||
|         	"errorMsg": null, | ||||
|         	"result": "{\"reason\":\"0\",\"zlbLogoSize\":30,\"vaccinated\":\"3\",\"modifiedTimes\":0,\"logoUrl\":\"//img.alicdn.com/imgextra/i1/O1CN01RTcWEm1mriBsqhQ3Q_!!6000000005008-2-tps-516-516.png\",\"uid\":2945226479,\"descEn\":\"Green Code: It gives you greenlight at public venues and major checkpoints in Zhejiang;Be attentive to your health condition;the code color might change when your health status or local regulations change.\",\"descCn\":\"绿码:凭此码可在浙江省范围内通行,请主动出示,配合检查;并做好自身防护工作,码颜色将根据您的申报由当地政府按照相关政策动态更新,出行前请仔细检查您的健康。\",\"logoSize\":30,\"vaccinatedSwitch\":true,\"name\":\"李建明\",\"healthRecord\":{\"colorCss\":\"#27AE64\",\"qrCode\":\"V0dinga7e710d462f82d242e2feadba6d9041e\",\"feControlModel\":{\"tips\":\"\",\"enTips\":\"\"},\"stateCouncilBarCode\":\"d8cbdc8eb52a2fcc9bc6864bccd8f917\",\"eHealthCode\":\"\",\"qrColor\":\"green\",\"extInfo\":\"{\\\"nucleicData\\\":{\\\"nucleicDescriptionEn\\\":\\\"d\\\",\\\"nucleicDescriptionCn\\\":\\\"天内\\\",\\\"countDownDescriptionEn\\\":\\\"3 Days To Maturity\\\",\\\"nucleicStatusCn\\\":\\\"阴性\\\",\\\"countDownDescriptionCn\\\":\\\"距离3天到期还剩\\\",\\\"nucleicStatusEn\\\":\\\"Neg\\\",\\\"expireSpecVal\\\":\\\"168\\\",\\\"showCompareTime\\\":true,\\\"lessthenDayNumbersDisplayAsHours\\\":2,\\\"compareType\\\":\\\"report\\\",\\\"checkTime\\\":\\\"2022-10-30 10:48:06\\\",\\\"hourValue\\\":67.0,\\\"nucleicDayEn\\\":\\\"≤3\\\",\\\"timeInterval\\\":\\\"72\\\",\\\"nucleicDayCn\\\":3,\\\"countDown\\\":17608,\\\"compareTime\\\":\\\"2022-10-30 15:21:44\\\",\\\"reportTime\\\":\\\"2022-10-30 15:21:44\\\",\\\"recentNoNucleicDay\\\":3}}\"},\"descCss\":\"#333333\",\"config\":\"{\\\"travelCardUrl\\\":\\\"alipays://platformapi/startapp?appId=2019011763060066&page=pages%2Fjourney-webview%2Fjourney-webview\\\",\\\"travelCardUrlH5\\\":\\\"https://xc.caict.ac.cn/?code=152&phone={phone}&t={timestamp}&ad=1\\\"}\"}", | ||||
|         	"arguments": null | ||||
|         } | ||||
|     """.trimIndent() | ||||
|  | ||||
|  | ||||
|  | ||||
|     @PostMapping("/unAuthLwp/queryHealthInfoByAuthCode") | ||||
|     fun queryHealthInfoByAuthCode(@RequestParam args: String, request: HttpServletRequest): String? { | ||||
|         val client = OkHttpClient() | ||||
|             .newBuilder() | ||||
|             .connectTimeout(Duration.ofSeconds(10)) | ||||
|             .callTimeout(Duration.ofSeconds(10)) | ||||
|             .build() | ||||
|  | ||||
|         val headerList: MutableList<String> = ArrayList() | ||||
|         val reqHeaders = request.headerNames | ||||
|         for (header in reqHeaders) { | ||||
|             headerList.add(header) | ||||
|             headerList.add(request.getHeader(header)) | ||||
|         } | ||||
|         headerList.add("Cookie") | ||||
|         headerList.add(request.cookies.toString()) | ||||
|         val headers: Headers = Headers.headersOf(*headerList.toTypedArray()) | ||||
|  | ||||
|         val request = Request.Builder() | ||||
|             .url("https://healthcode.dingtalk.com/unAuthLwp/queryHealthInfoByAuthCode") | ||||
|             .post( | ||||
|                 FormBody.Builder().add("args", args).build() | ||||
|             ) | ||||
|             .headers(headers) | ||||
|             .build() | ||||
|  | ||||
|         val response = client.newCall(request).execute() | ||||
|         val bodyString: String? = response.body?.string() | ||||
|         println(bodyString) | ||||
|         return json | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								src/main/kotlin/com/pomelotea/api/TempClipboardController.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/main/kotlin/com/pomelotea/api/TempClipboardController.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| //package com.pomelotea.api | ||||
| // | ||||
| //import org.springframework.web.bind.annotation.CookieValue | ||||
| //import org.springframework.web.bind.annotation.GetMapping | ||||
| //import org.springframework.web.bind.annotation.PathVariable | ||||
| //import org.springframework.web.bind.annotation.PutMapping | ||||
| //import org.springframework.web.bind.annotation.RequestBody | ||||
| //import org.springframework.web.bind.annotation.RequestMapping | ||||
| //import org.springframework.web.bind.annotation.RestController | ||||
| //import org.springframework.web.servlet.view.RedirectView | ||||
| //import java.nio.charset.StandardCharsets | ||||
| //import java.nio.file.Files | ||||
| //import java.nio.file.Paths | ||||
| //import java.util.concurrent.atomic.AtomicInteger | ||||
| //import javax.servlet.http.Cookie | ||||
| //import javax.servlet.http.HttpServletRequest | ||||
| //import javax.servlet.http.HttpServletResponse | ||||
| // | ||||
| ///** | ||||
| // * | ||||
| // * @version 0.0.1 | ||||
| // * @author jimlee | ||||
| // * date 2022-08-04 12:53 | ||||
| // * | ||||
| // **/ | ||||
| //@RestController | ||||
| //class TempClipboardController { | ||||
| // | ||||
| //    @GetMapping("/clipboard") | ||||
| //    fun getValue(@CookieValue(value = "clipId", defaultValue = "-1") clipId: Int): String { | ||||
| //        val tempData = clipMap[clipId] ?: return "" | ||||
| //        return if (tempData.type == Type.String) { | ||||
| //            tempData.value ?: "" | ||||
| //        } else { | ||||
| //            Files.readAllBytes(Paths.get("./temp/$clipId")).toString(StandardCharsets.UTF_8) | ||||
| //        } | ||||
| //    } | ||||
| // | ||||
| //    @GetMapping("/c/{clipId}") | ||||
| //    fun redirectToHome(@PathVariable clipId: Int, | ||||
| //                       request: HttpServletRequest, | ||||
| //                       response: HttpServletResponse): RedirectView { | ||||
| //        response.addCookie(Cookie("clipId", clipId.toString())) | ||||
| //        return RedirectView("https://c.pomelotea.com", true, false) | ||||
| //    } | ||||
| // | ||||
| //    @PutMapping("/clipboard") | ||||
| //    fun putValue(@RequestBody putDataRequest: PutDataRequest, | ||||
| //                 @CookieValue(value = "clipId", defaultValue = "-1") clipId: Int): Int? { | ||||
| //        if (putDataRequest.value == null) { | ||||
| //            return null | ||||
| //        } | ||||
| // | ||||
| //        val id: Int = if (clipId != -1) clipId else idInteger.incrementAndGet() | ||||
| //        clipMap[id] = if (putDataRequest.value.length > 10240) { | ||||
| //            Files.write(Paths.get("./temp/$id"), putDataRequest.value.toByteArray(StandardCharsets.UTF_8)) | ||||
| //            TempData(Type.File) | ||||
| //        } else { | ||||
| //            TempData(Type.String, putDataRequest.value) | ||||
| //        } | ||||
| //        return id | ||||
| //    } | ||||
| // | ||||
| //    companion object { | ||||
| //        private val clipMap: MutableMap<Int, TempData> = HashMap() | ||||
| //        private val idInteger: AtomicInteger = AtomicInteger(0) | ||||
| //    } | ||||
| //} | ||||
| // | ||||
| //data class PutDataRequest( | ||||
| //    val id: Int? = null, | ||||
| //    val value: String? = null | ||||
| //) | ||||
| // | ||||
| //data class TempData( | ||||
| //    val type: Type, | ||||
| //    val value: String? = null | ||||
| //) | ||||
| // | ||||
| //enum class Type { | ||||
| //    String, | ||||
| //    File | ||||
| //} | ||||
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										10
									
								
								src/main/resources/config/application.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/main/resources/config/application.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| server: | ||||
|   port: 8081 | ||||
|  | ||||
| spring: | ||||
|   servlet: | ||||
|     multipart: | ||||
|       max-request-size: 100MB | ||||
|       max-file-size: 100MB | ||||
|   application: | ||||
|     name: 临时粘贴板 | ||||
							
								
								
									
										300
									
								
								src/main/resources/static/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								src/main/resources/static/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>临时粘贴板</title> | ||||
|     <link rel="stylesheet" type="text/css" href="./waves.min.css?v=0.7.2"> | ||||
|     <style> | ||||
|  | ||||
|         body { | ||||
|             width: 100%; | ||||
|             margin: 5px -10px; | ||||
|             padding: 0 5px 0 14px; | ||||
|             position: absolute; | ||||
|         } | ||||
|  | ||||
|         /* 输入框 */ | ||||
|         .dzm-textarea { | ||||
|             padding: 5px; | ||||
|             border: 1px solid red; | ||||
|             width: 98%; | ||||
|             border-radius: 3px; | ||||
|             position: fixed; | ||||
|         } | ||||
|  | ||||
|         /* 输入框为空时显示 placeholder */ | ||||
|         .dzm-textarea:empty:before { | ||||
|             content: attr(placeholder); | ||||
|             color: red; | ||||
|         } | ||||
|  | ||||
|         /* 输入框获取焦点时移除 placeholder */ | ||||
|         .dzm-textarea:focus:before { | ||||
|             content: none; | ||||
|         } | ||||
|  | ||||
|         .textcopy { | ||||
|             position: fixed; | ||||
|             height: 40px; | ||||
|             width: 40px; | ||||
|             top: 50%; | ||||
|             right: 1%; | ||||
|             transform: translateX(-50%) translateY(-50%); | ||||
|         } | ||||
|  | ||||
|         .textcopy a, | ||||
|         .textcopy a:hover { | ||||
|             background: #01BCFF; | ||||
|             margin: 5px; | ||||
|             right: 10px; | ||||
|         } | ||||
|  | ||||
|         .btn { | ||||
|             color: #fff; | ||||
|         } | ||||
|  | ||||
|     </style> | ||||
|     <script type="text/javascript" src="./jquery.min.js"></script> | ||||
|     <script type="text/javascript" src="./waves.min.js?v=0.7.1"></script> | ||||
| </head> | ||||
| <body> | ||||
| <!-- textarea --> | ||||
| <div oninput="textInput()" id="textarea" class="dzm-textarea" contenteditable="true" placeholder="请输入内容" | ||||
|      style="resize: both; overflow: auto;"></div> | ||||
| <label for="copy_content"></label><input id="copy_content" type="text" value="" style="position: fixed;top: -100px;z-index: -10;"/> | ||||
| <div class="textcopy"> | ||||
|     <a class="btn float-buttons waves-effect waves-button waves-float" onclick="copyText()">复制</a> | ||||
|     <a class="btn float-buttons waves-effect waves-button waves-float" onclick="pasteText()">粘贴</a> | ||||
|     <a class="btn float-buttons waves-effect waves-button waves-float" onclick="openUrl()">打开</a> | ||||
| </div> | ||||
| <script> | ||||
|  | ||||
|     Waves.attach('.flat-buttons', ['waves-button']); | ||||
|     Waves.attach('.float-buttons', ['waves-button', 'waves-float']); | ||||
|     Waves.attach('.float-button-light', ['waves-button', 'waves-float', 'waves-light']); | ||||
|     $(document).on('ready', function () { | ||||
|         Waves.init(); | ||||
|         Waves.attach('.drag-ripple', 'waves-block', true); | ||||
|         Waves.attach('#bg-pattern', null, true); | ||||
|     }); | ||||
|     const textarea = document.querySelector(".dzm-textarea") | ||||
|  | ||||
|     function copyText() { | ||||
|         let nowValue = textarea.innerText; | ||||
|         if (nowValue === "") { | ||||
|             nowValue = document.querySelector("#textarea > img").src | ||||
|             // base64 image | ||||
|             if (nowValue.startsWith("data")) { | ||||
|                 let type = nowValue.substring(5, nowValue.indexOf(';')) | ||||
|                 let clipboardItemInput | ||||
|                 switch (type) { | ||||
|                     case "image/png": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "image/png": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "image/jpeg": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "image/jpeg": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "image/gif": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "image/gif": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/pdf": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/pdf": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.ms-excel": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.ms-excel": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.openxmlformats-officedocument.presentationml.presentation": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.openxmlformats-officedocument.presentationml.presentation": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.ms-powerpoint": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.ms-powerpoint": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.openxmlformats-officedocument.wordprocessingml.document": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/msword": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/msword": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                 } | ||||
|                 if (clipboardItemInput != null) { | ||||
|                     navigator.clipboard.write([clipboardItemInput]); | ||||
|                 } | ||||
|             } else { | ||||
|                 const selection = window.getSelection(); | ||||
|                 if (selection.rangeCount > 0) selection.removeAllRanges(); | ||||
|                 const range = document.createRange(); | ||||
|                 range.selectNode(document.querySelector("#textarea > img")); //传入dom | ||||
|                 selection.addRange(range); | ||||
|                 document.execCommand("copy"); //copy是复制 | ||||
|                 selection.removeAllRanges(); //清除缓存 | ||||
|             } | ||||
|         } else { | ||||
|             //获取要赋值的input的元素 | ||||
|             var inputElement = document.getElementById("copy_content"); | ||||
|             // 设置只读,否则移动端会弹出软键盘 | ||||
|             inputElement.setAttribute("readonly", "readonly"); | ||||
|             //给input框赋值 | ||||
|             inputElement.value = textarea.innerText; | ||||
|             //选中input框的内容 | ||||
|             inputElement.select(); | ||||
|             inputElement.setSelectionRange(0, 9999999999999); | ||||
|             // 执行浏览器复制命令 | ||||
|             // document.execCommand("Copy"); | ||||
|             navigator.clipboard.writeText(textarea.innerText) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function pasteText() { | ||||
|         navigator.clipboard.readText() | ||||
|             .then(text => { | ||||
|                 textarea.innerText = text | ||||
|             }) | ||||
|     } | ||||
|     // | ||||
|     // function appendText() { | ||||
|     //     navigator.clipboard.readText() | ||||
|     //         .then(text => { | ||||
|     //             textarea.innerText = textarea.innerText + text | ||||
|     //         }) | ||||
|     // } | ||||
|  | ||||
|     function openUrl() { | ||||
|         window.open(textarea.innerText) | ||||
|     } | ||||
|  | ||||
|     let lastUpdate = null | ||||
|     let lastValue = "" | ||||
|     let saveInterval | ||||
|     window.onload = function () { | ||||
|         loadValue() | ||||
|         // 监听页面状态 | ||||
|         document.addEventListener('visibilitychange', function () { | ||||
|                 // 页面状态变化为可见时触发 | ||||
|                 if (document.visibilityState === 'hidden') { | ||||
|                     if (lastUpdate != null && Date.now() - lastUpdate > 5000) { | ||||
|                         clearInterval(saveInterval) | ||||
|                     } | ||||
|                 } else if (document.visibilityState === 'visible') { | ||||
|                     loadValue() | ||||
|                     saveInterval = setInterval(() => { | ||||
|                         saveValue() | ||||
|                     }, 1000) | ||||
|                 } | ||||
|             } | ||||
|         ) | ||||
|         saveInterval = setInterval(() => { | ||||
|             saveValue() | ||||
|         }, 1000) | ||||
|     } | ||||
|  | ||||
|     function saveValue() { | ||||
|         let nowValue = textarea.innerText; | ||||
|         if (nowValue === "") { | ||||
|             nowValue = textarea.innerHTML | ||||
|         } | ||||
|         if (lastValue !== nowValue && lastUpdate != null && Date.now() - lastUpdate > 3000) { | ||||
|             lastValue = nowValue | ||||
|             var httpRequest = new XMLHttpRequest();// new对象 | ||||
|             httpRequest.open('PUT', '/clipboard', true);// get表示请求方式、url请求的地址 | ||||
|             httpRequest.setRequestHeader("Content-type", "application/json");//post方式需要设置请求头 | ||||
|             var reqParam = { | ||||
|                 'value': nowValue, | ||||
|             } | ||||
|             httpRequest.send(JSON.stringify(reqParam));//发送请求 将请求体写在send中 | ||||
|             // 返回处理 | ||||
|             httpRequest.onreadystatechange = function () { | ||||
|                 if (httpRequest.readyState === 4 && httpRequest.status === 200) { | ||||
|                     //success | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function loadValue() { | ||||
|         var httpRequest = new XMLHttpRequest();// new对象 | ||||
|         httpRequest.open('GET', window.origin + "/clipboard", true);// get表示请求方式、url请求的地址 | ||||
|         httpRequest.send();// 发送请求 | ||||
|         // 返回处理 | ||||
|         httpRequest.onreadystatechange = function () { | ||||
|             if (httpRequest.readyState === 4 && httpRequest.status === 200) { | ||||
|                 if (httpRequest.responseText.startsWith("<img")) { | ||||
|                     textarea.innerHTML = httpRequest.responseText | ||||
|                 } else { | ||||
|                     textarea.innerText = httpRequest.responseText.replaceAll("\n", "") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function textInput() { | ||||
|         lastUpdate = Date.now() | ||||
|     } | ||||
|  | ||||
|     document.querySelector('#textarea').addEventListener('paste', function (e) { | ||||
|         var cbd = e.clipboardData; | ||||
|         var ua = window.navigator.userAgent; | ||||
|         // 如果是 Safari 直接 return | ||||
|         if (!(e.clipboardData && e.clipboardData.items)) { | ||||
|             return; | ||||
|         } | ||||
|         // Mac平台下Chrome49版本以下 复制Finder中的文件的Bug Hack掉 | ||||
|         if (cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" && | ||||
|             cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" && | ||||
|             ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49) { | ||||
|             return; | ||||
|         } | ||||
|         for (var i = 0; i < cbd.items.length; i++) { | ||||
|             var item = cbd.items[i]; | ||||
|             if (item.kind === "file") { | ||||
|                 var blob = item.getAsFile(); | ||||
|                 if (blob.size === 0) { | ||||
|                     return; | ||||
|                 } | ||||
|                 var reader = new FileReader(); | ||||
|                 var imgs = new Image(); | ||||
|                 imgs.file = blob; | ||||
|                 reader.onload = (function (aImg) { | ||||
|                     return function (e) { | ||||
|                         aImg.src = e.target.result; | ||||
|                         // chrome下有Bug显示两张图片,此处为兼容处理 | ||||
|                         let imgary = $('#textarea > img') | ||||
|                         if (imgary.length > 1) { | ||||
|                             imgary.eq(-1).remove() | ||||
|                         } | ||||
|                     }; | ||||
|                 })(imgs); | ||||
|                 reader.readAsDataURL(blob); | ||||
|                 document.querySelector("#textarea").innerHTML = "" | ||||
|                 document.querySelector('#textarea').appendChild(imgs); | ||||
|                 lastUpdate = Date.now() | ||||
|             } | ||||
|         } | ||||
|     }, false); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										6
									
								
								src/main/resources/static/jquery.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/main/resources/static/jquery.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										8
									
								
								src/main/resources/static/waves.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/main/resources/static/waves.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| /*! | ||||
|  * Waves v0.7.2 | ||||
|  * http://fian.my.id/Waves  | ||||
|  *  | ||||
|  * Copyright 2014 Alfiana E. Sibuea and other contributors  | ||||
|  * Released under the MIT license  | ||||
|  * https://github.com/fians/Waves/blob/master/LICENSE  | ||||
|  */.waves-effect{position:relative;cursor:pointer;display:inline-block;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.waves-effect .waves-ripple{position:absolute;border-radius:50%;width:100px;height:100px;margin-top:-50px;margin-left:-50px;opacity:0;background:rgba(0,0,0,.2);background:-webkit-radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);background:-o-radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);background:-moz-radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);background:radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);-webkit-transition:all .5s ease-out;-moz-transition:all .5s ease-out;-o-transition:all .5s ease-out;transition:all .5s ease-out;-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform,opacity;-o-transition-property:-o-transform,opacity;transition-property:transform,opacity;-webkit-transform:scale(0) translate(0,0);-moz-transform:scale(0) translate(0,0);-ms-transform:scale(0) translate(0,0);-o-transform:scale(0) translate(0,0);transform:scale(0) translate(0,0);pointer-events:none}.waves-effect.waves-light .waves-ripple{background:rgba(255,255,255,.4);background:-webkit-radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%);background:-o-radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%);background:-moz-radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%);background:radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%)}.waves-effect.waves-classic .waves-ripple{background:rgba(0,0,0,.2)}.waves-effect.waves-classic.waves-light .waves-ripple{background:rgba(255,255,255,.4)}.waves-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.waves-button,.waves-circle{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0);-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.waves-button,.waves-button:hover,.waves-button:visited,.waves-button-input{white-space:nowrap;vertical-align:middle;cursor:pointer;border:none;outline:0;color:inherit;background-color:transparent;font-size:1em;line-height:1em;text-align:center;text-decoration:none;z-index:1}.waves-button{padding:.85em 1.1em;border-radius:.2em}.waves-button-input{margin:0;padding:.85em 1.1em}.waves-input-wrapper{border-radius:.2em;vertical-align:bottom}.waves-input-wrapper.waves-button{padding:0}.waves-input-wrapper .waves-button-input{position:relative;top:0;left:0;z-index:1}.waves-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%}.waves-float{-webkit-mask-image:none;-webkit-box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);-webkit-transition:all 300ms;-moz-transition:all 300ms;-o-transition:all 300ms;transition:all 300ms}.waves-float:active{-webkit-box-shadow:0 8px 20px 1px rgba(0,0,0,.3);box-shadow:0 8px 20px 1px rgba(0,0,0,.3)}.waves-block{display:block}a.waves-effect .waves-ripple{z-index:-1} | ||||
							
								
								
									
										10
									
								
								src/main/resources/static/waves.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/main/resources/static/waves.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								src/main/resources/static/waves.min.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/main/resources/static/waves.min.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								target/classes/META-INF/temp-clipboard.kotlin_module
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								target/classes/META-INF/temp-clipboard.kotlin_module
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										10
									
								
								target/classes/config/application.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								target/classes/config/application.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| server: | ||||
|   port: 8081 | ||||
|  | ||||
| spring: | ||||
|   servlet: | ||||
|     multipart: | ||||
|       max-request-size: 100MB | ||||
|       max-file-size: 100MB | ||||
|   application: | ||||
|     name: 临时粘贴板 | ||||
							
								
								
									
										300
									
								
								target/classes/static/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								target/classes/static/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>临时粘贴板</title> | ||||
|     <link rel="stylesheet" type="text/css" href="./waves.min.css?v=0.7.2"> | ||||
|     <style> | ||||
|  | ||||
|         body { | ||||
|             width: 100%; | ||||
|             margin: 5px -10px; | ||||
|             padding: 0 5px 0 14px; | ||||
|             position: absolute; | ||||
|         } | ||||
|  | ||||
|         /* 输入框 */ | ||||
|         .dzm-textarea { | ||||
|             padding: 5px; | ||||
|             border: 1px solid red; | ||||
|             width: 98%; | ||||
|             border-radius: 3px; | ||||
|             position: fixed; | ||||
|         } | ||||
|  | ||||
|         /* 输入框为空时显示 placeholder */ | ||||
|         .dzm-textarea:empty:before { | ||||
|             content: attr(placeholder); | ||||
|             color: red; | ||||
|         } | ||||
|  | ||||
|         /* 输入框获取焦点时移除 placeholder */ | ||||
|         .dzm-textarea:focus:before { | ||||
|             content: none; | ||||
|         } | ||||
|  | ||||
|         .textcopy { | ||||
|             position: fixed; | ||||
|             height: 40px; | ||||
|             width: 40px; | ||||
|             top: 50%; | ||||
|             right: 1%; | ||||
|             transform: translateX(-50%) translateY(-50%); | ||||
|         } | ||||
|  | ||||
|         .textcopy a, | ||||
|         .textcopy a:hover { | ||||
|             background: #01BCFF; | ||||
|             margin: 5px; | ||||
|             right: 10px; | ||||
|         } | ||||
|  | ||||
|         .btn { | ||||
|             color: #fff; | ||||
|         } | ||||
|  | ||||
|     </style> | ||||
|     <script type="text/javascript" src="./jquery.min.js"></script> | ||||
|     <script type="text/javascript" src="./waves.min.js?v=0.7.1"></script> | ||||
| </head> | ||||
| <body> | ||||
| <!-- textarea --> | ||||
| <div oninput="textInput()" id="textarea" class="dzm-textarea" contenteditable="true" placeholder="请输入内容" | ||||
|      style="resize: both; overflow: auto;"></div> | ||||
| <label for="copy_content"></label><input id="copy_content" type="text" value="" style="position: fixed;top: -100px;z-index: -10;"/> | ||||
| <div class="textcopy"> | ||||
|     <a class="btn float-buttons waves-effect waves-button waves-float" onclick="copyText()">复制</a> | ||||
|     <a class="btn float-buttons waves-effect waves-button waves-float" onclick="pasteText()">粘贴</a> | ||||
|     <a class="btn float-buttons waves-effect waves-button waves-float" onclick="openUrl()">打开</a> | ||||
| </div> | ||||
| <script> | ||||
|  | ||||
|     Waves.attach('.flat-buttons', ['waves-button']); | ||||
|     Waves.attach('.float-buttons', ['waves-button', 'waves-float']); | ||||
|     Waves.attach('.float-button-light', ['waves-button', 'waves-float', 'waves-light']); | ||||
|     $(document).on('ready', function () { | ||||
|         Waves.init(); | ||||
|         Waves.attach('.drag-ripple', 'waves-block', true); | ||||
|         Waves.attach('#bg-pattern', null, true); | ||||
|     }); | ||||
|     const textarea = document.querySelector(".dzm-textarea") | ||||
|  | ||||
|     function copyText() { | ||||
|         let nowValue = textarea.innerText; | ||||
|         if (nowValue === "") { | ||||
|             nowValue = document.querySelector("#textarea > img").src | ||||
|             // base64 image | ||||
|             if (nowValue.startsWith("data")) { | ||||
|                 let type = nowValue.substring(5, nowValue.indexOf(';')) | ||||
|                 let clipboardItemInput | ||||
|                 switch (type) { | ||||
|                     case "image/png": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "image/png": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "image/jpeg": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "image/jpeg": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "image/gif": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "image/gif": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/pdf": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/pdf": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.ms-excel": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.ms-excel": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.openxmlformats-officedocument.presentationml.presentation": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.openxmlformats-officedocument.presentationml.presentation": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.ms-powerpoint": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.ms-powerpoint": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/vnd.openxmlformats-officedocument.wordprocessingml.document": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                     case "application/msword": | ||||
|                         clipboardItemInput = new ClipboardItem({ | ||||
|                             "application/msword": nowValue.slice(23), | ||||
|                         }); | ||||
|                         break; | ||||
|                 } | ||||
|                 if (clipboardItemInput != null) { | ||||
|                     navigator.clipboard.write([clipboardItemInput]); | ||||
|                 } | ||||
|             } else { | ||||
|                 const selection = window.getSelection(); | ||||
|                 if (selection.rangeCount > 0) selection.removeAllRanges(); | ||||
|                 const range = document.createRange(); | ||||
|                 range.selectNode(document.querySelector("#textarea > img")); //传入dom | ||||
|                 selection.addRange(range); | ||||
|                 document.execCommand("copy"); //copy是复制 | ||||
|                 selection.removeAllRanges(); //清除缓存 | ||||
|             } | ||||
|         } else { | ||||
|             //获取要赋值的input的元素 | ||||
|             var inputElement = document.getElementById("copy_content"); | ||||
|             // 设置只读,否则移动端会弹出软键盘 | ||||
|             inputElement.setAttribute("readonly", "readonly"); | ||||
|             //给input框赋值 | ||||
|             inputElement.value = textarea.innerText; | ||||
|             //选中input框的内容 | ||||
|             inputElement.select(); | ||||
|             inputElement.setSelectionRange(0, 9999999999999); | ||||
|             // 执行浏览器复制命令 | ||||
|             // document.execCommand("Copy"); | ||||
|             navigator.clipboard.writeText(textarea.innerText) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function pasteText() { | ||||
|         navigator.clipboard.readText() | ||||
|             .then(text => { | ||||
|                 textarea.innerText = text | ||||
|             }) | ||||
|     } | ||||
|     // | ||||
|     // function appendText() { | ||||
|     //     navigator.clipboard.readText() | ||||
|     //         .then(text => { | ||||
|     //             textarea.innerText = textarea.innerText + text | ||||
|     //         }) | ||||
|     // } | ||||
|  | ||||
|     function openUrl() { | ||||
|         window.open(textarea.innerText) | ||||
|     } | ||||
|  | ||||
|     let lastUpdate = null | ||||
|     let lastValue = "" | ||||
|     let saveInterval | ||||
|     window.onload = function () { | ||||
|         loadValue() | ||||
|         // 监听页面状态 | ||||
|         document.addEventListener('visibilitychange', function () { | ||||
|                 // 页面状态变化为可见时触发 | ||||
|                 if (document.visibilityState === 'hidden') { | ||||
|                     if (lastUpdate != null && Date.now() - lastUpdate > 5000) { | ||||
|                         clearInterval(saveInterval) | ||||
|                     } | ||||
|                 } else if (document.visibilityState === 'visible') { | ||||
|                     loadValue() | ||||
|                     saveInterval = setInterval(() => { | ||||
|                         saveValue() | ||||
|                     }, 1000) | ||||
|                 } | ||||
|             } | ||||
|         ) | ||||
|         saveInterval = setInterval(() => { | ||||
|             saveValue() | ||||
|         }, 1000) | ||||
|     } | ||||
|  | ||||
|     function saveValue() { | ||||
|         let nowValue = textarea.innerText; | ||||
|         if (nowValue === "") { | ||||
|             nowValue = textarea.innerHTML | ||||
|         } | ||||
|         if (lastValue !== nowValue && lastUpdate != null && Date.now() - lastUpdate > 3000) { | ||||
|             lastValue = nowValue | ||||
|             var httpRequest = new XMLHttpRequest();// new对象 | ||||
|             httpRequest.open('PUT', '/clipboard', true);// get表示请求方式、url请求的地址 | ||||
|             httpRequest.setRequestHeader("Content-type", "application/json");//post方式需要设置请求头 | ||||
|             var reqParam = { | ||||
|                 'value': nowValue, | ||||
|             } | ||||
|             httpRequest.send(JSON.stringify(reqParam));//发送请求 将请求体写在send中 | ||||
|             // 返回处理 | ||||
|             httpRequest.onreadystatechange = function () { | ||||
|                 if (httpRequest.readyState === 4 && httpRequest.status === 200) { | ||||
|                     //success | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function loadValue() { | ||||
|         var httpRequest = new XMLHttpRequest();// new对象 | ||||
|         httpRequest.open('GET', window.origin + "/clipboard", true);// get表示请求方式、url请求的地址 | ||||
|         httpRequest.send();// 发送请求 | ||||
|         // 返回处理 | ||||
|         httpRequest.onreadystatechange = function () { | ||||
|             if (httpRequest.readyState === 4 && httpRequest.status === 200) { | ||||
|                 if (httpRequest.responseText.startsWith("<img")) { | ||||
|                     textarea.innerHTML = httpRequest.responseText | ||||
|                 } else { | ||||
|                     textarea.innerText = httpRequest.responseText.replaceAll("\n", "") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function textInput() { | ||||
|         lastUpdate = Date.now() | ||||
|     } | ||||
|  | ||||
|     document.querySelector('#textarea').addEventListener('paste', function (e) { | ||||
|         var cbd = e.clipboardData; | ||||
|         var ua = window.navigator.userAgent; | ||||
|         // 如果是 Safari 直接 return | ||||
|         if (!(e.clipboardData && e.clipboardData.items)) { | ||||
|             return; | ||||
|         } | ||||
|         // Mac平台下Chrome49版本以下 复制Finder中的文件的Bug Hack掉 | ||||
|         if (cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" && | ||||
|             cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" && | ||||
|             ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49) { | ||||
|             return; | ||||
|         } | ||||
|         for (var i = 0; i < cbd.items.length; i++) { | ||||
|             var item = cbd.items[i]; | ||||
|             if (item.kind === "file") { | ||||
|                 var blob = item.getAsFile(); | ||||
|                 if (blob.size === 0) { | ||||
|                     return; | ||||
|                 } | ||||
|                 var reader = new FileReader(); | ||||
|                 var imgs = new Image(); | ||||
|                 imgs.file = blob; | ||||
|                 reader.onload = (function (aImg) { | ||||
|                     return function (e) { | ||||
|                         aImg.src = e.target.result; | ||||
|                         // chrome下有Bug显示两张图片,此处为兼容处理 | ||||
|                         let imgary = $('#textarea > img') | ||||
|                         if (imgary.length > 1) { | ||||
|                             imgary.eq(-1).remove() | ||||
|                         } | ||||
|                     }; | ||||
|                 })(imgs); | ||||
|                 reader.readAsDataURL(blob); | ||||
|                 document.querySelector("#textarea").innerHTML = "" | ||||
|                 document.querySelector('#textarea').appendChild(imgs); | ||||
|                 lastUpdate = Date.now() | ||||
|             } | ||||
|         } | ||||
|     }, false); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										6
									
								
								target/classes/static/jquery.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								target/classes/static/jquery.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										8
									
								
								target/classes/static/waves.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								target/classes/static/waves.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| /*! | ||||
|  * Waves v0.7.2 | ||||
|  * http://fian.my.id/Waves  | ||||
|  *  | ||||
|  * Copyright 2014 Alfiana E. Sibuea and other contributors  | ||||
|  * Released under the MIT license  | ||||
|  * https://github.com/fians/Waves/blob/master/LICENSE  | ||||
|  */.waves-effect{position:relative;cursor:pointer;display:inline-block;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.waves-effect .waves-ripple{position:absolute;border-radius:50%;width:100px;height:100px;margin-top:-50px;margin-left:-50px;opacity:0;background:rgba(0,0,0,.2);background:-webkit-radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);background:-o-radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);background:-moz-radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);background:radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);-webkit-transition:all .5s ease-out;-moz-transition:all .5s ease-out;-o-transition:all .5s ease-out;transition:all .5s ease-out;-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform,opacity;-o-transition-property:-o-transform,opacity;transition-property:transform,opacity;-webkit-transform:scale(0) translate(0,0);-moz-transform:scale(0) translate(0,0);-ms-transform:scale(0) translate(0,0);-o-transform:scale(0) translate(0,0);transform:scale(0) translate(0,0);pointer-events:none}.waves-effect.waves-light .waves-ripple{background:rgba(255,255,255,.4);background:-webkit-radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%);background:-o-radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%);background:-moz-radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%);background:radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%)}.waves-effect.waves-classic .waves-ripple{background:rgba(0,0,0,.2)}.waves-effect.waves-classic.waves-light .waves-ripple{background:rgba(255,255,255,.4)}.waves-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.waves-button,.waves-circle{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0);-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.waves-button,.waves-button:hover,.waves-button:visited,.waves-button-input{white-space:nowrap;vertical-align:middle;cursor:pointer;border:none;outline:0;color:inherit;background-color:transparent;font-size:1em;line-height:1em;text-align:center;text-decoration:none;z-index:1}.waves-button{padding:.85em 1.1em;border-radius:.2em}.waves-button-input{margin:0;padding:.85em 1.1em}.waves-input-wrapper{border-radius:.2em;vertical-align:bottom}.waves-input-wrapper.waves-button{padding:0}.waves-input-wrapper .waves-button-input{position:relative;top:0;left:0;z-index:1}.waves-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%}.waves-float{-webkit-mask-image:none;-webkit-box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);-webkit-transition:all 300ms;-moz-transition:all 300ms;-o-transition:all 300ms;transition:all 300ms}.waves-float:active{-webkit-box-shadow:0 8px 20px 1px rgba(0,0,0,.3);box-shadow:0 8px 20px 1px rgba(0,0,0,.3)}.waves-block{display:block}a.waves-effect .waves-ripple{z-index:-1} | ||||
							
								
								
									
										10
									
								
								target/classes/static/waves.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								target/classes/static/waves.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								target/classes/static/waves.min.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								target/classes/static/waves.min.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										3
									
								
								target/maven-archiver/pom.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								target/maven-archiver/pom.properties
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| artifactId=temp-clipboard | ||||
| groupId=com.pomelotea | ||||
| version=1.0-SNAPSHOT | ||||
							
								
								
									
										101
									
								
								temp-clipboard.iml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								temp-clipboard.iml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> | ||||
|   <component name="FacetManager"> | ||||
|     <facet type="web" name="Web"> | ||||
|       <configuration> | ||||
|         <webroots /> | ||||
|         <sourceRoots> | ||||
|           <root url="file://$MODULE_DIR$/src/main/kotlin" /> | ||||
|           <root url="file://$MODULE_DIR$/src/main/resources" /> | ||||
|         </sourceRoots> | ||||
|       </configuration> | ||||
|     </facet> | ||||
|     <facet type="Spring" name="Spring"> | ||||
|       <configuration /> | ||||
|     </facet> | ||||
|     <facet type="kotlin-language" name="Kotlin"> | ||||
|       <configuration version="5" platform="JVM 1.8" allPlatforms="JVM [1.8]" useProjectSettings="false"> | ||||
|         <compilerSettings> | ||||
|           <option name="additionalArguments" value="-java-parameters" /> | ||||
|         </compilerSettings> | ||||
|         <compilerArguments> | ||||
|           <stringArguments> | ||||
|             <stringArg name="jvmTarget" arg="1.8" /> | ||||
|             <stringArg name="apiVersion" arg="1.7" /> | ||||
|             <stringArg name="languageVersion" arg="1.7" /> | ||||
|           </stringArguments> | ||||
|           <arrayArguments> | ||||
|             <arrayArg name="pluginClasspaths" /> | ||||
|             <arrayArg name="pluginOptions" /> | ||||
|           </arrayArguments> | ||||
|         </compilerArguments> | ||||
|       </configuration> | ||||
|     </facet> | ||||
|   </component> | ||||
|   <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> | ||||
|     <output url="file://$MODULE_DIR$/target/classes" /> | ||||
|     <output-test url="file://$MODULE_DIR$/target/test-classes" /> | ||||
|     <content url="file://$MODULE_DIR$"> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" isTestSource="true" /> | ||||
|       <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" /> | ||||
|       <excludeFolder url="file://$MODULE_DIR$/target" /> | ||||
|     </content> | ||||
|     <orderEntry type="inheritedJdk" /> | ||||
|     <orderEntry type="sourceFolder" forTests="false" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-junit5:1.7.0" level="project" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test:1.7.0" level="project" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.7.2" level="project" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.7.2" level="project" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.8.2" level="project" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.7.2" level="project" /> | ||||
|     <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.2" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.7.0" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.5.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.5.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.5.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.5.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-core:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.28" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.5.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.12.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.12.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.5.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.52" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.52" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.52" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-web:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-beans:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-aop:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-context:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework:spring-expression:5.3.9" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.alibaba:fastjson:2.0.7" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.alibaba.fastjson2:fastjson2-extension:2.0.7" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.alibaba.fastjson2:fastjson2:2.0.7" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.parkingwang:okhttp3-loginterceptor:0.5" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:4.2.2" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.squareup.okio:okio:2.2.2" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-kotlin:2.12.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.12.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.12.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.12.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-reflect:1.7.0" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.5.4" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.5" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.5" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.32" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.14.1" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.14.1" level="project" /> | ||||
|     <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.32" level="project" /> | ||||
|   </component> | ||||
| </module> | ||||
		Reference in New Issue
	
	Block a user
	 jimlee
					jimlee