短视频细节调整

master
gongfuxiang 2026-02-27 22:06:20 +08:00
parent ee63a26df4
commit 4f3dacc500
7 changed files with 207 additions and 220 deletions

View File

@ -188,9 +188,6 @@ button:before {
.wh-auto {
width: 100% !important;
}
.ht-auto {
height: 100% !important;
}
.tc {
text-align: center;
}

View File

@ -2060,9 +2060,7 @@
"transparentTitle": "always",
"titlePenetrate": "YES",
// #endif
"enablePullDownRefresh": false,
//
"disableScroll": true,
"enablePullDownRefresh": true,
"navigationBarTitleText": ""
}
},

View File

@ -1,6 +1,6 @@
<template>
<view class="content pr">
<template v-if="display_video_list.length > 0">
<template>
<view :class="theme_view">
<view v-if="display_video_list.length > 0" class="content pr">
<!-- 搜索框 -->
<view v-if="!show_comment_modal" class="header-top" :style="top_content_style + menu_button_info">
<view id="search-height" class="flex-row align-c">
@ -81,7 +81,7 @@
</view>
</swiper-item>
</swiper>
</template>
</view>
<template v-else>
<component-no-data :propStatus="data_list_loding_status" :propMsg="data_list_loding_msg"></component-no-data>
</template>
@ -247,19 +247,9 @@
bar_height = 0;
// #endif
export default {
components: {
commentInfoComponent,
commentMoreComponent,
searchComponent,
componentSharePopup,
componentNoData,
componentBottomLine,
componentPopup,
loadingComponent,
componentUpload
},
data() {
return {
return {
theme_view: app.globalData.get_theme_value_view(),
// 5,7,0 10 66bar_height
// #ifdef MP
top_content_style: 'padding-top:' + (bar_height + 5) + 'px;padding-bottom:10px;',
@ -322,6 +312,17 @@
editor_path_type: 'video',
is_manual_pause: false, //
};
},
components: {
commentInfoComponent,
commentMoreComponent,
searchComponent,
componentSharePopup,
componentNoData,
componentBottomLine,
componentPopup,
loadingComponent,
componentUpload
},
computed: {
//

View File

@ -1,22 +1,17 @@
.header-top {
.top-search {
position: sticky;
top: 0;
background: #fff;
z-index: 9;
}
/* 导航栏 */
.nav-tabs {
position: sticky;
width: 100%;
padding: 20rpx 16rpx 20rpx 24rpx;
padding: 10rpx 16rpx 20rpx 24rpx;
z-index: 9;
background: transparent; /* 默认透明背景 */
transition: background-color 0.3s ease; /* 添加背景色过渡动画 */
}
.nav-tabs.nav-tabs-sticky {
background: #fff; /* 粘性状态时背景变白 */
}
.nav-tabs .tabs-scroll-content {
display: flex;

View File

@ -1,67 +1,63 @@
<template>
<view class="wh-auto ht-auto pr video-container bottom-line-exclude-bottom">
<template v-if="tabs.length > 0">
<scroll-view scroll-y :show-scrollbar="false" class="ht" lower-threshold="60" scroll-with-animation="true" @scroll="on_scroll_event">
<view class="wh-auto ht-auto pr">
<!-- 搜索框 -->
<view class="header-top">
<view id="search-height" class="ht-auto flex-row align-c" :style="top_content_style + menu_button_info">
<!-- 支付宝小程序自带返回按钮这里就不给返回按钮了这里给留出一点空间就行 -->
<!-- #ifndef MP-ALIPAY -->
<view v-if="is_show_back" class="cp" @tap="handle_back">
<iconfont name="icon-arrow-left " size="36rpx" color="#333" class="ml-10 mr-10"></iconfont>
</view>
<!-- #endif -->
<view class="wh-auto ht-auto" :style="header_padding_left">
<search-component propIsDisabled @disabledSearch="handle_search"/>
</view>
</view>
</view>
<!-- 轮播 -->
<view v-if="slider_list.length > 0" class="padding-horizontal-main">
<component-banner :propData="slider_list" propBackgroundColor="#333" propSelectedBackgroundColor="#999"></component-banner>
</view>
<template v-if="tabs.length > 0">
<!-- 导航栏 -->
<view class="nav-tabs" :class="{ 'nav-tabs-sticky': is_nav_sticky }" :style="nav_sticky_style">
<scroll-view scroll-x :show-scrollbar="false" class="tabs-scroll nowrap">
<view class="tabs-scroll-content">
<view v-for="(item, index) in tabs" :key="index" class="tab-item flex-row align-c gap-5" :class="{ active: current_tabs_index === index }" :data-index="index" :data-id="item.id" @tap="switch_tab">
<image v-if="!isEmpty(item.icon)" class="tabs-scroll-image radius va-m" :src="item.icon" mode="aspectFill"></image>
<text class="va-m">{{ item.name }}</text>
</view>
</view>
</scroll-view>
</view>
</template>
<template v-if="recommend_videos.length > 0">
<!-- 推荐视频卡片区域 -->
<view class="recommend-videos">
<view class="video-grid">
<view v-for="(item, index) in recommend_videos" :key="index" class="video-card" :data-value="item.url" @tap="url_event">
<image class="video-thumbnail" :src="item.cover" mode="widthFix"></image>
<view class="video-info flex-col jc-c">
<view class="video-title text-line-2">{{ item.title }}</view>
<view class="flex-row align-c jc-sb">
<view class="video-date">{{ item.add_time_date }}</view>
<view class="video-likes flex-row align-c gap-4">
<iconfont name="icon-givealike-o-fine" size="24rpx"></iconfont>
<text>{{ item.give_thumbs_count }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 结尾 -->
<component-bottom-line :propStatus="true"></component-bottom-line>
</template>
<template v-else>
<component-no-data :propStatus="data_list_loding_status" :propMsg="data_list_loding_msg"></component-no-data>
</template>
</view>
</scroll-view>
</template>
<view :class="theme_view">
<view v-if="tabs.length > 0" class=" pr">
<!-- 搜索框 -->
<view class="top-search bg-white spacing-mb">
<view class="flex-row align-c" :style="top_content_style + menu_button_info">
<!-- 支付宝小程序自带返回按钮这里就不给返回按钮了这里给留出一点空间就行 -->
<!-- #ifndef MP-ALIPAY -->
<view v-if="is_show_back" class="cp" @tap="handle_back">
<iconfont name="icon-arrow-left " size="36rpx" color="#333" class="ml-10 mr-10"></iconfont>
</view>
<!-- #endif -->
<view class="wh-auto" :style="header_padding_left">
<search-component propIsDisabled @disabledSearch="handle_search"/>
</view>
</view>
</view>
<!-- 轮播 -->
<view v-if="slider_list.length > 0" class="padding-horizontal-main">
<component-banner :propData="slider_list" propBackgroundColor="#333" propSelectedBackgroundColor="#999"></component-banner>
</view>
<template v-if="tabs.length > 0">
<!-- 导航栏 -->
<view class="nav-tabs bs-bb" :class="{ 'bg-white': is_nav_sticky }" :style="nav_sticky_style">
<scroll-view scroll-x :show-scrollbar="false" class="tabs-scroll nowrap">
<view class="tabs-scroll-content">
<view v-for="(item, index) in tabs" :key="index" class="tab-item flex-row align-c gap-5" :class="{ active: current_tabs_index === index }" :data-index="index" :data-id="item.id" @tap="switch_tab">
<image v-if="!isEmpty(item.icon)" class="tabs-scroll-image radius va-m" :src="item.icon" mode="aspectFill"></image>
<text class="va-m">{{ item.name }}</text>
</view>
</view>
</scroll-view>
</view>
</template>
<template v-if="recommend_videos.length > 0">
<!-- 推荐视频卡片区域 -->
<view class="recommend-videos">
<view class="video-grid">
<view v-for="(item, index) in recommend_videos" :key="index" class="video-card" :data-value="item.url" @tap="url_event">
<image class="video-thumbnail" :src="item.cover" mode="widthFix"></image>
<view class="video-info flex-col jc-c">
<view class="video-title text-line-2">{{ item.title }}</view>
<view class="flex-row align-c jc-sb">
<view class="video-date">{{ item.add_time_date }}</view>
<view class="video-likes flex-row align-c gap-4">
<iconfont name="icon-givealike-o-fine" size="24rpx"></iconfont>
<text>{{ item.give_thumbs_count }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 结尾 -->
<component-bottom-line :propStatus="true"></component-bottom-line>
</template>
<template v-else>
<component-no-data :propStatus="data_list_loding_status" :propMsg="data_list_loding_msg" propLoadingLogoTop="50vh"></component-no-data>
</template>
</view>
<template v-else>
<component-no-data :propStatus="data_tabs_loding_status" :propMsg="data_tabs_loding_msg"></component-no-data>
</template>
@ -90,6 +86,7 @@ export default {
},
data() {
return {
theme_view: app.globalData.get_theme_value_view(),
// 5,7,0 10 66bar_height
// #ifdef MP
top_content_style: 'padding-top:' + (bar_height + 5) + 'px;padding-bottom:10px;',
@ -100,6 +97,7 @@ export default {
// #ifdef APP
top_content_style: 'padding-top:' + bar_height + 'px;padding-bottom:10px;',
// #endif
is_first: true,
is_show_back: true,
tabs: [],
current_tabs_index: 0,
@ -114,12 +112,7 @@ export default {
header_padding_left: '',
slider_list: [],
is_nav_sticky: false, // nav-tabs
// #ifdef H5 || MP-TOUTIAO
nav_sticky_threshold: 55, // CSStop
// #endif
// #ifdef MP || APP
nav_sticky_threshold: bar_height + 53, // CSStop
// #endif
nav_sticky_threshold: 0, // CSStop
nav_sticky_style: '',
};
},
@ -149,6 +142,11 @@ export default {
//
app.globalData.page_share_handle();
},
//
onPullDownRefresh() {
this.init_data(true);
},
methods: {
isEmpty,
@ -178,28 +176,44 @@ export default {
menu_button_info: menu_button_info,
});
//
this.init_data();
this.init_data(!this.is_first);
},
//
init_data() {
init_data(is_list_loading = false) {
//
uni.request({
url: app.globalData.get_request_url("indexinit", "index", "video"),
method: 'POST',
dataType: 'json',
success: res => {
uni.stopPullDownRefresh();
const data = res.data;
if (data.code == 0) {
const new_data = data.data;
this.setData({
is_first: false,
tabs: new_data.category_list,
current_tabs_id: new_data.category_list.length > 0 ? new_data.category_list[this.current_tabs_index].id : '',
data_tabs_loding_status: 0,
slider_list: new_data.slider_list,
});
//
this.get_video_list(this.current_tabs_id);
this.get_video_list(this.current_tabs_id, is_list_loading);
//
let self = this;
setTimeout(() => {
let query = uni.createSelectorQuery();
query.select('.top-search').boundingClientRect();
query.selectViewport().scrollOffset();
query.exec(function (res) {
self.setData({
nav_sticky_threshold: res[0].height,
nav_sticky_style: 'top:' + res[0].height + 'px;',
});
});
}, 100);
} else {
this.setData({
data_tabs_loding_status: 2,
@ -208,6 +222,7 @@ export default {
}
},
fail: (err) => {
uni.stopPullDownRefresh();
this.setData({
data_tabs_loding_status: 2,
data_list_loding_msg: this.$t('common.internet_error_tips'),
@ -217,10 +232,11 @@ export default {
},
//
get_video_list(id = '') {
get_video_list(id = '', is_list_loading = false) {
this.setData({
data_list_loding_status: 1,
data_list_loding_msg: '',
recommend_videos: is_list_loading ? this.recommend_videos : [],
});
//
uni.request({
@ -283,12 +299,10 @@ export default {
},
//
on_scroll_event(e) {
const scrollTop = e.detail.scrollTop;
onPageScroll(e) {
// nav-tabs
this.setData({
is_nav_sticky: scrollTop >= this.nav_sticky_threshold,
nav_sticky_style: 'top:' + this.nav_sticky_threshold * 2 + 'rpx;',
is_nav_sticky: e.scrollTop >= this.nav_sticky_threshold
});
}
}

View File

@ -12,7 +12,7 @@
.nav-tabs {
position: relative;
width: 100%;
padding: 0 24rpx 20rpx 24rpx;
padding: 10rpx 24rpx 20rpx 24rpx;
box-sizing: border-box;
}
@ -80,26 +80,18 @@
}
/* #endif */
/* 推荐视频列表 */
.recommend-videos {
padding: 20rpx 0;
}
.recommend-videos .video-grid {
padding: 0 24rpx;
column-count: 2;
column-gap: 10px;
/* 添加这些样式确保滚动事件能正常触发 */
overflow-y: auto;
-webkit-overflow-scrolling: touch;
column-gap: 20rpx;
}
.recommend-videos .video-card {
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-radius: 4px;
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1);
border-radius: 8rpx;
overflow: hidden;
break-inside: avoid;
margin-bottom: 10px;
margin-bottom: 20rpx;
width: 100%;
}
@ -175,9 +167,4 @@
}
::v-deep .popup .popup-mask {
z-index: 8 !important;
}
.recommend-scroll {
/* 使用更精确的高度计算 */
height: calc(100vh - 240rpx); /* 增加一些高度确保滚动空间 */
min-height: 500px; /* 设置最小高度 */
}

View File

@ -1,82 +1,76 @@
<template>
<view class="wh-auto ht-auto pr video-container">
<view class="wh-auto ht-auto pr">
<template v-if="category_list.length > 0">
<!-- 搜索框 -->
<view class="header-top">
<view class="header-search" :style="top_content_style + menu_button_info">
<view id="search-height" class="flex-row align-c">
<!-- 支付宝小程序自带返回按钮这里就不给返回按钮了这里给留出一点空间就行 -->
<!-- #ifndef MP-ALIPAY -->
<view class="cp" @tap="handle_back">
<iconfont name="icon-arrow-left " size="36rpx" color="#333" class="mr-10"></iconfont>
</view>
<!-- #endif -->
<view class="wh-auto ht-auto" :style="header_padding_left">
<search-component :propSearchQuery="search_keywords" @search="handle_search" />
</view>
</view>
</view>
<!-- 导航栏 -->
<view class="nav-tabs flex-row align-s jc-sb gap-10">
<view class="tabs-scroll-content">
<view v-for="(tab, index) in category_list" :key="index" class="tab-item" :class="(currentTab == index) ? 'active' : ''" :data-index="index" @click="switch_tab">{{ tab.name }}</view>
</view>
<view class="nav-tabs-filter" @click="toggle_filter_popup">
<iconfont name="icon-filter" size="32rpx"></iconfont>
</view>
</view>
</view>
<!-- 推荐视频卡片区域 -->
<view class="recommend-videos">
<scroll-view scroll-y :show-scrollbar="false" class="recommend-scroll" @scrolltolower="on_scroll_lower_event" lower-threshold="150" scroll-with-animation="true" enhanced="true">
<template v-if="recommend_videos.length > 0">
<view class="video-grid">
<view v-for="(item, index) in recommend_videos" :key="index" class="video-card" :data-value="item.url" @tap="url_event">
<image class="video-thumbnail" :src="item.cover" mode="widthFix"></image>
<view class="video-info flex-col jc-c">
<view class="video-title text-line-2">{{ item.title }}</view>
<view class="flex-row align-c jc-sb">
<view class="video-date">{{ item.add_time_date }}</view>
<view class="video-likes flex-row align-c gap-4">
<iconfont name="icon-givealike-o-fine" size="24rpx"></iconfont>
<text>{{ item.give_thumbs_count }}</text>
</view>
</view>
</view>
</view>
</view>
<template v-if="page < page_total">
<!-- 加载更多 -->
<loadingComponent v-if="is_more_loading"></loadingComponent>
</template>
<template v-else>
<!-- 结尾 -->
<component-bottom-line :propStatus="goods_bottom_line_status"></component-bottom-line>
</template>
</template>
<template v-else>
<component-no-data :propStatus="data_list_loding_status" :propMsg="data_list_loding_msg"></component-no-data>
</template>
</scroll-view>
</view>
</template>
<template v-else>
<component-no-data :propStatus="data_tabs_loding_status" :propMsg="data_tabs_loding_msg"></component-no-data>
</template>
</view>
<view :class="theme_view">
<template v-if="category_list.length > 0">
<!-- 搜索框 -->
<view class="header-top">
<view class="header-search" :style="top_content_style + menu_button_info">
<view id="search-height" class="flex-row align-c">
<!-- 支付宝小程序自带返回按钮这里就不给返回按钮了这里给留出一点空间就行 -->
<!-- #ifndef MP-ALIPAY -->
<view class="cp" @tap="handle_back">
<iconfont name="icon-arrow-left " size="36rpx" color="#333" class="mr-10"></iconfont>
</view>
<!-- #endif -->
<view class="wh-auto ht-auto" :style="header_padding_left">
<search-component :propSearchQuery="search_keywords" @search="handle_search" />
</view>
</view>
</view>
<!-- 导航栏 -->
<view class="nav-tabs flex-row align-s jc-sb gap-10">
<view class="tabs-scroll-content">
<view v-for="(tab, index) in category_list" :key="index" class="tab-item" :class="(currentTab == index) ? 'active' : ''" :data-index="index" @click="switch_tab">{{ tab.name }}</view>
</view>
<view class="nav-tabs-filter" @click="toggle_filter_popup">
<iconfont name="icon-filter" size="32rpx"></iconfont>
</view>
</view>
</view>
<!-- 推荐视频卡片区域 -->
<scroll-view class="recommend-videos" scroll-y :show-scrollbar="false" @scrolltolower="on_scroll_lower_event" lower-threshold="150" scroll-with-animation="true" enhanced="true" :style="scroll_view_style">
<template v-if="recommend_videos.length > 0">
<view class="video-grid padding-main">
<view v-for="(item, index) in recommend_videos" :key="index" class="video-card" :data-value="item.url" @tap="url_event">
<image class="video-thumbnail" :src="item.cover" mode="widthFix"></image>
<view class="video-info flex-col jc-c">
<view class="video-title text-line-2">{{ item.title }}</view>
<view class="flex-row align-c jc-sb">
<view class="video-date">{{ item.add_time_date }}</view>
<view class="video-likes flex-row align-c gap-4">
<iconfont name="icon-givealike-o-fine" size="24rpx"></iconfont>
<text>{{ item.give_thumbs_count }}</text>
</view>
</view>
</view>
</view>
</view>
<template v-if="page < page_total">
<!-- 加载更多 -->
<loadingComponent v-if="is_more_loading"></loadingComponent>
</template>
<template v-else>
<!-- 结尾 -->
<component-bottom-line :propStatus="goods_bottom_line_status"></component-bottom-line>
</template>
</template>
<template v-else>
<component-no-data :propStatus="data_list_loding_status" :propMsg="data_list_loding_msg"></component-no-data>
</template>
</scroll-view>
</template>
<template v-else>
<component-no-data :propStatus="data_tabs_loding_status" :propMsg="data_tabs_loding_msg"></component-no-data>
</template>
<!-- 选项卡更多弹窗 -->
<componentPopup :propShow="filter_popup_status" propPosition="top" :propMask="true" @onclose="close_filter_popup">
<view :class="'padding-bottom-lg ' + (['toutiao', 'app', 'h5'].includes(platform) ? 'padding-top-lg' : 'padding-top')" :style="{ 'padding-top': popup_top }">
<view class="divider-b">
<view class="nav-list-more">
<view class="flex-row flex-wrap align-c">
<!-- 筛选列表 -->
<view v-for="(item, index) in popup_list" :key="index" class="filter-group">
<view class="filter-title">{{ item.title }}</view>
<view class="filter-options">
<view v-for="(option, index) in item.list" :key="index" :class="'filter-option ' + (option.type == filter_params[item.id] ? 'active' : '')" :data-type="option.type" :data-id="item.id" @tap="select_filter">{{ option.name }}</view>
</view>
<view class="padding-bottom-lg" :style="filter_popup_top_style">
<view class="nav-list-more">
<view class="flex-row flex-wrap align-c">
<!-- 筛选列表 -->
<view v-for="(item, index) in popup_list" :key="index" class="filter-group">
<view class="filter-title">{{ item.title }}</view>
<view class="filter-options">
<view v-for="(option, index) in item.list" :key="index" :class="'filter-option ' + (option.type == filter_params[item.id] ? 'active' : '')" :data-type="option.type" :data-id="item.id" @tap="select_filter">{{ option.name }}</view>
</view>
</view>
</view>
@ -114,6 +108,7 @@ export default {
},
data() {
return {
theme_view: app.globalData.get_theme_value_view(),
// 5,7,0 10 66bar_height
// #ifdef MP
top_content_style: 'padding-top:' + (bar_height + 5) + 'px;padding-bottom:10px;',
@ -130,8 +125,8 @@ export default {
isLoadingMore: false,
params: null,
filter_popup_status: false,
popup_top: '0rpx',
platform: app.globalData.application_client_type(),
filter_popup_top_style: '',
scroll_view_style: '',
popup_list: [
{ title: this.$t('video-search.video-search.sdfgg4'), id: 'sort', list: []},
{ title: this.$t('video-search.video-search.gf3212'), id: 'time', list: [] },
@ -209,24 +204,8 @@ export default {
this.setData({
header_padding_left: padding_left,
menu_button_info: menu_button_info,
search_history: uni.getStorageSync(this.cache_key) || [],
});
//
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
//
query
.select('.header-top')
.boundingClientRect((res) => {
if ((res || null) != null) {
// data
this.setData({
popup_top: res.height * 2 + 'rpx',
});
}
})
.exec(); //
}, 500);
this.search_history = uni.getStorageSync(this.cache_key) || [];
//
this.init_data();
@ -257,9 +236,25 @@ export default {
search_cid: new_data?.category_list[0]?.id || '',
data_tabs_loding_status: 0,
popup_list: this.popup_list
})
});
//
this.load_recommend_videos();
//
let self = this;
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
query.select('.header-top').boundingClientRect()
query.selectViewport().scrollOffset();
query.exec(function (res) {
self.setData({
header_top_value: res[0].height,
filter_popup_top_style: 'padding-top:' + res[0].height + 'px;',
scroll_view_style: 'height: calc(100vh - '+res[0].height+'px);',
});
});
}, 100);
} else {
this.setData({
data_tabs_loding_status: 2,