uniapp-app/pages_app/searchVideo/searchVideo.vue
2025-09-16 16:19:29 +08:00

308 lines
6.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="video-search-page">
<!-- 头部导航栏 -->
<uni-nav-bar
left-icon="left"
:title="title"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
/>
<!-- 顶部排序标签 -->
<view class="tabs">
<view
class="tab"
:class="{ active: activeTab === 0 }"
@click="switchTab(0)"
>
<text class="tab-text">上传时间</text>
</view>
<view
class="tab"
:class="{ active: activeTab === 1 }"
@click="switchTab(1)"
>
<text class="tab-text">点播量</text>
</view>
</view>
<!-- 列表区域 -->
<scroll-view
class="list-scroll"
scroll-y
:show-scrollbar="false"
@scrolltolower="onReachBottom"
:refresher-enabled="true"
:refresher-triggered="isRefreshing"
@refresherrefresh="onRefresh"
>
<view class="video-list">
<view class="video-item" v-for="(item, idx) in videoList" :key="idx" @click="openDetail(item)">
<view class="item-title">{{ item.name }}</view>
<view class="item-meta">
<text class="item-tag">{{ item.public_name }}</text>
</view>
<view class="item-date-views">
<text class="item-date">{{ formatDate(item.create_date) }}</text>
<view class="item-views">
<uni-icons type="eye" size="20" color="#999"></uni-icons>
<text class="views-text">{{ item.readnum }}</text>
</view>
</view>
<view class="item-footer">
<text class="item-source">{{ item.video_type_name }}</text>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad,onShow } from '@dcloudio/uni-app'
import api from '@/api/api.js'
import navTo from '@/utils/navTo.js'
const keywords=ref('')
const title = ref('肝胆视频')
const activeTab = ref(0)
const page = ref(1)
const pageSize = ref(10)
const hasMore = ref(true)
const isRefreshing = ref(false)
const videoList = ref([])
const sort = ref('2')
const from=ref('');
const loadListHuanJiao=async (reset = false) => {
if (reset) {
page.value = 1
hasMore.value = true
videoList.value = []
}
if (!hasMore.value) return
const res = await api.videoBySearchNew({
name: keywords.value,
page: page.value,
pageSize: pageSize.value,
sort: sort.value,
})
if (res.code === 200 && res.data) {
const list = res.data.list || []
videoList.value = [...videoList.value, ...list]
if (list.length < pageSize.value) {
hasMore.value = false
} else {
page.value += 1
}
} else {
hasMore.value = false
}
}
const loadList = async (reset = false) => {
if (reset) {
page.value = 1
hasMore.value = true
videoList.value = []
}
if (!hasMore.value) return
const res = await api.videoBySearchNew({
name: keywords.value,
page: page.value,
pageSize: pageSize.value,
sort: sort.value,
})
if (res.code === 200 && res.data) {
const list = res.data.list || []
videoList.value = [...videoList.value, ...list]
if (list.length < pageSize.value) {
hasMore.value = false
} else {
page.value += 1
}
} else {
hasMore.value = false
}
}
onShow(() => {
if(from.value){
loadListHuanJiao(true)
}else{
loadList(true)
}
})
const onReachBottom = () => {
if(from.value){
loadListHuanJiao(false)
}else{
loadList(false)
}
}
const onRefresh = async () => {
isRefreshing.value = true
if(from.value){
await loadListHuanJiao(true)
}else{
await loadList(true)
}
isRefreshing.value = false
}
onLoad((options) => {
if (options.keywords) {
keywords.value = options.keywords
}
if(options.from){
from.value = options.from
title.value = '患教视频'
}
})
const switchTab = (index) => {
activeTab.value = index;
if(index==0){
sort.value='2'
}else{
sort.value='1'
}
loadList(true)
// 在此触发排序加载逻辑
}
const openDetail = (item) => {
// 打开视频详情/播放页
navTo({
url: `/pages_app/videoDetail/videoDetail?id=${item.uuid}`
})
}
const goBack = () => {
uni.navigateBack()
}
const formatDate = (val) => {
if (!val) return ''
try {
const d = new Date(val)
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return `${y}-${m}-${day}`
} catch (e) {
return val
}
}
</script>
<style lang="scss" scoped>
$primary: #8B2316;
$text-primary: #333;
$text-secondary: #666;
$text-light: #999;
$bg: #f6f6f6;
$white: #ffffff;
.video-search-page {
background: $bg;
min-height: 100vh;
}
.tabs {
position: fixed;
top: 140rpx;
left: 0;
right: 0;
z-index: 90;
display: grid;
grid-template-columns: 1fr 1fr;
background: $white;
border-bottom: 2rpx solid #eee;
.tab {
padding: 28rpx 0;
display: flex;
align-items: center;
justify-content: center;
.tab-text { color: $text-secondary; font-size: 30rpx; }
&.active {
.tab-text { color: $primary; font-weight: 600; }
position: relative;
}
}
}
.list-scroll {
position: fixed;
top: 215rpx; // 140rpx 导航 + 100rpx tabs
left: 0;
right: 0;
bottom: 0;
background: $bg;
}
.video-list {
padding: 20rpx 0;
.video-item {
background: $white;
padding: 28rpx 32rpx;
margin: 20rpx 30rpx 0; // 上 20rpx左右 30rpx
// 去底部分隔线
.item-title {
font-size: 34rpx;
color: $primary;
line-height: 1.5;
margin-bottom: 18rpx;
}
.item-meta {
margin-bottom: 12rpx;
.item-tag { color: $text-secondary; font-size: 28rpx; }
}
.item-date-views {
display: flex;
align-items: center;
justify-content: space-between; // 两端分布
width: 100%;
margin-bottom: 16rpx;
padding-bottom: 16rpx;
border-bottom: 2rpx solid #efefef;
.item-date { color: $text-secondary; font-size: 28rpx; }
.item-views { display: flex; align-items: center; gap: 10rpx; white-space: nowrap; }
.views-text { color: $text-secondary; font-size: 28rpx; }
}
.item-footer {
display: flex;
align-items: center;
justify-content: space-between;
.item-source {
font-size: 28rpx;
color: $text-secondary;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
}
}
}
</style>