七十二家房客-观看平台v162
This commit is contained in:
parent
f3a5c1e9c9
commit
320c7e3b9e
@ -3,7 +3,7 @@
|
||||
<div class="section-head d-flex justify-content-between align-items-center mb-3">
|
||||
<div>
|
||||
<h4 class="section-title mb-1">推荐展示</h4>
|
||||
<div class="section-subtitle">基于当前节目数据生成展示内容</div>
|
||||
<!--<div class="section-subtitle">基于当前节目数据生成展示内容</div>-->
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-secondary d-none d-lg-inline-flex"
|
||||
|
||||
@ -1,20 +1,59 @@
|
||||
<template>
|
||||
<div class="container-fluid qishier-page py-3">
|
||||
<div class="row g-3">
|
||||
<!-- 顶部标题区 -->
|
||||
<div class="col-12">
|
||||
<div class="top-card card border-0 shadow-sm">
|
||||
<div class="card-body d-flex flex-wrap justify-content-between align-items-center gap-3">
|
||||
<div class="card-body d-flex flex-wrap justify-content-between align-items-start gap-3">
|
||||
<div class="page-main-info">
|
||||
<!--<div class="page-tag mb-2">在线播放</div>-->
|
||||
|
||||
<div>
|
||||
<template v-if="currentEpisode">
|
||||
<div class="episode-badges mb-2">
|
||||
<span class="info-badge playing">当前播放</span><span class="mx-2">|</span>
|
||||
<span class="info-badge year">发布时间:{{ formatDate(currentEpisode.releasedAt) }}</span>
|
||||
<span class="info-badge year">时长:{{ formatDuration(currentEpisode.timeLength) }}</span>
|
||||
</div>
|
||||
|
||||
<h2 class="mb-2 page-title">{{ currentEpisode.title }}</h2>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<h2 class="mb-2 page-title">{{ columnInfo.name || '七十二家房客播放器' }}</h2>
|
||||
<div class="episode-meta mb-2">正在加载节目数据...</div>
|
||||
</template>
|
||||
|
||||
<div class="page-subtitle">
|
||||
共 {{ allEpisodeList.length }} 条 | 最后更新:{{ updatedAtText }}
|
||||
共 {{ allEpisodeList.length }} 条
|
||||
<span class="mx-2">|</span>
|
||||
最后更新:{{ updatedAtText }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header-actions d-flex flex-wrap gap-2">
|
||||
<button class="btn btn-dark btn-sm px-3" @click="handleRefresh">
|
||||
刷新数据
|
||||
</button>
|
||||
|
||||
<button class="btn btn-outline-dark btn-sm px-3" @click="openSource">
|
||||
数据来源
|
||||
</button>
|
||||
|
||||
<button class="btn btn-outline-primary btn-sm px-3" @click="openGitRepo">
|
||||
Git仓库:v162
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<div class="card-body d-flex flex-wrap gap-2 align-items-center">
|
||||
<!-- 控制区 -->
|
||||
<div class="col-12">
|
||||
<div class="control-card card border-0 shadow-sm">
|
||||
<div class="card-body d-flex flex-wrap justify-content-between align-items-center gap-3">
|
||||
<div class="d-flex flex-wrap gap-2 align-items-center">
|
||||
<button class="btn btn-outline-dark btn-sm" @click="playPrevEpisode" :disabled="!hasPrevEpisode">
|
||||
上一集
|
||||
</button>
|
||||
@ -23,49 +62,37 @@
|
||||
下一集
|
||||
</button>
|
||||
|
||||
<div class="form-check form-switch ms-2">
|
||||
<div class="form-check form-switch ms-1">
|
||||
<input id="autoNext" v-model="autoNext" class="form-check-input" type="checkbox" />
|
||||
<label class="form-check-label" for="autoNext">自动下一集</label>
|
||||
<label class="form-check-label small" for="autoNext">自动下一集</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 align-items-center">
|
||||
<select v-model="playMode" class="form-select form-select-sm mode-select">
|
||||
<option value="asc">顺序播放</option>
|
||||
<option value="desc">倒序播放</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-dark btn-sm px-3" @click="handleRefresh">刷新数据</button>
|
||||
<button class="btn btn-outline-dark btn-sm px-3" @click="openGitRepo">git仓库:v1.6</button>
|
||||
<button class="btn btn-warning btn-sm px-3" @click="openSource">数据来源:荔枝网</button>
|
||||
|
||||
<select v-model="selectedYear" class="form-select form-select-sm filter-select">
|
||||
<option value="all">全部年份</option>
|
||||
<option v-for="year in years" :key="year" :value="String(year)">
|
||||
{{ year }}年
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<select v-model="selectedMonth" class="form-select form-select-sm filter-select">
|
||||
<option value="all">全部月份</option>
|
||||
<option v-for="month in months" :key="month" :value="String(month)">
|
||||
{{ month }}月
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<div class="col-12">-->
|
||||
<!-- <div class="toolbar-card card border-0 shadow-sm">-->
|
||||
<!-- <div class="card-body d-flex flex-wrap gap-2 align-items-center">-->
|
||||
<!-- <button class="btn btn-outline-dark btn-sm" @click="playPrevEpisode" :disabled="!hasPrevEpisode">-->
|
||||
<!-- 上一集-->
|
||||
<!-- </button>-->
|
||||
|
||||
<!-- <button class="btn btn-outline-dark btn-sm" @click="playNextEpisode" :disabled="!hasNextEpisode">-->
|
||||
<!-- 下一集-->
|
||||
<!-- </button>-->
|
||||
|
||||
<!-- <div class="form-check form-switch ms-2">-->
|
||||
<!-- <input id="autoNext" v-model="autoNext" class="form-check-input" type="checkbox" />-->
|
||||
<!-- <label class="form-check-label" for="autoNext">自动下一集</label>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <select v-model="playMode" class="form-select form-select-sm mode-select">-->
|
||||
<!-- <option value="asc">顺序播放</option>-->
|
||||
<!-- <option value="desc">倒序播放</option>-->
|
||||
<!-- </select>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!-- 左侧播放器 -->
|
||||
<div class="col-xl-8 col-lg-7">
|
||||
<div class="content-card card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
@ -76,15 +103,21 @@
|
||||
@ended-next="handleEndedNext"
|
||||
/>
|
||||
|
||||
<div v-if="currentEpisode" class="episode-info mt-3">
|
||||
<div class="episode-badge mb-2">当前播放</div>
|
||||
<h4 class="mb-2 episode-title">{{ currentEpisode.title }}</h4>
|
||||
<div class="episode-meta">
|
||||
发布时间:{{ formatDate(currentEpisode.releasedAt) }}
|
||||
<span class="mx-2">|</span>
|
||||
时长:{{ formatDuration(currentEpisode.timeLength) }}
|
||||
</div>
|
||||
</div>
|
||||
<!--<div v-if="currentEpisode" class="episode-info-card mt-3">-->
|
||||
<!-- <div class="d-flex flex-wrap justify-content-between align-items-start gap-3">-->
|
||||
<!-- <div class="flex-grow-1">-->
|
||||
<!-- <div class="episode-badges mb-2">-->
|
||||
<!-- <span class="info-badge playing">当前播放</span>-->
|
||||
<!-- <span class="info-badge year">{{ selectedYear === 'all' ? '全部年份' : `${selectedYear}年` }}</span>-->
|
||||
<!-- <span class="info-badge month">{{ selectedMonth === 'all' ? '全部月份' : `${selectedMonth}月` }}</span>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <div class="episode-meta">-->
|
||||
<!-- 你可以使用上方筛选快速定位剧集,播放器会自动记录上次观看位置。-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<div v-if="errorMsg" class="alert alert-danger mt-3 mb-0">
|
||||
{{ errorMsg }}
|
||||
@ -95,12 +128,11 @@
|
||||
:episodes="showcaseEpisodes"
|
||||
@select="playEpisode"
|
||||
/>
|
||||
|
||||
<!--<QishierProjectLinks />-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧列表 -->
|
||||
<div class="col-xl-4 col-lg-5">
|
||||
<QishierEpisodeList
|
||||
:episodes="displayEpisodeList"
|
||||
@ -116,13 +148,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { getAllQishierList, refreshQishierCache, type EpisodeData } from '@/api/qishier'
|
||||
import { getCurrentEpisodeId, saveCurrentEpisodeId } from '@/utils/playHistory'
|
||||
import QishierVideoPlayer from '@/components/qishier/QishierVideoPlayer.vue'
|
||||
import QishierEpisodeList from '@/components/qishier/QishierEpisodeList.vue'
|
||||
import QishierShowcase from '@/components/qishier/QishierShowcase.vue'
|
||||
import QishierProjectLinks from '@/components/qishier/QishierProjectLinks.vue'
|
||||
|
||||
const columnInfo = reactive({
|
||||
name: '',
|
||||
@ -151,16 +182,12 @@ const displayEpisodeList = computed(() => {
|
||||
|
||||
if (selectedYear.value !== 'all') {
|
||||
const year = Number(selectedYear.value)
|
||||
list = list.filter(
|
||||
item => new Date(item.releasedAt).getFullYear() === year
|
||||
)
|
||||
list = list.filter(item => new Date(item.releasedAt).getFullYear() === year)
|
||||
}
|
||||
|
||||
if (selectedMonth.value !== 'all') {
|
||||
const month = Number(selectedMonth.value)
|
||||
list = list.filter(
|
||||
item => new Date(item.releasedAt).getMonth() + 1 === month
|
||||
)
|
||||
list = list.filter(item => new Date(item.releasedAt).getMonth() + 1 === month)
|
||||
}
|
||||
|
||||
if (playMode.value === 'desc') {
|
||||
@ -189,6 +216,10 @@ function openSource() {
|
||||
window.open('https://www1.gdtv.cn/', '_blank')
|
||||
}
|
||||
|
||||
function openGitRepo() {
|
||||
window.open('https://git.a-hxin.cn/ahxin/72QishierPlayer.git', '_blank')
|
||||
}
|
||||
|
||||
function handlePlayerError(message: string) {
|
||||
errorMsg.value = message
|
||||
}
|
||||
@ -201,8 +232,28 @@ function getEpisodeYear(item: EpisodeData) {
|
||||
return String(new Date(item.releasedAt).getFullYear())
|
||||
}
|
||||
|
||||
function openGitRepo() {
|
||||
window.open('https://git.a-hxin.cn/ahxin/72QishierPlayer.git', '_blank')
|
||||
function getEpisodeMonth(item: EpisodeData) {
|
||||
return String(new Date(item.releasedAt).getMonth() + 1)
|
||||
}
|
||||
|
||||
function rebuildMonthsByYear() {
|
||||
let source = [...allEpisodeList.value]
|
||||
|
||||
if (selectedYear.value !== 'all') {
|
||||
const year = Number(selectedYear.value)
|
||||
source = source.filter(item => new Date(item.releasedAt).getFullYear() === year)
|
||||
}
|
||||
|
||||
months.value = [
|
||||
...new Set(source.map(item => new Date(item.releasedAt).getMonth() + 1))
|
||||
].sort((a, b) => a - b)
|
||||
|
||||
if (selectedMonth.value !== 'all') {
|
||||
const currentMonth = Number(selectedMonth.value)
|
||||
if (!months.value.includes(currentMonth)) {
|
||||
selectedMonth.value = 'all'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchAllEpisodes() {
|
||||
@ -221,19 +272,15 @@ async function fetchAllEpisodes() {
|
||||
return
|
||||
}
|
||||
|
||||
months.value = [
|
||||
...new Set(
|
||||
allEpisodeList.value.map(item =>
|
||||
new Date(item.releasedAt).getMonth() + 1
|
||||
)
|
||||
)
|
||||
].sort((a, b) => a - b)
|
||||
rebuildMonthsByYear()
|
||||
|
||||
const savedEpisodeId = getCurrentEpisodeId()
|
||||
const savedEpisode = allEpisodeList.value.find(item => item.id === savedEpisodeId)
|
||||
|
||||
if (savedEpisode) {
|
||||
selectedYear.value = getEpisodeYear(savedEpisode)
|
||||
rebuildMonthsByYear()
|
||||
selectedMonth.value = getEpisodeMonth(savedEpisode)
|
||||
currentEpisode.value = savedEpisode
|
||||
return
|
||||
}
|
||||
@ -241,6 +288,8 @@ async function fetchAllEpisodes() {
|
||||
const firstEpisode = allEpisodeList.value[0]
|
||||
if (firstEpisode) {
|
||||
selectedYear.value = getEpisodeYear(firstEpisode)
|
||||
rebuildMonthsByYear()
|
||||
selectedMonth.value = getEpisodeMonth(firstEpisode)
|
||||
currentEpisode.value = firstEpisode
|
||||
}
|
||||
} catch (error: any) {
|
||||
@ -262,6 +311,8 @@ async function handleRefresh() {
|
||||
async function playEpisode(item: EpisodeData) {
|
||||
currentEpisode.value = item
|
||||
selectedYear.value = getEpisodeYear(item)
|
||||
rebuildMonthsByYear()
|
||||
selectedMonth.value = getEpisodeMonth(item)
|
||||
errorMsg.value = ''
|
||||
saveCurrentEpisodeId(item.id)
|
||||
}
|
||||
@ -304,6 +355,10 @@ function formatDuration(seconds: number): string {
|
||||
return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
watch(selectedYear, () => {
|
||||
rebuildMonthsByYear()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
void fetchAllEpisodes()
|
||||
})
|
||||
@ -319,16 +374,31 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.top-card,
|
||||
.toolbar-card,
|
||||
.control-card,
|
||||
.content-card {
|
||||
border-radius: 18px;
|
||||
border-radius: 20px;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.page-main-info {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.page-tag {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #8a5a00;
|
||||
background: rgba(255, 193, 7, 0.18);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-weight: 700;
|
||||
font-weight: 800;
|
||||
color: #212529;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
@ -336,31 +406,77 @@ onMounted(() => {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mode-select {
|
||||
width: 140px;
|
||||
width: 132px;
|
||||
}
|
||||
|
||||
.episode-info {
|
||||
padding: 2px 2px 6px;
|
||||
.filter-select {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.episode-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 10px;
|
||||
.episode-info-card {
|
||||
padding: 16px 18px;
|
||||
border-radius: 18px;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #f8f9fb 100%);
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.episode-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.info-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 5px 10px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 193, 7, 0.18);
|
||||
color: #9a6a00;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.info-badge.playing {
|
||||
background: rgba(255, 193, 7, 0.18);
|
||||
color: #9a6a00;
|
||||
}
|
||||
|
||||
.info-badge.year {
|
||||
background: rgba(13, 110, 253, 0.1);
|
||||
color: #0d6efd;
|
||||
}
|
||||
|
||||
.episode-title {
|
||||
color: #212529;
|
||||
font-weight: 700;
|
||||
font-weight: 800;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.episode-meta {
|
||||
color: #6c757d;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.episode-actions {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.header-actions {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.episode-info-card {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.episode-actions {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
近期最新的集数 这个新出的集数颜色那里 改成不是黄色 我想要好看点的颜色 还有 页面太空白了 别整那么空了,看着难受 clearfix
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user