最新同步的5条视频,手机浏览器播放

This commit is contained in:
jianzhichu
2025-12-21 13:29:40 +08:00
parent 413f19c537
commit 44e3962093
6 changed files with 287 additions and 70 deletions
@@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl> <_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl>
<History>True|2025-12-20T06:05:36.6224332Z||;False|2025-12-20T14:05:28.6359828+08:00||;True|2025-12-20T13:58:30.1641630+08:00||;True|2025-12-20T13:55:16.1759645+08:00||;True|2025-12-20T12:16:22.5224516+08:00||;True|2025-12-19T09:50:16.9517676+08:00||;True|2025-12-19T09:49:47.0871734+08:00||;False|2025-12-19T09:49:36.7638757+08:00||;True|2025-12-19T09:35:13.2489248+08:00||;True|2025-12-14T19:09:59.9031104+08:00||;True|2025-12-13T21:21:10.0022707+08:00||;True|2025-12-11T22:07:16.6229994+08:00||;True|2025-12-11T22:05:56.7363206+08:00||;True|2025-12-11T22:01:07.5862406+08:00||;True|2025-12-11T22:00:43.5796594+08:00||;True|2025-12-08T21:20:37.8369271+08:00||;False|2025-12-08T21:20:21.1646252+08:00||;True|2025-12-08T20:51:50.6845619+08:00||;True|2025-12-08T16:43:45.2425324+08:00||;False|2025-12-08T16:42:23.0308163+08:00||;True|2025-12-08T16:41:52.4103868+08:00||;True|2025-12-08T16:41:49.8972006+08:00||;False|2025-12-08T16:41:39.5343442+08:00||;True|2025-12-08T12:40:19.2430740+08:00||;True|2025-12-08T12:02:30.6005542+08:00||;True|2025-12-08T11:34:29.6673185+08:00||;False|2025-12-08T11:30:56.2857042+08:00||;True|2025-12-08T10:52:43.7427594+08:00||;True|2025-12-08T07:05:03.2845531+08:00||;True|2025-12-07T23:02:10.0037815+08:00||;True|2025-12-07T22:48:25.7859648+08:00||;True|2025-12-07T20:49:13.6683281+08:00||;True|2025-12-07T08:47:30.1236366+08:00||;True|2025-12-06T13:14:32.4410202+08:00||;True|2025-12-06T13:07:29.7182102+08:00||;True|2025-12-06T13:05:46.2855366+08:00||;False|2025-12-06T13:05:40.3550904+08:00||;True|2025-12-06T13:03:47.8773880+08:00||;True|2025-12-06T13:03:28.9521030+08:00||;True|2025-12-05T23:11:51.5026151+08:00||;True|2025-12-05T12:46:26.1415079+08:00||;False|2025-12-05T12:46:19.1274332+08:00||;True|2025-12-05T09:04:36.7111717+08:00||;True|2025-12-05T08:22:51.7343317+08:00||;True|2025-12-05T08:20:32.0383739+08:00||;True|2025-12-04T21:58:29.4112766+08:00||;True|2025-12-04T21:58:10.0382218+08:00||;True|2025-12-04T21:57:55.3894059+08:00||;True|2025-12-04T21:10:38.8943797+08:00||;True|2025-12-04T21:09:31.5024569+08:00||;True|2025-12-04T08:22:47.9617427+08:00||;False|2025-12-04T08:22:41.3759733+08:00||;True|2025-12-04T08:14:02.2478893+08:00||;True|2025-12-04T07:57:00.2208139+08:00||;True|2025-12-03T23:58:13.3693303+08:00||;True|2025-12-03T23:57:40.4257893+08:00||;True|2025-12-03T23:56:38.8717769+08:00||;True|2025-12-03T23:56:24.0663568+08:00||;False|2025-12-03T23:55:36.1902974+08:00||;True|2025-12-03T23:51:30.6688504+08:00||;True|2025-12-03T23:34:17.1648971+08:00||;False|2025-12-03T23:34:07.7649161+08:00||;True|2025-12-03T22:32:56.2435003+08:00||;True|2025-12-03T22:27:45.6059666+08:00||;True|2025-12-03T15:55:28.0186597+08:00||;False|2025-12-03T15:54:17.5032724+08:00||;True|2025-12-03T15:53:10.2273509+08:00||;True|2025-12-02T22:11:37.4645042+08:00||;False|2025-12-02T22:10:47.1320259+08:00||;True|2025-12-02T14:39:58.8932130+08:00||;True|2025-12-02T14:36:37.1529072+08:00||;True|2025-12-02T12:58:22.0951548+08:00||;True|2025-12-02T09:30:33.7066474+08:00||;True|2025-12-02T09:30:14.5481844+08:00||;True|2025-12-02T09:30:00.3123364+08:00||;False|2025-12-02T09:29:54.4615520+08:00||;True|2025-12-02T09:13:01.7995414+08:00||;False|2025-12-02T09:12:55.8360281+08:00||;True|2025-12-02T09:12:31.0156791+08:00||;True|2025-12-02T08:55:11.3773395+08:00||;True|2025-12-02T08:53:21.3927713+08:00||;False|2025-12-02T08:48:55.8638037+08:00||;True|2025-12-02T07:29:25.2192447+08:00||;False|2025-12-02T07:29:10.2504665+08:00||;True|2025-12-02T07:28:29.0769286+08:00||;True|2025-12-01T21:53:07.6474834+08:00||;True|2025-12-01T21:44:28.1674315+08:00||;True|2025-12-01T21:18:47.2119609+08:00||;True|2025-12-01T20:51:19.9948301+08:00||;True|2025-12-01T20:50:36.9904697+08:00||;True|2025-12-01T20:44:10.1695142+08:00||;True|2025-12-01T19:27:58.0479456+08:00||;True|2025-12-01T19:16:02.2288214+08:00||;False|2025-12-01T19:15:56.0372115+08:00||;True|2025-12-01T19:15:16.4854821+08:00||;False|2025-12-01T19:15:06.7001019+08:00||;True|2025-12-01T17:10:38.9739466+08:00||;False|2025-12-01T17:10:18.8928139+08:00||;True|2025-12-01T17:03:59.3171589+08:00||;True|2025-12-01T17:03:12.5681656+08:00||;</History> <History>True|2025-12-21T05:23:11.0272294Z||;True|2025-12-21T13:22:56.8339811+08:00||;False|2025-12-21T13:22:50.2395530+08:00||;True|2025-12-21T13:11:36.6129339+08:00||;True|2025-12-21T12:15:18.4086793+08:00||;True|2025-12-21T12:15:11.4448190+08:00||;True|2025-12-20T14:05:36.6224332+08:00||;False|2025-12-20T14:05:28.6359828+08:00||;True|2025-12-20T13:58:30.1641630+08:00||;True|2025-12-20T13:55:16.1759645+08:00||;True|2025-12-20T12:16:22.5224516+08:00||;True|2025-12-19T09:50:16.9517676+08:00||;True|2025-12-19T09:49:47.0871734+08:00||;False|2025-12-19T09:49:36.7638757+08:00||;True|2025-12-19T09:35:13.2489248+08:00||;True|2025-12-14T19:09:59.9031104+08:00||;True|2025-12-13T21:21:10.0022707+08:00||;True|2025-12-11T22:07:16.6229994+08:00||;True|2025-12-11T22:05:56.7363206+08:00||;True|2025-12-11T22:01:07.5862406+08:00||;True|2025-12-11T22:00:43.5796594+08:00||;True|2025-12-08T21:20:37.8369271+08:00||;False|2025-12-08T21:20:21.1646252+08:00||;True|2025-12-08T20:51:50.6845619+08:00||;True|2025-12-08T16:43:45.2425324+08:00||;False|2025-12-08T16:42:23.0308163+08:00||;True|2025-12-08T16:41:52.4103868+08:00||;True|2025-12-08T16:41:49.8972006+08:00||;False|2025-12-08T16:41:39.5343442+08:00||;True|2025-12-08T12:40:19.2430740+08:00||;True|2025-12-08T12:02:30.6005542+08:00||;True|2025-12-08T11:34:29.6673185+08:00||;False|2025-12-08T11:30:56.2857042+08:00||;True|2025-12-08T10:52:43.7427594+08:00||;True|2025-12-08T07:05:03.2845531+08:00||;True|2025-12-07T23:02:10.0037815+08:00||;True|2025-12-07T22:48:25.7859648+08:00||;True|2025-12-07T20:49:13.6683281+08:00||;True|2025-12-07T08:47:30.1236366+08:00||;True|2025-12-06T13:14:32.4410202+08:00||;True|2025-12-06T13:07:29.7182102+08:00||;True|2025-12-06T13:05:46.2855366+08:00||;False|2025-12-06T13:05:40.3550904+08:00||;True|2025-12-06T13:03:47.8773880+08:00||;True|2025-12-06T13:03:28.9521030+08:00||;True|2025-12-05T23:11:51.5026151+08:00||;True|2025-12-05T12:46:26.1415079+08:00||;False|2025-12-05T12:46:19.1274332+08:00||;True|2025-12-05T09:04:36.7111717+08:00||;True|2025-12-05T08:22:51.7343317+08:00||;True|2025-12-05T08:20:32.0383739+08:00||;True|2025-12-04T21:58:29.4112766+08:00||;True|2025-12-04T21:58:10.0382218+08:00||;True|2025-12-04T21:57:55.3894059+08:00||;True|2025-12-04T21:10:38.8943797+08:00||;True|2025-12-04T21:09:31.5024569+08:00||;True|2025-12-04T08:22:47.9617427+08:00||;False|2025-12-04T08:22:41.3759733+08:00||;True|2025-12-04T08:14:02.2478893+08:00||;True|2025-12-04T07:57:00.2208139+08:00||;True|2025-12-03T23:58:13.3693303+08:00||;True|2025-12-03T23:57:40.4257893+08:00||;True|2025-12-03T23:56:38.8717769+08:00||;True|2025-12-03T23:56:24.0663568+08:00||;False|2025-12-03T23:55:36.1902974+08:00||;True|2025-12-03T23:51:30.6688504+08:00||;True|2025-12-03T23:34:17.1648971+08:00||;False|2025-12-03T23:34:07.7649161+08:00||;True|2025-12-03T22:32:56.2435003+08:00||;True|2025-12-03T22:27:45.6059666+08:00||;True|2025-12-03T15:55:28.0186597+08:00||;False|2025-12-03T15:54:17.5032724+08:00||;True|2025-12-03T15:53:10.2273509+08:00||;True|2025-12-02T22:11:37.4645042+08:00||;False|2025-12-02T22:10:47.1320259+08:00||;True|2025-12-02T14:39:58.8932130+08:00||;True|2025-12-02T14:36:37.1529072+08:00||;True|2025-12-02T12:58:22.0951548+08:00||;True|2025-12-02T09:30:33.7066474+08:00||;True|2025-12-02T09:30:14.5481844+08:00||;True|2025-12-02T09:30:00.3123364+08:00||;False|2025-12-02T09:29:54.4615520+08:00||;True|2025-12-02T09:13:01.7995414+08:00||;False|2025-12-02T09:12:55.8360281+08:00||;True|2025-12-02T09:12:31.0156791+08:00||;True|2025-12-02T08:55:11.3773395+08:00||;True|2025-12-02T08:53:21.3927713+08:00||;False|2025-12-02T08:48:55.8638037+08:00||;True|2025-12-02T07:29:25.2192447+08:00||;False|2025-12-02T07:29:10.2504665+08:00||;True|2025-12-02T07:28:29.0769286+08:00||;True|2025-12-01T21:53:07.6474834+08:00||;True|2025-12-01T21:44:28.1674315+08:00||;True|2025-12-01T21:18:47.2119609+08:00||;True|2025-12-01T20:51:19.9948301+08:00||;True|2025-12-01T20:50:36.9904697+08:00||;True|2025-12-01T20:44:10.1695142+08:00||;True|2025-12-01T19:27:58.0479456+08:00||;True|2025-12-01T19:16:02.2288214+08:00||;False|2025-12-01T19:15:56.0372115+08:00||;</History>
<LastFailureDetails /> <LastFailureDetails />
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
-1
View File
@@ -33,7 +33,6 @@ const enforceMobileRoute = () => {
const currentPath = route.path.toLowerCase().trim(); const currentPath = route.path.toLowerCase().trim();
// 核心规则:手机浏览器 → 强制跳转到/mobile(无论当前路由是什么) // 核心规则:手机浏览器 → 强制跳转到/mobile(无论当前路由是什么)
console.log(isMobileBrowser.value);
if (isMobileBrowser.value) { if (isMobileBrowser.value) {
if (currentPath !== targetMobilePath) { if (currentPath !== targetMobilePath) {
// 替换路由(禁止返回上一页,避免用户回退到其他路由) // 替换路由(禁止返回上一页,避免用户回退到其他路由)
+282 -66
View File
@@ -10,19 +10,18 @@
<div class="stat-header"> <div class="stat-header">
<div class="header-left"> <div class="header-left">
<span class="stat-meta">视频统计</span> <span class="stat-meta">视频统计</span>
<div class="stat-value"> <!-- 拆分视频总数和总空间到左右两侧 -->
<div class="combined-values"> <div class="stat-value-container">
<span class="video-count">{{ totalVideos }}</span> <div class="stat-value video-count">
<span class="size-count">({{ fileSizeTotal }}G)</span> {{ totalVideos }}
<span class="value-label"></span>
</div>
<div class="stat-value size-count">
{{ fileSizeTotal }}G
</div> </div>
</div> </div>
</div> </div>
<div class="stat-icon video-icon"> <!-- 移除SVG图标 -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="23 7 16 12 23 17 23 7"></polygon>
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect>
</svg>
</div>
</div> </div>
<div class="stat-subitems"> <div class="stat-subitems">
<div class="subitem" :title="`我喜欢的视频数: ${favoriteCount} (占用: ${favoriteSize}G)`"> <div class="subitem" :title="`我喜欢的视频数: ${favoriteCount} (占用: ${favoriteSize}G)`">
@@ -31,8 +30,9 @@
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path> <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path>
</svg> </svg>
</div> </div>
<span class="subitem-meta">我喜欢的</span> <!-- 子项调整数量放在label后占用空间单独显示 -->
<span class="subitem-value">{{ favoriteCount }} <span class="unit">({{ favoriteSize }}G)</span></span> <span class="subitem-meta">我喜欢的 <span class="subitem-count">({{ favoriteCount }})</span></span>
<span class="subitem-size">{{ favoriteSize }}G</span>
</div> </div>
<div class="subitem" :title="`我收藏的视频数: ${collectCount} (占用: ${collectSize}G)`"> <div class="subitem" :title="`我收藏的视频数: ${collectCount} (占用: ${collectSize}G)`">
<div class="subitem-icon collect-icon"> <div class="subitem-icon collect-icon">
@@ -40,8 +40,8 @@
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path> <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>
</svg> </svg>
</div> </div>
<span class="subitem-meta">我收藏的</span> <span class="subitem-meta">我收藏的 <span class="subitem-count">({{ collectCount }})</span></span>
<span class="subitem-value">{{ collectCount }} <span class="unit">({{ collectSize }}G)</span></span> <span class="subitem-size">{{ collectSize }}G</span>
</div> </div>
<div class="subitem" :title="`我关注的视频数: ${followCount} (占用: ${followSize}G)`"> <div class="subitem" :title="`我关注的视频数: ${followCount} (占用: ${followSize}G)`">
<div class="subitem-icon follow-icon"> <div class="subitem-icon follow-icon">
@@ -52,8 +52,8 @@
<line x1="23" y1="11" x2="17" y2="11"></line> <line x1="23" y1="11" x2="17" y2="11"></line>
</svg> </svg>
</div> </div>
<span class="subitem-meta">我关注的</span> <span class="subitem-meta">我关注的 <span class="subitem-count">({{ followCount }})</span></span>
<span class="subitem-value">{{ followCount }} <span class="unit">({{ followSize }}G)</span></span> <span class="subitem-size">{{ followSize }}G</span>
</div> </div>
<div class="subitem" :title="`图文视频数: ${graphicVideoCount} (占用: ${graphicVideoSize}G)`"> <div class="subitem" :title="`图文视频数: ${graphicVideoCount} (占用: ${graphicVideoSize}G)`">
<div class="subitem-icon graphic-icon"> <div class="subitem-icon graphic-icon">
@@ -63,8 +63,8 @@
<polyline points="21 15 16 10 5 21"></polyline> <polyline points="21 15 16 10 5 21"></polyline>
</svg> </svg>
</div> </div>
<span class="subitem-meta">图文视频</span> <span class="subitem-meta">图文视频 <span class="subitem-count">({{ graphicVideoCount }})</span></span>
<span class="subitem-value">{{ graphicVideoCount }} <span class="unit">({{ graphicVideoSize }}G)</span></span> <span class="subitem-size">{{ graphicVideoSize }}G</span>
</div> </div>
</div> </div>
</div> </div>
@@ -76,21 +76,14 @@
<span class="stat-meta">最新同步</span> <span class="stat-meta">最新同步</span>
<!-- <div class="stat-value">TOP {{ topVideos.length }}</div> --> <!-- <div class="stat-value">TOP {{ topVideos.length }}</div> -->
</div> </div>
<div class="stat-icon size-icon"> <!-- 移除SVG图标 -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path>
</svg>
</div>
</div> </div>
<div class="stat-subitems video-list-container"> <div class="stat-subitems video-list-container">
<div v-for="(video, index) in topVideos" :key="index" class="subitem video-item" :title="video.title"> <div v-for="(video, index) in topVideos" :key="index" class="subitem video-item" :title="video.title">
<!-- <div class="subitem-icon video-list-icon">
<span class="video-index">{{ index + 1 }}</span>
</div> -->
<div class="video-info"> <div class="video-info">
<span class="subitem-meta video-title">{{ video.title }}</span> <!-- 点击标题播放视频 -->
<span class="subitem-value video-time">{{ formatVideoTime(video.time) }}</span> <span class="subitem-meta video-title" @click="openVideoPlayer(video)">{{ video.title }}</span>
<span class="subitem-value video-time">{{ video.time }}</span>
</div> </div>
</div> </div>
<div v-if="topVideos.length === 0" class="empty-video-list"> <div v-if="topVideos.length === 0" class="empty-video-list">
@@ -191,6 +184,39 @@
</div> </div>
</div> </div>
</div> </div>
<!-- 新增视频播放弹窗移动端适配 -->
<div v-if="showVideoPlayer" class="video-modal-mask" @click="closeVideoPlayer">
<div class="video-modal-content" @click.stop>
<div class="video-modal-header">
<h3 class="video-title-text"></h3>
<button class="video-close-btn" @click="closeVideoPlayer">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div class="video-modal-body">
<div v-if="videoLoading" class="video-loading">
<div class="loading-spinner"></div>
<p>加载视频中...</p>
</div>
<div v-else-if="videoError" class="video-error">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#f44336" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="8" x2="12" y2="12"></line>
<line x1="12" y1="16" x2="12.01" y2="16"></line>
</svg>
<p>视频加载失败</p>
<button class="retry-btn" @click="loadVideo(currentVideo)">重试</button>
</div>
<video v-else class="video-player" controls autoplay playsinline :src="videoPlayUrl" @error="handleVideoError">
您的浏览器不支持HTML5视频播放
</video>
</div>
</div>
</div>
</div> </div>
</template> </template>
@@ -222,11 +248,11 @@ interface LogItem {
fileName: string; fileName: string;
} }
// 新增 TopVideo 类型接口 // 新增 TopVideo 类型接口(增加videoId字段)
interface TopVideoItem { interface TopVideoItem {
title: string; title: string;
time: string; time: string;
[key: string]: any; // 其他字段 id: string; // 视频ID
} }
// 状态管理(仅保留核心数据) // 状态管理(仅保留核心数据)
@@ -254,6 +280,13 @@ const logContent = ref<string>('');
// Top Videos 相关状态 // Top Videos 相关状态
const topVideos = ref<TopVideoItem[]>([]); const topVideos = ref<TopVideoItem[]>([]);
// 新增:视频播放相关状态
const showVideoPlayer = ref<boolean>(false);
const currentVideo = ref<TopVideoItem | null>(null);
const videoPlayUrl = ref<string>('');
const videoLoading = ref<boolean>(false);
const videoError = ref<boolean>(false);
// 过滤后的日志列表 // 过滤后的日志列表
const filteredLogs = computed(() => { const filteredLogs = computed(() => {
if (logFilter.value === 'all') { if (logFilter.value === 'all') {
@@ -305,7 +338,7 @@ const loadLogData = async () => {
} }
}; };
// 加载热门视频数据 // 加载最新同步的视频5个
const TopVideo = () => { const TopVideo = () => {
useApiStore() useApiStore()
.TopVideo(5) .TopVideo(5)
@@ -316,27 +349,6 @@ const TopVideo = () => {
}); });
}; };
// 格式化视频时间显示(适配移动端显示)
const formatVideoTime = (timeStr?: string) => {
if (!timeStr) return '未知时间';
// 移动端适配的时间格式化
if (!isNaN(Number(timeStr))) {
const date = new Date(Number(timeStr));
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
.getDate()
.toString()
.padStart(2, '0')}`;
}
// 如果是8位数字日期(20251219
if (timeStr.length === 8 && /^\d+$/.test(timeStr)) {
return `${timeStr.slice(0, 4)}-${timeStr.slice(4, 6)}-${timeStr.slice(6, 8)}`;
}
return timeStr;
};
// 打开日志详情弹窗 // 打开日志详情弹窗
const openLogDetail = (log: LogItem) => { const openLogDetail = (log: LogItem) => {
currentLog.value = log; currentLog.value = log;
@@ -431,6 +443,49 @@ const fallbackCopyTextToClipboard = (text: string) => {
document.body.removeChild(textArea); document.body.removeChild(textArea);
}; };
// 新增:打开视频播放弹窗
const openVideoPlayer = (video: TopVideoItem) => {
if (!video.id) {
message.warn('视频ID不存在,无法播放');
return;
}
currentVideo.value = video;
showVideoPlayer.value = true;
loadVideo(video);
};
// 新增:加载视频播放地址
const loadVideo = async (video: TopVideoItem) => {
try {
videoLoading.value = true;
videoError.value = false;
const timestamp = new Date().getTime();
videoPlayUrl.value = `${import.meta.env.VITE_API_URL}api/Video/play/${video.id}?t=${timestamp}`;
} catch (err) {
console.error('加载视频失败:', err);
videoError.value = true;
message.error('视频加载失败,请稍后重试');
} finally {
videoLoading.value = false;
}
};
// 新增:关闭视频播放弹窗
const closeVideoPlayer = () => {
showVideoPlayer.value = false;
currentVideo.value = null;
videoPlayUrl.value = '';
videoLoading.value = false;
videoError.value = false;
};
// 新增:处理视频播放错误
const handleVideoError = () => {
videoError.value = true;
console.error('视频播放出错');
};
</script> </script>
<style scoped> <style scoped>
@@ -488,6 +543,7 @@ const fallbackCopyTextToClipboard = (text: string) => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
width: 100%;
} }
.stat-meta { .stat-meta {
font-size: 14px; font-size: 14px;
@@ -496,27 +552,31 @@ const fallbackCopyTextToClipboard = (text: string) => {
letter-spacing: 0.4px; letter-spacing: 0.4px;
font-weight: 500; font-weight: 500;
} }
/* 新增:视频总数和总空间容器样式 */
.stat-value-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-top: 8px;
}
.stat-value { .stat-value {
font-size: 20px; font-size: 26px;
font-weight: 700; font-weight: 700;
color: #1a1a1a; color: #1a1a1a;
line-height: 1.1; line-height: 1.1;
display: flex;
align-items: baseline;
gap: 6px;
} }
/* 合并数值样式(保持移动端视觉统一) */ .value-label {
.combined-values { font-size: 14px;
display: flex; color: #666;
align-items: baseline; font-weight: 500;
gap: 0px; margin-left: 4px;
font-size: 28px;
} }
.video-count { .video-count {
font-size: 26px; font-size: 22px;
} }
.size-count { .size-count {
font-size: 18px; font-size: 22px;
color: #666; color: #666;
} }
.unit { .unit {
@@ -557,6 +617,7 @@ const fallbackCopyTextToClipboard = (text: string) => {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
transition: all 0.2s ease; transition: all 0.2s ease;
cursor: default; cursor: default;
justify-content: space-between;
} }
.subitem:hover { .subitem:hover {
transform: translateY(-1px); transform: translateY(-1px);
@@ -601,6 +662,18 @@ const fallbackCopyTextToClipboard = (text: string) => {
font-weight: 500; font-weight: 500;
flex: 1; flex: 1;
} }
/* 新增:子项数量样式 */
.subitem-count {
color: #222;
font-weight: 600;
margin-left: 4px;
}
/* 新增:子项占用空间样式 */
.subitem-size {
font-size: 12px;
color: #999;
font-weight: 400;
}
/* 视频列表文字样式(适配移动端) */ /* 视频列表文字样式(适配移动端) */
.video-title { .video-title {
display: -webkit-box; display: -webkit-box;
@@ -612,6 +685,11 @@ const fallbackCopyTextToClipboard = (text: string) => {
max-height: 2.8em; /* 2行 * line-height */ max-height: 2.8em; /* 2行 * line-height */
width: 100%; width: 100%;
padding-right: 4px; padding-right: 4px;
cursor: pointer;
transition: color 0.2s;
}
.video-title:hover {
color: #2196f3;
} }
.video-time { .video-time {
font-size: 11px !important; font-size: 11px !important;
@@ -926,6 +1004,135 @@ const fallbackCopyTextToClipboard = (text: string) => {
background-color: #43a047; background-color: #43a047;
} }
/* 新增:视频播放弹窗样式(移动端适配) */
.video-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
padding: 0px;
box-sizing: border-box;
-webkit-backdrop-filter: blur(4px);
backdrop-filter: blur(4px);
}
.video-modal-content {
width: 100%;
max-width: 100%;
background-color: #111;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
max-height: 80vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.video-modal-header {
padding: 5px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #222;
}
.video-title-text {
font-size: 14px;
color: #fff;
font-weight: 500;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 80%;
}
.video-close-btn {
background: transparent;
border: none;
cursor: pointer;
color: #fff;
padding: 4px;
border-radius: 4px;
transition: all 0.2s ease;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
}
.video-close-btn:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.video-modal-body {
padding: 0;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
background-color: #000;
position: relative;
}
.video-player {
width: 100%;
height: 100%;
min-height: 200px;
max-height: 60vh;
object-fit: contain;
}
/* 视频加载状态 */
.video-loading {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
padding: 40px 20px;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(255, 255, 255, 0.2);
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
margin-bottom: 16px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* 视频错误状态 */
.video-error {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
padding: 40px 20px;
text-align: center;
}
.video-error p {
margin: 16px 0 24px;
font-size: 14px;
}
.retry-btn {
padding: 8px 16px;
background-color: #2196f3;
color: #fff;
border: none;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
}
.retry-btn:hover {
background-color: #1976d2;
}
/* 夜间模式(完全保留原有样式) */ /* 夜间模式(完全保留原有样式) */
html.dark-mode .stats-dashboard-mobile { html.dark-mode .stats-dashboard-mobile {
background-color: #1a1a2e; background-color: #1a1a2e;
@@ -953,7 +1160,10 @@ html.dark-mode .stat-meta {
html.dark-mode .stat-value { html.dark-mode .stat-value {
color: #ffffff; color: #ffffff;
} }
html.dark-mode .combined-values .size-count { html.dark-mode .value-label {
color: #d0d0d0;
}
html.dark-mode .size-count {
color: #d0d0d0; color: #d0d0d0;
} }
html.dark-mode .unit { html.dark-mode .unit {
@@ -968,6 +1178,12 @@ html.dark-mode .secondary-card .stat-icon {
html.dark-mode .subitem-meta { html.dark-mode .subitem-meta {
color: #c0c0d3; color: #c0c0d3;
} }
html.dark-mode .subitem-count {
color: #ffffff;
}
html.dark-mode .subitem-size {
color: #a0a0b3;
}
html.dark-mode .subitem-value { html.dark-mode .subitem-value {
color: #ffffff; color: #ffffff;
} }
+1 -1
View File
@@ -53,7 +53,7 @@ http.interceptors.response.use(
}).catch((err) => { }).catch((err) => {
console.error('跳转登录页失败:', err); // 关键!捕获跳转失败的原因 console.error('跳转登录页失败:', err); // 关键!捕获跳转失败的原因
}); });
}, 1000); }, 100);
} else { } else {
if (error.response && isAxiosResponse(error.response)) { if (error.response && isAxiosResponse(error.response)) {
+2
View File
@@ -6,5 +6,7 @@
public string Time { get; set; } public string Time { get; set; }
public string Id { get; set; }
} }
} }
+1 -1
View File
@@ -19,7 +19,7 @@ namespace dy.net.repository
public async Task<List<DouyinVideoTopDto>> GetTopsOrderBySyncTime(int top) public async Task<List<DouyinVideoTopDto>> GetTopsOrderBySyncTime(int top)
{ {
return await Db.Queryable<DouyinVideo>().Select(x=>new DouyinVideoTopDto { Title=x.VideoTitle,Time=x.SyncTime.ToString("yyyy-MM-dd HH:mm:ss")}).Take(top).OrderByDescending(x=>x.Time).ToListAsync(); return await Db.Queryable<DouyinVideo>().Select(x=>new DouyinVideoTopDto {Id=x.Id, Title=x.VideoTitle,Time=x.SyncTime.ToString("yyyy-MM-dd HH:mm:ss")}).Take(top).OrderByDescending(x=>x.Time).ToListAsync();
} }
/// <summary> /// <summary>
/// ///