9.1
This commit is contained in:
parent
7270482bd9
commit
82e0a5c10d
64
api/api.js
64
api/api.js
@ -81,13 +81,6 @@ const api = {
|
|||||||
return request('/expertAPI/my', data, 'post', false);
|
return request('/expertAPI/my', data, 'post', false);
|
||||||
},
|
},
|
||||||
|
|
||||||
getVideoList(data) {
|
|
||||||
return request('/video/list', data, 'get', true);
|
|
||||||
},
|
|
||||||
getVideoDetail(data) {
|
|
||||||
return request('/video/detail', data, 'get', true);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 新闻详情
|
// 新闻详情
|
||||||
getNewsDetail(data) {
|
getNewsDetail(data) {
|
||||||
return request('/expertAPI/newsDetail', data, 'post', false);
|
return request('/expertAPI/newsDetail', data, 'post', false);
|
||||||
@ -160,6 +153,63 @@ const api = {
|
|||||||
return request('/expertAPI/addBonusPointsN', data, 'post', false);
|
return request('/expertAPI/addBonusPointsN', data, 'post', false);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//视频顶部轮播
|
||||||
|
videoRoll(data){
|
||||||
|
return request('/expertAPI/videoRoll', data, 'post', false);
|
||||||
|
},
|
||||||
|
//视频标签
|
||||||
|
videoTagList(data){
|
||||||
|
return request('/expertAPI/videoTagList', data, 'post', false);
|
||||||
|
},
|
||||||
|
//视频首页
|
||||||
|
videoIndexN(data){
|
||||||
|
return request('/expertAPI/videoIndexN', data, 'post', false);
|
||||||
|
},
|
||||||
|
//视频类型
|
||||||
|
expertVideoTypeList(data){
|
||||||
|
return request('/expertAPI/expertVideoTypeList', data, 'post', false);
|
||||||
|
},
|
||||||
|
//视频搜索
|
||||||
|
videoByKeyWordsNew(data){
|
||||||
|
return request('/expertAPI/videoByKeyWordsNew', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 指南杂志 - 治疗指南列表
|
||||||
|
searchLibraryU(data){
|
||||||
|
return request('/expertAPI/searchLibraryU', data, 'post', false);
|
||||||
|
},
|
||||||
|
// 指南杂志 - 治疗指南最火TOP10
|
||||||
|
top10ByType(data){
|
||||||
|
return request('/expertAPI/top10ByType', data, 'post', false);
|
||||||
|
},
|
||||||
|
// 指南杂志 - 治疗指南分类
|
||||||
|
guideType(data){
|
||||||
|
return request('/expertAPI/guideType', data, 'post', false);
|
||||||
|
},
|
||||||
|
//指南标签
|
||||||
|
guideTag(data){
|
||||||
|
return request('/expertApp/tagList', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 肝胆新闻相关API
|
||||||
|
// 顶部轮播
|
||||||
|
newsRollNew(data){
|
||||||
|
return request('/expertAPI/newsRollNew', data, 'post', false);
|
||||||
|
},
|
||||||
|
// 新闻列表
|
||||||
|
defaultNewsListNew(data){
|
||||||
|
return request('/expertAPI/defaultNewsListNew', data, 'post', false);
|
||||||
|
},
|
||||||
|
// 根据标签查询新闻列表
|
||||||
|
newsListNew(data){
|
||||||
|
return request('/expertAPI/newsListNew', data, 'post', false);
|
||||||
|
},
|
||||||
|
// 新闻标签列表
|
||||||
|
newsTagList(data){
|
||||||
|
return request('/expertAPI/newsTagList', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default api
|
export default api
|
||||||
@ -2,15 +2,14 @@
|
|||||||
"name": "uniapp",
|
"name": "uniapp",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {},
|
||||||
|
|
||||||
},
|
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "",
|
"description": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
|
"dayjs": "^1.11.18",
|
||||||
"js-base64": "^3.7.8",
|
"js-base64": "^3.7.8",
|
||||||
"js-md5": "^0.8.3",
|
"js-md5": "^0.8.3",
|
||||||
"uview-plus": "^3.4.73"
|
"uview-plus": "^3.4.73"
|
||||||
|
|||||||
40
pages.json
40
pages.json
@ -511,6 +511,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "zhinanList/zhinanList",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"navigationBarTitleText": "uni-app分页",
|
||||||
|
"app": {
|
||||||
|
"bounce": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "newsList/newsList",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"navigationBarTitleText": "uni-app分页",
|
||||||
|
"app": {
|
||||||
|
"bounce": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "personInfo/personInfo",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"navigationBarTitleText": "uni-app分页",
|
||||||
|
"app": {
|
||||||
|
"bounce": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pptDetail/pptDetail",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"navigationBarTitleText": "uni-app分页",
|
||||||
|
"app": {
|
||||||
|
"bounce": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "patientMsg/patientMsg",
|
"path": "patientMsg/patientMsg",
|
||||||
"style": {
|
"style": {
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
<!-- Fixed Banner Swiper -->
|
<!-- Fixed Banner Swiper -->
|
||||||
<view class="banner-container">
|
<view class="banner-container">
|
||||||
<view class="swipemask">
|
<view class="swipemask">
|
||||||
<view class="banner-subtitle">111111111</view>
|
<view class="banner-subtitle">{{bannerList[currentBannerIndex].summary}}</view>
|
||||||
<view class="dotbox">
|
<view class="dotbox">
|
||||||
<view class="circle" :class="{active:currentBannerIndex==index} "v-for="(banner, index) in bannerList"
|
<view class="circle" :class="{active:currentBannerIndex==index} "v-for="(banner, index) in bannerList"
|
||||||
:key="banner.id"></view>
|
:key="banner.id"></view>
|
||||||
@ -39,19 +39,12 @@
|
|||||||
>
|
>
|
||||||
<view class="banner-item">
|
<view class="banner-item">
|
||||||
<image
|
<image
|
||||||
|
style="width:100%;"
|
||||||
class="banner-image"
|
class="banner-image"
|
||||||
:src="banner.thumbnail || '/static/big_background_my.png'"
|
:src="docUrl +banner.headImg"
|
||||||
mode="aspectFill"
|
mode="widthFix"
|
||||||
></image>
|
></image>
|
||||||
<view class="banner-content">
|
|
||||||
<view class="doctor-avatar" v-if="banner.doctorAvatar">
|
|
||||||
<image :src="banner.doctorAvatar" mode="aspectFill"></image>
|
|
||||||
</view>
|
|
||||||
<view class="banner-info">
|
|
||||||
<view class="banner-title">{{banner.title}}</view>
|
|
||||||
<view class="banner-subtitle">{{banner.subtitle || '专业医学视频教育平台'}}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
</swiper>
|
</swiper>
|
||||||
@ -59,7 +52,7 @@
|
|||||||
|
|
||||||
<scroll-view class="news-list" scroll-y="true">
|
<scroll-view class="news-list" scroll-y="true">
|
||||||
<!-- 肝胆新闻 -->
|
<!-- 肝胆新闻 -->
|
||||||
<view class="news-item" @click="goToNews('hepatoBiliaryNews')">
|
<view class="news-item" @click="goToNews('news')">
|
||||||
<view class="news-icon blue">
|
<view class="news-icon blue">
|
||||||
<uni-icons type="paperplane" size="24" color="#fff"></uni-icons>
|
<uni-icons type="paperplane" size="24" color="#fff"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
@ -73,7 +66,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 互动圈 -->
|
<!-- 互动圈 -->
|
||||||
<view class="news-item" @click="goToNews('interactionCircle')">
|
<!-- <view class="news-item" @click="goToNews('interactionCircle')">
|
||||||
<view class="news-icon purple">
|
<view class="news-icon purple">
|
||||||
<uni-icons type="redo" size="24" color="#fff"></uni-icons>
|
<uni-icons type="redo" size="24" color="#fff"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
@ -84,10 +77,10 @@
|
|||||||
<view class="news-arrow">
|
<view class="news-arrow">
|
||||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view> -->
|
||||||
|
|
||||||
<!-- 科研项目 -->
|
<!-- 科研项目 -->
|
||||||
<view class="news-item" @click="goToNews('researchProjects')">
|
<!-- <view class="news-item" @click="goToNews('researchProjects')">
|
||||||
<view class="news-icon orange">
|
<view class="news-icon orange">
|
||||||
<uni-icons type="star" size="24" color="#fff"></uni-icons>
|
<uni-icons type="star" size="24" color="#fff"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
@ -99,9 +92,9 @@
|
|||||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
-->
|
||||||
<!-- 临床招募 -->
|
<!-- 临床招募 -->
|
||||||
<view class="news-item" @click="goToNews('clinicalRecruitment')">
|
<!-- <view class="news-item" @click="goToNews('clinicalRecruitment')">
|
||||||
<view class="news-icon green">
|
<view class="news-icon green">
|
||||||
<uni-icons type="personadd" size="24" color="#fff"></uni-icons>
|
<uni-icons type="personadd" size="24" color="#fff"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
@ -112,7 +105,7 @@
|
|||||||
<view class="news-arrow">
|
<view class="news-arrow">
|
||||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view> -->
|
||||||
|
|
||||||
<!-- 肝胆会议 -->
|
<!-- 肝胆会议 -->
|
||||||
<view class="news-item" @click="goToCourse('hepatoBiliaryConference')">
|
<view class="news-item" @click="goToCourse('hepatoBiliaryConference')">
|
||||||
@ -129,7 +122,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 肝胆活动 -->
|
<!-- 肝胆活动 -->
|
||||||
<view class="news-item" @click="goToNews('hepatoBiliaryActivities')">
|
<!-- <view class="news-item" @click="goToNews('hepatoBiliaryActivities')">
|
||||||
<view class="news-icon pink">
|
<view class="news-icon pink">
|
||||||
<uni-icons type="gift" size="24" color="#fff"></uni-icons>
|
<uni-icons type="gift" size="24" color="#fff"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
@ -140,18 +133,48 @@
|
|||||||
<view class="news-arrow">
|
<view class="news-arrow">
|
||||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view> -->
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
|
import api from '@/api/api.js';
|
||||||
|
import docUrl from "@/utils/docUrl.js";
|
||||||
|
import navTo from '../../utils/navTo';
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadNewsBanner();
|
||||||
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
loadNewsBanner();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载新闻轮播数据
|
||||||
|
const loadNewsBanner = async () => {
|
||||||
|
try {
|
||||||
|
console.log(api)
|
||||||
|
const res = await api.newsRollNew({});
|
||||||
|
console.log('新闻轮播响应:', res);
|
||||||
|
|
||||||
|
if(res && res.code === 200) {
|
||||||
|
bannerList.value = res.data || [];
|
||||||
|
console.log('获取到轮播数据:', bannerList.value);
|
||||||
|
} else {
|
||||||
|
console.error('加载新闻轮播失败:', res.message);
|
||||||
|
// 如果接口失败,使用模拟数据作为备选
|
||||||
bannerList.value = getMockBannerData();
|
bannerList.value = getMockBannerData();
|
||||||
})
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error('加载新闻轮播异常:', e);
|
||||||
|
// 如果接口异常,使用模拟数据作为备选
|
||||||
|
bannerList.value = getMockBannerData();
|
||||||
|
}
|
||||||
|
};
|
||||||
// Banner相关数据
|
// Banner相关数据
|
||||||
const bannerList = ref([]);
|
const bannerList = ref([]);
|
||||||
const currentBannerIndex = ref(0);
|
const currentBannerIndex = ref(0);
|
||||||
@ -204,21 +227,17 @@
|
|||||||
|
|
||||||
// 新闻相关方法
|
// 新闻相关方法
|
||||||
const goToNews = (type) => {
|
const goToNews = (type) => {
|
||||||
console.log('跳转到新闻类型:', type);
|
if(type=="news"){
|
||||||
// 这里可以根据不同的新闻类型跳转到相应的页面
|
navTo({
|
||||||
uni.showToast({
|
url:'/pages_app/newsList/newsList'
|
||||||
title: '功能开发中',
|
})
|
||||||
icon: 'none'
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToCourse = (type) => {
|
const goToCourse = (type) => {
|
||||||
console.log('跳转到课程类型:', type);
|
navTo({
|
||||||
// 这里可以根据不同的课程类型跳转到相应的页面
|
url:'/pages/live/live'
|
||||||
uni.showToast({
|
})
|
||||||
title: '功能开发中',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -271,6 +290,10 @@
|
|||||||
.banner-subtitle {
|
.banner-subtitle {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: rgba(255,255,255,0.8);
|
color: rgba(255,255,255,0.8);
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 60%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dotbox{
|
.dotbox{
|
||||||
|
|||||||
718
pages_app/newsList/newsList.vue
Normal file
718
pages_app/newsList/newsList.vue
Normal file
@ -0,0 +1,718 @@
|
|||||||
|
<template>
|
||||||
|
<view class="news-list-page">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="肝胆新闻"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
fixed
|
||||||
|
color="#8B2316"
|
||||||
|
height="140rpx"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
></uni-nav-bar>
|
||||||
|
|
||||||
|
<!-- 导航标签 -->
|
||||||
|
<view class="nav-tabs">
|
||||||
|
<scroll-view class="tabs-scroll" scroll-x="true" :show-scrollbar="false">
|
||||||
|
<view class="tabs-container">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === index }"
|
||||||
|
v-for="(tab, index) in tabs"
|
||||||
|
:key="index"
|
||||||
|
@click="changeTab(index)"
|
||||||
|
>
|
||||||
|
<text>{{ tab.NAME }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 新闻列表 -->
|
||||||
|
<scroll-view
|
||||||
|
class="news-scroll-view"
|
||||||
|
scroll-y="true"
|
||||||
|
:refresher-enabled="true"
|
||||||
|
:refresher-triggered="isRefreshing"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
@scrolltolower="onScrollToLower"
|
||||||
|
:show-scrollbar="false"
|
||||||
|
>
|
||||||
|
<!-- 顶部轮播 -->
|
||||||
|
<view class="banner-container">
|
||||||
|
<view class="swipemask">
|
||||||
|
<view class="banner-subtitle" v-if="bannerList.length>0">{{bannerList[currentBannerIndex].summary}}</view>
|
||||||
|
<view class="dotbox">
|
||||||
|
<view class="circle" :class="{active:currentBannerIndex==index} "v-for="(banner, index) in bannerList"
|
||||||
|
:key="banner.id"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<swiper
|
||||||
|
class="banner-swiper"
|
||||||
|
:indicator-dots="false"
|
||||||
|
:autoplay="true"
|
||||||
|
:interval="5000"
|
||||||
|
:duration="300"
|
||||||
|
indicator-color="rgba(255,255,255,0.4)"
|
||||||
|
indicator-active-color="#fff"
|
||||||
|
circular
|
||||||
|
@change="onSwiperChange"
|
||||||
|
>
|
||||||
|
|
||||||
|
<swiper-item
|
||||||
|
v-for="(banner, index) in bannerList"
|
||||||
|
:key="banner.id"
|
||||||
|
@click="playBannerVideo(banner)"
|
||||||
|
>
|
||||||
|
<view class="banner-item">
|
||||||
|
<image
|
||||||
|
style="width:100%;"
|
||||||
|
class="banner-image"
|
||||||
|
:src="docUrl +banner.headImg"
|
||||||
|
mode="widthFix"
|
||||||
|
></image>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
</view>
|
||||||
|
<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"
|
||||||
|
mode="aspectFill"
|
||||||
|
></image>
|
||||||
|
<view class="important-tag" v-if="news.isImportant">重要通知</view>
|
||||||
|
</view>
|
||||||
|
<view class="item-content">
|
||||||
|
<view class="item-title">{{ news.title }}</view>
|
||||||
|
<view class="item-meta">
|
||||||
|
<text class="item-date">{{ formatDate(news.createDate) }}</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 || 0 }}</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 } from '@dcloudio/uni-app';
|
||||||
|
import api from '@/api/api.js';
|
||||||
|
import docUrl from '@/utils/docUrl.js';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
// 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 loadMoreText = reactive({
|
||||||
|
contentdown: '上拉显示更多',
|
||||||
|
contentrefresh: '正在加载...',
|
||||||
|
contentnomore: '没有更多数据了'
|
||||||
|
});
|
||||||
|
const newsTags = ref([]); // 新闻标签列表
|
||||||
|
onShow(() => {
|
||||||
|
loadNewsBanner();
|
||||||
|
loadNewsTags(); // 加载新闻标签列表
|
||||||
|
if(activeTab.value<0){
|
||||||
|
// 重新加载数据
|
||||||
|
loadNewsListIndex();
|
||||||
|
}else{
|
||||||
|
loadNewsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
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(activeTab.value<0){
|
||||||
|
// 重新加载数据
|
||||||
|
loadNewsListIndex();
|
||||||
|
}else{
|
||||||
|
loadNewsList();
|
||||||
|
}
|
||||||
|
} 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 changeTab = (index) => {
|
||||||
|
activeTab.value = index;
|
||||||
|
|
||||||
|
// 确保 tabs 数组存在且有数据
|
||||||
|
if (tabs.value && tabs.value.length > 0 && tabs.value[index]) {
|
||||||
|
newstagid.value = tabs.value[index].ID ;
|
||||||
|
} else {
|
||||||
|
newstagid.value = '';
|
||||||
|
console.warn('标签数据不完整,无法设置newstagid');
|
||||||
|
}
|
||||||
|
|
||||||
|
page.value = 1; // Reset page when changing tab
|
||||||
|
newsList.value = []; // Clear existing list
|
||||||
|
loadNewsList(true); // Load new data for the selected tab
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载新闻轮播数据
|
||||||
|
const loadNewsBanner = async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.newsRollNew({});
|
||||||
|
console.log('新闻轮播响应:', res);
|
||||||
|
|
||||||
|
if (res && res.code === 200) {
|
||||||
|
bannerList.value = res.data || [];
|
||||||
|
console.log('获取到轮播数据:', bannerList.value);
|
||||||
|
} else {
|
||||||
|
console.error('加载新闻轮播失败:', res.message);
|
||||||
|
// Fallback to mock data if API fails
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('加载新闻轮播异常:', e);
|
||||||
|
// Fallback to mock data if API fails
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载新闻标签列表
|
||||||
|
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 loadNewsList = 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.newsListNew({
|
||||||
|
page: page.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
newstagid: newstagid.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(activeTab.value<0){
|
||||||
|
// 重新加载数据
|
||||||
|
await loadNewsListIndex(true);
|
||||||
|
}else{
|
||||||
|
await loadNewsList(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '刷新成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToNewsDetail = (item) => {
|
||||||
|
// Implement navigation to news detail page
|
||||||
|
console.log('Go to news detail:', item);
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages_app/newsDetail/newsDetail?id=${item.uuid || item.id}`
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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:200rpx;
|
||||||
|
height: calc(100vh - 200rpx); // 减去导航栏、标签栏和banner的高度
|
||||||
|
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>
|
||||||
280
pages_app/personInfo/personInfo.vue
Normal file
280
pages_app/personInfo/personInfo.vue
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
<template>
|
||||||
|
<view class="person-page">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="个人资料"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
fixed
|
||||||
|
color="#8B2316"
|
||||||
|
height="140rpx"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
></uni-nav-bar>
|
||||||
|
|
||||||
|
<scroll-view class="content" scroll-y>
|
||||||
|
<!-- 基本资料分组 -->
|
||||||
|
<view class="section-header">基本资料</view>
|
||||||
|
|
||||||
|
<!-- 头像 -->
|
||||||
|
<view class="row" @click="onChooseAvatar">
|
||||||
|
<view class="label"><text>头像</text><text class="req">*</text></view>
|
||||||
|
<view class="value value-avatar">
|
||||||
|
<image :src="form.avatar" mode="aspectFill" class="avatar" />
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 姓名 -->
|
||||||
|
<view class="row">
|
||||||
|
<view class="label"><text>姓名</text><text class="req">*</text></view>
|
||||||
|
<view class="value">{{ form.name }}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 性别 -->
|
||||||
|
<view class="row" @click="onPickGender">
|
||||||
|
<view class="label"><text>性别</text><text class="req">*</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.gender }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 出生日期 -->
|
||||||
|
<view class="row" @click="onPickBirthday">
|
||||||
|
<view class="label"><text>出生日期</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.birthday || '' }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 手机号码 -->
|
||||||
|
<view class="row" @click="onEditPhone">
|
||||||
|
<view class="label"><text>手机号</text><text class="req">*</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.mobile }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 邮箱 -->
|
||||||
|
<view class="row" @click="onEditEmail">
|
||||||
|
<view class="label"><text>邮箱</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.email || '' }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 专业资料分组 -->
|
||||||
|
<view class="section-header">专业资料</view>
|
||||||
|
|
||||||
|
<!-- 医院 -->
|
||||||
|
<view class="row" @click="onPickHospital">
|
||||||
|
<view class="label"><text>医院</text><text class="req">*</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.hospital }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 科室 -->
|
||||||
|
<view class="row" @click="onPickDept">
|
||||||
|
<view class="label"><text>科室</text><text class="req">*</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.department }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 科室电话 -->
|
||||||
|
<view class="row" @click="onEditDeptPhone">
|
||||||
|
<view class="label"><text>科室电话</text><text class="req">*</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.departmentPhone }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 职称 -->
|
||||||
|
<view class="row" @click="onPickTitle">
|
||||||
|
<view class="label"><text>职称</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.title }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 执业医师证编号 -->
|
||||||
|
<view class="row" @click="onEditLicenseNo">
|
||||||
|
<view class="label"><text>执业医师证编号</text><text class="req">*</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.licenseNo }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 执业医师证照片/胸牌 -->
|
||||||
|
<view class="row" @click="onChooseLicenseImg">
|
||||||
|
<view class="label"><text>执业医师证图片或胸牌</text><text class="req">*</text></view>
|
||||||
|
<view class="value value-license">
|
||||||
|
<image :src="form.licenseImg" mode="aspectFill" class="license-thumb" />
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 专长 -->
|
||||||
|
<view class="row" @click="onEditSpecialty">
|
||||||
|
<view class="label"><text>专长</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<text>{{ form.specialty }}</text>
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 个人简介 -->
|
||||||
|
<view class="row" @click="onEditIntro">
|
||||||
|
<view class="label"><text>个人简介</text></view>
|
||||||
|
<view class="value with-arrow">
|
||||||
|
<uni-icons type="right" size="18" color="#bbb" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
avatar: '/static/big_background_my.png',
|
||||||
|
name: '邱建东',
|
||||||
|
gender: '男',
|
||||||
|
birthday: '',
|
||||||
|
mobile: '17600668628',
|
||||||
|
email: '',
|
||||||
|
hospital: '北京博爱医院',
|
||||||
|
department: '肝病科',
|
||||||
|
departmentPhone: '1234567890',
|
||||||
|
title: '主任中医师',
|
||||||
|
licenseNo: '12345678',
|
||||||
|
licenseImg: '/static/big_background_my.png',
|
||||||
|
specialty: '肝炎、肝硬化'
|
||||||
|
});
|
||||||
|
|
||||||
|
const goBack = () => uni.navigateBack();
|
||||||
|
|
||||||
|
// 通用打开裁剪器
|
||||||
|
const openCropper = (callback, opts = {}) => {
|
||||||
|
const { destWidth = 600, rectWidth = 300, fileType = 'jpg' } = opts;
|
||||||
|
const url = `/uni_modules/uview-plus/components/u-avatar-cropper/u-avatar-cropper?destWidth=${destWidth}&rectWidth=${rectWidth}&fileType=${fileType}`;
|
||||||
|
uni.navigateTo({
|
||||||
|
url,
|
||||||
|
success: (res) => {
|
||||||
|
res.eventChannel.on('uAvatarCropper', (path) => {
|
||||||
|
if (typeof callback === 'function') callback(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChooseAvatar = () => {
|
||||||
|
openCropper((path) => {
|
||||||
|
form.value.avatar = path;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChooseLicenseImg = () => {
|
||||||
|
openCropper((path) => {
|
||||||
|
form.value.licenseImg = path;
|
||||||
|
}, { destWidth: 1000, rectWidth: 500 });
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPickGender = () => {};
|
||||||
|
const onPickBirthday = () => {};
|
||||||
|
const onEditPhone = () => {};
|
||||||
|
const onEditEmail = () => {};
|
||||||
|
const onPickHospital = () => {};
|
||||||
|
const onPickDept = () => {};
|
||||||
|
const onEditDeptPhone = () => {};
|
||||||
|
const onPickTitle = () => {};
|
||||||
|
const onEditLicenseNo = () => {};
|
||||||
|
const onEditSpecialty = () => {};
|
||||||
|
const onEditIntro = () => {};
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
// 可在此处拉取并回填个人资料
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.person-page {
|
||||||
|
background-color: #ffffff;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
background-color: #d9d9d9;
|
||||||
|
color: #8B2316;
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding: 18rpx 24rpx;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 28rpx 24rpx;
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
.req {
|
||||||
|
color: #e44d3a;
|
||||||
|
margin-left: 8rpx;
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #666;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.with-arrow text {
|
||||||
|
margin-right: 14rpx;
|
||||||
|
}
|
||||||
|
.value-avatar {
|
||||||
|
gap: 14rpx;
|
||||||
|
}
|
||||||
|
.avatar {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.value-license {
|
||||||
|
gap: 14rpx;
|
||||||
|
}
|
||||||
|
.license-thumb {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<!-- 排序和筛选栏 -->
|
<!-- 排序和筛选栏 -->
|
||||||
<view class="filter-bar">
|
<view class="filter-bar">
|
||||||
<view class="filter-item" @click="toggleSort">
|
<view class="filter-item" @click="toggleSort">
|
||||||
<text class="filter-text">最新</text>
|
<text class="filter-text">{{sort==2?'最新':'最热'}}</text>
|
||||||
<view class="newbox">
|
<view class="newbox">
|
||||||
<up-image :src="upImg" width="20rpx" height="26rpx" ></up-image>
|
<up-image :src="upImg" width="20rpx" height="26rpx" ></up-image>
|
||||||
</view>
|
</view>
|
||||||
@ -104,7 +104,9 @@
|
|||||||
import downImg from "@/static/cb_up.png"
|
import downImg from "@/static/cb_up.png"
|
||||||
import tougaoImg from "@/static/kejiantougao.png"
|
import tougaoImg from "@/static/kejiantougao.png"
|
||||||
import downLoadImg from "@/static/wdxz.png"
|
import downLoadImg from "@/static/wdxz.png"
|
||||||
|
import api from '@/api/api.js';
|
||||||
const isFilterActive=ref(false)
|
const isFilterActive=ref(false)
|
||||||
|
const sort = ref(2);
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const refreshing = ref(false);
|
const refreshing = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -113,44 +115,7 @@
|
|||||||
const pageSize = ref(10);
|
const pageSize = ref(10);
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const coursewareList = ref([
|
const coursewareList = ref([]);
|
||||||
{
|
|
||||||
title: "颜学兵: 广东省基孔肯雅热诊疗指引",
|
|
||||||
author: "颜学兵 徐州医科大学附属医院",
|
|
||||||
views: 179,
|
|
||||||
price: "10.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "颜学兵: 佛山市基孔肯雅热中医诊治推荐用方",
|
|
||||||
author: "颜学兵 徐州医科大学附属医院",
|
|
||||||
views: 122,
|
|
||||||
price: "10.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "抗菌药物的临床应用",
|
|
||||||
author: "肝胆相照官方账号 北京肝胆相照公益基金会",
|
|
||||||
views: 656,
|
|
||||||
price: "15.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "中国肝癌多学科综合治疗专家共识 (2025)",
|
|
||||||
author: "肝胆相照官方账号 北京肝胆相照公益基金会",
|
|
||||||
views: 208,
|
|
||||||
price: "15.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "耐药结核病全口服短程治疗专家共识 (2025)",
|
|
||||||
author: "肝胆相照官方账号 北京肝胆相照公益基金会",
|
|
||||||
views: 256,
|
|
||||||
price: "15.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "结核分枝杆菌合并乙型肝炎病毒治专家共识",
|
|
||||||
author: "肝胆相照官方账号 北京肝胆相照公益基金会",
|
|
||||||
views: 358,
|
|
||||||
price: "15.0"
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
@ -171,10 +136,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleSort = () => {
|
const toggleSort = () => {
|
||||||
uni.showToast({
|
sort.value=sort.value==1?2:1
|
||||||
title: '排序功能',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -192,46 +154,13 @@
|
|||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 模拟API数据
|
|
||||||
const mockApiData = [
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
title: "肝胆疾病影像学诊断指南",
|
|
||||||
author: "影像科专家团队 北京协和医院",
|
|
||||||
views: 445,
|
|
||||||
price: "20.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
title: "肝硬化并发症治疗新进展",
|
|
||||||
author: "消化内科专家 上海交通大学医学院",
|
|
||||||
views: 332,
|
|
||||||
price: "18.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
title: "肝胆外科手术技巧精要",
|
|
||||||
author: "外科专家 中山大学附属第一医院",
|
|
||||||
views: 567,
|
|
||||||
price: "25.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
title: "肝胆疾病护理规范",
|
|
||||||
author: "护理专家团队 中国护理学会",
|
|
||||||
views: 289,
|
|
||||||
price: "12.0"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
// 下拉刷新
|
// 下拉刷新
|
||||||
const onRefresh = async () => {
|
const onRefresh = async () => {
|
||||||
refreshing.value = true;
|
refreshing.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 模拟API调用延迟
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
||||||
|
|
||||||
// 重置数据
|
// 重置数据
|
||||||
page.value = 1;
|
page.value = 1;
|
||||||
noMore.value = false;
|
noMore.value = false;
|
||||||
@ -261,9 +190,6 @@
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 模拟API调用延迟
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 800));
|
|
||||||
|
|
||||||
// 加载下一页数据
|
// 加载下一页数据
|
||||||
await loadData(false);
|
await loadData(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -278,22 +204,89 @@
|
|||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
const loadData = async (isRefresh = false) => {
|
const loadData = async (isRefresh = false) => {
|
||||||
// 模拟API分页逻辑
|
|
||||||
const startIndex = (page.value - 1) * pageSize.value;
|
|
||||||
const endIndex = startIndex + pageSize.value;
|
|
||||||
const newData = mockApiData.slice(startIndex, endIndex);
|
|
||||||
|
|
||||||
if (isRefresh) {
|
if (isRefresh) {
|
||||||
// 刷新时替换所有数据
|
page.value = 1;
|
||||||
coursewareList.value = coursewareList.value.slice(0, 6); // 保留原有6条数据
|
coursewareList.value = [];
|
||||||
|
noMore.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading.value || noMore.value) return;
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`开始加载第${page.value}页课件数据`);
|
||||||
|
|
||||||
|
// 调用API获取课件列表
|
||||||
|
const res = await api.ganDanFileByKeyWords({
|
||||||
|
page: page.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
sort: sort.value,
|
||||||
|
// 可以根据需要添加其他筛选参数
|
||||||
|
keywords: '',
|
||||||
|
title: '',
|
||||||
|
// fileType: selectedFileType.value,
|
||||||
|
// sortBy: sortType.value
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('课件列表API响应:', res);
|
||||||
|
|
||||||
|
if (res && res.code === 200) {
|
||||||
|
let newItems = [];
|
||||||
|
let totalCount = 0;
|
||||||
|
|
||||||
|
// 解析API返回的数据结构
|
||||||
|
if (res.data && res.data.list) {
|
||||||
|
newItems = res.data.list;
|
||||||
|
totalCount = res.data.total || res.data.totalRow || 0;
|
||||||
|
console.log('使用 res.data.list 结构');
|
||||||
|
} else if (res.data && Array.isArray(res.data)) {
|
||||||
|
newItems = res.data;
|
||||||
|
totalCount = res.total || 0;
|
||||||
|
console.log('使用 res.data 数组结构');
|
||||||
|
} else {
|
||||||
|
console.error('无法识别的数据结构:', res.data);
|
||||||
|
noMore.value = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('解析后的数据:', { newItems, totalCount, newItemsLength: newItems.length });
|
||||||
|
|
||||||
|
if (Array.isArray(newItems)) {
|
||||||
|
if (isRefresh) {
|
||||||
|
coursewareList.value = newItems;
|
||||||
|
console.log('刷新模式:替换列表数据');
|
||||||
|
} else {
|
||||||
|
coursewareList.value.push(...newItems);
|
||||||
|
console.log('加载更多:追加数据到列表');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
if (newItems.length < pageSize.value || coursewareList.value.length >= totalCount) {
|
||||||
|
noMore.value = true;
|
||||||
|
console.log('没有更多数据了');
|
||||||
} else {
|
} else {
|
||||||
// 加载更多时追加数据
|
|
||||||
if (newData.length > 0) {
|
|
||||||
coursewareList.value.push(...newData);
|
|
||||||
page.value++;
|
page.value++;
|
||||||
|
console.log(`还有更多数据,下一页: ${page.value}`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
console.error('API返回的数据不是数组格式:', newItems);
|
||||||
noMore.value = true;
|
noMore.value = true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.error('加载课件列表失败:', res.message);
|
||||||
|
uni.showToast({
|
||||||
|
title: res.message || '加载失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载课件列表异常:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '网络异常,请重试',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const showFilter = ref(false)
|
const showFilter = ref(false)
|
||||||
@ -340,7 +333,9 @@
|
|||||||
// 这里可以根据选中的标签进行数据筛选
|
// 这里可以根据选中的标签进行数据筛选
|
||||||
};
|
};
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
// 页面显示时的逻辑
|
// 页面显示时加载数据
|
||||||
|
console.log('页面显示,开始加载课件数据');
|
||||||
|
loadData(true);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -634,4 +629,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 加载状态样式
|
||||||
|
.loading-state,
|
||||||
|
.empty-state,
|
||||||
|
.load-more-state,
|
||||||
|
.no-more-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 60rpx 20rpx;
|
||||||
|
color: $text-secondary;
|
||||||
|
font-size: 28rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-state {
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-more-state {
|
||||||
|
padding: 40rpx 20rpx;
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-more-state {
|
||||||
|
padding: 40rpx 20rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
147
pages_app/pptDetail/pptDetail.vue
Normal file
147
pages_app/pptDetail/pptDetail.vue
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<view class="ppt-detail-page">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="课件详情"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
fixed
|
||||||
|
color="#8B2316"
|
||||||
|
height="140rpx"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
>
|
||||||
|
<template v-slot:right>
|
||||||
|
<view class="nav-actions">
|
||||||
|
<uni-icons type="paperplane" size="22" color="#8B2316"></uni-icons>
|
||||||
|
<uni-icons type="heart" size="22" color="#8B2316" style="margin-left: 20rpx;"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-nav-bar>
|
||||||
|
|
||||||
|
<!-- 下载提示条 -->
|
||||||
|
<view class="download-bar">
|
||||||
|
<view class="download-inner">
|
||||||
|
<u-icon name="download" color="#fff" size="28"></u-icon>
|
||||||
|
<text class="download-text">本课件下载</text>
|
||||||
|
<text class="download-price">{{ price }}</text>
|
||||||
|
<text class="download-unit">元</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 图片浏览 -->
|
||||||
|
<view class="viewer">
|
||||||
|
<swiper
|
||||||
|
class="ppt-swiper"
|
||||||
|
:indicator-dots="false"
|
||||||
|
:circular="true"
|
||||||
|
:autoplay="false"
|
||||||
|
@change="onSwiperChange"
|
||||||
|
>
|
||||||
|
<swiper-item v-for="(img, idx) in images" :key="idx">
|
||||||
|
<view class="slide">
|
||||||
|
<image :src="img" mode="widthFix" class="slide-image" />
|
||||||
|
</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
|
||||||
|
<!-- 页码指示 -->
|
||||||
|
<view class="page-indicator">{{ currentIndex + 1 }}/{{ images.length }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
|
|
||||||
|
const images = ref([
|
||||||
|
'/static/big_background_my.png',
|
||||||
|
'/static/big_background_my.png',
|
||||||
|
'/static/big_background_my.png'
|
||||||
|
]);
|
||||||
|
const currentIndex = ref(1); // 对应截图显示 2/23 的第二页效果
|
||||||
|
const price = ref('1.0');
|
||||||
|
|
||||||
|
const onSwiperChange = (e) => {
|
||||||
|
currentIndex.value = e.detail.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack();
|
||||||
|
};
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
// 可在此根据路由参数拉取课件详情与图片列表
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ppt-detail-page {
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-bar {
|
||||||
|
position: sticky;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
z-index: 9;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #6F6F6F; // 接近截图灰条
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.download-inner {
|
||||||
|
padding: 0 24rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.download-text {
|
||||||
|
margin-left: 12rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.download-price {
|
||||||
|
margin-left: 8rpx;
|
||||||
|
color: #ff3b30; // 红色价格
|
||||||
|
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.download-unit {
|
||||||
|
margin-left: 4rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewer {
|
||||||
|
padding: 24rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppt-swiper {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 400rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.slide {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.slide-image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-indicator {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
<!-- Fixed Banner Swiper -->
|
<!-- Fixed Banner Swiper -->
|
||||||
<view class="banner-container">
|
<view class="banner-container">
|
||||||
|
|
||||||
<view class="swipemask" >
|
<view class="swipemask" >
|
||||||
<view class="banner-subtitle">111111111</view>
|
<view class="banner-subtitle" v-if="bannerList.length>0">{{bannerList[currentBannerIndex].name}}</view>
|
||||||
<view class="dotbox">
|
<view class="dotbox">
|
||||||
<view class="circle" :class="{active:currentBannerIndex==index} "v-for="(banner, index) in bannerList"
|
<view class="circle" :class="{active:currentBannerIndex==index} "v-for="(banner, index) in bannerList"
|
||||||
:key="banner.id"></view>
|
:key="banner.id"></view>
|
||||||
@ -33,18 +34,10 @@
|
|||||||
<view class="banner-item">
|
<view class="banner-item">
|
||||||
<image
|
<image
|
||||||
class="banner-image"
|
class="banner-image"
|
||||||
:src="banner.thumbnail || '/static/big_background_my.png'"
|
:src="docUrl+banner.imgpath"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></image>
|
></image>
|
||||||
<view class="banner-content">
|
|
||||||
<view class="doctor-avatar" v-if="banner.doctorAvatar">
|
|
||||||
<image :src="banner.doctorAvatar" mode="aspectFill"></image>
|
|
||||||
</view>
|
|
||||||
<view class="banner-info">
|
|
||||||
<view class="banner-title">{{banner.title}}</view>
|
|
||||||
<view class="banner-subtitle">{{banner.subtitle || '专业医学视频教育平台'}}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
</swiper>
|
</swiper>
|
||||||
@ -57,25 +50,25 @@
|
|||||||
class="tab-item"
|
class="tab-item"
|
||||||
@click="showAllVideoPopup=!showAllVideoPopup"
|
@click="showAllVideoPopup=!showAllVideoPopup"
|
||||||
>
|
>
|
||||||
<up-image :src="allImg" width="30rpx" height="30rpx" ></up-image>
|
<up-image :src="isAllActive?allOnImg:allImg" width="30rpx" height="30rpx" ></up-image>
|
||||||
<text class="tab-text">全部视频</text>
|
<text class="tab-text" :class="{active:isAllActive}">{{typeName}}</text>
|
||||||
<up-image :src="selectImg" width="30rpx" height="30rpx" ></up-image>
|
<up-image :src="isAllActive?selectOnImg:selectImg" width="30rpx" height="30rpx" ></up-image>
|
||||||
</view>
|
</view>
|
||||||
<view class="right">
|
<view class="right">
|
||||||
<view
|
<view
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
|
@click="toggleSort"
|
||||||
>
|
>
|
||||||
<text class="tab-text">最新</text>
|
<text class="tab-text active">{{sort==2?'最新':'最热'}}</text>
|
||||||
<view class="newbox">
|
<view class="newbox">
|
||||||
<up-image :src="upImg" width="20rpx" height="26rpx" ></up-image>
|
<up-image :src="sort==2?upImg:downImg" width="20rpx" height="26rpx" ></up-image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
@click="showFilterPopup"
|
@click="showFilterPopup"
|
||||||
>
|
>
|
||||||
<text class="tab-text">筛选</text>
|
<text class="tab-text " :class="{active:isFilterActive}">筛选</text>
|
||||||
<view class="filterbox">
|
<view class="filterbox">
|
||||||
<up-image :src="isFilterActive ? filterOn : filter" width="30rpx" height="30rpx" ></up-image>
|
<up-image :src="isFilterActive ? filterOn : filter" width="30rpx" height="30rpx" ></up-image>
|
||||||
</view>
|
</view>
|
||||||
@ -100,22 +93,22 @@
|
|||||||
<view
|
<view
|
||||||
class="video-item"
|
class="video-item"
|
||||||
v-for="(video, index) in videoList"
|
v-for="(video, index) in videoList"
|
||||||
:key="video.id"
|
:key="video.id || video.uuid"
|
||||||
@click="playVideo(video)"
|
@click="playVideo(video)"
|
||||||
>
|
>
|
||||||
<view class="video-thumbnail">
|
<view class="video-thumbnail">
|
||||||
<image :src="video.thumbnail" mode="aspectFill"></image>
|
<image :src="docUrl + video.imgpath" mode="aspectFill"></image>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<view class="video-info">
|
<view class="video-info">
|
||||||
<view class="video-title">{{video.title}}</view>
|
<view class="video-title">{{video.title || video.name}}</view>
|
||||||
<view class="video-meta">
|
<view class="video-meta">
|
||||||
<text class="author">{{video.author}}</text>
|
<text class="author">{{video.public_name}}</text>
|
||||||
<view class="stats">
|
<view class="stats">
|
||||||
<uni-icons type="eye" size="14" color="#999"></uni-icons>
|
<uni-icons type="eye" size="14" color="#999"></uni-icons>
|
||||||
<text class="view-count">{{video.viewCount}}</text>
|
<text class="view-count">{{video.readnum}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -137,7 +130,7 @@
|
|||||||
<text>暂无视频内容</text>
|
<text>暂无视频内容</text>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="btnbox">
|
<view class="btnbox" @click="goPatientVideo">
|
||||||
<up-image :src="videoImg" width="44rpx" height="44rpx" ></up-image>
|
<up-image :src="videoImg" width="44rpx" height="44rpx" ></up-image>
|
||||||
患教视频
|
患教视频
|
||||||
|
|
||||||
@ -154,7 +147,7 @@
|
|||||||
:class="{ active: tag.selected }"
|
:class="{ active: tag.selected }"
|
||||||
@click="toggleTag(index)"
|
@click="toggleTag(index)"
|
||||||
>
|
>
|
||||||
{{ tag.name }}
|
{{ tag.DES }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -180,18 +173,28 @@
|
|||||||
:key="category.value"
|
:key="category.value"
|
||||||
@click="selectCategory(category.value)"
|
@click="selectCategory(category.value)"
|
||||||
>
|
>
|
||||||
{{ category.label }}
|
<view class="category-label">{{ category.label }}</view>
|
||||||
|
<view class="category-date" v-if="category.value !== '全部' && category.originalDate">
|
||||||
|
{{ formatDate(category.originalDate) }}
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="content-area">
|
<view class="content-area">
|
||||||
<view class="content-list">
|
<view class="content-list">
|
||||||
|
|
||||||
|
|
||||||
<view
|
<view
|
||||||
class="content-item"
|
class="content-item"
|
||||||
|
|
||||||
v-for="item in filteredContent"
|
v-for="item in filteredContent"
|
||||||
:key="item.id"
|
:key="item.uuid"
|
||||||
|
:class="{active:selectYearContent.uuid==item.uuid}"
|
||||||
@click="selectContent(item)"
|
@click="selectContent(item)"
|
||||||
>
|
>
|
||||||
{{ item.title }}
|
{{item.name }}
|
||||||
|
</view>
|
||||||
|
<view v-if="filteredContent.length === 0" class="empty-content">
|
||||||
|
<text>该分类暂无内容</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -202,7 +205,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed } from 'vue';
|
import { ref, onMounted, computed,reactive } from 'vue';
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
import api from '@/api/api.js';
|
import api from '@/api/api.js';
|
||||||
import allImg from "@/static/video_all.png"
|
import allImg from "@/static/video_all.png"
|
||||||
@ -212,8 +215,11 @@
|
|||||||
import filter from "@/static/cb_screen_no.png"
|
import filter from "@/static/cb_screen_no.png"
|
||||||
import filterOn from "@/static/cb_screen_yes.png"
|
import filterOn from "@/static/cb_screen_yes.png"
|
||||||
import upImg from "@/static/cb_up.png"
|
import upImg from "@/static/cb_up.png"
|
||||||
import downImg from "@/static/cb_up.png"
|
import downImg from "@/static/cb_down.png"
|
||||||
import videoImg from "@/static/patient_video.png"
|
import videoImg from "@/static/patient_video.png"
|
||||||
|
import docUrl from '@/utils/docUrl';
|
||||||
|
import navTo from '@/utils/navTo';
|
||||||
|
const isAllActive=ref(false)
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const videoList = ref([]);
|
const videoList = ref([]);
|
||||||
const bannerVideo = ref(null);
|
const bannerVideo = ref(null);
|
||||||
@ -224,13 +230,18 @@
|
|||||||
const currentPage = ref(1);
|
const currentPage = ref(1);
|
||||||
const pageSize = ref(10);
|
const pageSize = ref(10);
|
||||||
const hasMoreData = ref(true);
|
const hasMoreData = ref(true);
|
||||||
|
const filteredContent=ref([])
|
||||||
|
const sort =ref(2);
|
||||||
|
const keywords=ref('');
|
||||||
|
const typeUuid=ref('');
|
||||||
|
const typeName=ref('全部视频')
|
||||||
// Banner相关数据
|
// Banner相关数据
|
||||||
const bannerList = ref([]);
|
const bannerList = ref([]);
|
||||||
const currentBannerIndex = ref(0);
|
const currentBannerIndex = ref(0);
|
||||||
const isFilterActive=ref(false)
|
const isFilterActive=ref(false)
|
||||||
const showFilter = ref(false);
|
const showFilter = ref(false);
|
||||||
|
const yearList=ref([]);
|
||||||
|
const selectYearContent=reactive({})
|
||||||
// 筛选弹窗相关数据
|
// 筛选弹窗相关数据
|
||||||
const filterTags = ref([
|
const filterTags = ref([
|
||||||
{ name: '指南解读', selected: false },
|
{ name: '指南解读', selected: false },
|
||||||
@ -249,65 +260,171 @@
|
|||||||
|
|
||||||
// 全部视频弹窗相关数据
|
// 全部视频弹窗相关数据
|
||||||
const showAllVideoPopup = ref(false);
|
const showAllVideoPopup = ref(false);
|
||||||
const selectedCategory = ref('all');
|
const selectedCategory = ref('全部');
|
||||||
const categoryList = ref([
|
const categoryList = ref([
|
||||||
{ value: 'all', label: '全部' },
|
{ value: 'all', label: '全部' }
|
||||||
{ value: 'guide', label: '指南解读' },
|
|
||||||
{ value: 'case', label: '病例分析' },
|
|
||||||
{ value: 'lecture', label: '学术讲座' },
|
|
||||||
{ value: 'surgery', label: '手术视频' },
|
|
||||||
{ value: 'research', label: '研究进展' }
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 分类内容数据
|
// 分类内容数据 - 将根据API返回的类型动态生成
|
||||||
const contentByCategory = ref({
|
const contentByCategory = ref({
|
||||||
all: [
|
all: []
|
||||||
{ id: 1, title: '《2025年版慢加急性肝衰竭指南》解读' },
|
|
||||||
{ id: 2, title: '自身免疫性肝病专栏|免疫治疗的双刃剑' },
|
|
||||||
{ id: 3, title: '徐医感染:硬化出血发热路,关关难过关关过' },
|
|
||||||
{ id: 4, title: '徐医感染:一场呼吸的迷局' },
|
|
||||||
{ id: 5, title: '南京市第二医院疑难肝病病理读片会' }
|
|
||||||
],
|
|
||||||
guide: [
|
|
||||||
{ id: 6, title: '《2025年版慢加急性肝衰竭指南》解读' },
|
|
||||||
{ id: 7, title: '《原发性肝癌诊疗指南》更新要点' },
|
|
||||||
{ id: 8, title: '《慢性乙型肝炎防治指南》解读' }
|
|
||||||
],
|
|
||||||
case: [
|
|
||||||
{ id: 9, title: '自身免疫性肝病专栏|免疫治疗的双刃剑' },
|
|
||||||
{ id: 10, title: '徐医感染:硬化出血发热路,关关难过关关过' },
|
|
||||||
{ id: 11, title: '徐医感染:一场呼吸的迷局' }
|
|
||||||
],
|
|
||||||
lecture: [
|
|
||||||
{ id: 12, title: '南京市第二医院疑难肝病病理读片会' },
|
|
||||||
{ id: 13, title: '肝胆胰外科手术技巧分享' },
|
|
||||||
{ id: 14, title: '肝移植围手术期管理' }
|
|
||||||
],
|
|
||||||
surgery: [
|
|
||||||
{ id: 15, title: '腹腔镜肝切除术操作要点' },
|
|
||||||
{ id: 16, title: '机器人辅助肝切除术' },
|
|
||||||
{ id: 17, title: '肝移植手术技术进展' }
|
|
||||||
],
|
|
||||||
research: [
|
|
||||||
{ id: 18, title: '肝癌免疫治疗最新研究进展' },
|
|
||||||
{ id: 19, title: '肝纤维化分子机制研究' },
|
|
||||||
{ id: 20, title: '肝细胞再生与修复研究' }
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 存储API返回的原始类型数据
|
||||||
|
const videoTypesData = ref([]);
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
// 使用模拟数据初始化列表
|
// 调用真实API获取数据
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
hasMoreData.value = true;
|
hasMoreData.value = true;
|
||||||
loadMockVideoData(true);
|
loadVideoData(true);
|
||||||
// 初始化banner数据
|
loadBannerData();
|
||||||
bannerList.value = getMockBannerData();
|
loadVideoTags();
|
||||||
|
loadVideoTypes();
|
||||||
|
|
||||||
|
// 延迟加载"全部"分类的视频数据,确保类型数据先加载完成
|
||||||
|
setTimeout(() => {
|
||||||
|
loadCategoryVideos('all');
|
||||||
|
}, 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 加载轮播数据
|
||||||
|
const loadBannerData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await api.videoRoll({});
|
||||||
|
console.log('轮播API原始响应:', response);
|
||||||
|
bannerList.value=response.data;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载轮播数据失败:', error);
|
||||||
|
// 使用模拟数据作为备用
|
||||||
|
bannerList.value = getMockBannerData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载视频标签
|
||||||
|
const loadVideoTags = async () => {
|
||||||
|
try {
|
||||||
|
const response = await api.videoTagList({
|
||||||
|
type:2
|
||||||
|
});
|
||||||
|
console.log('标签API原始响应:', response);
|
||||||
|
|
||||||
|
if(response.code==200){
|
||||||
|
filterTags.value=response.data;
|
||||||
|
console.log(22222)
|
||||||
|
console.log(filterTags.value)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载视频标签失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载视频类型
|
||||||
|
const loadVideoTypes = async () => {
|
||||||
|
try {
|
||||||
|
const response = await api.expertVideoTypeList({
|
||||||
|
|
||||||
|
});
|
||||||
|
console.log('类型API原始响应:', response);
|
||||||
|
if(response.code==200){
|
||||||
|
yearList.value=response.data;
|
||||||
|
filteredContent.value=(response.data[0]).list;
|
||||||
|
console.log(33)
|
||||||
|
let arr=response.data.map(item=>{
|
||||||
|
return {
|
||||||
|
value:item.name,
|
||||||
|
label:item.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
categoryList.value=arr
|
||||||
|
}
|
||||||
|
console.log(2222)
|
||||||
|
console.log(categoryList.value)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载视频类型失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载分类视频数据
|
||||||
|
const loadCategoryVideos = async (categoryValue) => {
|
||||||
|
try {
|
||||||
|
console.log('加载分类视频:', categoryValue);
|
||||||
|
|
||||||
|
let response;
|
||||||
|
if (categoryValue === '全部') {
|
||||||
|
// 加载所有视频
|
||||||
|
response = await api.videoByKeyWordsNew({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
keywords: '',
|
||||||
|
sort: 0,
|
||||||
|
typeUuid: '',
|
||||||
|
tags: ''
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 根据日期分类加载对应的视频类型数据
|
||||||
|
// 找到该日期对应的视频类型
|
||||||
|
const typesForDate = videoTypesData.value.filter(type => type.create_date === categoryValue);
|
||||||
|
console.log(`日期 ${categoryValue} 对应的视频类型:`, typesForDate);
|
||||||
|
|
||||||
|
if (typesForDate.length > 0) {
|
||||||
|
// 获取这些类型的UUID列表
|
||||||
|
const typeUuids = typesForDate.map(type => type.id || type.uuid || type.value).join(',');
|
||||||
|
console.log('类型UUID列表:', typeUuids);
|
||||||
|
|
||||||
|
// 加载特定类型的视频
|
||||||
|
response = await api.videoByKeyWordsNew({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
keywords: '',
|
||||||
|
sort: 0,
|
||||||
|
typeUuid: typeUuids,
|
||||||
|
tags: ''
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn(`未找到日期 ${categoryValue} 对应的视频类型`);
|
||||||
|
contentByCategory.value[categoryValue] = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 } = videoData;
|
||||||
|
// 更新对应分类的内容
|
||||||
|
contentByCategory.value[categoryValue] = list.map(video => ({
|
||||||
|
id: video.id || video.uuid,
|
||||||
|
title: video.title || video.name,
|
||||||
|
name: video.name || video.title
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log(`分类 ${categoryValue} 的内容:`, contentByCategory.value[categoryValue]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载分类视频失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 加载视频数据
|
// 加载视频数据
|
||||||
const loadVideoData = async (isRefresh = false) => {
|
const loadVideoData = async (isRefresh = false) => {
|
||||||
if (loading.value && !isRefresh) return;
|
if (loading.value && !isRefresh) return;
|
||||||
@ -316,58 +433,60 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 调用真实API
|
// 调用真实API
|
||||||
const response = await api.getVideoList({
|
const selectedTags = filterTags.value.filter(tag => tag.selected).map(tag => tag.id).join(',');
|
||||||
|
console.log('请求参数:', {
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
category: activeTab.value // 根据选中的标签获取不同类别的视频
|
keywords: keywords.value,
|
||||||
|
sort: sort.value,
|
||||||
|
typeUuid:typeUuid.value,
|
||||||
|
tags: selectedTags
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const response = await api.videoByKeyWordsNew({
|
||||||
|
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) {
|
if (response.data.code === 200) {
|
||||||
const { list, hasMore } = response.data.data;
|
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, hasMore, total } = videoData;
|
||||||
|
console.log('视频列表数据:', list);
|
||||||
|
|
||||||
if (isRefresh) {
|
if (isRefresh) {
|
||||||
videoList.value = list;
|
videoList.value = list || [];
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
} else {
|
} else {
|
||||||
videoList.value = [...videoList.value, ...list];
|
videoList.value = [...videoList.value, ...(list || [])];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置banner视频(第一个视频)
|
hasMoreData.value = hasMore !== false;
|
||||||
if (isRefresh || currentPage.value === 1) {
|
|
||||||
bannerVideo.value = list[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
hasMoreData.value = hasMore;
|
|
||||||
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
|
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.data.message || '获取数据失败');
|
throw new Error(response?.message || '获取数据失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载视频失败:', error);
|
console.error('加载视频失败:', error);
|
||||||
|
|
||||||
// 如果API失败,使用模拟数据作为备用方案
|
|
||||||
const mockData = await getMockVideoData(currentPage.value, pageSize.value);
|
|
||||||
|
|
||||||
if (isRefresh) {
|
|
||||||
videoList.value = mockData.list;
|
|
||||||
currentPage.value = 1;
|
|
||||||
} else {
|
|
||||||
videoList.value = [...videoList.value, ...mockData.list];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置banner视频(第一个视频)
|
|
||||||
if (isRefresh || currentPage.value === 1) {
|
|
||||||
bannerVideo.value = mockData.list[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
hasMoreData.value = mockData.hasMore;
|
|
||||||
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
|
|
||||||
|
|
||||||
uni.showToast({
|
|
||||||
title: '网络连接异常,显示离线数据',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
refreshing.value = false;
|
refreshing.value = false;
|
||||||
@ -399,7 +518,7 @@
|
|||||||
refreshing.value = true;
|
refreshing.value = true;
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
hasMoreData.value = true;
|
hasMoreData.value = true;
|
||||||
loadMockVideoData(true);
|
loadVideoData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 上拉加载更多
|
// 上拉加载更多
|
||||||
@ -408,7 +527,7 @@
|
|||||||
|
|
||||||
loadMoreStatus.value = 'loading';
|
loadMoreStatus.value = 'loading';
|
||||||
currentPage.value++;
|
currentPage.value++;
|
||||||
loadMockVideoData();
|
loadVideoData();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换标签
|
// 切换标签
|
||||||
@ -417,13 +536,15 @@
|
|||||||
// 可以根据标签加载不同的数据
|
// 可以根据标签加载不同的数据
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
hasMoreData.value = true;
|
hasMoreData.value = true;
|
||||||
loadMockVideoData(true);
|
loadVideoData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 播放视频
|
// 播放视频
|
||||||
const playVideo = (video) => {
|
const playVideo = (video) => {
|
||||||
uni.navigateTo({
|
const videoId = video.id || video.uuid;
|
||||||
url: `/pages/videoDetail/videoDetail?id=${video.id}`
|
|
||||||
|
navTo({
|
||||||
|
url: `/pages_app/videoDetail/videoDetail?id=${videoId}`
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -436,6 +557,61 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 跳转到患教视频列表
|
||||||
|
const goPatientVideo = () => {
|
||||||
|
navTo({
|
||||||
|
url: '/pages_app/patientVideo/patientVideo'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索视频
|
||||||
|
const searchVideos = async (keywords) => {
|
||||||
|
if (!keywords || keywords.trim() === '') {
|
||||||
|
loadVideoData(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('搜索关键词:', keywords.trim());
|
||||||
|
const response = await api.videoByKeyWordsNew({
|
||||||
|
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'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Banner相关方法
|
// Banner相关方法
|
||||||
const getMockBannerData = () => {
|
const getMockBannerData = () => {
|
||||||
return [
|
return [
|
||||||
@ -468,8 +644,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const playBannerVideo = (banner) => {
|
const playBannerVideo = (banner) => {
|
||||||
uni.navigateTo({
|
const videoId = banner.id || banner.uuid;
|
||||||
url: `/pages/videoDetail/videoDetail?id=${banner.id}`
|
|
||||||
|
navTo({
|
||||||
|
url: `/pages_app/videoDetail/videoDetail?id=${videoId}`
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -481,22 +659,34 @@
|
|||||||
const closeAllVideoPopup = () => {
|
const closeAllVideoPopup = () => {
|
||||||
showAllVideoPopup.value = false;
|
showAllVideoPopup.value = false;
|
||||||
};
|
};
|
||||||
|
const selectCategory = async (categoryValue) => {
|
||||||
const selectCategory = (categoryValue) => {
|
|
||||||
selectedCategory.value = categoryValue;
|
selectedCategory.value = categoryValue;
|
||||||
|
console.log(yearList.value)
|
||||||
|
console.log('选择分类:', categoryValue);
|
||||||
|
for (var i = 0; i < yearList.value.length; i++) {
|
||||||
|
|
||||||
|
if(categoryValue==yearList.value[i].name){
|
||||||
|
console.log(yearList.value[i]);
|
||||||
|
filteredContent.value=yearList.value[i].list;
|
||||||
|
console.log(filteredContent.value)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectContent = (content) => {
|
const selectContent = (content) => {
|
||||||
// 这里可以根据选中的内容进行相应的操作
|
// 这里可以根据选中的内容进行相应的操作
|
||||||
console.log('选中内容:', content);
|
console.log('选中内容:', content);
|
||||||
closeAllVideoPopup();
|
closeAllVideoPopup();
|
||||||
// 可以跳转到对应的视频页面或执行其他操作
|
Object.assign(selectYearContent,content);
|
||||||
|
typeUuid.value=content.uuid;
|
||||||
|
typeName.value=content.name;
|
||||||
|
isAllActive.value=true;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 计算属性:根据选中的分类过滤内容
|
|
||||||
const filteredContent = computed(() => {
|
|
||||||
return contentByCategory.value[selectedCategory.value] || [];
|
|
||||||
});
|
|
||||||
|
|
||||||
// 筛选弹窗相关方法
|
// 筛选弹窗相关方法
|
||||||
const showFilterPopup = () => {
|
const showFilterPopup = () => {
|
||||||
@ -513,15 +703,37 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetFilter = () => {
|
const resetFilter = () => {
|
||||||
|
// 清空所有已选标签
|
||||||
filterTags.value.forEach(tag => tag.selected = false);
|
filterTags.value.forEach(tag => tag.selected = false);
|
||||||
|
// 关闭筛选激活态
|
||||||
isFilterActive.value = false;
|
isFilterActive.value = false;
|
||||||
|
// 清空关键字
|
||||||
|
keywords.value = '';
|
||||||
|
// 刷新列表数据(可按需保留或移除)
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
loadVideoData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmFilter = () => {
|
const confirmFilter = () => {
|
||||||
const selectedTags = filterTags.value.filter(tag => tag.selected);
|
const selectedTags = filterTags.value.filter(tag => tag.selected);
|
||||||
console.log('选中的筛选标签:', selectedTags);
|
console.log('选中的筛选标签:', selectedTags);
|
||||||
|
for (var i = 0; i < selectedTags.length; i++) {
|
||||||
|
if(keywords.value){
|
||||||
|
keywords.value+=","+selectedTags[i].DES
|
||||||
|
}else{
|
||||||
|
keywords.value=selectedTags[i].DES
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
isFilterActive.value=true;
|
||||||
hideFilterPopup();
|
hideFilterPopup();
|
||||||
// 这里可以根据选中的标签进行数据筛选
|
// 根据选中的标签重新加载数据
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
loadVideoData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 模拟数据 - 实际开发时替换为真实API
|
// 模拟数据 - 实际开发时替换为真实API
|
||||||
@ -565,6 +777,13 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const toggleSort = () => {
|
||||||
|
sort.value = sort.value === 1 ? 2 : 1; // 1=最新, 2=最热(与后端约定)
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
loadVideoData(true);
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -697,11 +916,16 @@
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
.tab-item:first-child .tab-text{
|
.tab-item:first-child .tab-text{
|
||||||
max-width:600rpx;
|
max-width:295rpx;
|
||||||
|
display: inline-block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
.tab-item .tab-text.active {
|
||||||
|
color: #8B2316;
|
||||||
|
|
||||||
|
}
|
||||||
/* Fixed Banner Container */
|
/* Fixed Banner Container */
|
||||||
.banner-container {
|
.banner-container {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -805,6 +1029,9 @@
|
|||||||
.banner-subtitle {
|
.banner-subtitle {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: rgba(255,255,255,0.8);
|
color: rgba(255,255,255,0.8);
|
||||||
|
white-space: nowrap; /* 单行显示 */
|
||||||
|
overflow: hidden; /* 隐藏溢出 */
|
||||||
|
text-overflow: ellipsis; /* 超出显示省略号 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Video List */
|
/* Video List */
|
||||||
@ -837,18 +1064,15 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.play-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
.video-duration {
|
||||||
left: 50%;
|
margin-top: 8rpx;
|
||||||
transform: translate(-50%, -50%);
|
}
|
||||||
background-color: rgba(0,0,0,0.6);
|
|
||||||
border-radius: 50%;
|
.video-duration text {
|
||||||
width: 60rpx;
|
font-size: 22rpx;
|
||||||
height: 60rpx;
|
color: #999;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-info {
|
.video-info {
|
||||||
@ -857,7 +1081,7 @@
|
|||||||
|
|
||||||
.video-title {
|
.video-title {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
font-weight: 600;
|
font-weight: 400;
|
||||||
color: #333;
|
color: #333;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
@ -866,6 +1090,7 @@
|
|||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
line-clamp: 2;
|
line-clamp: 2;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
height: 2.8em; /* 固定2行高度:1.4 * 2 = 2.8em */
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-meta {
|
.video-meta {
|
||||||
@ -988,6 +1213,17 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.category-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-date {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.content-area {
|
.content-area {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 20rpx;
|
padding: 20rpx;
|
||||||
@ -1011,13 +1247,20 @@
|
|||||||
border: 2rpx solid transparent;
|
border: 2rpx solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-item:hover {
|
|
||||||
background-color: #e8f4fd;
|
|
||||||
border-color: #4A90E2;
|
.content-item.active {
|
||||||
|
|
||||||
|
color: #8B2316;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-item:active {
|
.empty-content {
|
||||||
transform: scale(0.98);
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 200rpx;
|
||||||
|
color: #999;
|
||||||
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
// 筛选弹窗样式
|
// 筛选弹窗样式
|
||||||
.filter-popup {
|
.filter-popup {
|
||||||
@ -1033,8 +1276,8 @@
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
|
|
||||||
.filter-content {
|
.filter-content {
|
||||||
margin-top:329rpx;
|
margin-top:660rpx;
|
||||||
|
overflow-y:scroll;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
// border-radius: 20rpx 20rpx 0 0;
|
// border-radius: 20rpx 20rpx 0 0;
|
||||||
padding: 20rpx 30rpx 60rpx;
|
padding: 20rpx 30rpx 60rpx;
|
||||||
@ -1052,11 +1295,13 @@
|
|||||||
.tag-item {
|
.tag-item {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
color: $gray-dark;
|
color: $gray-dark;
|
||||||
padding: 8rpx 24rpx;
|
padding: 8rpx 0; /* 去掉左右padding,仅保留上下 */
|
||||||
border-radius: 30rpx;
|
border-radius: 30rpx;
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
border: 2rpx solid #efefef;
|
border: 2rpx solid #efefef;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
width: 152rpx; /* 固定宽度 */
|
||||||
|
text-align: center; /* 文本居中 */
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
@ -1073,6 +1318,7 @@
|
|||||||
bottom: 30rpx;
|
bottom: 30rpx;
|
||||||
left: 30rpx;
|
left: 30rpx;
|
||||||
right: 30rpx;
|
right: 30rpx;
|
||||||
|
background-color: #fff; /* 背景色为白色 */
|
||||||
|
|
||||||
.btn-reset,
|
.btn-reset,
|
||||||
.btn-confirm {
|
.btn-confirm {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
370
pages_app/zhinanList/zhinanList.vue
Normal file
370
pages_app/zhinanList/zhinanList.vue
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
<template>
|
||||||
|
<view class="zhinan-list-page">
|
||||||
|
<!-- 头部导航栏 -->
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="诊疗指南"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
fixed
|
||||||
|
color="#8B2316"
|
||||||
|
height="140rpx"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
></uni-nav-bar>
|
||||||
|
|
||||||
|
<!-- 指南列表 -->
|
||||||
|
<view class="guidelines-list">
|
||||||
|
<view
|
||||||
|
class="guideline-item"
|
||||||
|
v-for="(item, index) in guidelinesList"
|
||||||
|
:key="item.uuid || index"
|
||||||
|
>
|
||||||
|
<!-- 指南信息 -->
|
||||||
|
<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
|
||||||
|
v-if="item.can_download"
|
||||||
|
class="download-btn"
|
||||||
|
@click="downloadGuideline(item)"
|
||||||
|
>
|
||||||
|
<up-icon name="download" color="#8D2316" size="28"></up-icon>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-else
|
||||||
|
class="view-btn"
|
||||||
|
@click="viewGuideline(item)"
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<view class="loading-status">
|
||||||
|
<view v-if="isLoading && currentPage === 1" class="loading">
|
||||||
|
<uni-load-more status="loading" :content-text="loadingText"></uni-load-more>
|
||||||
|
</view>
|
||||||
|
<view v-else-if="hasMoreData && !isLoading" class="load-more" @click="loadMoreData">
|
||||||
|
<uni-load-more status="more" :content-text="loadingText"></uni-load-more>
|
||||||
|
</view>
|
||||||
|
<view v-else-if="!hasMoreData && guidelinesList.length > 0" class="no-more">
|
||||||
|
<uni-load-more status="noMore" :content-text="loadingText"></uni-load-more>
|
||||||
|
</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>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted} from 'vue'
|
||||||
|
import api from '@/api/api.js'
|
||||||
|
import { onShow, onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app";
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const guidelinesList = ref([])
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const hasMoreData = ref(true)
|
||||||
|
const currentPage = ref(1)
|
||||||
|
const pageSize = ref(20)
|
||||||
|
const isRefreshing = ref(false)
|
||||||
|
|
||||||
|
// 加载文本配置
|
||||||
|
const loadingText = {
|
||||||
|
contentdown: '上拉显示更多',
|
||||||
|
contentrefresh: '正在加载...',
|
||||||
|
contentnomore: '没有更多数据了'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onMounted(() => {
|
||||||
|
loadGuidelinesList()
|
||||||
|
})
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
// 页面显示时可以刷新数据
|
||||||
|
loadGuidelinesList()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
onPullDownRefresh(() => {
|
||||||
|
refreshData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 上拉加载更多
|
||||||
|
onReachBottom(() => {
|
||||||
|
if (hasMoreData.value && !isLoading.value) {
|
||||||
|
loadMoreData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = async () => {
|
||||||
|
if (isRefreshing.value) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
isRefreshing.value = true
|
||||||
|
currentPage.value = 1
|
||||||
|
hasMoreData.value = true
|
||||||
|
|
||||||
|
await loadGuidelinesList()
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '刷新成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('刷新失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '刷新失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
isRefreshing.value = false
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载指南列表
|
||||||
|
const loadGuidelinesList = async (isLoadMore = false) => {
|
||||||
|
if (isLoading.value) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoading.value = true
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
page: currentPage.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
type: 1, // 诊疗指南类型
|
||||||
|
keywords: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await api.searchLibraryU(params)
|
||||||
|
console.log('指南列表响应:', res)
|
||||||
|
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
const newData = res.data
|
||||||
|
|
||||||
|
if (isLoadMore) {
|
||||||
|
guidelinesList.value = [...guidelinesList.value, ...newData]
|
||||||
|
} else {
|
||||||
|
guidelinesList.value = newData
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
hasMoreData.value = newData.length === pageSize.value
|
||||||
|
} else {
|
||||||
|
console.error('加载指南列表失败:', res.message)
|
||||||
|
uni.showToast({
|
||||||
|
title: res.message || '加载失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载指南列表异常:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '网络异常,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多数据
|
||||||
|
const loadMoreData = () => {
|
||||||
|
if (hasMoreData.value && !isLoading.value) {
|
||||||
|
currentPage.value++
|
||||||
|
loadGuidelinesList(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载指南
|
||||||
|
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'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看指南
|
||||||
|
const viewGuideline = (item) => {
|
||||||
|
console.log('查看指南:', item)
|
||||||
|
// 跳转到指南详情页或预览页
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages_app/zhinanDetail/zhinanDetail?uuid=${item.uuid}&title=${encodeURIComponent(item.title)}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
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;
|
||||||
|
|
||||||
|
.zhinan-list-page {
|
||||||
|
background-color: $bg-color;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 指南列表
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载状态
|
||||||
|
.loading-status {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.loading, .load-more, .no-more {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 无数据提示
|
||||||
|
.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>
|
||||||
BIN
static/xingxing1.png
Normal file
BIN
static/xingxing1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
static/xingxing2.png
Normal file
BIN
static/xingxing2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@ -54,6 +54,7 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
|
|||||||
version: '4.0.0',
|
version: '4.0.0',
|
||||||
user_uuid:userInfo.uuid,
|
user_uuid:userInfo.uuid,
|
||||||
client_type: 'A', //client_type,
|
client_type: 'A', //client_type,
|
||||||
|
timestamp:new Date().getTime()
|
||||||
}
|
}
|
||||||
postData={
|
postData={
|
||||||
...data,
|
...data,
|
||||||
@ -69,12 +70,9 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
|
|||||||
version: '4.0.0',
|
version: '4.0.0',
|
||||||
user_uuid:userInfo.uuid,
|
user_uuid:userInfo.uuid,
|
||||||
client_type: 'A', //client_type,
|
client_type: 'A', //client_type,
|
||||||
|
timestamp:new Date().getTime()
|
||||||
}
|
}
|
||||||
defaultData = {
|
|
||||||
version: '4.0.0',
|
|
||||||
user_uuid:userInfo.uuid,
|
|
||||||
client_type: 'A', //client_type,
|
|
||||||
}
|
|
||||||
postData={
|
postData={
|
||||||
...data,
|
...data,
|
||||||
...defaultData
|
...defaultData
|
||||||
@ -87,7 +85,7 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
|
|||||||
return new Promise(function(e, n) {
|
return new Promise(function(e, n) {
|
||||||
let timestamp = Date.now();
|
let timestamp = Date.now();
|
||||||
uni.request({
|
uni.request({
|
||||||
data: {...data,...defaultData},
|
data: postData,
|
||||||
url: url.indexOf('http') != -1 ? url : encodeURI(BASE_URL + url),
|
url: url.indexOf('http') != -1 ? url : encodeURI(BASE_URL + url),
|
||||||
method: method,
|
method: method,
|
||||||
sslVerify: false,
|
sslVerify: false,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user