mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Add bangumi ranklist
This commit is contained in:
parent
583f44dc59
commit
7d9bf609b3
@ -109,6 +109,8 @@ export default Vue.extend({
|
||||
|
||||
.fresh-home-categories {
|
||||
@include v-stretch();
|
||||
--fresh-home-categories-column-gap: 28px;
|
||||
--fresh-home-categories-header-gap: 12px;
|
||||
&-content {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@ -1,5 +1,160 @@
|
||||
<template>
|
||||
<div class="">
|
||||
bangumi content
|
||||
<div class="fresh-home-categories-bangumi">
|
||||
<div class="fresh-home-categories-bangumi-timeline">
|
||||
<div class="fresh-home-categories-bangumi-timeline-header">
|
||||
<SubHeader>
|
||||
时间表
|
||||
</SubHeader>
|
||||
<VButton
|
||||
v-if="viewLastWeek"
|
||||
class="fresh-home-header-icon-button fresh-home-categories-bangumi-timeline-down"
|
||||
round
|
||||
@click="verticalScroll(false)"
|
||||
>
|
||||
<VIcon icon="mdi-arrow-down" :size="20" />
|
||||
本周
|
||||
</VButton>
|
||||
<VButton
|
||||
v-else
|
||||
class="fresh-home-header-icon-button fresh-home-categories-bangumi-timeline-up"
|
||||
round
|
||||
@click="verticalScroll(true)"
|
||||
>
|
||||
<VIcon icon="mdi-arrow-up" :size="20" />
|
||||
上周
|
||||
</VButton>
|
||||
</div>
|
||||
<BangumiTimeline
|
||||
:view-last-week="viewLastWeek"
|
||||
:api="bangumiDataMap[route].api"
|
||||
/>
|
||||
</div>
|
||||
<div class="fresh-home-categories-bangumi-rank-list">
|
||||
<a
|
||||
class="fresh-home-categories-bangumi-rank-list-header"
|
||||
:href="rankingsLink"
|
||||
target="_blank"
|
||||
>
|
||||
<SubHeader>
|
||||
排行榜
|
||||
</SubHeader>
|
||||
</a>
|
||||
<RankList
|
||||
bangumi-mode
|
||||
:parse-json="parseJson"
|
||||
:api="rankingsApi"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {
|
||||
VButton,
|
||||
VIcon,
|
||||
} from '@/ui'
|
||||
import SubHeader from '../../../SubHeader.vue'
|
||||
import RankList from './RankList.vue'
|
||||
import BangumiTimeline from './BangumiTimeline.vue'
|
||||
import { RankListCard } from './rank-list-card'
|
||||
|
||||
const bangumiDataMap = {
|
||||
anime: {
|
||||
api: 'https://bangumi.bilibili.com/web_api/timeline_global',
|
||||
seasonType: 1,
|
||||
rankingName: 'bangumi',
|
||||
},
|
||||
guochuang: {
|
||||
api: 'https://bangumi.bilibili.com/web_api/timeline_cn',
|
||||
seasonType: 4,
|
||||
// 你永远不知道"国创"在 b 站代码里有多少种叫法...
|
||||
rankingName: 'guochan',
|
||||
},
|
||||
}
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
SubHeader,
|
||||
VButton,
|
||||
VIcon,
|
||||
BangumiTimeline,
|
||||
RankList,
|
||||
},
|
||||
props: {
|
||||
region: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const { route } = this.region.category
|
||||
return {
|
||||
viewLastWeek: false,
|
||||
bangumiDataMap,
|
||||
route,
|
||||
rankingsApi: `https://api.bilibili.com/pgc/season/rank/web/list?day=3&season_type=${bangumiDataMap[route].seasonType}`,
|
||||
rankingsLink: `https://www.bilibili.com/v/popular/rank/${bangumiDataMap[route].rankingName}`,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
verticalScroll(goUp: boolean) {
|
||||
this.viewLastWeek = goUp
|
||||
},
|
||||
parseJson(json: any) {
|
||||
const items = (json.data?.list ?? []) as any[]
|
||||
return items
|
||||
.map(
|
||||
(item): RankListCard => ({
|
||||
id: item.season_id,
|
||||
title: item.title,
|
||||
playCount: item.stat.view,
|
||||
points: item.pts,
|
||||
upHref: item.url,
|
||||
upName: item.new_ep?.index_show ?? item.title,
|
||||
coverUrl: item.new_ep?.cover ?? item.ss_horizontal_cover,
|
||||
videoHref: item.url,
|
||||
}),
|
||||
)
|
||||
.slice(0, 10)
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "common";
|
||||
@import "./effects";
|
||||
|
||||
.fresh-home-categories-bangumi {
|
||||
@include h-stretch(var(--fresh-home-categories-column-gap));
|
||||
|
||||
&-timeline {
|
||||
flex: 1;
|
||||
@include v-stretch(var(--fresh-home-categories-header-gap));
|
||||
&-down {
|
||||
&:hover .be-icon {
|
||||
@include bounce-y(2);
|
||||
}
|
||||
&:active .be-icon {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
&-up {
|
||||
&:hover .be-icon {
|
||||
@include bounce-y(-2);
|
||||
}
|
||||
&:active .be-icon {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
&-header {
|
||||
@include h-center();
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
&-rank-list {
|
||||
@include v-stretch(var(--fresh-home-categories-header-gap));
|
||||
&-header {
|
||||
// Timeline 的 header 中, 图标为 20px, 上下 padding 共 8px, 这里的 line-height 需要保持一致来对齐
|
||||
line-height: calc(20px + 8px);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div class="fresh-home-categories-bangumi-timeline-content">
|
||||
timeline
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { requestMixin } from './mixin'
|
||||
|
||||
interface TimelineSeason {
|
||||
cover: string
|
||||
delay: number
|
||||
ep_id: number
|
||||
favorites: number
|
||||
follow: number
|
||||
is_published: number
|
||||
pub_index: string
|
||||
pub_time: string
|
||||
pub_ts: number
|
||||
season_id: number
|
||||
season_status: number
|
||||
square_cover: string
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
interface TimelineDay {
|
||||
date: string
|
||||
date_ts: number
|
||||
day_of_week: number
|
||||
is_today: number
|
||||
seasons: TimelineSeason[]
|
||||
}
|
||||
|
||||
export default Vue.extend({
|
||||
mixins: [requestMixin],
|
||||
props: {
|
||||
viewLastWeek: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
parseJson(json: any) {
|
||||
return json.result ?? []
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "common";
|
||||
|
||||
.fresh-home-categories-bangumi {
|
||||
&-timeline-content {
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div
|
||||
class="fresh-home-categories-default"
|
||||
>
|
||||
<div class="fresh-home-categories-default">
|
||||
<div class="fresh-home-categories-default-video-column">
|
||||
<div class="fresh-home-categories-default-video-column-item">
|
||||
<SubHeader>
|
||||
@ -22,19 +20,24 @@
|
||||
排行榜
|
||||
</SubHeader>
|
||||
</a>
|
||||
<RankList :api="rankingsApi" />
|
||||
<RankList
|
||||
:parse-json="parseJson"
|
||||
:api="rankingsApi"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { RankListCard } from './rank-list-card'
|
||||
import RankList from './RankList.vue'
|
||||
import VideoSlides from './VideoSlides.vue'
|
||||
import SubHeader from '../../../SubHeader.vue'
|
||||
|
||||
/*
|
||||
TODO: 有几个区表面上是普通视频, 但内容走的还是番剧那套, 所以 RankList 也要换 API
|
||||
视频排行: `https://api.bilibili.com/x/web-interface/ranking/region?rid=${regionCode}&day=3&original=0`
|
||||
视频排行: `https://api.bilibili.com/x/web-interface/ranking/region?day=3&original=0&rid=${regionCode}`
|
||||
番剧排行: `https://api.bilibili.com/pgc/season/rank/web/list?day=3&season_type=${seasonType}`
|
||||
- seasonType: 1 番剧 2 电影 3 纪录片 4 国创 5 电视剧
|
||||
*/
|
||||
|
||||
export default Vue.extend({
|
||||
@ -59,23 +62,42 @@ export default Vue.extend({
|
||||
rankingsLink: `https://www.bilibili.com/v/popular/rank/${this.region.category.route}`,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
parseJson(json: any) {
|
||||
const items = (lodash.get(json, 'data', []) || []) as any[]
|
||||
return items
|
||||
.map(
|
||||
(item): RankListCard => ({
|
||||
id: item.aid,
|
||||
title: item.title,
|
||||
playCount: item.play,
|
||||
points: item.pts,
|
||||
upHref: `https://space.bilibili.com/${item.mid}`,
|
||||
upName: item.author,
|
||||
coverUrl: item.pic,
|
||||
videoHref: `https://www.bilibili.com/video/${item.bvid}`,
|
||||
}),
|
||||
)
|
||||
.slice(0, 10)
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "common";
|
||||
|
||||
.fresh-home-categories-default {
|
||||
@include h-stretch(28px);
|
||||
@include h-stretch(var(--fresh-home-categories-column-gap));
|
||||
|
||||
&-video-column {
|
||||
@include v-stretch(16px);
|
||||
flex: 1;
|
||||
&-item {
|
||||
@include v-stretch(12px);
|
||||
@include v-stretch(var(--fresh-home-categories-header-gap));
|
||||
}
|
||||
}
|
||||
&-rank-list {
|
||||
@include v-stretch(12px);
|
||||
@include v-stretch(var(--fresh-home-categories-header-gap));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<a
|
||||
class="fresh-home-rank-list-rank-item-title"
|
||||
target="_blank"
|
||||
:href="videoHref(firstItem)"
|
||||
:href="firstItem.videoHref"
|
||||
:title="firstItem.title"
|
||||
>
|
||||
{{ firstItem.title }}
|
||||
@ -28,7 +28,7 @@
|
||||
<a
|
||||
class="fresh-home-rank-list-cover"
|
||||
target="_blank"
|
||||
:href="videoHref(firstItem)"
|
||||
:href="firstItem.videoHref"
|
||||
>
|
||||
<DpiImage
|
||||
:src="firstItem.coverUrl"
|
||||
@ -36,9 +36,13 @@
|
||||
/>
|
||||
<UpInfo
|
||||
:up-face-url="firstItem.upFaceUrl"
|
||||
:up-id="firstItem.upID"
|
||||
:href="firstItem.upHref"
|
||||
:up-name="firstItem.upName"
|
||||
/>
|
||||
>
|
||||
<template #fallback-icon>
|
||||
<VIcon v-bind="upInfoProps" />
|
||||
</template>
|
||||
</UpInfo>
|
||||
<div class="fresh-home-rank-list-stats">
|
||||
<VIcon icon="mdi-fire" :size="16" />
|
||||
{{ firstItem.points | formatCount }}
|
||||
@ -50,7 +54,7 @@
|
||||
<a
|
||||
class="fresh-home-rank-list-rank-item"
|
||||
target="_blank"
|
||||
:href="videoHref(secondItem)"
|
||||
:href="secondItem.videoHref"
|
||||
>
|
||||
<div
|
||||
class="fresh-home-rank-list-rank-item-title"
|
||||
@ -60,9 +64,13 @@
|
||||
</div>
|
||||
<UpInfo
|
||||
:up-face-url="secondItem.upFaceUrl"
|
||||
:up-id="secondItem.upID"
|
||||
:href="secondItem.upHref"
|
||||
:up-name="secondItem.upName"
|
||||
/>
|
||||
>
|
||||
<template #fallback-icon>
|
||||
<VIcon v-bind="upInfoProps" />
|
||||
</template>
|
||||
</UpInfo>
|
||||
<div class="fresh-home-rank-list-stats">
|
||||
<VIcon icon="mdi-fire" :size="16" />
|
||||
{{ secondItem.points | formatCount }}
|
||||
@ -73,7 +81,7 @@
|
||||
<a
|
||||
class="fresh-home-rank-list-cover"
|
||||
target="_blank"
|
||||
:href="videoHref(secondItem)"
|
||||
:href="secondItem.videoHref"
|
||||
>
|
||||
<DpiImage
|
||||
:src="secondItem.coverUrl"
|
||||
@ -86,7 +94,7 @@
|
||||
<a
|
||||
class="fresh-home-rank-list-rank-item"
|
||||
target="_blank"
|
||||
:href="videoHref(thirdItem)"
|
||||
:href="thirdItem.videoHref"
|
||||
>
|
||||
<div
|
||||
class="fresh-home-rank-list-rank-item-title"
|
||||
@ -96,9 +104,13 @@
|
||||
</div>
|
||||
<UpInfo
|
||||
:up-face-url="thirdItem.upFaceUrl"
|
||||
:up-id="thirdItem.upID"
|
||||
:href="thirdItem.upHref"
|
||||
:up-name="thirdItem.upName"
|
||||
/>
|
||||
>
|
||||
<template #fallback-icon>
|
||||
<VIcon v-bind="upInfoProps" />
|
||||
</template>
|
||||
</UpInfo>
|
||||
<div class="fresh-home-rank-list-stats">
|
||||
<VIcon icon="mdi-fire" :size="16" />
|
||||
{{ secondItem.points | formatCount }}
|
||||
@ -109,7 +121,7 @@
|
||||
<a
|
||||
class="fresh-home-rank-list-cover"
|
||||
target="_blank"
|
||||
:href="videoHref(thirdItem)"
|
||||
:href="thirdItem.videoHref"
|
||||
>
|
||||
<DpiImage
|
||||
:src="thirdItem.coverUrl"
|
||||
@ -122,7 +134,6 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { VideoCard } from '@/components/feeds/video-card'
|
||||
import UpInfo from '@/components/feeds/UpInfo.vue'
|
||||
import { formatCount } from '@/core/utils/formatters'
|
||||
import {
|
||||
@ -162,6 +173,16 @@ export default Vue.extend({
|
||||
thirdCoverWidth: 139,
|
||||
}),
|
||||
],
|
||||
props: {
|
||||
parseJson: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
bangumiMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
firstItem() {
|
||||
return this.items[0]
|
||||
@ -172,6 +193,15 @@ export default Vue.extend({
|
||||
thirdItem() {
|
||||
return this.items[2]
|
||||
},
|
||||
upInfoProps() {
|
||||
return {
|
||||
size: 18,
|
||||
icon: this.bangumiMode ? 'mdi-television-classic' : 'up-outline',
|
||||
style: {
|
||||
transform: this.bangumiMode ? 'translateY(-1px)' : 'none',
|
||||
},
|
||||
}
|
||||
},
|
||||
firstRow() {
|
||||
return this.items.slice(3, 6)
|
||||
},
|
||||
@ -179,33 +209,6 @@ export default Vue.extend({
|
||||
return this.items.slice(6, 10)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
parseJson(json: any) {
|
||||
const items = (lodash.get(json, 'data', []) || []) as any[]
|
||||
return items
|
||||
.map(
|
||||
(item): VideoCard => ({
|
||||
id: item.aid,
|
||||
aid: parseInt(item.aid),
|
||||
bvid: item.bvid,
|
||||
title: item.title,
|
||||
playCount: item.play,
|
||||
favorites: item.favorites,
|
||||
upID: item.mid,
|
||||
upName: item.author,
|
||||
description: item.description,
|
||||
coverUrl: item.pic,
|
||||
coins: item.coins,
|
||||
durationText: item.duration,
|
||||
points: item.pts,
|
||||
}),
|
||||
)
|
||||
.slice(0, 10)
|
||||
},
|
||||
videoHref(videoCard: VideoCard) {
|
||||
return `https://www.bilibili.com/video/${videoCard.bvid}`
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@ -216,6 +219,7 @@ export default Vue.extend({
|
||||
flex: 1;
|
||||
width: 400px;
|
||||
overflow: hidden;
|
||||
min-height: var(--panel-height);
|
||||
height: var(--panel-height);
|
||||
padding: var(--padding);
|
||||
margin: calc(0px - var(--padding));
|
||||
@ -241,6 +245,7 @@ export default Vue.extend({
|
||||
& &-rank-item {
|
||||
@include card(12px);
|
||||
@include v-stretch();
|
||||
border-radius: var(--home-card-radius);
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
height: var(--rank-item-height);
|
||||
|
||||
@ -222,6 +222,7 @@ export default Vue.extend({
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "common";
|
||||
@import "./effects";
|
||||
|
||||
.fresh-home-video-slides {
|
||||
@include card(12px);
|
||||
@ -235,19 +236,6 @@ export default Vue.extend({
|
||||
padding: var(--main-padding-y) var(--main-padding-x);
|
||||
height: 266px;
|
||||
|
||||
@mixin bounce-x($offset-in-px) {
|
||||
@keyframes bounce-x-#{$offset-in-px} {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(#{$offset-in-px}px);
|
||||
}
|
||||
}
|
||||
animation: bounce-x-#{$offset-in-px} 0.4s ease-out;
|
||||
}
|
||||
|
||||
.cover-placeholder-vertical {
|
||||
height: var(--other-cover-height);
|
||||
width: 0;
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
@mixin bounce-x($offset-in-px) {
|
||||
@keyframes bounce-x-#{$offset-in-px} {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(#{$offset-in-px}px);
|
||||
}
|
||||
}
|
||||
animation: bounce-x-#{$offset-in-px} 0.4s ease-out;
|
||||
}
|
||||
@mixin bounce-y($offset-in-px) {
|
||||
@keyframes bounce-y-#{$offset-in-px} {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(#{$offset-in-px}px);
|
||||
}
|
||||
}
|
||||
animation: bounce-y-#{$offset-in-px} 0.4s ease-out;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
export interface RankListCard {
|
||||
id: string
|
||||
title: string
|
||||
videoHref: string
|
||||
coverUrl: string
|
||||
upFaceUrl?: string
|
||||
upHref: string
|
||||
upName: string
|
||||
points: number
|
||||
playCount: number
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
<a
|
||||
class="be-up-info"
|
||||
:class="{ fallback: !upFaceUrl }"
|
||||
:href="`https://space.bilibili.com/${upId}`"
|
||||
:href="actualHref"
|
||||
:title="upName"
|
||||
target="_blank"
|
||||
>
|
||||
@ -13,10 +13,12 @@
|
||||
:src="upFaceUrl"
|
||||
/>
|
||||
<div v-else class="be-up-info-cover-fallback">
|
||||
<VIcon
|
||||
icon="up-outline"
|
||||
:size="18"
|
||||
/>
|
||||
<slot name="fallback-icon">
|
||||
<VIcon
|
||||
icon="up-outline"
|
||||
:size="18"
|
||||
/>
|
||||
</slot>
|
||||
</div>
|
||||
<div class="be-up-info-name">
|
||||
{{ upName }}
|
||||
@ -32,9 +34,13 @@ export default Vue.extend({
|
||||
VIcon,
|
||||
},
|
||||
props: {
|
||||
href: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
upId: {
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
default: '',
|
||||
},
|
||||
upFaceUrl: {
|
||||
type: String,
|
||||
@ -45,6 +51,14 @@ export default Vue.extend({
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
actualHref() {
|
||||
if (this.href) {
|
||||
return this.href
|
||||
}
|
||||
return `https://space.bilibili.com/${this.upId}`
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user