2025-12-10 17:33:39 +08:00

823 lines
20 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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
});
}
});
// 保存task对象到store用于暂停/继续)
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.downloadFile不支持断点续传所以从0开始
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>