mirror of
https://gitee.com/bookshelfplus/bookshelfplus
synced 2025-09-21 01:10:39 +08:00
添加网盘分享链接解析页面;只有对象存储的文件才显示刷新状态按钮;一些前端小调整和小优化
This commit is contained in:
93
README.md
93
README.md
@@ -718,6 +718,12 @@ node ./bookshelfplus-frontend/cleanup.js
|
||||
|
||||
### Nginx 无法启动
|
||||
|
||||
【问题特征】启动时,报如下错误:
|
||||
|
||||
```bash
|
||||
nginx: [emerg] CreateFile() "xxxxxxx/nginx.conf" failed (1113: No mapping for the Unicode character exists in the target multi-byte code page)
|
||||
```
|
||||
|
||||
【问题原因】
|
||||
|
||||
nginx启动目录不能包含中文,否则无法启动
|
||||
@@ -778,13 +784,96 @@ chmod -R 755 bookshelf.plus/
|
||||
检查一下
|
||||
|
||||
- 云服务器的“安全组”(不同厂商有不同的叫法)中是否开放了80端口
|
||||
- nginx 配置是否正确(主要看 server_name, listen, location 等配置)
|
||||
- nginx 配置是否正确(主要看 `server_name`, `listen`, `location` 等配置)
|
||||
|
||||
|
||||
|
||||
### 项目启动后,DruidDataSource 疯狂报错 create connection SQLException, ...
|
||||
|
||||
【错误原因】数据库访问不了
|
||||
|
||||
【解决方法】
|
||||
|
||||
检查一下数据库是否开启,配置文件中的数据库配置是否正确,以及配置的 MySQL 用户是否有访问权限
|
||||
|
||||
【错误日志】
|
||||
|
||||
```bash
|
||||
2022-04-25 00:34:32.726 ERROR 18344 --- [reate-335731589] com.alibaba.druid.pool.DruidDataSource : create connection SQLException, url: jdbc:mysql://127.0.0.1:3306/bookshelfplus?useSSL=false&serverTimezone=Asia/Shanghai, errorCode 0, state 08S01
|
||||
|
||||
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
|
||||
|
||||
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
|
||||
at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:829) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:449) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:242) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1657) ~[druid-1.2.8.jar:1.2.8]
|
||||
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1723) ~[druid-1.2.8.jar:1.2.8]
|
||||
at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2838) ~[druid-1.2.8.jar:1.2.8]
|
||||
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
|
||||
|
||||
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
|
||||
at sun.reflect.GeneratedConstructorAccessor59.newInstance(Unknown Source) ~[na:na]
|
||||
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_201]
|
||||
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_201]
|
||||
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:89) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.NativeSession.connect(NativeSession.java:120) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:949) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:819) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
... 6 common frames omitted
|
||||
Caused by: java.net.ConnectException: Connection refused: connect
|
||||
at java.net.DualStackPlainSocketImpl.connect0(Native Method) ~[na:1.8.0_201]
|
||||
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) ~[na:1.8.0_201]
|
||||
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_201]
|
||||
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_201]
|
||||
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_201]
|
||||
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_201]
|
||||
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_201]
|
||||
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_201]
|
||||
at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:156) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:63) ~[mysql-connector-java-8.0.28.jar:8.0.28]
|
||||
... 9 common frames omitted
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 项目启动报错 Error parsing HTTP request header
|
||||
|
||||
【问题原因】客户端没有按照规范发HTTP请求
|
||||
|
||||
【解决方法】不影响项目运行,无需修改,可忽略该错误
|
||||
|
||||
【错误日志】
|
||||
|
||||
```bash
|
||||
2022-04-25 00:19:43.698 INFO 434027 --- [nio-8090-exec-1] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
|
||||
Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
|
||||
|
||||
java.lang.IllegalArgumentException: Invalid character found in method name [0x030x000x00/*0xe00x000x000x000x000x00Cookie: ]. HTTP method names must be tokens
|
||||
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:419) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:271) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
|
||||
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 其他问题
|
||||
|
||||
以上仅列出了部分常见问题,如果您没有找到相关解决方法,可以在 GitHub 仓库中创建一个 issue。提问时请注意要尽可能详细地描述问题,以及社区提问基本礼仪。
|
||||
以上仅列出了部分常见问题,如果您没有找到相关解决方法,可以在 Gitee 或 GitHub 仓库中创建一个 issue。提问时请注意要尽可能详细地描述问题,以及社区提问基本礼仪。
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,59 @@
|
||||
function getNetdiskShareDetails(shareText) {
|
||||
var result = {
|
||||
success: false,
|
||||
url: null,
|
||||
pwd: "",
|
||||
platform: null
|
||||
};
|
||||
try {
|
||||
result.url = shareText.match(/https?:\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g)[0];
|
||||
var pwdRegExpResult = shareText.match(/提取码[:|:] *(.*)[ |\n]?/); //.match(/提取码[:|:] *(.*?)[ |\n]?/);
|
||||
// console.log(shareText, pwdRegExpResult);
|
||||
// console.log("--------")
|
||||
// return;
|
||||
result.pwd = pwdRegExpResult && pwdRegExpResult.length > 1 ? pwdRegExpResult[1] : "";
|
||||
result.platform = result.url.indexOf("pan.baidu.com") > -1
|
||||
? { display: "百度网盘", name: "BAIDU_NETDISK" }
|
||||
: (result.url.indexOf("aliyundrive.com") > -1
|
||||
? { display: "阿里云盘", name: "ALIYUN_DRIVE" }
|
||||
: { display: null, name: null }
|
||||
);
|
||||
if (!result.platform || !result.platform.name) {
|
||||
throw new Exception("error");
|
||||
}
|
||||
result.success = true;
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
// console.log(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// // 百度网盘(手机版)有密码
|
||||
// getNetdiskShareDetails(`--来自百度网盘超级会员V3的分享
|
||||
// hi,这是我用百度网盘分享的内容~复制这段内容打开「百度网盘」APP即可获取
|
||||
// 链接:https://pan.baidu.com/s/1cxv2Rw5WgXrnE-kfyfkpxA?pwd=k2hk
|
||||
// 提取码:k2hk`);
|
||||
|
||||
// // 百度网盘(电脑版)有密码
|
||||
// getNetdiskShareDetails(`链接:https://pan.baidu.com/s/1YBeqYwrka7Z9G0H0q0GO_w?pwd=60va
|
||||
// 提取码:60va
|
||||
// --来自百度网盘超级会员V3的分享`);
|
||||
|
||||
// // 百度网盘无密码
|
||||
// getNetdiskShareDetails(`链接:https://pan.baidu.com/s/1YBeqYwrka7Z9G0H0q0GO_w?pwd=60va`);
|
||||
|
||||
// // 阿里云盘有密码
|
||||
// getNetdiskShareDetails(`「实战Nginx.pdf」https://www.aliyundrive.com/s/pquxbpPfj2u 提取码: en86
|
||||
// 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。`);
|
||||
|
||||
// // 阿里云盘无密码
|
||||
// getNetdiskShareDetails(`「ZenTaoPMS.16.4.win64.exe」https://www.aliyundrive.com/s/aZLhoqNFyiv
|
||||
// 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。`);
|
||||
|
||||
// // 其他情况
|
||||
// getNetdiskShareDetails(`非链接`);
|
||||
// getNetdiskShareDetails(`其他的链接https://www.baidu.com/s?wd=60va dsadsads`);
|
||||
// getNetdiskShareDetails(`链接:https://pan.woshijiade.com/s/1YBeqYwrka7Z9G0H0q0GO_w?pwd=60va
|
||||
// 提取码:60vas`);
|
@@ -126,6 +126,11 @@ router.get('/dashboard/:group/:page/:subpage?', function (req, res) {
|
||||
baseTemplate: "table",
|
||||
pageTemplate: "FileManage",
|
||||
childPage: {
|
||||
"upload": {
|
||||
title: "上传文件",
|
||||
baseTemplate: "blank",
|
||||
pageTemplate: "FileManage_Upload",
|
||||
},
|
||||
"detail": {
|
||||
title: "文件详情",
|
||||
baseTemplate: "blank",
|
||||
@@ -141,10 +146,10 @@ router.get('/dashboard/:group/:page/:subpage?', function (req, res) {
|
||||
baseTemplate: "form",
|
||||
pageTemplate: "FileManage_ObjectManage_Detail",
|
||||
},
|
||||
"upload": {
|
||||
title: "上传文件",
|
||||
"get-share-url": {
|
||||
title: "粘贴网盘分享链接",
|
||||
baseTemplate: "blank",
|
||||
pageTemplate: "FileManage_Upload",
|
||||
pageTemplate: "FileManage_ObjectManage_getShareUrl",
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@@ -78,7 +78,7 @@
|
||||
</span>`,
|
||||
管理: `<span style="margin: 0 auto;">
|
||||
<a href="<%= pageUrl %>detail?id=${element.id}">详情</a>
|
||||
<a href="<%= pageUrl %>object-detail?fileId=${element.id}">添加网盘链接</a><br>
|
||||
<a href="<%= pageUrl %>get-share-url?fileId=${element.id}">添加网盘链接</a><br>
|
||||
<a href="javascript:deleteFile(${element.id});">删除(TODO)</a>
|
||||
</span>`,
|
||||
})
|
||||
|
@@ -84,18 +84,21 @@
|
||||
items.push(`<tr>
|
||||
<td>${item.id}</td>
|
||||
<td>${item.storageMediumForDisplay}</td>
|
||||
<td style="font-size: 12px;">${item.filePath}</td>
|
||||
<td style="font-size: 12px; max-width: 120px;">
|
||||
<span class="overflow-omit">${item.filePath}</span>
|
||||
</td>
|
||||
<td>${item.filePwd}</td>
|
||||
<td>${item.fileShareCode}</td>
|
||||
<td>${(item.uploadStatus ? item.uploadStatus : "<span style='color: grey; font-weight: bold;'>未知</span>")
|
||||
.replace("SUCCESS", "<span style='color: green; font-weight: bold;'>成功</span>")
|
||||
.replace("UPLOADING", "<span style='color: orange; font-weight: bold;'>正在上传</span>")
|
||||
.replace("NOT_EXIST", "<span style='color: red; font-weight: bold;'>不存在</span>")}</td>
|
||||
<td><a href="<%= pageUrl %>../object-detail?id=${item.id}&fileId=${item.fileId}">修改</a></td>
|
||||
</tr>`);
|
||||
}
|
||||
document.getElementById("file-object-container").innerHTML =
|
||||
`<a href="<%= pageUrl %>../object-detail?fileId=${fileId}">添加网盘链接</a><br>
|
||||
<table border="1" style="margin: 0 auto;">
|
||||
`<a href="<%= pageUrl %>../get-share-url?fileId=${fileId}">添加网盘链接</a><br>
|
||||
<table border="1" style="margin: 0 auto; width: 100%;">
|
||||
<tr>
|
||||
<th>文件对象Id</th>
|
||||
<th>存储介质</th>
|
||||
@@ -103,6 +106,7 @@
|
||||
<th>文件密码</th>
|
||||
<th>提取码</th>
|
||||
<th>状态</th>
|
||||
<th>管理</th>
|
||||
</tr>
|
||||
${items.join("")}
|
||||
</table>`;
|
||||
|
@@ -48,8 +48,8 @@
|
||||
.replace("UPLOADING", "<span style='color: orange; font-weight: bold;'>正在上传</span>")
|
||||
.replace("NOT_EXIST", "<span style='color: red; font-weight: bold;'>不存在</span>")}`,
|
||||
管理: `<span span class="overflow-omit" style="margin: 0 auto;">
|
||||
<a href="javascript:refreshFileObjectStatus(${element.id});">刷新状态</a>
|
||||
<a href="<%= pageUrl %>../object-detail?id=${element.id}">修改(TODO)</a>
|
||||
<a href="javascript:refreshFileObjectStatus(${element.id});" style="${element.storageMedium == "QCLOUD_COS" ? "" : "display: none;"}">刷新状态</a>
|
||||
<a href="<%= pageUrl %>../object-detail?id=${element.id}&fileId=${element.fileId}">修改</a>
|
||||
<a href="javascript:deleteFileObject(${element.id});">删除</a>
|
||||
</span >`,
|
||||
})
|
||||
|
@@ -1,6 +1,9 @@
|
||||
<div class="show-only-modify" style="text-align: center;">
|
||||
上传状态:<span id="upload-status"></span>
|
||||
</div>
|
||||
<script>
|
||||
// 如果传入了 id 那么就是修改文件对象,否则就是添加文件对象
|
||||
var params = getParams()
|
||||
var params = getParams();
|
||||
var fileObjectId = params.id;
|
||||
var fileId = params.fileId;
|
||||
if (!fileId) {
|
||||
@@ -12,6 +15,7 @@
|
||||
if (!isModify) {
|
||||
// 新增文件对象
|
||||
fileObjectId = 0;
|
||||
$(".show-only-modify").hide();
|
||||
} else {
|
||||
// 修改文件对象
|
||||
}
|
||||
@@ -25,7 +29,10 @@
|
||||
success: function (data) {
|
||||
console.log(data);
|
||||
alert(isModify ? "修改成功!" : "添加成功!");
|
||||
history.go(-1);
|
||||
if (params.referrer)
|
||||
location.replace(params.referrer);
|
||||
else
|
||||
history.go(-1);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -65,6 +72,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是修改文件对象,那么显示文件上传状态
|
||||
$("#upload-status").html(fileObjectDetail.uploadStatus || "");
|
||||
|
||||
return [
|
||||
// 必须设置 id, name
|
||||
@@ -74,7 +83,7 @@
|
||||
"attr": {
|
||||
"id": "storageMedium",
|
||||
"name": "storageMedium",
|
||||
"value": fileObjectDetail.storageMedium || "",
|
||||
"value": params.disk || fileObjectDetail.storageMedium || "",
|
||||
...modifyDisabledAttr
|
||||
},
|
||||
"label": {
|
||||
@@ -116,7 +125,7 @@
|
||||
"id": "filePath",
|
||||
"name": "filePath",
|
||||
"placeholder": "文件对象链接或路径",
|
||||
"value": fileObjectDetail.filePath || "",
|
||||
"value": params.url || fileObjectDetail.filePath || "",
|
||||
...filePathDisabledAttr // 如果是对象存储,那么就不允许编辑
|
||||
},
|
||||
"label": {
|
||||
@@ -171,7 +180,7 @@
|
||||
"id": "fileShareCode",
|
||||
"name": "fileShareCode",
|
||||
"placeholder": "提取码",
|
||||
"value": fileObjectDetail.fileShareCode || "",
|
||||
"value": params.pwd || fileObjectDetail.fileShareCode || "",
|
||||
},
|
||||
"label": {
|
||||
"value": "提取码",
|
||||
|
@@ -0,0 +1,78 @@
|
||||
<style>
|
||||
#sharecode_input {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#next-button {
|
||||
margin-top: 30px;
|
||||
}
|
||||
</style>
|
||||
<input id="sharecode_input" placeholder="请在此处粘贴网盘分享链接">
|
||||
<input id="paste-button" value="点击粘贴" type="button" onclick="pasteText();">
|
||||
<input id="next-button" value="直接前往添加" type="button" onclick="location.replace(redirectUrl);">
|
||||
<!-- 获取参数 -->
|
||||
<script src="/assets/javascripts/getParams.js"></script>
|
||||
<script>
|
||||
var requestParams = getParams();
|
||||
var fileId = Number(requestParams["fileId"]) ?? "";
|
||||
if (fileId === "")
|
||||
history.go(-1);
|
||||
console.log(fileId);
|
||||
</script>
|
||||
|
||||
<!-- 获取网盘分享链接 -->
|
||||
<script src="/assets/javascripts/dashboard/netdiskShareStringUtils.js"></script>
|
||||
<script>
|
||||
var redirectUrl = `<%= pageUrl %>../object-detail?fileId=${fileId}&referrer=${encodeURIComponent(document.referrer)}`
|
||||
$(document).ready(function () {
|
||||
$("#sharecode_input").on({
|
||||
// copy: function () {
|
||||
// alert('复制');
|
||||
// },
|
||||
paste: onPaste,
|
||||
// cut: function () {
|
||||
// alert('剪切');
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
// input 粘贴事件
|
||||
function onPaste() {
|
||||
// alert('粘贴');
|
||||
|
||||
// 直接获取的话,获取到的值还是粘贴之前的,所以这里使用了 setTimeout
|
||||
// console.log(this.value);
|
||||
setTimeout(function (val) {
|
||||
var inputValue = $("#sharecode_input").val();
|
||||
console.log("用户输入", inputValue);
|
||||
var result = getNetdiskShareDetails(inputValue);
|
||||
console.log(result);
|
||||
if (result && result.success) {
|
||||
redirectUrl += `&disk=${result.platform.name}&url=${encodeURIComponent(result.url)}&pwd=${result.pwd}`
|
||||
} else {
|
||||
if (!confirm("未检测到网盘分享链接,是否直接跳转?"))
|
||||
return;
|
||||
}
|
||||
// 跳转
|
||||
console.log("将要跳转", redirectUrl);
|
||||
location.replace(redirectUrl);
|
||||
}, 1)
|
||||
}
|
||||
|
||||
// 点击粘贴按钮
|
||||
function pasteText() {
|
||||
if (!navigator.clipboard) {
|
||||
alert("浏览器不支持读取剪切板,请手动粘贴!");
|
||||
return;
|
||||
}
|
||||
navigator.clipboard.readText().then(text => {
|
||||
console.log("剪切板内容:" + text);
|
||||
$("#sharecode_input").val(text);
|
||||
onPaste();
|
||||
}).catch(err => {
|
||||
console.error('Failed to read clipboard contents: ', err);
|
||||
alert("读取剪切板失败,请手动粘贴!");
|
||||
});
|
||||
}
|
||||
</script>
|
Reference in New Issue
Block a user