From 7d8b33afe057d2347f4030e2bd06eaff9c142d18 Mon Sep 17 00:00:00 2001 From: yukaidi Date: Fri, 29 May 2026 12:38:34 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=89=8D=E7=AB=AF=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=B4=A8=E9=87=8F=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix: Home.vue 组件名 'App' → 'Home' - fix: DirectoryTree selectAll 补 parserUrl 空值检查 - fix: 提取 previewBaseUrl 到 utils/constants.js,解除 ShowFile 对 Home 的耦合 - fix: Home.vue focus 事件监听器改为命名函数,加 beforeUnmount 移除 - fix: Playground.vue MutationObserver 保存引用,onUnmounted 中 disconnect - chore: 删除未使用的 api.js - chore: 删除 ClientLinks.vue 死代码 downloadClient/shouldShowDownloadButton - chore: 删除 DirectoryTree.vue 死代码 buildTree --- web-front/src/components/DirectoryTree.vue | 6 +- web-front/src/utils/api.js | 125 --------------------- web-front/src/utils/constants.js | 6 + web-front/src/views/ClientLinks.vue | 27 ----- web-front/src/views/Home.vue | 20 ++-- web-front/src/views/Playground.vue | 7 +- web-front/src/views/ShowFile.vue | 4 +- 7 files changed, 27 insertions(+), 168 deletions(-) delete mode 100644 web-front/src/utils/api.js create mode 100644 web-front/src/utils/constants.js diff --git a/web-front/src/components/DirectoryTree.vue b/web-front/src/components/DirectoryTree.vue index fa90d1a..d322291 100644 --- a/web-front/src/components/DirectoryTree.vue +++ b/web-front/src/components/DirectoryTree.vue @@ -487,10 +487,6 @@ export default { } return `${baseUrl}?${params.toString()}` }, - // 文件树与窗格同源:直接返回当前目录数据 - buildTree(list) { - return list || [] - }, // 懒加载子节点 loadNode(node, resolve) { if (node.level === 0) { @@ -852,7 +848,7 @@ export default { this.toggleFileSelect(file) }, selectAll() { - this.selectedFiles = this.currentFileList.filter(f => f.fileType !== 'folder') + this.selectedFiles = this.currentFileList.filter(f => f.fileType !== 'folder' && f.parserUrl) }, deselectAll() { this.selectedFiles = [] diff --git a/web-front/src/utils/api.js b/web-front/src/utils/api.js deleted file mode 100644 index 7065caa..0000000 --- a/web-front/src/utils/api.js +++ /dev/null @@ -1,125 +0,0 @@ -import axios from 'axios' - -// 创建 axios 实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || '', - timeout: 30000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - // 可以在这里添加认证token等 - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - return response.data - }, - error => { - console.error('API请求错误:', error) - - if (error.response) { - // 服务器返回错误状态码 - const message = error.response.data?.message || error.response.data?.error || '服务器错误' - return Promise.reject(new Error(message)) - } else if (error.request) { - // 网络错误 - return Promise.reject(new Error('网络连接失败,请检查网络设置')) - } else { - // 其他错误 - return Promise.reject(new Error(error.message || '请求失败')) - } - } -) - -// 客户端链接 API -export const clientLinksApi = { - /** - * 获取所有客户端下载链接 - * @param {string} shareUrl - 分享链接 - * @param {string} password - 提取码(可选) - * @returns {Promise} 客户端链接响应 - */ - async getClientLinks(shareUrl, password = '') { - const params = new URLSearchParams() - params.append('url', shareUrl) - if (password) { - params.append('pwd', password) - } - - return await api.get(`/v2/clientLinks?${params.toString()}`) - }, - - /** - * 获取指定类型的客户端下载链接 - * @param {string} shareUrl - 分享链接 - * @param {string} password - 提取码(可选) - * @param {string} clientType - 客户端类型 - * @returns {Promise} 指定类型的客户端链接 - */ - async getClientLink(shareUrl, password = '', clientType) { - const params = new URLSearchParams() - params.append('url', shareUrl) - if (password) { - params.append('pwd', password) - } - params.append('clientType', clientType) - - return await api.get(`/v2/clientLink?${params.toString()}`) - } -} - -// 其他 API(如果需要的话) -export const parserApi = { - /** - * 解析分享链接 - * @param {string} shareUrl - 分享链接 - * @param {string} password - 提取码(可选) - * @returns {Promise} 解析结果 - */ - async parseLink(shareUrl, password = '') { - const params = new URLSearchParams() - params.append('url', shareUrl) - if (password) { - params.append('pwd', password) - } - - return await api.get(`/v2/linkInfo?${params.toString()}`) - }, - - /** - * 获取文件列表 - * @param {string} shareUrl - 分享链接 - * @param {string} password - 提取码(可选) - * @param {string} dirId - 目录ID(可选) - * @param {string} uuid - UUID(可选) - * @returns {Promise} 文件列表 - */ - async getFileList(shareUrl, password = '', dirId = '', uuid = '') { - const params = new URLSearchParams() - params.append('url', shareUrl) - if (password) { - params.append('pwd', password) - } - if (dirId) { - params.append('dirId', dirId) - } - if (uuid) { - params.append('uuid', uuid) - } - - return await api.get(`/v2/getFileList?${params.toString()}`) - } -} - -export default api diff --git a/web-front/src/utils/constants.js b/web-front/src/utils/constants.js new file mode 100644 index 0000000..e53920e --- /dev/null +++ b/web-front/src/utils/constants.js @@ -0,0 +1,6 @@ +/** + * 前端全局常量 + */ + +/** 预览服务基础 URL */ +export const PREVIEW_BASE_URL = 'https://nfd-parser.github.io/nfd-preview/preview.html?src=' diff --git a/web-front/src/views/ClientLinks.vue b/web-front/src/views/ClientLinks.vue index 00626d2..ecb6bed 100644 --- a/web-front/src/views/ClientLinks.vue +++ b/web-front/src/views/ClientLinks.vue @@ -293,24 +293,6 @@ export default { return clientConfig[type]?.downloadUrl || '#' } - // 判断是否应该显示下载客户端按钮 - const shouldShowDownloadButton = (type) => { - const os = getOSInfo() - switch (type) { - case 'CURL': - // cURL 在 Windows 上可能需要安装 - return os === 'windows' - case 'ARIA2': - // Aria2 需要手动安装 - return true - case 'THUNDER': - // 迅雷主要在 Windows 上使用 - return os === 'windows' - default: - return false - } - } - // 获取操作系统信息 const getOSInfo = () => { const userAgent = navigator.userAgent.toLowerCase() @@ -383,13 +365,6 @@ export default { } } - // 下载客户端 - const downloadClient = (type) => { - const url = getClientDownloadUrl(type) - window.open(url, '_blank', 'noopener,noreferrer') - ElMessage.success(`正在跳转到 ${getClientDisplayName(type)} 下载页面`) - } - // 格式化文件大小 const formatFileSize = (bytes) => { if (!bytes) return '未知' @@ -440,9 +415,7 @@ export default { getTextareaRows, goBack, getClientLogo, - downloadClient, handleImageError, - shouldShowDownloadButton, getClientSupportsCookie, goToAuthConfig } diff --git a/web-front/src/views/Home.vue b/web-front/src/views/Home.vue index ebe3b71..8cd9d8d 100644 --- a/web-front/src/views/Home.vue +++ b/web-front/src/views/Home.vue @@ -595,11 +595,10 @@ import fileTypeUtils from '@/utils/fileTypeUtils' import { ElMessage, ElMessageBox } from 'element-plus' import { playgroundApi } from '@/utils/playgroundApi' import { testConnection, autoDetect, addDownload, getConfig, saveConfig } from '@/utils/downloaderService' - -export const previewBaseUrl = 'https://nfd-parser.github.io/nfd-preview/preview.html?src='; +import { PREVIEW_BASE_URL } from '@/utils/constants' export default { - name: 'App', + name: 'Home', components: { DarkMode, DirectoryTree, DownloadDialog }, mixins: [fileTypeUtils], data() { @@ -617,7 +616,7 @@ export default { parseResult: {}, downloadUrl: null, directLink: '', - previewBaseUrl, + previewBaseUrl: PREVIEW_BASE_URL, // 功能结果 markdownText: '', @@ -1791,19 +1790,26 @@ export default { } // 监听窗口焦点事件 - window.addEventListener('focus', () => { + this._onFocusHandler = () => { if (this.autoReadClipboard) { this.hasClipboardSuccessTip = false // 聚焦时重置,只提示一次 this.getPaste() } - }) + } + window.addEventListener('focus', this._onFocusHandler) // 首次打开页面弹出风险提示 if (!window.localStorage.getItem('nfd_risk_ack')) { this.showRiskDialog = true } }, - + + beforeUnmount() { + if (this._onFocusHandler) { + window.removeEventListener('focus', this._onFocusHandler) + } + }, + watch: { downloadUrl(val) { if (!val) { diff --git a/web-front/src/views/Playground.vue b/web-front/src/views/Playground.vue index 0d5159f..a68693e 100644 --- a/web-front/src/views/Playground.vue +++ b/web-front/src/views/Playground.vue @@ -2220,6 +2220,8 @@ curl "${baseUrl}/json/parser?url=${encodeURIComponent(exampleUrl)}" }, 100); }; + let themeObserver = null; + onMounted(async () => { // 初始化移动端检测 updateIsMobile(); @@ -2246,10 +2248,10 @@ curl "${baseUrl}/json/parser?url=${encodeURIComponent(exampleUrl)}" const html = document.documentElement; if (html && html.classList) { try { - const observer = new MutationObserver(() => { + themeObserver = new MutationObserver(() => { checkDarkMode(); }); - observer.observe(html, { + themeObserver.observe(html, { attributes: true, attributeFilter: ['class', 'data-theme'] }); @@ -2266,6 +2268,7 @@ curl "${baseUrl}/json/parser?url=${encodeURIComponent(exampleUrl)}" window.removeEventListener('resize', updateIsMobile); // 移除页面关闭/刷新前的提示 window.removeEventListener('beforeunload', handleBeforeUnload); + themeObserver?.disconnect(); }); return { diff --git a/web-front/src/views/ShowFile.vue b/web-front/src/views/ShowFile.vue index 37d8436..7d174ef 100644 --- a/web-front/src/views/ShowFile.vue +++ b/web-front/src/views/ShowFile.vue @@ -32,7 +32,7 @@