126 lines
5.1 KiB
TypeScript
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 |