chore: knip (#744)

This commit is contained in:
Stephen Zhou
2024-05-11 11:36:10 +08:00
committed by GitHub
parent 4b69aaf8d3
commit 2cea2dfaf9
15 changed files with 1217 additions and 1285 deletions

View File

@@ -1,371 +0,0 @@
<script lang="ts" setup>
import type { Ref, UnwrapNestedRefs } from 'vue'
import { useDateFormat } from '@vueuse/core'
import type { Comment, UserCardInfo, VideoInfo } from './types'
import { getCSRF, removeHttpFromUrl } from '~/utils/main'
import { calcTimeSince, numFormatter } from '~/utils/dataFormatter'
import { useApiClient } from '~/composables/api'
const api = useApiClient()
const videoContent = ref() as Ref<HTMLElement>
// const commentContent = ref() as Ref<HTMLElement>
const danmukuContent = ref() as Ref<HTMLElement>
const recommendedContent = ref() as Ref<HTMLElement>
const videoEpisodeList = ref() as Ref<HTMLElement>
const videoInfo = reactive<VideoInfo | NonNullable<unknown>>({}) as UnwrapNestedRefs<VideoInfo>
const userCardInfo = reactive<UserCardInfo | NonNullable<unknown>>({}) as UnwrapNestedRefs<UserCardInfo>
// const videoPlayerPreviousPosition = reactive<{ right: string; bottom: string }>({ right: '0', bottom: '0' })
const commentList = reactive<Comment[]>([])
const commentPageInfo = reactive<any>({})
onMounted(async () => {
window.onload = () => {
nextTick(async () => {
const videoPlayer = document.querySelector('#playerWrap') as HTMLElement
if (videoContent.value && videoPlayer)
videoContent.value.appendChild(videoPlayer)
const danmukuBox = document.querySelector('#danmukuBox') as HTMLElement
if (danmukuContent.value && danmukuBox)
danmukuContent.value.appendChild(danmukuBox)
const recoList = document.querySelector('#reco_list') as HTMLElement
if (recommendedContent.value && recoList)
recommendedContent.value.appendChild(recoList)
const multiPage = document.querySelector('#multi_page') as HTMLElement
if (videoEpisodeList.value && multiPage)
videoEpisodeList.value.appendChild(multiPage)
// setupVideoSize()
// const videoPlayerContainer = document.querySelector('#bilibili-player .bpx-player-container') as HTMLElement
// videoPlayerContainer.dataset.screen = 'normal'
// videoPlayerContainer.style.right = '0'
// videoPlayerContainer.style.bottom = '0'
const app = document.querySelector('#app') as HTMLElement
app.innerHTML = ''
await getVideoInfo()
getVideoComments()
})
}
})
// watch(() => 'location.href', async (newValue, oldValue) => {
// console.log('location change')
// await getVideoInfo()
// getVideoComments()
// }, { deep: true })
onUnmounted(() => {
window.onload = () => {}
})
async function getVideoInfo() {
// e.g. https://www.bilibili.com/video/BV1vx4y1V7VD/
const url = location.href
// url.match(/video\/[0-9a-zA-Z]*/) = ['video/BV1vx4y1V7VD/', index: 25, input: 'https://www.bilibili.com/video/BV1vx4y1V7VD/', groups: undefined]
// url.match(/video\/[0-9a-zA-Z]*/)[0] = 'video/BV1vx4y1V7VD/'
const videoId = url.match(/video\/[0-9a-zA-Z]*\/?/)![0].split('/')[1]
const isBV = videoId.startsWith('BV')
let res
if (isBV)
res = await api.video.getVideoInfo({ bvid: videoId })
else
res = await api.video.getVideoInfo({ aid: videoId.replace('av', '') })
if (res.code === 0) {
Object.assign(videoInfo, res.data.View)
Object.assign(userCardInfo, res.data.Card)
}
}
// function setupVideoSize() {
// const videoPlayerContainer = document.querySelector('#bilibili-player .bpx-player-container') as HTMLElement
// const playerTopWrap = videoPlayerContainer.querySelector('.bpx-player-top-wrap') as HTMLElement
// const playerTopIssue = videoPlayerContainer.querySelector('.bpx-player-top-issue') as HTMLElement
// const playerStateWrap = videoPlayerContainer.querySelector('.bpx-player-state-wrap') as HTMLElement
// const playerStatePlay = videoPlayerContainer.querySelector('.bpx-player-state-play') as HTMLElement
// const playerToastWrap = videoPlayerContainer.querySelector('.bpx-player-toast-wrap') as HTMLElement
// const playerControlWrap = videoPlayerContainer.querySelector('.bpx-player-control-wrap') as HTMLElement
// const playerControlMask = videoPlayerContainer.querySelector('.bpx-player-control-mask') as HTMLElement
// videoPlayerPreviousPosition.right = videoPlayerContainer.style.right ?? '0'
// videoPlayerPreviousPosition.bottom = videoPlayerContainer.style.bottom ?? '0'
// videoPlayerContainer.dataset.screen = 'normal'
// window.onscroll = () => {
// if (window.scrollY > videoPlayerContainer.offsetHeight) {
// videoPlayerContainer.dataset.screen = 'mini'
// playerTopWrap.style.display = 'none'
// playerTopIssue.style.display = 'none'
// playerStateWrap.style.display = 'none'
// playerStatePlay.style.display = 'none'
// playerToastWrap.style.display = 'none'
// playerControlWrap.style.display = 'none'
// playerControlMask.style.display = 'none'
// if (videoPlayerPreviousPosition.right && videoPlayerPreviousPosition.bottom) {
// videoPlayerContainer.style.right = structuredClone(videoPlayerPreviousPosition.right)
// videoPlayerContainer.style.bottom = structuredClone(videoPlayerPreviousPosition.bottom)
// }
// }
// else {
// videoPlayerContainer.dataset.screen = 'normal'
// videoPlayerPreviousPosition.right = structuredClone(videoPlayerContainer.style.right)
// videoPlayerPreviousPosition.bottom = structuredClone(videoPlayerContainer.style.bottom)
// console.log(videoPlayerPreviousPosition)
// videoPlayerContainer.style.right = '0'
// videoPlayerContainer.style.bottom = '0'
// playerTopWrap.style.display = ''
// playerTopIssue.style.display = ''
// playerStateWrap.style.display = ''
// playerStatePlay.style.display = ''
// playerToastWrap.style.display = ''
// playerControlWrap.style.display = ''
// playerControlMask.style.display = ''
// }
// }
// }
function getVideoComments() {
api.video.getVideoComments({
csrf: getCSRF(),
oid: videoInfo.aid,
pn: 1,
sort: 1,
}).then((res) => {
if (res.code === 0) {
Object.assign(commentList, res.data.replies)
Object.assign(commentPageInfo, res.data.page)
}
})
}
function setupCommentEmote(content: string, emote: any) {
let result = `${content}`
if (!emote || Object.keys(emote).length === 0)
return content
Object.keys(emote).forEach((key) => {
if (emote[key].meta.size === 1) {
result = result.replaceAll(key, `
<img
src="${removeHttpFromUrl(emote[key].url)}@40w_40h.webp" width="20" height="20"
style="vertical-align: text-bottom; display: inline"
/>`)
}
else {
result = result.replaceAll(key, `
<img
src="${removeHttpFromUrl(emote[key].url)}@112w_112h.webp" width="50" height="50"
style="vertical-align: text-bottom; display: inline"
/>`)
}
})
return result
}
</script>
<template>
<div class="video-page-wrapper" flex gap-6 m-auto>
<main w="3/4" min-w-640px flex="~ col gap-4">
<div ref="videoContent" bg="$bew-fill-1" />
<!-- <DPlayer /> -->
<section>
<p text-2xl fw-600>
{{ videoInfo.title }}
</p>
<p text="$bew-text-2" flex gap-4 lh-6>
<span>{{ $t('common.view', { count: videoInfo.stat?.view }) }}</span>
<span>{{ videoInfo.stat?.danmaku }} danmaku</span>
</p>
</section>
<section bg="$bew-content-solid-1" rounded="$bew-radius" p-4>
<section
flex justify-between bg="$bew-fill-1" rounded="$bew-radius" p-2
mb-4 relative z-1
overflow-hidden
>
<img
v-if="videoInfo.owner?.face"
:src="`${videoInfo.owner?.face}@60w_60h_1c`"
:alt="videoInfo.owner.name" object-cover
blur-lg pointer-events-none z--1
w-full h-full pos="absolute top-0 left-0"
opacity-30
>
<div flex relative z-1>
<img
v-if="videoInfo.owner?.face"
:src="`${videoInfo.owner?.face}@60w_60h_1c`"
:alt="videoInfo.owner.name" rounded="$bew-radius" aspect-square
w-40px mr-4 shrink-0
>
<div>
<p text-base fw-500>
{{ videoInfo.owner?.name }}
</p>
<p text="sm $bew-text-2">
{{ numFormatter(userCardInfo.follower) }} subscribers
</p>
<!-- <Button @click="changeUrl">
click me
</Button> -->
<!-- <p>{{ videoInfo.owner }}</p> -->
</div>
</div>
</section>
<section style="white-space: pre-wrap" v-html="(videoInfo.desc_v2 ?? [''])[0].raw_text" />
</section>
<!-- Comments -->
<section>
<h2 text-2xl bold mb-6>
{{ commentPageInfo.acount }} Comments
</h2>
<ul>
<li
v-for="comment in commentList" :key="comment.rpid" flex="~ gap-4" mb-6
>
<div shrink-0>
<img
:src="`${removeHttpFromUrl(comment.member.avatar)}@60w_60h_1c`" alt=""
aspect-square w-40px
rounded="$bew-radius"
>
</div>
<div w-full>
<!-- username & sending time -->
<div mb-2 lh-6 flex gap-2 items-center>
<h3 fw-600>
{{ comment.member.uname }}
</h3>
<div class="group">
<span text="$bew-text-2" cursor-pointer v-text="calcTimeSince(comment.ctime * 1000)" />
<span
bg="black dark:white" text="white dark:black sm"
p="x-2 y-1" ml-2 rounded-8 pointer-events-none
opacity="0 group-hover:100" duration-300
v-text="useDateFormat(comment.ctime * 1000, 'YYYY-MM-DD HH:mm:ss').value"
/>
</div>
</div>
<span v-html="setupCommentEmote(comment.content.message, comment.content.emote)" />
<div>
<ul v-if="comment.replies" mt-6>
<li
v-for="reply in comment.replies" :key="reply.rpid" flex="~ gap-4" mb-6
>
<div shrink-0>
<img
:src="`${removeHttpFromUrl(reply.member.avatar)}@60w_60h_1c`" alt=""
aspect-square w-30px
rounded="$bew-radius"
>
</div>
<div>
<!-- username & sending time -->
<div mb-2 lh-6 flex gap-2 items-center>
<h3 fw-600>
{{ reply.member.uname }}
</h3>
<div class="group">
<span text="$bew-text-2" cursor-pointer v-text="calcTimeSince(reply.ctime * 1000)" />
<span
bg="black dark:white" text="white dark:black sm"
p="x-2 y-1" ml-2 rounded-8 pointer-events-none
opacity="0 group-hover:100"
duration-300
v-text="useDateFormat(reply.ctime * 1000, 'YYYY-MM-DD HH:mm:ss').value"
/>
</div>
</div>
<span v-html="setupCommentEmote(reply.content.message, reply.content.emote)" />
</div>
</li>
</ul>
</div>
</div>
</li>
</ul>
</section>
</main>
<aside w="1/4" min-w-400px>
<section ref="danmukuContent" rounded="$bew-radius" shadow="$bew-shadow-1" mb-3 />
<section ref="videoEpisodeList" rounded="$bew-radius" shadow="$bew-shadow-1" />
<section ref="recommendedContent" />
</aside>
</div>
</template>
<style lang="scss" scoped>
.video-page-wrapper {
width: 100%;
min-width: 1040px;
}
@media screen and (max-height: 800px) {
.video-page-wrapper {
width: 80%;
}
}
@media screen and (max-height: 600px) {
.video-page-wrapper {
width: 60%;
}
}
@media screen and (max-height: 500px) {
.video-page-wrapper {
width: 40%;
}
}
</style>
<style lang="scss">
#bilibili-player {
width: 100%;
}
#bilibili-player-placeholder {
--at-apply: shadow-$bew-shadow-2
}
.bpx-player-container {
--at-apply: shadow-none;
}
.bpx-player-sending-area:before {
background-color: var(--bew-fill-3)
}
.bpx-player-sending-bar .bpx-player-video-inputbar{
background-color: var(--bew-fill-1)
}
#danmukuBox .bpx-player-auxiliary {
--bpx-aux-header-bg: var(--bew-content-solid-1);
--bpx-aux-header-font: var(--bew-text-1);
--bpx-aux-content-bg: var(--bew-content-solid-1);
--bpx-aux-content-font1: var(--bew-text-2);
--bpx-aux-content-font2: var(--bew-text-3);
}
.video-page-game-card-small {
display: none;
}
</style>

View File

@@ -1,309 +0,0 @@
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/info.md#%E8%8E%B7%E5%8F%96%E8%A7%86%E9%A2%91%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AFweb%E7%AB%AF
export interface VideoInfo {
bvid: string
aid: number
videos: number
tid: number
tname: string
copyright: number
pic: string
title: string
pubdate: number
ctime: number
desc: string
desc_v2: [
{
raw_text: string
type: number
biz_id: number
},
]
state: number
duration: number
mission_id: number
rights: {
bp: number
elec: number
download: number
movie: number
pay: number
hd5: number
no_reprint: number
autoplay: number
ugc_pay: number
is_cooperation: number
ugc_pay_preview: number
no_background: number
clean_mode: number
is_stein_gate: number
is_360: number
no_share: number
arc_pay: number
free_watch: number
}
owner: {
mid: number
name: string
face: string
}
staff: Array<{
mid: number
title: string
name: string
face: string
follower: number
}>
stat: {
aid: number
view: number
danmaku: number
reply: number
favorite: number
coin: number
share: number
now_rank: number
his_rank: number
like: number
dislike: number
evaluation: string
argue_msg: string
}
dynamic: string
cid: number
dimension: {
width: number
height: number
rotate: number
}
season_id: number
premiere: null
teenage_mode: number
is_chargeable_season: boolean
is_story: false
no_cache: boolean
pages: Array<{
cid: number
page: number
from: string
part: string
duration: number
vid: string
weblink: string
dimension: {
width: number
height: number
rotate: number
}
first_frame: string
}>
subtitle: {
allow_submit: boolean
list: string[]
}
ugc_season: {
id: number
title: string
cover: string
mid: number
intro: string
sign_state: number
attribute: number
sections: [
{
season_id: number
id: number
title: string
type: number
episodes: Array<{
season_id: number
section_id: number
id: number
aid: number
cid: number
title: string
attribute: number
arc: {
aid: number
videos: number
type_id: number
type_name: string
copyright: number
pic: string
title: string
pubdate: number
ctime: number
desc: string
state: number
duration: number
rights: {
bp: number
elec: number
download: number
movie: number
pay: number
hd5: number
no_reprint: number
autoplay: number
ugc_pay: number
is_cooperation: number
ugc_pay_preview: number
arc_pay: number
free_watch: number
}
author: {
mid: number
name: string
face: string
}
stat: {
aid: number
view: number
danmaku: number
reply: number
fav: number
coin: number
share: number
now_rank: number
his_rank: number
like: number
dislike: number
evaluation: string
argue_msg: string
}
dynamic: string
dimension: {
width: number
height: number
rotate: number
}
desc_v2: null
is_chargeable_season: boolean
is_blooper: boolean
}
page: {
cid: number
page: number
from: string
part: string
duration: number
vid: string
weblink: string
dimension: {
width: number
height: number
rotate: number
}
}
bvid: string
}>
},
]
stat: {
season_id: number
view: number
danmaku: number
reply: number
fav: number
coin: number
share: number
now_rank: number
his_rank: number
like: number
}
ep_count: number
season_type: number
is_pay_season: boolean
}
is_season_display: boolean
user_garb: {
url_image_ani_cut: string
}
like_icon: string
need_jump_bv: boolean
}
export interface UserCardInfo {
card: any
following: boolean
follower: number
}
export interface Comment {
rpid: number
oid: number
type: number
mid: number
root: 0
parent: 0
dialog: 0
count: 0
rcount: 0
state: 0
fansgrade: 0
attr: 0
ctime: number
like: 0
action: 0
member: {
mid: number
uname: string
sex: string
avatar: string
rank: string
level_info: {
current_level: number
current_min: number
current_exp: number
next_exp: number
}
// 'official_verify': {
// 'type': -1
// 'desc': ''
// }
// 'vip': {
// 'vipType': 1
// 'vipDueDate': number
// 'dueRemark': ''
// 'accessStatus': 0
// 'vipStatus': 0
// 'vipStatusWarn': ''
// 'themeType': 0
// 'label': {
// 'path': ''
// 'text': ''
// 'label_theme': ''
// 'text_color': ''
// 'bg_style': 0
// 'bg_color': ''
// 'border_color': ''
// 'use_img_label': true
// 'img_label_uri_hans': ''
// 'img_label_uri_hant': ''
// 'img_label_uri_hans_static': 'https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png'
// 'img_label_uri_hant_static': 'https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png'
// }
// 'avatar_subscript': 0
// 'nickname_color': ''
// }
}
content: {
message: string
members: []
jump_url: NonNullable<unknown>
max_line: 6
emote: any
}
replies?: Comment[]
up_action: {
like: false
reply: false
}
invisible: false
folder: {
has_folded: false
is_folded: false
rule: string
}
dynamic_id_str: string
}