mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-05-27 16:57:28 +00:00
Compare commits
8 Commits
b967c7a1bb
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8582290db3 | ||
|
|
5ff33d7c58 | ||
|
|
0cfb69a240 | ||
|
|
110a9beda4 | ||
|
|
fd6a3f5929 | ||
|
|
82ad6ec427 | ||
|
|
1bfc7c960d | ||
|
|
332f49f483 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -41,7 +41,9 @@ gradlew.bat
|
||||
unused.txt
|
||||
/web-service/src/main/generated/
|
||||
/db
|
||||
/netdisk-fast-download/
|
||||
/webroot/nfd-front/
|
||||
/netdisk-fast-download/webroot/nfd-front/
|
||||
package-lock.json
|
||||
|
||||
# Maven generated files
|
||||
|
||||
48
README.md
48
README.md
@@ -29,7 +29,8 @@ QQ交流群:1017480890
|
||||
[API接入](https://nfdparser.apifox.cn/)
|
||||
[公益解析,lz站](https://lz.qaiu.top)
|
||||
[公益解析,lz0站](https://lz0.qaiu.top)
|
||||
[专业版189站,注册体验](https://189.qaiu.top)
|
||||
[专业版](https://189.qaiu.top)
|
||||
|
||||
|
||||
## 快速开始
|
||||
命令行下载分享文件:
|
||||
@@ -58,7 +59,7 @@ https://nfd-parser.github.io/nfd-preview/preview.html?src=https%3A%2F%2Flz.qaiu.
|
||||
|
||||
**注意⚠️小飞机解析有IP限制,多数云服务商的大陆IP会被拦截(可以自行配置代理),和本程序无关**
|
||||
**注意⚠️收到很多用户反馈,小飞机近期封号频繁,请尽可能选择其他网盘分享**
|
||||
**注意⚠️请不要过度依赖 lz.qaiu.top,建议本地搭建或者云服务器自行搭建。请求量过多的话服务器可能会被云盘厂商限制,遇到解析失败的分享链接不要着急提issues,请先检查分享是否有效,** [lz站](https://lz.qaiu.top) 和 [lz0](https://lz0.qaiu.top) 不支持大文件,请使用 [189站](https://189.qaiu.top) 注册体验。
|
||||
**注意⚠️请不要过度依赖 lz.qaiu.top,建议本地搭建或者云服务器自行搭建。请求量过多的话服务器可能会被云盘厂商限制,遇到解析失败的分享链接不要着急提issues,请先检查分享是否有效。**
|
||||
|
||||
## 网盘支持情况:
|
||||
> 20230905 奶牛云直链做了防盗链,需加入请求头:Referer: https://cowtransfer.com/
|
||||
@@ -90,17 +91,10 @@ https://nfd-parser.github.io/nfd-preview/preview.html?src=https%3A%2F%2Flz.qaiu.
|
||||
- [WPS云文档-pwps](https://www.kdocs.cn/)
|
||||
- [汽水音乐-qishui_music](https://music.douyin.com/qishui/)
|
||||
- [咪咕音乐-migu](https://music.migu.cn/)
|
||||
- [一刻相册-baidu_photo](https://photo.baidu.com/)
|
||||
- Google云盘-pgd
|
||||
- Onedrive-pod
|
||||
- Dropbox-pdp
|
||||
- iCloud-pic
|
||||
### 专属版提供
|
||||
- [夸克云盘-qk](https://pan.quark.cn/)
|
||||
- [UC云盘-uc](https://fast.uc.cn/)
|
||||
- [移动云盘-p139](https://yun.139.com/)
|
||||
- [联通云盘-pwo](https://pan.wo.cn/)
|
||||
- [天翼云盘-p189](https://cloud.189.cn/)
|
||||
|
||||
## API接口
|
||||
|
||||
@@ -332,10 +326,9 @@ json返回数据格式示例:
|
||||
| 网盘名称 | 免登陆下载分享 | 加密分享 | 初始网盘空间 | 单文件大小限制 |
|
||||
|-------------|---------|----------|-----------|-----------------|
|
||||
| 蓝奏云 | √ | √ | 不限空间 | 100M |
|
||||
| 奶牛快传 | √ | X | 10G | 不限大小 |
|
||||
| 移动云云空间(个人版) | √ | √(密码可忽略) | 5G(个人) | 不限大小 |
|
||||
| 小飞机网盘 | √ | √(密码可忽略) | 10G | 不限大小 |
|
||||
| 360亿方云 | √ | √(密码可忽略) | 100G(须实名) | 不限大小 |
|
||||
| 小飞机网盘 | √ | √ | 10G | 不限大小 |
|
||||
| 360亿方云 | √ | √ | 100G(须实名) | 不限大小 |
|
||||
| 123云盘 | √ | √ | 2T | 100G(>100M需要登录) |
|
||||
| 文叔叔 | √ | √ | 10G | 5GB |
|
||||
| WPS云文档 | √ | X | 5G(免费) | 10M(免费)/2G(会员) |
|
||||
@@ -494,23 +487,6 @@ auths:
|
||||
|
||||
**注意:** 目前仅支持 123(ye)的认证配置。
|
||||
|
||||
## 开发计划
|
||||
### v0.1.8~v0.1.9 ✓
|
||||
- API添加文件信息(专属版/开源版)
|
||||
- 目录解析(专属版/开源版)
|
||||
- 文件预览功能(专属版/开源版)
|
||||
- 文件夹预览功能(开源版)
|
||||
- 友好的错误提示和一键反馈功能(开源版)
|
||||
- 带cookie/token/username/pwd参数解析大文件(专属版)
|
||||
### v0.2.x
|
||||
- web后台管理--认证配置/分享链接管理(开源版/专属版)
|
||||
- 123/小飞机/蓝奏优享等大文件解析(开源版)
|
||||
- 直链分享(开源版/专属版)
|
||||
- aria2/idm+/curl/wget链接生成(开源版/专属版)
|
||||
- IP限流配置(开源版/专属版)
|
||||
- refere防盗链,API鉴权防盗链(专属版)
|
||||
- 123/小飞机/蓝奏优享/蓝奏文件夹解析API,天翼云盘/移动云盘文件夹解析API(专属版)
|
||||
- 用户管理面板--营销推广系统(专属版)
|
||||
|
||||
**技术栈:**
|
||||
Jdk17+Vert.x4
|
||||
@@ -535,20 +511,6 @@ Core模块集成Vert.x实现类似spring的注解式路由API
|
||||
</p>
|
||||
|
||||
|
||||
### 关于赞助定制专属版
|
||||
1. 专属版提供对小飞机,蓝奏优享大文件解析的支持, 提供天翼云盘/移动云盘/联通云盘的解析支持。
|
||||
2. 可提供托管服务:包含部署服务和云服务器环境。
|
||||
3. 可提供功能定制开发。
|
||||
您可能需要提供一定的资金赞助支持定制专属版, 请添加以下任意一个联系方式详谈赞助模式:
|
||||
<p>qq: 197575894</p>
|
||||
<p>wechat: imcoding_</p>
|
||||
|
||||
<!--
|
||||

|
||||
|
||||
[手机端支付宝打赏跳转链接](https://qr.alipay.com/fkx01882dnoxxtjenhlxt53)
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -77,25 +78,13 @@ public class ReverseProxyVerticle extends AbstractVerticle {
|
||||
* @param proxyConf 代理配置
|
||||
*/
|
||||
private void handleProxyConf(JsonObject proxyConf) {
|
||||
// page404 path
|
||||
if (proxyConf.containsKey(
|
||||
|
||||
"page404")) {
|
||||
System.getProperty("user.dir");
|
||||
String path = proxyConf.getString("page404");
|
||||
if (StringUtils.isEmpty(path)) {
|
||||
proxyConf.put("page404", DEFAULT_PATH_404);
|
||||
} else {
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
if (!new File(System.getProperty("user.dir") + path).exists()) {
|
||||
proxyConf.put("page404", DEFAULT_PATH_404);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
proxyConf.put("page404", DEFAULT_PATH_404);
|
||||
// page404 path: 兼容不同启动目录(根目录或子模块目录)
|
||||
String configured404 = proxyConf.getString("page404");
|
||||
String resolved404 = resolveExistingPath(configured404, false);
|
||||
if (resolved404 == null) {
|
||||
resolved404 = resolveExistingPath(DEFAULT_PATH_404, false);
|
||||
}
|
||||
proxyConf.put("page404", resolved404 == null ? DEFAULT_PATH_404 : resolved404);
|
||||
|
||||
final HttpClient httpClient = VertxHolder.getVertxInstance().createHttpClient();
|
||||
Router proxyRouter = Router.router(vertx);
|
||||
@@ -180,7 +169,14 @@ public class ReverseProxyVerticle extends AbstractVerticle {
|
||||
|
||||
StaticHandler staticHandler;
|
||||
if (staticConf.containsKey("root")) {
|
||||
staticHandler = StaticHandler.create(staticConf.getString("root"));
|
||||
String configuredRoot = staticConf.getString("root");
|
||||
String resolvedRoot = resolveStaticRoot(configuredRoot);
|
||||
if (resolvedRoot != null) {
|
||||
staticHandler = StaticHandler.create(resolvedRoot);
|
||||
} else {
|
||||
LOGGER.warn("static root not found, fallback to configured path: {}", configuredRoot);
|
||||
staticHandler = StaticHandler.create(configuredRoot);
|
||||
}
|
||||
} else {
|
||||
staticHandler = StaticHandler.create();
|
||||
}
|
||||
@@ -253,4 +249,77 @@ public class ReverseProxyVerticle extends AbstractVerticle {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析配置路径: 优先绝对路径, 否则尝试 user.dir 和 user.dir/..。
|
||||
*/
|
||||
private String resolveExistingPath(String path, boolean directory) {
|
||||
if (StringUtils.isBlank(path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File directFile = new File(path);
|
||||
if (existsByType(directFile, directory)) {
|
||||
return directFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
String userDir = System.getProperty("user.dir");
|
||||
File inUserDir = new File(userDir, path);
|
||||
if (existsByType(inUserDir, directory)) {
|
||||
return inUserDir.getAbsolutePath();
|
||||
}
|
||||
|
||||
File inParentDir = new File(new File(userDir).getParentFile(), path);
|
||||
if (existsByType(inParentDir, directory)) {
|
||||
return inParentDir.getAbsolutePath();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* StaticHandler 只接受相对 web root,不接受以 / 开头的绝对路径。
|
||||
*/
|
||||
private String resolveStaticRoot(String path) {
|
||||
if (StringUtils.isBlank(path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File directFile = new File(path);
|
||||
if (existsByType(directFile, true)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
String userDir = System.getProperty("user.dir");
|
||||
File inUserDir = new File(userDir, path);
|
||||
if (existsByType(inUserDir, true)) {
|
||||
return relativizePath(new File(userDir), inUserDir);
|
||||
}
|
||||
|
||||
File userDirFile = new File(userDir);
|
||||
File parentDir = userDirFile.getParentFile();
|
||||
File inParentDir = parentDir == null ? null : new File(parentDir, path);
|
||||
if (existsByType(inParentDir, true)) {
|
||||
return relativizePath(userDirFile, inParentDir);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String relativizePath(File baseDir, File target) {
|
||||
try {
|
||||
Path basePath = baseDir.toPath().toAbsolutePath().normalize();
|
||||
Path targetPath = target.toPath().toAbsolutePath().normalize();
|
||||
return basePath.relativize(targetPath).toString().replace(File.separatorChar, '/');
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return target.getPath().replace(File.separatorChar, '/');
|
||||
}
|
||||
}
|
||||
|
||||
private boolean existsByType(File file, boolean directory) {
|
||||
if (file == null || !file.exists()) {
|
||||
return false;
|
||||
}
|
||||
return directory ? file.isDirectory() : file.isFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,12 +59,12 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<!-- Versions -->
|
||||
<vertx.version>4.5.22</vertx.version>
|
||||
<vertx.version>4.5.24</vertx.version>
|
||||
<org.reflections.version>0.10.2</org.reflections.version>
|
||||
<lombok.version>1.18.38</lombok.version>
|
||||
<slf4j.version>2.0.5</slf4j.version>
|
||||
<slf4j.version>2.0.16</slf4j.version>
|
||||
<commons-lang3.version>3.18.0</commons-lang3.version>
|
||||
<jackson.version>2.14.2</jackson.version>
|
||||
<jackson.version>2.18.6</jackson.version>
|
||||
<logback.version>1.5.19</logback.version>
|
||||
<junit.version>4.13.2</junit.version>
|
||||
</properties>
|
||||
|
||||
@@ -99,7 +99,8 @@ public class PodTool extends PanBase {
|
||||
Matcher matcher1 =
|
||||
Pattern.compile("\"downloadUrl\":\"(?<url>https?://[^\s\"]+)").matcher(body);
|
||||
if (matcher1.find()) {
|
||||
complete(matcher1.group("url"));
|
||||
// 响应体是 JSON 文本,URL 中的 '&' 被转义为 \u0026,需要反转义
|
||||
complete(unescapeJsonUnicode(matcher1.group("url")));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
@@ -134,6 +135,34 @@ public class PodTool extends PanBase {
|
||||
throw new RuntimeException("URL匹配失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 反转义 JSON 响应文本中残留的 Unicode 转义序列(主要是 \u0026 -> &)。
|
||||
* 主分支通过正则直接从 JSON 原文抠 URL,未经过 JSON 解析器,需要手动还原。
|
||||
*/
|
||||
private String unescapeJsonUnicode(String s) {
|
||||
if (s == null || s.indexOf("\\u") < 0) {
|
||||
return s;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(s.length());
|
||||
int i = 0;
|
||||
while (i < s.length()) {
|
||||
char c = s.charAt(i);
|
||||
if (c == '\\' && i + 5 < s.length() && s.charAt(i + 1) == 'u') {
|
||||
try {
|
||||
int cp = Integer.parseInt(s.substring(i + 2, i + 6), 16);
|
||||
sb.append((char) cp);
|
||||
i += 6;
|
||||
continue;
|
||||
} catch (NumberFormatException ignored) {
|
||||
// 非法转义按原样保留
|
||||
}
|
||||
}
|
||||
sb.append(c);
|
||||
i++;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
private String matcherToken(String html) {
|
||||
// 正则表达式来匹配 inputElem.value 中的 Token
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -26,13 +26,13 @@
|
||||
<packageDirectory>${project.basedir}/web-service/target/package</packageDirectory>
|
||||
|
||||
<!-- Vert.x 4.5.24 已包含安全修复,无需单独指定 Netty 版本 -->
|
||||
<vertx.version>4.5.14</vertx.version>
|
||||
<vertx.version>4.5.24</vertx.version>
|
||||
<org.reflections.version>0.10.2</org.reflections.version>
|
||||
<lombok.version>1.18.38</lombok.version>
|
||||
<slf4j.version>2.0.16</slf4j.version>
|
||||
<commons-lang3.version>3.18.0</commons-lang3.version>
|
||||
<commons-beanutils2.version>2.0.0</commons-beanutils2.version>
|
||||
<jackson.version>2.18.2</jackson.version>
|
||||
<jackson.version>2.18.6</jackson.version>
|
||||
<!-- Logback 最新稳定版 -->
|
||||
<logback.version>1.5.18</logback.version>
|
||||
<junit.version>4.13.2</junit.version>
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import { ElTree } from 'element-plus'
|
||||
import { ElTree, ElMessageBox } from 'element-plus'
|
||||
import { Splitpanes, Pane } from 'splitpanes'
|
||||
import 'splitpanes/dist/splitpanes.css'
|
||||
import fileTypeUtils from '@/utils/fileTypeUtils'
|
||||
@@ -677,7 +677,31 @@ export default {
|
||||
this.$message.success(`自动检测到 ${detected.type} ${detected.version}`)
|
||||
return true
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'未检测到本地下载器,是否切换为迅雷下载?',
|
||||
'下载器未检测到',
|
||||
{
|
||||
confirmButtonText: '使用迅雷',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
const thunderConfig = {
|
||||
...config,
|
||||
downloaderType: 'thunder',
|
||||
rpcUrl: ''
|
||||
}
|
||||
saveConfig(thunderConfig)
|
||||
const thunderResult = await testConnection()
|
||||
if (thunderResult.connected) {
|
||||
this.$message.success('已切换并保存为迅雷下载器配置')
|
||||
return true
|
||||
}
|
||||
this.$message.error('已保存为迅雷配置,但未检测到迅雷客户端,请先启动迅雷')
|
||||
} catch {
|
||||
this.$message.error('下载器连接失败,请先在首页设置中配置下载器')
|
||||
}
|
||||
return false
|
||||
},
|
||||
async sendSingleToDownloader(file) {
|
||||
|
||||
@@ -73,9 +73,9 @@
|
||||
</div>
|
||||
<!-- 项目简介移到卡片内 -->
|
||||
<div class="project-intro">
|
||||
<div class="intro-title">NFD网盘直链解析0.2.1b3</div>
|
||||
<div class="intro-title">NFD网盘直链解析0.3.0</div>
|
||||
<div class="intro-desc">
|
||||
<div>支持网盘:蓝奏云、蓝奏云优享、小飞机盘、123云盘、奶牛快传、移动云空间、QQ邮箱云盘、QQ闪传等 <el-link style="color:#606cf5" href="https://github.com/qaiu/netdisk-fast-download?tab=readme-ov-file#%E7%BD%91%E7%9B%98%E6%94%AF%E6%8C%81%E6%83%85%E5%86%B5" target="_blank"> >> </el-link></div>
|
||||
<div>支持网盘:蓝奏云、蓝奏云优享、小飞机盘、123云盘、iCloud、移动云空间、联想乐云、QQ闪传等 <el-link style="color:#606cf5" href="https://github.com/qaiu/netdisk-fast-download?tab=readme-ov-file#%E7%BD%91%E7%9B%98%E6%94%AF%E6%8C%81%E6%83%85%E5%86%B5" target="_blank"> >> </el-link></div>
|
||||
<div>文件夹解析支持:蓝奏云、蓝奏云优享、小飞机盘、123云盘</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,8 +111,8 @@
|
||||
</el-input>
|
||||
|
||||
<p style="text-align: center">
|
||||
<el-button style="margin-left: 40px" @click="parseFile">解析文件</el-button>
|
||||
<el-button style="margin-left: 20px" @click="parseDirectory">解析目录</el-button>
|
||||
<el-button class="parse-action-btn" type="success" style="margin-left: 40px" @click="parseFile">解析文件</el-button>
|
||||
<el-button class="parse-action-btn" type="success" style="margin-left: 20px" @click="parseDirectory">解析目录</el-button>
|
||||
<el-button style="margin-left: 20px" @click="generateMarkdown">生成Markdown</el-button>
|
||||
<el-button style="margin-left: 20px" @click="generateQRCode">扫码下载</el-button>
|
||||
<el-button style="margin-left: 20px" @click="getStatistics">分享统计</el-button>
|
||||
@@ -592,7 +592,7 @@ import DirectoryTree from '@/components/DirectoryTree'
|
||||
import DownloadDialog from '@/components/DownloadDialog'
|
||||
import parserUrl from '../parserUrl1'
|
||||
import fileTypeUtils from '@/utils/fileTypeUtils'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { playgroundApi } from '@/utils/playgroundApi'
|
||||
import { testConnection, autoDetect, addDownload, getConfig, saveConfig } from '@/utils/downloaderService'
|
||||
|
||||
@@ -708,7 +708,9 @@ export default {
|
||||
downloadDialogVisible: false,
|
||||
downloadDialogInfo: null,
|
||||
// 目录解析支持的网盘列表
|
||||
directoryParseSupportedPans: []
|
||||
directoryParseSupportedPans: [],
|
||||
// 后端支持网盘列表(用于短格式 type:key@pwd 展开)
|
||||
panList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -1041,6 +1043,7 @@ export default {
|
||||
|
||||
// 验证输入
|
||||
validateInput() {
|
||||
this.normalizeShortcutInput()
|
||||
this.clearResults()
|
||||
|
||||
if (!this.link.startsWith("https://") && !this.link.startsWith("http://")) {
|
||||
@@ -1049,6 +1052,58 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 获取后端支持网盘列表
|
||||
async getPanList() {
|
||||
try {
|
||||
const response = await axios.get(`${this.baseAPI}/v2/getPanList`)
|
||||
const payload = response?.data
|
||||
const list = Array.isArray(payload)
|
||||
? payload
|
||||
: (Array.isArray(payload?.data) ? payload.data : [])
|
||||
if (list.length > 0) {
|
||||
this.panList = list
|
||||
}
|
||||
} catch (error) {
|
||||
// 静默失败:短格式解析会自动回退
|
||||
}
|
||||
},
|
||||
|
||||
// 按后端网盘列表展开短格式(type:key@pwd)
|
||||
expandShortFormat(text) {
|
||||
const raw = (text || '').trim()
|
||||
if (!raw) return null
|
||||
|
||||
const shortMatch = raw.match(/^([a-zA-Z][a-zA-Z0-9]{1,10}):([^@]+?)(?:@(.+))?$/)
|
||||
if (!shortMatch) return null
|
||||
|
||||
const [, shortType, shortKey, shortPwd] = shortMatch
|
||||
const pan = this.panList.find(p => (p.type || '').toLowerCase() === shortType.toLowerCase())
|
||||
if (!pan || !pan.shareUrlFormat) return null
|
||||
|
||||
const link = pan.shareUrlFormat
|
||||
.replace('{shareKey}', shortKey)
|
||||
.replace(/\{pwd}/g, shortPwd || '')
|
||||
|
||||
return {
|
||||
link,
|
||||
pwd: shortPwd || '',
|
||||
name: pan.name || pan.type || shortType
|
||||
}
|
||||
},
|
||||
|
||||
// 识别并转换短链输入(如 lz:shareKey@pwd)
|
||||
normalizeShortcutInput() {
|
||||
const shortInfo = this.expandShortFormat(this.link)
|
||||
if (!shortInfo) return
|
||||
|
||||
this.link = shortInfo.link
|
||||
if (!this.password && shortInfo.pwd) {
|
||||
this.password = shortInfo.pwd
|
||||
}
|
||||
this.$message.success(`已识别短格式并自动转换,网盘类型: ${shortInfo.name}`)
|
||||
this.updateDirectLink()
|
||||
},
|
||||
|
||||
// 清除结果
|
||||
clearResults() {
|
||||
this.parseResult = {}
|
||||
@@ -1266,6 +1321,23 @@ export default {
|
||||
const text = await navigator.clipboard.readText()
|
||||
console.log('获取到的文本内容是:', text)
|
||||
|
||||
const shortInfo = this.expandShortFormat(text)
|
||||
if (shortInfo) {
|
||||
if (shortInfo.link !== this.link || shortInfo.pwd !== this.password) {
|
||||
this.password = shortInfo.pwd
|
||||
this.link = shortInfo.link
|
||||
this.updateDirectLink()
|
||||
if (!this.hasClipboardSuccessTip) {
|
||||
this.$message.success(`自动识别分享成功, 网盘类型: ${shortInfo.name}; 分享URL ${this.link}; 分享密码: ${this.password || '空'}`)
|
||||
this.hasClipboardSuccessTip = true
|
||||
}
|
||||
} else {
|
||||
this.$message.warning(`[${shortInfo.name}]分享信息无变化`)
|
||||
}
|
||||
this.hasWarnedNoLink = false
|
||||
return
|
||||
}
|
||||
|
||||
const linkInfo = parserUrl.parseLink(text)
|
||||
const pwd = parserUrl.parsePwd(text) || ''
|
||||
|
||||
@@ -1375,6 +1447,7 @@ export default {
|
||||
|
||||
// 跳转到客户端链接页面
|
||||
async goToClientLinks() {
|
||||
this.normalizeShortcutInput()
|
||||
// 验证输入
|
||||
if (!this.link.trim()) {
|
||||
this.$message.warning('请先输入分享链接')
|
||||
@@ -1550,9 +1623,19 @@ export default {
|
||||
aria2: 'http://localhost:6800/jsonrpc',
|
||||
thunder: ''
|
||||
}
|
||||
|
||||
// 切换类型时先清空旧连接状态,避免显示残留版本信息
|
||||
this.aria2Connected = false
|
||||
this.aria2Version = ''
|
||||
|
||||
if (defaults[this.aria2ConfigForm.downloaderType] !== undefined) {
|
||||
this.aria2ConfigForm.rpcUrl = defaults[this.aria2ConfigForm.downloaderType]
|
||||
}
|
||||
|
||||
// 非迅雷类型在切换后自动静默重测,刷新连接状态
|
||||
if (this.aria2ConfigForm.downloaderType !== 'thunder') {
|
||||
this.$nextTick(() => this.testAria2Connection(true))
|
||||
}
|
||||
},
|
||||
async testAria2Connection(silent = false) {
|
||||
this.aria2Testing = true
|
||||
@@ -1599,8 +1682,26 @@ export default {
|
||||
this.aria2Version = result.version || ''
|
||||
this.$message.success(`检测到 ${this.downloaderTypeName} ${this.aria2Version}`)
|
||||
} else {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'未检测到本地下载器,是否切换为迅雷下载?',
|
||||
'下载器未检测到',
|
||||
{
|
||||
confirmButtonText: '使用迅雷',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
this.aria2ConfigForm.downloaderType = 'thunder'
|
||||
this.aria2ConfigForm.rpcUrl = ''
|
||||
saveConfig(this.aria2ConfigForm)
|
||||
this.$message.success('已切换并保存为迅雷下载器配置')
|
||||
this.aria2DialogVisible = true
|
||||
await this.testAria2Connection(true)
|
||||
} catch {
|
||||
this.$message.warning('未检测到本地下载器,请确认 Motrix/Gopeed/Aria2 正在运行')
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error('自动检测失败:' + e.message)
|
||||
} finally {
|
||||
@@ -1676,6 +1777,9 @@ export default {
|
||||
// 初始化下载器配置
|
||||
this.getAria2Config()
|
||||
|
||||
// 拉取后端网盘支持列表(用于 type:key@pwd 短格式)
|
||||
this.getPanList()
|
||||
|
||||
// 自动读取剪切板
|
||||
if (this.autoReadClipboard) {
|
||||
this.getPaste()
|
||||
@@ -2094,4 +2198,26 @@ hr {
|
||||
#app.dark-theme .el-form-item__label {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/* 解析按钮专用配色:亮色浅绿,暗色深绿 */
|
||||
.parse-action-btn.el-button--success {
|
||||
--el-button-bg-color: #7fcb96;
|
||||
--el-button-border-color: #7fcb96;
|
||||
--el-button-text-color: #f7fff9;
|
||||
--el-button-hover-bg-color: #93d8a8;
|
||||
--el-button-hover-border-color: #93d8a8;
|
||||
--el-button-active-bg-color: #69b884;
|
||||
--el-button-active-border-color: #69b884;
|
||||
}
|
||||
|
||||
#app.dark-theme .parse-action-btn.el-button--success,
|
||||
body.dark-theme .parse-action-btn.el-button--success {
|
||||
--el-button-bg-color: #1f6b3a;
|
||||
--el-button-border-color: #1f6b3a;
|
||||
--el-button-text-color: #ecf9f0;
|
||||
--el-button-hover-bg-color: #2b7d49;
|
||||
--el-button-hover-border-color: #2b7d49;
|
||||
--el-button-active-bg-color: #185731;
|
||||
--el-button-active-border-color: #185731;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -85,7 +85,8 @@ module.exports = {
|
||||
{
|
||||
source: './node_modules/monaco-editor/min/vs',
|
||||
destination: './nfd-front/js/vs'
|
||||
}
|
||||
},
|
||||
{ source: './nfd-front', destination: '../webroot/nfd-front' }
|
||||
],
|
||||
archive: [ //然后我们选择dist文件夹将之打包成dist.zip并放在根目录
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user