Compare commits
No commits in common. "92bfc36d51e31b8701c326c4b14080804c0bd3e3" and "1f4c0834fa609929fbfad68e307121ef5576405e" have entirely different histories.
92bfc36d51
...
1f4c0834fa
59
api/api.js
59
api/api.js
@ -23,10 +23,12 @@ const api = {
|
|||||||
smsLogin(data,header){
|
smsLogin(data,header){
|
||||||
return request('/expertAPI/smsLogin', data, 'post', true,'application/json',header);
|
return request('/expertAPI/smsLogin', data, 'post', true,'application/json',header);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 密码登录
|
// 密码登录
|
||||||
pwdLogin(data){
|
pwdLogin(data){
|
||||||
return request('/expertAPI/login', data, 'post', true);
|
return request('/expertAPI/login', data, 'post', true);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取短信验证码
|
// 获取短信验证码
|
||||||
getCode(data,header) {
|
getCode(data,header) {
|
||||||
return request('/expertAPI/smsSend', data, 'post', true,'application/json',header);
|
return request('/expertAPI/smsSend', data, 'post', true,'application/json',header);
|
||||||
@ -205,63 +207,6 @@ 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,14 +2,15 @@
|
|||||||
"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
@ -531,46 +531,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"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": {
|
||||||
|
|||||||
@ -268,6 +268,7 @@
|
|||||||
const res = await api.getMyInfo({})
|
const res = await api.getMyInfo({})
|
||||||
if (res && res.code === 200 && res.data) {
|
if (res && res.code === 200 && res.data) {
|
||||||
const data = res.data
|
const data = res.data
|
||||||
|
avatar.value = '',
|
||||||
myInfoBackGround.value = data.myInfoBackGround;
|
myInfoBackGround.value = data.myInfoBackGround;
|
||||||
followupCount.value = data.follow_patient_num || data.relationPatientNum || 0
|
followupCount.value = data.follow_patient_num || data.relationPatientNum || 0
|
||||||
consultCount.value = data.consult_total || data.consultCount || 0
|
consultCount.value = data.consult_total || data.consultCount || 0
|
||||||
|
|||||||
@ -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">{{bannerList[currentBannerIndex].summary}}</view>
|
<view class="banner-subtitle">111111111</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,12 +39,19 @@
|
|||||||
>
|
>
|
||||||
<view class="banner-item">
|
<view class="banner-item">
|
||||||
<image
|
<image
|
||||||
style="width:100%;"
|
|
||||||
class="banner-image"
|
class="banner-image"
|
||||||
:src="docUrl +banner.headImg"
|
:src="banner.thumbnail || '/static/big_background_my.png'"
|
||||||
mode="widthFix"
|
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>
|
||||||
@ -52,7 +59,7 @@
|
|||||||
|
|
||||||
<scroll-view class="news-list" scroll-y="true">
|
<scroll-view class="news-list" scroll-y="true">
|
||||||
<!-- 肝胆新闻 -->
|
<!-- 肝胆新闻 -->
|
||||||
<view class="news-item" @click="goToNews('news')">
|
<view class="news-item" @click="goToNews('hepatoBiliaryNews')">
|
||||||
<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>
|
||||||
@ -66,7 +73,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>
|
||||||
@ -77,10 +84,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>
|
||||||
@ -92,9 +99,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>
|
||||||
@ -105,7 +112,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')">
|
||||||
@ -122,7 +129,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>
|
||||||
@ -133,48 +140,18 @@
|
|||||||
<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, onMounted } from 'vue';
|
import { ref } 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(() => {
|
onShow(()=>{
|
||||||
loadNewsBanner();
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
||||||
@ -227,17 +204,21 @@ import navTo from '../../utils/navTo';
|
|||||||
|
|
||||||
// 新闻相关方法
|
// 新闻相关方法
|
||||||
const goToNews = (type) => {
|
const goToNews = (type) => {
|
||||||
if(type=="news"){
|
console.log('跳转到新闻类型:', type);
|
||||||
navTo({
|
// 这里可以根据不同的新闻类型跳转到相应的页面
|
||||||
url:'/pages_app/newsList/newsList'
|
uni.showToast({
|
||||||
})
|
title: '功能开发中',
|
||||||
}
|
icon: 'none'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToCourse = (type) => {
|
const goToCourse = (type) => {
|
||||||
navTo({
|
console.log('跳转到课程类型:', type);
|
||||||
url:'/pages/live/live'
|
// 这里可以根据不同的课程类型跳转到相应的页面
|
||||||
})
|
uni.showToast({
|
||||||
|
title: '功能开发中',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -290,10 +271,6 @@ import navTo from '../../utils/navTo';
|
|||||||
.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{
|
||||||
|
|||||||
@ -1,718 +0,0 @@
|
|||||||
<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>
|
|
||||||
@ -1,280 +0,0 @@
|
|||||||
<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">{{sort==2?'最新':'最热'}}</text>
|
<text class="filter-text">最新</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,9 +104,7 @@
|
|||||||
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);
|
||||||
@ -115,7 +113,44 @@
|
|||||||
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 = () => {
|
||||||
@ -136,7 +171,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleSort = () => {
|
const toggleSort = () => {
|
||||||
sort.value=sort.value==1?2:1
|
uni.showToast({
|
||||||
|
title: '排序功能',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -154,13 +192,46 @@
|
|||||||
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;
|
||||||
@ -190,6 +261,9 @@
|
|||||||
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) {
|
||||||
@ -204,89 +278,22 @@
|
|||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
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 = coursewareList.value.slice(0, 6); // 保留原有6条数据
|
||||||
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)
|
||||||
@ -333,9 +340,7 @@
|
|||||||
// 这里可以根据选中的标签进行数据筛选
|
// 这里可以根据选中的标签进行数据筛选
|
||||||
};
|
};
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
// 页面显示时加载数据
|
// 页面显示时的逻辑
|
||||||
console.log('页面显示,开始加载课件数据');
|
|
||||||
loadData(true);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -629,39 +634,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 加载状态样式
|
|
||||||
.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>
|
||||||
@ -1,147 +0,0 @@
|
|||||||
<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,9 +6,8 @@
|
|||||||
|
|
||||||
<!-- 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>
|
||||||
@ -34,10 +33,18 @@
|
|||||||
<view class="banner-item">
|
<view class="banner-item">
|
||||||
<image
|
<image
|
||||||
class="banner-image"
|
class="banner-image"
|
||||||
:src="docUrl+banner.imgpath"
|
:src="banner.thumbnail || '/static/big_background_my.png'"
|
||||||
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>
|
||||||
@ -50,25 +57,25 @@
|
|||||||
class="tab-item"
|
class="tab-item"
|
||||||
@click="showAllVideoPopup=!showAllVideoPopup"
|
@click="showAllVideoPopup=!showAllVideoPopup"
|
||||||
>
|
>
|
||||||
<up-image :src="isAllActive?allOnImg:allImg" width="30rpx" height="30rpx" ></up-image>
|
<up-image :src="allImg" width="30rpx" height="30rpx" ></up-image>
|
||||||
<text class="tab-text" :class="{active:isAllActive}">{{typeName}}</text>
|
<text class="tab-text">全部视频</text>
|
||||||
<up-image :src="isAllActive?selectOnImg:selectImg" width="30rpx" height="30rpx" ></up-image>
|
<up-image :src="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 active">{{sort==2?'最新':'最热'}}</text>
|
<text class="tab-text">最新</text>
|
||||||
<view class="newbox">
|
<view class="newbox">
|
||||||
<up-image :src="sort==2?upImg:downImg" width="20rpx" height="26rpx" ></up-image>
|
<up-image :src="upImg" 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 " :class="{active:isFilterActive}">筛选</text>
|
<text class="tab-text">筛选</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>
|
||||||
@ -93,22 +100,22 @@
|
|||||||
<view
|
<view
|
||||||
class="video-item"
|
class="video-item"
|
||||||
v-for="(video, index) in videoList"
|
v-for="(video, index) in videoList"
|
||||||
:key="video.id || video.uuid"
|
:key="video.id"
|
||||||
@click="playVideo(video)"
|
@click="playVideo(video)"
|
||||||
>
|
>
|
||||||
<view class="video-thumbnail">
|
<view class="video-thumbnail">
|
||||||
<image :src="docUrl + video.imgpath" mode="aspectFill"></image>
|
<image :src="video.thumbnail" mode="aspectFill"></image>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<view class="video-info">
|
<view class="video-info">
|
||||||
<view class="video-title">{{video.title || video.name}}</view>
|
<view class="video-title">{{video.title}}</view>
|
||||||
<view class="video-meta">
|
<view class="video-meta">
|
||||||
<text class="author">{{video.public_name}}</text>
|
<text class="author">{{video.author}}</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.readnum}}</text>
|
<text class="view-count">{{video.viewCount}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -130,7 +137,7 @@
|
|||||||
<text>暂无视频内容</text>
|
<text>暂无视频内容</text>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="btnbox" @click="goPatientVideo">
|
<view class="btnbox">
|
||||||
<up-image :src="videoImg" width="44rpx" height="44rpx" ></up-image>
|
<up-image :src="videoImg" width="44rpx" height="44rpx" ></up-image>
|
||||||
患教视频
|
患教视频
|
||||||
|
|
||||||
@ -147,7 +154,7 @@
|
|||||||
:class="{ active: tag.selected }"
|
:class="{ active: tag.selected }"
|
||||||
@click="toggleTag(index)"
|
@click="toggleTag(index)"
|
||||||
>
|
>
|
||||||
{{ tag.DES }}
|
{{ tag.name }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -173,28 +180,18 @@
|
|||||||
:key="category.value"
|
:key="category.value"
|
||||||
@click="selectCategory(category.value)"
|
@click="selectCategory(category.value)"
|
||||||
>
|
>
|
||||||
<view class="category-label">{{ category.label }}</view>
|
{{ category.label }}
|
||||||
<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.uuid"
|
:key="item.id"
|
||||||
:class="{active:selectYearContent.uuid==item.uuid}"
|
|
||||||
@click="selectContent(item)"
|
@click="selectContent(item)"
|
||||||
>
|
>
|
||||||
{{item.name }}
|
{{ item.title }}
|
||||||
</view>
|
|
||||||
<view v-if="filteredContent.length === 0" class="empty-content">
|
|
||||||
<text>该分类暂无内容</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -205,7 +202,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed,reactive } from 'vue';
|
import { ref, onMounted, computed } 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"
|
||||||
@ -215,11 +212,8 @@
|
|||||||
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_down.png"
|
import downImg from "@/static/cb_up.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);
|
||||||
@ -230,18 +224,13 @@
|
|||||||
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 },
|
||||||
@ -260,170 +249,64 @@
|
|||||||
|
|
||||||
// 全部视频弹窗相关数据
|
// 全部视频弹窗相关数据
|
||||||
const showAllVideoPopup = ref(false);
|
const showAllVideoPopup = ref(false);
|
||||||
const selectedCategory = ref('全部');
|
const selectedCategory = ref('all');
|
||||||
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;
|
||||||
loadVideoData(true);
|
loadMockVideoData(true);
|
||||||
loadBannerData();
|
// 初始化banner数据
|
||||||
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();
|
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) => {
|
||||||
@ -433,60 +316,58 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 调用真实API
|
// 调用真实API
|
||||||
const selectedTags = filterTags.value.filter(tag => tag.selected).map(tag => tag.id).join(',');
|
const response = await api.getVideoList({
|
||||||
console.log('请求参数:', {
|
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
keywords: keywords.value,
|
category: activeTab.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) {
|
||||||
videoData = response.data.data || {};
|
const { list, hasMore } = 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];
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMoreData.value = hasMore !== false;
|
// 设置banner视频(第一个视频)
|
||||||
|
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?.message || '获取数据失败');
|
throw new Error(response.data.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;
|
||||||
@ -518,7 +399,7 @@
|
|||||||
refreshing.value = true;
|
refreshing.value = true;
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
hasMoreData.value = true;
|
hasMoreData.value = true;
|
||||||
loadVideoData(true);
|
loadMockVideoData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 上拉加载更多
|
// 上拉加载更多
|
||||||
@ -527,7 +408,7 @@
|
|||||||
|
|
||||||
loadMoreStatus.value = 'loading';
|
loadMoreStatus.value = 'loading';
|
||||||
currentPage.value++;
|
currentPage.value++;
|
||||||
loadVideoData();
|
loadMockVideoData();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换标签
|
// 切换标签
|
||||||
@ -536,15 +417,13 @@
|
|||||||
// 可以根据标签加载不同的数据
|
// 可以根据标签加载不同的数据
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
hasMoreData.value = true;
|
hasMoreData.value = true;
|
||||||
loadVideoData(true);
|
loadMockVideoData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 播放视频
|
// 播放视频
|
||||||
const playVideo = (video) => {
|
const playVideo = (video) => {
|
||||||
const videoId = video.id || video.uuid;
|
uni.navigateTo({
|
||||||
|
url: `/pages/videoDetail/videoDetail?id=${video.id}`
|
||||||
navTo({
|
|
||||||
url: `/pages_app/videoDetail/videoDetail?id=${videoId}`
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -557,61 +436,6 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转到患教视频列表
|
|
||||||
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 [
|
||||||
@ -644,10 +468,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const playBannerVideo = (banner) => {
|
const playBannerVideo = (banner) => {
|
||||||
const videoId = banner.id || banner.uuid;
|
uni.navigateTo({
|
||||||
|
url: `/pages/videoDetail/videoDetail?id=${banner.id}`
|
||||||
navTo({
|
|
||||||
url: `/pages_app/videoDetail/videoDetail?id=${videoId}`
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -659,34 +481,22 @@
|
|||||||
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 = () => {
|
||||||
@ -703,37 +513,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
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
|
||||||
@ -777,13 +565,6 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
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">
|
||||||
@ -916,16 +697,11 @@
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
.tab-item:first-child .tab-text{
|
.tab-item:first-child .tab-text{
|
||||||
max-width:295rpx;
|
max-width:600rpx;
|
||||||
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;
|
||||||
@ -1029,9 +805,6 @@
|
|||||||
.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 */
|
||||||
@ -1064,15 +837,18 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.play-icon {
|
||||||
|
position: absolute;
|
||||||
.video-duration {
|
top: 50%;
|
||||||
margin-top: 8rpx;
|
left: 50%;
|
||||||
}
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: rgba(0,0,0,0.6);
|
||||||
.video-duration text {
|
border-radius: 50%;
|
||||||
font-size: 22rpx;
|
width: 60rpx;
|
||||||
color: #999;
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-info {
|
.video-info {
|
||||||
@ -1081,7 +857,7 @@
|
|||||||
|
|
||||||
.video-title {
|
.video-title {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
font-weight: 400;
|
font-weight: 600;
|
||||||
color: #333;
|
color: #333;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
@ -1090,7 +866,6 @@
|
|||||||
-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 {
|
||||||
@ -1213,17 +988,6 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.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;
|
||||||
@ -1247,20 +1011,13 @@
|
|||||||
border: 2rpx solid transparent;
|
border: 2rpx solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content-item:hover {
|
||||||
|
background-color: #e8f4fd;
|
||||||
.content-item.active {
|
border-color: #4A90E2;
|
||||||
|
|
||||||
color: #8B2316;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-content {
|
.content-item:active {
|
||||||
display: flex;
|
transform: scale(0.98);
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 200rpx;
|
|
||||||
color: #999;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
}
|
||||||
// 筛选弹窗样式
|
// 筛选弹窗样式
|
||||||
.filter-popup {
|
.filter-popup {
|
||||||
@ -1276,8 +1033,8 @@
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
|
|
||||||
.filter-content {
|
.filter-content {
|
||||||
margin-top:660rpx;
|
margin-top:329rpx;
|
||||||
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;
|
||||||
@ -1295,13 +1052,11 @@
|
|||||||
.tag-item {
|
.tag-item {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
color: $gray-dark;
|
color: $gray-dark;
|
||||||
padding: 8rpx 0; /* 去掉左右padding,仅保留上下 */
|
padding: 8rpx 24rpx;
|
||||||
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;
|
||||||
@ -1318,7 +1073,6 @@
|
|||||||
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
@ -1,370 +0,0 @@
|
|||||||
<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>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@ -54,7 +54,6 @@ 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,
|
||||||
@ -70,9 +69,12 @@ 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
|
||||||
@ -85,7 +87,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: postData,
|
data: {...data,...defaultData},
|
||||||
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