Files
BiliDown/client/src/work/index.ts
T

126 lines
5.1 KiB
TypeScript

import van, { State } from 'vanjs-core'
import { Route, goto } from 'vanjs-router'
import VideoInfoCard from './view/videoInfoCard'
import { checkLogin, GLOBAL_HAS_LOGIN, showErrorPage } from '../mixin'
import { VideoParseResult, VideoInfoCardMode, SectionItem } from './type'
import { IDType, start } from './mixin'
import { ParseModalComp } from './view/parseModal'
import InputBox from './view/inputBox'
import { Modal } from 'bootstrap'
import { LoadingBox } from '../view'
import { getPopularVideoBvIds } from './data'
const { div } = van.tags
export class WorkRoute {
element: HTMLDivElement
/** 输入框内容是否标识为异常 */
urlInvalid = van.state(false)
/** 仅作为类名字符串 */
urlInvalidClass = van.derive(() => this.urlInvalid.val ? 'is-invalid' : '')
urlValue = van.state('')
videoInfoCardData = van.state<VideoParseResult>({
title: '', description: '', cover: '', publishData: '', duration: 0,
pages: [], owner: { face: '', mid: 0, name: '' },
dimension: { width: 0, height: 0, rotate: 0 },
staff: [], status: '', areas: [], styles: [], targetURL: '',
section: []
})
/** 标识视频信息卡片应该显示普通视频还是剧集,值为 `hide` 时隐藏卡片 */
videoInfoCardMode: VideoInfoCardMode = van.state('hide')
ownerFaceHide = van.derive(() => this.videoInfoCardData.val.owner.face == '')
/** 全部选项卡和列表数据 */
allSection
/** 当前选项卡的按钮列表 */
sectionPages
/** 当前选中的按钮列表 */
selectedPages
/** 视频列表批量解析模态框 */
parseModal: Modal
parseModalComp: ParseModalComp
/** 按钮是否处于 `loading` 状态,如果是则按钮设置为 `disabled` */
btnLoading = van.state(false)
/** 页面初始加载的 loading 状态 */
initLoading = van.state(true)
/** 是否是初始的热门推荐结果 */
isInitPopular = van.state(false)
sectionTabsActiveIndex = van.state(0)
constructor() {
const _that = this
this.allSection = van.derive(() => {
const list = (
this.videoInfoCardMode.val == 'season'
|| this.videoInfoCardMode.val == 'video' && this.videoInfoCardData.val.section.length == 0
? [{ title: '正片', pages: this.videoInfoCardData.val.pages }] : []
).concat(this.videoInfoCardData.val.section)
return list
})
this.sectionPages = van.derive(() => {
return this.allSection.val[this.sectionTabsActiveIndex.val]?.pages || []
})
this.selectedPages = van.derive(() => this.sectionPages.val.filter(page => page.selected.val))
this.parseModalComp = new ParseModalComp({ workRoute: this })
van.add(document.body, this.parseModalComp.element)
this.parseModal = new Modal(this.parseModalComp.element)
this.element = Route({
rule: 'work',
Loader() {
return div(
() => _that.initLoading.val ? LoadingBox() : '',
div({ class: 'vstack gap-3', hidden: _that.initLoading },
InputBox(_that),
div({ hidden: () => _that.videoInfoCardMode.val == 'hide' || _that.btnLoading.val },
VideoInfoCard(_that),
),
)
)
},
async onFirst() {
if (!await checkLogin()) return
let idType = this.args[0] as IDType
let value = this.args[1]
// if (!value) return goto('work'), _that.initLoading.val = false
if (!value) {
_that.isInitPopular.val = true
const popularBvidList = await getPopularVideoBvIds()
idType = 'bv'
value = popularBvidList[Math.floor(Math.random() * popularBvidList.length)]
}
if (idType == 'bv' && !value.match(/^BV1[a-zA-Z0-9]+$/)) return goto('work')
if ((idType == 'ep' || idType == 'ss' || idType == 'fav')
&& !value.match(/^\d+$/)) return goto('work')
if (idType == 'bv' && !_that.isInitPopular.val) _that.urlValue.val = value
else if (idType == 'ep' || idType == 'ss') _that.urlValue.val = `${idType}${value}`
start(_that, {
idType,
value,
from: 'onFirst'
}).catch(error => {
const errorMessage = `获取视频信息失败:${error.message}`
showErrorPage(errorMessage)
_that.videoInfoCardMode.val = 'hide'
}).finally(() => {
_that.btnLoading.val = false
_that.isInitPopular.val = false
setTimeout(() => {
_that.initLoading.val = false
}, 200)
})
},
async onLoad() {
if (!GLOBAL_HAS_LOGIN.val) return goto('login')
}
})
}
}
export default () => new WorkRoute().element