refactor: 抽象出IconButton以优化代码

This commit is contained in:
lanyeeee
2025-09-10 06:49:27 +08:00
parent c8b24073bb
commit 07f6e18719
8 changed files with 84 additions and 120 deletions
+1
View File
@@ -10,6 +10,7 @@ declare module 'vue' {
export interface GlobalComponents {
ColorfulTag: typeof import('./src/components/ColorfulTag.vue')['default']
FloatLabelInput: typeof import('./src/components/FloatLabelInput.vue')['default']
IconButton: typeof import('./src/components/IconButton.vue')['default']
NA: typeof import('naive-ui')['NA']
NBadge: typeof import('naive-ui')['NBadge']
NButton: typeof import('naive-ui')['NButton']
+21
View File
@@ -0,0 +1,21 @@
<script setup lang="ts">
defineProps<{
href?: string
}>()
</script>
<template>
<a
v-if="href !== undefined"
:href="href"
target="_blank"
draggable="false"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6 active:text-white">
<slot />
</a>
<div
v-else
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6 active:text-white">
<slot />
</div>
</template>
@@ -5,6 +5,7 @@ import { ensureHttps, isElementInViewport, playTaskToQueueAnimation } from '../.
import { PhDownloadSimple, PhGoogleChromeLogo, PhMagnifyingGlass } from '@phosphor-icons/vue'
import { EpInBangumiFollow } from '../../../bindings.ts'
import SimpleCheckbox from '../../../components/SimpleCheckbox.vue'
import IconButton from '../../../components/IconButton.vue'
const searchPaneRef = inject(searchPaneRefKey)
@@ -18,7 +19,7 @@ const props = defineProps<{
const navDownloadButtonRef = inject(navDownloadButtonRefKey)
const rootDivRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<InstanceType<typeof IconButton>>()
async function handleDownloadClick() {
if (props.downloadEpisode === undefined) {
@@ -34,7 +35,7 @@ function playDownloadAnimation() {
return
}
const from = downloadButtonRef.value
const from = downloadButtonRef.value?.$el
const to = navDownloadButtonRef?.value
if (from instanceof Element && to !== undefined) {
@@ -71,29 +72,20 @@ defineExpose({ playDownloadAnimation, ep: props.ep })
</div>
<div class="flex gap-1 items-center mt-2">
<a
:href="`https://www.bilibili.com/bangumi/play/ss${ep.season_id}`"
target="_blank"
draggable="false"
title="在浏览器中打开"
class="p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6">
<IconButton title="在浏览器中打开" :href="`https://www.bilibili.com/bangumi/play/ss${ep.season_id}`">
<PhGoogleChromeLogo :size="24" />
</a>
<div
title="在下载器内搜索"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="searchPaneRef?.search(`ss${props.ep.season_id}`, 'Bangumi')">
</IconButton>
<IconButton title="在下载器内搜索" @click="searchPaneRef?.search(`ss${props.ep.season_id}`, 'Bangumi')">
<PhMagnifyingGlass :size="24" />
</div>
<div
</IconButton>
<IconButton
v-if="downloadEpisode !== undefined"
ref="downloadButtonRef"
class="ml-auto"
title="一键下载"
class="ml-auto cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="handleDownloadClick">
<PhDownloadSimple :size="24" />
</div>
</IconButton>
</div>
</div>
</template>
@@ -19,6 +19,7 @@ import ColorfulTag from '../../../components/ColorfulTag.vue'
import { searchPaneRefKey } from '../../../injection_keys.ts'
import { ProgressData } from '../DownloadPane.vue'
import { ensureHttps } from '../../../utils.tsx'
import IconButton from '../../../components/IconButton.vue'
const store = useStore()
@@ -206,34 +207,24 @@ function handleSearchClick() {
</div>
<div class="ml-auto flex gap-2 items-center">
<div
<IconButton
v-if="p.state === 'Completed' && p.video_task.selected"
title="打开mp4目录"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="showMp4InFileManager(p.episode_dir, p.filename)">
<PhFileVideo :size="24" />
</div>
<div
</IconButton>
<IconButton
v-if="p.state === 'Completed'"
title="打开下载目录"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="showEpisodeDirInFileManager(p.episode_dir)">
<PhFolderOpen :size="24" />
</div>
<div
title="在下载器内搜索"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="handleSearchClick">
</IconButton>
<IconButton title="在下载器内搜索" @click="handleSearchClick">
<PhMagnifyingGlass :size="24" />
</div>
<a
:href="href"
target="_blank"
draggable="false"
title="在浏览器中打开"
class="p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6">
</IconButton>
<IconButton title="在浏览器中打开" :href="href">
<PhGoogleChromeLogo :size="24" />
</a>
</IconButton>
</div>
</div>
</div>
+10 -20
View File
@@ -6,6 +6,7 @@ import { ensureHttps, isElementInViewport, playTaskToQueueAnimation } from '../.
import { computed, inject, ref } from 'vue'
import { navDownloadButtonRefKey } from '../../../injection_keys.ts'
import { SearchType } from '../../SearchPane/SearchPane.vue'
import IconButton from '../../../components/IconButton.vue'
const props = defineProps<{
media: MediaInFav
@@ -18,7 +19,7 @@ const props = defineProps<{
const navDownloadButtonRef = inject(navDownloadButtonRefKey)
const rootDivRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<InstanceType<typeof IconButton>>()
const openInBrowserHref = computed<string | undefined>(() => {
if (props.media.type === 2) {
@@ -54,7 +55,7 @@ function playDownloadAnimation() {
return
}
const from = downloadButtonRef.value
const from = downloadButtonRef.value?.$el
const to = navDownloadButtonRef?.value
if (from instanceof Element && to !== undefined) {
@@ -121,31 +122,20 @@ defineExpose({ playDownloadAnimation, media: props.media })
</div>
<div class="flex gap-1 items-center">
<a
:href="openInBrowserHref"
target="_blank"
draggable="false"
title="在浏览器中打开"
class="p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6">
<IconButton title="在浏览器中打开" :href="openInBrowserHref">
<PhGoogleChromeLogo :size="24" />
</a>
<div
v-if="search !== undefined"
title="在下载器内搜索"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="searchInSearchPane">
</IconButton>
<IconButton v-if="search !== undefined" title="在下载器内搜索" @click="searchInSearchPane">
<PhMagnifyingGlass :size="24" />
</div>
<div
</IconButton>
<IconButton
v-if="props.downloadEpisode !== undefined"
ref="downloadButtonRef"
class="ml-auto"
title="一键下载"
class="ml-auto cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="handleDownloadClick">
<PhDownloadSimple :size="24" />
</div>
</IconButton>
</div>
</div>
</template>
@@ -6,6 +6,7 @@ import { navDownloadButtonRefKey } from '../../../injection_keys.ts'
import { ensureHttps, isElementInViewport, playTaskToQueueAnimation } from '../../../utils.tsx'
import { PhDownloadSimple, PhGoogleChromeLogo, PhMagnifyingGlass } from '@phosphor-icons/vue'
import SimpleCheckbox from '../../../components/SimpleCheckbox.vue'
import IconButton from '../../../components/IconButton.vue'
const props = defineProps<{
episodeType: EpisodeType
@@ -19,7 +20,7 @@ const props = defineProps<{
const navDownloadButtonRef = inject(navDownloadButtonRefKey)
const rootDivRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<InstanceType<typeof IconButton>>()
const openInBrowserHref = computed<string | undefined>(() => {
if (props.episodeType === 'Normal') {
@@ -98,7 +99,7 @@ function playDownloadAnimation() {
return
}
const from = downloadButtonRef.value
const from = downloadButtonRef.value?.$el
const to = navDownloadButtonRef?.value
if (from instanceof Element && to !== undefined) {
@@ -175,31 +176,20 @@ defineExpose({ playDownloadAnimation, historyDetail: props.historyDetail })
</div>
<div class="flex gap-1 items-center">
<a
:href="openInBrowserHref"
target="_blank"
draggable="false"
title="在浏览器中打开"
class="p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6">
<IconButton title="在浏览器中打开" :href="openInBrowserHref">
<PhGoogleChromeLogo :size="24" />
</a>
<div
v-if="search !== undefined"
title="在下载器内搜索"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="searchInSearchPane">
</IconButton>
<IconButton v-if="search !== undefined" title="在下载器内搜索" @click="searchInSearchPane">
<PhMagnifyingGlass :size="24" />
</div>
<div
</IconButton>
<IconButton
v-if="props.downloadEpisode !== undefined"
ref="downloadButtonRef"
class="ml-auto"
title="一键下载"
class="ml-auto cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="handleDownloadClick">
<PhDownloadSimple :size="24" />
</div>
</IconButton>
</div>
</div>
</template>
+13 -24
View File
@@ -18,6 +18,7 @@ import PartsDialogContent from './PartsDialogContent.vue'
import { ensureHttps, extractBvid, isElementInViewport, playTaskToQueueAnimation } from '../../../utils.tsx'
import { navDownloadButtonRefKey } from '../../../injection_keys.ts'
import { SearchType } from '../SearchPane.vue'
import IconButton from '../../../components/IconButton.vue'
onMounted(() => console.log('EpisodeCard mounted'))
onUpdated(() => console.log('EpisodeCard updated'))
@@ -51,7 +52,7 @@ const props = defineProps<{
const navDownloadButtonRef = inject(navDownloadButtonRefKey)
const rootDivRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<InstanceType<typeof IconButton>>()
const episodeInfo = computed<EpisodeInfo>(() => {
if (props.episodeType === 'NormalSingle') {
@@ -174,7 +175,7 @@ function playDownloadAnimation() {
return
}
const from = downloadButtonRef.value
const from = downloadButtonRef.value?.$el
const to = navDownloadButtonRef?.value
if (from instanceof Element && to !== undefined) {
@@ -226,38 +227,26 @@ defineExpose({ playDownloadAnimation, episodeInfo })
</div>
<div class="flex gap-1 items-center">
<a
v-if="episodeInfo.href !== undefined"
:href="episodeInfo.href"
target="_blank"
draggable="false"
title="在浏览器中打开"
class="p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6">
<IconButton v-if="episodeInfo.href !== undefined" title="在浏览器中打开" :href="episodeInfo.href">
<PhGoogleChromeLogo :size="24" />
</a>
<div
v-if="partsButtonShowing"
title="查看分P"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="handlePartsButtonClick">
</IconButton>
<IconButton v-if="partsButtonShowing" title="查看分P" @click="handlePartsButtonClick">
<PhQueue :size="24" />
</div>
<div
</IconButton>
<IconButton
v-if="search !== undefined && episodeInfo.bvid !== undefined"
title="在下载器内搜索"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="search(episodeInfo.bvid, 'Normal')">
<PhMagnifyingGlass :size="24" />
</div>
<div
ref="downloadButtonRef"
</IconButton>
<IconButton
v-if="downloadEpisode !== undefined"
ref="downloadButtonRef"
title="一键下载"
class="ml-auto cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
class="ml-auto"
@click="handleDownloadClick">
<PhDownloadSimple :size="24" />
</div>
</IconButton>
</div>
</div>
</template>
@@ -6,6 +6,7 @@ import { ensureHttps, extractEpId, isElementInViewport, playTaskToQueueAnimation
import { PhDownloadSimple, PhGoogleChromeLogo, PhMagnifyingGlass } from '@phosphor-icons/vue'
import SimpleCheckbox from '../../../components/SimpleCheckbox.vue'
import { SearchType } from '../../SearchPane/SearchPane.vue'
import IconButton from '../../../components/IconButton.vue'
const props = defineProps<{
media: MediaInWatchLater
@@ -18,7 +19,7 @@ const props = defineProps<{
const navDownloadButtonRef = inject(navDownloadButtonRefKey)
const rootDivRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<HTMLDivElement>()
const downloadButtonRef = ref<InstanceType<typeof IconButton>>()
const openInBrowserHref = computed<string>(() => {
if (props.media.redirect_url === null) {
@@ -43,7 +44,7 @@ function playDownloadAnimation() {
return
}
const from = downloadButtonRef.value
const from = downloadButtonRef.value?.$el
const to = navDownloadButtonRef?.value
if (from instanceof Element && to !== undefined) {
@@ -109,31 +110,20 @@ defineExpose({ playDownloadAnimation, media: props.media })
</div>
<div class="flex gap-1 items-center">
<a
:href="openInBrowserHref"
target="_blank"
draggable="false"
title="在浏览器中打开"
class="p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6">
<IconButton title="在浏览器中打开" :href="openInBrowserHref">
<PhGoogleChromeLogo :size="24" />
</a>
<div
v-if="search !== undefined"
title="在下载器内搜索"
class="cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
@click="searchInSearchPane">
</IconButton>
<IconButton v-if="search !== undefined" title="在下载器内搜索" @click="searchInSearchPane">
<PhMagnifyingGlass :size="24" />
</div>
<div
</IconButton>
<IconButton
v-if="downloadEpisode !== undefined"
ref="downloadButtonRef"
title="一键下载"
class="ml-auto cursor-pointer p-1 rounded-lg flex items-center justify-between text-gray-6 hover:bg-sky-5 hover:text-white active:bg-sky-6"
class="ml-auto"
@click="handleDownloadClick">
<PhDownloadSimple :size="24" />
</div>
</IconButton>
</div>
</div>
</template>