refactor: move api response types to ~/models/apiModels

This commit is contained in:
Hakadao
2023-12-04 00:37:59 +08:00
parent 69e16d780c
commit a6769f0f0d
18 changed files with 790 additions and 305 deletions

View File

@@ -1,14 +1,15 @@
<script setup lang="ts">
// import PopularAnimeCarousel from './components/PopularAnimeCarousel.vue'
import AnimeTimeTable from './components/AnimeTimeTable.vue'
import type { AnimeItem, PopularAnime } from './types'
import { getUserID, openLinkToNewTab } from '~/utils/main'
import { numFormatter } from '~/utils/dataFormatter'
import emitter from '~/utils/mitt'
import type { List as WatchListItem, WatchListResult } from '~/models/apiModels/anime/watchList'
import type { List as PopularAnimeItem, PopularAnimeResult } from '~/models/apiModels/anime/popular'
import type { ItemSubItem as RecommendationItem, RecommendationResult } from '~/models/apiModels/anime/recommendation'
const animeWatchList = reactive<AnimeItem[]>([])
const recommendAnimeList = reactive<AnimeItem[]>([])
const popularAnimeList = reactive<AnimeItem[]>([])
const animeWatchList = reactive<WatchListItem[]>([])
const recommendAnimeList = reactive<RecommendationItem[]>([])
const popularAnimeList = reactive<PopularAnimeItem[]>([])
const cursor = ref<number>(0)
const isLoadingAnimeWatchList = ref<boolean>()
const isLoadingPopularAnime = ref<boolean>()
@@ -40,13 +41,13 @@ function getAnimeWatchList() {
pn: 1,
ps: 30,
})
.then((response) => {
.then((response: WatchListResult) => {
const {
code,
data: { list },
} = response
if (code === 0)
Object.assign(animeWatchList, list as AnimeItem[])
Object.assign(animeWatchList, list as WatchListItem[])
})
.catch(() => Object.assign(animeWatchList, []))
.finally(() => {
@@ -61,14 +62,14 @@ function getRecommendAnimeList() {
contentScriptQuery: 'getRecommendAnimeList',
coursor: cursor.value,
})
.then((response) => {
.then((response: RecommendationResult) => {
const {
code,
data: { items, coursor, has_next },
} = response
if (code === 0 && has_next) {
if (recommendAnimeList.length === 0)
Object.assign(recommendAnimeList, items[0].sub_items as AnimeItem[])
Object.assign(recommendAnimeList, items[0].sub_items as RecommendationItem[])
else recommendAnimeList.push(...items[0].sub_items)
cursor.value = coursor
@@ -85,13 +86,13 @@ function getPopularAnimeList() {
.sendMessage({
contentScriptQuery: 'getPopularAnimeList',
})
.then((response) => {
.then((response: PopularAnimeResult) => {
const {
code,
result: { list },
} = response
if (code === 0)
Object.assign(popularAnimeList, list as PopularAnime[])
Object.assign(popularAnimeList, list as PopularAnimeItem[])
})
.catch(() => {})
.finally(() => isLoadingPopularAnime.value = false)
@@ -255,3 +256,4 @@ function getPopularAnimeList() {
--at-apply: mb-8 mt-14 first:mt-0;
}
</style>
~/models/apiModels/anime/watchList

View File

@@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n'
import browser from 'webextension-polyfill'
import type { AnimeTimeTableItem } from '../types'
import { removeHttpFromUrl } from '~/utils/main'
import type { Result as TimetableItem, TimetableResult } from '~/models/apiModels/anime/timetable'
const { t } = useI18n()
@@ -31,10 +32,10 @@ function getAnimeTimeTable() {
.sendMessage({
contentScriptQuery: 'getAnimeTimeTable',
})
.then((res) => {
.then((res: TimetableResult) => {
const { code, result } = res
if (code === 0)
Object.assign(animeTimeTable, result as AnimeTimeTableItem[])
Object.assign(animeTimeTable, result as TimetableItem[])
})
}
</script>

View File

@@ -1,105 +0,0 @@
<script setup lang="ts">
import type { PopularAnime } from '../types'
const popularAnimeList = reactive<PopularAnime[]>([])
const activatedAnime = ref<PopularAnime>()
const bannerContent = ref<HTMLElement>()
const bannerHeight = ref<number>(0)
onload = () => {
bannerHeight.value = bannerContent.value?.offsetHeight as number
}
onresize = () => {
bannerHeight.value = bannerContent.value?.offsetHeight as number
}
onMounted(() => {
getPopularAnimeList()
})
function getPopularAnimeList() {
browser.runtime
.sendMessage({
contentScriptQuery: 'getPopularAnimeList',
})
.then((response) => {
const {
code,
result: { list },
} = response
if (code === 0) {
Object.assign(popularAnimeList, list.slice(0, 7) as PopularAnime[])
activatedAnime.value = popularAnimeList[0]
}
})
}
</script>
<template>
<div ref="bannerContent" w-full h-800px pos="absolute top-0 left-0" z="-1">
<!-- banner mask -->
<div
pos="absolute bottom-0 left-0"
w-full
h-300px
bg="gradient-to-b gradient-from-transparent gradient-to-$bew-bg"
z-1
/>
<div
:style="{
backgroundImage: `url(${activatedAnime?.ss_horizontal_cover})`,
}"
bg="cover center"
duration-600
w-full
h-full
pos="absolute"
after:content-none
after:pos="absolute top-0 left-0"
after:w-full
after:h-full
/>
</div>
<!-- banner -->
<div h-800px z-1 pos="relative" flex justify-center>
<div>
<!-- <img
:src="activatedAnime?.ss_horizontal_cover.replace('https:', '')"
pointer-events-none
rounded="$bew-radius"
h="[calc(100%-170px)]"
> -->
<!-- <div text="2xl white" p-4 pos="relative" bg="black opacity-60">
{{ activatedAnime?.title }}
</div> -->
</div>
</div>
<div flex="~ justify-between" m="t--350px">
<ul
w="1/3"
ml-auto
flex
overflow-hidden
z-1
relative
>
<li
v-for="(item, index) in popularAnimeList"
:key="index"
pr-2
flex="~ 1 gap-2 shrink-0"
@mouseover="activatedAnime = item"
>
<img :src="item.cover.replace('https:', '')">
<!-- <div flex items-center>
{{ item.title }}
</div> -->
</li>
</ul>
</div>
</template>
<style lang="scss" scoped></style>

View File

@@ -1,90 +0,0 @@
export interface PopularAnime {
badge: '独家' | '会员抢先' | '会员专享' | '出品'
badge_info: {
bg_color: string
bg_color_night: string
text: string
}
badge_type: number
copyright: string
cover: string // 豎向封面
new_ep: {
cover: string
index_show: string
}
rank: number // 排名
rating: string // 評分
season_id: number
ss_horizontal_cover: string // 橫向封面
stat: {
danmaku: number // 彈幕
follow: number // 訂閲
series_follow: number // 當前系列訂閲???
view: number // 觀看數
}
title: string
url: string
}
export interface AnimeItem {
cover: string
horizontal_cover_16_9?: string
episode_id: number
evaluate: string
hover: {
img: string
text: string[] // 番劇風格
}
link: string
url: string
rank_id: number
rating: string
rating_count: number
report: object
season_id: number
season_type: number
stat: {
danmaku: number
duration: number
view: number
series_follow: number
}
sub_title: string
subtitle: string
text: string[]
title: string
user_status: {
follow: number
}
progress: string
is_finish: 1 | 0 // 是否已經完結
total_count: number // 當前集數
styles: string[] // 番劇風格
rank: number
}
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/bangumi/timeline.md#%E8%8E%B7%E5%8F%96%E7%95%AA%E5%89%A7%E6%88%96%E5%BD%B1%E8%A7%86%E6%97%B6%E9%97%B4%E7%BA%BF
export interface AnimeTimeTableItem {
date: string
date_ts: number
day_of_week: number
episodes: Array<{
cover: string
delay: number
delay_id: number
delay_index: string
delay_reason: string
ep_cover: string
episode_id: number
follows: string
plays: string
pub_index: string
pub_time: string
pub_ts: number
published: number
season_id: number
square_cover: string
title: string
}>
is_today: number
}

View File

@@ -4,11 +4,13 @@ import { getCSRF, getUserID, openLinkToNewTab, removeHttpFromUrl } from '~/utils
import type { FavoriteCategory, FavoriteResource } from '~/components/Topbar/types'
import emitter from '~/utils/mitt'
import { settings } from '~/logic'
import type { Media as FavoriteItem, FavoritesResult } from '~/models/apiModels/video/favorite'
import type { List as CategoryItem, FavoritesCategoryResult } from '~/models/apiModels/video/favoriteCategory'
const { t } = useI18n()
const favoriteCategories = reactive<Array<FavoriteCategory>>([])
const favoriteResources = reactive<Array<FavoriteResource>>([])
const favoriteCategories = reactive<CategoryItem[]>([])
const favoriteResources = reactive<FavoriteItem[]>([])
const categoryOptions = reactive<Array<{ value: any; label: string }>>([])
const selectedCategory = ref<FavoriteCategory>()
@@ -69,7 +71,7 @@ async function getFavoriteCategories() {
contentScriptQuery: 'getFavoriteCategories',
mid: getUserID(),
})
.then((res) => {
.then((res: FavoritesCategoryResult) => {
if (res.code === 0) {
Object.assign(favoriteCategories, res.data.list)
@@ -99,7 +101,7 @@ async function getFavoriteResources(
isFullPageLoading.value = true
isLoading.value = true
try {
const res = await browser.runtime
const res: FavoritesResult = await browser.runtime
.sendMessage({
contentScriptQuery: 'getFavoriteResources',
mediaId,

View File

@@ -1,11 +1,14 @@
<script setup lang="ts">
import { useDateFormat } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import { HistoryType } from './types'
import type { HistoryItem } from './types'
// import type { HistoryItem } from './types'
import { getCSRF, openLinkToNewTab, removeHttpFromUrl } from '~/utils/main'
import { calcCurrentTime } from '~/utils/dataFormatter'
import emitter from '~/utils/mitt'
import { Business } from '~/models/apiModels/video/history'
import type { List as HistoryItem, HistoryResult } from '~/models/apiModels/video/history'
import type { List as HistorySearchItem, HistorySearchResult } from '~/models/apiModels/video/historySearch'
const { t } = useI18n()
@@ -16,6 +19,10 @@ const currentPageNum = ref<number>(1)
const keyword = ref<string>()
const historyStatus = ref<boolean>()
const HistoryBusiness = computed(() => {
return Business
})
watch(
() => keyword.value,
(newValue, oldValue) => {
@@ -76,7 +83,7 @@ function getHistoryList() {
? historyList[historyList.length - 1].view_at
: 0,
})
.then((res) => {
.then((res: HistoryResult) => {
if (res.code === 0) {
if (Array.isArray(res.data.list) && res.data.list.length > 0)
historyList.push(...res.data.list)
@@ -101,7 +108,7 @@ function searchHistoryList() {
pn: currentPageNum.value++,
keyword: keyword.value,
})
.then((res) => {
.then((res: HistorySearchResult) => {
if (res.code === 0) {
if (historyList.length !== 0 && res.data.list.length < 20) {
isLoading.value = false
@@ -109,8 +116,8 @@ function searchHistoryList() {
return
}
res.data.list.forEach((item: HistoryItem) => {
historyList.push(item)
res.data.list.forEach((item: HistorySearchItem) => {
historyList.push(item as HistoryItem)
})
noMoreContent.value = false
@@ -162,7 +169,7 @@ function getHistoryUrl(item: HistoryItem) {
function getHistoryItemCover(item: HistoryItem) {
if (item.history.business === 'article')
return removeHttpFromUrl(item.covers[0])
return removeHttpFromUrl(`${item.covers[0]}`)
return removeHttpFromUrl(item.cover)
}
@@ -322,7 +329,7 @@ function jumpToLoginPage() {
>
<span
v-if="historyItem.history.business !== HistoryType.Archive"
v-if="historyItem.history.business !== HistoryBusiness.ARCHIVE"
pos="absolute right-0 top-0"
bg="$bew-theme-color"
text="xs white"
@@ -331,19 +338,19 @@ function jumpToLoginPage() {
rounded="$bew-radius-half"
>
<template
v-if="historyItem.history.business === HistoryType.Live"
v-if="historyItem.history.business === HistoryBusiness.LIVE"
>
Livestreaming
</template>
<template
v-else-if="
historyItem.history.business === HistoryType.Article
historyItem.history.business === HistoryBusiness.ARCHIVE
"
>
Article
</template>
<template
v-else-if="historyItem.history.business === HistoryType.PGC"
v-else-if="historyItem.history.business === HistoryBusiness.PGC"
>
Anime
</template>
@@ -351,8 +358,8 @@ function jumpToLoginPage() {
<div
v-if="
historyItem.history.business === HistoryType.Archive
|| historyItem.history.business === HistoryType.PGC
historyItem.history.business === HistoryBusiness.ARCHIVE
|| historyItem.history.business === HistoryBusiness.PGC
"
pos="absolute bottom-0 right-0"
bg="black opacity-60"
@@ -374,8 +381,8 @@ function jumpToLoginPage() {
<div w-full pos="absolute bottom-0" bg="white opacity-60">
<Progress
v-if="
historyItem.history.business === HistoryType.Archive
|| historyItem.history.business === HistoryType.PGC
historyItem.history.business === HistoryBusiness.ARCHIVE
|| historyItem.history.business === HistoryBusiness.PGC
"
:percentage="
(historyItem.progress / historyItem.duration) * 100

View File

@@ -1,31 +0,0 @@
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/history&toview/history.md#%E8%8E%B7%E5%8F%96%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%E5%88%97%E8%A1%A8_web%E7%AB%AF
export enum HistoryType {
Archive = 'archive', // archive稿件
PGC = 'pgc', // pgc剧集 (番剧 / 影视)
Live = 'live', // live直播
ArticleList = 'article-list', // article-list文集
Article = 'article', // article文章
}
export interface HistoryItem {
title: string
cover: string
covers: Array<string>
history: {
business: HistoryType
epid: number
bvid: string
part: string
oid: number
}
author_name: string
author_face: string
author_mid: string
view_at: number
progress: number
duration: number
kid: number
live_status: 0 | 1 // 0未开播 1已开播
uri: string
show_title: string
}

View File

@@ -1,16 +1,16 @@
<script setup lang="ts">
import { useDateFormat } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import type { WatchLaterModel } from './types'
import { getCSRF, openLinkToNewTab, removeHttpFromUrl } from '~/utils/main'
import { calcCurrentTime } from '~/utils/dataFormatter'
import emitter from '~/utils/mitt'
import type { List as VideoItem, WatchLaterResult } from '~/models/apiModels/video/watchLater'
const { t } = useI18n()
const isLoading = ref<boolean>()
const noMoreContent = ref<boolean>()
const watchLaterList = reactive<Array<WatchLaterModel>>([])
const watchLaterList = reactive<VideoItem[]>([])
onMounted(() => {
getAllWatchLaterList()
@@ -36,7 +36,7 @@ function getAllWatchLaterList() {
.sendMessage({
contentScriptQuery: 'getAllWatchLaterList',
})
.then((res) => {
.then((res: WatchLaterResult) => {
if (res.code === 0)
Object.assign(watchLaterList, res.data.list)

View File

@@ -1,44 +0,0 @@
export interface WatchLaterModel {
aid: number
videos: number
tid: number
tname: string
copyright: number
pic: string
title: string
pubdate: number
ctime: number
desc: string
state: number
duration: number
mission_id: number
rights: {}
owner: {
mid: number
name: string
face: string
}
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
}
short_link_v2: string
first_frame: string
count: number
cid: number
progress: number
add_at: number
bvid: string
uri: string
viewed: boolean
enable_vt: number
}