初始化

This commit is contained in:
jimlee 2023-01-10 17:11:39 +08:00
parent 8030d31753
commit aab0134c8e
28 changed files with 1175 additions and 0 deletions

155
pom.xml Normal file
View 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>

View 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()))
}

File diff suppressed because one or more lines are too long

View 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
}
}

View 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

Binary file not shown.

View File

@ -0,0 +1,10 @@
server:
port: 8081
spring:
servlet:
multipart:
max-request-size: 100MB
max-file-size: 100MB
application:
name: 临时粘贴板

View 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>

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -0,0 +1,10 @@
server:
port: 8081
spring:
servlet:
multipart:
max-request-size: 100MB
max-file-size: 100MB
application:
name: 临时粘贴板

View 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

File diff suppressed because one or more lines are too long

8
target/classes/static/waves.min.css vendored Normal file
View 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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
artifactId=temp-clipboard
groupId=com.pomelotea
version=1.0-SNAPSHOT

101
temp-clipboard.iml Normal file
View 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>

2
upload.sh Normal file
View File

@ -0,0 +1,2 @@
mvn clean package -DskipTests=true
scp target/temp-clipboard-1.0-SNAPSHOT-executable.jar sweetless@47.102.204.44:~/clipboard/