12.10提交

This commit is contained in:
zoujiandong 2025-12-10 17:33:39 +08:00
parent 22104881f1
commit c86aa03f01
28 changed files with 3237 additions and 279 deletions

30
App.vue
View File

@ -27,9 +27,17 @@ export default {
options.referrerInfo.extraData &&
options.referrerInfo.extraData.targetPath
) {
uni.navigateTo({
url: options.referrerInfo.extraData.targetPath,
});
let src=options.referrerInfo.extraData.targetPath
if(src.indexOf('downLoadVideo') > -1 ){
uni.navigateTo({
url: src+'?from=mine',
});
}else{
uni.navigateTo({
url: src,
});
}
}
console.log("app传递登录信息onLaunch-------------------");
@ -43,9 +51,15 @@ export default {
plus.runtime.quit();
}
if(event.indexOf("goPage") > -1){
uni.navigateTo({
url: data,
});
if(data.indexOf('downLoadVideo') > -1){
uni.navigateTo({
url: data+'?from=mine'
});
}else{
uni.navigateTo({
url: data,
});
}
}
});
// #endif
@ -181,8 +195,8 @@ page {
/* #endif */
.uni-nav-bar-text {
font-weight: bold;
font-size: 36rpx !important;
font-size: 40rpx !important;
}
.example-info {

View File

@ -654,6 +654,9 @@ const api = {
useWelfareNum(data){
return request('/expertAPI/useWelfareNum', data, 'post', false);
},
deleteComment(data){
return request('/expertAPI/deleteComment', data, 'post', false);
},
}
export default api

View File

@ -130,6 +130,8 @@
}
.dialog-container {
position: relative;
z-index:100;
background-color: #ffffff;
border-radius: 20rpx;
width: 92%;

View File

@ -10,16 +10,16 @@
},
"pages": [
// {
// "path": "pages/loading/loading",
// "style": {
// "navigationBarTitleText": "",
// "navigationStyle": "custom",
// "app": {
// "bounce": "none"
// }
// }
// },
{
"path": "pages/loading/loading",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"app": {
"bounce": "none"
}
}
},
{
"path": "pages/index/index",
"style": {
@ -314,6 +314,36 @@
}
}
},
{
"path": "zhinanDownload/zhinanDownload",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "治疗指南",
"app": {
"bounce": "none"
}
}
},
{
"path": "pptDownload/pptDownload",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "治疗指南",
"app": {
"bounce": "none"
}
}
},
{
"path": "articleDownload/articleDownload",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "文献期刊",
"app": {
"bounce": "none"
}
}
},
{
"path": "patientVideo/patientVideo",
"style": {
@ -388,6 +418,56 @@
"bounce": "none"
}
}
},
{
"path": "consultDetail/consultDetail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
}
}
},
{
"path": "freeDetail/freeDetail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
}
}
},
{
"path": "consult/consult",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
}
}
},
{
"path": "myAnswer/myAnswer",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "我的意见",
"app": {
"bounce": "none"
}
}
},
{
"path": "newsList/newsList",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
}
}
},
{
"path": "pwdLogin/pwdLogin",
@ -441,36 +521,8 @@
// }
// },
// {
// "path": "myAnswer/myAnswer",
// "style": {
// "navigationStyle": "custom",
// "navigationBarTitleText": "我的意见",
// "app": {
// "bounce": "none"
// }
// }
// },
// {
// "path": "consultDetail/consultDetail",
// "style": {
// "navigationStyle": "custom",
// "navigationBarTitleText": "uni-app分页",
// "app": {
// "bounce": "none"
// }
// }
// },
// {
// "path": "consult/consult",
// "style": {
// "navigationStyle": "custom",
// "navigationBarTitleText": "uni-app分页",
// "app": {
// "bounce": "none"
// }
// }
// },
// {
// "path": "searchNews/searchNews",
// "style": {
@ -761,16 +813,7 @@
// }
// }
// },
// {
// "path": "freeDetail/freeDetail",
// "style": {
// "navigationStyle": "custom",
// "navigationBarTitleText": "uni-app分页",
// "app": {
// "bounce": "none"
// }
// }
// },
// {
// "path": "searchPatient/searchPatient",
// "style": {
@ -1029,16 +1072,7 @@
// }
// }
// },
// {
// "path": "newsList/newsList",
// "style": {
// "navigationStyle": "custom",
// "navigationBarTitleText": "uni-app分页",
// "app": {
// "bounce": "none"
// }
// }
// },
// {
// "path": "personInfo/personInfo",
// "style": {

View File

@ -0,0 +1,843 @@
<template>
<view class="zhinan-list-page">
<!-- 头部导航栏 -->
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="文献期刊"
@clickLeft="goBack"
color="#8B2316"
:border="false"
backgroundColor="#eeeeee"
>
</uni-nav-bar>
</view>
<!-- 使用scroll-view实现列表 -->
<scroll-view
class="guidelines-scroll-view"
scroll-y="true"
>
<!-- 指南列表 -->
<view class="guidelines-list">
<view
class="guideline-item"
v-for="(item, index) in downLoadtaskList"
:key="item.id || 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
class="view-btn"
@click.stop="viewGuideline(item)"
>查看</view>
</view>
</view>
</view>
</view>
</view>
<!-- 无数据提示 -->
<view class="no-data" v-if="downLoadtaskList.length === 0 ">
<uni-icons type="info" size="60" color="#999"></uni-icons>
<text>暂无数据</text>
</view>
</scroll-view>
</view>
<!-- 组内排序弹窗 -->
<view v-if="showInnerSort" class="popup-panel">
<view
class="popup-item"
:class="{ active: sort == 1 }"
@click.stop="chooseInnerSort(1)"
>
<text class="item-text">下载量</text>
<uni-icons
v-if="sort == 1"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
<view class="popup-divider"></view>
<view
class="popup-item"
:class="{ active: sort == 2 }"
@click.stop="chooseInnerSort(2)"
>
<text class="item-text">上传时间</text>
<uni-icons
v-if="sort == 2"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
<view class="popup-divider"></view>
<view
class="popup-item"
:class="{ active: sort == 3 }"
@click.stop="chooseInnerSort(3)"
>
<text class="item-text">标题</text>
<uni-icons
v-if="sort == 3"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
</view>
</template>
<script setup>
import { ref, onMounted,computed,nextTick} from "vue";
import api from "@/api/api.js";
import { onShow, onLoad } from "@dcloudio/uni-app";
import docUrl from "@/utils/docUrl.js";
import navTo from "@/utils/navTo.js";
import hotImg from "@/static/hot_booklist.png";
const guidelinesList = ref([]);
const isLoading = ref(false);
const hasMoreData = ref(true);
const currentPage = ref(1);
const pageSize = ref(10);
const isRefreshing = ref(false);
const keywords = ref("");
import upImg from "@/static/triangle_green_theme.png";
import downImg from "@/static/triangle_normal.png";
const loadMoreStatus = ref("more"); // 'loading', 'more', 'noMore'
const typeUuid = ref("");
const title = ref("");
const sort = ref(2);
const showInnerSort = ref(false);
const innerSortTitle = ref("上传时间");
import downloadStore from "@/store/downloadStoreFile.js";
const downloadTasks=ref([]);
const downLoadtaskList=computed(()=>{
return downloadTasks.value.filter((item)=>item.status == "completed" && item.type == "article");
});
const chooseInnerSort = (index) => {
sort.value = index;
if (index == 1) {
innerSortTitle.value = "下载量";
} else if (index == 2) {
innerSortTitle.value = "上传时间";
} else if (index == 3) {
innerSortTitle.value = "标题";
}
showInnerSort.value = false;
loadGuidelinesList(true);
};
onLoad((options) => {
});
const goGot = () => {
navTo({
url: "/pages_app/hot/hot?from=hot&typeUuid=" + typeUuid.value,
});
};
const toggleInnerSort = () => {
showInnerSort.value = !showInnerSort.value;
};
onShow(() => {
syncTasksFromStore();
// store
downloadStore.addListener((tasks) => {
downloadTasks.value = tasks;
});
//
resumeDownloadingTasks();
//
});
//
const goToSearch = () => {
const q = keywords.value ? encodeURIComponent(keywords.value) : "";
const t = title.value ? encodeURIComponent(title.value) : "";
const type = typeUuid.value
? `&typeUuid=${encodeURIComponent(typeUuid.value)}`
: "";
uni.navigateTo({
url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`,
});
// const goSearch=()=>{
// uni.sendNativeEvent('goHomeSearch', {
// msg: 'goHomeSearch'
// },ret => {
// console.log(ret);
// })
// }
};
// 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: currentPage.value,
listLength: guidelinesList.value.length,
hasMoreData: hasMoreData.value,
isLoading: isLoading.value,
});
if (
loadMoreStatus.value === "more" &&
!isRefreshing.value &&
!isLoading.value
) {
console.log("条件满足,开始加载更多数据");
loadMoreData();
} else {
console.log("条件不满足,跳过加载:", {
loadMoreStatus: loadMoreStatus.value,
isRefreshing: isRefreshing.value,
isLoading: isLoading.value,
});
}
};
//
const refreshData = async () => {
try {
currentPage.value = 1;
hasMoreData.value = true;
loadMoreStatus.value = "more";
await loadGuidelinesList(true);
uni.showToast({
title: "刷新成功",
icon: "none",
});
} catch (error) {
console.error("刷新失败:", error);
uni.showToast({
title: "刷新失败",
icon: "none",
});
}
};
//
const loadGuidelinesList = async (isRefresh = false) => {
console.log("=== loadGuidelinesList 开始 ===");
console.log("当前参数:", {
isRefresh,
page: currentPage.value,
keywords: keywords.value,
});
if (isLoading.value) return;
try {
isLoading.value = true;
loadMoreStatus.value = "loading";
const params = {
page: currentPage.value,
pageSize: pageSize.value,
type: 1, //
sort: 2,
typeUuid: typeUuid.value,
keywords: keywords.value,
};
const res = await api.searchLibraryU(params);
console.log("指南列表响应:", res);
if (res.code === 200 && res.data) {
const newData = res.data.list || res.data;
if (isRefresh) {
guidelinesList.value = newData;
console.log("刷新模式:替换列表数据");
} else {
guidelinesList.value = [...guidelinesList.value, ...newData];
console.log("加载更多:追加数据到列表");
}
//
if (newData.length < pageSize.value) {
loadMoreStatus.value = "noMore";
hasMoreData.value = false;
console.log("没有更多数据了");
} else {
loadMoreStatus.value = "more";
hasMoreData.value = true;
//
if (!isRefresh) {
currentPage.value++;
console.log(`还有更多数据,下一页: ${currentPage.value}`);
}
}
} else {
console.error("加载指南列表失败:", res.message);
loadMoreStatus.value = "noMore";
uni.showToast({
title: res.message || "加载失败",
icon: "none",
});
}
} catch (error) {
console.error("加载指南列表异常:", error);
loadMoreStatus.value = "noMore";
uni.showToast({
title: "网络异常,请重试",
icon: "none",
});
} finally {
isLoading.value = false;
console.log("=== loadGuidelinesList 结束 ===");
console.log("最终状态:", {
loadMoreStatus: loadMoreStatus.value,
page: currentPage.value,
listLength: guidelinesList.value.length,
});
}
};
//
const loadMoreData = () => {
console.log("=== loadMoreData 被调用 ===");
console.log("检查条件:", {
hasMoreData: hasMoreData.value,
isLoading: isLoading.value,
currentPage: currentPage.value,
});
if (hasMoreData.value && !isLoading.value) {
console.log("条件满足,开始加载更多数据");
loadGuidelinesList(false);
} else {
console.log("条件不满足,跳过加载更多");
}
};
//
const downloadGuideline = (item) => {
console.log("下载指南:", item);
uni.showToast({
title: "开始下载...",
icon: "none",
});
// API
// PDF
if (item.file_path) {
uni.downloadFile({
url: item.file_path,
success: (res) => {
if (res.statusCode === 200) {
uni.showToast({
title: "下载成功",
icon: "none",
});
}
},
fail: (err) => {
console.error("下载失败:", err);
uni.showToast({
title: "下载失败1",
icon: "none",
});
},
});
}
};
const downLoad = (item) => {
if(!item.path){
uni.showToast({
title: "暂无下载链接",
icon: "none",
});
return;
}
addDownloadTask({
url: docUrl + item.path,
title: item.title,
id: item.uuid,
});
};
// pdf/doc/docx/xls/xlsx/ppt/pptx/txt
const viewGuideline = (cell) => {
console.log(downloadTasks.value);
downloadTasks.value.forEach(item => {
if(item.id == cell.id) {
console.log(2222222222);
console.log(item.localPath);
plus.runtime.openFile(item.localPath, function(e) {
console.log('打开成功');
}, function(e) {
uni.showToast({
title: '打开失败:' + e.message,
icon: "none",
duration: 2000,
});
console.log('打开失败:' + e.message);
});
// uni.openDocument({
// filePath: item.localPath,
// fileType: 'pdf',
// success: () => console.log(''),
// fail: (err) => {
// uni.showModal({
// title: '',
// content: JSON.stringify(err),
// showCancel: false,
// confirmText: '',
// success: (res) => {
// if(res.confirm){
// }
// }
// });
// }
// });
// let url = "https://view.xdocin.com/view?src=" + encodeURIComponent(pdfUrl);
// uni.downloadFile({
// url: pdfUrl,
// success: (res) => {
// if (res.statusCode === 200) {
// uni.openDocument({
// filePath: res.tempFilePath, //
// fileType: 'pdf',
// success: () => console.log(''),
// fail: (err) => console.error('', err)
// });
// }
// },
// });
}
});
}
//
const goBack = () => {
uni.navigateBack();
};
//
const addDownloadTask = (item) => {
// 使store
const taskIndex = downloadStore.addTask({
...item,
type: 'zhinan',
});
//
syncTasksFromStore();
//
startDownload(taskIndex);
};
//
const startDownload = (index) => {
const taskItem = downloadStore.getTask(index);
if (!taskItem) return;
if(taskItem.status == "loading"){
return false;
};
uni.showToast({
title: "正在下载中",
icon: "none",
});
downloadStore.updateTask(index, {
status: "loading"
});
const task = uni.downloadFile({
url: taskItem.url,
success: (res1) => {
console.log("res1:"+JSON.stringify(res1));
if (res1.statusCode === 200) {
downloadStore.updateTask(index, {
status: "completed",
filePath: res1.tempFilePath,
});
uni.showToast({
title: "下载成功",
icon: "none",
});
uni.saveFile({
tempFilePath: res1.tempFilePath,
success: function (res2) {
console.log("res2:"+JSON.stringify(res2));
uni.getSavedFileInfo({
filePath: res2.savedFilePath,
success: function (res) {
console.log("res:"+JSON.stringify(res));
console.log("size:"+res.size);
downloadStore.updateTask(index, {
status: "completed",
localPath: res2.savedFilePath,
});
},
});
},
});
} else {
downloadStore.updateTask(index, {
status: "failed",
});
removeTask(index);
uni.showToast({
title: "下载失败2",
icon: "none",
});
}
},
fail: (err) => {
downloadStore.updateTask(index, {
status: "failed",
});
removeTask(index);
uni.showToast({
title: "下载失败3: " + (err.errMsg || "未知错误"),
icon: "none",
duration: 2000,
});
},
});
//
task.onProgressUpdate((update) => {
const currentTask = downloadStore.getTask(index);
if (currentTask && currentTask.status === "downloading") {
downloadStore.updateTask(index, {
progress: update.progress
});
}
});
// taskstore/
downloadStore.updateTask(index, {
task: task,
});
};
const syncTasksFromStore = () => {
downloadTasks.value = downloadStore.getTasks();
};
const removeTask = (index) => {
downloadStore.removeTask(index);
syncTasksFromStore();
};
//
const resumeDownloadingTasks = () => {
// 使 nextTick
nextTick(() => {
downloadStore.resumeDownloadingTasks((index) => {
// uni.downloadFile0
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
startDownload(index);
});
});
};
//
const testLoadMore = () => {
console.log("=== 手动测试加载更多 ===");
console.log("当前状态:", {
loadMoreStatus: loadMoreStatus.value,
hasMoreData: hasMoreData.value,
isLoading: isLoading.value,
currentPage: currentPage.value,
listLength: guidelinesList.value.length,
});
if (loadMoreStatus.value === "more" && !isLoading.value) {
loadMoreData();
} else {
uni.showToast({
title: `状态: ${loadMoreStatus.value}, 加载中: ${isLoading.value}`,
icon: "none",
duration: 2000,
});
}
};
//
const formatDate = (dateString) => {
if (!dateString) return "";
try {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
} catch (error) {
return dateString;
}
};
</script>
<style lang="scss" scoped>
//
$primary-color: #ff4757;
$text-primary: #333;
$text-secondary: #666;
$text-light: #999;
$border-color: #e0e0e0;
$bg-color: #f6f6f6;
$white: #ffffff;
.imgbox {
width: 32rpx;
margin-top: -10rpx;
}
.popup-panel {
position: fixed;
top:285rpx;
left: 0;
right: 0;
background: #fff;
z-index: 100;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.08);
}
.popup-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 28rpx 30rpx;
font-size: 30rpx;
color: #333;
}
.popup-divider {
height: 2rpx;
background: #eaeaea;
}
.popup-item.active .item-text {
color: #8b2316;
}
.current-sort {
display: flex;
align-items: center;
gap: 10rpx;
.sort-text {
font-size: 28rpx;
color: #333;
}
.sort-icon.up {
width: 0;
height: 0;
border-left: 8rpx solid transparent;
border-right: 8rpx solid transparent;
border-bottom: 12rpx solid #999;
&.active {
border-bottom-color: #ff0000;
}
}
}
.zhinan-list-page {
background-color: $bg-color;
height: 100vh;
}
.guidelines-scroll-view {
position: fixed;
top: calc(var(--status-bar-height) + 44px);
left: 0;
right: 0;
bottom: 0;
z-index: 99;
height: calc(100vh - var(--status-bar-height) - 44px);
background-color: $bg-color;
}
//
.search-container-fixed {
position: fixed;
top: calc(var(--status-bar-height) + 44px); //
left: 0;
right: 0;
z-index: 90;
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 30rpx;
background-color: $white;
gap: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
//
.filter-bar {
background-color: $white;
display: flex;
align-items: center;
border-bottom: 2px solid #eee;
.search-box {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
.search-text {
font-size: 14px;
color: #999;
}
}
.divider {
width: 1px;
height: 16px;
background-color: #999;
margin: 0 60rpx;
}
.filter-item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 3px;
font-size: 14px;
color: #999;
}
}
//
.guidelines-list {
padding: 20rpx 30rpx;
.guideline-item {
background-color: $white;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
.item-content {
flex: 1;
margin-right: 30rpx;
.item-title {
font-size: 32rpx;
color: $text-primary;
line-height: 1.5;
margin-bottom: 16rpx;
font-weight: 500;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.item-bottom {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10rpx;
.item-date {
font-size: 26rpx;
color: $text-secondary;
}
.item-action {
display: flex;
align-items: center;
.download-btn {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: rgba(255, 71, 87, 0.1);
// transition: all 0.3s ease;
// &:active {
// transform: scale(0.95);
// background-color: rgba(255, 71, 87, 0.2);
// }
}
.view-btn {
color: #8b2316;
font-size: 28rpx;
font-weight: 500;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
background-color: darken($primary-color, 10%);
}
}
}
}
}
}
}
//
.load-more-status {
padding: 20rpx 0;
text-align: center;
.loading,
.more,
.no-more {
display: flex;
align-items: center;
justify-content: center;
gap: 10rpx;
padding: 20rpx 0;
font-size: 26rpx;
color: $text-light;
}
}
//
.no-data {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
text {
margin-top: 30rpx;
font-size: 28rpx;
color: $text-light;
}
}
</style>

View File

@ -384,7 +384,7 @@ function onReachBottom(){
height: 44px;
padding: 0 16px;
position: fixed;
top: 180rpx;
top: calc(var(--status-bar-height) + 44px);
left: 0;
right: 0;
z-index: 10;
@ -397,14 +397,14 @@ function onReachBottom(){
color: #7a7a7a;
padding: 10px 0;
&.active { color: #8B2316; position: relative; }
&.active::after { content: ''; position: absolute; left: 25%; right: 25%; bottom: 2px; height: 3px; background-color: #8B2316; border-radius: 2px; }
&.active::after { content: ''; position: absolute; left: 25%; right: 25%; bottom: -1px; height: 3px; background-color: #8B2316; border-radius: 2px; }
}
}
.tabs-spacer { height: 44px; }
.list-scroll {
flex: 1;
position: fixed;
top: 268rpx;
top: calc(var(--status-bar-height) + 44px + 44px);
bottom: 136rpx;
padding: 8px 0px 0 0px;
margin: 20rpx rpx 0;

View File

@ -58,7 +58,17 @@
<view class="doctor-cell" v-for="item in questionInfo.AnswerList" :key="item.answer_uuid">
<view class="doctor-card">
<view class="doctor-info">
<image :src="doctorReply.avatar" class="doctor-avatar" />
<up-image :src="docUrl+item.photo" mode="aspectFill"
:loadingIcon="lazyImg"
:errorIcon="lazyImg"
:lazy-load="true" class="doctor-avatar" width="90rpx" height="90rpx" radius="10rpx">
<template #error>
<image :src="lazyImg" mode="aspectFill" height="90rpx" width="90rpx" radius="10rpx"></image>
</template>
<template v-slot:loading>
<image :src="lazyImg" mode="aspectFill" height="90rpx" width="90rpx" radius="10rpx"></image>
</template>
</up-image>
<view class="doctor-details">
<view class="doctor-name">{{ item.realname }}</view>
<view class="hospital-time-row">
@ -72,7 +82,7 @@
<text class="reply-text">{{ item.note }}</text>
</view>
<view class="reply-content" style="background:none;pading:0">
<view class="reply-content" style="background:none;padding:0;">
<view v-if="item.imgs" class="reply-images">
<image
v-for="(img, idx) in item.imgs.split(',')"
@ -116,6 +126,7 @@ import navTo from '@/utils/navTo.js'
import { onLoad,onShow } from '@dcloudio/uni-app'
import docUrl from '@/utils/docUrl'
import api from "@/api/api.js"
import lazyImg from "@/static/avastar.png"
const uuid = ref('');
const step1_uuid = ref('');
const answer_uuid = ref('');
@ -337,7 +348,7 @@ function editQuestion() {
background-color: #ffffff;
border-radius: 16rpx;
margin-bottom: 24rpx;
padding: 0 30rpx;
margin: 0 30rpx;
.user-info {
display: flex;
@ -477,9 +488,9 @@ function editQuestion() {
margin-bottom: 24rpx;
.doctor-avatar {
width: 80rpx;
height: 80rpx;
border-radius: 40rpx;
width: 90rpx;
height: 90rpx;
border-radius: 10rpx;
margin-right: 24rpx;
}
@ -490,6 +501,7 @@ function editQuestion() {
font-size: 32rpx;
color: #333;
font-weight: 500;
margin-left: 8rpx;
margin-bottom: 8rpx;
}

View File

@ -39,7 +39,7 @@
</view>
<!-- 内容列表 -->
<scroll-view class="content-scroll" scroll-y>
<scroll-view class="content-scroll" scroll-y :scroll-top="scrollTop">
<view v-if="currentList.length === 0" class="empty-state">
<text>暂无数据</text>
</view>
@ -144,7 +144,7 @@
<script setup>
import { ref, computed, onMounted, nextTick } from "vue";
import downloadStore from "@/store/downloadStoreVideo.js";
import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
import { onLoad, onShow,onUnload,onBackPress} from "@dcloudio/uni-app";
import playImg from "@/static/down_true.png";
import pauseImg from "@/static/down_false.png";
import navTo from "@/utils/navTo";
@ -156,6 +156,7 @@ const selectedItems = ref([]);
//
const activeTab = ref("completed"); // completed: , downloading:
const isEditMode = ref(false);
const scrollTop = ref(0);
const storageInfo = ref({
total: "461.31G",
available: "312.92G",
@ -204,7 +205,12 @@ const clearAll=()=>{
const isItemSelected = (item) => {
return selectedItems.value.includes(item.id);
}
onBackPress(() => {
if(from.value){
plus.runtime.quit();
return true;
}
});
//
const toggleSelectItem = (item) => {
const index = selectedItems.value.indexOf(item.id);
@ -237,13 +243,11 @@ const currentList = computed(() => {
});
//
const goBack = () => {
uni.navigateBack({
fail() {
uni.redirectTo({
url: "/pages/index/index",
});
},
});
if(from.value){
plus.runtime.quit();
}else{
uni.navigateBack()
};
};
const switchTab = (tab) => {
@ -252,6 +256,14 @@ const switchTab = (tab) => {
//
selectedItems.value = [];
isAllSelect.value = false;
//
if (tab === 'downloading') {
// 0tick0
scrollTop.value = 0.01;
nextTick(() => {
scrollTop.value = 0;
});
}
};
const toggleEdit = () => {
@ -330,8 +342,14 @@ const formatSize = (size) => {
//
return size;
};
onLoad(() => {
const from = ref('');
onLoad((options) => {
if(options.from){
from.value = options.from;
}
if(options.type){
switchTab('downloading')
}
// store
syncTasksFromStore();
// store

View File

@ -324,7 +324,6 @@ function editQuestion() {
border-radius: 16rpx;
margin-bottom: 24rpx;
padding: 0 30rpx;
margin: 0 30rpx;
.user-info {
display: flex;
align-items: center;

View File

@ -42,7 +42,8 @@
<view class="item-action">
<view class="download-btn" @click.stop="downLoad(item)" v-if="!downLoadtaskList.includes(item.uuid)">
<!-- <up-icon name="download" color="#8D2316" size="28" ></up-icon> -->
<uni-icons type="arrow-down" size="26" color="#8D2316"></uni-icons>
<up-image :src="downIng" width="35rpx" height="35rpx"></up-image>
<!-- <uni-icons type="arrow-down" size="26" color="#8D2316"></uni-icons> -->
</view>
<view
v-else
@ -70,10 +71,11 @@
</view>
<!-- 无数据提示 -->
<view class="no-data" v-if="guidelinesList.length === 0 && !isLoading">
<empty v-if="guidelinesList.length === 0 && !isLoading"></empty>
<!-- <view class="no-data" v-if="guidelinesList.length === 0 && !isLoading">
<uni-icons type="info" size="60" color="#999"></uni-icons>
<text>暂无诊疗指南数据</text>
</view>
</view> -->
</scroll-view>
</view>
@ -87,6 +89,7 @@ import docUrl from "@/utils/docUrl.js"
import navTo from "@/utils/navTo.js"
import hotImg from "@/static/hot_booklist.png"
import navBar from "@/components/navBar/navBar.vue"
import empty from "@/components/empty/empty.vue"
//
const guidelinesList = ref([])
const isLoading = ref(false)
@ -97,6 +100,7 @@ const isRefreshing = ref(false)
const keywords=ref('');
import upImg from "@/static/triangle_green_theme.png"
import downImg from "@/static/triangle_normal.png"
import downIng from "@/static/icon_library_down.png";
const loadMoreStatus = ref('more') // 'loading', 'more', 'noMore'
const typeUuid=ref('');
const title=ref('');
@ -160,7 +164,7 @@ onShow(() => {
if(from.value){
top10ByType();
}else{
loadGuidelinesList(true)
loadGuidelinesList(false)
}
}
})
@ -257,15 +261,16 @@ const loadGuidelinesList = async (isRefresh = false) => {
try {
isLoading.value = true
loadMoreStatus.value = 'loading'
let expertUuid=uni.getStorageSync('userInfo').uuid;
const params = {
page: currentPage.value,
pageSize: pageSize.value,
expertUUid:expertUuid,
type: 1, //
sort:2,
name:name.value,
typeUuid:typeUuid.value,
keywords:keywords.value
keyWords:keywords.value
}
const res = await api.searchLibraryU(params)
@ -283,7 +288,7 @@ const loadGuidelinesList = async (isRefresh = false) => {
}
//
if (newData.length < pageSize.value) {
if (newData.length < res.data.pageSize) {
loadMoreStatus.value = 'noMore'
hasMoreData.value = false
console.log('没有更多数据了');
@ -382,6 +387,8 @@ const downLoad = (item) => {
url: docUrl + item.path,
title: item.title,
id: item.uuid,
type: 'zhinan',
releaseTime: item.releaseTime,
});
};
// pdf/doc/docx/xls/xlsx/ppt/pptx/txt

View File

@ -1,5 +1,25 @@
<template>
<navBar title="患教视频" />
<!-- <navBar title="患教视频" /> -->
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="患教视频"
@clickLeft="goBack"
color="#8B2316"
:border="false"
backgroundColor="#eeeeee"
>
<template #right>
<view class="nav-actions">
<view class="collect-img" @click="goSearch">
<image class="img-icon" :src="searchImg" mode="aspectFill" />
</view>
</view>
</template>
</uni-nav-bar>
</view>
<view class="video-page">
<!-- Header -->
@ -12,7 +32,7 @@
@click="showAllVideoPopup=!showAllVideoPopup"
>
<up-image :src="isAllActive?allOnImg:allImg" width="30rpx" height="30rpx" ></up-image>
<text class="tab-text" :class="{active:isAllActive}">{{typeName}}</text>
<text class="tab-text" :class="{active:isAllActive}" style="margin-top:4rpx;">{{formatName(typeName)}}</text>
<up-image :src="isAllActive?selectOnImg:selectImg" width="30rpx" height="30rpx" ></up-image>
</view>
<view class="right">
@ -25,6 +45,7 @@
<up-image :src="sort==2?upImg:downImg" width="20rpx" height="26rpx" ></up-image>
</view>
</view>
<view class="bar"></view>
<view
class="tab-item"
@click="showFilterPopup"
@ -58,7 +79,32 @@
@click="playVideo(video)"
>
<view class="video-thumbnail">
<image :src="docUrl + video.imgpath" mode="aspectFill"></image>
<up-image
:src="docUrl + video.imgpath"
class="poster-image"
mode="aspectFill"
:loadingIcon="lazyImg"
:errorIcon="lazyImg"
:lazy-load="true"
width="100%"
height="220rpx"
>
<template #error>
<image
:src="lazyImg"
class="video-thumbnail"
mode="aspectFill"
></image>
</template>
<template v-slot:loading>
<image
:src="lazyImg"
class="video-thumbnail"
mode="aspectFill"
></image>
</template>
</up-image>
<!-- <image :src="docUrl + video.imgpath" mode="aspectFill"></image> -->
</view>
<view class="video-info">
<view class="video-title">{{video.title || video.name}}</view>
@ -126,7 +172,7 @@
:key="item.uuid"
@click="selectCategory(item.uuid)"
>
{{ item.name }}
{{ formatName(item.name) }}
</view>
<view v-if="videoTypeList.length === 0" class="empty-content">
<text>暂无数据</text>
@ -139,7 +185,7 @@
<script setup>
import { ref, onMounted, computed,reactive } from 'vue';
import { onShow } from "@dcloudio/uni-app";
import { onShow,onLoad} from "@dcloudio/uni-app";
import api from '@/api/api.js';
import allImg from "@/static/video_all.png"
import allOnImg from "@/static/video_select.png"
@ -154,6 +200,7 @@
import empty from '@/components/empty/empty.vue';
import formatNumber from '@/utils/formatNumber.js';
import navBar from '@/components/navBar/navBar.vue';
import lazyImg from "@/static/default_video.png";
const isAllActive=ref(false)
//
const videoList = ref([]);
@ -165,6 +212,7 @@
const pageSize = ref(10);
const hasMoreData = ref(true);
const filteredContent=ref([])
import searchImg from "@/static/search.png";
const sort =ref(2);
const keywords=ref('');
const typeUuid=ref('0e5fa3d76b8047528fdd3c452b77e9dd');
@ -187,15 +235,19 @@
isAllActive.value=true;
closeAllVideoPopup();
currentPage.value = 1;
videoList.value = [];
hasMoreData.value = true;
loadVideoData();
}
const videoTypeList=ref([]);
const videoTypeList=ref([{
name:'全部视频',
uuid:''
}]);
const patientVideoNew=async ()=>{
const res=await api.patientVideoNew();
if(res.code==200){
videoTypeList.value=res.data;
videoTypeList.value=videoTypeList.value.concat(res.data).filter(item=>!item.name.includes('BMS患者端'));
}
}
//
@ -203,7 +255,7 @@
});
onShow(() => {
onLoad(() => {
// API
currentPage.value = 1;
hasMoreData.value = true;
@ -211,7 +263,18 @@
loadVideoData();
patientVideoNew();
});
const formatName = (name) => {
let nameStr=name.substring(0,4);
let lateStr=name.substring(4,name.length);
let index = nameStr.lastIndexOf("-");
if (index > -1) {
return name.substring(index+1,4)+lateStr;
}
return name;
};
//
//
@ -244,7 +307,7 @@
page: currentPage.value,
pageSize: pageSize.value,
keywords: keywords.value,
sort:sort.value,
sort:sort.value.toString(),
typeUuid:typeUuid.value,
});
@ -329,12 +392,6 @@
//
const goSearch = () => {
uni.navigateTo({
url: '/pages_app/search/search'
});
};
//
@ -442,23 +499,30 @@
//
currentPage.value = 1;
hasMoreData.value = true;
videoList.value = [];
loadVideoData(true);
};
//
const goBack = () => {
uni.navigateBack({
fail() {
uni.redirectTo({
url: '/pages/index/index'
});
}
});
uni.navigateBack();
}
const goSearch = () => {
uni.sendNativeEvent(
"goHomeSearch",
{
msg: "patientVideo",
},
(ret) => {
console.log(ret);
}
);
}
const toggleSort = () => {
sort.value = sort.value === 1 ? 2 : 1; // 1=, 2=
currentPage.value = 1;
hasMoreData.value = true;
videoList.value = [];
loadVideoData();
};
@ -505,7 +569,16 @@
display: flex;
align-items: center;
}
.img-icon {
width: 34rpx;
height: 34rpx;
}
.nav-actions {
display: flex;
align-items: center;
justify-content: center;
}
.header-title {
font-size: 36rpx;
font-weight: 600;
@ -516,7 +589,7 @@
.scroll-view {
position: fixed;
bottom: 0rpx;
height: calc(100vh - var(--status-bar-height) - 44px); /* 固定高度,减去导航栏高度 */
height: calc(100vh - var(--status-bar-height) - 65px); /* 固定高度,减去导航栏高度 */
background-color: #f5f5f5;
top: calc(var(--status-bar-height) + 65px); /* 为导航栏留出空间 */
}
@ -527,8 +600,9 @@
.filter-tabs {
background-color: #fff;
display: flex;
justify-content: space-between;
padding: 30rpx 30rpx;
padding: 15rpx 30rpx;
}
.tab-item {
@ -543,6 +617,7 @@
}
.right{
display: flex;
align-items: center;
}
.tab-item.active .tab-text {
@ -556,7 +631,7 @@
color: #666;
}
.tab-item:first-child .tab-text{
max-width:295rpx;
max-width:250rpx;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
@ -715,7 +790,7 @@
.popup-content {
width: 100%;
background-color: #fff;
height:calc(100vh - 272rpx);
height:calc(100vh - 242rpx);
overflow-y: scroll;
}
@ -780,18 +855,18 @@
z-index: 9999;
.filter-content {
margin-top:272rpx;
margin-top:calc(var(--status-bar-height) + 44px + 90rpx);
overflow-y:scroll;
background-color: $white;
// border-radius: 20rpx 20rpx 0 0;
padding: 20rpx 30rpx 60rpx;
width: 100%;
height: calc(100vh - 272rpx);
height: calc(100vh - calc(var(--status-bar-height) + 44px + 90rpx));
.filter-tags {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 60rpx;
max-height: 65vh;
overflow-y: auto;
@ -801,6 +876,7 @@
color: $gray-dark;
padding: 8rpx 0; /* 去掉左右padding仅保留上下 */
border-radius: 30rpx;
margin:8rpx;
font-size: 26rpx;
border: 2rpx solid #efefef;
transition: all 0.3s ease;
@ -852,5 +928,13 @@
}
}
}
}
.bar {
width: 2rpx;
margin: 0 26rpx 0 6rpx;
height: 32rpx;
background-color: #666;
}
</style>

View File

@ -0,0 +1,843 @@
<template>
<view class="zhinan-list-page">
<!-- 头部导航栏 -->
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="课件文档"
@clickLeft="goBack"
color="#8B2316"
:border="false"
backgroundColor="#eeeeee"
>
</uni-nav-bar>
</view>
<!-- 使用scroll-view实现列表 -->
<scroll-view
class="guidelines-scroll-view"
scroll-y="true"
>
<!-- 指南列表 -->
<view class="guidelines-list">
<view
class="guideline-item"
v-for="(item, index) in downLoadtaskList"
:key="item.id || 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
class="view-btn"
@click.stop="viewGuideline(item)"
>查看</view>
</view>
</view>
</view>
</view>
</view>
<!-- 无数据提示 -->
<view class="no-data" v-if="downLoadtaskList.length === 0 ">
<uni-icons type="info" size="60" color="#999"></uni-icons>
<text>暂无数据</text>
</view>
</scroll-view>
</view>
<!-- 组内排序弹窗 -->
<view v-if="showInnerSort" class="popup-panel">
<view
class="popup-item"
:class="{ active: sort == 1 }"
@click.stop="chooseInnerSort(1)"
>
<text class="item-text">下载量</text>
<uni-icons
v-if="sort == 1"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
<view class="popup-divider"></view>
<view
class="popup-item"
:class="{ active: sort == 2 }"
@click.stop="chooseInnerSort(2)"
>
<text class="item-text">上传时间</text>
<uni-icons
v-if="sort == 2"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
<view class="popup-divider"></view>
<view
class="popup-item"
:class="{ active: sort == 3 }"
@click.stop="chooseInnerSort(3)"
>
<text class="item-text">标题</text>
<uni-icons
v-if="sort == 3"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
</view>
</template>
<script setup>
import { ref, onMounted,computed,nextTick} from "vue";
import api from "@/api/api.js";
import { onShow, onLoad } from "@dcloudio/uni-app";
import docUrl from "@/utils/docUrl.js";
import navTo from "@/utils/navTo.js";
import hotImg from "@/static/hot_booklist.png";
const guidelinesList = ref([]);
const isLoading = ref(false);
const hasMoreData = ref(true);
const currentPage = ref(1);
const pageSize = ref(10);
const isRefreshing = ref(false);
const keywords = ref("");
import upImg from "@/static/triangle_green_theme.png";
import downImg from "@/static/triangle_normal.png";
const loadMoreStatus = ref("more"); // 'loading', 'more', 'noMore'
const typeUuid = ref("");
const title = ref("");
const sort = ref(2);
const showInnerSort = ref(false);
const innerSortTitle = ref("上传时间");
import downloadStore from "@/store/downloadStoreFile.js";
const downloadTasks=ref([]);
const downLoadtaskList=computed(()=>{
return downloadTasks.value.filter((item)=>item.status == "completed" && item.type == "ppt");
});
const chooseInnerSort = (index) => {
sort.value = index;
if (index == 1) {
innerSortTitle.value = "下载量";
} else if (index == 2) {
innerSortTitle.value = "上传时间";
} else if (index == 3) {
innerSortTitle.value = "标题";
}
showInnerSort.value = false;
loadGuidelinesList(true);
};
onLoad((options) => {
});
const goGot = () => {
navTo({
url: "/pages_app/hot/hot?from=hot&typeUuid=" + typeUuid.value,
});
};
const toggleInnerSort = () => {
showInnerSort.value = !showInnerSort.value;
};
onShow(() => {
syncTasksFromStore();
// store
downloadStore.addListener((tasks) => {
downloadTasks.value = tasks;
});
//
resumeDownloadingTasks();
//
});
//
const goToSearch = () => {
const q = keywords.value ? encodeURIComponent(keywords.value) : "";
const t = title.value ? encodeURIComponent(title.value) : "";
const type = typeUuid.value
? `&typeUuid=${encodeURIComponent(typeUuid.value)}`
: "";
uni.navigateTo({
url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`,
});
// const goSearch=()=>{
// uni.sendNativeEvent('goHomeSearch', {
// msg: 'goHomeSearch'
// },ret => {
// console.log(ret);
// })
// }
};
// 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: currentPage.value,
listLength: guidelinesList.value.length,
hasMoreData: hasMoreData.value,
isLoading: isLoading.value,
});
if (
loadMoreStatus.value === "more" &&
!isRefreshing.value &&
!isLoading.value
) {
console.log("条件满足,开始加载更多数据");
loadMoreData();
} else {
console.log("条件不满足,跳过加载:", {
loadMoreStatus: loadMoreStatus.value,
isRefreshing: isRefreshing.value,
isLoading: isLoading.value,
});
}
};
//
const refreshData = async () => {
try {
currentPage.value = 1;
hasMoreData.value = true;
loadMoreStatus.value = "more";
await loadGuidelinesList(true);
uni.showToast({
title: "刷新成功",
icon: "none",
});
} catch (error) {
console.error("刷新失败:", error);
uni.showToast({
title: "刷新失败",
icon: "none",
});
}
};
//
const loadGuidelinesList = async (isRefresh = false) => {
console.log("=== loadGuidelinesList 开始 ===");
console.log("当前参数:", {
isRefresh,
page: currentPage.value,
keywords: keywords.value,
});
if (isLoading.value) return;
try {
isLoading.value = true;
loadMoreStatus.value = "loading";
const params = {
page: currentPage.value,
pageSize: pageSize.value,
type: 1, //
sort: 2,
typeUuid: typeUuid.value,
keywords: keywords.value,
};
const res = await api.searchLibraryU(params);
console.log("指南列表响应:", res);
if (res.code === 200 && res.data) {
const newData = res.data.list || res.data;
if (isRefresh) {
guidelinesList.value = newData;
console.log("刷新模式:替换列表数据");
} else {
guidelinesList.value = [...guidelinesList.value, ...newData];
console.log("加载更多:追加数据到列表");
}
//
if (newData.length < pageSize.value) {
loadMoreStatus.value = "noMore";
hasMoreData.value = false;
console.log("没有更多数据了");
} else {
loadMoreStatus.value = "more";
hasMoreData.value = true;
//
if (!isRefresh) {
currentPage.value++;
console.log(`还有更多数据,下一页: ${currentPage.value}`);
}
}
} else {
console.error("加载指南列表失败:", res.message);
loadMoreStatus.value = "noMore";
uni.showToast({
title: res.message || "加载失败",
icon: "none",
});
}
} catch (error) {
console.error("加载指南列表异常:", error);
loadMoreStatus.value = "noMore";
uni.showToast({
title: "网络异常,请重试",
icon: "none",
});
} finally {
isLoading.value = false;
console.log("=== loadGuidelinesList 结束 ===");
console.log("最终状态:", {
loadMoreStatus: loadMoreStatus.value,
page: currentPage.value,
listLength: guidelinesList.value.length,
});
}
};
//
const loadMoreData = () => {
console.log("=== loadMoreData 被调用 ===");
console.log("检查条件:", {
hasMoreData: hasMoreData.value,
isLoading: isLoading.value,
currentPage: currentPage.value,
});
if (hasMoreData.value && !isLoading.value) {
console.log("条件满足,开始加载更多数据");
loadGuidelinesList(false);
} else {
console.log("条件不满足,跳过加载更多");
}
};
//
const downloadGuideline = (item) => {
console.log("下载指南:", item);
uni.showToast({
title: "开始下载...",
icon: "none",
});
// API
// PDF
if (item.file_path) {
uni.downloadFile({
url: item.file_path,
success: (res) => {
if (res.statusCode === 200) {
uni.showToast({
title: "下载成功",
icon: "none",
});
}
},
fail: (err) => {
console.error("下载失败:", err);
uni.showToast({
title: "下载失败1",
icon: "none",
});
},
});
}
};
const downLoad = (item) => {
if(!item.path){
uni.showToast({
title: "暂无下载链接",
icon: "none",
});
return;
}
addDownloadTask({
url: docUrl + item.path,
title: item.title,
id: item.uuid,
});
};
// pdf/doc/docx/xls/xlsx/ppt/pptx/txt
const viewGuideline = (cell) => {
console.log(downloadTasks.value);
downloadTasks.value.forEach(item => {
if(item.id == cell.id) {
console.log(2222222222);
console.log(item.localPath);
plus.runtime.openFile(item.localPath, function(e) {
console.log('打开成功');
}, function(e) {
uni.showToast({
title: '打开失败:' + e.message,
icon: "none",
duration: 2000,
});
console.log('打开失败:' + e.message);
});
// uni.openDocument({
// filePath: item.localPath,
// fileType: 'pdf',
// success: () => console.log(''),
// fail: (err) => {
// uni.showModal({
// title: '',
// content: JSON.stringify(err),
// showCancel: false,
// confirmText: '',
// success: (res) => {
// if(res.confirm){
// }
// }
// });
// }
// });
// let url = "https://view.xdocin.com/view?src=" + encodeURIComponent(pdfUrl);
// uni.downloadFile({
// url: pdfUrl,
// success: (res) => {
// if (res.statusCode === 200) {
// uni.openDocument({
// filePath: res.tempFilePath, //
// fileType: 'pdf',
// success: () => console.log(''),
// fail: (err) => console.error('', err)
// });
// }
// },
// });
}
});
}
//
const goBack = () => {
uni.navigateBack();
};
//
const addDownloadTask = (item) => {
// 使store
const taskIndex = downloadStore.addTask({
...item,
type: 'zhinan',
});
//
syncTasksFromStore();
//
startDownload(taskIndex);
};
//
const startDownload = (index) => {
const taskItem = downloadStore.getTask(index);
if (!taskItem) return;
if(taskItem.status == "loading"){
return false;
};
uni.showToast({
title: "正在下载中",
icon: "none",
});
downloadStore.updateTask(index, {
status: "loading"
});
const task = uni.downloadFile({
url: taskItem.url,
success: (res1) => {
console.log("res1:"+JSON.stringify(res1));
if (res1.statusCode === 200) {
downloadStore.updateTask(index, {
status: "completed",
filePath: res1.tempFilePath,
});
uni.showToast({
title: "下载成功",
icon: "none",
});
uni.saveFile({
tempFilePath: res1.tempFilePath,
success: function (res2) {
console.log("res2:"+JSON.stringify(res2));
uni.getSavedFileInfo({
filePath: res2.savedFilePath,
success: function (res) {
console.log("res:"+JSON.stringify(res));
console.log("size:"+res.size);
downloadStore.updateTask(index, {
status: "completed",
localPath: res2.savedFilePath,
});
},
});
},
});
} else {
downloadStore.updateTask(index, {
status: "failed",
});
removeTask(index);
uni.showToast({
title: "下载失败2",
icon: "none",
});
}
},
fail: (err) => {
downloadStore.updateTask(index, {
status: "failed",
});
removeTask(index);
uni.showToast({
title: "下载失败3: " + (err.errMsg || "未知错误"),
icon: "none",
duration: 2000,
});
},
});
//
task.onProgressUpdate((update) => {
const currentTask = downloadStore.getTask(index);
if (currentTask && currentTask.status === "downloading") {
downloadStore.updateTask(index, {
progress: update.progress
});
}
});
// taskstore/
downloadStore.updateTask(index, {
task: task,
});
};
const syncTasksFromStore = () => {
downloadTasks.value = downloadStore.getTasks();
};
const removeTask = (index) => {
downloadStore.removeTask(index);
syncTasksFromStore();
};
//
const resumeDownloadingTasks = () => {
// 使 nextTick
nextTick(() => {
downloadStore.resumeDownloadingTasks((index) => {
// uni.downloadFile0
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
startDownload(index);
});
});
};
//
const testLoadMore = () => {
console.log("=== 手动测试加载更多 ===");
console.log("当前状态:", {
loadMoreStatus: loadMoreStatus.value,
hasMoreData: hasMoreData.value,
isLoading: isLoading.value,
currentPage: currentPage.value,
listLength: guidelinesList.value.length,
});
if (loadMoreStatus.value === "more" && !isLoading.value) {
loadMoreData();
} else {
uni.showToast({
title: `状态: ${loadMoreStatus.value}, 加载中: ${isLoading.value}`,
icon: "none",
duration: 2000,
});
}
};
//
const formatDate = (dateString) => {
if (!dateString) return "";
try {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
} catch (error) {
return dateString;
}
};
</script>
<style lang="scss" scoped>
//
$primary-color: #ff4757;
$text-primary: #333;
$text-secondary: #666;
$text-light: #999;
$border-color: #e0e0e0;
$bg-color: #f6f6f6;
$white: #ffffff;
.imgbox {
width: 32rpx;
margin-top: -10rpx;
}
.popup-panel {
position: fixed;
top:285rpx;
left: 0;
right: 0;
background: #fff;
z-index: 100;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.08);
}
.popup-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 28rpx 30rpx;
font-size: 30rpx;
color: #333;
}
.popup-divider {
height: 2rpx;
background: #eaeaea;
}
.popup-item.active .item-text {
color: #8b2316;
}
.current-sort {
display: flex;
align-items: center;
gap: 10rpx;
.sort-text {
font-size: 28rpx;
color: #333;
}
.sort-icon.up {
width: 0;
height: 0;
border-left: 8rpx solid transparent;
border-right: 8rpx solid transparent;
border-bottom: 12rpx solid #999;
&.active {
border-bottom-color: #ff0000;
}
}
}
.zhinan-list-page {
background-color: $bg-color;
height: 100vh;
}
.guidelines-scroll-view {
position: fixed;
top: calc(var(--status-bar-height) + 44px);
left: 0;
right: 0;
bottom: 0;
z-index: 99;
height: calc(100vh - var(--status-bar-height) - 44px);
background-color: $bg-color;
}
//
.search-container-fixed {
position: fixed;
top: calc(var(--status-bar-height) + 44px); //
left: 0;
right: 0;
z-index: 90;
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 30rpx;
background-color: $white;
gap: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
//
.filter-bar {
background-color: $white;
display: flex;
align-items: center;
border-bottom: 2px solid #eee;
.search-box {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
.search-text {
font-size: 14px;
color: #999;
}
}
.divider {
width: 1px;
height: 16px;
background-color: #999;
margin: 0 60rpx;
}
.filter-item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 3px;
font-size: 14px;
color: #999;
}
}
//
.guidelines-list {
padding: 20rpx 30rpx;
.guideline-item {
background-color: $white;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
.item-content {
flex: 1;
margin-right: 30rpx;
.item-title {
font-size: 32rpx;
color: $text-primary;
line-height: 1.5;
margin-bottom: 16rpx;
font-weight: 500;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.item-bottom {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10rpx;
.item-date {
font-size: 26rpx;
color: $text-secondary;
}
.item-action {
display: flex;
align-items: center;
.download-btn {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: rgba(255, 71, 87, 0.1);
// transition: all 0.3s ease;
// &:active {
// transform: scale(0.95);
// background-color: rgba(255, 71, 87, 0.2);
// }
}
.view-btn {
color: #8b2316;
font-size: 28rpx;
font-weight: 500;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
background-color: darken($primary-color, 10%);
}
}
}
}
}
}
}
//
.load-more-status {
padding: 20rpx 0;
text-align: center;
.loading,
.more,
.no-more {
display: flex;
align-items: center;
justify-content: center;
gap: 10rpx;
padding: 20rpx 0;
font-size: 26rpx;
color: $text-light;
}
}
//
.no-data {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
text {
margin-top: 30rpx;
font-size: 28rpx;
color: $text-light;
}
}
</style>

View File

@ -103,7 +103,7 @@
if (loading.value && !isRefresh) return;
loading.value = true;
try {
const response = await api.videoByTypeNew({
const response = await api.patientVideoByJingHuaNew({
page: currentPage.value,
pageSize: pageSize.value,
typeUuid:typeUuid.value,

View File

@ -11,7 +11,7 @@
>
<template #right>
<view class="nav-actions">
<view class="collect-img" @click="goSearch">
<view class="collect-img" @click="goSearch" style="margin-right: 20rpx;">
<image class="img-icon" :src="searchImg" mode="aspectFill" />
</view>
<view class="collect-img" @click="goMeet">
@ -74,7 +74,7 @@
mode="aspectFill"
></image>
</template>
<template #loading>
<template v-slot:loading>
<image
:src="lazyVideoImg"
class="banner-image"
@ -96,8 +96,8 @@
width="30rpx"
height="30rpx"
></up-image>
<text class="tab-text" :class="{ active: isAllActive }">{{
typeName
<text class="tab-text" :class="{ active: isAllActive }" style="margin-top:4rpx;">{{
formatName(typeName)
}}</text>
<up-image
:src="isAllActive ? selectOnImg : selectImg"
@ -171,13 +171,20 @@
mode="aspectFill"
></image>
</template>
<template #loading>
<template v-slot:loading>
<image
:src="lazyImg"
class="poster-image"
mode="aspectFill"
></image>
</template>
</template>
<!-- <template #loading>
<image
:src="lazyImg"
class="poster-image"
mode="aspectFill"
></image>
</template> -->
</up-image>
</view>
<view class="video-info">
@ -273,11 +280,12 @@
:key="item.uuid"
:class="{ active: selectYearContent.uuid == item.uuid }"
@click="selectContent(item)"
>
{{ formatName(item.name) }}
</view>
<view v-if="filteredContent.length === 0" class="empty-content">
<text>该分类暂无内容</text>
<text>暂无内容</text>
</view>
</view>
</view>
@ -289,7 +297,7 @@
<script setup>
import { ref, onMounted, computed, reactive } from "vue";
import { onShow,onBackPress} from "@dcloudio/uni-app";
import { onShow,onBackPress,onLoad} from "@dcloudio/uni-app";
import api from "@/api/api.js";
import allImg from "@/static/video_all.png";
import allOnImg from "@/static/video_select.png";
@ -332,19 +340,19 @@ const showFilter = ref(false);
const yearList = ref([]);
const selectYearContent = reactive({});
onBackPress(() => {
try {
uni.sendNativeEvent(
"goTabbarPage",
{
msg: "home",
},
(ret) => {
console.log(ret);
}
);
} catch (e) {
console.log(e);
}
// try {
// uni.sendNativeEvent(
// "goTabbarPage",
// {
// msg: "home",
// },
// (ret) => {
// console.log(ret);
// }
// );
// } catch (e) {
// console.log(e);
// }
plus.runtime.quit();
return true;
});
@ -352,7 +360,7 @@ const goSearch = () => {
uni.sendNativeEvent(
"goHomeSearch",
{
msg: "goHomeSearch",
msg: "meetVideo",
},
(ret) => {
console.log(ret);
@ -395,13 +403,18 @@ const videoTypesData = ref([]);
//
onMounted(() => {});
const formatName = (name) => {
let index = name.lastIndexOf("-");
let nameStr=name.substring(0,4);
let lateStr=name.substring(4,name.length);
let index = nameStr.lastIndexOf("-");
if (index > -1) {
return name.substring(index + 1, name.length);
return name.substring(index+1,4)+lateStr;
}
return name;
};
onShow(() => {
onLoad(() => {
// API
currentPage.value = 1;
hasMoreData.value = true;
@ -454,7 +467,7 @@ const loadVideoTypes = async () => {
if (response.code == 200) {
yearList.value = response.data;
let all = [{ uuid: "", name: "全部视频" }];
filteredContent.value = all.concat(response.data[0].list);
filteredContent.value = all.concat(response.data[0].list).filter(item=>!item.name.includes('BMS专家端'));
console.log(33);
let arr = response.data.map((item) => {
return {
@ -767,8 +780,8 @@ const selectCategory = async (categoryValue) => {
console.log(yearList.value[i]);
filteredContent.value =
categoryValue == "全部"
? all.concat(yearList.value[i].list)
: yearList.value[i].list;
? all.concat(yearList.value[i].list).filter(item=>!item.name.includes('BMS专家端'))
: yearList.value[i].list.filter(item=>!item.name.includes('BMS专家端'));
console.log(filteredContent.value);
break;
}
@ -877,13 +890,14 @@ const getMockVideoData = (page, size) => {
};
//
const goBack = () => {
uni.navigateBack({
fail() {
uni.redirectTo({
url: "/pages/index/index",
});
},
});
// uni.navigateBack({
// fail() {
// uni.redirectTo({
// url: "/pages/index/index",
// });
// },
// });
plus.runtime.quit();
};
const toggleSort = () => {
sort.value = sort.value === 1 ? 2 : 1; // 1=, 2=
@ -909,14 +923,14 @@ $border-radius-small: 6px;
$padding: 15px;
$padding-small: 10px;
.img-icon {
width: 42rpx;
height: 42rpx;
width: 34rpx;
height: 34rpx;
}
.nav-actions {
display: flex;
align-items: center;
justify-content: center;
gap: 20rpx;
}
.video-page {
background-color: #f5f5f5;
@ -934,7 +948,7 @@ $padding-small: 10px;
justify-content: center;
align-items: center;
color: #fff;
font-size: 30rpx;
font-size: 32rpx;
}
}
@ -1015,7 +1029,7 @@ $padding-small: 10px;
background-color: #fff;
display: flex;
justify-content: space-between;
padding: 30rpx 30rpx;
padding: 15rpx 30rpx;
}
.tab-item {
@ -1289,7 +1303,7 @@ $padding-small: 10px;
.popup-content {
width: 100%;
margin-top: calc(var(--status-bar-height) + 44px + 400rpx + 117rpx);
margin-top: calc(var(--status-bar-height) + 44px + 400rpx + 90rpx);
height: calc(100vh - var(--status-bar-height) - 44px - 400rpx - 117rpx);
background-color: #fff;
@ -1406,7 +1420,7 @@ $padding-small: 10px;
z-index: 9999;
.filter-content {
margin-top: calc(var(--status-bar-height) + 44px + 400rpx + 117rpx);
margin-top: calc(var(--status-bar-height) + 44px + 400rpx + 90rpx);
overflow-y: scroll;
background-color: $white;
// border-radius: 20rpx 20rpx 0 0;
@ -1417,7 +1431,7 @@ $padding-small: 10px;
.filter-tags {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 60rpx;
max-height: 65vh;
overflow-y: auto;
@ -1427,6 +1441,7 @@ $padding-small: 10px;
color: $gray-dark;
padding: 8rpx 0; /* 去掉左右padding仅保留上下 */
border-radius: 30rpx;
margin:8rpx;
font-size: 26rpx;
border: 2rpx solid #efefef;
transition: all 0.3s ease;

View File

@ -11,7 +11,7 @@
>
<template #right>
<view class="nav-actions" v-if="from != 'download'">
<view class="collect-img" @click="shareToggle">
<view class="collect-img" @click="shareToggle" style="margin-right: 20rpx;">
<image class="share-img-icon" :src="shareIcon" mode="aspectFill" />
</view>
<view class="collect-img" @click="toCollection">
@ -26,16 +26,17 @@
</uni-nav-bar>
</view>
<!-- <video
v-if="showVideo && !isAndroid"
<video
v-if="showVideo"
class="player-wrapper"
:style="{width: videoWidth + 'px'}"
:src="videoSrc"
controls
object-fit="contain"
:autoplay="false"
></video> -->
<sunny-video
@error="onVideoError"
></video>
<!-- <sunny-video
v-if="showVideo"
class="player-wrapper"
:src="videoSrc"
@ -43,7 +44,7 @@
:videoWidth="videoWidth"
:seekTime="0"
@fullscreenchange="onFullscreenChange"
/>
/> -->
<!-- 标签切换 -->
<cover-view class="tabs" v-if="from != 'download'" :style="{ opacity:isFullScreen?0:1, width: videoWidth + 'px' }" >
@ -62,7 +63,9 @@
>
评论
<cover-view class="tab-line" v-if="activeTab === 'comment'"></cover-view>
</cover-view>
<cover-view class="line"></cover-view>
</cover-view>
<view class="video-detail-page" v-if="from != 'download'">
<!-- <scroll-view
@ -97,7 +100,7 @@
<view class="content">{{ c.content }}</view>
<view class="time">{{ c.time }}</view>
<view v-if="c.children && c.children.length" class="child-list">
<view class="child-item" v-for="(r, i) in c.children" :key="i">
<view class="child-item" v-for="(r, i) in getVisibleChildren(c)" :key="i">
<image
class="avatar small"
:src="r.avatar"
@ -109,9 +112,19 @@
<view class="time">{{ r.time }}</view>
</view>
</view>
<view
class="toggle-children"
v-if="c.children.length > 3"
@click="toggleChildren(c)"
>
{{ c.showAllChildren ? "--收起" : "--展开更多回复" }}
</view>
</view>
</view>
<view class="reply-btn" @click="onReply(c)">回复</view>
<uni-icons type="trash" size="30" color="#8b2316" @click="onDelete(c)" v-if="current_user_id==c.user_uuid"></uni-icons>
<!-- <view class="reply-btn" @click="onReply(c)"v-if="current_user_id==c.user_uuid">删除</view> -->
<view class="reply-btn" @click="onReply(c)" v-else>回复</view>
</view>
<!-- 加载状态/没有更多 -->
<view v-if="loading" class="list-loading">加载中...</view>
@ -124,7 +137,7 @@
</view>
</view>
<!-- 底部区域信息页为下载条评论页为上传图片+输入+发送 -->
<!-- 底部区域信息页为下载条评论页为上传图片+输入+发送 -->
<view v-if="activeTab === 'info' && from != 'download'" class="bottom-download" @click="onDownload">
<text class="download-text" v-if="!hasDownload"
>点击下载<text v-if="!isVideoDownloadRecord && welfareNum <= 0"
@ -167,6 +180,17 @@
@close="notEnoughVisible = false"
@confirm="notEnoughConfirm"
></unidialog>
<!-- 删除确认弹窗 -->
<view v-if="showDeleteModal" class="delete-modal-mask" @click="closeDeleteModal">
<view class="delete-modal-content" @click.stop>
<view class="delete-modal-title">确认删除</view>
<view class="delete-modal-text">确定要删除这条评论吗</view>
<view class="delete-modal-buttons">
<view class="delete-modal-btn cancel-btn" @click="closeDeleteModal">取消</view>
<view class="delete-modal-btn confirm-btn" @click="confirmDelete">删除</view>
</view>
</view>
</view>
<!-- 分享弹窗 -->
<uni-popup ref="shareRef" type="bottom" safeArea backgroundColor="#fff">
<view class="share-popup">
@ -200,7 +224,7 @@
<script setup>
import { ref, nextTick } from "vue";
import uniVideo from "@/components/uniVideo/uniVideo.vue";
//import uniVideo from "@/components/uniVideo/uniVideo.vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import unidialog from "@/components/dialog/dialog.vue";
import collectImg from "@/static/icon_book_collect_sel.png";
@ -211,6 +235,7 @@ import wxImg from "@/static/share_weixin.png";
import friendImg from "@/static/share_wxc.png";
import logoImg from "@/static/weiboShare.png";
import isAndroid from "@/utils/platform.js";
import avastarImg from "@/static/avastar.png";
import api from "@/api/api";
import docUrl from "@/utils/docUrl";
import navTo from "@/utils/navTo";
@ -225,6 +250,9 @@ const pointContent = ref("");
const notEnoughVisible = ref(false);
const notEnoughContent = ref("");
const welfareNum = ref(0);
//
const showDeleteModal = ref(false);
const currentDeleteItem = ref(null);
const showVideo = ref(false);
const videoWidth = ref(375);
const hasDownload = ref(false);
@ -233,11 +261,14 @@ let downList = uni.getStorageSync("downLoadVideo") || [];
const downLoadList = ref(downList);
const isFullScreen = ref(false);
//import DomVideoPlayer from 'uniapp-video-player'
import sunnyVideo from "@/uni_modules/sunny-video/components/sunny-video/sunny-video.vue";
//import sunnyVideo from "@/uni_modules/sunny-video/components/sunny-video/sunny-video.vue";
import downloadStore from "@/store/downloadStoreVideo.js";
const downloadTasks = ref([]);
let userInfo = uni.getStorageSync("userInfo");
const current_user_id = ref(userInfo.uuid);
//
const addDownloadTask = (item) => {
// 使store
const taskIndex = downloadStore.addTask(item);
//
@ -256,6 +287,7 @@ const startDownload = (index) => {
const taskItem = downloadStore.getTask(index);
if (!taskItem) return;
hasDownload.value = true;
isVideoDownloadRecord.value=true;
downLoadStatus.value = 'loading';
const task = uni.downloadFile({
url: taskItem.url,
@ -339,9 +371,14 @@ const syncTasksFromStore = () => {
const notEnoughConfirm = () => {
notEnoughVisible.value = false;
navTo({
url: "/pages_app/buyPoint/buyPoint",
uni.sendNativeEvent('buyPointPage', {
msg: 'buyPointPage'
},ret => {
console.log(ret);
});
// navTo({
// url: "/pages_app/buyPoint/buyPoint",
// });
};
const pointConfirm = () => {
pointVisible.value = false;
@ -377,12 +414,6 @@ const onLoadedmetadata = (e) => {
showCancel: false,
});
};
const onVideoError = (e) => {
uni.showModal({
content: JSON.stringify(e),
showCancel: false,
});
};
//
const pageParams = ref({});
const useWelfareNum = async () => {
@ -402,6 +433,13 @@ const useWelfareNum = async () => {
});
}
};
const onVideoError = (e) => {
// uni.showToast({
// title: "",
// icon: "none",
// });
videoSrc.value= videoSrc.value.replace('.mp4', '.m3u8');
};
const videoDetail = async () => {
const res = await api.videoDetail({ video_uuid: video_uuid.value });
if (res.code == 200) {
@ -409,13 +447,16 @@ const videoDetail = async () => {
videoInfo.value = res.video;
//hasDownload.value = downLoadList.value.includes(video_uuid.value);
let vid = res.video.polyv_uuid;
let vid =res.video.polyv_uuid || extractPolyvVid(res.video.content);
console.log(222222);
console.log(vid);
let uuid = vid.substring(0, 10);
let index = vid.lastIndexOf("_");
let f = vid.substring(index - 1, index);
let id = vid.substring(0, index + 1);
//videoSrc.value = 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4';
videoSrc.value = `http://mpv.videocc.net/${uuid}/${f}/${id}1.mp4`;
console.log(videoSrc.value);
showVideo.value = true;
shareLink.value =
otherHost +
@ -487,7 +528,7 @@ const videoCommentListV2 = async () => {
});
if (res && res.code == 200 && Array.isArray(res.data)) {
const mapped = res.data.map(mapComment);
commentList.value = mapped.reverse();
commentList.value = mapped;
noMore.value = true;
} else {
noMore.value = true;
@ -528,6 +569,7 @@ onShow(() => {
console.log('runing');
console.log(downloadTasks.value[i].status);
hasDownload.value = true;
isVideoDownloadRecord.value=true;
if(downloadTasks.value[i].status == 'completed') {
downLoadStatus.value = 'completed';
}else if(downloadTasks.value[i].status == 'downloading') {
@ -535,13 +577,10 @@ onShow(() => {
title: '视频缓存中',
icon: 'none',
});
hasDownload.value = true;
downLoadStatus.value = 'loading';
}else if(downloadTasks.value[i].status == 'paused') {
hasDownload.value = true;
downLoadStatus.value = 'loading';
}else if(downloadTasks.value[i].status == 'failed') {
hasDownload.value = true;
downLoadStatus.value = 'loading';
}
}
@ -789,6 +828,7 @@ const switchTab = (tab) => {
};
const payVideoDownload = async () => {
const res = await api.payVideoDownload({ video_uuid: video_uuid.value });
console.log(res);
if (res.code == 200) {
addDownloadTask({
url: videoSrc.value,
@ -805,9 +845,13 @@ const payVideoDownload = async () => {
};
const onDownload = () => {
if(videoSrc.value.includes('.m3u8')) {
uni.showToast({ title: "该视频不支持下载", icon: "none" });
return;
}
if (!isVideoDownloadRecord.value) {
if(welfareNum.value <= 0) {
pointContent.value = `当前需要${videoInfo.value.point}积分兑换,若删除可以再次缓存`;
pointContent.value = `该视频需要${videoInfo.value.point}积分兑换,若删除可以再次免费缓存`;
uni.getNetworkType({
success: function (res) {
if (res.networkType != "none") {
@ -834,9 +878,15 @@ const onDownload = () => {
} else {
if (hasDownload.value) {
navTo({
url: "/pages_app/downLoadVideo/downLoadVideo",
});
if(downLoadStatus.value == 'completed') {
navTo({
url: "/pages_app/downLoadVideo/downLoadVideo",
});
} else {
navTo({
url: "/pages_app/downLoadVideo/downLoadVideo?type=2",
});
}
} else {
addDownloadTask({
url: videoSrc.value,
@ -865,6 +915,12 @@ const addCommentV2 = async () => {
}
};
const onReply = (c) => {
console.log('onReply');
console.log(c);
if(!c.user_uuid){
uni.showToast({ title: "该评论无法回复", icon: "none" });
return;
}
navTo({
url:
"/pages_app/reply/reply?comment_partent=" +
@ -875,6 +931,15 @@ const onReply = (c) => {
video_uuid.value,
});
};
const extractPolyvVid = (htmlStr) => {
const vidRegex = /["']?vid["']?\s*:\s*["']([^"']+)["']/i;
//
const match = htmlStr.match(vidRegex);
// vidnull
return match ? match[1] : null;
}
//
const commentText = ref("");
@ -886,28 +951,66 @@ const sendComment = () => {
addCommentV2();
};
//
const getVisibleChildren = (comment) => {
if (!comment.children || !comment.children.length) return [];
return comment.showAllChildren ? comment.children : comment.children.slice(0, 3);
};
const toggleChildren = (comment) => {
comment.showAllChildren = !comment.showAllChildren;
//
commentList.value = [...commentList.value];
};
//
const page = ref(1);
const pageSize = ref(10);
const loading = ref(false);
const noMore = ref(false);
const onDelete = (c) => {
currentDeleteItem.value = c;
showDeleteModal.value = true;
};
//
const closeDeleteModal = () => {
showDeleteModal.value = false;
currentDeleteItem.value = null;
};
//
const confirmDelete = async () => {
console.log(currentDeleteItem.value);
if (!currentDeleteItem.value) return;
const res = await api.deleteComment({
uuid: currentDeleteItem.value.comment_uuid,
});
if (res.code == 200) {
uni.showToast({ title: "删除成功", icon: "none" });
videoCommentListV2();
closeDeleteModal();
}
};
const onScrollToLower = async () => {
if (activeTab.value !== "comment" || loading.value || noMore.value) return;
// push
};
const toFullUrl = (p) => {
if (!p) return "/static/icon_home_my_public.png";
if (!p) return avastarImg;
return p.startsWith("http") ? p : docUrl + p;
};
const mapComment = (item) => {
return {
avatar: toFullUrl(item.photo || ""),
name: item.name || "匿名",
name: item.name || "账号已注销",
content: item.content || "",
time: item.create_date || "",
user_uuid: item.user_uuid || "",
comment_uuid: item.comment_uuid || "",
showAllChildren: false,
children: Array.isArray(item.childs) ? item.childs.map(mapComment) : [],
};
};
@ -920,9 +1023,6 @@ $bg-color: #f7f7f7;
$text-primary: #333;
$text-secondary: #666;
$theme-color: #8b2316;
.collect-img {
/* margin-top:50rpx; */
}
.navbox {
:deep(.uni-navbar__header-btns-right) {
width: 100px !important;
@ -943,11 +1043,11 @@ $theme-color: #8b2316;
.nav-actions {
display: flex;
align-items: center;
gap: 20rpx;
}
.video-detail-page {
border-top: 2rpx solid #cccccc;
background: $bg-color;
overflow: hidden;
}
@ -979,8 +1079,15 @@ $theme-color: #8b2316;
width: 100%;
z-index: 99;
z-index: 66;
.line{
position: absolute;
height:2rpx;
bottom:0;
background: #cccccc;
width: 100%;
z-index:999;
}
.tab {
width: 120rpx;
position: relative;
@ -1037,7 +1144,7 @@ $theme-color: #8b2316;
}
.intro {
// background: #fff;
padding: 40rpx 28rpx 100rpx;
padding: 60rpx 28rpx 100rpx;
// margin-top: calc(var(--status-bar-height) + 44px + 220px + 88rpx);
// height: calc(100vh - var(--status-bar-height) - 44px - 220px - 88rpx);
// overflow-y: scroll;
@ -1082,7 +1189,7 @@ $theme-color: #8b2316;
// height: calc(100vh - var(--status-bar-height) - 44px - 220px - 88rpx);
// overflow-y: scroll;
// padding-bottom: 100rpx;
padding: 20rpx 20rpx 40rpx;
padding: 60rpx 20rpx 40rpx;
.empty {
text-align: center;
@ -1161,6 +1268,11 @@ $theme-color: #8b2316;
border-radius: 12rpx;
margin-right: 16rpx;
}
.toggle-children {
color: #8b2316;
font-size: 26rpx;
margin-top: 12rpx;
}
}
.bottom-spacer {
@ -1184,7 +1296,7 @@ $theme-color: #8b2316;
}
.download-text {
color: #fff;
font-size: 30rpx;
font-size: 32rpx;
}
}
@ -1303,4 +1415,78 @@ $theme-color: #8b2316;
.share-cancel:active {
background-color: #f5f5f5;
}
//
.delete-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.delete-modal-content {
width: 600rpx;
background-color: #fff;
border-radius: 24rpx;
padding: 60rpx 40rpx 40rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
}
.delete-modal-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
text-align: center;
margin-bottom: 30rpx;
}
.delete-modal-text {
font-size: 28rpx;
color: #666;
text-align: center;
line-height: 1.6;
margin-bottom: 50rpx;
word-break: break-all;
}
.delete-modal-buttons {
display: flex;
gap: 20rpx;
}
.delete-modal-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: 500;
transition: all 0.3s ease;
}
.cancel-btn {
background-color: #f5f5f5;
color: #333;
&:active {
background-color: #e0e0e0;
}
}
.confirm-btn {
background-color: #8b2316;
color: #fff;
&:active {
background-color: #6b1a0f;
}
}
</style>

View File

@ -16,17 +16,17 @@
<!-- 固定搜索栏 -->
<view class="search-container-fixed filter-bar">
<view class="search-box" @click="goSearch">
<uni-icons type="search" size="16" color="#999"></uni-icons>
<uni-icons type="search" size="22" color="#999"></uni-icons>
<text class="search-text">搜索</text>
</view>
<view class="divider"></view>
<view class="filter-item" @click="showFilterPopup">
<text>筛选</text>
<text :class="{active: keywords}">筛选</text>
<up-image
:src="isFilterActive ? filterOn : filter"
width="30rpx"
height="30rpx"
:src="keywords ? filterOn : filter"
width="36rpx"
height="36rpx"
></up-image>
</view>
</view>
@ -40,11 +40,23 @@
@click="enterCategory(item)"
>
<view class="item-image">
<image
<up-image
:src="docUrl + item.imgs"
mode="widthFix"
width="100%"
height="320rpx"
class="category-icon"
></image>
:loadingIcon="lazyImg"
:errorIcon="lazyImg"
:lazy-load="true"
>
<template #error>
<image :src="lazyImg" class="category-icon" mode="widthFix"></image>
</template>
<template v-slot:loading>
<image :src="lazyImg" class="category-icon" mode="widthFix"></image>
</template>
</up-image>
</view>
<view class="item-content">
<text class="category-title">{{ item.name }}</text>
@ -280,7 +292,7 @@
<script setup>
import { ref, onMounted } from "vue";
import { onShow, onBackPress } from "@dcloudio/uni-app";
import { onShow, onBackPress,onLoad} from "@dcloudio/uni-app";
import upImg from "@/static/cb_up.png";
import downImg from "@/static/cb_up.png";
import filter from "@/static/cb_screen_no.png";
@ -298,6 +310,8 @@ import api from "@/api/api.js";
import docUrl from "@/utils/docUrl.js";
import navTo from "@/utils/navTo.js";
import navBar from "@/components/navBar/navBar.vue";
import lazyImg from "@/static/zhinanLazy.png";
import throttle from "@/utils/throttle.js";
const total = ref(0);
const tab = ref("zhinan");
//
@ -327,9 +341,7 @@ onBackPress(() => {
});
//
onMounted(() => {
loadGuideTypes();
loadSearchLibrary();
loadGuideTags();
});
const showFilter = ref(false);
//
@ -340,7 +352,7 @@ const goSearch = () => {
uni.sendNativeEvent(
"goHomeSearch",
{
msg: "goHomeSearch",
msg: "zhinan",
},
(ret) => {
console.log(ret);
@ -352,8 +364,17 @@ const hideFilterPopup = () => {
};
const toggleTag = (index) => {
filterTags.value[index].selected = !filterTags.value[index].selected;
isFilterActive.value = filterTags.value.some((tag) => tag.selected);
const tag = filterTags.value[index];
// 3
if (!tag.selected && filterTags.value.filter((t) => t.selected).length >= 3) {
uni.showToast({
title: "最多选择3个标签",
icon: "none",
});
return;
}
tag.selected = !tag.selected;
isFilterActive.value = filterTags.value.some((item) => item.selected);
};
const resetFilter = () => {
@ -369,29 +390,35 @@ const resetFilter = () => {
//loadVideoData(true);
};
const confirmFilter = () => {
const selectedTags = filterTags.value.filter((tag) => tag.selected);
console.log("选中的筛选标签:", selectedTags);
for (var i = 0; i < selectedTags.length; i++) {
if (keywords.value) {
keywords.value += "," + selectedTags[i].NAME;
} else {
keywords.value = selectedTags[i].NAME;
}
navTo({
url: "/pages_app/hot/hot?keywords=" + encodeURIComponent(keywords.value),
});
}
const confirmFilter = throttle(() => {
isFilterActive.value = true;
hideFilterPopup();
const selectedTags = filterTags.value.filter((tag) => tag.selected);
let words="";
console.log("选中的筛选标签:", selectedTags);
for (let i = 0; i < selectedTags.length; i++) {
if (words) {
words += "," + selectedTags[i].NAME;
} else {
words= selectedTags[i].NAME;
}
}
keywords.value=words;
console.log(1111111);
console.log('看看执行了几次');
navTo({
url: "/pages_app/hot/hot?keywords="+encodeURIComponent(keywords.value)
});
//
};
onShow(() => {
//
},1000);
onLoad(() => {
loadGuideTypes();
loadSearchLibrary();
loadGuideTags();
});
onShow(() => {
});
// guideType
const loadGuideTypes = async () => {
@ -429,14 +456,14 @@ const loadGuideTags = async () => {
const res = await api.guideTag({
type: 3,
});
console.log("指南标签API响应:", res);
if (res && res.code === 200 && res.data) {
// API
filterTags.value = res.data.map((tag) => ({
...tag,
selected: false,
}));
console.log("指南标签加载成功:", filterTags.value);
}
} catch (e) {
console.error("加载指南标签失败:", e);
@ -641,7 +668,7 @@ $accent-color: #4a90e2;
gap: 5px;
.search-text {
font-size: 14px;
font-size:36rpx;
color: $gray-medium;
}
}
@ -659,8 +686,15 @@ $accent-color: #4a90e2;
align-items: center;
justify-content: center;
gap: 3px;
font-size: 14px;
font-size: 36rpx;
color: #999;
text{
margin-top:-1rpx;
&.active {
color: #8b2316;
}
}
}
}
@ -1112,7 +1146,7 @@ $accent-color: #4a90e2;
.filter-tags {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 60rpx;
max-height: 65vh;
overflow-y: auto;
@ -1123,6 +1157,7 @@ $accent-color: #4a90e2;
padding: 8rpx 0; /* 去掉左右padding仅保留上下 */
border-radius: 30rpx;
font-size: 26rpx;
margin:8rpx 5rpx;
border: 2rpx solid #efefef;
transition: all 0.3s ease;
width: 152rpx; /* 固定宽度 */

View File

@ -0,0 +1,823 @@
<template>
<view class="zhinan-list-page">
<!-- 头部导航栏 -->
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="诊疗指南"
@clickLeft="goBack"
color="#8B2316"
:border="false"
backgroundColor="#eeeeee"
>
</uni-nav-bar>
</view>
<!-- 使用scroll-view实现列表 -->
<scroll-view
class="guidelines-scroll-view"
scroll-y="true"
>
<!-- 指南列表 -->
<view class="guidelines-list">
<view
class="guideline-item"
v-for="(item, index) in downLoadtaskList"
:key="item.id || index"
@longpress="handleLongPress(item)"
>
<!-- 指南信息 -->
<view class="item-content">
<view class="item-title">{{ item.title }}</view>
<view class="item-bottom">
<view class="item-date">{{ formatDate(item.releaseTime) }}</view>
<!-- 操作按钮 -->
<view class="item-action">
<view
class="view-btn"
@click.stop="viewGuideline(item)"
>查看</view>
</view>
</view>
</view>
</view>
</view>
<!-- 无数据提示 -->
<view class="no-data" v-if="downLoadtaskList.length === 0 ">
<uni-icons type="info" size="60" color="#999"></uni-icons>
<text>暂无数据</text>
</view>
</scroll-view>
</view>
<!-- 删除确认弹窗 -->
<view v-if="showDeleteModal" class="delete-modal-mask" @click="closeDeleteModal">
<view class="delete-modal-content" @click.stop>
<view class="delete-modal-title">确认删除</view>
<view class="delete-modal-text">确定要删除"{{ currentDeleteItem?.title }}"</view>
<view class="delete-modal-buttons">
<view class="delete-modal-btn cancel-btn" @click="closeDeleteModal">取消</view>
<view class="delete-modal-btn confirm-btn" @click="confirmDelete">删除</view>
</view>
</view>
</view>
<!-- 组内排序弹窗 -->
<view v-if="showInnerSort" class="popup-panel">
<view
class="popup-item"
:class="{ active: sort == 1 }"
@click.stop="chooseInnerSort(1)"
>
<text class="item-text">下载量</text>
<uni-icons
v-if="sort == 1"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
<view class="popup-divider"></view>
<view
class="popup-item"
:class="{ active: sort == 2 }"
@click.stop="chooseInnerSort(2)"
>
<text class="item-text">上传时间</text>
<uni-icons
v-if="sort == 2"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
<view class="popup-divider"></view>
<view
class="popup-item"
:class="{ active: sort == 3 }"
@click.stop="chooseInnerSort(3)"
>
<text class="item-text">标题</text>
<uni-icons
v-if="sort == 3"
type="checkmarkempty"
color="#8B2316"
size="22"
></uni-icons>
</view>
</view>
</template>
<script setup>
import { ref, onMounted,computed,nextTick} from "vue";
import api from "@/api/api.js";
import { onShow, onLoad,onBackPress } from "@dcloudio/uni-app";
import docUrl from "@/utils/docUrl.js";
import navTo from "@/utils/navTo.js";
import hotImg from "@/static/hot_booklist.png";
const guidelinesList = ref([]);
const isLoading = ref(false);
const hasMoreData = ref(true);
const currentPage = ref(1);
const pageSize = ref(10);
const isRefreshing = ref(false);
const keywords = ref("");
import upImg from "@/static/triangle_green_theme.png";
import downImg from "@/static/triangle_normal.png";
const loadMoreStatus = ref("more"); // 'loading', 'more', 'noMore'
const typeUuid = ref("");
const title = ref("");
const sort = ref(2);
const showInnerSort = ref(false);
const innerSortTitle = ref("上传时间");
import downloadStore from "@/store/downloadStoreFile.js";
const downloadTasks=ref([]);
const downLoadtaskList=computed(()=>{
return downloadTasks.value.filter((item)=>item.status == "completed" && item.type == "zhinan");
});
//
const showDeleteModal = ref(false);
const currentDeleteItem = ref(null);
onLoad((options) => {
// if(options.action){
// uni.redirectTo({
// url: "/pages_app/zhinanDownload/zhinanDownload"
// });
// }
});
onBackPress(() => {
// try {
// uni.sendNativeEvent(
// "goMyDownloadPage",
// {
// msg: "goMyDownloadPage",
// },
// (ret) => {
// console.log(ret);
// }
// );
// } catch (e) {
// console.log(e);
// }
plus.runtime.quit();
return true;
});
const toggleInnerSort = () => {
showInnerSort.value = !showInnerSort.value;
};
onShow(() => {
syncTasksFromStore();
// store
downloadStore.addListener((tasks) => {
downloadTasks.value = tasks;
});
//
resumeDownloadingTasks();
//
});
//
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: "none",
});
}
},
fail: (err) => {
console.error("下载失败:", err);
uni.showToast({
title: "下载失败1",
icon: "none",
});
},
});
}
};
const downLoad = (item) => {
if(!item.path){
uni.showToast({
title: "暂无下载链接",
icon: "none",
});
return;
}
addDownloadTask({
url: docUrl + item.path,
title: item.title,
id: item.uuid,
});
};
// pdf/doc/docx/xls/xlsx/ppt/pptx/txt
const viewGuideline = (cell) => {
console.log(downloadTasks.value);
downloadTasks.value.forEach(item => {
if(item.id == cell.id) {
console.log(2222222222);
console.log(item.localPath);
plus.runtime.openFile(item.localPath, function(e) {
console.log('打开成功');
}, function(e) {
uni.showToast({
title: '打开失败:' + e.message,
icon: "none",
duration: 2000,
});
console.log('打开失败:' + e.message);
});
// uni.openDocument({
// filePath: item.localPath,
// fileType: 'pdf',
// success: () => console.log(''),
// fail: (err) => {
// uni.showModal({
// title: '',
// content: JSON.stringify(err),
// showCancel: false,
// confirmText: '',
// success: (res) => {
// if(res.confirm){
// }
// }
// });
// }
// });
// let url = "https://view.xdocin.com/view?src=" + encodeURIComponent(pdfUrl);
// uni.downloadFile({
// url: pdfUrl,
// success: (res) => {
// if (res.statusCode === 200) {
// uni.openDocument({
// filePath: res.tempFilePath, //
// fileType: 'pdf',
// success: () => console.log(''),
// fail: (err) => console.error('', err)
// });
// }
// },
// });
}
});
}
//
const goBack = () => {
//uni.navigateBack();
// try {
// uni.sendNativeEvent(
// "goMyDownloadPage",
// {
// msg: "goMyDownloadPage",
// },
// (ret) => {
// console.log(ret);
// }
// );
// } catch (e) {
// console.log(e);
// }
plus.runtime.quit();
};
//
const addDownloadTask = (item) => {
// 使store
const taskIndex = downloadStore.addTask({
...item,
type: 'zhinan',
});
//
syncTasksFromStore();
//
startDownload(taskIndex);
};
//
const startDownload = (index) => {
const taskItem = downloadStore.getTask(index);
if (!taskItem) return;
if(taskItem.status == "loading"){
return false;
};
uni.showToast({
title: "正在下载中",
icon: "none",
});
downloadStore.updateTask(index, {
status: "loading"
});
const task = uni.downloadFile({
url: taskItem.url,
success: (res1) => {
console.log("res1:"+JSON.stringify(res1));
if (res1.statusCode === 200) {
downloadStore.updateTask(index, {
status: "completed",
filePath: res1.tempFilePath,
});
uni.showToast({
title: "下载成功",
icon: "none",
});
uni.saveFile({
tempFilePath: res1.tempFilePath,
success: function (res2) {
console.log("res2:"+JSON.stringify(res2));
uni.getSavedFileInfo({
filePath: res2.savedFilePath,
success: function (res) {
console.log("res:"+JSON.stringify(res));
console.log("size:"+res.size);
downloadStore.updateTask(index, {
status: "completed",
localPath: res2.savedFilePath,
});
},
});
},
});
} else {
downloadStore.updateTask(index, {
status: "failed",
});
removeTask(index);
uni.showToast({
title: "下载失败2",
icon: "none",
});
}
},
fail: (err) => {
downloadStore.updateTask(index, {
status: "failed",
});
removeTask(index);
uni.showToast({
title: "下载失败3: " + (err.errMsg || "未知错误"),
icon: "none",
duration: 2000,
});
},
});
//
task.onProgressUpdate((update) => {
const currentTask = downloadStore.getTask(index);
if (currentTask && currentTask.status === "downloading") {
downloadStore.updateTask(index, {
progress: update.progress
});
}
});
// taskstore/
downloadStore.updateTask(index, {
task: task,
});
};
const syncTasksFromStore = () => {
downloadTasks.value = downloadStore.getTasks();
};
const removeTask = (index) => {
downloadStore.removeTask(index);
syncTasksFromStore();
};
//
const handleLongPress = (item) => {
currentDeleteItem.value = item;
showDeleteModal.value = true;
};
//
const closeDeleteModal = () => {
showDeleteModal.value = false;
currentDeleteItem.value = null;
};
//
const confirmDelete = () => {
if (!currentDeleteItem.value) return;
// store id task index
const allTasks = downloadStore.getTasks();
const taskIndex = allTasks.findIndex(task => task.id === currentDeleteItem.value.id);
if (taskIndex !== -1) {
const taskItem = downloadStore.getTask(taskIndex);
//
if (taskItem && taskItem.localPath) {
uni.removeSavedFile({
filePath: taskItem.localPath,
success: () => {
console.log('本地文件删除成功');
},
fail: (err) => {
console.log('本地文件删除失败:', err);
// 使
},
complete: () => {
//
removeTask(taskIndex);
uni.showToast({
title: "删除成功",
icon: "none",
duration: 1500,
});
closeDeleteModal();
}
});
} else {
//
removeTask(taskIndex);
uni.showToast({
title: "删除成功",
icon: "success",
duration: 1500,
});
closeDeleteModal();
}
} else {
uni.showToast({
title: "删除失败,未找到任务",
icon: "none",
duration: 1500,
});
closeDeleteModal();
}
};
//
const resumeDownloadingTasks = () => {
// 使 nextTick
nextTick(() => {
downloadStore.resumeDownloadingTasks((index) => {
// uni.downloadFile0
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
startDownload(index);
});
});
};
//
const formatDate = (dateString) => {
if (!dateString) return "";
try {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
} catch (error) {
return dateString;
}
};
</script>
<style lang="scss" scoped>
//
$primary-color: #ff4757;
$text-primary: #333;
$text-secondary: #666;
$text-light: #999;
$border-color: #e0e0e0;
$bg-color: #f6f6f6;
$white: #ffffff;
.imgbox {
width: 32rpx;
margin-top: -10rpx;
}
.popup-panel {
position: fixed;
top:285rpx;
left: 0;
right: 0;
background: #fff;
z-index: 100;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.08);
}
.popup-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 28rpx 30rpx;
font-size: 30rpx;
color: #333;
}
.popup-divider {
height: 2rpx;
background: #eaeaea;
}
.popup-item.active .item-text {
color: #8b2316;
}
.current-sort {
display: flex;
align-items: center;
gap: 10rpx;
.sort-text {
font-size: 28rpx;
color: #333;
}
.sort-icon.up {
width: 0;
height: 0;
border-left: 8rpx solid transparent;
border-right: 8rpx solid transparent;
border-bottom: 12rpx solid #999;
&.active {
border-bottom-color: #ff0000;
}
}
}
.zhinan-list-page {
background-color: $bg-color;
height: 100vh;
}
.guidelines-scroll-view {
position: fixed;
top: calc(var(--status-bar-height) + 44px);
left: 0;
right: 0;
bottom: 0;
z-index: 99;
height: calc(100vh - var(--status-bar-height) - 44px);
background-color: $bg-color;
}
//
.search-container-fixed {
position: fixed;
top: calc(var(--status-bar-height) + 44px); //
left: 0;
right: 0;
z-index: 90;
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 30rpx;
background-color: $white;
gap: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
//
.filter-bar {
background-color: $white;
display: flex;
align-items: center;
border-bottom: 2px solid #eee;
.search-box {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
.search-text {
font-size: 14px;
color: #999;
}
}
.divider {
width: 1px;
height: 16px;
background-color: #999;
margin: 0 60rpx;
}
.filter-item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 3px;
font-size: 14px;
color: #999;
}
}
//
.guidelines-list {
padding: 20rpx 30rpx;
.guideline-item {
background-color: $white;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
.item-content {
flex: 1;
margin-right: 30rpx;
.item-title {
font-size: 32rpx;
color: $text-primary;
line-height: 1.5;
margin-bottom: 16rpx;
font-weight: 500;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.item-bottom {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10rpx;
.item-date {
font-size: 26rpx;
color: $text-secondary;
}
.item-action {
display: flex;
align-items: center;
.download-btn {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: rgba(255, 71, 87, 0.1);
// transition: all 0.3s ease;
// &:active {
// transform: scale(0.95);
// background-color: rgba(255, 71, 87, 0.2);
// }
}
.view-btn {
color: #8b2316;
font-size: 28rpx;
font-weight: 500;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
background-color: darken($primary-color, 10%);
}
}
}
}
}
}
}
//
.load-more-status {
padding: 20rpx 0;
text-align: center;
.loading,
.more,
.no-more {
display: flex;
align-items: center;
justify-content: center;
gap: 10rpx;
padding: 20rpx 0;
font-size: 26rpx;
color: $text-light;
}
}
//
.no-data {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
text {
margin-top: 30rpx;
font-size: 28rpx;
color: $text-light;
}
}
//
.delete-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.delete-modal-content {
width: 600rpx;
background-color: $white;
border-radius: 24rpx;
padding: 60rpx 40rpx 40rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
}
.delete-modal-title {
font-size: 36rpx;
font-weight: 600;
color: $text-primary;
text-align: center;
margin-bottom: 30rpx;
}
.delete-modal-text {
font-size: 28rpx;
color: $text-secondary;
text-align: center;
line-height: 1.6;
margin-bottom: 50rpx;
word-break: break-all;
}
.delete-modal-buttons {
display: flex;
gap: 20rpx;
}
.delete-modal-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: 500;
transition: all 0.3s ease;
}
.cancel-btn {
background-color: #f5f5f5;
color: $text-primary;
&:active {
background-color: #e0e0e0;
}
}
.confirm-btn {
background-color: #8b2316;
color: $white;
&:active {
background-color: #6b1a0f;
}
}
</style>

View File

@ -23,15 +23,15 @@
<!-- 固定搜索栏 -->
<view class="search-container-fixed filter-bar">
<view class="search-box" @click="goToSearch">
<uni-icons type="search" size="16" color="#999"></uni-icons>
<uni-icons type="search" size="22" color="#999"></uni-icons>
<text class="search-text">搜索</text>
</view>
<view class="divider"></view>
<view class="current-sort" @click="toggleInnerSort">
<text class="sort-text">{{ innerSortTitle }}</text>
<text class="sort-text" :class="{active: isSetStatus}">{{ innerSortTitle }}</text>
<view class="imgbox">
<up-image :src="upImg" width="26rpx" height="26rpx"></up-image>
<up-image :src="isSetStatus?upImg:downImg" width="26rpx" height="26rpx" :class="{active: isSetStatus}"></up-image>
</view>
</view>
</view>
@ -61,7 +61,8 @@
<!-- 操作按钮 -->
<view class="item-action">
<view class="download-btn" @click.stop="downLoad(item)" v-if="!downLoadtaskList.includes(item.uuid)">
<uni-icons type="arrow-down" size="26" color="#8D2316"></uni-icons>
<up-image :src="downIng" width="35rpx" height="35rpx"></up-image>
<!-- <uni-icons type="arrow-down" size="26" color="#8D2316"></uni-icons> -->
<!-- <up-icon name="download" color="#8D2316" size="56rpx" ></up-icon> -->
</view>
<view
@ -149,6 +150,7 @@ import { onShow, onLoad } from "@dcloudio/uni-app";
import docUrl from "@/utils/docUrl.js";
import navTo from "@/utils/navTo.js";
import hotImg from "@/static/hot_booklist.png";
import downIng from "@/static/icon_library_down.png";
let downList = uni.getStorageSync("downLoadPdf") || [];
const downLoadList = ref(downList);
//
@ -167,6 +169,7 @@ const title = ref("");
const sort = ref(2);
const showInnerSort = ref(false);
const innerSortTitle = ref("上传时间");
const isSetStatus=ref(false);
import downloadStore from "@/store/downloadStoreFile.js";
const downloadTasks=ref([]);
const downLoadtaskList=computed(()=>{
@ -174,6 +177,7 @@ const downLoadtaskList=computed(()=>{
});
const chooseInnerSort = (index) => {
sort.value = index;
isSetStatus.value = true;
if (index == 1) {
innerSortTitle.value = "下载量";
} else if (index == 2) {
@ -217,20 +221,20 @@ onShow(() => {
resumeDownloadingTasks();
//
if (guidelinesList.value.length === 0) {
loadGuidelinesList(true);
loadGuidelinesList(false);
}
});
//
const goToSearch = () => {
const q = keywords.value ? encodeURIComponent(keywords.value) : "";
const t = title.value ? encodeURIComponent(title.value) : "";
const type = typeUuid.value
? `&typeUuid=${encodeURIComponent(typeUuid.value)}`
: "";
uni.navigateTo({
url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`,
});
// const q = keywords.value ? encodeURIComponent(keywords.value) : "";
// const t = title.value ? encodeURIComponent(title.value) : "";
// const type = typeUuid.value
// ? `&typeUuid=${encodeURIComponent(typeUuid.value)}`
// : "";
// uni.navigateTo({
// url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`,
// });
// const goSearch=()=>{
// uni.sendNativeEvent('goHomeSearch', {
// msg: 'goHomeSearch'
@ -238,6 +242,15 @@ const goToSearch = () => {
// console.log(ret);
// })
// }
uni.sendNativeEvent(
"goHomeSearch",
{
msg: "zhinan",
},
(ret) => {
console.log(ret);
}
);
};
// scroll-view
@ -317,7 +330,7 @@ const loadGuidelinesList = async (isRefresh = false) => {
page: currentPage.value,
pageSize: pageSize.value,
type: 1, //
sort: 2,
sort: sort.value,
typeUuid: typeUuid.value,
keywords: keywords.value,
};
@ -326,7 +339,7 @@ const loadGuidelinesList = async (isRefresh = false) => {
console.log("指南列表响应:", res);
if (res.code === 200 && res.data) {
const newData = res.data.list || res.data;
const newData = res.data.list;
if (isRefresh) {
guidelinesList.value = newData;
@ -335,15 +348,19 @@ const loadGuidelinesList = async (isRefresh = false) => {
guidelinesList.value = [...guidelinesList.value, ...newData];
console.log("加载更多:追加数据到列表");
}
console.log(222222);
console.log(res.data.pageSize);
console.log(newData.length);
//
if (newData.length < pageSize.value) {
if (newData.length <res.data.pageSize) {
loadMoreStatus.value = "noMore";
hasMoreData.value = false;
console.log("没有更多数据了");
} else {
loadMoreStatus.value = "more";
hasMoreData.value = true;
console.log(333333);
console.log(!isRefresh);
//
if (!isRefresh) {
currentPage.value++;
@ -425,6 +442,8 @@ const downloadGuideline = (item) => {
}
};
const downLoad = (item) => {
console.log(item);
console.log(2222);
if(!item.path){
uni.showToast({
title: "暂无下载链接",
@ -436,6 +455,8 @@ const downLoad = (item) => {
url: docUrl + item.path,
title: item.title,
id: item.uuid,
releaseTime: item.releaseTime,
type: 'zhinan'
});
};
// pdf/doc/docx/xls/xlsx/ppt/pptx/txt
@ -675,7 +696,7 @@ $white: #ffffff;
}
.popup-panel {
position: fixed;
top:285rpx;
top:calc(var(--status-bar-height) + 44px + 106rpx);
left: 0;
right: 0;
background: #fff;
@ -700,14 +721,21 @@ $white: #ffffff;
.popup-item.active .item-text {
color: #8b2316;
}
.search-box{
flex:1;
}
.current-sort {
display: flex;
flex:1;
align-items: center;
gap: 10rpx;
.sort-text {
font-size: 28rpx;
color: #333;
font-size: 36rpx;
color: #999;
&.active {
color: #8b2316;
}
}
.sort-icon.up {
@ -766,7 +794,7 @@ $white: #ffffff;
gap: 5px;
.search-text {
font-size: 14px;
font-size: 36rpx;
color: #999;
}
}

BIN
static/avastar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
static/zhinanLazy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -14,6 +14,9 @@ class DownloadStoreFile {
url: '',
status: 'downloading', // downloading, paused, completed, failed
progress: 0,
title:'',
type:'',
releaseTime:'',
task: null,
filePath: '',
createTime: Date.now(),
@ -93,6 +96,9 @@ class DownloadStoreFile {
filePath: item.filePath,
createTime: item.createTime,
localPath:item.localPath,
title:item.title,
type:item.type,
releaseTime:item.releaseTime,
}));
uni.setStorageSync('downloadFileTasks', tasksToSave);
}

View File

@ -71,6 +71,11 @@

View File

@ -1,7 +1,6 @@
console.log('打印app');
let BASE_URL='https://dev-app.igandan.com/app';
//let BASE_URL='https://app.igandan.com/app'
//let BASE_URL='https://dev-app.igandan.com/app';
let BASE_URL='https://app.igandan.com/app'
// try {
// const app = getApp({allowDefault: true});

View File

@ -1,6 +1,6 @@
//const app = getApp({allowDefault: true});
let DOC_URL='https://dev-doc.igandan.com/app/';
//let DOC_URL='https://doc.igandan.com/app/'
//let DOC_URL='https://dev-doc.igandan.com/app/';
let DOC_URL='https://doc.igandan.com/app/'
// if(app.globalData.apiHost.indexOf('dev')>-1){
// DOC_URL='https://dev-doc.igandan.com/app/'
// }else{

View File

@ -3,7 +3,7 @@ const formatNumber = (number) => {
if(number < 10000){
return number;
}else{
return (number / 10000).toFixed(1) + 'w';
return (number / 10000).toFixed(1) + '';
}
}
export default formatNumber;

View File

@ -1,5 +1,5 @@
let OTHER_HOST='https://dev-wx.igandan.com'
//let OTHER_HOST='https://wx.igandan.com'
//let OTHER_HOST='https://dev-wx.igandan.com'
let OTHER_HOST='https://wx.igandan.com'
//const app = getApp({allowDefault: true});
// if(app.globalData.apiHost && app.globalData.apiHost.indexOf('dev')>-1){
// OTHER_HOST='https://dev-wx.igandan.com'

View File

@ -89,7 +89,7 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
}
console.log(postData);
return new Promise(function(e, n) {
let timestamp = Date.now();
uni.request({
@ -141,6 +141,8 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
})
plus.runtime.quit();
}else if(res.data.code==106){
e(res.data)
}else{
uni.showToast({
title: res.data.message,