11.28提交

This commit is contained in:
zoujiandong 2025-11-28 10:43:13 +08:00
parent 91726b87c5
commit 9788e723a2
17 changed files with 1005 additions and 408 deletions

165
App.vue
View File

@ -1,36 +1,41 @@
<script> <script>
export default {
export default {
globalData: { globalData: {
plAd: true, plAd: true,
dotNumber: { dotNumber: {},
apiHost: "https://dev-app.igandan.com/app",
},
apiHost: 'https://dev-app.igandan.com/app',
//BASE_URL='https://dev-app.igandan.com/app' //BASE_URL='https://dev-app.igandan.com/app'
}, },
onLaunch(options) { onLaunch(options) {
//uni.setStorageSync('apiHost', 'value') //uni.setStorageSync('apiHost', 'value')
console.log('打印options'); console.log("打印options");
console.log(options); console.log(options);
if (options && options.referrerInfo.extraData && options.referrerInfo.extraData.token) { if (
uni.setStorageSync("AUTH_TOKEN_App", options.referrerInfo.extraData.token); options &&
options.referrerInfo.extraData &&
options.referrerInfo.extraData.token
) {
uni.setStorageSync(
"AUTH_TOKEN_App",
options.referrerInfo.extraData.token
);
uni.setStorageSync("userInfo", options.referrerInfo.extraData.userInfo); uni.setStorageSync("userInfo", options.referrerInfo.extraData.userInfo);
//getApp({allowDefault: true}).globalData.apiHost = options.referrerInfo.extraData.apiHost; //getApp({allowDefault: true}).globalData.apiHost = options.referrerInfo.extraData.apiHost;
}; }
if (options && options.referrerInfo.extraData && options.referrerInfo.extraData.targetPath) { if (
options &&
options.referrerInfo.extraData &&
options.referrerInfo.extraData.targetPath
) {
uni.navigateTo({ uni.navigateTo({
url: options.referrerInfo.extraData.targetPath url: options.referrerInfo.extraData.targetPath,
}); });
}; }
console.log("app传递登录信息onLaunch-------------------"); console.log("app传递登录信息onLaunch-------------------");
try { try {
// #ifdef APP // #ifdef APP
// uni.onNativeEventReceive((event, data) => { // uni.onNativeEventReceive((event, data) => {
// console.log("app-------------------"); // console.log("app-------------------");
// console.log("event"); // console.log("event");
// console.log(event); // console.log(event);
@ -52,35 +57,43 @@
onShow() { onShow() {
try { try {
// #ifdef APP // #ifdef APP
let checkTokenCallBackFlag = false let checkTokenCallBackFlag = false;
console.log("执行onshow") console.log("执行onshow");
uni.sendNativeEvent('checkToken', { uni.sendNativeEvent(
msg: 'checkToken' "checkToken",
}, ret => { {
checkTokenCallBackFlag = true msg: "checkToken",
console.log('check回调') },
console.log(ret) (ret) => {
checkTokenCallBackFlag = true;
console.log("check回调");
console.log(ret);
if (ret.code == 0) { if (ret.code == 0) {
uni.showModal({ uni.showModal({
title: '提示', title: "提示",
showCancel: false, showCancel: false,
content: '您已退出登录!', content: "您已退出登录!",
success: function (res) { success: function (res) {
if (res.confirm) { if (res.confirm) {
uni.sendNativeEvent('goTabbarPage', { uni.sendNativeEvent(
msg: 'home' "goTabbarPage",
}, ret => { {
msg: "home",
},
(ret) => {
console.log(ret); console.log(ret);
}) }
plus.runtime.quit() );
plus.runtime.quit();
} else if (res.cancel) { } else if (res.cancel) {
console.log('用户点击取消'); console.log("用户点击取消");
}
} }
},
}); });
} }
}) }
);
// setTimeout(function(){ // setTimeout(function(){
// console.log(" setTimeout") // console.log(" setTimeout")
@ -108,27 +121,31 @@
console.log("event", event); console.log("event", event);
console.log("data", data); console.log("data", data);
if (event.indexOf("clearToken") > -1) { if (event.indexOf("clearToken") > -1) {
uni.setStorageSync('AUTH_TOKEN_App', '') uni.setStorageSync("AUTH_TOKEN_App", "");
plus.runtime.quit() plus.runtime.quit();
} }
}) if(event.indexOf("goPage") > -1){
uni.navigateTo({
url: data,
});
}
});
let main = plus.android.runtimeMainActivity(); let main = plus.android.runtimeMainActivity();
//退quit //退quit
plus.runtime.quit = function() { plus.runtime.quit = function () {
main.moveTaskToBack(false); main.moveTaskToBack(false);
}; };
//toast 退 toast //toast 退 toast
plus.nativeUI.toast = (function(str) { plus.nativeUI.toast = function (str) {
if (str == '再按一次退出应用') { if (str == "再按一次退出应用") {
main.moveTaskToBack(false); main.moveTaskToBack(false);
} else { } else {
uni.showToast({ uni.showToast({
title: str, title: str,
icon: 'none', icon: "none",
})
}
}); });
}
};
// uni.onNativeEventReceive((event, data) => { // uni.onNativeEventReceive((event, data) => {
// console.log("apponshow-------------------"); // console.log("apponshow-------------------");
@ -144,16 +161,14 @@
// } // }
// }); // });
// #endif // #endif
} catch (error) { } catch (error) {
console.log('error'); console.log("error");
console.log(error) console.log(error);
} }
}, },
onHide() {}, onHide() {},
methods: {}, methods: {},
}; };
</script> </script>
<template> <template>
@ -161,66 +176,66 @@
</template> </template>
<style lang="scss"> <style lang="scss">
/*每个页面公共css */ /*每个页面公共css */
@import "@/uni_modules/uni-scss/index.scss"; @import "@/uni_modules/uni-scss/index.scss";
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
@import "@/static/customicons.css"; @import "@/static/customicons.css";
// //
page { page {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
.uni-navbar__header-btns-right { .uni-navbar__header-btns-right {
min-width: 120rpx; min-width: 120rpx;
width: auto !important; width: auto !important;
} }
/* #endif */ /* #endif */
.uni-nav-bar-text { .uni-nav-bar-text {
font-weight: bold; font-weight: bold;
font-size: 36rpx !important; font-size: 36rpx !important;
} }
.example-info { .example-info {
font-size: 14px; font-size: 14px;
color: #333; color: #333;
padding: 10px; padding: 10px;
} }
.twoline { .twoline {
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
overflow: hidden; overflow: hidden;
} }
.oneline { .oneline {
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.uni-navbar .uniui-left { .uni-navbar .uniui-left {
font-weight: bold; font-weight: bold;
font-size: 50rpx !important; font-size: 50rpx !important;
} }
::-webkit-scrollbar { ::-webkit-scrollbar {
display: none; display: none;
} }
.status_bar { .status_bar {
height: var(--status-bar-height); height: var(--status-bar-height);
background-color: #eeeeee; background-color: #eeeeee;
} }
.navbox { .navbox {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
height: calc(var(--status-bar-height) + 44px); height: calc(var(--status-bar-height) + 44px);
z-index: 9999; z-index: 9999;
} }
</style> </style>

View File

@ -334,6 +334,38 @@
"bounce": "none" "bounce": "none"
} }
} }
},
{
"path": "zhinan/zhinan",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
}
}
},
{
"path": "zhinanList/zhinanList",
"style": {
"navigationStyle": "custom",
"navigationBarRightButton":{ "hide": true},
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
}
}
},
{
"path": "hot/hot",
"style": {
"navigationStyle": "custom",
"navigationBarRightButton":{ "hide": true},
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
}
}
}, },
{ {
"path": "login/login", "path": "login/login",
@ -559,17 +591,7 @@
// } // }
// } // }
// }, // },
// {
// "path": "hot/hot",
// "style": {
// "navigationStyle": "custom",
// "navigationBarRightButton":{ "hide": true},
// "navigationBarTitleText": "uni-app分页",
// "app": {
// "bounce": "none"
// }
// }
// },
// { // {
@ -727,16 +749,7 @@
// } // }
// } // }
// }, // },
// {
// "path": "zhinan/zhinan",
// "style": {
// "navigationStyle": "custom",
// "navigationBarTitleText": "uni-app分页",
// "app": {
// "bounce": "none"
// }
// }
// },
// { // {
// "path": "caseRecord/caseRecord", // "path": "caseRecord/caseRecord",
// "style": { // "style": {

View File

@ -102,7 +102,7 @@
<view class="video-progress-bar-inner" :style="{ width: item.progress + '%' }"></view> <view class="video-progress-bar-inner" :style="{ width: item.progress + '%' }"></view>
</view> --> </view> -->
<!-- <text>{{ item.progress + '%' }}</text> --> <!-- <text>{{ item.progress + '%' }}</text> -->
<text>{{ formatSize(item.downloadSize) }} / {{ formatSize(item.totalSize) }}</text> <view class="size-box">{{ formatSize(item.downloadSize) }}/{{ formatSize(item.totalSize) }}</view>
</view> </view>
</view> </view>
</view> </view>
@ -596,13 +596,24 @@ onMounted(() => {
page{ page{
background-color: #ffffff; background-color: #ffffff;
} }
.size-box{
display: flex;
white-space: nowrap;
justify-content: flex-end;
white-space: nowrap;
font-size: 24rpx;
color:#8b2316
}
.box{ .box{
display: flex; display: flex;
flex:1; white-space: nowrap;
align-items: center; justify-content: flex-end;
margin-left: 30rpx; margin-left: 30rpx;
text{ text{
width: 40rpx; width: 40rpx;
display: flex;
white-space: nowrap;
font-size: 24rpx; font-size: 24rpx;
color:#8b2316 color:#8b2316
} }
@ -804,8 +815,8 @@ page{
} }
.video-status{ .video-status{
display: flex; display: flex;
align-items: center;
margin-right: 20rpx;
justify-content: space-between; justify-content: space-between;
.status-icon{ .status-icon{
display: flex; display: flex;

View File

@ -1,7 +1,7 @@
<template> <template>
<view class="zhinan-list-page"> <view class="zhinan-list-page">
<!-- 头部导航栏 --> <!-- 头部导航栏 -->
<uni-nav-bar <!-- <uni-nav-bar
left-icon="left" left-icon="left"
:title="title" :title="title"
@clickLeft="goBack" @clickLeft="goBack"
@ -12,7 +12,8 @@
backgroundColor="#eeeeee" backgroundColor="#eeeeee"
> >
</uni-nav-bar> </uni-nav-bar> -->
<navBar :title="title" />
<!-- 使用scroll-view实现列表 --> <!-- 使用scroll-view实现列表 -->
<scroll-view <scroll-view
@ -39,19 +40,15 @@
<view class="item-date">{{ formatDate(item.releaseTime) }}</view> <view class="item-date">{{ formatDate(item.releaseTime) }}</view>
<!-- 操作按钮 --> <!-- 操作按钮 -->
<view class="item-action"> <view class="item-action">
<view <view class="download-btn" @click.stop="downLoad(item)" v-if="!downLoadtaskList.includes(item.uuid)">
class="download-btn" <!-- <up-icon name="download" color="#8D2316" size="28" ></up-icon> -->
@click.stop="viewGuideline(item)" <uni-icons type="arrow-down" size="26" color="#8D2316"></uni-icons>
>
<up-icon name="download" color="#8D2316" size="28"></up-icon>
</view> </view>
<!-- <view <view
v-else v-else
class="view-btn" class="view-btn"
@click.stop="viewGuideline(item)" @click.stop="viewGuideline(item)"
> >查看</view>
查看
</view> -->
</view> </view>
</view> </view>
</view> </view>
@ -83,12 +80,13 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted} from 'vue' import { ref, onMounted,computed,nextTick} from 'vue'
import api from '@/api/api.js' import api from '@/api/api.js'
import { onShow,onLoad } from "@dcloudio/uni-app"; import { onShow,onLoad } from "@dcloudio/uni-app";
import docUrl from "@/utils/docUrl.js" import docUrl from "@/utils/docUrl.js"
import navTo from "@/utils/navTo.js" import navTo from "@/utils/navTo.js"
import hotImg from "@/static/hot_booklist.png" import hotImg from "@/static/hot_booklist.png"
import navBar from "@/components/navBar/navBar.vue"
// //
const guidelinesList = ref([]) const guidelinesList = ref([])
const isLoading = ref(false) const isLoading = ref(false)
@ -107,6 +105,13 @@ const from=ref('');
const name=ref(''); const name=ref('');
const showInnerSort=ref(false); const showInnerSort=ref(false);
const innerSortTitle=ref('上传时间'); const innerSortTitle=ref('上传时间');
import downloadStore from "@/store/downloadStoreFile.js";
const downloadTasks=ref([]);
const downLoadtaskList=computed(()=>{
console.log('downLoadtaskList');
console.log(downloadTasks.value.map((item)=>item.id));
return downloadTasks.value.map((item)=>item.id);
});
const chooseInnerSort=(index)=>{ const chooseInnerSort=(index)=>{
sort.value=index; sort.value=index;
if(index==1){ if(index==1){
@ -144,6 +149,14 @@ const toggleInnerSort=()=>{
showInnerSort.value=!showInnerSort.value; showInnerSort.value=!showInnerSort.value;
} }
onShow(() => { onShow(() => {
syncTasksFromStore();
// store
downloadStore.addListener((tasks) => {
downloadTasks.value = tasks;
});
//
resumeDownloadingTasks();
// //
if (guidelinesList.value.length === 0) { if (guidelinesList.value.length === 0) {
if(from.value){ if(from.value){
@ -359,66 +372,39 @@ const downloadGuideline = (item) => {
}) })
} }
} }
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 // pdf/doc/docx/xls/xlsx/ppt/pptx/txt
const viewGuideline = (item) => { const viewGuideline = (cell) => {
const url = docUrl+item.path console.log(cell);
if (url) { if (!cell.path) {
const isPDF = /\.(pdf)(\?|$)/i.test(url) uni.showToast({
const isOffice = /\.(docx?|xlsx?|pptx?)(\?|$)/i.test(url) title: "暂无下载链接",
const isText = /\.(txt)(\?|$)/i.test(url) icon: "none",
});
// H5 return;
// #ifdef H5
if (isPDF) {
try { window.open(url, '_blank') } catch (e) {
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
} }
return downloadTasks.value.forEach(item => {
} if(item.id == cell.uuid) {
if (isOffice) {
const officeUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`
try { window.open(officeUrl, '_blank') } catch (e) {
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(officeUrl)}` })
}
return
}
if (isText) {
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
return
}
// webview
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
return
// #endif
// H5 openDocument退 webview
// #ifndef H5
uni.showToast({ title: '正在打开...', icon: 'none' })
uni.downloadFile({
url,
success: (res) => {
if (res.statusCode === 200 && res.tempFilePath) {
uni.openDocument({ uni.openDocument({
filePath: res.tempFilePath, filePath: item.localPath,
showMenu: true, success: () => console.log('打开成功'),
success: () => {}, fail: (err) => console.error('打开失败', err)
fail: () => { });
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
} }
}) });
} else {
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
}
},
fail: () => {
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
}
})
return
// #endif
}
// 退
} }
@ -463,6 +449,116 @@ const formatDate = (dateString) => {
return dateString return dateString
} }
} }
//
const addDownloadTask = (item) => {
// 使store
const taskIndex = downloadStore.addTask(item);
//
syncTasksFromStore();
//
startDownload(taskIndex);
};
//
const startDownload = (index) => {
const taskItem = downloadStore.getTask(index);
if (!taskItem) return;
if(taskItem.status == "loading"){
uni.showToast({
title: "正在下载",
icon: "none",
});
return false;
};
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",
});
uni.showToast({
title: "下载失败",
icon: "none",
});
}
},
fail: (err) => {
downloadStore.updateTask(index, {
status: "failed",
});
uni.showToast({
title: "下载失败: " + (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 resumeDownloadingTasks = () => {
// 使 nextTick
nextTick(() => {
downloadStore.resumeDownloadingTasks((index) => {
// uni.downloadFile0
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
startDownload(index);
});
});
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,5 +1,5 @@
<template> <template>
<navBar title="肝胆回放" /> <navBar :title="from == 'video' ? '肝胆视频' : '肝胆回放'" />
<view class="page"> <view class="page">
<!-- 筛选标签栏 --> <!-- 筛选标签栏 -->
<view class="filter-bar"> <view class="filter-bar">
@ -221,7 +221,7 @@
<script setup> <script setup>
import { ref, nextTick, computed } from "vue"; import { ref, nextTick, computed } from "vue";
import { onShow, onHide } from "@dcloudio/uni-app"; import { onShow, onHide,onLoad } from "@dcloudio/uni-app";
import CustomTabbar from "@/components/tabBar/tabBar.vue"; import CustomTabbar from "@/components/tabBar/tabBar.vue";
import api from "@/api/api.js"; import api from "@/api/api.js";
import select from "@/static/triangle_normal.png"; import select from "@/static/triangle_normal.png";
@ -234,6 +234,12 @@ import navTo from "@/utils/navTo";
import navBar from "@/components/navBar/navBar.vue"; import navBar from "@/components/navBar/navBar.vue";
import empty from "@/components/empty/empty.vue"; import empty from "@/components/empty/empty.vue";
import lazyImg from "@/static/default_news_iv.png"; import lazyImg from "@/static/default_news_iv.png";
const from=ref('');
onLoad((options)=>{
if(options.from){
from.value=options.from;
}
});
// //
const isTimePopupShow = ref(false); const isTimePopupShow = ref(false);
const isLocationPopupShow = ref(false); const isLocationPopupShow = ref(false);

View File

@ -5,9 +5,9 @@
@clickLeft="goBack" :title="name" color="#8B2316" :border="false" backgroundColor="#eeeeee"> @clickLeft="goBack" :title="name" color="#8B2316" :border="false" backgroundColor="#eeeeee">
<template #right> <template #right>
<!-- <view class="nav-right" @click="goSelect"> <view class="nav-right" @click="goSelect">
精选 精选
</view> --> </view>
</template> </template>
</uni-nav-bar> </uni-nav-bar>
</view> </view>

View File

@ -11,7 +11,7 @@
:refresher-triggered="refreshing" :refresher-triggered="refreshing"
@refresherrefresh="onRefresh" @refresherrefresh="onRefresh"
@scrolltolower="onLoadMore" @scrolltolower="onLoadMore"
lower-threshold="1000" lower-threshold="300"
> >
<view class="meeting-list"> <view class="meeting-list">
<view <view
@ -101,9 +101,7 @@
}; };
const loadVideoData = async (isRefresh = false) => { const loadVideoData = async (isRefresh = false) => {
if (loading.value && !isRefresh) return; if (loading.value && !isRefresh) return;
loading.value = true; loading.value = true;
try { try {
const response = await api.videoByTypeNew({ const response = await api.videoByTypeNew({
page: currentPage.value, page: currentPage.value,
@ -128,7 +126,7 @@
if (videoData && videoData.list) { if (videoData && videoData.list) {
const { list, totalPage,pageNumber } = videoData; const { list, totalPage,pageNumber } = videoData;
console.log('视频列表数据:', list); console.log('视频列表数据:', list);
loading.value=false;
if (isRefresh) { if (isRefresh) {
meetingList.value = list || []; meetingList.value = list || [];
currentPage.value = 1; currentPage.value = 1;
@ -138,6 +136,10 @@
hasMoreData.value = totalPage>pageNumber; hasMoreData.value = totalPage>pageNumber;
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore'; loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
if(hasMoreData.value ){
onLoadMore();
}
} else { } else {
throw new Error(response?.message || '获取数据失败'); throw new Error(response?.message || '获取数据失败');
} }
@ -162,6 +164,8 @@
// //
const onLoadMore = () => { const onLoadMore = () => {
console.log('onLoadMore'); console.log('onLoadMore');
console.log('hasMoreData',hasMoreData.value);
console.log('loading',loading.value);
if (!hasMoreData.value || loading.value) return; if (!hasMoreData.value || loading.value) return;
loadMoreStatus.value = 'loading'; loadMoreStatus.value = 'loading';

View File

@ -1,5 +1,31 @@
<template> <template>
<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 class="collect-img" @click="goMeet">
<image
class="img-icon"
:src="meetImg"
mode="aspectFill"
/>
</view>
</view>
</template>
</uni-nav-bar>
</view>
<view class="video-page"> <view class="video-page">
<!-- Header --> <!-- Header -->
@ -31,11 +57,23 @@
@click="playBannerVideo(banner)" @click="playBannerVideo(banner)"
> >
<view class="banner-item"> <view class="banner-item">
<image <up-image
class="banner-image" class="banner-image"
:src="docUrl+banner.imgpath" :src="docUrl+banner.imgpath"
mode="aspectFill" mode="aspectFill"
></image> :loadingIcon="lazyVideoImg"
:errorIcon="lazyVideoImg"
:lazy-load="true"
width="100%"
height="400rpx"
>
<template #error>
<image :src="lazyVideoImg" class="banner-image" mode="aspectFill"></image>
</template>
<template #loading>
<image :src="lazyVideoImg" class="banner-image" mode="aspectFill"></image>
</template>
</up-image>
</view> </view>
</swiper-item> </swiper-item>
@ -97,7 +135,25 @@
@click="playVideo(video)" @click="playVideo(video)"
> >
<view class="video-thumbnail"> <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="poster-image" mode="aspectFill"></image>
</template>
<template #loading>
<image :src="lazyImg" class="poster-image" mode="aspectFill"></image>
</template>
</up-image>
</view> </view>
<view class="video-info"> <view class="video-info">
<view class="video-title">{{video.title || video.name}}</view> <view class="video-title">{{video.title || video.name}}</view>
@ -219,6 +275,10 @@
import videoImg from "@/static/patient_video.png" import videoImg from "@/static/patient_video.png"
import docUrl from '@/utils/docUrl'; import docUrl from '@/utils/docUrl';
import navTo from '@/utils/navTo'; import navTo from '@/utils/navTo';
import searchImg from "@/static/search.png"
import lazyImg from "@/static/default_video.png"
import lazyVideoImg from "@/static/videoPlaceholder.png";
import meetImg from "@/static/sfewm.png"
import formatNumber from '@/utils/formatNumber.js'; import formatNumber from '@/utils/formatNumber.js';
import navBar from '@/components/navBar/navBar.vue'; import navBar from '@/components/navBar/navBar.vue';
const isAllActive=ref(false) const isAllActive=ref(false)
@ -244,6 +304,18 @@
const showFilter = ref(false); const showFilter = ref(false);
const yearList=ref([]); const yearList=ref([]);
const selectYearContent=reactive({}) const selectYearContent=reactive({})
const goSearch=()=>{
uni.sendNativeEvent('goHomeSearch', {
msg: 'goHomeSearch'
},ret => {
console.log(ret);
})
}
const goMeet=()=>{
uni.navigateTo({
url: '/pages_app/liveReplay/liveReplay?from=video'
});
}
// //
const filterTags = ref([ const filterTags = ref([
{ name: '指南解读', selected: false }, { name: '指南解读', selected: false },
@ -554,11 +626,11 @@
// //
const goSearch = () => { // const goSearch = () => {
uni.navigateTo({ // uni.navigateTo({
url: '/pages_app/search/search' // url: '/pages_app/search/search'
}); // });
}; // };
// //
const goPatientVideo = () => { const goPatientVideo = () => {
@ -777,6 +849,16 @@
$border-radius-small: 6px; $border-radius-small: 6px;
$padding: 15px; $padding: 15px;
$padding-small: 10px; $padding-small: 10px;
.img-icon{
width: 42rpx;
height: 42rpx;
}
.nav-actions{
display: flex;
align-items: center;
justify-content: center;
gap: 20rpx;
}
.video-page { .video-page {
background-color: #f5f5f5; background-color: #f5f5f5;
height: 100vh; height: 100vh;
@ -1138,7 +1220,7 @@
.popup-content { .popup-content {
width: 100%; width: 100%;
margin-top: calc(var(--status-bar-height) + 44px + 400rpx + 117rpx); margin-top: calc(var(--status-bar-height) + 44px + 400rpx + 117rpx);
height: 80vh; height: calc(100vh - var(--status-bar-height) - 44px - 400rpx - 117rpx);
background-color: #fff; background-color: #fff;
overflow: scroll; overflow: scroll;
@ -1167,7 +1249,7 @@
.popup-body { .popup-body {
display: flex; display: flex;
height: 600rpx; height: 100%;
} }
.category-sidebar { .category-sidebar {

View File

@ -41,16 +41,17 @@
:src="videoSrc" :src="videoSrc"
:videoHeight="220" :videoHeight="220"
:seekTime="0" :seekTime="0"
@fullscreenchange="onFullscreenChange"
/> />
<!-- 标签切换 --> <!-- 标签切换 -->
<cover-view class="tabs" v-if="from != 'download'"> <cover-view class="tabs" v-if="from != 'download'" :style="{ opacity: isFullScreen ? 0: 1 }">
<cover-view <cover-view
class="tab" class="tab"
:class="{ active: activeTab === 'info' }" :class="{ active: activeTab === 'info' }"
@click="switchTab('info')" @click="switchTab('info')"
> >
视频简介 视频简介
<view-cover class="tab-line" v-if="activeTab === 'info'"></view-cover> <cover-view class="tab-line" v-if="activeTab === 'info'"></cover-view>
</cover-view> </cover-view>
<cover-view <cover-view
class="tab" class="tab"
@ -58,7 +59,7 @@
@click="switchTab('comment')" @click="switchTab('comment')"
> >
评论 评论
<view-cover class="tab-line" v-if="activeTab === 'comment'"></view-cover> <cover-view class="tab-line" v-if="activeTab === 'comment'"></cover-view>
</cover-view> </cover-view>
</cover-view> </cover-view>
<view class="video-detail-page" v-if="from != 'download'"> <view class="video-detail-page" v-if="from != 'download'">
@ -132,7 +133,8 @@
<text v-if="!isVideoDownloadRecord && welfareNum > 0">(剩余免费下载{{ welfareNum }}次数)</text> <text v-if="!isVideoDownloadRecord && welfareNum > 0">(剩余免费下载{{ welfareNum }}次数)</text>
</text </text
> >
<text class="download-text" v-else-if="downLoadStatus === 'loading'">视频缓存中</text>
<text class="download-text" v-else-if="downLoadStatus === 'loading' || downLoadStatus === 'failed'">视频缓存中</text>
<text class="download-text" v-else-if="downLoadStatus === 'completed'">查看缓存</text> <text class="download-text" v-else-if="downLoadStatus === 'completed'">查看缓存</text>
</view> </view>
<view v-if="activeTab !== 'info' && from != 'download'" class="bottom-comment"> <view v-if="activeTab !== 'info' && from != 'download'" class="bottom-comment">
@ -226,6 +228,7 @@ const hasDownload = ref(false);
const downLoadStatus = ref('start'); const downLoadStatus = ref('start');
let downList = uni.getStorageSync("downLoadVideo") || []; let downList = uni.getStorageSync("downLoadVideo") || [];
const downLoadList = ref(downList); const downLoadList = ref(downList);
const isFullScreen = ref(false);
//import DomVideoPlayer from 'uniapp-video-player' //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"; import downloadStore from "@/store/downloadStoreVideo.js";
@ -239,6 +242,12 @@ const addDownloadTask = (item) => {
// //
startDownload(taskIndex); startDownload(taskIndex);
}; };
const onFullscreenChange = (e) => {
let { fullScreen, direction } = e;
nextTick(() => {
isFullScreen.value = fullScreen;
});
};
// //
const startDownload = (index) => { const startDownload = (index) => {
const taskItem = downloadStore.getTask(index); const taskItem = downloadStore.getTask(index);
@ -342,17 +351,11 @@ const toCollection = () => {
}; };
const networkConfirm = () => { const networkConfirm = () => {
networkVisible.value = false; networkVisible.value = false;
pointVisible.value = true;
if(welfareNum.value > 0) { if(welfareNum.value > 0) {
useWelfareNum(); useWelfareNum();
}else{ }else{
addDownloadTask({ pointVisible.value = true;
url: videoSrc.value,
id: video_uuid.value,
imgpath: videoInfo.value.imgpath,
author: videoInfo.value.public_name,
name: videoInfo.value.name,
});
} }
}; };
@ -399,18 +402,7 @@ const videoDetail = async () => {
if (res.code == 200) { if (res.code == 200) {
const userInfo = uni.getStorageSync("userInfo"); const userInfo = uni.getStorageSync("userInfo");
videoInfo.value = res.video; videoInfo.value = res.video;
downloadTasks.value.forEach(item => {
if (item.id == video_uuid.value) {
uni.getSavedFileInfo({
filePath: item.localPath, //
success: function (res) {
hasDownload.value = true;
downLoadStatus.value = 'completed';
}
});
}
});
//hasDownload.value = downLoadList.value.includes(video_uuid.value); //hasDownload.value = downLoadList.value.includes(video_uuid.value);
let vid = res.video.polyv_uuid; let vid = res.video.polyv_uuid;
let uuid = vid.substring(0, 10); let uuid = vid.substring(0, 10);
@ -452,6 +444,24 @@ const VideoDownloadRecord = async () => {
const res = await api.isVideoDownloadRecord({ video_uuid: video_uuid.value }); const res = await api.isVideoDownloadRecord({ video_uuid: video_uuid.value });
if (res.code == 200) { if (res.code == 200) {
isVideoDownloadRecord.value = res.result == 0 ? false : true; isVideoDownloadRecord.value = res.result == 0 ? false : true;
if(isVideoDownloadRecord.value) {
downloadTasks.value.forEach(item => {
if (item.id == video_uuid.value) {
uni.getSavedFileInfo({
filePath: item.localPath, //
success: function (res) {
hasDownload.value = true;
downLoadStatus.value = 'completed';
},
fail: function (err) {
// hasDownload.value = false;
// downLoadStatus.value = 'failed';
}
});
}
});
}
} }
}; };
@ -496,17 +506,48 @@ const resumeDownloadingTasks = () => {
onShow(() => { onShow(() => {
hasDownload.value = false; hasDownload.value = false;
downLoadStatus.value = 'start'; downLoadStatus.value = 'start';
console.log('onShow');
syncTasksFromStore(); syncTasksFromStore();
// store // store
downloadStore.addListener((tasks) => { downloadStore.addListener((tasks) => {
downloadTasks.value = tasks; downloadTasks.value = tasks;
}); });
// //
resumeDownloadingTasks(); resumeDownloadingTasks();
console.log('tasks');
console.log(downloadTasks.value);
if(downloadTasks.value.length > 0) {
for(let i = 0; i < downloadTasks.value.length; i++) {
if(downloadTasks.value[i].id == video_uuid.value) {
console.log('runing');
console.log(downloadTasks.value[i].status);
hasDownload.value = true;
if(downloadTasks.value[i].status == 'completed') {
downLoadStatus.value = 'completed';
}else if(downloadTasks.value[i].status == 'downloading') {
uni.showToast({
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';
}
}
}
};
if (activeTab.value == "comment") { if (activeTab.value == "comment") {
videoCommentListV2(); videoCommentListV2();
} }
if(from.value != 'download') {
videoDetail(); videoDetail();
}
uni.hideLoading(); uni.hideLoading();
}); });
@ -694,9 +735,12 @@ onLoad((options) => {
}); });
video_uuid.value = options.id; video_uuid.value = options.id;
from.value = options.from; from.value = options.from;
if(from.value != 'download') {
addVideoWatchRecord(); addVideoWatchRecord();
VideoDownloadRecord(); VideoDownloadRecord();
getWelfareNum(); getWelfareNum();
}
// store // store
syncTasksFromStore(); syncTasksFromStore();
// store // store
@ -706,6 +750,18 @@ onLoad((options) => {
}); });
// //
resumeDownloadingTasks(); resumeDownloadingTasks();
if(from.value == 'download') {
downloadTasks.value.forEach(item => {
if(item.id == video_uuid.value) {
console.log(222222);
console.log(item.localPath);
videoSrc.value = item.localPath;
showVideo.value = true;
}
});
}
// navTo({ // navTo({
// url: "/pages_app/downLoadVideo/downLoadVideo", // url: "/pages_app/downLoadVideo/downLoadVideo",
// }); // });
@ -736,6 +792,7 @@ const payVideoDownload = async () => {
author: videoInfo.value.public_name, author: videoInfo.value.public_name,
name: videoInfo.value.name, name: videoInfo.value.name,
}); });
} else if (res.code == 106) { } else if (res.code == 106) {
notEnoughVisible.value = true; notEnoughVisible.value = true;
notEnoughContent.value = `您的积分不足,是否购买积分?`; notEnoughContent.value = `您的积分不足,是否购买积分?`;
@ -885,6 +942,7 @@ $theme-color: #8b2316;
} }
.video-detail-page { .video-detail-page {
border-top: 2rpx solid #cccccc;
background: $bg-color; background: $bg-color;
overflow: hidden; overflow: hidden;
} }
@ -914,7 +972,7 @@ $theme-color: #8b2316;
top: calc(var(--status-bar-height) + 44px + 220px); top: calc(var(--status-bar-height) + 44px + 220px);
padding: 24rpx 0 0; padding: 24rpx 0 0;
border-bottom: 2rpx solid #cccccc;
width: 100%; width: 100%;
z-index: 99; z-index: 99;
@ -926,7 +984,7 @@ $theme-color: #8b2316;
align-items: center; align-items: center;
padding: 16rpx 0 24rpx; padding: 16rpx 0 24rpx;
color: $text-secondary; color: $text-secondary;
font-size: 28rpx; font-size: 28rpx!important;
.tab-line { .tab-line {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
@ -939,7 +997,11 @@ $theme-color: #8b2316;
background: $theme-color; background: $theme-color;
} }
&:nth-child(2) { &:nth-child(2) {
display: flex;
margin-left: 200rpx; margin-left: 200rpx;
justify-content: center;
align-items: center;
text-align: center;
} }
&.active { &.active {
color: $theme-color; color: $theme-color;
@ -963,7 +1025,7 @@ $theme-color: #8b2316;
width: 100%; width: 100%;
background: #fff; background: #fff;
// padding: 24rpx 28rpx 40rpx; // padding: 24rpx 28rpx 40rpx;
top: calc(var(--status-bar-height) + 44px + 220px + 88rpx); top: calc(var(--status-bar-height) + 44px + 220px + 99rpx);
height: calc(100vh - var(--status-bar-height) - 44px - 220px - 90rpx); height: calc(100vh - var(--status-bar-height) - 44px - 220px - 90rpx);
overflow-y: scroll; overflow-y: scroll;
// background: red; // background: red;

View File

@ -1,5 +1,5 @@
<template> <template>
<uni-nav-bar <!-- <uni-nav-bar
left-icon="left" left-icon="left"
title="诊疗指南" title="诊疗指南"
@clickLeft="goBack" @clickLeft="goBack"
@ -8,14 +8,15 @@
height="180rpx" height="180rpx"
:border="false" :border="false"
backgroundColor="#eeeeee" backgroundColor="#eeeeee"
></uni-nav-bar> ></uni-nav-bar> -->
<navBar title="诊疗指南"/>
<view class="zhinan-page" v-if="tab=='zhinan'"> <view class="zhinan-page" v-if="tab=='zhinan'">
<!-- 导航栏 --> <!-- 导航栏 -->
<!-- 固定搜索栏 --> <!-- 固定搜索栏 -->
<view class="search-container-fixed filter-bar"> <view class="search-container-fixed filter-bar">
<view class="search-box"> <view class="search-box" @click="goSearch">
<uni-icons type="search" size="16" color="#999"></uni-icons> <uni-icons type="search" size="16" color="#999"></uni-icons>
<text class="search-text">搜索</text> <text class="search-text">搜索</text>
</view> </view>
@ -264,6 +265,7 @@
import api from '@/api/api.js' import api from '@/api/api.js'
import docUrl from "@/utils/docUrl.js" import docUrl from "@/utils/docUrl.js"
import navTo from '@/utils/navTo.js'; import navTo from '@/utils/navTo.js';
import navBar from "@/components/navBar/navBar.vue"
const total=ref(0); const total=ref(0);
const tab=ref('zhinan') const tab=ref('zhinan')
// //
@ -285,7 +287,13 @@
const showFilterPopup = () => { const showFilterPopup = () => {
showFilter.value = true; showFilter.value = true;
}; };
const goSearch=()=>{
uni.sendNativeEvent('goHomeSearch', {
msg: 'goHomeSearch'
},ret => {
console.log(ret);
})
}
const hideFilterPopup = () => { const hideFilterPopup = () => {
showFilter.value = false; showFilter.value = false;
}; };
@ -556,7 +564,7 @@ $accent-color: #4A90E2;
// //
.search-container-fixed { .search-container-fixed {
position: fixed; position: fixed;
top: 180rpx; // top: calc(var(--status-bar-height) + 44px); //
left: 0; left: 0;
right: 0; right: 0;
z-index: 90; z-index: 90;
@ -613,7 +621,7 @@ $accent-color: #4A90E2;
padding: 30rpx; padding: 30rpx;
gap: 20rpx; gap: 20rpx;
margin:0 30rpx; margin:0 30rpx;
margin-top: 100rpx; // (80rpx + ) margin-top: calc(var(--status-bar-height) + 44px + 106rpx); // (80rpx + )
.guideline-item { .guideline-item {

View File

@ -1,22 +1,25 @@
<template> <template>
<view class="zhinan-list-page"> <view class="zhinan-list-page">
<!-- 头部导航栏 --> <!-- 头部导航栏 -->
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar <uni-nav-bar
left-icon="left" left-icon="left"
:title="title" :title="title"
@clickLeft="goBack" @clickLeft="goBack"
fixed
color="#8B2316" color="#8B2316"
height="180rpx"
:border="false" :border="false"
backgroundColor="#eeeeee" backgroundColor="#eeeeee"
> >
<template v-slot:right> <template v-slot:right>
<view class="nav-right" @click="goGot"> <view class="nav-right" @click="goGot" >
<up-image :src="hotImg" width="40rpx" height="40rpx"></up-image> <up-image :src="hotImg" width="40rpx" height="40rpx"></up-image>
</view> </view>
</template> </template>
</uni-nav-bar> </uni-nav-bar>
</view>
<!-- 固定搜索栏 --> <!-- 固定搜索栏 -->
<view class="search-container-fixed filter-bar"> <view class="search-container-fixed filter-bar">
<view class="search-box" @click="goToSearch"> <view class="search-box" @click="goToSearch">
@ -48,7 +51,7 @@
class="guideline-item" class="guideline-item"
v-for="(item, index) in guidelinesList" v-for="(item, index) in guidelinesList"
:key="item.uuid || index" :key="item.uuid || index"
@click="viewGuideline(item)"
> >
<!-- 指南信息 --> <!-- 指南信息 -->
<view class="item-content"> <view class="item-content">
@ -57,8 +60,9 @@
<view class="item-date">{{ formatDate(item.releaseTime) }}</view> <view class="item-date">{{ formatDate(item.releaseTime) }}</view>
<!-- 操作按钮 --> <!-- 操作按钮 -->
<view class="item-action"> <view class="item-action">
<view class="download-btn" @click.stop="viewGuideline(item)" v-if="!downLoadList.includes(item.uuid)"> <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-icon name="download" color="#8D2316" size="56rpx" ></up-icon> -->
</view> </view>
<view <view
v-else v-else
@ -139,7 +143,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted,computed,nextTick} from "vue";
import api from "@/api/api.js"; import api from "@/api/api.js";
import { onShow, onLoad } from "@dcloudio/uni-app"; import { onShow, onLoad } from "@dcloudio/uni-app";
import docUrl from "@/utils/docUrl.js"; import docUrl from "@/utils/docUrl.js";
@ -163,6 +167,13 @@ const title = ref("");
const sort = ref(2); const sort = ref(2);
const showInnerSort = ref(false); const showInnerSort = ref(false);
const innerSortTitle = ref("上传时间"); const innerSortTitle = ref("上传时间");
import downloadStore from "@/store/downloadStoreFile.js";
const downloadTasks=ref([]);
const downLoadtaskList=computed(()=>{
console.log('downLoadtaskList');
console.log(downloadTasks.value.map((item)=>item.id));
return downloadTasks.value.map((item)=>item.id);
});
const chooseInnerSort = (index) => { const chooseInnerSort = (index) => {
sort.value = index; sort.value = index;
if (index == 1) { if (index == 1) {
@ -197,6 +208,15 @@ const toggleInnerSort = () => {
showInnerSort.value = !showInnerSort.value; showInnerSort.value = !showInnerSort.value;
}; };
onShow(() => { onShow(() => {
console.log('onShow');
syncTasksFromStore();
// store
downloadStore.addListener((tasks) => {
downloadTasks.value = tasks;
});
//
resumeDownloadingTasks();
// //
if (guidelinesList.value.length === 0) { if (guidelinesList.value.length === 0) {
loadGuidelinesList(true); loadGuidelinesList(true);
@ -213,6 +233,13 @@ const goToSearch = () => {
uni.navigateTo({ uni.navigateTo({
url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`, url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`,
}); });
// const goSearch=()=>{
// uni.sendNativeEvent('goHomeSearch', {
// msg: 'goHomeSearch'
// },ret => {
// console.log(ret);
// })
// }
}; };
// scroll-view // scroll-view
@ -392,44 +419,62 @@ const downloadGuideline = (item) => {
fail: (err) => { fail: (err) => {
console.error("下载失败:", err); console.error("下载失败:", err);
uni.showToast({ uni.showToast({
title: "下载失败", title: "下载失败1",
icon: "none", icon: "none",
}); });
}, },
}); });
} }
}; };
const downLoad = (item) => {
// pdf/doc/docx/xls/xlsx/ppt/pptx/txt if(!item.path){
const viewGuideline = (item) => {
if (!item.path) {
uni.showToast({ uni.showToast({
title: "暂无下载链接", title: "暂无下载链接",
icon: "none", icon: "none",
}); });
return; return;
} }
const pdfUrl = docUrl + item.path; addDownloadTask({
let url = "https://view.xdocin.com/view?src=" + encodeURIComponent(pdfUrl); url: docUrl + item.path,
uni.downloadFile({ title: item.title,
url: pdfUrl, id: item.uuid,
success: (res) => { });
if (res.statusCode === 200) { };
let index = downLoadList.value.find((cell) => item.uuid == cell.id); // pdf/doc/docx/xls/xlsx/ppt/pptx/txt
if (!index) { const viewGuideline = (cell) => {
downLoadList.value.push(item.uuid); console.log(cell);
uni.setStorageSync("downLoadPdf", downLoadList.value); if (!cell.path) {
uni.showToast({
title: "暂无下载链接",
icon: "none",
});
return;
} }
navTo({ const pdfUrl = docUrl + cell.path;
url: console.log(downloadTasks.value);
"/pages_app/webview/webview?url=" + downloadTasks.value.forEach(item => {
encodeURIComponent(url) + if(item.id == cell.uuid) {
"&title=" + uni.openDocument({
item.title, filePath: item.localPath,
success: () => console.log('打开成功'),
fail: (err) => console.error('打开失败', err)
}); });
} }
},
}); });
// 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)
// });
// }
// },
// });
}; };
// //
@ -437,6 +482,122 @@ const goBack = () => {
uni.navigateBack(); uni.navigateBack();
}; };
//
const addDownloadTask = (item) => {
// 使store
const taskIndex = downloadStore.addTask(item);
//
syncTasksFromStore();
//
startDownload(taskIndex);
};
//
const startDownload = (index) => {
const taskItem = downloadStore.getTask(index);
if (!taskItem) return;
if(taskItem.status == "loading"){
uni.showToast({
title: "正在下载",
icon: "none",
});
return false;
};
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 = () => { const testLoadMore = () => {
console.log("=== 手动测试加载更多 ==="); console.log("=== 手动测试加载更多 ===");
@ -490,7 +651,7 @@ $white: #ffffff;
} }
.popup-panel { .popup-panel {
position: fixed; position: fixed;
top: 256rpx; /* 紧贴筛选栏 */ top:285rpx;
left: 0; left: 0;
right: 0; right: 0;
background: #fff; background: #fff;
@ -544,18 +705,18 @@ $white: #ffffff;
.guidelines-scroll-view { .guidelines-scroll-view {
position: fixed; position: fixed;
top: 285rpx; top: calc(var(--status-bar-height) + 44px + 106rpx);
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
z-index: 99; z-index: 99;
height: calc(100vh - 180rpx); height: calc(100vh - var(--status-bar-height) - 44px - 106rpx);
background-color: $bg-color; background-color: $bg-color;
} }
// //
.search-container-fixed { .search-container-fixed {
position: fixed; position: fixed;
top: 180rpx; // top: calc(var(--status-bar-height) + 44px); //
left: 0; left: 0;
right: 0; right: 0;
z-index: 90; z-index: 90;
@ -658,12 +819,12 @@ $white: #ffffff;
justify-content: center; justify-content: center;
border-radius: 50%; border-radius: 50%;
background-color: rgba(255, 71, 87, 0.1); background-color: rgba(255, 71, 87, 0.1);
transition: all 0.3s ease; // transition: all 0.3s ease;
&:active { // &:active {
transform: scale(0.95); // transform: scale(0.95);
background-color: rgba(255, 71, 87, 0.2); // background-color: rgba(255, 71, 87, 0.2);
} // }
} }
.view-btn { .view-btn {

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
static/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
static/videoPlaceholder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

135
store/downloadStoreFile.js Normal file
View File

@ -0,0 +1,135 @@
// 下载任务全局状态管理
class DownloadStoreFile {
constructor() {
let tasks = uni.getStorageSync('downloadFileTasks');
this.tasks = tasks || [] ; // 下载任务列表
this.listeners = []; // 监听器列表
}
// 添加任务
addTask(data) {
const taskIndex = this.tasks.length;
const taskItem = {
id: Date.now() + Math.random(), // 唯一ID
url: '',
status: 'downloading', // downloading, paused, completed, failed
progress: 0,
task: null,
filePath: '',
createTime: Date.now(),
localPath:''
};
Object.assign(taskItem, data);
this.tasks.push(taskItem);
this.notifyListeners();
this.saveToStorage();
return taskIndex;
}
// 更新任务
updateTask(index, updates) {
if (this.tasks[index]) {
Object.assign(this.tasks[index], updates);
this.notifyListeners();
this.saveToStorage();
}
}
// 删除任务
removeTask(index) {
const taskItem = this.tasks[index];
if (taskItem && taskItem.task && taskItem.status === 'downloading') {
taskItem.task.abort();
}
this.tasks.splice(index, 1);
this.notifyListeners();
this.saveToStorage();
}
// 获取所有任务
getTasks() {
return this.tasks;
}
// 获取任务
getTask(index) {
return this.tasks[index];
}
// 添加监听器
addListener(callback) {
this.listeners.push(callback);
// 返回取消监听的函数
return () => {
const index = this.listeners.indexOf(callback);
if (index > -1) {
this.listeners.splice(index, 1);
}
};
}
// 通知所有监听器
notifyListeners() {
// 创建新数组引用确保Vue能检测到变化
const tasksCopy = [...this.tasks];
this.listeners.forEach(callback => {
try {
callback(tasksCopy);
} catch (e) {
console.error('DownloadStoreFile listener error:', e);
}
});
}
// 保存到本地存储
saveToStorage() {
// 只保存基本信息不保存task对象
const tasksToSave = this.tasks.map(item => ({
id: item.id,
url: item.url,
status: item.status,
progress: item.progress,
filePath: item.filePath,
createTime: item.createTime,
localPath:item.localPath,
}));
uni.setStorageSync('downloadFileTasks', tasksToSave);
}
// 从本地存储加载
loadFromStorage() {
const savedTasks = uni.getStorageSync('downloadFileTasks');
if (savedTasks && Array.isArray(savedTasks)) {
this.tasks = savedTasks.map(item => ({
...item,
task: null // task对象无法序列化需要重新创建
}));
this.notifyListeners();
}
}
// 恢复下载中的任务
resumeDownloadingTasks(startDownloadCallback) {
this.tasks.forEach((taskItem, index) => {
// 如果任务状态是下载中但task对象为null说明需要重新创建下载任务
if (taskItem.status === 'downloading' && !taskItem.task) {
if (typeof startDownloadCallback === 'function') {
startDownloadCallback(index);
}
}
});
}
}
// 创建单例
const downloadStoreFile = new DownloadStoreFile();
// 在应用启动时加载存储的任务
// #ifndef VUE3
if (typeof Vue !== 'undefined') {
Vue.prototype.$downloadStoreFile = downloadStoreFile;
}
// #endif
export default downloadStoreFile;

View File

@ -64,6 +64,10 @@