mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Add match popup (#5055)
This commit is contained in:
parent
fd02464c5e
commit
5619761be4
@ -6,7 +6,8 @@ import { logo } from './logo/logo'
|
|||||||
import { home } from './home/home'
|
import { home } from './home/home'
|
||||||
import { games } from './games/games'
|
import { games } from './games/games'
|
||||||
import { blanks } from './flexible-blank/flexible-blank'
|
import { blanks } from './flexible-blank/flexible-blank'
|
||||||
import { bangumi, music, shop, match, creations, lives } from './simple-links/simple-links'
|
import { bangumi, music, shop, creations, lives } from './simple-links/simple-links'
|
||||||
|
import { match } from './match/match'
|
||||||
import { upload } from './upload/upload'
|
import { upload } from './upload/upload'
|
||||||
import { search } from './search/search'
|
import { search } from './search/search'
|
||||||
import { feeds } from './feeds/feeds'
|
import { feeds } from './feeds/feeds'
|
||||||
|
|||||||
234
registry/lib/components/style/custom-navbar/match/MatchPopup.vue
Normal file
234
registry/lib/components/style/custom-navbar/match/MatchPopup.vue
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, reactive, ref } from 'vue'
|
||||||
|
import { VLoading, VButton } from '@/ui'
|
||||||
|
import { bilibiliApi, getJsonWithCredentials, postTextWithCredentials } from '@/core/ajax'
|
||||||
|
import { CustomNavbarItem } from '../custom-navbar-item'
|
||||||
|
import { usePopper } from '../mixins'
|
||||||
|
import type { MatchInfo, MatchPreviewItem } from './types'
|
||||||
|
import { getCsrf } from '@/core/utils'
|
||||||
|
import { logError } from '@/core/utils/log'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: CustomNavbarItem
|
||||||
|
container: HTMLElement
|
||||||
|
}>()
|
||||||
|
const popper = usePopper(props)
|
||||||
|
|
||||||
|
const loading = ref(true)
|
||||||
|
const matchInfo = ref<MatchInfo | undefined>(undefined)
|
||||||
|
const bannerItems = computed(() => matchInfo.value?.banner)
|
||||||
|
const hotItems = computed(() => matchInfo.value?.hot)
|
||||||
|
const previewItems = computed(() => matchInfo.value?.preview)
|
||||||
|
const loadMatchInfo = async () => {
|
||||||
|
matchInfo.value = reactive(
|
||||||
|
await bilibiliApi<MatchInfo>(
|
||||||
|
getJsonWithCredentials('https://api.bilibili.com/x/web-interface/nav/game'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
const toggleSubscribe = async (card: MatchPreviewItem) => {
|
||||||
|
const isSubscribed = card.fav_status !== 0
|
||||||
|
try {
|
||||||
|
await postTextWithCredentials(
|
||||||
|
isSubscribed
|
||||||
|
? 'https://api.bilibili.com/x/esports/fav/del'
|
||||||
|
: 'https://api.bilibili.com/x/esports/fav/add',
|
||||||
|
new URLSearchParams({
|
||||||
|
cid: card.cid.toString(),
|
||||||
|
csrf: getCsrf(),
|
||||||
|
}).toString(),
|
||||||
|
)
|
||||||
|
if (isSubscribed) {
|
||||||
|
card.fav_status = 0
|
||||||
|
} else {
|
||||||
|
card.fav_status = 1
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
popupShow() {
|
||||||
|
popper.popupShow()
|
||||||
|
loadMatchInfo()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="custom-navbar-match-popup">
|
||||||
|
<div v-if="loading" class="loading-container">
|
||||||
|
<VLoading />
|
||||||
|
</div>
|
||||||
|
<div v-if="!loading" class="custom-navbar-match-panel">
|
||||||
|
<div class="custom-navbar-match-left-panel">
|
||||||
|
<a
|
||||||
|
v-for="card of bannerItems"
|
||||||
|
:key="card.jump_url"
|
||||||
|
class="banner-match-card"
|
||||||
|
:href="card.jump_url"
|
||||||
|
>
|
||||||
|
<img :src="card.cover" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="custom-navbar-match-panel-separator"></div>
|
||||||
|
<div class="custom-navbar-match-right-panel">
|
||||||
|
<div class="hot-match-list">
|
||||||
|
<div class="hot-match-list-title">热门赛事</div>
|
||||||
|
<a
|
||||||
|
v-for="card of hotItems"
|
||||||
|
:key="card.jump_url"
|
||||||
|
:href="card.jump_url"
|
||||||
|
:title="card.name"
|
||||||
|
class="hot-match-card"
|
||||||
|
>
|
||||||
|
<div class="hot-match-card-title">
|
||||||
|
{{ card.name }}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="preview-match-list">
|
||||||
|
<div class="preview-match-list-title">精彩预告</div>
|
||||||
|
<a
|
||||||
|
v-for="card of previewItems"
|
||||||
|
:key="card.jump_url"
|
||||||
|
:href="card.jump_url"
|
||||||
|
:title="card.name"
|
||||||
|
class="preview-match-card"
|
||||||
|
>
|
||||||
|
<!-- spell-checker: disable-next-line -->
|
||||||
|
<div class="preview-match-date">{{ card.stime }}</div>
|
||||||
|
<div class="preview-match-title">{{ card.name }}</div>
|
||||||
|
<VButton
|
||||||
|
class="preview-match-subscribe"
|
||||||
|
:type="card.fav_status === 0 ? 'primary' : 'light'"
|
||||||
|
@click.prevent="toggleSubscribe(card)"
|
||||||
|
>
|
||||||
|
{{ card.fav_status === 0 ? '订阅' : '已订阅' }}
|
||||||
|
</VButton>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="scss">
|
||||||
|
@import 'common';
|
||||||
|
|
||||||
|
.custom-navbar-match-popup {
|
||||||
|
width: 650px;
|
||||||
|
font-size: 12px;
|
||||||
|
$gap: 12px;
|
||||||
|
@include v-stretch();
|
||||||
|
|
||||||
|
.loading-container {
|
||||||
|
flex-grow: 1;
|
||||||
|
@include v-center();
|
||||||
|
justify-content: center;
|
||||||
|
height: 240px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-navbar-match-panel {
|
||||||
|
@include h-stretch($gap);
|
||||||
|
padding: $gap;
|
||||||
|
.custom-navbar-match-left-panel {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 0 0 45%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: $gap;
|
||||||
|
.banner-match-card {
|
||||||
|
overflow: hidden;
|
||||||
|
@include round-corner(6px);
|
||||||
|
&:first-child {
|
||||||
|
grid-column: 1 / 3;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
background: #8882;
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
transition: transform 0.2s ease-out;
|
||||||
|
}
|
||||||
|
&:hover img {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.custom-navbar-match-panel-separator {
|
||||||
|
width: 1px;
|
||||||
|
background-color: #8882;
|
||||||
|
}
|
||||||
|
.custom-navbar-match-right-panel {
|
||||||
|
@include v-stretch($gap);
|
||||||
|
justify-content: space-between;
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
|
padding: 6px 4px;
|
||||||
|
|
||||||
|
.hot-match-list-title,
|
||||||
|
.preview-match-list-title {
|
||||||
|
font-size: large;
|
||||||
|
@include semi-bold();
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.hot-match-list,
|
||||||
|
.preview-match-list {
|
||||||
|
@include v-stretch();
|
||||||
|
counter-reset: match-item;
|
||||||
|
}
|
||||||
|
.hot-match-card {
|
||||||
|
@include h-center(6px);
|
||||||
|
padding: 5px 0;
|
||||||
|
&-title {
|
||||||
|
@include single-line();
|
||||||
|
transition: color 0.2s ease-out;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
flex: 1 0 0;
|
||||||
|
}
|
||||||
|
&::before {
|
||||||
|
counter-increment: match-item;
|
||||||
|
content: counter(match-item);
|
||||||
|
@include semi-bold();
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
&:hover .hot-match-card-title {
|
||||||
|
color: var(--theme-color) !important;
|
||||||
|
}
|
||||||
|
&:nth-child(2)::before {
|
||||||
|
color: #e64747;
|
||||||
|
}
|
||||||
|
&:nth-child(3)::before {
|
||||||
|
color: #ff6e42;
|
||||||
|
}
|
||||||
|
&:nth-child(4)::before {
|
||||||
|
color: #ff9900;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.preview-match-card {
|
||||||
|
@include h-center(4px);
|
||||||
|
padding: 5px 0;
|
||||||
|
.preview-match-date {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.preview-match-title {
|
||||||
|
flex: 1 0 0;
|
||||||
|
@include single-line();
|
||||||
|
}
|
||||||
|
.preview-match-subscribe.be-button {
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
&:hover .preview-match-title {
|
||||||
|
color: var(--theme-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
14
registry/lib/components/style/custom-navbar/match/match.ts
Normal file
14
registry/lib/components/style/custom-navbar/match/match.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||||
|
|
||||||
|
export const match: CustomNavbarItemInit = {
|
||||||
|
name: 'match',
|
||||||
|
displayName: '赛事',
|
||||||
|
content: '赛事',
|
||||||
|
|
||||||
|
touch: true,
|
||||||
|
href: 'https://www.bilibili.com/v/game/match/',
|
||||||
|
|
||||||
|
boundingWidth: 650,
|
||||||
|
noPopupPadding: true,
|
||||||
|
popupContent: () => import('./MatchPopup.vue').then(m => m.default),
|
||||||
|
}
|
||||||
31
registry/lib/components/style/custom-navbar/match/types.ts
Normal file
31
registry/lib/components/style/custom-navbar/match/types.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
export interface MatchInfo {
|
||||||
|
hot: MatchHotItem[]
|
||||||
|
banner: MatchBannerItem[]
|
||||||
|
preview: MatchPreviewItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MatchHotItem {
|
||||||
|
index: number
|
||||||
|
cid: number
|
||||||
|
desc: string
|
||||||
|
status: number
|
||||||
|
name: string
|
||||||
|
jump_url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MatchBannerItem {
|
||||||
|
index: number
|
||||||
|
cover: string
|
||||||
|
jump_url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MatchPreviewItem {
|
||||||
|
index: number
|
||||||
|
cid: number
|
||||||
|
name: string
|
||||||
|
desc: string
|
||||||
|
fav_status: number
|
||||||
|
jump_url: string
|
||||||
|
// spell-checker: disable-next-line
|
||||||
|
stime: string
|
||||||
|
}
|
||||||
@ -32,11 +32,6 @@ export const shop = getSimpleLinkItem({
|
|||||||
displayName: '会员购',
|
displayName: '会员购',
|
||||||
href: 'https://show.bilibili.com',
|
href: 'https://show.bilibili.com',
|
||||||
})
|
})
|
||||||
export const match = getSimpleLinkItem({
|
|
||||||
name: 'match',
|
|
||||||
displayName: '赛事',
|
|
||||||
href: 'https://www.bilibili.com/v/game/match/',
|
|
||||||
})
|
|
||||||
export const creations = getSimpleLinkItem({
|
export const creations = getSimpleLinkItem({
|
||||||
name: 'creations',
|
name: 'creations',
|
||||||
displayName: '创作中心',
|
displayName: '创作中心',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user