From 33811051b7fd2d9f9d0cffba8aec89cae3f31f76 Mon Sep 17 00:00:00 2001 From: AdingApkgg Date: Sun, 28 Dec 2025 08:07:10 +0800 Subject: [PATCH] Remove unused configuration files and improve TypeScript settings - Deleted eslint.config.mjs and tailwind.config.ts as they are no longer needed. - Updated tsconfig.json to include additional TypeScript files for better project structure. - Refactored various components to enhance modal management and improve code clarity. - Changed console.log statements to console.info for consistent logging practices across the application. --- eslint.config.mjs => eslint.config.js | 1 - scripts/sw-version-plugin.ts | 12 +- src/App.vue | 23 +- src/api/search.ts | 23 +- src/components/CommentsModal.vue | 4 +- src/components/FloatingButtons.vue | 24 +- src/components/LazyRender.vue | 15 +- src/components/SearchHeader.vue | 6 +- src/components/SearchResults.vue | 11 +- src/components/SettingsModal.vue | 8 +- src/components/TopToolbar.vue | 5 +- src/components/VndbPanel.vue | 889 +++++++++++++---------- src/composables/useKeyboardShortcuts.ts | 20 +- src/composables/useSound.ts | 40 +- src/composables/useTextScroll.ts | 6 +- src/config/env.ts | 2 +- src/config/index.ts | 6 +- src/main.ts | 20 +- src/stores/plugins.ts | 7 +- src/stores/search.ts | 2 +- src/stores/stats.ts | 6 +- src/stores/ui.ts | 93 ++- src/utils/icons.ts | 1 + src/utils/imageDB.ts | 3 + src/utils/persistence.ts | 2 +- src/utils/theme.ts | 7 +- src/utils/urlParams.ts | 8 +- tailwind.config.ts => tailwind.config.js | 5 +- tsconfig.json | 2 +- 29 files changed, 726 insertions(+), 525 deletions(-) rename eslint.config.mjs => eslint.config.js (99%) rename tailwind.config.ts => tailwind.config.js (98%) diff --git a/eslint.config.mjs b/eslint.config.js similarity index 99% rename from eslint.config.mjs rename to eslint.config.js index ff8cfb2..51778b4 100644 --- a/eslint.config.mjs +++ b/eslint.config.js @@ -11,7 +11,6 @@ export default tseslint.config( '**/.pnpm-store/**', '**/public/**', '**/*.config.js', - '**/*.config.mjs', '**/*.config.ts', '**/.history/**', // 忽略编辑器历史文件 '**/.vscode/**', diff --git a/scripts/sw-version-plugin.ts b/scripts/sw-version-plugin.ts index 8f0287e..48ac502 100644 --- a/scripts/sw-version-plugin.ts +++ b/scripts/sw-version-plugin.ts @@ -81,13 +81,13 @@ export function swVersionPlugin(options: SwVersionPluginOptions = {}): Plugin { version = generateVersion(includeGitHash, prefix) const buildInfo = getBuildInfo() - console.log('\n📦 SW Version Plugin') - console.log(` Version: ${version}`) - console.log(` Build Time: ${buildInfo.buildTime}`) + console.info('\n📦 SW Version Plugin') + console.info(` Version: ${version}`) + console.info(` Build Time: ${buildInfo.buildTime}`) if (buildInfo.gitCommit) { - console.log(` Git: ${buildInfo.gitBranch}@${buildInfo.gitCommit}`) + console.info(` Git: ${buildInfo.gitBranch}@${buildInfo.gitCommit}`) } - console.log('') + console.info('') }, // 构建完成后注入版本到 sw.js @@ -116,7 +116,7 @@ export function swVersionPlugin(options: SwVersionPluginOptions = {}): Plugin { writeFileSync(swFilePath, content) - console.log(`✅ SW version injected: ${version}`) + console.info(`✅ SW version injected: ${version}`) }, } } diff --git a/src/App.vue b/src/App.vue index 597fddd..5c30cf8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -105,9 +105,9 @@ const uiStore = useUIStore() const settingsStore = useSettingsStore() const searchHeaderRef = ref | null>(null) -// 切换设置面板 +// 切换设置面板(互斥) function openSettings() { - uiStore.isSettingsModalOpen = !uiStore.isSettingsModalOpen + uiStore.toggleSettingsModal() } // 处理历史记录选择 @@ -342,6 +342,7 @@ function cleanupBlobUrls(currentUrl: string) { // 创建新 Map,保留当前使用的 URL const newBlobUrls = new Map() + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion newBlobUrls.set(currentUrl, blobUrls.get(currentUrl)!) // 保留最近添加的 URL(Map 保持插入顺序) @@ -408,12 +409,12 @@ async function displayNextImage() { } preloadImg.onerror = () => { // 加载失败,尝试下一张 - displayNextImage() + void displayNextImage() } preloadImg.src = blobUrl || nextImageUrl - } catch (error) { + } catch { // 加载失败,尝试下一张 - displayNextImage() + void displayNextImage() } } @@ -424,10 +425,10 @@ function startFetchInterval() { } // 立即获取第一张 - fetchAndCacheImage() + void fetchAndCacheImage() fetchInterval = window.setInterval(() => { - fetchAndCacheImage() + void fetchAndCacheImage() }, FETCH_INTERVAL) } @@ -438,10 +439,10 @@ function startDisplayInterval() { } // 立即显示第一张 - displayNextImage() + void displayNextImage() displayInterval = window.setInterval(() => { - displayNextImage() + void displayNextImage() }, DISPLAY_INTERVAL) } @@ -466,8 +467,8 @@ onMounted(async () => { // URL hash 优先级最高 - 覆盖会话状态 const hash = window.location.hash if (hash.startsWith('#atk-comment-')) { - // 评论链接:打开评论面板 - uiStore.isCommentsModalOpen = true + // 评论链接:打开评论面板(互斥) + uiStore.openCommentsModal() } // 恢复保存的搜索状态 diff --git a/src/api/search.ts b/src/api/search.ts index e980416..1e13dde 100644 --- a/src/api/search.ts +++ b/src/api/search.ts @@ -455,7 +455,7 @@ export async function fetchVndbData(gameName: string): Promise // 获取封面图片 - 优先选择安全级别的图片 let mainImageUrl: string | null = null - if (result.image && result.image.url) { + if (result.image?.url) { // 只使用 sexual <= 1 且 violence === 0 的图片 if ((result.image.sexual === 0 || result.image.sexual === 1) && result.image.violence === 0) { mainImageUrl = result.image.url @@ -650,7 +650,7 @@ export async function fetchVndbCharacters(vnId: string): Promise { let imageUrl: string | undefined - if (c.image && c.image.url && c.image.sexual <= 1 && c.image.violence === 0) { + if (c.image?.url && c.image.sexual <= 1 && c.image.violence === 0) { imageUrl = c.image.url } @@ -669,7 +669,7 @@ export async function fetchVndbCharacters(vnId: string): Promise { - if (char.image && char.image.startsWith('https://t.vndb.org/')) { + if (char.image?.startsWith('https://t.vndb.org/')) { char.image = proxyUrl(char.image) } }) @@ -735,11 +735,10 @@ export type TranslateMode = 'description' | 'tags' | 'quotes' const DESCRIPTION_PROMPT = `你是一名专业的视觉小说(Galgame/AVG)本地化专家。请将游戏简介精准翻译为简体中文。 【翻译规范】 -1. 格式净化:清除所有 HTML、Markdown、BBCode 等标记,仅保留纯文本 -2. 结构保留:保持原文段落划分,段落间用换行分隔 -3. 术语处理:使用视觉小说领域通用的中文术语 -4. 人名处理:优先使用中文圈广泛接受的译名,无通用译名时保留原名 -5. 内容控制:禁止添加剧透、解释性文字或主观评价 +1. 结构保留:保持原文段落划分,段落间用换行分隔 +2. 术语处理:使用视觉小说领域通用的中文术语 +3. 人名处理:优先使用中文圈广泛接受的译名,无通用译名时保留原名 +4. 内容控制:禁止添加剧透、解释性文字或主观评价 【输出要求】 仅输出翻译后的纯文本,无需任何说明` @@ -811,7 +810,7 @@ const COMBINED_PROMPT = `你是一名专业的视觉小说(Galgame/AVG)本 export async function translateText( text: string, mode: TranslateMode = 'description', - maxRetries: number = 2, + maxRetries = 2, ): Promise { if (!text || text.trim().length === 0) { return null @@ -913,7 +912,7 @@ export async function translateAllContent( description: string | null, tags: string[] | null, quotes: string[] | null, - maxRetries: number = 2, + maxRetries = 2, ): Promise { const result: TranslateAllResult = { description: null, @@ -1032,12 +1031,12 @@ function replaceVndbUrls(vndbInfo: VndbInfo) { } // 替换封面图片 URL - if (vndbInfo.mainImageUrl && vndbInfo.mainImageUrl.startsWith('https://t.vndb.org/')) { + if (vndbInfo.mainImageUrl?.startsWith('https://t.vndb.org/')) { vndbInfo.mainImageUrl = proxyUrl(vndbInfo.mainImageUrl) } // 替换主截图 URL - if (vndbInfo.screenshotUrl && vndbInfo.screenshotUrl.startsWith('https://t.vndb.org/')) { + if (vndbInfo.screenshotUrl?.startsWith('https://t.vndb.org/')) { vndbInfo.screenshotUrl = proxyUrl(vndbInfo.screenshotUrl) } diff --git a/src/components/CommentsModal.vue b/src/components/CommentsModal.vue index 82bf69b..0fe301b 100644 --- a/src/components/CommentsModal.vue +++ b/src/components/CommentsModal.vue @@ -10,7 +10,7 @@ leave-to-class="opacity-0 scale-[0.98] translate-y-10" >
@@ -140,7 +140,7 @@ function initArtalk() { } } - nextTick(() => { + void nextTick(() => { const commentsEl = document.getElementById('Comments') if (commentsEl) { try { diff --git a/src/components/FloatingButtons.vue b/src/components/FloatingButtons.vue index 2ff5217..dffd54e 100644 --- a/src/components/FloatingButtons.vue +++ b/src/components/FloatingButtons.vue @@ -195,15 +195,15 @@ function scrollToTop() { } function toggleComments() { - uiStore.isCommentsModalOpen = !uiStore.isCommentsModalOpen + uiStore.toggleCommentsModal() } function toggleVndbPanel() { - uiStore.isVndbPanelOpen = !uiStore.isVndbPanelOpen + uiStore.toggleVndbPanel() } function toggleHistory() { - uiStore.isHistoryModalOpen = !uiStore.isHistoryModalOpen + uiStore.toggleHistoryModal() } function togglePlatformNav(withSound = false) { @@ -257,15 +257,19 @@ function handleScrollToPlatform(platformName: string) { } function scrollToPlatform(platformName: string) { - const platformElements = document.querySelectorAll('[data-platform]') - const targetElement = Array.from(platformElements).find( - el => el.getAttribute('data-platform') === platformName, - ) as HTMLElement + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const targetElement = document.querySelector(`[data-platform="${platformName}"]`)! if (targetElement) { - const yOffset = -80 - const y = targetElement.getBoundingClientRect().top + window.pageYOffset + yOffset - window.scrollTo({ top: y, behavior: 'smooth' }) + // 先瞬间滚动到目标位置附近,触发途中的 LazyRender 渲染 + targetElement.scrollIntoView({ behavior: 'instant', block: 'start' }) + + // 等待渲染完成后,再平滑滚动到精确位置 + requestAnimationFrame(() => { + setTimeout(() => { + targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' }) + }, 50) + }) // 滚动后关闭导航 playTransitionDown() diff --git a/src/components/LazyRender.vue b/src/components/LazyRender.vue index 6d0f5e3..6d2ac33 100644 --- a/src/components/LazyRender.vue +++ b/src/components/LazyRender.vue @@ -1,5 +1,12 @@