样式优化
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using ClockSnowFlake;
|
using ClockSnowFlake;
|
||||||
using dy.net.dto;
|
using dy.net.dto;
|
||||||
|
using dy.net.extension;
|
||||||
using dy.net.model;
|
using dy.net.model;
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
@@ -395,11 +396,23 @@ namespace dy.net.Controllers
|
|||||||
public async Task<IActionResult> GetExistMps()
|
public async Task<IActionResult> GetExistMps()
|
||||||
{
|
{
|
||||||
var path = Path.Combine(AppContext.BaseDirectory, "mp3");
|
var path = Path.Combine(AppContext.BaseDirectory, "mp3");
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(ServiceExtension.FnDataFolder))
|
||||||
|
{
|
||||||
|
path = ServiceExtension.FnDataFolder;
|
||||||
|
}
|
||||||
|
|
||||||
if (Directory.Exists(path))
|
if (Directory.Exists(path))
|
||||||
{
|
{
|
||||||
var audioFiles = Directory.GetFiles(path);
|
var allowedExtensions = new HashSet<string> { ".mp3", ".wav" };
|
||||||
|
|
||||||
var fileNames = audioFiles.Select(f => new {filename= Path.GetFileName(f) }).Where(x=>x.filename!= "silent_10.mp3").ToList();
|
var customMusics = Directory.GetFiles(path)
|
||||||
|
.Where(filePath =>
|
||||||
|
allowedExtensions.Contains(Path.GetExtension(filePath).ToLowerInvariant()) &&
|
||||||
|
Path.GetFileNameWithoutExtension(filePath) != "silent_10")
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var fileNames = customMusics.Select(f => new {filename= Path.GetFileName(f) }).Where(x=>x.filename!= "silent_10.mp3").ToList();
|
||||||
return ApiResult.Success(fileNames);
|
return ApiResult.Success(fileNames);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -418,6 +431,11 @@ namespace dy.net.Controllers
|
|||||||
public async Task<IActionResult> GetMp3([FromQuery] string name)
|
public async Task<IActionResult> GetMp3([FromQuery] string name)
|
||||||
{
|
{
|
||||||
var path = Path.Combine(AppContext.BaseDirectory, "mp3", name);
|
var path = Path.Combine(AppContext.BaseDirectory, "mp3", name);
|
||||||
|
if (!string.IsNullOrWhiteSpace(ServiceExtension.FnDataFolder))
|
||||||
|
{
|
||||||
|
path = Path.Combine(ServiceExtension.FnDataFolder, name);
|
||||||
|
}
|
||||||
|
|
||||||
if (System.IO.File.Exists(path))
|
if (System.IO.File.Exists(path))
|
||||||
{
|
{
|
||||||
//返回mp3文件流
|
//返回mp3文件流
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<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|2026-01-14T17:10:48.9066941Z||;True|2026-01-15T01:03:23.6216975+08:00||;True|2026-01-15T01:03:16.3364591+08:00||;False|2026-01-15T01:03:10.5654436+08:00||;True|2026-01-15T00:49:21.6559622+08:00||;True|2026-01-15T00:10:42.7288439+08:00||;True|2026-01-15T00:06:28.4241682+08:00||;True|2026-01-13T22:34:15.2372411+08:00||;True|2026-01-13T22:26:46.4522947+08:00||;True|2026-01-13T22:15:56.9735179+08:00||;True|2026-01-13T22:15:51.8250677+08:00||;False|2026-01-13T22:15:46.6608690+08:00||;True|2026-01-13T22:03:06.4683237+08:00||;False|2026-01-13T22:03:01.2036027+08:00||;True|2026-01-13T21:36:05.8776209+08:00||;True|2026-01-13T21:33:02.0766289+08:00||;False|2026-01-13T21:32:57.1976141+08:00||;True|2026-01-13T19:14:35.2519439+08:00||;True|2026-01-13T15:07:50.0836745+08:00||;False|2026-01-13T15:06:35.5929685+08:00||;True|2026-01-13T10:21:41.6012776+08:00||;True|2026-01-13T09:57:25.4788847+08:00||;True|2026-01-13T09:53:14.4900360+08:00||;True|2026-01-13T09:23:53.6465295+08:00||;True|2026-01-12T22:04:14.5886955+08:00||;False|2026-01-12T22:04:08.2008101+08:00||;True|2026-01-12T21:53:46.9947176+08:00||;True|2026-01-12T21:11:15.8358024+08:00||;True|2026-01-12T21:09:51.8663228+08:00||;True|2026-01-11T21:25:07.5052845+08:00||;False|2026-01-11T21:24:27.5744557+08:00||;True|2026-01-11T19:59:15.4734611+08:00||;False|2026-01-11T19:59:04.9543339+08:00||;True|2026-01-11T18:51:30.6649269+08:00||;True|2026-01-08T21:07:57.5094466+08:00||;True|2026-01-08T14:51:18.2266231+08:00||;True|2026-01-08T14:31:55.1137120+08:00||;True|2026-01-08T00:16:24.4451490+08:00||;True|2026-01-08T00:14:20.7430793+08:00||;True|2026-01-08T00:07:46.7228194+08:00||;True|2026-01-07T23:52:13.3290082+08:00||;True|2026-01-07T23:49:28.4838650+08:00||;True|2026-01-07T23:47:45.1936189+08:00||;True|2026-01-07T23:35:09.7818611+08:00||;True|2026-01-07T23:20:43.7462863+08:00||;True|2026-01-07T23:04:39.5140429+08:00||;False|2026-01-07T23:04:36.5367611+08:00||;True|2026-01-07T22:53:14.6013449+08:00||;True|2026-01-07T22:49:59.9549006+08:00||;True|2026-01-07T22:36:40.0254856+08:00||;False|2026-01-07T22:36:28.8275903+08:00||;True|2026-01-07T21:59:51.4355171+08:00||;True|2026-01-03T21:38:51.4307034+08:00||;True|2026-01-02T19:09:16.9668906+08:00||;False|2026-01-02T19:09:11.7496369+08:00||;True|2026-01-02T15:42:08.2215697+08:00||;True|2026-01-02T09:46:56.1654861+08:00||;True|2026-01-02T09:35:28.0211225+08:00||;True|2026-01-01T23:07:01.9022045+08:00||;False|2026-01-01T23:06:56.0537216+08:00||;True|2026-01-01T22:16:10.2974067+08:00||;True|2026-01-01T22:16:06.2123787+08:00||;False|2026-01-01T22:15:33.3626979+08:00||;True|2026-01-01T22:01:30.7161900+08:00||;True|2026-01-01T21:10:19.3664263+08:00||;True|2026-01-01T21:09:38.6071080+08:00||;True|2025-12-30T11:45:54.5543034+08:00||;True|2025-12-30T09:19:08.3178124+08:00||;True|2025-12-29T18:57:29.7032246+08:00||;True|2025-12-27T14:52:24.4780776+08:00||;False|2025-12-27T14:52:19.5635794+08:00||;True|2025-12-27T14:48:01.6252748+08:00||;False|2025-12-27T14:47:55.7976192+08:00||;True|2025-12-27T14:38:23.9723838+08:00||;True|2025-12-27T13:00:29.8583858+08:00||;True|2025-12-26T22:18:42.4015637+08:00||;True|2025-12-26T22:10:58.5274572+08:00||;True|2025-12-26T22:06:26.3129600+08:00||;True|2025-12-26T22:03:55.6718618+08:00||;False|2025-12-26T22:03:48.3809954+08:00||;True|2025-12-26T22:02:33.1840390+08:00||;True|2025-12-26T22:01:16.1660100+08:00||;True|2025-12-25T00:50:26.1116465+08:00||;True|2025-12-25T00:48:27.3087708+08:00||;True|2025-12-25T00:47:38.4835720+08:00||;</History>
|
<History>True|2026-01-15T14:18:57.9835738Z||;True|2026-01-15T22:07:25.4753938+08:00||;True|2026-01-15T22:07:14.8243754+08:00||;True|2026-01-15T21:40:13.2613927+08:00||;True|2026-01-15T20:57:56.6291682+08:00||;True|2026-01-15T20:57:47.1363536+08:00||;True|2026-01-15T20:08:44.4710883+08:00||;True|2026-01-15T20:04:51.8284314+08:00||;False|2026-01-15T20:04:45.3258155+08:00||;True|2026-01-15T19:59:11.7907672+08:00||;True|2026-01-15T01:10:48.9066941+08:00||;True|2026-01-15T01:03:23.6216975+08:00||;True|2026-01-15T01:03:16.3364591+08:00||;False|2026-01-15T01:03:10.5654436+08:00||;True|2026-01-15T00:49:21.6559622+08:00||;True|2026-01-15T00:10:42.7288439+08:00||;True|2026-01-15T00:06:28.4241682+08:00||;True|2026-01-13T22:34:15.2372411+08:00||;True|2026-01-13T22:26:46.4522947+08:00||;True|2026-01-13T22:15:56.9735179+08:00||;True|2026-01-13T22:15:51.8250677+08:00||;False|2026-01-13T22:15:46.6608690+08:00||;True|2026-01-13T22:03:06.4683237+08:00||;False|2026-01-13T22:03:01.2036027+08:00||;True|2026-01-13T21:36:05.8776209+08:00||;True|2026-01-13T21:33:02.0766289+08:00||;False|2026-01-13T21:32:57.1976141+08:00||;True|2026-01-13T19:14:35.2519439+08:00||;True|2026-01-13T15:07:50.0836745+08:00||;False|2026-01-13T15:06:35.5929685+08:00||;True|2026-01-13T10:21:41.6012776+08:00||;True|2026-01-13T09:57:25.4788847+08:00||;True|2026-01-13T09:53:14.4900360+08:00||;True|2026-01-13T09:23:53.6465295+08:00||;True|2026-01-12T22:04:14.5886955+08:00||;False|2026-01-12T22:04:08.2008101+08:00||;True|2026-01-12T21:53:46.9947176+08:00||;True|2026-01-12T21:11:15.8358024+08:00||;True|2026-01-12T21:09:51.8663228+08:00||;True|2026-01-11T21:25:07.5052845+08:00||;False|2026-01-11T21:24:27.5744557+08:00||;True|2026-01-11T19:59:15.4734611+08:00||;False|2026-01-11T19:59:04.9543339+08:00||;True|2026-01-11T18:51:30.6649269+08:00||;True|2026-01-08T21:07:57.5094466+08:00||;True|2026-01-08T14:51:18.2266231+08:00||;True|2026-01-08T14:31:55.1137120+08:00||;True|2026-01-08T00:16:24.4451490+08:00||;True|2026-01-08T00:14:20.7430793+08:00||;True|2026-01-08T00:07:46.7228194+08:00||;True|2026-01-07T23:52:13.3290082+08:00||;True|2026-01-07T23:49:28.4838650+08:00||;True|2026-01-07T23:47:45.1936189+08:00||;True|2026-01-07T23:35:09.7818611+08:00||;True|2026-01-07T23:20:43.7462863+08:00||;True|2026-01-07T23:04:39.5140429+08:00||;False|2026-01-07T23:04:36.5367611+08:00||;True|2026-01-07T22:53:14.6013449+08:00||;True|2026-01-07T22:49:59.9549006+08:00||;True|2026-01-07T22:36:40.0254856+08:00||;False|2026-01-07T22:36:28.8275903+08:00||;True|2026-01-07T21:59:51.4355171+08:00||;True|2026-01-03T21:38:51.4307034+08:00||;True|2026-01-02T19:09:16.9668906+08:00||;False|2026-01-02T19:09:11.7496369+08:00||;True|2026-01-02T15:42:08.2215697+08:00||;True|2026-01-02T09:46:56.1654861+08:00||;True|2026-01-02T09:35:28.0211225+08:00||;True|2026-01-01T23:07:01.9022045+08:00||;False|2026-01-01T23:06:56.0537216+08:00||;True|2026-01-01T22:16:10.2974067+08:00||;True|2026-01-01T22:16:06.2123787+08:00||;False|2026-01-01T22:15:33.3626979+08:00||;True|2026-01-01T22:01:30.7161900+08:00||;True|2026-01-01T21:10:19.3664263+08:00||;True|2026-01-01T21:09:38.6071080+08:00||;True|2025-12-30T11:45:54.5543034+08:00||;True|2025-12-30T09:19:08.3178124+08:00||;True|2025-12-29T18:57:29.7032246+08:00||;True|2025-12-27T14:52:24.4780776+08:00||;False|2025-12-27T14:52:19.5635794+08:00||;True|2025-12-27T14:48:01.6252748+08:00||;False|2025-12-27T14:47:55.7976192+08:00||;True|2025-12-27T14:38:23.9723838+08:00||;True|2025-12-27T13:00:29.8583858+08:00||;True|2025-12-26T22:18:42.4015637+08:00||;True|2025-12-26T22:10:58.5274572+08:00||;True|2025-12-26T22:06:26.3129600+08:00||;True|2025-12-26T22:03:55.6718618+08:00||;False|2025-12-26T22:03:48.3809954+08:00||;True|2025-12-26T22:02:33.1840390+08:00||;True|2025-12-26T22:01:16.1660100+08:00||;True|2025-12-25T00:50:26.1116465+08:00||;True|2025-12-25T00:48:27.3087708+08:00||;True|2025-12-25T00:47:38.4835720+08:00||;</History>
|
||||||
<LastFailureDetails />
|
<LastFailureDetails />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -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|2026-01-14T17:12:37.7594645Z||;True|2026-01-15T00:48:09.3576293+08:00||;True|2026-01-15T00:36:39.6208221+08:00||;True|2026-01-15T00:36:29.1250549+08:00||;False|2026-01-15T00:36:18.2658521+08:00||;True|2026-01-13T22:27:04.3807307+08:00||;True|2026-01-08T14:31:13.4473659+08:00||;True|2026-01-08T00:19:20.8948701+08:00||;True|2026-01-07T21:59:04.8702022+08:00||;True|2026-01-03T21:42:41.3864639+08:00||;False|2026-01-03T21:42:26.7041325+08:00||;True|2026-01-02T09:32:11.1396877+08:00||;True|2026-01-01T23:30:38.0205783+08:00||;True|2026-01-01T23:29:35.2877898+08:00||;False|2026-01-01T23:27:39.5930556+08:00||;False|2026-01-01T23:24:52.0996222+08:00||;False|2026-01-01T23:24:09.0444840+08:00||;False|2026-01-01T23:24:06.1610789+08:00||;False|2026-01-01T23:24:03.3178410+08:00||;False|2026-01-01T23:22:56.2224992+08:00||;False|2026-01-01T23:22:47.8246988+08:00||;False|2026-01-01T23:22:43.2890820+08:00||;True|2026-01-01T23:21:03.6027351+08:00||;True|2026-01-01T23:07:57.5938094+08:00||;True|2025-12-29T18:55:45.8262096+08:00||;True|2025-12-28T00:21:04.1648410+08:00||;True|2025-12-28T00:18:49.2137559+08:00||;True|2025-12-28T00:14:18.1456892+08:00||;True|2025-12-28T00:11:06.6645248+08:00||;False|2025-12-28T00:10:49.4906020+08:00||;True|2025-12-27T23:51:57.6426264+08:00||;True|2025-12-27T23:40:08.4783210+08:00||;True|2025-12-27T14:59:32.0605406+08:00||;False|2025-12-27T14:59:21.2076690+08:00||;True|2025-12-27T12:58:06.9934830+08:00||;True|2025-12-27T12:51:45.3402320+08:00||;True|2025-12-27T12:45:49.9795040+08:00||;True|2025-12-27T12:42:13.9395619+08:00||;True|2025-12-27T11:32:35.8851241+08:00||;True|2025-12-27T11:32:11.1199261+08:00||;True|2025-12-27T11:31:34.3939619+08:00||;True|2025-12-26T22:39:54.4903900+08:00||;False|2025-12-26T22:39:38.9956198+08:00||;True|2025-12-26T13:29:16.3817938+08:00||;True|2025-12-26T13:13:27.1756564+08:00||;True|2025-12-26T13:12:27.5681845+08:00||;True|2025-12-25T21:53:39.9851108+08:00||;True|2025-12-25T21:14:06.5238213+08:00||;True|2025-12-25T14:05:40.5153425+08:00||;True|2025-12-25T00:52:42.0632072+08:00||;False|2025-12-25T00:52:36.5033522+08:00||;True|2025-12-24T20:47:03.4244585+08:00||;True|2025-12-24T20:38:49.1905853+08:00||;True|2025-12-24T20:38:18.7336590+08:00||;True|2025-12-24T20:33:27.1126773+08:00||;True|2025-12-24T20:32:29.2799273+08:00||;True|2025-12-23T20:55:43.6793723+08:00||;True|2025-12-23T20:54:55.9960612+08:00||;True|2025-12-21T13:23:11.0272294+08:00||;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||;</History>
|
<History>True|2026-01-15T14:26:32.5592635Z||;False|2026-01-15T22:26:22.8207579+08:00||;True|2026-01-15T20:11:16.7025777+08:00||;True|2026-01-15T01:27:08.0668895+08:00||;True|2026-01-15T01:22:47.5988241+08:00||;True|2026-01-15T01:20:09.5613415+08:00||;True|2026-01-15T01:12:37.7594645+08:00||;True|2026-01-15T00:48:09.3576293+08:00||;True|2026-01-15T00:36:39.6208221+08:00||;True|2026-01-15T00:36:29.1250549+08:00||;False|2026-01-15T00:36:18.2658521+08:00||;True|2026-01-13T22:27:04.3807307+08:00||;True|2026-01-08T14:31:13.4473659+08:00||;True|2026-01-08T00:19:20.8948701+08:00||;True|2026-01-07T21:59:04.8702022+08:00||;True|2026-01-03T21:42:41.3864639+08:00||;False|2026-01-03T21:42:26.7041325+08:00||;True|2026-01-02T09:32:11.1396877+08:00||;True|2026-01-01T23:30:38.0205783+08:00||;True|2026-01-01T23:29:35.2877898+08:00||;False|2026-01-01T23:27:39.5930556+08:00||;False|2026-01-01T23:24:52.0996222+08:00||;False|2026-01-01T23:24:09.0444840+08:00||;False|2026-01-01T23:24:06.1610789+08:00||;False|2026-01-01T23:24:03.3178410+08:00||;False|2026-01-01T23:22:56.2224992+08:00||;False|2026-01-01T23:22:47.8246988+08:00||;False|2026-01-01T23:22:43.2890820+08:00||;True|2026-01-01T23:21:03.6027351+08:00||;True|2026-01-01T23:07:57.5938094+08:00||;True|2025-12-29T18:55:45.8262096+08:00||;True|2025-12-28T00:21:04.1648410+08:00||;True|2025-12-28T00:18:49.2137559+08:00||;True|2025-12-28T00:14:18.1456892+08:00||;True|2025-12-28T00:11:06.6645248+08:00||;False|2025-12-28T00:10:49.4906020+08:00||;True|2025-12-27T23:51:57.6426264+08:00||;True|2025-12-27T23:40:08.4783210+08:00||;True|2025-12-27T14:59:32.0605406+08:00||;False|2025-12-27T14:59:21.2076690+08:00||;True|2025-12-27T12:58:06.9934830+08:00||;True|2025-12-27T12:51:45.3402320+08:00||;True|2025-12-27T12:45:49.9795040+08:00||;True|2025-12-27T12:42:13.9395619+08:00||;True|2025-12-27T11:32:35.8851241+08:00||;True|2025-12-27T11:32:11.1199261+08:00||;True|2025-12-27T11:31:34.3939619+08:00||;True|2025-12-26T22:39:54.4903900+08:00||;False|2025-12-26T22:39:38.9956198+08:00||;True|2025-12-26T13:29:16.3817938+08:00||;True|2025-12-26T13:13:27.1756564+08:00||;True|2025-12-26T13:12:27.5681845+08:00||;True|2025-12-25T21:53:39.9851108+08:00||;True|2025-12-25T21:14:06.5238213+08:00||;True|2025-12-25T14:05:40.5153425+08:00||;True|2025-12-25T00:52:42.0632072+08:00||;False|2025-12-25T00:52:36.5033522+08:00||;True|2025-12-24T20:47:03.4244585+08:00||;True|2025-12-24T20:38:49.1905853+08:00||;True|2025-12-24T20:38:18.7336590+08:00||;True|2025-12-24T20:33:27.1126773+08:00||;True|2025-12-24T20:32:29.2799273+08:00||;True|2025-12-23T20:55:43.6793723+08:00||;True|2025-12-23T20:54:55.9960612+08:00||;True|2025-12-21T13:23:11.0272294+08:00||;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||;</History>
|
||||||
<LastFailureDetails />
|
<LastFailureDetails />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -3,14 +3,12 @@
|
|||||||
<div class="dashboard-container">
|
<div class="dashboard-container">
|
||||||
<!-- 看板 Tab 内容 -->
|
<!-- 看板 Tab 内容 -->
|
||||||
<div v-if="activeTab === 'dashboard'" class="tab-content">
|
<div v-if="activeTab === 'dashboard'" class="tab-content">
|
||||||
<!-- 仅显示核心统计概览(无底部详细数据) -->
|
|
||||||
<section class="stats-overview">
|
<section class="stats-overview">
|
||||||
<!-- 合并后的总视频数和空间总计卡片(保留原有移动端样式) -->
|
<!-- 合并后的总视频数和空间总计卡片 -->
|
||||||
<div class="stat-card primary-card main-card">
|
<div class="stat-card primary-card main-card">
|
||||||
<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-container">
|
<div class="stat-value-container">
|
||||||
<div class="stat-value video-count">
|
<div class="stat-value video-count">
|
||||||
{{ totalVideos }}
|
{{ totalVideos }}
|
||||||
@@ -21,7 +19,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 移除SVG图标 -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="stat-subitems">
|
<div class="stat-subitems">
|
||||||
<div class="subitem" :title="`我喜欢的视频数: ${favoriteCount} (占用: ${favoriteSize}G)`">
|
<div class="subitem" :title="`我喜欢的视频数: ${favoriteCount} (占用: ${favoriteSize}G)`">
|
||||||
@@ -30,7 +27,6 @@
|
|||||||
<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>
|
||||||
<!-- 子项调整:数量放在label后,占用空间单独显示 -->
|
|
||||||
<span class="subitem-meta">我喜欢的 <span class="subitem-count">({{ favoriteCount }})</span></span>
|
<span class="subitem-meta">我喜欢的 <span class="subitem-count">({{ favoriteCount }})</span></span>
|
||||||
<span class="subitem-size">{{ favoriteSize }}G</span>
|
<span class="subitem-size">{{ favoriteSize }}G</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,19 +65,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 新增 Top Videos 列表(使用原有移动端卡片样式体系) -->
|
<!-- 最新同步视频列表 -->
|
||||||
<div class="stat-card secondary-card main-card">
|
<div class="stat-card secondary-card main-card">
|
||||||
<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">TOP {{ topVideos.length }}</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
<!-- 移除SVG图标 -->
|
|
||||||
</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="video-info">
|
<div class="video-info">
|
||||||
<!-- 点击标题播放视频 -->
|
|
||||||
<span class="subitem-meta video-title" @click="openVideoPlayer(video)">{{ video.title }}</span>
|
<span class="subitem-meta video-title" @click="openVideoPlayer(video)">{{ video.title }}</span>
|
||||||
<span class="subitem-value video-time">{{ video.time }}</span>
|
<span class="subitem-value video-time">{{ video.time }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,7 +87,7 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 日志 Tab 内容(完全保留原有样式) -->
|
<!-- 日志 Tab 内容 -->
|
||||||
<div v-if="activeTab === 'log'" class="tab-content log-tab">
|
<div v-if="activeTab === 'log'" class="tab-content log-tab">
|
||||||
<div class="log-header">
|
<div class="log-header">
|
||||||
<h2 class="log-title">系统日志</h2>
|
<h2 class="log-title">系统日志</h2>
|
||||||
@@ -129,7 +122,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 底部导航菜单(完全保留原有样式) -->
|
<!-- 底部导航菜单 -->
|
||||||
<div class="bottom-nav">
|
<div class="bottom-nav">
|
||||||
<div class="nav-item" :class="{ active: activeTab === 'dashboard' }" @click="activeTab = 'dashboard'">
|
<div class="nav-item" :class="{ active: activeTab === 'dashboard' }" @click="activeTab = 'dashboard'">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
@@ -150,7 +143,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 日志详情弹窗(完全保留原有样式) -->
|
<!-- 日志详情弹窗 -->
|
||||||
<div v-if="showLogModal" class="log-modal-mask" @click="closeLogModal">
|
<div v-if="showLogModal" class="log-modal-mask" @click="closeLogModal">
|
||||||
<div class="log-modal-content" @click.stop>
|
<div class="log-modal-content" @click.stop>
|
||||||
<div class="log-modal-header">
|
<div class="log-modal-header">
|
||||||
@@ -169,7 +162,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="log-modal-body">
|
<div class="log-modal-body">
|
||||||
<div class="file-name">{{ currentLog?.fileName }}</div>
|
<!-- <div class="file-name">{{ currentLog?.fileName }}</div> -->
|
||||||
<pre class="log-content">{{ logContent || '加载日志内容中...' }}</pre>
|
<pre class="log-content">{{ logContent || '加载日志内容中...' }}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -179,16 +172,15 @@
|
|||||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||||
</svg>
|
</svg>
|
||||||
复制日志
|
复制
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 新增:视频播放弹窗(全屏适配+暂停显示删除按钮) -->
|
<!-- 视频播放弹窗(竖屏铺满+横屏适配,无旋转) -->
|
||||||
<div v-if="showVideoPlayer" class="video-modal-mask" @click="closeVideoPlayer">
|
<div v-if="showVideoPlayer" class="video-modal-mask" @click="closeVideoPlayer">
|
||||||
<div class="video-modal-content" @click.stop>
|
<div class="video-modal-content" @click.stop>
|
||||||
<!-- 移除原有标题栏,将关闭按钮直接放在内容容器内,实现悬浮 -->
|
|
||||||
<button class="video-close-btn floating-close-btn" @click="closeVideoPlayer">
|
<button class="video-close-btn floating-close-btn" @click="closeVideoPlayer">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||||
@@ -197,12 +189,10 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="video-modal-body">
|
<div class="video-modal-body">
|
||||||
<!-- 加载中状态 -->
|
|
||||||
<div v-if="videoLoading" class="video-loading">
|
<div v-if="videoLoading" class="video-loading">
|
||||||
<div class="loading-spinner"></div>
|
<div class="loading-spinner"></div>
|
||||||
<p>加载视频中...</p>
|
<p>加载视频中...</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- 错误状态 -->
|
|
||||||
<div v-else-if="videoError" class="video-error">
|
<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">
|
<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>
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
@@ -212,24 +202,18 @@
|
|||||||
<p>视频加载失败</p>
|
<p>视频加载失败</p>
|
||||||
<button class="retry-btn" @click="loadVideo(currentVideo)">重试</button>
|
<button class="retry-btn" @click="loadVideo(currentVideo)">重试</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- 视频播放区域:添加ref用于获取视频实例,绑定暂停/播放事件 -->
|
|
||||||
<div v-else class="video-player-wrapper">
|
<div v-else class="video-player-wrapper">
|
||||||
<video ref="videoPlayerRef" class="video-player" controls autoplay playsinline :src="videoPlayUrl" @error="handleVideoError" @pause="onVideoPause" @play="onVideoPlay">
|
<video ref="videoPlayerRef" class="video-player" controls autoplay playsinline :src="videoPlayUrl" @error="handleVideoError" @pause="onVideoPause" @play="onVideoPlay" width="100%" height="100%" preload="auto" @loadedmetadata="handleVideoLoadedMetadata">
|
||||||
您的浏览器不支持HTML5视频播放
|
您的浏览器不支持HTML5视频播放
|
||||||
</video>
|
</video>
|
||||||
<!-- 悬浮透明删除X按钮:仅暂停时显示 -->
|
|
||||||
<button class="video-delete-btn" v-show="isVideoPaused" @click.stop="deleteCurrentVideo" title="删除该视频">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" 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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, computed } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import { useApiStore } from '@/store';
|
import { useApiStore } from '@/store';
|
||||||
@@ -258,14 +242,13 @@ interface LogItem {
|
|||||||
fileName: string;
|
fileName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增 TopVideo 类型接口(增加videoId字段)
|
|
||||||
interface TopVideoItem {
|
interface TopVideoItem {
|
||||||
title: string;
|
title: string;
|
||||||
time: string;
|
time: string;
|
||||||
id: string; // 视频ID
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 状态管理(仅保留核心数据)
|
// 状态管理
|
||||||
const totalVideos = ref<number>(0);
|
const totalVideos = ref<number>(0);
|
||||||
const fileSizeTotal = ref<string>('0.00');
|
const fileSizeTotal = ref<string>('0.00');
|
||||||
const favoriteCount = ref<number>(0);
|
const favoriteCount = ref<number>(0);
|
||||||
@@ -290,15 +273,14 @@ const logContent = ref<string>('');
|
|||||||
// Top Videos 相关状态
|
// Top Videos 相关状态
|
||||||
const topVideos = ref<TopVideoItem[]>([]);
|
const topVideos = ref<TopVideoItem[]>([]);
|
||||||
|
|
||||||
// 新增:视频播放相关状态
|
// 视频播放相关状态(无旋转相关)
|
||||||
const showVideoPlayer = ref<boolean>(false);
|
const showVideoPlayer = ref<boolean>(false);
|
||||||
const currentVideo = ref<TopVideoItem | null>(null);
|
const currentVideo = ref<TopVideoItem | null>(null);
|
||||||
const videoPlayUrl = ref<string>('');
|
const videoPlayUrl = ref<string>('');
|
||||||
const videoLoading = ref<boolean>(false);
|
const videoLoading = ref<boolean>(false);
|
||||||
const videoError = ref<boolean>(false);
|
const videoError = ref<boolean>(false);
|
||||||
// 新增:视频实例引用和暂停状态
|
|
||||||
const videoPlayerRef = ref<HTMLVideoElement | null>(null);
|
const videoPlayerRef = ref<HTMLVideoElement | null>(null);
|
||||||
const isVideoPaused = ref<boolean>(false); // 控制删除按钮显示
|
const isVideoPaused = ref<boolean>(false);
|
||||||
|
|
||||||
// 过滤后的日志列表
|
// 过滤后的日志列表
|
||||||
const filteredLogs = computed(() => {
|
const filteredLogs = computed(() => {
|
||||||
@@ -315,7 +297,7 @@ defineOptions({ name: 'StatsDashboardMobile' });
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadDashboardData();
|
loadDashboardData();
|
||||||
loadLogData();
|
loadLogData();
|
||||||
TopVideo(); // 加载热门视频数据
|
TopVideo();
|
||||||
});
|
});
|
||||||
|
|
||||||
const loadDashboardData = async () => {
|
const loadDashboardData = async () => {
|
||||||
@@ -336,7 +318,6 @@ const loadDashboardData = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载日志数据(模拟接口,实际项目中替换为真实接口)
|
|
||||||
const loadLogData = async () => {
|
const loadLogData = async () => {
|
||||||
try {
|
try {
|
||||||
useApiStore()
|
useApiStore()
|
||||||
@@ -351,7 +332,6 @@ const loadLogData = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载最新同步的视频10个
|
|
||||||
const TopVideo = () => {
|
const TopVideo = () => {
|
||||||
useApiStore()
|
useApiStore()
|
||||||
.TopVideo(10)
|
.TopVideo(10)
|
||||||
@@ -362,21 +342,18 @@ const TopVideo = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开日志详情弹窗
|
|
||||||
const openLogDetail = (log: LogItem) => {
|
const openLogDetail = (log: LogItem) => {
|
||||||
currentLog.value = log;
|
currentLog.value = log;
|
||||||
showLogModal.value = true;
|
showLogModal.value = true;
|
||||||
loadLogDetailContent(log);
|
loadLogDetailContent(log);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭日志详情弹窗
|
|
||||||
const closeLogModal = () => {
|
const closeLogModal = () => {
|
||||||
showLogModal.value = false;
|
showLogModal.value = false;
|
||||||
currentLog.value = null;
|
currentLog.value = null;
|
||||||
logContent.value = '';
|
logContent.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载日志详情内容
|
|
||||||
const loadLogDetailContent = (log: LogItem) => {
|
const loadLogDetailContent = (log: LogItem) => {
|
||||||
try {
|
try {
|
||||||
const type = log.type.toLowerCase();
|
const type = log.type.toLowerCase();
|
||||||
@@ -402,19 +379,16 @@ const loadLogDetailContent = (log: LogItem) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 格式化日期显示(20251211 → 2025-12-11)
|
|
||||||
const formatShowDate = (dateStr?: string) => {
|
const formatShowDate = (dateStr?: string) => {
|
||||||
if (!dateStr || dateStr.length !== 8) return dateStr || '';
|
if (!dateStr || dateStr.length !== 8) return dateStr || '';
|
||||||
return `${dateStr.slice(0, 4)}-${dateStr.slice(4, 6)}-${dateStr.slice(6, 8)}`;
|
return `${dateStr.slice(0, 4)}-${dateStr.slice(4, 6)}-${dateStr.slice(6, 8)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理日志时间戳,仅保留时分秒
|
|
||||||
const formatLogTime = (logContent: string) => {
|
const formatLogTime = (logContent: string) => {
|
||||||
const timeRegex = /\d{4}-\d{2}-\d{2} (\d{2}:\d{2}:\d{2})\.\d+ \+08:00/g;
|
const timeRegex = /\d{4}-\d{2}-\d{2} (\d{2}:\d{2}:\d{2})\.\d+ \+08:00/g;
|
||||||
return logContent.replace(timeRegex, '$1');
|
return logContent.replace(timeRegex, '$1');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 复制日志内容(移动端兼容)
|
|
||||||
const copyLogContent = () => {
|
const copyLogContent = () => {
|
||||||
if (!logContent.value) {
|
if (!logContent.value) {
|
||||||
message.warn('暂无日志内容可复制');
|
message.warn('暂无日志内容可复制');
|
||||||
@@ -433,7 +407,6 @@ const copyLogContent = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 复制降级方案(适配移动端)
|
|
||||||
const fallbackCopyTextToClipboard = (text: string) => {
|
const fallbackCopyTextToClipboard = (text: string) => {
|
||||||
const textArea = document.createElement('textarea');
|
const textArea = document.createElement('textarea');
|
||||||
textArea.value = text;
|
textArea.value = text;
|
||||||
@@ -457,7 +430,6 @@ const fallbackCopyTextToClipboard = (text: string) => {
|
|||||||
document.body.removeChild(textArea);
|
document.body.removeChild(textArea);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 新增:打开视频播放弹窗
|
|
||||||
const openVideoPlayer = (video: TopVideoItem) => {
|
const openVideoPlayer = (video: TopVideoItem) => {
|
||||||
if (!video.id) {
|
if (!video.id) {
|
||||||
message.warn('视频ID不存在,无法播放');
|
message.warn('视频ID不存在,无法播放');
|
||||||
@@ -467,20 +439,22 @@ const openVideoPlayer = (video: TopVideoItem) => {
|
|||||||
currentVideo.value = video;
|
currentVideo.value = video;
|
||||||
showVideoPlayer.value = true;
|
showVideoPlayer.value = true;
|
||||||
loadVideo(video).then(() => {
|
loadVideo(video).then(() => {
|
||||||
// 视频加载完成后触发播放,避免浏览器拦截
|
|
||||||
if (videoPlayerRef.value) {
|
if (videoPlayerRef.value) {
|
||||||
videoPlayerRef.value.play().catch((err) => console.log('自动播放被拦截:', err));
|
videoPlayerRef.value.play().catch((err) => console.log('自动播放被拦截:', err));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 新增:加载视频播放地址
|
|
||||||
const loadVideo = async (video: TopVideoItem) => {
|
const loadVideo = async (video: TopVideoItem) => {
|
||||||
try {
|
try {
|
||||||
videoLoading.value = true;
|
videoLoading.value = true;
|
||||||
videoError.value = false;
|
videoError.value = false;
|
||||||
const timestamp = new Date().getTime();
|
const timestamp = new Date().getTime();
|
||||||
videoPlayUrl.value = `${import.meta.env.VITE_API_URL}api/Video/play/${video.id}?t=${timestamp}`;
|
videoPlayUrl.value = `${import.meta.env.VITE_API_URL}api/Video/play/${video.id}?t=${timestamp}`;
|
||||||
|
if (videoPlayerRef.value) {
|
||||||
|
videoPlayerRef.value.style.width = '100%';
|
||||||
|
videoPlayerRef.value.style.height = '100%';
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('加载视频失败:', err);
|
console.error('加载视频失败:', err);
|
||||||
videoError.value = true;
|
videoError.value = true;
|
||||||
@@ -490,60 +464,117 @@ const loadVideo = async (video: TopVideoItem) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 新增:关闭视频播放弹窗
|
|
||||||
const closeVideoPlayer = () => {
|
const closeVideoPlayer = () => {
|
||||||
showVideoPlayer.value = false;
|
showVideoPlayer.value = false;
|
||||||
currentVideo.value = null;
|
currentVideo.value = null;
|
||||||
videoPlayUrl.value = '';
|
videoPlayUrl.value = '';
|
||||||
videoLoading.value = false;
|
videoLoading.value = false;
|
||||||
videoError.value = false;
|
videoError.value = false;
|
||||||
isVideoPaused.value = false; // 重置暂停状态
|
isVideoPaused.value = false;
|
||||||
|
if (videoPlayerRef.value) {
|
||||||
|
videoPlayerRef.value.pause();
|
||||||
|
videoPlayerRef.value.style.width = '100%';
|
||||||
|
videoPlayerRef.value.style.height = '100%';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 新增:处理视频播放错误
|
|
||||||
const handleVideoError = () => {
|
const handleVideoError = () => {
|
||||||
videoError.value = true;
|
videoError.value = true;
|
||||||
console.error('视频播放出错');
|
console.error('视频播放出错');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 新增:视频暂停回调
|
|
||||||
const onVideoPause = () => {
|
const onVideoPause = () => {
|
||||||
isVideoPaused.value = true;
|
isVideoPaused.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 新增:视频播放回调
|
|
||||||
const onVideoPlay = () => {
|
const onVideoPlay = () => {
|
||||||
isVideoPaused.value = false;
|
isVideoPaused.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteCurrentVideo = async () => {
|
const deleteCurrentVideo = async () => {
|
||||||
// 关闭播放弹窗,刷新视频列表
|
|
||||||
closeVideoPlayer();
|
closeVideoPlayer();
|
||||||
TopVideo(); // 重新加载最新视频列表
|
TopVideo();
|
||||||
loadDashboardData(); // 刷新仪表盘统计数据
|
loadDashboardData();
|
||||||
|
};
|
||||||
|
// 视频加载完成后,动态获取视频尺寸并调整容器
|
||||||
|
const handleVideoLoadedMetadata = () => {
|
||||||
|
if (!videoPlayerRef.value) return;
|
||||||
|
|
||||||
|
// 获取视频原宽高比
|
||||||
|
const videoWidth = videoPlayerRef.value.videoWidth;
|
||||||
|
const videoHeight = videoPlayerRef.value.videoHeight;
|
||||||
|
const videoRatio = videoWidth / videoHeight; // 宽/高:>1 横向,≤1 竖向
|
||||||
|
|
||||||
|
// 获取播放器容器
|
||||||
|
const wrapper = document.querySelector('.video-player-wrapper');
|
||||||
|
if (!wrapper) return;
|
||||||
|
const wrapperWidth = wrapper.clientWidth;
|
||||||
|
const wrapperHeight = wrapper.clientHeight;
|
||||||
|
|
||||||
|
const video = videoPlayerRef.value;
|
||||||
|
|
||||||
|
// 1. 竖向视频(高≥宽):全屏填满,无黑边
|
||||||
|
if (videoRatio <= 1) {
|
||||||
|
video.style.width = '100%';
|
||||||
|
video.style.height = '100%';
|
||||||
|
video.style.objectFit = 'cover'; // 填满容器,裁剪多余部分
|
||||||
|
video.style.margin = '0';
|
||||||
|
video.style.position = 'static';
|
||||||
|
}
|
||||||
|
// 2. 横向视频(宽>高):居中显示,完整保留,上下黑边
|
||||||
|
else {
|
||||||
|
// 重置为 contain,确保视频完整显示
|
||||||
|
video.style.objectFit = 'contain';
|
||||||
|
video.style.width = '100%';
|
||||||
|
video.style.height = '100%';
|
||||||
|
// 强制视频垂直+水平居中,解决下方没填满的问题
|
||||||
|
video.style.position = 'absolute';
|
||||||
|
video.style.top = '50%';
|
||||||
|
video.style.left = '50%';
|
||||||
|
video.style.transform = 'translate(-50%, -50%)';
|
||||||
|
// 可选:限制横向视频最大高度不超过容器,避免溢出
|
||||||
|
video.style.maxHeight = '100%';
|
||||||
|
video.style.maxWidth = '100%';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<!-- 全局样式,放在 scoped 样式外 -->
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
#app {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* 完全保留原有移动端样式 */
|
|
||||||
.stats-dashboard-mobile {
|
.stats-dashboard-mobile {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
padding: 15px 0;
|
padding: 5px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-bottom: 80px; /* 为底部导航留出空间 */
|
padding-bottom: 80px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.dashboard-container {
|
.dashboard-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 15px;
|
padding: 0 5px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
-webkit-overflow-scrolling: touch; /* 移动端弹性滚动 */
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
.tab-content {
|
.tab-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -553,10 +584,10 @@ const deleteCurrentVideo = async () => {
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
.main-card {
|
.main-card {
|
||||||
padding: 20px 16px;
|
padding: 0px 10px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
@@ -588,7 +619,6 @@ const deleteCurrentVideo = async () => {
|
|||||||
letter-spacing: 0.4px;
|
letter-spacing: 0.4px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
/* 新增:视频总数和总空间容器样式 */
|
|
||||||
.stat-value-container {
|
.stat-value-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -683,7 +713,6 @@ const deleteCurrentVideo = async () => {
|
|||||||
background-color: rgba(255, 159, 64, 0.1);
|
background-color: rgba(255, 159, 64, 0.1);
|
||||||
color: #d9091a;
|
color: #d9091a;
|
||||||
}
|
}
|
||||||
/* 视频列表图标样式(沿用原有样式体系) */
|
|
||||||
.video-list-icon {
|
.video-list-icon {
|
||||||
background-color: rgba(33, 150, 243, 0.15);
|
background-color: rgba(33, 150, 243, 0.15);
|
||||||
color: #2196f3;
|
color: #2196f3;
|
||||||
@@ -698,27 +727,24 @@ const deleteCurrentVideo = async () => {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
/* 新增:子项数量样式 */
|
|
||||||
.subitem-count {
|
.subitem-count {
|
||||||
color: #222;
|
color: #222;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
/* 新增:子项占用空间样式 */
|
|
||||||
.subitem-size {
|
.subitem-size {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #999;
|
color: #999;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
/* 视频列表文字样式(适配移动端) */
|
|
||||||
.video-title {
|
.video-title {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 2; /* 显示2行 */
|
-webkit-line-clamp: 2;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
max-height: 2.8em; /* 2行 * line-height */
|
max-height: 2.8em;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -733,8 +759,8 @@ const deleteCurrentVideo = async () => {
|
|||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
font-weight: 300 !important;
|
font-weight: 300 !important;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center; /* 垂直居中 */
|
align-items: center;
|
||||||
justify-content: flex-end; /* 水平右对齐 */
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
.video-info {
|
.video-info {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -759,16 +785,14 @@ const deleteCurrentVideo = async () => {
|
|||||||
.secondary-card {
|
.secondary-card {
|
||||||
border-top: 3px solid #2196f3;
|
border-top: 3px solid #2196f3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 空视频列表样式(适配移动端) */
|
|
||||||
.empty-video-list {
|
.empty-video-list {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 20px 0;
|
padding: 10px 0;
|
||||||
color: #999;
|
color: #999;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部导航样式(完全保留) */
|
/* 底部导航样式 */
|
||||||
.bottom-nav {
|
.bottom-nav {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@@ -809,9 +833,9 @@ const deleteCurrentVideo = async () => {
|
|||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 日志 Tab 样式(完全保留) */
|
/* 日志 Tab 样式 */
|
||||||
.log-tab {
|
.log-tab {
|
||||||
padding: 10px 0;
|
padding: 5px 0;
|
||||||
}
|
}
|
||||||
.log-header {
|
.log-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -851,15 +875,15 @@ const deleteCurrentVideo = async () => {
|
|||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 日志列表样式(完全保留) */
|
/* 日志列表样式 */
|
||||||
.log-list {
|
.log-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
.log-item {
|
.log-item {
|
||||||
padding: 15px;
|
padding: 10px;
|
||||||
border-radius: 8px;
|
border-radius: 5px;
|
||||||
border: 1px solid #f0f0f0;
|
border: 1px solid #f0f0f0;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
@@ -912,7 +936,7 @@ const deleteCurrentVideo = async () => {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 日志详情弹窗样式(完全保留) */
|
/* 日志详情弹窗样式 */
|
||||||
.log-modal-mask {
|
.log-modal-mask {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -924,7 +948,7 @@ const deleteCurrentVideo = async () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
padding: 20px;
|
padding: 10px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.log-modal-content {
|
.log-modal-content {
|
||||||
@@ -938,7 +962,7 @@ const deleteCurrentVideo = async () => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.log-modal-header {
|
.log-modal-header {
|
||||||
padding: 10px;
|
padding: 5px;
|
||||||
border-bottom: 1px solid #f0f0f0;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -1014,7 +1038,7 @@ const deleteCurrentVideo = async () => {
|
|||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
.log-modal-footer {
|
.log-modal-footer {
|
||||||
padding: 16px 20px;
|
padding: 5px 20px;
|
||||||
border-top: 1px solid #f0f0f0;
|
border-top: 1px solid #f0f0f0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
@@ -1039,41 +1063,66 @@ const deleteCurrentVideo = async () => {
|
|||||||
.copy-btn:hover:not(:disabled) {
|
.copy-btn:hover:not(:disabled) {
|
||||||
background-color: #43a047;
|
background-color: #43a047;
|
||||||
}
|
}
|
||||||
/* 视频播放弹窗样式(纯全屏+悬浮右上角关闭按钮) */
|
/* 视频弹窗遮罩:确保全屏无偏移 */
|
||||||
.video-modal-mask {
|
.video-modal-mask {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: #000; /* 纯黑背景更贴合全屏播放 */
|
background-color: #000;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-webkit-backdrop-filter: blur(4px);
|
overflow: hidden;
|
||||||
backdrop-filter: blur(4px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 视频弹窗内容:全屏铺满,无内边距 */
|
||||||
.video-modal-content {
|
.video-modal-content {
|
||||||
width: 100vw; /* 视口宽度100% */
|
width: 100vw;
|
||||||
height: 100vh; /* 视口高度100% */
|
height: 100vh;
|
||||||
max-width: none; /* 移除原有最大宽度限制 */
|
max-width: none;
|
||||||
max-height: none; /* 移除原有最大高度限制 */
|
max-height: none;
|
||||||
background-color: #111;
|
background-color: #000; /* 改为纯黑,即使有微小留白也不明显 */
|
||||||
border-radius: 0; /* 全屏移除圆角 */
|
border-radius: 0;
|
||||||
box-shadow: none; /* 全屏无需阴影 */
|
box-shadow: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative; /* 为悬浮关闭按钮提供定位上下文 */
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0; /* 确保无内边距 */
|
||||||
|
box-sizing: border-box;
|
||||||
|
/* iOS安全区域适配:不额外增加留白,直接填充状态栏 */
|
||||||
|
padding-top: env(safe-area-inset-top);
|
||||||
|
height: calc(100vh - env(safe-area-inset-top));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 视频播放器容器:全屏铺满,无额外空间 */
|
||||||
|
.video-player-wrapper {
|
||||||
|
position: relative; /* 新增:为视频绝对定位提供参考 */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
/* 消除安全区域带来的高度偏差 */
|
||||||
|
height: calc(100% - env(safe-area-inset-top));
|
||||||
|
/* 新增:确保容器内内容垂直居中(兜底) */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
/* 悬浮右上角关闭按钮样式 */
|
|
||||||
.floating-close-btn {
|
.floating-close-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20px; /* 右上角间距,可调整 */
|
top: env(safe-area-inset-top);
|
||||||
right: 20px; /* 右上角间距,可调整 */
|
right: 0px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@@ -1085,7 +1134,7 @@ const deleteCurrentVideo = async () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
z-index: 2010; /* 确保在视频上方 */
|
z-index: 2010;
|
||||||
backdrop-filter: blur(2px);
|
backdrop-filter: blur(2px);
|
||||||
}
|
}
|
||||||
.floating-close-btn:hover {
|
.floating-close-btn:hover {
|
||||||
@@ -1101,20 +1150,29 @@ const deleteCurrentVideo = async () => {
|
|||||||
background-color: #000;
|
background-color: #000;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%; /* 完全填充父容器,无高度损耗 */
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
/* 新增:视频播放器容器(用于定位删除按钮) */
|
|
||||||
.video-player-wrapper {
|
.video-player-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
height: calc(100% - env(safe-area-inset-top));
|
||||||
}
|
}
|
||||||
.video-player {
|
.video-player {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: contain; /* 保持视频比例,全屏填充无黑边(也可改为 cover 强制填充,可能裁剪视频) */
|
object-fit: cover;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
/* 悬浮透明删除X按钮样式 */
|
|
||||||
.video-delete-btn {
|
.video-delete-btn {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1139,7 +1197,6 @@ const deleteCurrentVideo = async () => {
|
|||||||
background-color: rgba(244, 67, 54, 0.5);
|
background-color: rgba(244, 67, 54, 0.5);
|
||||||
transform: translateY(-50%) scale(1.1);
|
transform: translateY(-50%) scale(1.1);
|
||||||
}
|
}
|
||||||
/* 视频加载状态 */
|
|
||||||
.video-loading {
|
.video-loading {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -1164,7 +1221,6 @@ const deleteCurrentVideo = async () => {
|
|||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 视频错误状态 */
|
|
||||||
.video-error {
|
.video-error {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -1194,7 +1250,7 @@ const deleteCurrentVideo = async () => {
|
|||||||
background-color: #1976d2;
|
background-color: #1976d2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 夜间模式(完全保留原有样式) */
|
/* 夜间模式 */
|
||||||
html.dark-mode .stats-dashboard-mobile {
|
html.dark-mode .stats-dashboard-mobile {
|
||||||
background-color: #1a1a2e;
|
background-color: #1a1a2e;
|
||||||
color: #eaeaea;
|
color: #eaeaea;
|
||||||
@@ -1338,7 +1394,7 @@ html.dark-mode .close-btn:hover {
|
|||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 夜间模式 - 视频弹窗样式适配 */
|
/* 夜间模式 - 视频弹窗样式适配(移除旋转按钮相关) */
|
||||||
html.dark-mode .video-delete-btn {
|
html.dark-mode .video-delete-btn {
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
}
|
}
|
||||||
|
|||||||
+239
-142
@@ -1,196 +1,293 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="margin: 5px 0;">
|
<a-form layout="inline" style="margin-top:5px;margin-bottom:5px;align-items: center;">
|
||||||
<!-- 日志类型按钮组 -->
|
|
||||||
<a-button-group>
|
|
||||||
<a-button :type="typeValue === 'debug' ? 'primary' : 'default'" @click="typeValue = 'debug'; loadLogs()" class="type-btn">
|
|
||||||
普通日志
|
|
||||||
</a-button>
|
|
||||||
<a-button :type="typeValue === 'error' ? 'primary' : 'default'" @click="typeValue = 'error'; loadLogs()" class="type-btn">
|
|
||||||
错误日志
|
|
||||||
</a-button>
|
|
||||||
</a-button-group>
|
|
||||||
|
|
||||||
<!-- 日期操作按钮组(核心调整颜色) -->
|
|
||||||
<a-button-group style="margin-left: 10px;" class="date-btn-group">
|
|
||||||
<a-button @click="changeDate('prev')">前一天</a-button>
|
|
||||||
<a-button class="today-btn" @click="changeDate('current')">今天</a-button>
|
|
||||||
<a-button @click="changeDate('next')">下一天</a-button>
|
|
||||||
</a-button-group>
|
|
||||||
|
|
||||||
|
<!-- 日期控制 -->
|
||||||
|
<a-form-item>
|
||||||
|
<div class="date-control-group">
|
||||||
|
<a-button type="text" @click="handleDateMinus" class="date-btn"><left-outlined /></a-button>
|
||||||
|
<span class="current-date-text">{{ currentDateText }}</span>
|
||||||
|
<a-button type="text" @click="handleDatePlus" class="date-btn" :disabled="isToday"><right-outlined /></a-button>
|
||||||
</div>
|
</div>
|
||||||
|
</a-form-item>
|
||||||
<!-- 日志展示区域 -->
|
<!-- debug/error单选按钮 -->
|
||||||
<div class="log-container">
|
<a-form-item>
|
||||||
<a-card bordered>
|
<a-radio-group class="log-type-radio-group" v-model:value="typeValue" @change="typeChange" button-style="solid">
|
||||||
<pre class="log-content">{{ logs }}</pre>
|
<a-radio-button value="debug">debug</a-radio-button>
|
||||||
|
<a-radio-button value="error">error</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 复制按钮 - 同一行最右侧 -->
|
||||||
|
<a-form-item style="margin-left: auto;">
|
||||||
|
<a-button type="text" size="small" @click="copyLogs" class="copy-btn">
|
||||||
|
<copy-outlined />
|
||||||
|
</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<div class="container">
|
||||||
|
<a-card title="" :bordered="true" :class="{ 'log-error': typeValue === 'error' }">
|
||||||
|
<pre class="card-width-pre">{{ logs }}</pre>
|
||||||
</a-card>
|
</a-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import { useApiStore } from '@/store';
|
import { useApiStore } from '@/store';
|
||||||
import dayjs from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
import 'dayjs/locale/zh-cn';
|
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
// 初始化dayjs中文环境
|
|
||||||
dayjs.locale('zh-cn');
|
dayjs.locale('zh-cn');
|
||||||
|
|
||||||
// 核心变量(极简:只维护两个核心变量)
|
const currentDate = ref<Dayjs>(dayjs());
|
||||||
const typeValue = ref<string>('debug'); // 日志类型
|
const typeValue = ref<string>('debug');
|
||||||
const currentDate = ref<dayjs.Dayjs>(dayjs()); // 当前选中的日期(唯一日期变量)
|
const iframeUrl = ref<string>('');
|
||||||
const logs = ref<string>('加载中...'); // 日志内容
|
const logs = ref<string>('');
|
||||||
|
|
||||||
// 计算可访问的日期范围(近10天:今天 ~ 9天前)
|
const currentDateText = computed(() => {
|
||||||
const maxDate = computed(() => dayjs()); // 最大日期:今天
|
return currentDate.value.format('YYYYMMDD');
|
||||||
const minDate = computed(() => dayjs().subtract(9, 'day')); // 最小日期:9天前
|
});
|
||||||
|
|
||||||
// 格式化日期文本(供显示和请求使用)
|
const isToday = computed(() => {
|
||||||
const currentDateText = computed(() => currentDate.value.format('YYYYMMDD'));
|
return currentDate.value.isSame(dayjs(), 'day');
|
||||||
const minDateText = computed(() => minDate.value.format('YYYYMMDD'));
|
});
|
||||||
const maxDateText = computed(() => maxDate.value.format('YYYYMMDD'));
|
|
||||||
|
|
||||||
// 日期切换核心逻辑(极简:直接修改currentDate)
|
const handleDateMinus = () => {
|
||||||
const changeDate = (action: 'prev' | 'current' | 'next') => {
|
currentDate.value = currentDate.value.subtract(1, 'day');
|
||||||
let newDate: dayjs.Dayjs;
|
updateIframeUrlAndLoadLogs();
|
||||||
|
};
|
||||||
|
|
||||||
switch (action) {
|
const handleDatePlus = () => {
|
||||||
case 'prev':
|
if (isToday.value) return;
|
||||||
newDate = currentDate.value.subtract(1, 'day');
|
currentDate.value = currentDate.value.add(1, 'day');
|
||||||
break;
|
updateIframeUrlAndLoadLogs();
|
||||||
case 'next':
|
};
|
||||||
newDate = currentDate.value.add(1, 'day');
|
|
||||||
break;
|
|
||||||
case 'current':
|
|
||||||
default:
|
|
||||||
newDate = dayjs();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 范围校验:限制在10天内
|
const updateIframeUrlAndLoadLogs = () => {
|
||||||
if (newDate.isBefore(minDate.value)) {
|
iframeUrl.value = `${typeValue.value}/${currentDateText.value}`;
|
||||||
newDate = minDate.value;
|
|
||||||
logs.value = `已到最早可查看日期(${minDateText.value}),无法继续往前`;
|
|
||||||
} else if (newDate.isAfter(maxDate.value)) {
|
|
||||||
newDate = maxDate.value;
|
|
||||||
logs.value = `已到最新可查看日期(${maxDateText.value}),无法继续往后`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新当前日期并加载日志
|
|
||||||
currentDate.value = newDate;
|
|
||||||
loadLogs();
|
loadLogs();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载日志数据
|
const typeChange = (e: any) => {
|
||||||
const loadLogs = () => {
|
typeValue.value = e.target.value;
|
||||||
// 拼接请求参数
|
updateIframeUrlAndLoadLogs();
|
||||||
const params = `${typeValue.value}/${currentDateText.value}`;
|
};
|
||||||
|
|
||||||
// 调用接口加载日志
|
const formatLogTime = (logContent: string) => {
|
||||||
|
const timeRegex = /(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+ \+08:00/g;
|
||||||
|
return logContent.replace(timeRegex, '$1');
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadLogs = () => {
|
||||||
useApiStore()
|
useApiStore()
|
||||||
.apiGetLogs(params)
|
.apiGetLogs(iframeUrl.value)
|
||||||
.then((logContent) => {
|
.then((log) => {
|
||||||
if (!logContent) {
|
log = formatLogTime(log);
|
||||||
logs.value = `【${currentDateText.value}】暂无${typeValue.value === 'debug' ? '普通' : '错误'}日志数据`;
|
const lines = log.split('\n');
|
||||||
return;
|
const reversedLines = lines.reverse();
|
||||||
}
|
const reversedText = reversedLines.join('\n');
|
||||||
// 格式化日志时间(移除毫秒和时区)
|
logs.value = reversedText;
|
||||||
const formatLog = logContent.replace(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d+ \+08:00/g, '$1');
|
|
||||||
// 倒序显示
|
|
||||||
logs.value = formatLog.split('\n').reverse().join('\n');
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('加载日志失败:', err);
|
console.error('加载日志失败:', err);
|
||||||
logs.value = `加载日志失败:${err.message || '网络异常'}`;
|
logs.value = '日志加载失败,请稍后重试';
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面挂载时加载初始日志
|
// 复制日志内容的核心函数
|
||||||
|
const copyLogs = async () => {
|
||||||
|
try {
|
||||||
|
// 空内容判断
|
||||||
|
if (!logs.value || logs.value === '日志加载失败,请稍后重试') {
|
||||||
|
message.warning('暂无可复制的日志内容');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 使用浏览器剪贴板API复制内容
|
||||||
|
await navigator.clipboard.writeText(logs.value);
|
||||||
|
message.success('日志内容复制成功!');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('复制失败:', err);
|
||||||
|
// 降级方案:兼容不支持Clipboard API的浏览器
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = logs.value;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
// 提示反馈
|
||||||
|
message.success('日志内容复制成功!');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadLogs();
|
updateIframeUrlAndLoadLogs();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang='less' scoped>
|
<style lang='less' scoped>
|
||||||
// 日志展示容器样式
|
// 基础样式:仅清理默认margin/padding,不设置全屏
|
||||||
.log-container {
|
html,
|
||||||
width: 100%;
|
body {
|
||||||
height: calc(100vh - 80px);
|
height: 100vh;
|
||||||
margin-top: 10px;
|
|
||||||
|
|
||||||
.log-content {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-wrap: break-word;
|
|
||||||
height: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 15px;
|
padding: 0;
|
||||||
background: #f9f9f9;
|
}
|
||||||
|
|
||||||
|
// 表单容器:正常宽度,保留少量间距
|
||||||
|
:deep(.ant-form) {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日志容器:正常宽度(继承父元素),高度适配
|
||||||
|
.container {
|
||||||
|
width: 100%; // 继承父元素宽度,非全屏
|
||||||
|
height: calc(100vh - 50px); // 留出顶部表单高度,固定高度不溢出
|
||||||
|
padding: 0 8px; // 保留少量左右间距,视觉更友好
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden; // 新增:隐藏容器外溢出内容,避免挤压footer
|
||||||
|
}
|
||||||
|
// pre样式:继承card-body宽度(核心)
|
||||||
|
.card-width-pre {
|
||||||
|
width: 100% !important; // 完全继承父元素(card-body)宽度
|
||||||
|
min-width: 100%;
|
||||||
|
padding: 8px; // 合理内边距,避免内容贴边
|
||||||
|
margin: 0 !important;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
height: 100%; // 继承card-body高度
|
||||||
|
max-height: calc(100vh - 66px); // 新增:严格限制最大高度,避开表单+卡片内边距
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow-y: auto; // 保留:纵向滚动(优先显示垂直滚动条)
|
||||||
|
overflow-x: auto; // 保留:横向滚动(日志行过长时)
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
// 可选:美化滚动条(适配现代浏览器)
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px; // 垂直滚动条宽度
|
||||||
|
height: 6px; // 水平滚动条高度
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按钮组基础样式
|
.date-control-group {
|
||||||
:deep(.ant-btn-group) {
|
display: flex;
|
||||||
.ant-btn {
|
align-items: center;
|
||||||
height: 36px;
|
justify-content: center;
|
||||||
padding: 0 18px;
|
gap: 8px;
|
||||||
font-size: 14px;
|
|
||||||
border-radius: 0 !important; // 按钮组圆角处理
|
.date-btn {
|
||||||
transition: all 0.2s ease;
|
width: 36px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
// 第一个按钮左圆角
|
|
||||||
.ant-btn:first-child {
|
.current-date-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1f2329;
|
||||||
|
font-weight: 500;
|
||||||
|
min-width: 80px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制按钮样式
|
||||||
|
.copy-btn {
|
||||||
|
// height: 32px; /* 和日期按钮/单选按钮高度一致 */
|
||||||
|
// padding: 0 16px;
|
||||||
|
color: #722ed1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// card-body样式:恢复默认内边距,作为pre的宽度基准
|
||||||
|
:deep(.ant-card-body) {
|
||||||
|
padding: 4px; // 恢复合理内边距,作为pre的宽度容器
|
||||||
|
height: 100%; // 全屏继承容器高度
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden; // 新增:隐藏卡片内溢出,确保pre独占滚动区域
|
||||||
|
}
|
||||||
|
|
||||||
|
// error状态下pre文字颜色
|
||||||
|
.log-error {
|
||||||
|
.card-width-pre {
|
||||||
|
color: #f5222d !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// radio-button样式(保留之前的修正版)
|
||||||
|
:deep(.log-type-radio-group) {
|
||||||
|
.ant-radio-button-wrapper:first-child {
|
||||||
|
&.ant-radio-button-wrapper-checked {
|
||||||
|
background-color: #52c41a !important;
|
||||||
|
border-color: #52c41a !important;
|
||||||
|
color: #fff !important;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
background-color: #389e0d !important;
|
||||||
|
border-color: #389e0d !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.ant-radio-button-wrapper-checked):hover {
|
||||||
|
border-color: #73d13d !important;
|
||||||
|
color: #52c41a !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-radio-button-wrapper:last-child {
|
||||||
|
&.ant-radio-button-wrapper-checked {
|
||||||
|
background-color: #f5222d !important;
|
||||||
|
border-color: #f5222d !important;
|
||||||
|
color: #fff !important;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
background-color: #cf1322 !important;
|
||||||
|
border-color: #cf1322 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.ant-radio-button-wrapper-checked):hover {
|
||||||
|
border-color: #ff4d4f !important;
|
||||||
|
color: #f5222d !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-radio-button-wrapper {
|
||||||
|
&:first-child {
|
||||||
border-radius: 6px 0 0 6px !important;
|
border-radius: 6px 0 0 6px !important;
|
||||||
}
|
}
|
||||||
// 最后一个按钮右圆角
|
&:last-child {
|
||||||
.ant-btn:last-child {
|
|
||||||
border-radius: 0 6px 6px 0 !important;
|
border-radius: 0 6px 6px 0 !important;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ========== 核心修改:日期按钮颜色 ==========
|
&:not(:first-child) {
|
||||||
.date-btn-group {
|
margin-left: -1px !important;
|
||||||
:deep(.ant-btn) {
|
|
||||||
// 日期按钮默认样式
|
|
||||||
background: #fff;
|
|
||||||
border-color: #e6e6e6;
|
|
||||||
color: #333;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #f0f9ff;
|
|
||||||
border-color: #00b42a; // hover时边框变绿色
|
|
||||||
color: #00b42a;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// “今天”按钮高亮样式(核心颜色修改处)
|
.ant-radio-button-wrapper-checked {
|
||||||
:deep(.today-btn) {
|
&:first-child {
|
||||||
background: #00b42a !important; // 深绿色背景(可替换成你想要的颜色)
|
&::before {
|
||||||
border-color: #00b42a !important;
|
background-color: transparent !important;
|
||||||
color: #fff !important;
|
}
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #00c834 !important; // hover时稍浅的绿色
|
|
||||||
border-color: #00c834 !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 可选:日志类型按钮颜色也同步调整(可选) ==========
|
// 调整form布局,让复制按钮靠右
|
||||||
.type-btn {
|
:deep(.ant-form-inline) {
|
||||||
:deep(&.ant-btn-primary) {
|
display: flex;
|
||||||
background: #722ed1 !important; // 日志类型选中用紫色(可改)
|
align-items: center;
|
||||||
border-color: #722ed1 !important;
|
width: 100%;
|
||||||
color: #fff !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #8046e0 !important;
|
|
||||||
border-color: #8046e0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
<!-- 提示文本调整 -->
|
<!-- 提示文本调整 -->
|
||||||
<div class="flex items-start mt-1 text-sm text-gray-500" style="color:red">
|
<div class="flex items-start mt-1 text-sm text-gray-500" style="color:red">
|
||||||
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
|
<InfoCircleOutlined class="text-blue-400 mr-1 mt-0.5" />
|
||||||
<span>当下载图文视频时,音频因版权原因无法下载时,将用该音频文件作为合成视频的音频</span>
|
<span>当下载图文视频时,音频因版权原因无法下载时,将用该音频文件作为合成视频的音频(仅支持mp3、wav)</span>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
|||||||
@@ -25,15 +25,33 @@ const isMobile = (): boolean => {
|
|||||||
|
|
||||||
// 标记是否已跳转到移动端路由,防止无限循环
|
// 标记是否已跳转到移动端路由,防止无限循环
|
||||||
let hasRedirectedToMobile = false;
|
let hasRedirectedToMobile = false;
|
||||||
|
// 新增:标记是否已从/mobile跳转到/dashboard,防止无限循环
|
||||||
|
let hasRedirectedToDashboard = false;
|
||||||
// 优化后的移动端跳转守卫(登录优先)
|
// 优化后的移动端跳转守卫(登录优先)
|
||||||
const MobileRedirectGuard: NavigationGuard = function (to, from, next) {
|
const MobileRedirectGuard: NavigationGuard = function (to, from, next) {
|
||||||
// 1. 排除移动端路由和登录页,避免逻辑干扰
|
// 1. 排除移动端路由和登录页,避免逻辑干扰
|
||||||
const isMobileRoute = to.path === '/mobile';
|
const isMobileRoute = to.path === '/mobile';
|
||||||
const isLoginRoute = to.path === '/login';
|
const isLoginRoute = to.path === '/login';
|
||||||
|
// 新增:检测当前是否为非移动端设备
|
||||||
|
const isNonMobile = !isMobile();
|
||||||
|
|
||||||
|
// 【新增核心逻辑】:当前路由是/mobile,但不是移动端设备,跳转到/dashboard
|
||||||
|
if (isMobileRoute && isNonMobile) {
|
||||||
|
if (!hasRedirectedToDashboard) {
|
||||||
|
hasRedirectedToDashboard = true;
|
||||||
|
// 重置移动端跳转标记,避免后续干扰
|
||||||
|
hasRedirectedToMobile = false;
|
||||||
|
next({ path: '/dashboard' });
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isMobileRoute) {
|
if (isMobileRoute) {
|
||||||
hasRedirectedToMobile = true;
|
hasRedirectedToMobile = true;
|
||||||
|
// 重置dashboard跳转标记,避免后续干扰
|
||||||
|
hasRedirectedToDashboard = false;
|
||||||
next();
|
next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -41,6 +59,7 @@ const MobileRedirectGuard: NavigationGuard = function (to, from, next) {
|
|||||||
if (isLoginRoute) {
|
if (isLoginRoute) {
|
||||||
// 登录页无需移动端跳转,直接放行
|
// 登录页无需移动端跳转,直接放行
|
||||||
hasRedirectedToMobile = false; // 重置标记,登录后可正常跳转移动端
|
hasRedirectedToMobile = false; // 重置标记,登录后可正常跳转移动端
|
||||||
|
hasRedirectedToDashboard = false; // 重置dashboard跳转标记
|
||||||
next();
|
next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -55,30 +74,31 @@ const MobileRedirectGuard: NavigationGuard = function (to, from, next) {
|
|||||||
// 已登录:跳移动端(防止重复跳转)
|
// 已登录:跳移动端(防止重复跳转)
|
||||||
if (!hasRedirectedToMobile) {
|
if (!hasRedirectedToMobile) {
|
||||||
hasRedirectedToMobile = true;
|
hasRedirectedToMobile = true;
|
||||||
|
hasRedirectedToDashboard = false; // 重置dashboard跳转标记
|
||||||
next({ path: '/mobile' });
|
next({ path: '/mobile' });
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 非移动端:重置标记,不影响后续操作
|
// 非移动端:重置所有标记,不影响后续操作
|
||||||
hasRedirectedToMobile = false;
|
hasRedirectedToMobile = false;
|
||||||
|
hasRedirectedToDashboard = false;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 原有守卫逻辑(无修改)
|
|
||||||
const loginGuard: NavigationGuard = function (to, from, next) {
|
const loginGuard: NavigationGuard = function (to, from, next) {
|
||||||
if (!http.checkAuthorization() && !/^\/(init|login|home|mobile)?$/.test(to.fullPath)) {
|
if (!http.checkAuthorization() && !/^\/(init|login|home|mobile)?$/.test(to.fullPath)) {
|
||||||
console.log(to.fullPath)
|
console.log(to.fullPath)
|
||||||
const account = useAccountStore();
|
const account = useAccountStore();
|
||||||
account.setLogged(false);
|
account.setLogged(false);
|
||||||
|
// 重置dashboard跳转标记
|
||||||
|
hasRedirectedToDashboard = false;
|
||||||
next('/login');
|
next('/login');
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const dynamicinitRoute = {
|
const dynamicinitRoute = {
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
@@ -154,11 +174,24 @@ const NotFoundGuard: NaviGuard = {
|
|||||||
|
|
||||||
// 优化后的页面刷新移动端检测(登录优先)
|
// 优化后的页面刷新移动端检测(登录优先)
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
if (isMobile() && window.location.pathname !== '/mobile') {
|
const currentPath = window.location.pathname;
|
||||||
|
const isNonMobile = !isMobile();
|
||||||
|
|
||||||
|
// 【新增】:刷新后如果是/mobile路由且非移动端,跳转到/dashboard
|
||||||
|
if (currentPath === '/mobile' && isNonMobile) {
|
||||||
|
router.push('/dashboard').catch(err => {
|
||||||
|
if (!err.message.includes('NavigationDuplicated')) {
|
||||||
|
console.error('刷新时从/mobile跳转到/dashboard失败:', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMobile() && currentPath !== '/mobile') {
|
||||||
const isAuthorized = http.checkAuthorization();
|
const isAuthorized = http.checkAuthorization();
|
||||||
if (!isAuthorized) {
|
if (!isAuthorized) {
|
||||||
// 未登录:跳登录(避免重复跳转)
|
// 未登录:跳登录(避免重复跳转)
|
||||||
if (window.location.pathname !== '/login') {
|
if (currentPath !== '/login') {
|
||||||
router.push('/login').catch(err => {
|
router.push('/login').catch(err => {
|
||||||
if (!err.message.includes('NavigationDuplicated')) {
|
if (!err.message.includes('NavigationDuplicated')) {
|
||||||
console.error('刷新时跳转登录页失败:', err);
|
console.error('刷新时跳转登录页失败:', err);
|
||||||
|
|||||||
Reference in New Issue
Block a user