9.5上午更新
This commit is contained in:
parent
9a26193ea4
commit
397cf0c88e
30
api/api.js
30
api/api.js
@ -297,14 +297,6 @@ const api = {
|
||||
return request('/expertAPI/modifyMobile', data, 'post', false);
|
||||
},
|
||||
|
||||
pointTicketlist(data){
|
||||
return request('/expertAPI/pointTicketlist', data, 'post', false);
|
||||
},
|
||||
|
||||
pointTicketExchange(data){
|
||||
return request('/expertAPI/updateStatus', data, 'post', false);
|
||||
},
|
||||
|
||||
smsSend(data){
|
||||
return request('/expertAPI/smsSend', data, 'post', false);
|
||||
},
|
||||
@ -381,7 +373,27 @@ const api = {
|
||||
cancelRes(data){
|
||||
return request('/expertAPI/cancelRes', data, 'post', false);
|
||||
},
|
||||
|
||||
polularScienceArticleListByKeywordsNew(data){
|
||||
return request('/expertAPI/polularScienceArticleListByKeywordsNew', data, 'post', false);
|
||||
},
|
||||
patientVideoByKeyWordsNew(data){
|
||||
return request('/expertAPI/patientVideoByKeyWordsNew', data, 'post', false);
|
||||
},
|
||||
patientVideoNew(data){
|
||||
return request('/expertAPI/patientVideoNew', data, 'post', false);
|
||||
},
|
||||
top10ByType(data){
|
||||
return request('/expertAPI/top10ByType', data, 'post', false);
|
||||
},
|
||||
videoBySearchNew(data){
|
||||
return request('/expertAPI/videoBySearchNew', data, 'post', false);
|
||||
},
|
||||
patientVideoBySearchNew(data){
|
||||
return request('/expertAPI/patientVideoBySearchNew', data, 'post', false);
|
||||
},
|
||||
polularScienceArticleListIndexNew(data){
|
||||
return request('/expertAPI/polularScienceArticleListIndexNew', data, 'post', false);
|
||||
},
|
||||
}
|
||||
|
||||
export default api
|
||||
57
pages.json
57
pages.json
@ -198,10 +198,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "searchNews/searchNews",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "searchVideo/searchVideo",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarRightButton":{ "hide": true},
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "search/search",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarRightButton":{ "hide": true},
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
@ -285,6 +307,28 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "hot/hot",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarRightButton":{ "hide": true},
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "patientVideo/patientVideo",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarRightButton":{ "hide": true},
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "selectPatient/selectPatient",
|
||||
"style": {
|
||||
@ -658,6 +702,7 @@
|
||||
"path": "zhinanList/zhinanList",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarRightButton":{ "hide": true},
|
||||
"navigationBarTitleText": "uni-app分页",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
@ -792,16 +837,6 @@
|
||||
{
|
||||
"root": "pages_goods",
|
||||
"pages": [
|
||||
{
|
||||
"path": "coupon/coupon",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "积分券",
|
||||
"app": {
|
||||
"bounce": "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pointMall/pointMall",
|
||||
"style": {
|
||||
@ -893,7 +928,7 @@
|
||||
"list": [
|
||||
{
|
||||
"name": "", //模式名称
|
||||
"path": "pages/index/index", //启动页面,必选
|
||||
"path": "pages_app/videoDetail/videoDetail", //启动页面,必选
|
||||
"query": "" //启动参数,在页面的onLoad函数里面得到
|
||||
}
|
||||
]
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<!-- 课程列表 -->
|
||||
<view class="course-list">
|
||||
<!-- 肝胆精品课 -->
|
||||
<view class="course-item" @click="goToCourse('hepatoBiliary')">
|
||||
<view class="course-item" @click="goToCourse('course')">
|
||||
<up-image :src="course" width="94rpx" height="94rpx" ></up-image>
|
||||
<view class="course-content">
|
||||
<view class="course-title">肝胆精品课</view>
|
||||
@ -16,7 +16,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 肝胆视频 -->
|
||||
<view class="course-item" @click="goToCourse('hepatoBiliaryVideo')">
|
||||
<view class="course-item" @click="goToCourse('video')">
|
||||
<up-image :src="videoImg" width="94rpx" height="94rpx" ></up-image>
|
||||
<view class="course-content">
|
||||
<view class="course-title">肝胆视频</view>
|
||||
@ -28,7 +28,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 肝胆课件 -->
|
||||
<view class="course-item" @click="goToCourse('hepatoBiliaryCourseware')">
|
||||
<view class="course-item" @click="goToCourse('ppt')">
|
||||
<up-image :src="pptImg" width="94rpx" height="94rpx" ></up-image>
|
||||
<view class="course-content">
|
||||
<view class="course-title">肝胆课件</view>
|
||||
@ -40,7 +40,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 病例讨论 -->
|
||||
<view class="course-item" @click="goToCourse('caseDiscussion')">
|
||||
<!-- <view class="course-item" @click="goToCourse('caseDiscussion')">
|
||||
<up-image :src="talkImg" width="94rpx" height="94rpx" ></up-image>
|
||||
<view class="course-content">
|
||||
<view class="course-title">病例讨论</view>
|
||||
@ -49,10 +49,10 @@
|
||||
<view class="course-arrow">
|
||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 病例荟萃 -->
|
||||
<view class="course-item" @click="goToCourse('caseCollection')">
|
||||
<!-- <view class="course-item" @click="goToCourse('caseCollection')">
|
||||
<up-image :src="huicuiImg" width="94rpx" height="94rpx" ></up-image>
|
||||
<view class="course-content">
|
||||
<view class="course-title">病例荟萃</view>
|
||||
@ -61,10 +61,10 @@
|
||||
<view class="course-arrow">
|
||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 现代肝病学院 -->
|
||||
<view class="course-item" @click="goToCourse('modernHepatology')">
|
||||
<!-- <view class="course-item" @click="goToCourse('modernHepatology')">
|
||||
<up-image :src="xueyuanImg" width="94rpx" height="94rpx" ></up-image>
|
||||
<view class="course-content">
|
||||
<view class="course-title">现代肝病学院</view>
|
||||
@ -73,10 +73,10 @@
|
||||
<view class="course-arrow">
|
||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 新手教程 -->
|
||||
<view class="course-item" @click="goToCourse('tutorial')">
|
||||
<!-- <view class="course-item" @click="goToCourse('tutorial')">
|
||||
<up-image :src="newerImg" width="94rpx" height="94rpx" ></up-image>
|
||||
<view class="course-content">
|
||||
<view class="course-title">新手教程</view>
|
||||
@ -85,7 +85,7 @@
|
||||
<view class="course-arrow">
|
||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<CustomTabbar></CustomTabbar>
|
||||
@ -102,6 +102,7 @@
|
||||
import huicuiImg from "@/static/jingdianbingli.png"
|
||||
import xueyuanImg from "@/static/ganbingxueyuan.png"
|
||||
import newerImg from "@/static/xinshoujiaocheng.png"
|
||||
import navTo from '@/utils/navTo.js';
|
||||
// 方法
|
||||
// 方法
|
||||
const goToCourse = (courseType) => {
|
||||
@ -109,47 +110,20 @@
|
||||
|
||||
// 根据课程类型进行不同的处理
|
||||
switch(courseType) {
|
||||
case 'hepatoBiliary':
|
||||
uni.showToast({
|
||||
title: '肝胆精品课功能开发中',
|
||||
icon: 'none'
|
||||
});
|
||||
case 'course':
|
||||
navTo({
|
||||
url: '/pages_course/index/index'
|
||||
})
|
||||
break;
|
||||
case 'hepatoBiliaryVideo':
|
||||
uni.showToast({
|
||||
title: '肝胆视频功能开发中',
|
||||
icon: 'none'
|
||||
});
|
||||
case 'video':
|
||||
navTo({
|
||||
url: '/pages_app/video/video'
|
||||
})
|
||||
break;
|
||||
case 'hepatoBiliaryCourseware':
|
||||
uni.showToast({
|
||||
title: '肝胆课件功能开发中',
|
||||
icon: 'none'
|
||||
});
|
||||
break;
|
||||
case 'caseDiscussion':
|
||||
uni.showToast({
|
||||
title: '病例讨论功能开发中',
|
||||
icon: 'none'
|
||||
});
|
||||
break;
|
||||
case 'caseCollection':
|
||||
uni.showToast({
|
||||
title: '病例荟萃功能开发中',
|
||||
icon: 'none'
|
||||
});
|
||||
break;
|
||||
case 'modernHepatology':
|
||||
uni.showToast({
|
||||
title: '现代肝病学院功能开发中',
|
||||
icon: 'none'
|
||||
});
|
||||
break;
|
||||
case 'tutorial':
|
||||
uni.showToast({
|
||||
title: '新手教程功能开发中',
|
||||
icon: 'none'
|
||||
});
|
||||
case 'ppt':
|
||||
navTo({
|
||||
url: '/pages_app/ppt/ppt'
|
||||
})
|
||||
break;
|
||||
default:
|
||||
uni.showToast({
|
||||
|
||||
@ -253,9 +253,13 @@
|
||||
import sign from "@/static/home_qiandao_icon.png"
|
||||
import signImg from "@/static/sign_in_bng_big.png"
|
||||
import dayjs from 'dayjs'
|
||||
import docUrl from "@/utils/docUrl.js"
|
||||
const expertDetail=reactive({})
|
||||
const showSign=ref(false)
|
||||
const signInfo=reactive({
|
||||
news:{
|
||||
summary:''
|
||||
}
|
||||
})
|
||||
// 定义refs
|
||||
const tabbarRef = ref(null);
|
||||
const visible=ref(false)
|
||||
@ -850,7 +854,6 @@
|
||||
url: '/pages_course/course/course'
|
||||
});
|
||||
};
|
||||
const signInfo=reactive({})
|
||||
// 签到点击事件
|
||||
const onSignClick = async () => {
|
||||
// 如果已经签到,显示提示
|
||||
|
||||
@ -20,17 +20,18 @@
|
||||
|
||||
<!-- 筛选栏 -->
|
||||
<view class="filter-bar">
|
||||
<view class="search-box">
|
||||
<view class="search-box" @click="goToSearch">
|
||||
<uni-icons type="search" size="16" color="#999"></uni-icons>
|
||||
<text class="search-text">搜索</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<view class="filter-item">
|
||||
<text>最新</text>
|
||||
<up-image :src="upImg" width="20rpx" height="26rpx" ></up-image>
|
||||
<view class="filter-item active" @click="toggleSort">
|
||||
<text>{{type==1?'最新':'最热'}}</text>
|
||||
<up-image v-if="type==1" :src="upImg" width="20rpx" height="26rpx" ></up-image>
|
||||
<up-image v-else :src="downImg" width="20rpx" height="26rpx" ></up-image>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<view class="filter-item" @click="showFilterPopup">
|
||||
<view class="filter-item" :class="{ active: isFilterActive }" @click="showFilterPopup">
|
||||
<text>筛选</text>
|
||||
<up-image :src="isFilterActive ? filterOn : filter" width="30rpx" height="30rpx" ></up-image>
|
||||
</view>
|
||||
@ -50,7 +51,7 @@
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.name }}
|
||||
{{ tag.DES }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -63,8 +64,16 @@
|
||||
</view>
|
||||
|
||||
<!-- 文章列表 -->
|
||||
<scroll-view class="article-list" scroll-y>
|
||||
<view class="article-item" v-for="(article, index) in articleList" :key="index" @click="goToDetail(article)">
|
||||
<scroll-view
|
||||
class="article-list"
|
||||
scroll-y
|
||||
refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="onLoadMore"
|
||||
:lower-threshold="100"
|
||||
>
|
||||
<view class="article-item" v-for="(article, index) in articleList" :key="article.uuid || index" @click="goToDetail(article)">
|
||||
<image class="article-image" :src="article.image" mode="aspectFill"></image>
|
||||
<view class="article-content">
|
||||
<view class="article-title">{{ article.title }}</view>
|
||||
@ -77,13 +86,30 @@
|
||||
<text>{{ article.views }}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<uni-icons type="heart" size="12" color="#999"></uni-icons>
|
||||
<uni-icons type="hand-up" size="13" color="#999"></uni-icons>
|
||||
<text>{{ article.likes }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多状态 -->
|
||||
<view class="load-more" v-if="loading">
|
||||
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
|
||||
<text class="load-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 没有更多数据 -->
|
||||
<view class="no-more" v-if="!hasMore && articleList.length > 0">
|
||||
<text class="no-more-text">没有更多数据了</text>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-if="articleList.length === 0 && !loading">
|
||||
<uni-icons type="article" size="80" color="#cccccc"></uni-icons>
|
||||
<text class="empty-text">暂无文章</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部导航栏 -->
|
||||
@ -100,128 +126,177 @@
|
||||
import downImg from "@/static/cb_up.png"
|
||||
import filter from "@/static/cb_screen_no.png"
|
||||
import filterOn from "@/static/cb_screen_yes.png"
|
||||
import api from "@/api/api.js"
|
||||
import docUrl from '@/utils/docUrl.js';
|
||||
import navTo from '@/utils/navTo.js';
|
||||
|
||||
const type=ref(1)
|
||||
|
||||
// 分页相关状态
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const hasMore = ref(true);
|
||||
const loading = ref(false);
|
||||
const refreshing = ref(false);
|
||||
// 响应式数据
|
||||
const activeTab = ref(0);
|
||||
const showFilter = ref(false);
|
||||
const isFilterActive = ref(false);
|
||||
|
||||
// 筛选标签数据
|
||||
const filterTags = ref([
|
||||
{ name: '甲型肝炎', selected: false },
|
||||
{ name: '乙型肝炎', selected: false },
|
||||
{ name: '丙型肝炎', selected: false },
|
||||
{ name: '药物肝', selected: false },
|
||||
{ name: '自免肝', selected: false },
|
||||
{ name: '酒精肝', selected: false },
|
||||
{ name: '脂肪肝', selected: false },
|
||||
{ name: '肝纤维化', selected: false },
|
||||
{ name: '肝硬化', selected: false },
|
||||
{ name: '肝癌', selected: false },
|
||||
{ name: '肝囊虫', selected: false },
|
||||
{ name: '肝移植', selected: false },
|
||||
{ name: '胆结石', selected: false },
|
||||
{ name: '胆囊炎', selected: false },
|
||||
{ name: '其他疾病', selected: false },
|
||||
{ name: '肝脏检查', selected: false },
|
||||
{ name: '乙肝五项', selected: false },
|
||||
{ name: '肝功能', selected: false },
|
||||
{ name: '报告解读', selected: false },
|
||||
{ name: '肝炎病毒', selected: false },
|
||||
{ name: '传播途径', selected: false },
|
||||
{ name: '症状表现', selected: false },
|
||||
{ name: '疫苗接种', selected: false },
|
||||
{ name: '诊断治疗', selected: false },
|
||||
{ name: '抗病毒', selected: false },
|
||||
{ name: '干扰素', selected: false },
|
||||
{ name: '用药', selected: false },
|
||||
{ name: '耐药', selected: false },
|
||||
{ name: '保肝降酶', selected: false },
|
||||
{ name: '毒副反应', selected: false },
|
||||
{ name: '治愈停药', selected: false },
|
||||
{ name: '肝炎复发', selected: false },
|
||||
{ name: '预后预防', selected: false },
|
||||
{ name: '日常生活', selected: false },
|
||||
{ name: '饮食营养', selected: false },
|
||||
{ name: '养肝护肝', selected: false },
|
||||
{ name: '一图读懂', selected: false },
|
||||
{ name: '误区辟谣', selected: false },
|
||||
{ name: '生儿育女', selected: false },
|
||||
{ name: '医保报销', selected: false },
|
||||
{ name: '肝胆相照', selected: false },
|
||||
{ name: '精华好文', selected: false },
|
||||
{ name: '肝病故事', selected: false },
|
||||
{ name: '名医科普', selected: false },
|
||||
{ name: '肝病现状', selected: false },
|
||||
{ name: '中医中药', selected: false }
|
||||
]);
|
||||
|
||||
// 模拟文章数据
|
||||
const articleList = ref([
|
||||
{
|
||||
id: 1,
|
||||
image: '/static/liver_knowledge.png',
|
||||
title: '甩掉"乙肝大国"的帽子后,中国第一大肝病变成了它,正在侵...',
|
||||
date: '今日',
|
||||
isToday: true,
|
||||
views: 185,
|
||||
likes: 0
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
image: '/static/doctor_liver.png',
|
||||
title: '从你我做起,让肝炎止步',
|
||||
date: '08-01',
|
||||
isToday: false,
|
||||
views: 315,
|
||||
likes: 0
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
image: '/static/liver_health.png',
|
||||
title: '这6个指标正常,说明你肝脏健康',
|
||||
date: '07-25',
|
||||
isToday: false,
|
||||
views: 1033,
|
||||
likes: 0
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
image: '/static/diet_liver.png',
|
||||
title: '无需节食!吃饭一个改变,脂肪肝好转了!4个月肝脏脂肪减...',
|
||||
date: '07-18',
|
||||
isToday: false,
|
||||
views: 1829,
|
||||
likes: 1
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
image: '/static/cooking_spices.png',
|
||||
title: '这种家家都有的调料,吃太多会增加肝癌风险?很多人已超标!',
|
||||
date: '07-11',
|
||||
isToday: false,
|
||||
views: 2992,
|
||||
likes: 0
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
image: '/static/liver_protection.png',
|
||||
title: '肝炎拖成肝硬化,下一步就是肝癌,养肝护肝,记住这3点',
|
||||
date: '07-04',
|
||||
isToday: false,
|
||||
views: 1993,
|
||||
likes: 1
|
||||
const toggleSort = () => {
|
||||
type.value = type.value === 1 ? 2 : 1;
|
||||
// 重置分页状态
|
||||
currentPage.value = 1;
|
||||
hasMore.value = true;
|
||||
polularScienceArticleListByKeywordsNew(true);
|
||||
};
|
||||
const loadGuideTags = async () => {
|
||||
try {
|
||||
const res = await api.guideTag({
|
||||
type:4
|
||||
});
|
||||
if(res && res.code === 200 && res.data) {
|
||||
// 将API返回的标签数据转换为筛选标签格式
|
||||
filterTags.value = res.data.map(tag => ({
|
||||
...tag,
|
||||
selected: false
|
||||
}));
|
||||
console.log('指南标签加载成功:', filterTags.value);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载指南标签失败:', e);
|
||||
}
|
||||
};
|
||||
const polularScienceArticleListByKeywordsNew = async (isRefresh = false) => {
|
||||
if (loading.value) return;
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const page = isRefresh ? 1 : currentPage.value;
|
||||
const res = await api.polularScienceArticleListByKeywordsNew({
|
||||
keywords: keywords.value,
|
||||
page: page,
|
||||
type: type.value
|
||||
});
|
||||
|
||||
if (res && res.code === 200 && res.data) {
|
||||
const newData = res.data.list || [];
|
||||
|
||||
if (isRefresh) {
|
||||
// 下拉刷新:替换数据
|
||||
articleList.value = newData.map(item => formatArticleData(item));
|
||||
currentPage.value = 1;
|
||||
} else {
|
||||
// 上拉加载:追加数据
|
||||
const formattedData = newData.map(item => formatArticleData(item));
|
||||
articleList.value = [...articleList.value, ...formattedData];
|
||||
}
|
||||
|
||||
// 判断是否还有更多数据
|
||||
hasMore.value = newData.length >= pageSize.value;
|
||||
|
||||
if (!isRefresh) {
|
||||
currentPage.value++;
|
||||
}
|
||||
|
||||
console.log('文章数据加载成功:', articleList.value);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取文章列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
refreshing.value = false;
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
// 格式化文章数据
|
||||
const formatArticleData = (item) => {
|
||||
// 安全检查,确保item存在且有所需属性
|
||||
if (!item) return null;
|
||||
|
||||
const submitDate = item.submitDate ? new Date(item.submitDate) : new Date();
|
||||
const today = new Date();
|
||||
const isToday = submitDate.toDateString() === today.toDateString();
|
||||
|
||||
return {
|
||||
uuid: item.uuid || '',
|
||||
title: item.topic || '无标题',
|
||||
summary: item.summary || '',
|
||||
image: item.imgPath ? docUrl + item.imgPath : '/static/liver_knowledge.png',
|
||||
date: isToday ? '今日' : formatDate(submitDate),
|
||||
isToday: isToday,
|
||||
views: item.readnum || 0,
|
||||
likes: item.agreenum || 0,
|
||||
tags: item.tags || '',
|
||||
path: item.path || '',
|
||||
submitDate: item.submitDate || ''
|
||||
};
|
||||
};
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (date) => {
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${month}-${day}`;
|
||||
};
|
||||
// 筛选标签数据
|
||||
const filterTags = ref([]);
|
||||
|
||||
// 文章列表数据
|
||||
const articleList = ref([]);
|
||||
|
||||
// 方法
|
||||
const switchTab = (index) => {
|
||||
activeTab.value = index;
|
||||
|
||||
if(index==1){
|
||||
navTo({
|
||||
url: '/pages_app/patientVideo/patientVideo'
|
||||
})
|
||||
}else if(index==2){
|
||||
let url=encodeURIComponent('https://wx.igandan.com/wxPatient/index.htm#/problem?link=share&fromtype=doctor')
|
||||
navTo({
|
||||
url: '/pages_app/webview/webview?url='+url
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const goToDetail = (article) => {
|
||||
console.log('查看文章详情:', article);
|
||||
// 跳转到详情页
|
||||
if (article.path) {
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/webview/webview?url=${encodeURIComponent(docUrl+article.path)}&title=${encodeURIComponent(article.title)}`
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 跳转到搜索页面
|
||||
const goToSearch = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages_app/search/search'
|
||||
});
|
||||
};
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = async () => {
|
||||
refreshing.value = true;
|
||||
await polularScienceArticleListByKeywordsNew(true);
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
});
|
||||
};
|
||||
|
||||
// 上拉加载更多
|
||||
const onLoadMore = async () => {
|
||||
if (!hasMore.value || loading.value) return;
|
||||
await polularScienceArticleListByKeywordsNew(false);
|
||||
};
|
||||
|
||||
const goToPage = (page) => {
|
||||
@ -253,7 +328,7 @@
|
||||
});
|
||||
isFilterActive.value = false;
|
||||
};
|
||||
|
||||
const keywords=ref('');
|
||||
const confirmFilter = () => {
|
||||
// 检查是否有选中的标签
|
||||
const hasSelected = filterTags.value.some(tag => tag.selected);
|
||||
@ -261,16 +336,24 @@
|
||||
|
||||
// 执行筛选逻辑
|
||||
if (hasSelected) {
|
||||
const selectedTags = filterTags.value.filter(tag => tag.selected).map(tag => tag.name);
|
||||
const selectedTags = filterTags.value.filter(tag => tag.selected).map(tag => tag.DES);
|
||||
console.log('选中的标签:', selectedTags);
|
||||
// 这里可以添加实际的筛选逻辑
|
||||
keywords.value = selectedTags.join(',');
|
||||
} else {
|
||||
keywords.value = '';
|
||||
}
|
||||
|
||||
// 重置分页状态
|
||||
currentPage.value = 1;
|
||||
hasMore.value = true;
|
||||
|
||||
showFilter.value = false;
|
||||
polularScienceArticleListByKeywordsNew(true);
|
||||
};
|
||||
|
||||
onShow(() => {
|
||||
console.log('患教学堂页面显示');
|
||||
polularScienceArticleListByKeywordsNew(true);
|
||||
loadGuideTags();
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -372,8 +455,13 @@ $padding-small: 10px;
|
||||
gap: 3px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
.filter-item.active{
|
||||
color: $theme-color;
|
||||
}
|
||||
|
||||
|
||||
// 文章列表
|
||||
.article-list {
|
||||
@ -449,6 +537,46 @@ $padding-small: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载状态样式
|
||||
.load-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 30rpx;
|
||||
color: #999;
|
||||
|
||||
.load-text {
|
||||
margin-left: 10rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.no-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 30rpx;
|
||||
|
||||
.no-more-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 30rpx;
|
||||
|
||||
.empty-text {
|
||||
margin-top: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部导航栏
|
||||
|
||||
707
pages_app/hot/hot.vue
Normal file
707
pages_app/hot/hot.vue
Normal file
@ -0,0 +1,707 @@
|
||||
<template>
|
||||
<view class="zhinan-list-page">
|
||||
<!-- 头部导航栏 -->
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
:title="title"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
height="140rpx"
|
||||
:border="false"
|
||||
backgroundColor="#eeeeee"
|
||||
>
|
||||
|
||||
</uni-nav-bar>
|
||||
|
||||
<!-- 使用scroll-view实现列表 -->
|
||||
<scroll-view
|
||||
class="guidelines-scroll-view"
|
||||
scroll-y="true"
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="isRefreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="onScrollToLower"
|
||||
:show-scrollbar="false"
|
||||
>
|
||||
<!-- 指南列表 -->
|
||||
<view class="guidelines-list">
|
||||
<view
|
||||
class="guideline-item"
|
||||
v-for="(item, index) in guidelinesList"
|
||||
:key="item.uuid || index"
|
||||
@click="viewGuideline(item)"
|
||||
>
|
||||
<!-- 指南信息 -->
|
||||
<view class="item-content">
|
||||
<view class="item-title">{{ item.title }}</view>
|
||||
<view class="item-bottom">
|
||||
<view class="item-date">{{ formatDate(item.releaseTime) }}</view>
|
||||
<!-- 操作按钮 -->
|
||||
<view class="item-action">
|
||||
<view
|
||||
class="download-btn"
|
||||
@click.stop="viewGuideline(item)"
|
||||
>
|
||||
<up-icon name="download" color="#8D2316" size="28"></up-icon>
|
||||
</view>
|
||||
<!-- <view
|
||||
v-else
|
||||
class="view-btn"
|
||||
@click.stop="viewGuideline(item)"
|
||||
>
|
||||
查看
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多状态 -->
|
||||
<view class="load-more-status">
|
||||
<view v-if="loadMoreStatus === 'loading'" class="loading">
|
||||
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
<view v-else-if="loadMoreStatus === 'more'" class="more">
|
||||
<text>上拉加载更多</text>
|
||||
</view>
|
||||
<view v-else-if="loadMoreStatus === 'noMore'" class="no-more">
|
||||
<text>没有更多数据了</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 无数据提示 -->
|
||||
<view class="no-data" v-if="guidelinesList.length === 0 && !isLoading">
|
||||
<uni-icons type="info" size="60" color="#999"></uni-icons>
|
||||
<text>暂无诊疗指南数据</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted} from 'vue'
|
||||
import api from '@/api/api.js'
|
||||
import { onShow,onLoad } from "@dcloudio/uni-app";
|
||||
import docUrl from "@/utils/docUrl.js"
|
||||
import navTo from "@/utils/navTo.js"
|
||||
import hotImg from "@/static/hot_booklist.png"
|
||||
// 响应式数据
|
||||
const guidelinesList = ref([])
|
||||
const isLoading = ref(false)
|
||||
const hasMoreData = ref(true)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const isRefreshing = ref(false)
|
||||
const keywords=ref('');
|
||||
import upImg from "@/static/triangle_green_theme.png"
|
||||
import downImg from "@/static/triangle_normal.png"
|
||||
const loadMoreStatus = ref('more') // 'loading', 'more', 'noMore'
|
||||
const typeUuid=ref('');
|
||||
const title=ref('');
|
||||
const sort=ref(2);
|
||||
const from=ref('');
|
||||
const name=ref('');
|
||||
const showInnerSort=ref(false);
|
||||
const innerSortTitle=ref('上传时间');
|
||||
const chooseInnerSort=(index)=>{
|
||||
sort.value=index;
|
||||
if(index==1){
|
||||
innerSortTitle.value='下载量';
|
||||
}else if(index==2){
|
||||
innerSortTitle.value='上传时间';
|
||||
}else if(index==3){
|
||||
innerSortTitle.value='标题';
|
||||
}
|
||||
showInnerSort.value=false;
|
||||
loadGuidelinesList(true);
|
||||
}
|
||||
onLoad((options)=>{
|
||||
if(options.keywords){
|
||||
keywords.value=decodeURIComponent(options.keywords);
|
||||
}
|
||||
console.log(options)
|
||||
if(options.from){
|
||||
from.value=options.from;
|
||||
}
|
||||
if(options.name){
|
||||
name.value=options.name;
|
||||
}
|
||||
if(options.typeUuid){
|
||||
typeUuid.value=options.typeUuid;
|
||||
}
|
||||
title.value=options.from?'年度Top10':'诊疗指南';
|
||||
})
|
||||
const goGot=()=>{
|
||||
navTo({
|
||||
url:'/pages_app/hot/hot?from=hot'
|
||||
})
|
||||
}
|
||||
const toggleInnerSort=()=>{
|
||||
showInnerSort.value=!showInnerSort.value;
|
||||
}
|
||||
onShow(() => {
|
||||
// 页面显示时,如果列表为空则加载数据
|
||||
if (guidelinesList.value.length === 0) {
|
||||
if(from.value){
|
||||
top10ByType();
|
||||
}else{
|
||||
loadGuidelinesList(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 跳转到搜索页
|
||||
const goToSearch = () => {
|
||||
const q = keywords.value ? encodeURIComponent(keywords.value) : ''
|
||||
const t = title.value ? encodeURIComponent(title.value) : ''
|
||||
const type = typeUuid.value ? `&typeUuid=${encodeURIComponent(typeUuid.value)}` : ''
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`
|
||||
})
|
||||
}
|
||||
|
||||
// scroll-view 下拉刷新
|
||||
const onRefresh = async () => {
|
||||
console.log('scroll-view 下拉刷新触发');
|
||||
isRefreshing.value = true;
|
||||
await refreshData();
|
||||
isRefreshing.value = false;
|
||||
};
|
||||
const top10ByType=async ()=>{
|
||||
const res=await api.top10ByType({
|
||||
type:1,
|
||||
guide_type_uuid:typeUuid.value
|
||||
});
|
||||
if(res.code==200){
|
||||
guidelinesList.value=res.data;
|
||||
loadMoreStatus.value = 'noMore'
|
||||
hasMoreData.value = false
|
||||
}
|
||||
}
|
||||
// scroll-view 滚动到底部
|
||||
const onScrollToLower = () => {
|
||||
console.log('=== onScrollToLower 触发 ===');
|
||||
console.log('当前状态:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
isRefreshing: isRefreshing.value,
|
||||
currentPage: currentPage.value,
|
||||
listLength: guidelinesList.value.length,
|
||||
hasMoreData: hasMoreData.value,
|
||||
isLoading: isLoading.value
|
||||
});
|
||||
|
||||
if (loadMoreStatus.value === 'more' && !isRefreshing.value && !isLoading.value) {
|
||||
console.log('条件满足,开始加载更多数据');
|
||||
if(from.value){
|
||||
top10ByType();
|
||||
}else{
|
||||
loadGuidelinesList()
|
||||
}
|
||||
} else {
|
||||
console.log('条件不满足,跳过加载:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
isRefreshing: isRefreshing.value,
|
||||
isLoading: isLoading.value
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 刷新数据
|
||||
const refreshData = async () => {
|
||||
try {
|
||||
currentPage.value = 1
|
||||
hasMoreData.value = true
|
||||
loadMoreStatus.value = 'more'
|
||||
if(from.value){
|
||||
await top10ByType();
|
||||
}else{
|
||||
await loadGuidelinesList(true)
|
||||
}
|
||||
|
||||
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success'
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('刷新失败:', error)
|
||||
uni.showToast({
|
||||
title: '刷新失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 加载指南列表
|
||||
const loadGuidelinesList = async (isRefresh = false) => {
|
||||
console.log('=== loadGuidelinesList 开始 ===');
|
||||
console.log('当前参数:', { isRefresh, page: currentPage.value, keywords: keywords.value });
|
||||
|
||||
if (isLoading.value) return
|
||||
|
||||
try {
|
||||
isLoading.value = true
|
||||
loadMoreStatus.value = 'loading'
|
||||
|
||||
const params = {
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
type: 1, // 诊疗指南类型
|
||||
sort:2,
|
||||
name:name.value,
|
||||
typeUuid:typeUuid.value,
|
||||
keywords:keywords.value
|
||||
}
|
||||
|
||||
const res = await api.searchLibraryU(params)
|
||||
console.log('指南列表响应:', res)
|
||||
|
||||
if (res.code === 200 && res.data) {
|
||||
const newData = res.data.list || res.data
|
||||
|
||||
if (isRefresh) {
|
||||
guidelinesList.value = newData
|
||||
console.log('刷新模式:替换列表数据');
|
||||
} else {
|
||||
guidelinesList.value = [...guidelinesList.value, ...newData]
|
||||
console.log('加载更多:追加数据到列表');
|
||||
}
|
||||
|
||||
// 判断是否还有更多数据
|
||||
if (newData.length < pageSize.value) {
|
||||
loadMoreStatus.value = 'noMore'
|
||||
hasMoreData.value = false
|
||||
console.log('没有更多数据了');
|
||||
} else {
|
||||
loadMoreStatus.value = 'more'
|
||||
hasMoreData.value = true
|
||||
// 只有在加载更多模式下才递增页码
|
||||
if (!isRefresh) {
|
||||
currentPage.value++
|
||||
console.log(`还有更多数据,下一页: ${currentPage.value}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error('加载指南列表失败:', res.message)
|
||||
loadMoreStatus.value = 'noMore'
|
||||
uni.showToast({
|
||||
title: res.message || '加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载指南列表异常:', error)
|
||||
loadMoreStatus.value = 'noMore'
|
||||
uni.showToast({
|
||||
title: '网络异常,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
console.log('=== loadGuidelinesList 结束 ===');
|
||||
console.log('最终状态:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
page: currentPage.value,
|
||||
listLength: guidelinesList.value.length
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多数据
|
||||
const loadMoreData = () => {
|
||||
console.log('=== loadMoreData 被调用 ===');
|
||||
console.log('检查条件:', {
|
||||
hasMoreData: hasMoreData.value,
|
||||
isLoading: isLoading.value,
|
||||
currentPage: currentPage.value
|
||||
});
|
||||
|
||||
if (hasMoreData.value && !isLoading.value) {
|
||||
console.log('条件满足,开始加载更多数据');
|
||||
loadGuidelinesList(false);
|
||||
} else {
|
||||
console.log('条件不满足,跳过加载更多');
|
||||
}
|
||||
}
|
||||
|
||||
// 下载指南
|
||||
const downloadGuideline = (item) => {
|
||||
console.log('下载指南:', item)
|
||||
uni.showToast({
|
||||
title: '开始下载...',
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
// 这里可以调用下载API
|
||||
// 示例:下载PDF文件
|
||||
if (item.file_path) {
|
||||
uni.downloadFile({
|
||||
url: item.file_path,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.showToast({
|
||||
title: '下载成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('下载失败:', err)
|
||||
uni.showToast({
|
||||
title: '下载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 查看指南(支持常用文档直链:pdf/doc/docx/xls/xlsx/ppt/pptx/txt)
|
||||
const viewGuideline = (item) => {
|
||||
const url = docUrl+item.path
|
||||
if (url) {
|
||||
const isPDF = /\.(pdf)(\?|$)/i.test(url)
|
||||
const isOffice = /\.(docx?|xlsx?|pptx?)(\?|$)/i.test(url)
|
||||
const isText = /\.(txt)(\?|$)/i.test(url)
|
||||
|
||||
// H5 端
|
||||
// #ifdef H5
|
||||
if (isPDF) {
|
||||
try { window.open(url, '_blank') } catch (e) {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
return
|
||||
}
|
||||
if (isOffice) {
|
||||
const officeUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`
|
||||
try { window.open(officeUrl, '_blank') } catch (e) {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(officeUrl)}` })
|
||||
}
|
||||
return
|
||||
}
|
||||
if (isText) {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
return
|
||||
}
|
||||
// 其他格式统一用 webview 打开
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
return
|
||||
// #endif
|
||||
|
||||
// 非 H5 端:下载后尝试用 openDocument,失败回退 webview
|
||||
// #ifndef H5
|
||||
uni.showToast({ title: '正在打开...', icon: 'none' })
|
||||
uni.downloadFile({
|
||||
url,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200 && res.tempFilePath) {
|
||||
uni.openDocument({
|
||||
filePath: res.tempFilePath,
|
||||
showMenu: true,
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
})
|
||||
return
|
||||
// #endif
|
||||
}
|
||||
// 无直链,回退到详情页
|
||||
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
// 测试加载更多功能
|
||||
const testLoadMore = () => {
|
||||
console.log('=== 手动测试加载更多 ===');
|
||||
console.log('当前状态:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
hasMoreData: hasMoreData.value,
|
||||
isLoading: isLoading.value,
|
||||
currentPage: currentPage.value,
|
||||
listLength: guidelinesList.value.length
|
||||
});
|
||||
|
||||
if (loadMoreStatus.value === 'more' && !isLoading.value) {
|
||||
loadMoreData();
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: `状态: ${loadMoreStatus.value}, 加载中: ${isLoading.value}`,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateString) => {
|
||||
if (!dateString) return ''
|
||||
|
||||
try {
|
||||
const date = new Date(dateString)
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
} catch (error) {
|
||||
return dateString
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 颜色变量
|
||||
$primary-color: #ff4757;
|
||||
$text-primary: #333;
|
||||
$text-secondary: #666;
|
||||
$text-light: #999;
|
||||
$border-color: #e0e0e0;
|
||||
$bg-color: #f6f6f6;
|
||||
$white: #ffffff;
|
||||
.imgbox{
|
||||
width: 32rpx;
|
||||
margin-top: -10rpx;
|
||||
}
|
||||
.popup-panel {
|
||||
position: fixed;
|
||||
top: 242rpx; /* 紧贴筛选栏 */
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
z-index: 10;
|
||||
box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.popup-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 28rpx 30rpx;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-divider {
|
||||
height: 2rpx;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
.popup-item.active .item-text {
|
||||
color: #8B2316;
|
||||
}
|
||||
.current-sort {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
|
||||
.sort-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sort-icon.up {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8rpx solid transparent;
|
||||
border-right: 8rpx solid transparent;
|
||||
border-bottom: 12rpx solid #999;
|
||||
|
||||
&.active {
|
||||
border-bottom-color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zhinan-list-page {
|
||||
background-color: $bg-color;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.guidelines-scroll-view {
|
||||
position: fixed;
|
||||
top: 140rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
height: calc(100vh - 140rpx);
|
||||
background-color: $bg-color;
|
||||
}
|
||||
// 固定搜索容器
|
||||
.search-container-fixed {
|
||||
position: fixed;
|
||||
top: 140rpx; // 导航栏高度
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 90;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 30rpx 30rpx;
|
||||
background-color: $white;
|
||||
gap: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
// 筛选栏
|
||||
.filter-bar {
|
||||
background-color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 2px solid #eee;
|
||||
|
||||
.search-box {
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
|
||||
.search-text {
|
||||
font-size: 14px;
|
||||
color:#999;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 1px;
|
||||
height: 16px;
|
||||
background-color: #999;
|
||||
margin: 0 60rpx;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex:1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 3px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
// 指南列表
|
||||
.guidelines-list {
|
||||
padding: 20rpx 30rpx;
|
||||
|
||||
.guideline-item {
|
||||
background-color: $white;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||
|
||||
.item-content {
|
||||
flex: 1;
|
||||
margin-right: 30rpx;
|
||||
|
||||
.item-title {
|
||||
font-size: 32rpx;
|
||||
color: $text-primary;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 16rpx;
|
||||
font-weight: 500;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.item-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 10rpx;
|
||||
|
||||
.item-date {
|
||||
font-size: 26rpx;
|
||||
color: $text-secondary;
|
||||
}
|
||||
|
||||
.item-action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.download-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 71, 87, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
background-color: rgba(255, 71, 87, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.view-btn {
|
||||
color:#8B2316;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
background-color: darken($primary-color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多状态
|
||||
.load-more-status {
|
||||
padding: 20rpx 0;
|
||||
text-align: center;
|
||||
|
||||
.loading, .more, .no-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
padding: 20rpx 0;
|
||||
font-size: 26rpx;
|
||||
color: $text-light;
|
||||
}
|
||||
}
|
||||
|
||||
// 无数据提示
|
||||
.no-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 120rpx 0;
|
||||
|
||||
text {
|
||||
margin-top: 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: $text-light;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
855
pages_app/patientVideo/patientVideo.vue
Normal file
855
pages_app/patientVideo/patientVideo.vue
Normal file
@ -0,0 +1,855 @@
|
||||
<template>
|
||||
<uni-nav-bar left-icon="left"
|
||||
@clickLeft="goBack" title="患教视频" fixed color="#8B2316" height="140rpx" :border="false" backgroundColor="#eeeeee"></uni-nav-bar>
|
||||
<view class="video-page">
|
||||
<!-- Header -->
|
||||
|
||||
|
||||
<!-- Fixed Filter Tabs -->
|
||||
<view class="filter-tabs-container">
|
||||
<view class="filter-tabs">
|
||||
<view
|
||||
class="tab-item"
|
||||
@click="showAllVideoPopup=!showAllVideoPopup"
|
||||
>
|
||||
<up-image :src="isAllActive?allOnImg:allImg" width="30rpx" height="30rpx" ></up-image>
|
||||
<text class="tab-text" :class="{active:isAllActive}">{{typeName}}</text>
|
||||
<up-image :src="isAllActive?selectOnImg:selectImg" width="30rpx" height="30rpx" ></up-image>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view
|
||||
class="tab-item"
|
||||
@click="toggleSort"
|
||||
>
|
||||
<text class="tab-text active">{{sort==2?'最新':'最热'}}</text>
|
||||
<view class="newbox">
|
||||
<up-image :src="sort==2?upImg:downImg" width="20rpx" height="26rpx" ></up-image>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="tab-item"
|
||||
@click="showFilterPopup"
|
||||
>
|
||||
<text class="tab-text " :class="{active:isFilterActive}">筛选</text>
|
||||
<view class="filterbox">
|
||||
<up-image :src="isFilterActive ? filterOn : filter" width="30rpx" height="30rpx" ></up-image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Main Content -->
|
||||
<scroll-view
|
||||
class="scroll-view"
|
||||
scroll-y="true"
|
||||
refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="onLoadMore"
|
||||
lower-threshold="100"
|
||||
>
|
||||
|
||||
<!-- Video List -->
|
||||
<view class="video-list">
|
||||
<view
|
||||
class="video-item"
|
||||
v-for="(video, index) in videoList"
|
||||
:key="video.id || video.uuid"
|
||||
@click="playVideo(video)"
|
||||
>
|
||||
<view class="video-thumbnail">
|
||||
<image :src="docUrl + video.imgpath" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="video-info">
|
||||
<view class="video-title">{{video.title || video.name}}</view>
|
||||
<view class="video-meta">
|
||||
<text class="author">{{video.public_name}}</text>
|
||||
<view class="stats">
|
||||
<uni-icons type="eye" size="14" color="#999"></uni-icons>
|
||||
<text class="view-count">{{video.readnum}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Loading More -->
|
||||
<uni-load-more
|
||||
v-if="videoList.length > 0"
|
||||
:status="loadMoreStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了'
|
||||
}"
|
||||
></uni-load-more>
|
||||
|
||||
<!-- Empty State -->
|
||||
<view class="empty-state" v-if="videoList.length === 0 && !loading">
|
||||
<empty></empty>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 筛选弹窗 -->
|
||||
<view class="filter-popup" v-if="showFilter" @click="hideFilterPopup">
|
||||
<view class="filter-content" @click.stop>
|
||||
<!-- 筛选标签网格 -->
|
||||
<view class="filter-tags">
|
||||
<view
|
||||
class="tag-item"
|
||||
v-for="(tag, index) in filterTags"
|
||||
:key="index"
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.NAME }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="filter-buttons">
|
||||
<view class="btn-reset" @click="resetFilter">重置</view>
|
||||
<view class="btn-confirm" @click="confirmFilter">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 全部视频弹窗 -->
|
||||
<view class="all-video-popup" v-if="showAllVideoPopup" @click="closeAllVideoPopup">
|
||||
<view class="popup-content" @click.stop>
|
||||
<view class="popup-body">
|
||||
<view
|
||||
class="category-item"
|
||||
:class="{ active: typeUuid === item.uuid }"
|
||||
v-for="item in videoTypeList"
|
||||
:key="item.uuid"
|
||||
@click="selectCategory(item.uuid)"
|
||||
>
|
||||
{{ item.name }}
|
||||
</view>
|
||||
<view v-if="videoTypeList.length === 0" class="empty-content">
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed,reactive } from 'vue';
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import api from '@/api/api.js';
|
||||
import allImg from "@/static/video_all.png"
|
||||
import allOnImg from "@/static/video_select.png"
|
||||
import selectImg from "@/static/all_video.png"
|
||||
import selectOnImg from "@/static/select_video.png"
|
||||
import filter from "@/static/cb_screen_no.png"
|
||||
import filterOn from "@/static/cb_screen_yes.png"
|
||||
import upImg from "@/static/cb_up.png"
|
||||
import downImg from "@/static/cb_down.png"
|
||||
import docUrl from '@/utils/docUrl';
|
||||
import navTo from '@/utils/navTo';
|
||||
import empty from '@/components/empty/empty.vue';
|
||||
const isAllActive=ref(false)
|
||||
// 响应式数据
|
||||
const videoList = ref([]);
|
||||
const activeTab = ref(1); // 默认选中"最新"
|
||||
const loading = ref(false);
|
||||
const refreshing = ref(false);
|
||||
const loadMoreStatus = ref('more'); // more, loading, noMore
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const hasMoreData = ref(true);
|
||||
const filteredContent=ref([])
|
||||
const sort =ref(2);
|
||||
const keywords=ref('');
|
||||
const typeUuid=ref('0e5fa3d76b8047528fdd3c452b77e9dd');
|
||||
const typeName=ref('乙肝')
|
||||
const isFilterActive=ref(false)
|
||||
const showFilter = ref(false);
|
||||
const yearList=ref([]);
|
||||
const selectYearContent=reactive({})
|
||||
// 筛选弹窗相关数据
|
||||
const filterTags = ref([]);
|
||||
|
||||
// 全部视频弹窗相关数据
|
||||
const showAllVideoPopup = ref(false);
|
||||
const selectedCategory = ref('全部');
|
||||
const selectCategory=(uuid)=>{
|
||||
console.log(222)
|
||||
console.log(uuid)
|
||||
typeUuid.value=uuid;
|
||||
typeName.value=videoTypeList.value.find(item=>item.uuid==uuid).name;
|
||||
isAllActive.value=true;
|
||||
closeAllVideoPopup();
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData();
|
||||
}
|
||||
|
||||
const videoTypeList=ref([]);
|
||||
const patientVideoNew=async ()=>{
|
||||
const res=await api.patientVideoNew();
|
||||
if(res.code==200){
|
||||
videoTypeList.value=res.data;
|
||||
}
|
||||
}
|
||||
// 页面加载
|
||||
onMounted(() => {
|
||||
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
// 调用真实API获取数据
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadGuideTags();
|
||||
loadVideoData();
|
||||
patientVideoNew();
|
||||
});
|
||||
|
||||
// 加载轮播数据
|
||||
|
||||
// 加载视频标签
|
||||
const loadGuideTags = async () => {
|
||||
try {
|
||||
const res = await api.guideTag({
|
||||
type:5
|
||||
});
|
||||
console.log('指南标签API响应:', res);
|
||||
if(res && res.code === 200 && res.data) {
|
||||
// 将API返回的标签数据转换为筛选标签格式
|
||||
filterTags.value = res.data.map(tag => ({
|
||||
...tag,
|
||||
selected: false
|
||||
}));
|
||||
console.log('指南标签加载成功:', filterTags.value);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载指南标签失败:', e);
|
||||
}
|
||||
};
|
||||
// 加载视频数据
|
||||
const loadVideoData = async (isRefresh = false) => {
|
||||
if (loading.value && !isRefresh) return;
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const response = await api.patientVideoByKeyWordsNew({
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
keywords: keywords.value,
|
||||
sort:sort.value,
|
||||
typeUuid:typeUuid.value,
|
||||
});
|
||||
|
||||
console.log('视频列表API原始响应:', response);
|
||||
|
||||
// 检查响应结构
|
||||
let videoData = {};
|
||||
if (response && response.data) {
|
||||
if (response.data.code === 200) {
|
||||
videoData = response.data.data || {};
|
||||
} else if (response.code === 200) {
|
||||
videoData = response.data || {};
|
||||
}
|
||||
} else if (response && response.code === 200) {
|
||||
videoData = response.data || {};
|
||||
}
|
||||
|
||||
console.log('解析后的视频数据:', videoData);
|
||||
|
||||
if (videoData && videoData.list) {
|
||||
const { list, totalPage,pageNumber } = videoData;
|
||||
console.log('视频列表数据:', list);
|
||||
|
||||
if (isRefresh) {
|
||||
videoList.value = list || [];
|
||||
currentPage.value = 1;
|
||||
} else {
|
||||
videoList.value = [...videoList.value, ...(list || [])];
|
||||
}
|
||||
|
||||
hasMoreData.value = totalPage>pageNumber;
|
||||
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
|
||||
} else {
|
||||
throw new Error(response?.message || '获取数据失败');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载视频失败:', error);
|
||||
|
||||
} finally {
|
||||
loading.value = false;
|
||||
refreshing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true;
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData(true);
|
||||
};
|
||||
|
||||
// 上拉加载更多
|
||||
const onLoadMore = () => {
|
||||
if (!hasMoreData.value || loading.value) return;
|
||||
|
||||
loadMoreStatus.value = 'loading';
|
||||
currentPage.value++;
|
||||
loadVideoData();
|
||||
};
|
||||
|
||||
// 切换标签
|
||||
const switchTab = (tabIndex) => {
|
||||
activeTab.value = tabIndex;
|
||||
// 可以根据标签加载不同的数据
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData();
|
||||
};
|
||||
|
||||
// 播放视频
|
||||
const playVideo = (video) => {
|
||||
const videoId = video.id || video.uuid;
|
||||
|
||||
navTo({
|
||||
url: `/pages_app/videoDetail/videoDetail?id=${videoId}`
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 搜索
|
||||
const goSearch = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages_app/search/search'
|
||||
});
|
||||
};
|
||||
|
||||
// 跳转到患教视频列表
|
||||
|
||||
// 搜索视频
|
||||
const searchVideos = async (keywords) => {
|
||||
if (!keywords || keywords.trim() === '') {
|
||||
loadVideoData();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('搜索关键词:', keywords.trim());
|
||||
const response = await api.patientVideoByKeyWordsNew({
|
||||
keywords: keywords.trim(),
|
||||
page: 1,
|
||||
pageSize: pageSize.value
|
||||
});
|
||||
|
||||
console.log('搜索API原始响应:', response);
|
||||
|
||||
// 检查响应结构
|
||||
let searchData = {};
|
||||
if (response && response.data) {
|
||||
if (response.data.code === 200) {
|
||||
searchData = response.data.data || {};
|
||||
} else if (response.code === 200) {
|
||||
searchData = response.data || {};
|
||||
}
|
||||
} else if (response && response.code === 200) {
|
||||
searchData = response.data || {};
|
||||
}
|
||||
|
||||
console.log('解析后的搜索数据:', searchData);
|
||||
|
||||
if (searchData && searchData.list) {
|
||||
const { list, hasMore } = searchData;
|
||||
console.log('搜索结果:', list);
|
||||
videoList.value = list || [];
|
||||
hasMoreData.value = hasMore !== false;
|
||||
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
|
||||
currentPage.value = 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('搜索视频失败:', error);
|
||||
uni.showToast({
|
||||
title: '搜索失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// 全部视频弹窗相关方法
|
||||
const openAllVideoPopup = () => {
|
||||
showAllVideoPopup.value = true;
|
||||
};
|
||||
|
||||
const closeAllVideoPopup = () => {
|
||||
showAllVideoPopup.value = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 筛选弹窗相关方法
|
||||
const showFilterPopup = () => {
|
||||
showFilter.value = true;
|
||||
};
|
||||
|
||||
const hideFilterPopup = () => {
|
||||
showFilter.value = false;
|
||||
};
|
||||
|
||||
const toggleTag = (index) => {
|
||||
filterTags.value[index].selected = !filterTags.value[index].selected;
|
||||
|
||||
};
|
||||
|
||||
const resetFilter = () => {
|
||||
// 清空所有已选标签
|
||||
filterTags.value.forEach(tag => tag.selected = false);
|
||||
// 关闭筛选激活态
|
||||
|
||||
// 清空关键字
|
||||
keywords.value = '';
|
||||
// 刷新列表数据(可按需保留或移除)
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData(true);
|
||||
};
|
||||
|
||||
const confirmFilter = () => {
|
||||
const selectedTags = filterTags.value.filter(tag => tag.selected);
|
||||
console.log('选中的筛选标签:', selectedTags);
|
||||
for (var i = 0; i < selectedTags.length; i++) {
|
||||
if(keywords.value){
|
||||
keywords.value+=","+selectedTags[i].NAME
|
||||
}else{
|
||||
keywords.value=selectedTags[i].NAME
|
||||
}
|
||||
}
|
||||
isFilterActive.value=true;
|
||||
hideFilterPopup();
|
||||
// 根据选中的标签重新加载数据
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData(true);
|
||||
};
|
||||
|
||||
// 返回
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
fail() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
const toggleSort = () => {
|
||||
sort.value = sort.value === 1 ? 2 : 1; // 1=最新, 2=最热(与后端约定)
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData();
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$primary-color: #ff6b6b;
|
||||
$theme-color: #8B2316;
|
||||
$white: #fff;
|
||||
$gray-bg: #f5f5f5;
|
||||
$gray-light: #eee;
|
||||
$gray-medium: #999;
|
||||
$gray-dark: #666;
|
||||
$text-color: #333;
|
||||
|
||||
// 尺寸变量
|
||||
$border-radius: 8px;
|
||||
$border-radius-small: 6px;
|
||||
$padding: 15px;
|
||||
$padding-small: 10px;
|
||||
.video-page {
|
||||
background-color: #f5f5f5;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Header Styles */
|
||||
.header {
|
||||
background-color: #fff;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.header-left, .header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #8B4513;
|
||||
}
|
||||
|
||||
/* Scroll View */
|
||||
.scroll-view {
|
||||
position: fixed;
|
||||
bottom: 0rpx;
|
||||
height: calc(100vh - 140rpx); /* 固定高度,减去导航栏高度 */
|
||||
background-color: #f5f5f5;
|
||||
top: 172rpx; /* 为导航栏留出空间 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Filter Tabs */
|
||||
.filter-tabs {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 30rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 60rpx;
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
.tab-item:last-child{
|
||||
margin-right: 0;
|
||||
}
|
||||
.right{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: #E74C3C;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
margin: 0 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
.tab-item:first-child .tab-text{
|
||||
max-width:295rpx;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tab-item .tab-text.active {
|
||||
color: #8B2316;
|
||||
|
||||
}
|
||||
|
||||
/* Fixed Filter Tabs Container */
|
||||
.filter-tabs-container {
|
||||
position: fixed;
|
||||
top: 140rpx; /* uni-nav-bar height */
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 40;
|
||||
background-color: #fff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.doctor-avatar {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.doctor-avatar image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Video List */
|
||||
.video-list {
|
||||
padding: 0 20rpx;
|
||||
margin-top: 100rpx; /* 为固定的Filter Tabs留出空间 */
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx; /* 卡片间距 */
|
||||
}
|
||||
|
||||
.video-item {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
|
||||
width: calc(50% - 8rpx); /* 两列布局,减半gap */
|
||||
min-width: 300rpx; /* 确保最小宽度 */
|
||||
flex-shrink: 0; /* 防止收缩 */
|
||||
}
|
||||
|
||||
.video-thumbnail {
|
||||
position: relative;
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.video-thumbnail image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.video-duration {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.video-duration text {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.video-info {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.video-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 16rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
overflow: hidden;
|
||||
height: 2.8em; /* 固定2行高度:1.4 * 2 = 2.8em */
|
||||
}
|
||||
|
||||
.video-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.author {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.view-count {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
/* Empty State */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-state image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 30rpx;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-state text {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.newbox{
|
||||
margin-top: -12rpx;
|
||||
}
|
||||
|
||||
/* 全部视频弹窗样式 */
|
||||
.all-video-popup {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
height:calc(100vh - 272rpx);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
height:100%;
|
||||
|
||||
}
|
||||
|
||||
.category-item {
|
||||
padding: 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background-color: #fff;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.category-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.category-item.active {
|
||||
background-color: #f8f8f8;
|
||||
color: #8B2316;
|
||||
}
|
||||
|
||||
.category-item:active {
|
||||
background-color: #e8f4fd;
|
||||
}
|
||||
|
||||
.empty-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
// 筛选弹窗样式
|
||||
.filter-popup {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
// background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
z-index: 9999;
|
||||
|
||||
.filter-content {
|
||||
margin-top:272rpx;
|
||||
overflow-y:scroll;
|
||||
background-color: $white;
|
||||
// border-radius: 20rpx 20rpx 0 0;
|
||||
padding: 20rpx 30rpx 60rpx;
|
||||
width: 100%;
|
||||
height: calc(100vh - 272rpx);
|
||||
|
||||
.filter-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 60rpx;
|
||||
max-height: 65vh;
|
||||
overflow-y: auto;
|
||||
|
||||
.tag-item {
|
||||
background-color: #f8f8f8;
|
||||
color: $gray-dark;
|
||||
padding: 8rpx 0; /* 去掉左右padding,仅保留上下 */
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
border: 2rpx solid #efefef;
|
||||
transition: all 0.3s ease;
|
||||
width: 152rpx; /* 固定宽度 */
|
||||
text-align: center; /* 文本居中 */
|
||||
white-space: nowrap; /* 单行显示 */
|
||||
overflow: hidden; /* 隐藏溢出 */
|
||||
text-overflow: ellipsis; /* 超出显示省略号 */
|
||||
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
color: $theme-color;
|
||||
border-color: $theme-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-buttons {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
position: fixed;
|
||||
bottom: 30rpx;
|
||||
left: 30rpx;
|
||||
right: 30rpx;
|
||||
background-color: #fff; /* 背景色为白色 */
|
||||
|
||||
.btn-reset,
|
||||
.btn-confirm {
|
||||
flex: 1;
|
||||
height: 70rpx;
|
||||
border-radius: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-reset {
|
||||
background-color: $white;
|
||||
color: $theme-color;
|
||||
border: 2rpx solid $theme-color;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
border: 2rpx solid $theme-color;
|
||||
background-color: $theme-color;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -38,7 +38,7 @@
|
||||
class="category-item"
|
||||
v-for="(item, index) in categoryList"
|
||||
:key="index"
|
||||
@click="onCategoryClick(index)"
|
||||
@click="onCategoryClick(Index,item.type)"
|
||||
>
|
||||
<view class="category-icon">
|
||||
<up-image :src="item.icon" width="60rpx" height="60rpx" v-if="tab!=index"></up-image>
|
||||
@ -97,7 +97,7 @@
|
||||
{ name: '指南', icon:zhinan, activeIcon:zhinanOn,type: 'zhinan' },
|
||||
{ name: '精品课', icon:course,activeIcon:courseOn, type: 'course' },
|
||||
{ name: '肝胆课件', icon:ppt,activeIcon:pptOn, type: 'ppt' },
|
||||
{ name: '患者', icon:patient, patientIcon:videoOn,type: 'patient' },
|
||||
{ name: '患者', icon:patient, patientIcon:patientOn,type: 'patient' },
|
||||
{ name: '名院', icon:doctor,activeIcon:doctorOn, type: 'doctor' },
|
||||
{ name: '名科', icon:department,activeIcon:departmentOn, type: 'department' },
|
||||
{ name: '名医', icon:doctor, activeIcon:doctorOn,type: 'doctor' },
|
||||
@ -134,8 +134,33 @@
|
||||
};
|
||||
|
||||
// 点击分类
|
||||
const onCategoryClick = (index) => {
|
||||
const onCategoryClick = (index,type) => {
|
||||
tab.value=index;
|
||||
if(type=='video'){
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/searchVideo/searchVideo?keywords=${searchKeyword.value}`
|
||||
})
|
||||
}else if(type=='videoPatient'){
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/searchVideo/searchVideo?keywords=${searchKeyword.value}&from=hjsp`
|
||||
})
|
||||
}else if(type=='news'){
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/searchNews/searchNews?keywords=${searchKeyword.value}`
|
||||
})
|
||||
}else if(type=='kepu'){
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/searchNews/searchNews?keywords=${searchKeyword.value}&from=kp`
|
||||
})
|
||||
}else if(type=='zhinan'){
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/hot/hot?name=${searchKeyword.value}`
|
||||
})
|
||||
}else if(type=='course'){
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/searchNews/searchNews?keywords=${searchKeyword.value}&from=kp`
|
||||
})
|
||||
}
|
||||
|
||||
// 这里可以根据分类进行搜索
|
||||
};
|
||||
@ -313,6 +338,7 @@
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
638
pages_app/searchNews/searchNews.vue
Normal file
638
pages_app/searchNews/searchNews.vue
Normal file
@ -0,0 +1,638 @@
|
||||
<template>
|
||||
<view class="news-list-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
:title="title"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
height="140rpx"
|
||||
:border="false"
|
||||
backgroundColor="#eeeeee"
|
||||
></uni-nav-bar>
|
||||
|
||||
|
||||
<!-- 新闻列表 -->
|
||||
<scroll-view
|
||||
class="news-scroll-view"
|
||||
scroll-y="true"
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="isRefreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="onScrollToLower"
|
||||
:show-scrollbar="false"
|
||||
>
|
||||
|
||||
<view class="news-list">
|
||||
<view
|
||||
class="news-item"
|
||||
v-for="(news, index) in newsList"
|
||||
:key="news.uuid || index"
|
||||
@click="goToNewsDetail(news)"
|
||||
>
|
||||
<view class="item-image-container">
|
||||
<image
|
||||
class="item-image"
|
||||
:src="docUrl + (news.headImg || news.imgPath) "
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view class="important-tag" v-if="news.isImportant">重要通知</view>
|
||||
</view>
|
||||
<view class="item-content">
|
||||
<view class="item-title">{{ news.title || news.topic }}</view>
|
||||
<view class="item-meta">
|
||||
<text class="item-date">{{ formatDate(news.createDate || news.submitDate) }}</text>
|
||||
<view class="item-stats">
|
||||
<uni-icons type="eye" size="14" color="#999"></uni-icons>
|
||||
<text>{{ news.readnum || 0 }}</text>
|
||||
<uni-icons type="hand-up" size="14" color="#999" style="margin-left: 20rpx;"></uni-icons>
|
||||
<text>{{ news.likenum || news.agreenum }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多/无数据提示 -->
|
||||
<view class="load-more-status">
|
||||
<view v-if="loadMoreStatus === 'loading'" class="loading">
|
||||
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
<view v-else-if="loadMoreStatus === 'more'" class="more">
|
||||
<text>上拉加载更多</text>
|
||||
</view>
|
||||
<view v-else-if="loadMoreStatus === 'noMore'" class="no-more">
|
||||
<text>没有更多数据了</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, reactive } from 'vue';
|
||||
import { onShow, onPullDownRefresh, onReachBottom,onLoad } from '@dcloudio/uni-app';
|
||||
import api from '@/api/api.js';
|
||||
import docUrl from '@/utils/docUrl.js';
|
||||
import dayjs from 'dayjs';
|
||||
import navTo from '@/utils/navTo.js';
|
||||
const from=ref('');
|
||||
const title=ref('肝胆新闻');
|
||||
// Banner相关数据
|
||||
const bannerList = ref([]);
|
||||
const currentBannerIndex = ref(0);
|
||||
const newstagid=ref('');
|
||||
// 响应式数据
|
||||
const activeTab = ref(-1); // '肝胆新闻' is the second tab (index 1)
|
||||
const tabs = ref(['精选', '肝胆新闻', '技术快讯', '基地动态', '专家动态']);
|
||||
|
||||
const newsList = ref([]);
|
||||
const page = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const total = ref(0);
|
||||
const loadMoreStatus = ref('more'); // more, loading, noMore
|
||||
const isRefreshing = ref(false); // 控制下拉刷新状态
|
||||
const keywords=ref('');
|
||||
const loadMoreText = reactive({
|
||||
contentdown: '上拉显示更多',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了'
|
||||
});
|
||||
const newsTags = ref([]); // 新闻标签列表
|
||||
onLoad((options) => {
|
||||
if(options.from){
|
||||
from.value = options.from
|
||||
title.value = '患教学堂'
|
||||
}
|
||||
if(options.keywords){
|
||||
keywords.value = options.keywords
|
||||
}
|
||||
|
||||
})
|
||||
onShow(() => {
|
||||
|
||||
if(from.value){
|
||||
loadNewsListKePu();
|
||||
}else{
|
||||
loadNewsListIndex();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
const onSwiperChange = (e) => {
|
||||
currentBannerIndex.value = e.detail.current;
|
||||
};
|
||||
|
||||
// scroll-view 下拉刷新
|
||||
const onRefresh = async () => {
|
||||
console.log('scroll-view 下拉刷新触发');
|
||||
isRefreshing.value = true;
|
||||
await refreshData();
|
||||
isRefreshing.value = false;
|
||||
};
|
||||
|
||||
// scroll-view 滚动到底部
|
||||
const onScrollToLower = () => {
|
||||
console.log('=== onScrollToLower 触发 ===');
|
||||
console.log('当前状态:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
isRefreshing: isRefreshing.value,
|
||||
currentPage: page.value,
|
||||
listLength: newsList.value.length
|
||||
});
|
||||
|
||||
if (loadMoreStatus.value === 'more' && !isRefreshing.value) {
|
||||
console.log('条件满足,开始加载更多数据');
|
||||
if(from.value){
|
||||
loadNewsListKePu();
|
||||
}else{
|
||||
loadNewsListIndex();
|
||||
}
|
||||
} else {
|
||||
console.log('条件不满足,跳过加载:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
isRefreshing: isRefreshing.value
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 方法
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const goToSearch = () => {
|
||||
// Implement navigation to search page
|
||||
console.log('Go to search page');
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 加载新闻轮播数据
|
||||
|
||||
|
||||
// 加载新闻标签列表
|
||||
const loadNewsTags = async () => {
|
||||
try {
|
||||
const res = await api.newsTagList({});
|
||||
console.log('新闻标签响应:', res);
|
||||
|
||||
if (res && res.code === 200) {
|
||||
console.log('获取到标签数据:', res.data);
|
||||
tabs.value = res.data;
|
||||
|
||||
// 确保标签数据存在且有效
|
||||
if (res.data && Array.isArray(res.data) && res.data.length > 0) {
|
||||
newstagid.value = res.data[0].ID;
|
||||
//loadNewsList(true); // Initial load
|
||||
} else {
|
||||
console.warn('标签数据为空或格式不正确');
|
||||
newstagid.value = '';
|
||||
}
|
||||
} else {
|
||||
console.error('加载新闻标签失败:', res.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载新闻标签异常:', e);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载新闻列表数据
|
||||
const loadNewsListKePu = async (isRefresh = false) => {
|
||||
|
||||
if (isRefresh) {
|
||||
page.value = 1;
|
||||
newsList.value = [];
|
||||
loadMoreStatus.value = 'more';
|
||||
console.log('刷新模式:重置分页状态');
|
||||
}
|
||||
|
||||
// 检查加载状态
|
||||
if (loadMoreStatus.value === 'noMore' || loadMoreStatus.value === 'loading') {
|
||||
console.log('当前状态不允许加载:', loadMoreStatus.value);
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置加载状态
|
||||
loadMoreStatus.value = 'loading';
|
||||
console.log(`开始加载第${page.value}页数据,newstagid: ${newstagid.value}`);
|
||||
|
||||
try {
|
||||
const res = await api.polularScienceArticleListIndexNew({
|
||||
page: page.value,
|
||||
pageSize: pageSize.value,
|
||||
topic: keywords.value
|
||||
});
|
||||
console.log('新闻列表API响应:', res);
|
||||
|
||||
if (res && res.code === 200) {
|
||||
// 尝试多种可能的数据结构
|
||||
let newItems = [];
|
||||
let totalCount = 0;
|
||||
|
||||
if (res.data && res.data.list) {
|
||||
newItems = res.data.list;
|
||||
totalCount = res.data.totalRow;
|
||||
console.log('使用 res.data.list 结构');
|
||||
}
|
||||
|
||||
console.log('解析后的数据:', { newItems, totalCount, newItemsLength: newItems.length });
|
||||
|
||||
// 确保 newItems 是数组
|
||||
if (Array.isArray(newItems)) {
|
||||
if (isRefresh) {
|
||||
newsList.value = newItems;
|
||||
console.log('刷新模式:替换列表数据');
|
||||
} else {
|
||||
newsList.value = [...newsList.value, ...newItems];
|
||||
console.log('加载更多:追加数据到列表');
|
||||
}
|
||||
|
||||
total.value = totalCount;
|
||||
console.log(`当前页数据: ${newItems.length}, 总数: ${total.value}, 当前列表长度: ${newsList.value.length}`);
|
||||
|
||||
// 判断是否还有更多数据
|
||||
if (newItems.length < pageSize.value || newsList.value.length >= total.value) {
|
||||
loadMoreStatus.value = 'noMore';
|
||||
console.log('没有更多数据了');
|
||||
} else {
|
||||
loadMoreStatus.value = 'more';
|
||||
page.value++;
|
||||
console.log(`还有更多数据,下一页: ${page.value}`);
|
||||
}
|
||||
} else {
|
||||
console.error('API返回的数据不是数组格式:', newItems);
|
||||
loadMoreStatus.value = 'noMore';
|
||||
}
|
||||
} else {
|
||||
console.error('加载新闻列表失败:', res.message);
|
||||
loadMoreStatus.value = 'noMore';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载新闻列表异常:', e);
|
||||
loadMoreStatus.value = 'noMore';
|
||||
}
|
||||
|
||||
console.log('=== loadNewsList 结束 ===');
|
||||
console.log('最终状态:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
page: page.value,
|
||||
listLength: newsList.value.length
|
||||
});
|
||||
};
|
||||
|
||||
const loadNewsListIndex = async (isRefresh = false) => {
|
||||
console.log('=== loadNewsList 开始 ===');
|
||||
console.log('当前参数:', { isRefresh, page: page.value, newstagid: newstagid.value });
|
||||
|
||||
// 验证 newstagid 是否有效
|
||||
|
||||
|
||||
if (isRefresh) {
|
||||
page.value = 1;
|
||||
newsList.value = [];
|
||||
loadMoreStatus.value = 'more';
|
||||
console.log('刷新模式:重置分页状态');
|
||||
}
|
||||
|
||||
// 检查加载状态
|
||||
if (loadMoreStatus.value === 'noMore' || loadMoreStatus.value === 'loading') {
|
||||
console.log('当前状态不允许加载:', loadMoreStatus.value);
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置加载状态
|
||||
loadMoreStatus.value = 'loading';
|
||||
console.log(`开始加载第${page.value}页数据,newstagid: ${newstagid.value}`);
|
||||
|
||||
try {
|
||||
const res = await api.defaultNewsListNew({
|
||||
page: page.value,
|
||||
pageSize: pageSize.value,
|
||||
});
|
||||
console.log('新闻列表API响应:', res);
|
||||
|
||||
if (res && res.code === 200) {
|
||||
// 尝试多种可能的数据结构
|
||||
let newItems = [];
|
||||
let totalCount = 0;
|
||||
|
||||
if (res.data && res.data.list) {
|
||||
newItems = res.data.list;
|
||||
totalCount = res.data.totalRow || 0;
|
||||
console.log('使用 res.data.list 结构');
|
||||
}
|
||||
|
||||
console.log('解析后的数据:', { newItems, totalCount, newItemsLength: newItems.length });
|
||||
|
||||
// 确保 newItems 是数组
|
||||
if (Array.isArray(newItems)) {
|
||||
if (isRefresh) {
|
||||
newsList.value = newItems;
|
||||
console.log('刷新模式:替换列表数据');
|
||||
} else {
|
||||
newsList.value = [...newsList.value, ...newItems];
|
||||
console.log('加载更多:追加数据到列表');
|
||||
}
|
||||
|
||||
total.value = totalCount;
|
||||
console.log(`当前页数据: ${newItems.length}, 总数: ${total.value}, 当前列表长度: ${newsList.value.length}`);
|
||||
|
||||
// 判断是否还有更多数据
|
||||
if (newItems.length < pageSize.value || newsList.value.length >= total.value) {
|
||||
loadMoreStatus.value = 'noMore';
|
||||
console.log('没有更多数据了');
|
||||
} else {
|
||||
loadMoreStatus.value = 'more';
|
||||
page.value++;
|
||||
console.log(`还有更多数据,下一页: ${page.value}`);
|
||||
}
|
||||
} else {
|
||||
console.error('API返回的数据不是数组格式:', newItems);
|
||||
loadMoreStatus.value = 'noMore';
|
||||
}
|
||||
} else {
|
||||
console.error('加载新闻列表失败:', res.message);
|
||||
loadMoreStatus.value = 'noMore';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载新闻列表异常:', e);
|
||||
loadMoreStatus.value = 'noMore';
|
||||
}
|
||||
|
||||
console.log('=== loadNewsList 结束 ===');
|
||||
console.log('最终状态:', {
|
||||
loadMoreStatus: loadMoreStatus.value,
|
||||
page: page.value,
|
||||
listLength: newsList.value.length
|
||||
});
|
||||
};
|
||||
|
||||
const refreshData = async () => {
|
||||
console.log('Refreshing data...');
|
||||
// 重置分页状态
|
||||
page.value = 1;
|
||||
newsList.value = [];
|
||||
loadMoreStatus.value = 'more';
|
||||
|
||||
if(from.value){
|
||||
// 重新加载数据
|
||||
await loadNewsListKePu(true);
|
||||
}else{
|
||||
await loadNewsListIndex(true);
|
||||
}
|
||||
|
||||
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success'
|
||||
});
|
||||
};
|
||||
|
||||
const goToNewsDetail = (item) => {
|
||||
console.log('Go to news detail:', item);
|
||||
let url=encodeURIComponent(docUrl+item.path)
|
||||
navTo({
|
||||
url: `/pages_app/webview/webview?url=${url}`
|
||||
});
|
||||
};
|
||||
|
||||
const formatDate = (dateString) => {
|
||||
if (!dateString) return '';
|
||||
try {
|
||||
// 使用 dayjs 格式化日期
|
||||
return dayjs(dateString).format('YYYY-MM-DD');
|
||||
} catch (error) {
|
||||
console.error('日期格式化失败:', error, dateString);
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.news-list-page {
|
||||
background-color: #f8f8f8;
|
||||
height: 100vh;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.uni-navbar {
|
||||
/* Custom styles for uni-nav-bar if needed */
|
||||
.uni-navbar__content {
|
||||
height: 44px; // Standard navbar height
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
background-color: #ffffff;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
position: sticky;
|
||||
top: calc(var(--status-bar-height) + 44px); // Below navbar
|
||||
z-index: 99;
|
||||
|
||||
.tabs-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tabs-container {
|
||||
display: flex;
|
||||
padding: 0 20rpx;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex-shrink: 0;
|
||||
padding: 10rpx 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
margin-right: 20rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #ff4757;
|
||||
font-weight: bold;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -10rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 60%;
|
||||
height: 4rpx;
|
||||
background-color: #ff4757;
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fixed Banner Container */
|
||||
.banner-container {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
.swipemask{
|
||||
width:100%;
|
||||
z-index:3;
|
||||
box-sizing:border-box;
|
||||
position: absolute;
|
||||
bottom:0;
|
||||
padding:0 20rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
.banner-subtitle {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255,255,255,0.8);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 60%;
|
||||
}
|
||||
|
||||
.dotbox{
|
||||
display:flex;
|
||||
align-items: center;
|
||||
|
||||
.circle{
|
||||
margin:0 4rpx;
|
||||
width:16rpx;
|
||||
height:16rpx;
|
||||
background-color: #eee;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.circle.active{
|
||||
background-color: #8B2316;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.news-scroll-view {
|
||||
position: fixed;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
top:140rpx;
|
||||
height: calc(100vh - 140rpx); // 仅减去导航栏高度
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.news-list {
|
||||
padding: 20rpx;
|
||||
background-color: #f8f8f8;
|
||||
|
||||
.news-item {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
overflow: hidden; // Ensure content respects border-radius
|
||||
|
||||
.item-image-container {
|
||||
flex-shrink: 0;
|
||||
width: 200rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
margin-right: 20rpx;
|
||||
position: relative;
|
||||
background-color: #f0f0f0; // Placeholder background
|
||||
|
||||
.item-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.important-tag {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #ff4757;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border-bottom-right-radius: 8rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: normal; // Removed bold as per previous request
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2; // Fixed two-line height
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.item-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
|
||||
.item-date {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.item-stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
text {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.load-more-status {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.more {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.no-more {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
306
pages_app/searchVideo/searchVideo.vue
Normal file
306
pages_app/searchVideo/searchVideo.vue
Normal file
@ -0,0 +1,306 @@
|
||||
<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'
|
||||
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?uuid=${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>
|
||||
|
||||
@ -263,7 +263,7 @@
|
||||
import delImg from "@/static/delete_paper.png"
|
||||
import api from '@/api/api.js'
|
||||
import docUrl from "@/utils/docUrl.js"
|
||||
import navTo from '../../utils/navTo';
|
||||
import navTo from '@/utils/navTo.js';
|
||||
const total=ref(0);
|
||||
const tab=ref('zhinan')
|
||||
// 响应式数据
|
||||
@ -319,7 +319,7 @@ import navTo from '../../utils/navTo';
|
||||
}
|
||||
|
||||
navTo({
|
||||
url:'/pages_app/zhinanList/zhinanList?keywords='+encodeURIComponent(keywords.value)
|
||||
url:'/pages_app/hot/hot?keywords='+encodeURIComponent(keywords.value)
|
||||
})
|
||||
|
||||
}
|
||||
@ -388,9 +388,8 @@ import navTo from '../../utils/navTo';
|
||||
|
||||
// 进入指南分类
|
||||
const enterCategory = (item) => {
|
||||
console.log('进入分类:', item.category);
|
||||
uni.navigateTo({
|
||||
url: `/pages/guidelineList/guidelineList?category=${item.category}&title=${item.title}`
|
||||
navTo({
|
||||
url: `/pages_app/zhinanList/zhinanList?typeUuid=${item.uuid}&title=${item.name}`
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
<view class="zhinan-list-page">
|
||||
<!-- 头部导航栏 -->
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
title="诊疗指南"
|
||||
left-icon="left"
|
||||
:title="title"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
@ -12,12 +12,26 @@
|
||||
backgroundColor="#eeeeee"
|
||||
>
|
||||
<template v-slot:right>
|
||||
<view class="nav-right" @click="testLoadMore">
|
||||
<text style="font-size: 24rpx; color: #8B2316;">测试加载</text>
|
||||
<view class="nav-right" @click="goGot">
|
||||
<up-image :src="hotImg" width="40rpx" height="40rpx" ></up-image>
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
<!-- 固定搜索栏 -->
|
||||
<view class="search-container-fixed filter-bar">
|
||||
<view class="search-box" @click="goToSearch">
|
||||
<uni-icons type="search" size="16" color="#999"></uni-icons>
|
||||
<text class="search-text">搜索</text>
|
||||
</view>
|
||||
|
||||
<view class="divider"></view>
|
||||
<view class="current-sort" @click="toggleInnerSort">
|
||||
<text class="sort-text">{{ innerSortTitle }}</text>
|
||||
<view class="imgbox">
|
||||
<up-image :src="upImg" width="26rpx" height="26rpx" ></up-image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 使用scroll-view实现列表 -->
|
||||
<scroll-view
|
||||
class="guidelines-scroll-view"
|
||||
@ -34,6 +48,7 @@
|
||||
class="guideline-item"
|
||||
v-for="(item, index) in guidelinesList"
|
||||
:key="item.uuid || index"
|
||||
@click="viewGuideline(item)"
|
||||
>
|
||||
<!-- 指南信息 -->
|
||||
<view class="item-content">
|
||||
@ -43,19 +58,18 @@
|
||||
<!-- 操作按钮 -->
|
||||
<view class="item-action">
|
||||
<view
|
||||
v-if="item.can_download"
|
||||
class="download-btn"
|
||||
@click="downloadGuideline(item)"
|
||||
@click.stop="viewGuideline(item)"
|
||||
>
|
||||
<up-icon name="download" color="#8D2316" size="28"></up-icon>
|
||||
</view>
|
||||
<view
|
||||
<!-- <view
|
||||
v-else
|
||||
class="view-btn"
|
||||
@click="viewGuideline(item)"
|
||||
@click.stop="viewGuideline(item)"
|
||||
>
|
||||
查看
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -83,13 +97,32 @@
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 组内排序弹窗 -->
|
||||
<view v-if="showInnerSort" class="popup-panel">
|
||||
<view class="popup-item" :class="{ active:sort==1 }" @click.stop="chooseInnerSort(1)">
|
||||
<text class="item-text">下载量</text>
|
||||
<uni-icons v-if="sort==1" type="checkmarkempty" color="#8B2316" size="22"></uni-icons>
|
||||
</view>
|
||||
<view class="popup-divider"></view>
|
||||
<view class="popup-item" :class="{ active:sort==2 }" @click.stop="chooseInnerSort(2)">
|
||||
<text class="item-text">上传时间</text>
|
||||
<uni-icons v-if="sort==2" type="checkmarkempty" color="#8B2316" size="22"></uni-icons>
|
||||
</view>
|
||||
<view class="popup-divider"></view>
|
||||
<view class="popup-item" :class="{ active:sort==3 }" @click.stop="chooseInnerSort(3)">
|
||||
<text class="item-text">标题</text>
|
||||
<uni-icons v-if="sort==3" type="checkmarkempty" color="#8B2316" size="22"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted} from 'vue'
|
||||
import api from '@/api/api.js'
|
||||
import { onShow,onLoad } from "@dcloudio/uni-app";
|
||||
|
||||
import docUrl from "@/utils/docUrl.js"
|
||||
import navTo from "@/utils/navTo.js"
|
||||
import hotImg from "@/static/hot_booklist.png"
|
||||
// 响应式数据
|
||||
const guidelinesList = ref([])
|
||||
const isLoading = ref(false)
|
||||
@ -98,14 +131,48 @@ const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const isRefreshing = ref(false)
|
||||
const keywords=ref('');
|
||||
import upImg from "@/static/triangle_green_theme.png"
|
||||
import downImg from "@/static/triangle_normal.png"
|
||||
const loadMoreStatus = ref('more') // 'loading', 'more', 'noMore'
|
||||
|
||||
const typeUuid=ref('');
|
||||
const title=ref('');
|
||||
const sort=ref(2);
|
||||
const showInnerSort=ref(false);
|
||||
const innerSortTitle=ref('上传时间');
|
||||
const chooseInnerSort=(index)=>{
|
||||
sort.value=index;
|
||||
if(index==1){
|
||||
innerSortTitle.value='下载量';
|
||||
}else if(index==2){
|
||||
innerSortTitle.value='上传时间';
|
||||
}else if(index==3){
|
||||
innerSortTitle.value='标题';
|
||||
}
|
||||
showInnerSort.value=false;
|
||||
loadGuidelinesList(true);
|
||||
}
|
||||
onLoad((options)=>{
|
||||
console.log(options)
|
||||
keywords.value=decodeURIComponent(options.keywords);
|
||||
console.log(keywords.value);
|
||||
if(options.typeUuid){
|
||||
typeUuid.value=options.typeUuid;
|
||||
}
|
||||
if(options.title){
|
||||
title.value=options.title;
|
||||
}
|
||||
if(options.keywords){
|
||||
keywords.value=decodeURIComponent(options.keywords);
|
||||
title.value=decodeURIComponent(options.title);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const goGot=()=>{
|
||||
navTo({
|
||||
url:'/pages_app/hot/hot?from=hot&typeUuid='+typeUuid.value
|
||||
})
|
||||
}
|
||||
const toggleInnerSort=()=>{
|
||||
showInnerSort.value=!showInnerSort.value;
|
||||
}
|
||||
onShow(() => {
|
||||
// 页面显示时,如果列表为空则加载数据
|
||||
if (guidelinesList.value.length === 0) {
|
||||
@ -113,6 +180,16 @@ onShow(() => {
|
||||
}
|
||||
})
|
||||
|
||||
// 跳转到搜索页
|
||||
const goToSearch = () => {
|
||||
const q = keywords.value ? encodeURIComponent(keywords.value) : ''
|
||||
const t = title.value ? encodeURIComponent(title.value) : ''
|
||||
const type = typeUuid.value ? `&typeUuid=${encodeURIComponent(typeUuid.value)}` : ''
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`
|
||||
})
|
||||
}
|
||||
|
||||
// scroll-view 下拉刷新
|
||||
const onRefresh = async () => {
|
||||
console.log('scroll-view 下拉刷新触发');
|
||||
@ -183,6 +260,7 @@ const loadGuidelinesList = async (isRefresh = false) => {
|
||||
pageSize: pageSize.value,
|
||||
type: 1, // 诊疗指南类型
|
||||
sort:2,
|
||||
typeUuid:typeUuid.value,
|
||||
keywords:keywords.value
|
||||
}
|
||||
|
||||
@ -289,13 +367,66 @@ const downloadGuideline = (item) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 查看指南
|
||||
// 查看指南(支持常用文档直链:pdf/doc/docx/xls/xlsx/ppt/pptx/txt)
|
||||
const viewGuideline = (item) => {
|
||||
console.log('查看指南:', item)
|
||||
// 跳转到指南详情页或预览页
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/zhinanDetail/zhinanDetail?uuid=${item.uuid}&title=${encodeURIComponent(item.title)}`
|
||||
})
|
||||
const url = docUrl+item.path
|
||||
if (url) {
|
||||
const isPDF = /\.(pdf)(\?|$)/i.test(url)
|
||||
const isOffice = /\.(docx?|xlsx?|pptx?)(\?|$)/i.test(url)
|
||||
const isText = /\.(txt)(\?|$)/i.test(url)
|
||||
|
||||
// H5 端
|
||||
// #ifdef H5
|
||||
if (isPDF) {
|
||||
try { window.open(url, '_blank') } catch (e) {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
return
|
||||
}
|
||||
if (isOffice) {
|
||||
const officeUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`
|
||||
try { window.open(officeUrl, '_blank') } catch (e) {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(officeUrl)}` })
|
||||
}
|
||||
return
|
||||
}
|
||||
if (isText) {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
return
|
||||
}
|
||||
// 其他格式统一用 webview 打开
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
return
|
||||
// #endif
|
||||
|
||||
// 非 H5 端:下载后尝试用 openDocument,失败回退 webview
|
||||
// #ifndef H5
|
||||
uni.showToast({ title: '正在打开...', icon: 'none' })
|
||||
uni.downloadFile({
|
||||
url,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200 && res.tempFilePath) {
|
||||
uni.openDocument({
|
||||
filePath: res.tempFilePath,
|
||||
showMenu: true,
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
||||
}
|
||||
})
|
||||
return
|
||||
// #endif
|
||||
}
|
||||
// 无直链,回退到详情页
|
||||
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
@ -350,16 +481,126 @@ $text-light: #999;
|
||||
$border-color: #e0e0e0;
|
||||
$bg-color: #f6f6f6;
|
||||
$white: #ffffff;
|
||||
.imgbox{
|
||||
width: 32rpx;
|
||||
margin-top: -10rpx;
|
||||
}
|
||||
.popup-panel {
|
||||
position: fixed;
|
||||
top: 256rpx; /* 紧贴筛选栏 */
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
z-index: 100;
|
||||
box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.popup-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 28rpx 30rpx;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-divider {
|
||||
height: 2rpx;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
.popup-item.active .item-text {
|
||||
color: #8B2316;
|
||||
}
|
||||
.current-sort {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
|
||||
.sort-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sort-icon.up {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8rpx solid transparent;
|
||||
border-right: 8rpx solid transparent;
|
||||
border-bottom: 12rpx solid #999;
|
||||
|
||||
&.active {
|
||||
border-bottom-color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zhinan-list-page {
|
||||
background-color: $bg-color;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.guidelines-scroll-view {
|
||||
position: fixed;
|
||||
top: 242rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
height: calc(100vh - 140rpx);
|
||||
background-color: $bg-color;
|
||||
}
|
||||
// 固定搜索容器
|
||||
.search-container-fixed {
|
||||
position: fixed;
|
||||
top: 140rpx; // 导航栏高度
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 90;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 30rpx 30rpx;
|
||||
background-color: $white;
|
||||
gap: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
// 筛选栏
|
||||
.filter-bar {
|
||||
background-color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 2px solid #eee;
|
||||
|
||||
.search-box {
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
|
||||
.search-text {
|
||||
font-size: 14px;
|
||||
color:#999;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 1px;
|
||||
height: 16px;
|
||||
background-color: #999;
|
||||
margin: 0 60rpx;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex:1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 3px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
// 指南列表
|
||||
.guidelines-list {
|
||||
|
||||
BIN
static/hot_booklist.png
Normal file
BIN
static/hot_booklist.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
Loading…
x
Reference in New Issue
Block a user