refactor: use ALink to unify link Opening Behavior

This commit is contained in:
Hakadao
2024-11-04 02:02:12 +08:00
parent 6b87241e43
commit c09c65f729
17 changed files with 122 additions and 86 deletions

58
src/components/ALink.vue Normal file
View File

@@ -0,0 +1,58 @@
<script lang="ts" setup>
import { useBewlyApp } from '~/composables/useAppProvider'
import { settings } from '~/logic'
import { isHomePage } from '~/utils/main'
const props = defineProps<{
href: string
title?: string
rel?: string
type: 'topBar' | 'videoCard'
customClickEvent?: boolean
}>()
const emit = defineEmits<{
(e: 'click', value: MouseEvent): void
}>()
const { openIframeDrawer } = useBewlyApp()
const openMode = computed(() => {
if (props.type === 'topBar')
return settings.value.topBarLinkOpenMode
else if (props.type === 'videoCard')
return settings.value.videoCardLinkOpenMode
return 'newTab'
})
const target = computed(() => {
if (openMode.value === 'newTab') {
return '_blank'
}
if (openMode.value === 'currentTabIfNotHomepage') {
return isHomePage() ? '_blank' : '_self'
}
if (openMode.value === 'currentTab') {
return '_self'
}
return '_self'
})
function handleClick(event: MouseEvent) {
if (props.customClickEvent) {
emit('click', event)
return
}
if (openMode.value === 'drawer' && !event.ctrlKey && !event.metaKey) {
event.preventDefault()
openIframeDrawer(props.href)
}
}
</script>
<template>
<a :href="href" :target="target" :title="title" :rel="rel" @click="handleClick">
<slot />
</a>
</template>

View File

@@ -1,13 +1,11 @@
<script setup lang="ts">
import { useBewlyApp } from '~/composables/useAppProvider'
import { useDark } from '~/composables/useDark'
import { settings } from '~/logic'
import { numFormatter } from '~/utils/dataFormatter'
import { removeHttpFromUrl } from '~/utils/main'
import BangumiCardSkeleton from './BangumiCardSkeleton.vue'
const props = defineProps<{
defineProps<{
skeleton?: boolean
bangumi: Bangumi
horizontal?: boolean
@@ -33,31 +31,22 @@ interface Bangumi {
}
const { isDark } = useDark()
const { openIframeDrawer } = useBewlyApp()
function handleClick(event: MouseEvent) {
if (settings.value.videoCardLinkOpenMode === 'drawer' && props.bangumi.url) {
event.preventDefault()
openIframeDrawer(props.bangumi.url)
}
}
</script>
<template>
<div mb-6>
<a
<ALink
v-if="!skeleton && bangumi"
class="group"
:style="{
display: horizontal ? 'flex' : 'block',
}"
:href="bangumi.url" target="_blank"
:href="bangumi.url"
type="videoCard"
gap-4 hover:bg="$bew-fill-2" hover:ring="8 $bew-fill-2"
content-visibility-auto intrinsic-size-400px
transition="all ease-in-out 300"
rounded="$bew-radius" h-fit
@click="handleClick"
>
<!-- Cover -->
<div
@@ -102,7 +91,6 @@ function handleClick(event: MouseEvent) {
aspect="12/16"
pos="relative"
>
<!-- anime genres -->
<div
v-if="bangumi.evaluate || (Array.isArray(bangumi.tags) && bangumi.tags?.length > 0)"
@@ -119,7 +107,9 @@ function handleClick(event: MouseEvent) {
);
"
>
<div mb-4 text="white group-hover:shadow-[0_0_4px_rgba(0,0,0,1)]">{{ bangumi.evaluate }}</div>
<div mb-4 text="white group-hover:shadow-[0_0_4px_rgba(0,0,0,1)]">
{{ bangumi.evaluate }}
</div>
<template v-if="Array.isArray(bangumi.tags) && bangumi.tags?.length > 0">
<div flex="~ wrap" gap-2>
<span
@@ -194,7 +184,7 @@ function handleClick(event: MouseEvent) {
<span lh-22px> {{ bangumi.desc }} </span>
</div>
</div>
</a>
</ALink>
<BangumiCardSkeleton
v-else-if="skeleton"
:horizontal="horizontal"

View File

@@ -11,7 +11,6 @@ import api from '~/utils/api'
import { getUserID, isHomePage } from '~/utils/main'
import emitter from '~/utils/mitt'
import ALink from './components/ALink.vue'
import ChannelsPop from './components/ChannelsPop.vue'
import FavoritesPop from './components/FavoritesPop.vue'
import HistoryPop from './components/HistoryPop.vue'
@@ -542,6 +541,7 @@ defineExpose({
<ALink
ref="avatarImg"
:href="`https://space.bilibili.com/${mid}`"
type="topBar"
class="avatar-img"
:class="{ hover: popupVisible.userPanel }"
:style="{
@@ -647,6 +647,7 @@ defineExpose({
<ALink
href="https://message.bilibili.com"
:title="$t('topbar.notifications')"
type="topBar"
>
<div i-tabler:bell />
</ALink>
@@ -680,6 +681,7 @@ defineExpose({
<ALink
href="https://t.bilibili.com"
:title="$t('topbar.moments')"
type="topBar"
>
<div i-tabler:windmill />
</ALink>
@@ -698,6 +700,7 @@ defineExpose({
<ALink
:href="`https://space.bilibili.com/${mid}/favlist`"
:title="$t('topbar.favorites')"
type="topBar"
>
<div i-mingcute:star-line />
</ALink>
@@ -723,6 +726,7 @@ defineExpose({
<ALink
href="https://www.bilibili.com/account/history"
:title="$t('topbar.history')"
type="topBar"
>
<div i-mingcute:time-line />
</ALink>
@@ -745,6 +749,7 @@ defineExpose({
<ALink
href="https://www.bilibili.com/watchlater/#/list"
:title="$t('topbar.watch_later')"
type="topBar"
>
<div i-mingcute:carplay-line />
</ALink>

View File

@@ -11,7 +11,6 @@ import api from '~/utils/api'
import { getUserID, isHomePage } from '~/utils/main'
import emitter from '~/utils/mitt'
import ALink from './components/ALink.vue'
import ChannelsPop from './components/ChannelsPop.vue'
import FavoritesPop from './components/FavoritesPop.vue'
import HistoryPop from './components/HistoryPop.vue'
@@ -555,6 +554,7 @@ defineExpose({
<ALink
href="https://t.bilibili.com"
:title="$t('topbar.moments')"
type="topBar"
>
<div i-tabler:windmill />
</ALink>
@@ -579,6 +579,7 @@ defineExpose({
<ALink
:href="`https://space.bilibili.com/${mid}/favlist`"
:title="$t('topbar.favorites')"
type="topBar"
>
<div i-mingcute:star-line />
</ALink>
@@ -604,8 +605,8 @@ defineExpose({
>
<ALink
href="https://www.bilibili.com/account/history"
:title="$t('topbar.history')"
type="topBar"
>
<div i-mingcute:time-line />
</ALink>
@@ -629,6 +630,7 @@ defineExpose({
<ALink
href="https://www.bilibili.com/watchlater/#/list"
:title="$t('topbar.watch_later')"
type="topBar"
>
<div i-mingcute:carplay-line />
</ALink>
@@ -727,6 +729,7 @@ defineExpose({
<ALink
href="https://message.bilibili.com"
:title="$t('topbar.notifications')"
type="topBar"
>
<div i-tabler:bell />
</ALink>
@@ -753,6 +756,7 @@ defineExpose({
<ALink
ref="avatarImg"
:href="`https://space.bilibili.com/${mid}`"
type="topBar"
class="avatar-img"
:class="{ hover: popupVisible.userPanel }"
:style="{

View File

@@ -1,29 +0,0 @@
<script lang="ts" setup>
import { settings } from '~/logic'
import { isHomePage } from '~/utils/main'
defineProps<{
href?: string
title?: string
rel?: string
}>()
const target = computed(() => {
if (settings.value.topBarLinkOpenMode === 'newTab') {
return '_blank'
}
if (settings.value.topBarLinkOpenMode === 'currentTabIfNotHomepage') {
return isHomePage() ? '_blank' : '_self'
}
if (settings.value.topBarLinkOpenMode === 'currentTab') {
return '_self'
}
return '_self'
})
</script>
<template>
<a :href="href" :target="target" :title="title" :rel="rel">
<slot />
</a>
</template>

View File

@@ -1,8 +1,6 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import ALink from './ALink.vue'
const { t } = useI18n()
const genres = computed(() => [
@@ -72,6 +70,7 @@ const otherLinks = computed(() => [
>
<ALink
:href="genre.href"
type="topBar"
>
<svg aria-hidden="true" class="svg-icon">
<use :xlink:href="genre.icon" />
@@ -92,6 +91,7 @@ const otherLinks = computed(() => [
>
<ALink
:href="otherLink.href"
type="topBar"
>
<div v-if="otherLink.icon.startsWith('#')" class="icon">
<svg

View File

@@ -9,7 +9,6 @@ import { calcCurrentTime } from '~/utils/dataFormatter'
import { getUserID, removeHttpFromUrl, scrollToTop } from '~/utils/main'
import type { FavoriteCategory, FavoriteResource } from '../types'
import ALink from './ALink.vue'
const favoriteCategories = reactive<Array<FavoriteCategory>>([])
const favoriteResources = reactive<Array<FavoriteResource>>([])
@@ -164,12 +163,14 @@ defineExpose({
<div flex="~ gap-4">
<ALink
:href="playAllUrl"
type="topBar"
flex="~" items="center"
>
<span text="sm">{{ $t('common.play_all') }}</span>
</ALink>
<ALink
:href="viewAllUrl"
type="topBar"
flex="~" items="center"
>
<span text="sm">{{ $t('common.view_all') }}</span>
@@ -238,6 +239,7 @@ defineExpose({
v-for="item in favoriteResources"
:key="item.id"
:href="isMusic(item) ? `https://www.bilibili.com/audio/au${item.id}` : `//www.bilibili.com/video/${item.bvid}`"
type="topBar"
hover:bg="$bew-fill-2"
rounded="$bew-radius"
m="last:b-4" p="2"

View File

@@ -12,8 +12,6 @@ import api from '~/utils/api'
import { calcCurrentTime } from '~/utils/dataFormatter'
import { removeHttpFromUrl, scrollToTop } from '~/utils/main'
import ALink from './ALink.vue'
const { t } = useI18n()
const historys = reactive<Array<HistoryItem>>([])
const historyTabs = computed(() => [
@@ -207,6 +205,7 @@ function getHistoryList(type: Business, view_at = 0 as number) {
</div>
<ALink
href="https://www.bilibili.com/account/history"
type="topBar"
flex="~ items-center"
>
<span text="sm">{{ $t('common.view_all') }}</span>
@@ -250,6 +249,7 @@ function getHistoryList(type: Business, view_at = 0 as number) {
v-for="historyItem in historys"
:key="historyItem.kid"
:href="getHistoryUrl(historyItem)"
type="topBar"
m="last:b-4" p="2"
rounded="$bew-radius"
hover:bg="$bew-fill-2"
@@ -370,6 +370,7 @@ function getHistoryList(type: Business, view_at = 0 as number) {
<div text="$bew-text-2 sm" m="t-4" flex="~" align="items-center">
<ALink
:href="`https://space.bilibili.com/${historyItem.author_mid}`"
type="topBar"
>
{{ historyItem.author_name }}
</ALink>

View File

@@ -11,8 +11,6 @@ import type { TopBarMomentResult } from '~/models/moment/topBarMoment'
import api from '~/utils/api'
import { getCSRF, scrollToTop } from '~/utils/main'
import ALink from './ALink.vue'
type MomentType = 'video' | 'live' | 'article'
interface MomentTab { type: MomentType, name: any }
interface MomentCard {
@@ -316,6 +314,7 @@ defineExpose({
</div>
<ALink
href="https://t.bilibili.com/"
type="topBar"
flex="~ items-center"
>
<span text="sm">{{ $t('common.view_all') }}</span>
@@ -354,6 +353,7 @@ defineExpose({
v-for="(moment, index) in moments"
:key="index"
:href="moment.link"
type="topBar"
flex="~ justify-between"
m="b-2" p="2"
rounded="$bew-radius"
@@ -374,6 +374,7 @@ defineExpose({
/>
<ALink
:href="moment.authorJumpUrl"
type="topBar"
rounded="1/2"
w="40px" h="40px" m="r-4"
bg="$bew-skeleton"
@@ -393,6 +394,7 @@ defineExpose({
<ALink
:href="moment.authorJumpUrl"
type="topBar"
font-bold
>
{{ moment.author }}

View File

@@ -3,8 +3,6 @@ import { useI18n } from 'vue-i18n'
import { getUserID } from '~/utils/main'
import ALink from './ALink.vue'
const { t } = useI18n()
const list = computed((): { name: string, url: string, icon: string }[] => [
@@ -31,6 +29,7 @@ const list = computed((): { name: string, url: string, icon: string }[] => [
v-for="item in list"
:key="item.name"
:href="item.url"
type="topBar"
pos="relative"
p="x-4 y-2"
bg="hover:$bew-fill-2"

View File

@@ -3,8 +3,6 @@ import { useI18n } from 'vue-i18n'
import api from '~/utils/api'
import ALink from './ALink.vue'
const { t } = useI18n()
const list = ref<{ name: string, url: string, unreadCount: number, icon: string }[]>([
{
@@ -85,6 +83,7 @@ function getUnreadMessageCount() {
v-for="item in list"
:key="item.name"
:href="item.url"
type="topBar"
pos="relative"
flex="~ items-center justify-between gap-2"
p="x-4 y-2"

View File

@@ -10,7 +10,6 @@ import { LV0_ICON, LV1_ICON, LV2_ICON, LV3_ICON, LV4_ICON, LV5_ICON, LV6_ICON, L
import { getCSRF, getUserID, isHomePage } from '~/utils/main'
import type { UserInfo, UserStat } from '../types'
import ALink from './ALink.vue'
const props = defineProps<{
userInfo: UserInfo
@@ -155,12 +154,14 @@ function handleClickChannel() {
<ALink
class="group mr-4"
href="https://account.bilibili.com/account/coin"
type="topBar"
>
{{ $t('topbar.user_dropdown.money') + (userInfo.money ?? '-') }}
</ALink>
<ALink
class="group"
href="https://pay.bilibili.com/pay-v2-web/bcoin_index"
type="topBar"
>
{{
$t('topbar.user_dropdown.b_coins') + (userInfo.wallet?.bcoin_balance ?? '-')
@@ -170,6 +171,7 @@ function handleClickChannel() {
<ALink
href="//account.bilibili.com/account/record?type=exp"
type="topBar"
block mb-2 w-full
flex="~ col justify-center items-start"
>
@@ -223,6 +225,7 @@ function handleClickChannel() {
class="channel-info-item"
:href="`https://space.bilibili.com/${mid}/fans/follow`"
:title="`${userStat.following}`"
type="topBar"
>
<div class="num">
{{ userStat.following ? numFormatter(userStat.following) : '0' }}
@@ -233,6 +236,7 @@ function handleClickChannel() {
class="channel-info-item"
:href="`https://space.bilibili.com/${mid}/fans/fans`"
:title="`${userStat.follower}`"
type="topBar"
>
<div class="num">
{{ userStat.follower ? numFormatter(userStat.follower) : '0' }}
@@ -243,6 +247,7 @@ function handleClickChannel() {
class="channel-info-item"
:href="`https://space.bilibili.com/${mid}/dynamic`"
:title="`${userStat.dynamic_count}`"
type="topBar"
>
<div class="num">
{{

View File

@@ -9,8 +9,6 @@ import api from '~/utils/api'
import { calcCurrentTime } from '~/utils/dataFormatter'
import { removeHttpFromUrl } from '~/utils/main'
import ALink from './ALink.vue'
const watchLaterList = reactive<VideoItem[]>([])
const isLoading = ref<boolean>()
const viewAllUrl = computed((): string => {
@@ -82,12 +80,14 @@ function getAllWatchLaterList() {
<div flex="~ gap-4">
<ALink
:href="playAllUrl"
type="topBar"
flex="~" items="center"
>
<span text="sm">{{ $t('common.play_all') }}</span>
</ALink>
<ALink
:href="viewAllUrl"
type="topBar"
flex="~" items="center"
>
<span text="sm">{{ $t('common.view_all') }}</span>
@@ -131,6 +131,7 @@ function getAllWatchLaterList() {
v-for="item in watchLaterList"
:key="item.aid"
:href="getWatchLaterUrl(item.bvid)"
type="topBar"
m="last:b-4" p="2"
rounded="$bew-radius"
hover:bg="$bew-fill-2"

View File

@@ -8,7 +8,6 @@ import { numFormatter } from '~/utils/dataFormatter'
import { LV0_ICON, LV1_ICON, LV2_ICON, LV3_ICON, LV4_ICON, LV5_ICON, LV6_ICON, LV6_LIGHTNING_ICON } from '~/utils/lvIcons'
import { getCSRF, getUserID, isHomePage } from '~/utils/main'
import ALink from '../components/ALink.vue'
import type { UserInfo, UserStat } from '../types'
const props = defineProps<{
@@ -206,6 +205,7 @@ function getLvIcon(level: number, isSigma: boolean = false): string {
class="channel-info-item"
:href="`https://space.bilibili.com/${mid}/fans/follow`"
:title="`${userStat.following}`"
type="topBar"
>
<div class="num">
{{ userStat.following ? numFormatter(userStat.following) : '0' }}
@@ -216,6 +216,7 @@ function getLvIcon(level: number, isSigma: boolean = false): string {
class="channel-info-item"
:href="`https://space.bilibili.com/${mid}/fans/fans`"
:title="`${userStat.follower}`"
type="topBar"
>
<div class="num">
{{ userStat.follower ? numFormatter(userStat.follower) : '0' }}
@@ -226,6 +227,7 @@ function getLvIcon(level: number, isSigma: boolean = false): string {
class="channel-info-item"
:href="`https://space.bilibili.com/${mid}/dynamic`"
:title="`${userStat.dynamic_count}`"
type="topBar"
>
<div class="num">
{{

View File

@@ -218,12 +218,11 @@ function handelMouseLeave() {
clearTimeout(mouseLeaveTimeOut.value)
}
function handleClick(event: MouseEvent) {
async function handleClick(event: MouseEvent) {
videoCurrentTime.value = getCurrentTime()
if (settings.value.videoCardLinkOpenMode === 'drawer' && videoUrl.value && !event.ctrlKey && !event.metaKey) {
event.preventDefault()
openIframeDrawer(videoUrl.value)
}
}
@@ -300,9 +299,11 @@ provide('getVideoType', () => props.type!)
w="full"
rounded="$bew-radius"
>
<a
<ALink
:style="{ display: horizontal ? 'flex' : 'block', gap: horizontal ? '1.5rem' : '0' }"
:href="videoUrl" :target="settings.videoCardLinkOpenMode === 'currentTab' ? '_self' : '_blank'"
:href="videoUrl"
type="videoCard"
custom-click-event
@mouseenter="handleMouseEnter"
@mouseleave="handelMouseLeave"
@click="handleClick"
@@ -610,7 +611,7 @@ provide('getVideoType', () => props.type!)
</div>
</div>
</div>
</a>
</ALink>
</div>
</div>

View File

@@ -3,7 +3,6 @@ import { useDateFormat } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import { useBewlyApp } from '~/composables/useAppProvider'
import { settings } from '~/logic'
import type { HistoryResult, List as HistoryItem } from '~/models/history/history'
import { Business } from '~/models/history/history'
import type { HistorySearchResult, List as HistorySearchItem } from '~/models/video/historySearch'
@@ -12,7 +11,6 @@ import { calcCurrentTime } from '~/utils/dataFormatter'
import { getCSRF, removeHttpFromUrl } from '~/utils/main'
const { t } = useI18n()
const { openIframeDrawer } = useBewlyApp()
const isLoading = ref<boolean>()
const noMoreContent = ref<boolean>(false)
@@ -143,19 +141,19 @@ function getHistoryUrl(item: HistoryItem): string {
// Video
if (item.history.business === Business.ARCHIVE) {
if (item?.videos && item.videos > 0)
return `//www.bilibili.com/video/${item.history.bvid}?p=${item.history.page}`
return `//www.bilibili.com/video/${item.history.bvid}`
return `https://www.bilibili.com/video/${item.history.bvid}?p=${item.history.page}`
return `https://www.bilibili.com/video/${item.history.bvid}`
}
// Live
else if (item.history.business === Business.LIVE) {
return `//live.bilibili.com/${item.history.oid}`
return `https://live.bilibili.com/${item.history.oid}`
}
// Article
else if (item.history.business === Business.ARTICLE || item.history.business === Business.ARTICLE_LIST) {
if (item.history.cid === 0)
return `//www.bilibili.com/read/cv${item.history.oid}`
return `https://www.bilibili.com/read/cv${item.history.oid}`
else
return `//www.bilibili.com/read/cv${item.history.cid}`
return `https://www.bilibili.com/read/cv${item.history.cid}`
}
return ''
}
@@ -235,16 +233,15 @@ function jumpToLoginPage() {
</h3>
<!-- historyList -->
<TransitionGroup name="list">
<a
<ALink
v-for="(historyItem, index) in historyList"
:key="historyItem.kid"
:href="settings.videoCardLinkOpenMode === 'drawer' ? undefined : getHistoryUrl(historyItem)"
:target="settings.videoCardLinkOpenMode === 'currentTab' ? '_self' : '_blank'"
type="videoCard"
:href="getHistoryUrl(historyItem)"
block
class="group"
flex
cursor-pointer
@click="settings.videoCardLinkOpenMode === 'drawer' && openIframeDrawer(getHistoryUrl(historyItem))"
>
<!-- time slot -->
<div
@@ -463,7 +460,7 @@ function jumpToLoginPage() {
</button>
</div>
</section>
</a>
</ALink>
</TransitionGroup>
<!-- no more content -->

View File

@@ -163,13 +163,13 @@ function jumpToLoginPage() {
<template v-else>
<!-- watcher later list -->
<TransitionGroup name="list">
<a
<ALink
v-for="(item, index) in currentWatchLaterList"
:key="item.aid"
:href="`https://www.bilibili.com/list/watchlater?bvid=${item.bvid}`"
type="videoCard"
class="group"
flex cursor-pointer
@click.prevent="handleLinkClick(`https://www.bilibili.com/list/watchlater?bvid=${item.bvid}`)"
>
<section
rounded="$bew-radius"
@@ -295,10 +295,9 @@ function jumpToLoginPage() {
<div i-tabler:trash />
</button>
</div>
</div>
</section>
</a>
</ALink>
</TransitionGroup>
<!-- loading -->
<Transition name="fade">