ow
This commit is contained in:
1 parent
7c8af2fb08
commit
c10f8347e2
31 files changed
+358
-292
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -34,8 +34,6 @@ public partial class Program
|
|||||||
string taskName = null;
|
string taskName = null;
|
||||||
Dictionary<string, string> bodyDict = new Dictionary<string, string>();
|
Dictionary<string, string> bodyDict = new Dictionary<string, string>();
|
||||||
|
|
||||||
File.AppendAllText("log.txt", "Main:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n");
|
|
||||||
|
|
||||||
if (args != null && args.Length > 0)
|
if (args != null && args.Length > 0)
|
||||||
{
|
{
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<History>True|2026-09-21T07:29:51.3588778Z||;True|2026-09-21T15:18:10.5399306+08:00||;True|2026-09-21T14:59:51.6908938+08:00||;True|2026-09-21T14:49:11.2390264+08:00||;True|2026-09-21T14:17:57.4013084+08:00||;True|2026-09-21T14:00:14.9207890+08:00||;True|2026-09-21T11:59:35.1020536+08:00||;True|2026-09-21T11:50:47.8944224+08:00||;True|2026-09-21T11:30:52.9019631+08:00||;True|2026-09-21T10:47:01.8026331+08:00||;</History>
|
<History>True|2026-09-21T13:16:57.9976233Z||;True|2026-09-21T19:43:49.4288081+08:00||;True|2026-09-21T18:49:13.4734866+08:00||;True|2026-09-21T18:10:56.1357602+08:00||;True|2026-09-21T17:47:00.1779419+08:00||;True|2026-09-21T15:29:51.3588778+08:00||;True|2026-09-21T15:18:10.5399306+08:00||;True|2026-09-21T14:59:51.6908938+08:00||;True|2026-09-21T14:49:11.2390264+08:00||;True|2026-09-21T14:17:57.4013084+08:00||;True|2026-09-21T14:00:14.9207890+08:00||;True|2026-09-21T11:59:35.1020536+08:00||;True|2026-09-21T11:50:47.8944224+08:00||;True|2026-09-21T11:30:52.9019631+08:00||;True|2026-09-21T10:47:01.8026331+08:00||;</History>
|
||||||
<LastFailureDetails />
|
<LastFailureDetails />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -31,20 +31,24 @@ namespace CloudBuilder.Topshelf.Task
|
|||||||
IRepository<SecurityScheduleTaskQueueEntity> taskRepository = service.GetRepository<IRepository<SecurityScheduleTaskQueueEntity>>();
|
IRepository<SecurityScheduleTaskQueueEntity> taskRepository = service.GetRepository<IRepository<SecurityScheduleTaskQueueEntity>>();
|
||||||
|
|
||||||
|
|
||||||
SecurityScheduleTaskQueueEntity task = taskRepository.DetachedEntities.OrderBy(x => x.QueueId).FirstOrDefault();
|
SecurityScheduleTaskQueueEntity[] tasks = taskRepository.DetachedEntities.OrderBy(x => x.QueueId).ToArray();
|
||||||
|
|
||||||
if (task == null) return;
|
if (tasks == null || tasks.Length == 0) return;
|
||||||
|
|
||||||
|
foreach (var task in tasks)
|
||||||
|
{
|
||||||
|
IRepository<DmsFileEntity> repositoryDmsFile = service.GetRepository<IRepository<DmsFileEntity>>();
|
||||||
|
DmsFileEntity dmsFile = repositoryDmsFile.DetachedEntities.Where(x => x.OrderKey == task.DocumentId).FirstOrDefault();
|
||||||
|
|
||||||
IRepository<DmsFileEntity> repositoryDmsFile = service.GetRepository<IRepository<DmsFileEntity>>();
|
if (dmsFile == null) return;
|
||||||
DmsFileEntity dmsFile = repositoryDmsFile.DetachedEntities.Where(x => x.OrderKey == task.DocumentId).FirstOrDefault();
|
|
||||||
|
|
||||||
if (dmsFile == null) return;
|
RunMyProcess(task.TaskId, task.TaskParam);
|
||||||
|
|
||||||
RunMyProcess(task.TaskId, task.TaskParam);
|
dmsFile.TranscodeIndc = YesNoPolicy.YES;
|
||||||
|
repositoryDmsFile.UpdateNow(dmsFile);
|
||||||
|
|
||||||
dmsFile.TranscodeIndc = YesNoPolicy.YES;
|
taskRepository.DeleteNow(task);
|
||||||
repositoryDmsFile.UpdateNow(dmsFile);
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -60,7 +64,11 @@ namespace CloudBuilder.Topshelf.Task
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parameters = parameters.Replace("/app/data", "/vol1/1000/Docker/NET8/DEV/data");
|
//Dockerfile中定义的volumes的映射地址
|
||||||
|
var rf = service.Configuration["FileServiceSettings:RelativeFileDirectory"];
|
||||||
|
var af = service.Configuration["FileServiceSettings:AbsoluteFileDirectory"];
|
||||||
|
|
||||||
|
parameters = parameters.Replace(rf, af);
|
||||||
|
|
||||||
log.WriteToFile(exePath + parameters);
|
log.WriteToFile(exePath + parameters);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"DbContexts": {
|
"DbContexts": {
|
||||||
"MasterDbContext": {
|
"MasterDbContext": {
|
||||||
"DbContextTypeName": "MasterDbContext",
|
"DbContextTypeName": "MasterDbContext",
|
||||||
"ConnectionString": "server=nas.youjiala.com;port=3307;database=builder;uid=root;pwd=Root@1237890;CharSet=utf8mb4;",
|
"ConnectionString": "server=nas.youjiala.com;port=3307;database=Furion;uid=root;pwd=Root@1237890;CharSet=utf8mb4;",
|
||||||
"DatabaseType": "MySql",
|
"DatabaseType": "MySql",
|
||||||
"LazyLoadingProxiesEnabled": true,
|
"LazyLoadingProxiesEnabled": true,
|
||||||
"AuditEntityEnabled": true,
|
"AuditEntityEnabled": true,
|
||||||
@@ -26,6 +26,10 @@
|
|||||||
"UserMobile": "13560851330"
|
"UserMobile": "13560851330"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"FileServiceSettings": {
|
||||||
|
"AbsoluteFileDirectory": "/vol1/1000/Docker/NET8/publish/data",
|
||||||
|
"RelativeFileDirectory": "/app/data" //Dockerfile - /vol1/1000/Docker/NET8/publish/data:/app/data
|
||||||
|
},
|
||||||
"IApplicationService": {
|
"IApplicationService": {
|
||||||
"UserId": "000003" //通过Service是不需要用户权限而直接调用
|
"UserId": "000003" //通过Service是不需要用户权限而直接调用
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1404,7 +1404,7 @@ namespace CloudBuilder.Master.Service
|
|||||||
return para.ToArray().ToDelimiteredList(' ');
|
return para.ToArray().ToDelimiteredList(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TsToM3u8(string documentId, string mp4Url, string m3u8Url, int videoLength = 6)
|
public void TsToM3u8(string documentId, string mp4Url, string m3u8Url)
|
||||||
{
|
{
|
||||||
string para = string.Format(service.Configuration[ServiceSettingsPolicy.FfmpegPictrue], mp4Url, m3u8Url);
|
string para = string.Format(service.Configuration[ServiceSettingsPolicy.FfmpegPictrue], mp4Url, m3u8Url);
|
||||||
try
|
try
|
||||||
@@ -1431,7 +1431,7 @@ namespace CloudBuilder.Master.Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
//return;
|
//return;
|
||||||
para = string.Format(service.Configuration["Ffmpeg:Arguments"], mp4Url, videoLength, fullName);
|
para = string.Format(service.Configuration["Ffmpeg:Arguments"], mp4Url, fullName);
|
||||||
//不直接转码视频文件,影响服务器性能,改为在闭时自动生成
|
//不直接转码视频文件,影响服务器性能,改为在闭时自动生成
|
||||||
//Task.Run(() =>
|
//Task.Run(() =>
|
||||||
//{
|
//{
|
||||||
@@ -1513,16 +1513,30 @@ namespace CloudBuilder.Master.Service
|
|||||||
{
|
{
|
||||||
log.WriteToFile(exePath + Parameters);
|
log.WriteToFile(exePath + Parameters);
|
||||||
if (string.IsNullOrEmpty(exePath)) return;
|
if (string.IsNullOrEmpty(exePath)) return;
|
||||||
Cli.Wrap(exePath)
|
|
||||||
.WithArguments(Parameters)
|
// 必须等 ffmpeg 真正退出:视频封面(jpg)要在接口返回前落盘,
|
||||||
.ExecuteAsync();
|
// 否则前端刷新列表时文件还没生成,<img> 请求 404 且不会自动重试,
|
||||||
|
// 表现为"上传完看不到封面,手动刷新才有"。
|
||||||
|
// 最多等 15 秒,超时就交给前端的封面重试机制兜底,不再死等拖住上传请求。
|
||||||
|
// CliWrap 的 ExecuteAsync 返回 CommandTask<CommandResult>,取它的 Task 才能等待
|
||||||
|
var task = Cli.Wrap(exePath)
|
||||||
|
.WithArguments(Parameters)
|
||||||
|
.ExecuteAsync()
|
||||||
|
.Task;
|
||||||
|
|
||||||
|
if (!task.Wait(TimeSpan.FromSeconds(15)))
|
||||||
|
{
|
||||||
|
log.WriteToFile("ffmpeg 执行超时(15s):" + Parameters);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.WriteToFile("ffmpeg 执行完成,ExitCode:" + task.Result.ExitCode);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
// 截图失败不影响上传本身,这里只记日志,封面由前端重试兜底
|
||||||
log.WriteToFile(ex.Message);
|
log.WriteToFile(ex.Message);
|
||||||
throw new ValidatedException(ex.Message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DmsFileEntity CreateDmsFile(DmsFileEntity dmsFile)
|
public DmsFileEntity CreateDmsFile(DmsFileEntity dmsFile)
|
||||||
|
|||||||
@@ -89,9 +89,9 @@ namespace CloudBuilder.Master.Service
|
|||||||
var upload = ServiceSettingsPolicy.GetDmsFileUploadDirectory(service).Replace(phy, "");
|
var upload = ServiceSettingsPolicy.GetDmsFileUploadDirectory(service).Replace(phy, "");
|
||||||
|
|
||||||
//暂时不支持转码
|
//暂时不支持转码
|
||||||
//DmsFileEntity dmsFileEntity = repositoryDmsFile.DetachedEntities.Where(x => x.OrderKey == item.Url).FirstOrDefault();
|
DmsFileEntity dmsFileEntity = repositoryDmsFile.DetachedEntities.Where(x => x.OrderKey == item.Url).FirstOrDefault();
|
||||||
item.FormattedPic = FileTypePolicy.PackPicUrl(service, item.CreatedBy, item.Url);
|
item.FormattedPic = FileTypePolicy.PackPicUrl(service, item.CreatedBy, item.Url);
|
||||||
item.FormattedUrl = FileTypePolicy.PackUrl(service, item.CreatedBy, item.Url, YesNoPolicy.NO);
|
item.FormattedUrl = FileTypePolicy.PackUrl(service, item.CreatedBy, item.Url, dmsFileEntity.TranscodeIndc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,8 @@ namespace CloudBuilder.Security.Policy
|
|||||||
var upload = (ServiceSettingsPolicy.GetDmsFileBackupDirectory(service) ?? "").Replace(phy ?? "", "");
|
var upload = (ServiceSettingsPolicy.GetDmsFileBackupDirectory(service) ?? "").Replace(phy ?? "", "");
|
||||||
var filePathRel = Path.Combine(upload, createdBy, fileExtension.Replace(".", ""), "");
|
var filePathRel = Path.Combine(upload, createdBy, fileExtension.Replace(".", ""), "");
|
||||||
var filePath = filePathRel.Replace(Path.DirectorySeparatorChar, '/') + "/";
|
var filePath = filePathRel.Replace(Path.DirectorySeparatorChar, '/') + "/";
|
||||||
url = service.Configuration[AppsettingsPolicy.ApplicationUrl] + webRootPath + filePath + Path.GetFileNameWithoutExtension(orderKey) + JPG + "?v=" + DateTime.Now.ToString("yyyyMMddhhmmss");
|
// HH 才是 24 小时制:写成 hh 会让上午/下午的时间重复,缓存穿透失效
|
||||||
|
url = service.Configuration[AppsettingsPolicy.ApplicationUrl] + webRootPath + filePath + Path.GetFileNameWithoutExtension(orderKey) + JPG + "?v=" + DateTime.Now.ToString("yyyyMMddHHmmss");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_PublishTargetUrl>C:\inetpub\wwwroot\dockwebapi2</_PublishTargetUrl>
|
<_PublishTargetUrl>C:\inetpub\wwwroot\dockwebapi2</_PublishTargetUrl>
|
||||||
<History>True|2026-09-21T08:51:19.8137872Z||;True|2026-09-21T16:30:01.0950896+08:00||;True|2026-09-21T15:09:00.2326737+08:00||;True|2026-09-21T14:47:09.6120256+08:00||;True|2026-09-21T14:16:35.3194409+08:00||;True|2026-09-21T13:54:58.2829712+08:00||;True|2026-09-21T13:36:45.3134499+08:00||;True|2026-09-19T09:48:52.0085130+08:00||;False|2026-09-19T09:47:56.1658214+08:00||;True|2026-09-17T18:50:15.9493380+08:00||;True|2026-09-17T18:11:11.5364547+08:00||;True|2026-09-17T18:07:27.7830758+08:00||;True|2026-09-17T17:58:16.5798560+08:00||;True|2026-09-17T15:37:30.9025614+08:00||;True|2026-09-17T15:25:46.9116292+08:00||;True|2026-09-17T15:05:18.6592403+08:00||;True|2026-09-17T14:57:28.7997437+08:00||;True|2026-09-17T14:36:00.6339386+08:00||;True|2026-09-17T13:56:43.2376873+08:00||;True|2026-09-16T13:56:51.8724546+08:00||;True|2026-09-15T20:44:46.6559899+08:00||;True|2026-09-13T19:02:59.5654245+08:00||;True|2026-09-10T09:14:56.2914193+08:00||;True|2026-09-09T16:40:16.6461154+08:00||;True|2026-09-08T13:55:23.1502435+08:00||;True|2026-09-08T08:04:53.4279263+08:00||;True|2026-09-07T08:48:17.4682304+08:00||;True|2026-09-04T14:39:08.7878670+08:00||;True|2026-09-04T14:35:48.2937877+08:00||;True|2026-09-04T11:45:16.1372876+08:00||;True|2026-09-04T11:42:59.9356436+08:00||;True|2026-09-03T16:05:52.5270232+08:00||;True|2026-09-03T14:52:56.8559144+08:00||;True|2026-09-02T11:08:23.8720038+08:00||;True|2026-09-02T10:58:16.8081797+08:00||;True|2026-08-26T13:34:12.3805892+08:00||;True|2026-08-25T08:31:30.7787234+08:00||;True|2026-08-20T13:10:46.4725468+08:00||;True|2026-08-20T13:10:28.3142576+08:00||;True|2026-08-19T16:10:27.3362887+08:00||;True|2026-08-19T16:01:12.6234971+08:00||;True|2026-08-19T15:42:46.6576265+08:00||;True|2026-08-19T13:39:59.9363522+08:00||;True|2026-08-19T13:36:53.0379313+08:00||;True|2026-08-19T13:31:36.0841398+08:00||;True|2026-08-19T11:44:37.5319626+08:00||;True|2026-08-19T09:36:45.6000047+08:00||;True|2026-08-19T09:34:36.8468631+08:00||;True|2026-08-19T08:35:41.2202300+08:00||;True|2026-08-18T16:20:59.0170916+08:00||;</History>
|
<History>True|2026-09-21T13:01:22.8888913Z||;True|2026-09-21T19:15:03.4753747+08:00||;True|2026-09-21T18:08:30.0866986+08:00||;True|2026-09-21T16:51:19.8137872+08:00||;True|2026-09-21T16:30:01.0950896+08:00||;True|2026-09-21T15:09:00.2326737+08:00||;True|2026-09-21T14:47:09.6120256+08:00||;True|2026-09-21T14:16:35.3194409+08:00||;True|2026-09-21T13:54:58.2829712+08:00||;True|2026-09-21T13:36:45.3134499+08:00||;True|2026-09-19T09:48:52.0085130+08:00||;False|2026-09-19T09:47:56.1658214+08:00||;True|2026-09-17T18:50:15.9493380+08:00||;True|2026-09-17T18:11:11.5364547+08:00||;True|2026-09-17T18:07:27.7830758+08:00||;True|2026-09-17T17:58:16.5798560+08:00||;True|2026-09-17T15:37:30.9025614+08:00||;True|2026-09-17T15:25:46.9116292+08:00||;True|2026-09-17T15:05:18.6592403+08:00||;True|2026-09-17T14:57:28.7997437+08:00||;True|2026-09-17T14:36:00.6339386+08:00||;True|2026-09-17T13:56:43.2376873+08:00||;True|2026-09-16T13:56:51.8724546+08:00||;True|2026-09-15T20:44:46.6559899+08:00||;True|2026-09-13T19:02:59.5654245+08:00||;True|2026-09-10T09:14:56.2914193+08:00||;True|2026-09-09T16:40:16.6461154+08:00||;True|2026-09-08T13:55:23.1502435+08:00||;True|2026-09-08T08:04:53.4279263+08:00||;True|2026-09-07T08:48:17.4682304+08:00||;True|2026-09-04T14:39:08.7878670+08:00||;True|2026-09-04T14:35:48.2937877+08:00||;True|2026-09-04T11:45:16.1372876+08:00||;True|2026-09-04T11:42:59.9356436+08:00||;True|2026-09-03T16:05:52.5270232+08:00||;True|2026-09-03T14:52:56.8559144+08:00||;True|2026-09-02T11:08:23.8720038+08:00||;True|2026-09-02T10:58:16.8081797+08:00||;True|2026-08-26T13:34:12.3805892+08:00||;True|2026-08-25T08:31:30.7787234+08:00||;True|2026-08-20T13:10:46.4725468+08:00||;True|2026-08-20T13:10:28.3142576+08:00||;True|2026-08-19T16:10:27.3362887+08:00||;True|2026-08-19T16:01:12.6234971+08:00||;True|2026-08-19T15:42:46.6576265+08:00||;True|2026-08-19T13:39:59.9363522+08:00||;True|2026-08-19T13:36:53.0379313+08:00||;True|2026-08-19T13:31:36.0841398+08:00||;True|2026-08-19T11:44:37.5319626+08:00||;True|2026-08-19T09:36:45.6000047+08:00||;True|2026-08-19T09:34:36.8468631+08:00||;True|2026-08-19T08:35:41.2202300+08:00||;True|2026-08-18T16:20:59.0170916+08:00||;</History>
|
||||||
<LastFailureDetails />
|
<LastFailureDetails />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
"DbContexts": {
|
"DbContexts": {
|
||||||
"MasterDbContext": {
|
"MasterDbContext": {
|
||||||
"DbContextTypeName": "MasterDbContext",
|
"DbContextTypeName": "MasterDbContext",
|
||||||
"ConnectionString": "server=nas.youjiala.com;port=3307;database=Furion;uid=root;pwd=Root@1237890;CharSet=utf8mb4;",
|
"ConnectionString": "server=nas.youjiala.com;port=3307;database=builder;uid=root;pwd=Root@1237890;CharSet=utf8mb4;",
|
||||||
"DatabaseType": "MySql",
|
"DatabaseType": "MySql",
|
||||||
"LazyLoadingProxiesEnabled": true,
|
"LazyLoadingProxiesEnabled": true,
|
||||||
"AuditEntityEnabled": true,
|
"AuditEntityEnabled": true,
|
||||||
@@ -68,8 +68,8 @@
|
|||||||
},
|
},
|
||||||
"Ffmpeg": {
|
"Ffmpeg": {
|
||||||
"Path": "D:\\NET8\\Exe\\ffmpeg\\bin\\ffmpeg.exe", //视频转码
|
"Path": "D:\\NET8\\Exe\\ffmpeg\\bin\\ffmpeg.exe", //视频转码
|
||||||
"Pictrue": " -i {0} -ss 00:00:2.000 -frames:v 1 -vf \"scale=1280:-1\" -q:v 4 {1}", //" -i {0} -ss 00:00:2.000 -frames:v 1 {1}",
|
"Pictrue": " -i {0} -ss 00:00:2.000 -frames:v 1 -vf \"scale=1280:-2\" -q:v 4 {1}", //" -i {0} -ss 00:00:2.000 -frames:v 1 {1}",
|
||||||
"Arguments": " -i {0} -c:v libx264 -vf scale=1280:-1 -start_number 0 -hls_time {1} -hls_list_size 0 -f hls {2}" //0-源路径,1-目标路径,2-存放多少秒 1280×720,852*480
|
"Arguments": "-i {0} -c:v libx264 -preset veryfast -crf 26 -profile:v main -level 3.1 -vf \"scale='min(1280,iw)':-2\" -maxrate 1500k -bufsize 2400k -c:a aac -b:a 96k -ac 2 -ar 44100 -start_number 0 -hls_time 3 -hls_list_size 0 -hls_flags independent_segments -f hls {1}" //0-源路径,1-目标路径
|
||||||
},
|
},
|
||||||
"CloudBuilder.Topshelf": {
|
"CloudBuilder.Topshelf": {
|
||||||
"Path": "D:\\MAFAI\\CloudBuilder.Topshelf\\bin\\Debug\\net8.0\\CloudBuilder.Topshelf.exe" //图片压缩
|
"Path": "D:\\MAFAI\\CloudBuilder.Topshelf\\bin\\Debug\\net8.0\\CloudBuilder.Topshelf.exe" //图片压缩
|
||||||
|
|||||||
Generated
+5
-22
@@ -25,6 +25,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"gsap": "^3.12.5",
|
"gsap": "^3.12.5",
|
||||||
|
"hls.js": "^1.7.3",
|
||||||
"howler": "^2.2.4",
|
"howler": "^2.2.4",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
@@ -38,7 +39,6 @@
|
|||||||
"vue-request": "^2.0.4",
|
"vue-request": "^2.0.4",
|
||||||
"vue-router": "^4.0.13",
|
"vue-router": "^4.0.13",
|
||||||
"vue3-photo-preview": "^0.3.0",
|
"vue3-photo-preview": "^0.3.0",
|
||||||
"vue3-video-play": "^1.3.1",
|
|
||||||
"wow.js": "^1.2.2"
|
"wow.js": "^1.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -2899,9 +2899,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hls.js": {
|
"node_modules/hls.js": {
|
||||||
"version": "1.5.8",
|
"version": "1.7.3",
|
||||||
"resolved": "https://registry.npmmirror.com/hls.js/-/hls.js-1.5.8.tgz",
|
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.7.3.tgz",
|
||||||
"integrity": "sha512-hJYMPfLhWO7/7+n4f9pn6bOheCGx0WgvVz7k3ouq3Pp1bja48NN+HeCQu3XCGYzqWQF/wo7Sk6dJAyWVJD8ECA=="
|
"integrity": "sha512-MsPlx6yVW4Qv4C7mEVou4/gk/5cN2dVxOTnrNjPSmyH2f0Ln+/UkG10Ax1PE6OvrmTVPKgQYozTtBaPOuCzq7A==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/howler": {
|
"node_modules/howler": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
@@ -3772,24 +3773,6 @@
|
|||||||
"vue": ">=3.2.0"
|
"vue": ">=3.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vue3-video-play": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/vue3-video-play/-/vue3-video-play-1.3.1.tgz",
|
|
||||||
"integrity": "sha512-krx3wC3TGB6CHgNEEC3cDsq3UwUQhMW9FU4ryZtgDpMctjIMs275cQe3wrXTVDRIk3IVcHJ5HV4UlaHX2DKTFw==",
|
|
||||||
"dependencies": {
|
|
||||||
"hls.js": "^1.0.10",
|
|
||||||
"throttle-debounce": "^3.0.1",
|
|
||||||
"vue": "^3.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/vue3-video-play/node_modules/throttle-debounce": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/warning": {
|
"node_modules/warning": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmmirror.com/warning/-/warning-4.0.3.tgz",
|
"resolved": "https://registry.npmmirror.com/warning/-/warning-4.0.3.tgz",
|
||||||
|
|||||||
+1
-1
@@ -26,6 +26,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"gsap": "^3.12.5",
|
"gsap": "^3.12.5",
|
||||||
|
"hls.js": "^1.7.3",
|
||||||
"howler": "^2.2.4",
|
"howler": "^2.2.4",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
@@ -39,7 +40,6 @@
|
|||||||
"vue-request": "^2.0.4",
|
"vue-request": "^2.0.4",
|
||||||
"vue-router": "^4.0.13",
|
"vue-router": "^4.0.13",
|
||||||
"vue3-photo-preview": "^0.3.0",
|
"vue3-photo-preview": "^0.3.0",
|
||||||
"vue3-video-play": "^1.3.1",
|
|
||||||
"wow.js": "^1.2.2"
|
"wow.js": "^1.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ const requestChunk = async (
|
|||||||
percent: percentBefore,
|
percent: percentBefore,
|
||||||
current: index,
|
current: index,
|
||||||
total: chunks.length,
|
total: chunks.length,
|
||||||
text: `网络异常,正在重试(${attempt + 1}/${retries})...`,
|
text: `网络异常,正在重试(${attempt + 1}/${retries})... ${percentBefore}%`,
|
||||||
});
|
});
|
||||||
await sleep(props.retryDelay * Math.pow(2, attempt));
|
await sleep(props.retryDelay * Math.pow(2, attempt));
|
||||||
}
|
}
|
||||||
@@ -262,10 +262,11 @@ const uploadChunk = async (
|
|||||||
percent,
|
percent,
|
||||||
current: index,
|
current: index,
|
||||||
total: chunks.length,
|
total: chunks.length,
|
||||||
|
// 单文件、多文件都统一用百分比(按字节算的整体进度),不再显示「第几片/共几片」
|
||||||
text:
|
text:
|
||||||
progress.fileCount > 1
|
progress.fileCount > 1
|
||||||
? `上传中(第 ${progress.fileNo}/${progress.fileCount} 个,分片 ${index}/${chunks.length}) ${percent}%`
|
? `上传中(第 ${progress.fileNo}/${progress.fileCount} 个) ${percent}%`
|
||||||
: `上传中(${index}/${chunks.length})...`,
|
: `上传中 ${percent}%`,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (index < chunks.length) {
|
if (index < chunks.length) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
<template v-else-if="isVideo(record.OrderKey)">
|
<template v-else-if="isVideo(record.OrderKey)">
|
||||||
<div class="video-thumb">
|
<div class="video-thumb">
|
||||||
<img :src="record.FormattedPic" :title="record.OrgFileName" />
|
<img :src="record.FormattedPic" :title="record.OrgFileName" @error="retryImage($event)" />
|
||||||
<div class="play-overlay">
|
<div class="play-overlay">
|
||||||
<PlayCircleOutlined />
|
<PlayCircleOutlined />
|
||||||
</div>
|
</div>
|
||||||
@@ -109,6 +109,7 @@ import {
|
|||||||
AppstoreOutlined,
|
AppstoreOutlined,
|
||||||
} from "@ant-design/icons-vue";
|
} from "@ant-design/icons-vue";
|
||||||
import { DmsFileUploadViewDisplayData } from "@/data/auto/dmsFileUploadViewDisplayData";
|
import { DmsFileUploadViewDisplayData } from "@/data/auto/dmsFileUploadViewDisplayData";
|
||||||
|
import { retryImage } from "@/utils/imageRetry";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
datas: DmsFileUploadViewDisplayData[];
|
datas: DmsFileUploadViewDisplayData[];
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="record.FormattedPic"
|
:src="record.FormattedPic"
|
||||||
:title="record.OrgFileName"
|
:title="record.OrgFileName"
|
||||||
|
@error="retryImage($event)"
|
||||||
/>
|
/>
|
||||||
<div class="play-overlay">
|
<div class="play-overlay">
|
||||||
<PlayCircleOutlined />
|
<PlayCircleOutlined />
|
||||||
@@ -192,6 +193,7 @@ import {
|
|||||||
} from "@ant-design/icons-vue";
|
} from "@ant-design/icons-vue";
|
||||||
import { FamilyDmsFileViewDisplayData } from "@/data/auto/familyDmsFileViewDisplayData";
|
import { FamilyDmsFileViewDisplayData } from "@/data/auto/familyDmsFileViewDisplayData";
|
||||||
import { notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
|
import { retryImage } from "@/utils/imageRetry";
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
datas: FamilyDmsFileViewDisplayData[];
|
datas: FamilyDmsFileViewDisplayData[];
|
||||||
selectedKeys: FamilyDmsFileViewDisplayData[];
|
selectedKeys: FamilyDmsFileViewDisplayData[];
|
||||||
|
|||||||
@@ -58,20 +58,20 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="2" v-if="!isDirectorySelected && isSingleItem && isSingleVideo">
|
<a-col :span="2" v-if="!isDirectorySelected && isSingleItem && isSingleVideo">
|
||||||
<a-tooltip title="播放">
|
<a-tooltip>
|
||||||
<a-button class="nav-btn" @click="onPlayVideo"><cust-icon-font size="16"
|
<a-button class="nav-btn" @click="onPlayVideo"><cust-icon-font size="16"
|
||||||
type="icon-foldervideo" /></a-button>
|
type="icon-foldervideo" /></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="2" v-if="!isDirectorySelected && isSingleItem && isSingleAudio" style="margin-left: 4px">
|
<a-col :span="2" v-if="!isDirectorySelected && isSingleItem && isSingleAudio" style="margin-left: 4px">
|
||||||
<a-tooltip v-if="selectedItem.IsPlay != 'Y'" title="播放">
|
<a-tooltip v-if="selectedItem.IsPlay != 'Y'">
|
||||||
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
||||||
@click="onPlayAudio"></a-button>
|
@click="onPlayAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip v-else-if="selectedItem.IsPause != 'Y'" title="暂停">
|
<a-tooltip v-else-if="selectedItem.IsPause != 'Y'">
|
||||||
<a-button class="nav-btn" :icon="h(PauseCircleOutlined)" @click="onPauseAudio"></a-button>
|
<a-button class="nav-btn" :icon="h(PauseCircleOutlined)" @click="onPauseAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip v-else title="继续">
|
<a-tooltip v-else>
|
||||||
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
||||||
@click="onContinueAudio"></a-button>
|
@click="onContinueAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
@@ -85,9 +85,8 @@
|
|||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<FileUpload v-if="canCreate" ref="fileUploadRef" :action="uploadUrl" :headers="headers"
|
<FileUpload v-if="canCreate" ref="fileUploadRef" :action="uploadUrl" :headers="headers"
|
||||||
:resolve-file-path="resolveFilePath" :multiple="multiple" @start="onUploadStart"
|
:resolve-file-path="resolveFilePath" :multiple="multiple" @start="onUploadStart" @progress="onUploadProgress"
|
||||||
@progress="onUploadProgress" @success="onUploadSuccess" @complete="onUploadComplete"
|
@success="onUploadSuccess" @complete="onUploadComplete" @interrupted="onUploadInterrupted" @error="onUploadError" />
|
||||||
@interrupted="onUploadInterrupted" @error="onUploadError" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<a-row>
|
<a-row>
|
||||||
<a-col flex="300px">
|
<a-col flex="300px">
|
||||||
<a-row justify="start">
|
<a-row justify="start">
|
||||||
<a-col :span="3" style="margin-left: 8px">
|
<a-col :span="3" style="margin-left: 8px">
|
||||||
<a-tooltip title="还原">
|
<a-tooltip title="还原">
|
||||||
<a-button class="nav-btn" :icon="h(UndoOutlined)" style="color:green;"
|
<a-button class="nav-btn" :icon="h(UndoOutlined)" style="color:green;"
|
||||||
:disabled="!hasSelection" @click="$emit('restore', selectedItems)"></a-button>
|
:disabled="!hasSelection" @click="$emit('restore', selectedItems)"></a-button>
|
||||||
@@ -12,33 +12,36 @@
|
|||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="3">
|
<a-col :span="3">
|
||||||
<a-tooltip title="下载">
|
<a-tooltip title="下载">
|
||||||
<a-button class="nav-btn" :icon="h(DownloadOutlined)" :disabled="!hasSelection || isDirectorySelected || !isSingleItem"
|
<a-button class="nav-btn" :icon="h(DownloadOutlined)"
|
||||||
|
:disabled="!hasSelection || isDirectorySelected || !isSingleItem"
|
||||||
@click="onDownload"></a-button>
|
@click="onDownload"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="3" v-if="hasSelection">
|
<a-col :span="3" v-if="hasSelection">
|
||||||
<a-tooltip title="删除">
|
<a-tooltip title="删除">
|
||||||
<a-popconfirm title="确定是否删除?" ok-text="是" cancel-text="否" @confirm="$emit('delete', selectedItems)">
|
<a-popconfirm title="确定是否删除?" ok-text="是" cancel-text="否"
|
||||||
<a-button class="nav-btn" :icon="h(DeleteOutlined)" style="color:red;"
|
@confirm="$emit('delete', selectedItems)">
|
||||||
:disabled="!canCreate" ></a-button></a-popconfirm>
|
<a-button class="nav-btn" :icon="h(DeleteOutlined)" style="color:red;"
|
||||||
|
:disabled="!canCreate"></a-button></a-popconfirm>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleVideo">
|
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleVideo">
|
||||||
<a-tooltip title="播放">
|
<a-tooltip>
|
||||||
<a-button class="nav-btn" @click="onPlayVideo"><cust-icon-font size="16"
|
<a-button class="nav-btn" @click="onPlayVideo"><cust-icon-font size="16"
|
||||||
type="icon-foldervideo" /></a-button>
|
type="icon-foldervideo" /></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleAudio" >
|
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleAudio">
|
||||||
<a-tooltip v-if="selectedItem.IsPlay != 'Y'" title="播放">
|
<a-tooltip v-if="selectedItem.IsPlay != 'Y'">
|
||||||
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
||||||
@click="onPlayAudio"></a-button>
|
@click="onPlayAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip v-else-if="selectedItem.IsPause != 'Y'" title="暂停">
|
<a-tooltip v-else-if="selectedItem.IsPause != 'Y'">
|
||||||
<a-button class="nav-btn" :icon="h(PauseCircleOutlined)" @click="onPauseAudio"></a-button>
|
<a-button class="nav-btn" :icon="h(PauseCircleOutlined)"
|
||||||
|
@click="onPauseAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip v-else title="继续">
|
<a-tooltip v-else>
|
||||||
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
||||||
@click="onContinueAudio"></a-button>
|
@click="onContinueAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -182,20 +185,20 @@ const onContinueAudio = () => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.nav-btn {
|
.nav-btn {
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-btn:hover:not(:disabled) {
|
.nav-btn:hover:not(:disabled) {
|
||||||
background: #e6f4ff;
|
background: #e6f4ff;
|
||||||
color: #1677ff;
|
color: #1677ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-btn:disabled {
|
.nav-btn:disabled {
|
||||||
color: #bfbfbf;
|
color: #bfbfbf;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -24,20 +24,20 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleVideo">
|
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleVideo">
|
||||||
<a-tooltip title="播放">
|
<a-tooltip >
|
||||||
<a-button class="nav-btn" @click="onPlayVideo"><cust-icon-font size="16"
|
<a-button class="nav-btn" @click="onPlayVideo"><cust-icon-font size="16"
|
||||||
type="icon-foldervideo" /></a-button>
|
type="icon-foldervideo" /></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleAudio">
|
<a-col :span="3" v-if="!isDirectorySelected && isSingleItem && isSingleAudio">
|
||||||
<a-tooltip v-if="selectedItem.IsPlay != 'Y'" title="播放">
|
<a-tooltip v-if="selectedItem.IsPlay != 'Y'">
|
||||||
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
||||||
@click="onPlayAudio"></a-button>
|
@click="onPlayAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip v-else-if="selectedItem.IsPause != 'Y'" title="暂停">
|
<a-tooltip v-else-if="selectedItem.IsPause != 'Y'" >
|
||||||
<a-button class="nav-btn" :icon="h(PauseCircleOutlined)" @click="onPauseAudio"></a-button>
|
<a-button class="nav-btn" :icon="h(PauseCircleOutlined)" @click="onPauseAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip v-else title="继续">
|
<a-tooltip v-else >
|
||||||
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
<a-button class="nav-btn" :icon="h(PlayCircleOutlined, { style: { color: 'red' } })"
|
||||||
@click="onContinueAudio"></a-button>
|
@click="onContinueAudio"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
<a-spin size="large" />
|
<a-spin size="large" />
|
||||||
<span>加载中…</span>
|
<span>加载中…</span>
|
||||||
</div>
|
</div>
|
||||||
<button v-if="!isPlaying && !buffering" class="vp-bigplay" type="button" title="播放" @click.stop="toggle">
|
<button v-if="!isPlaying && !buffering" class="vp-bigplay" type="button" aria-label="播放"
|
||||||
|
@click.stop="toggle">
|
||||||
<CaretRightFilled />
|
<CaretRightFilled />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,7 +108,7 @@
|
|||||||
<button class="vp-ctl" type="button" title="上一个" @click="goPrev">
|
<button class="vp-ctl" type="button" title="上一个" @click="goPrev">
|
||||||
<StepBackwardFilled />
|
<StepBackwardFilled />
|
||||||
</button>
|
</button>
|
||||||
<button class="vp-play" type="button" :title="isPlaying ? '暂停' : '播放'" @click="toggle">
|
<button class="vp-play" type="button" :aria-label="isPlaying ? '暂停' : '播放'" @click="toggle">
|
||||||
<PauseOutlined v-if="isPlaying" />
|
<PauseOutlined v-if="isPlaying" />
|
||||||
<CaretRightFilled v-else />
|
<CaretRightFilled v-else />
|
||||||
</button>
|
</button>
|
||||||
@@ -161,11 +162,20 @@ import {
|
|||||||
/** 一个视频 */
|
/** 一个视频 */
|
||||||
export type VideoItem = PublishVideoDetailDisplayData;
|
export type VideoItem = PublishVideoDetailDisplayData;
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{ videos?: VideoItem[] }>(), { videos: () => [] });
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
videos?: VideoItem[];
|
||||||
|
/** 打开时从第几个开始播(点列表里的某一个进来时用) */
|
||||||
|
startIndex?: number;
|
||||||
|
/** 挂上播放源后是否立即播放(弹窗里默认自动播) */
|
||||||
|
autoPlay?: boolean;
|
||||||
|
}>(),
|
||||||
|
{ videos: () => [], startIndex: 0, autoPlay: false },
|
||||||
|
);
|
||||||
|
|
||||||
/* ---------------- 基础状态 ---------------- */
|
/* ---------------- 基础状态 ---------------- */
|
||||||
const videoRef = ref<HTMLVideoElement | null>(null);
|
const videoRef = ref<HTMLVideoElement | null>(null);
|
||||||
const index = ref(0);
|
const index = ref(props.startIndex);
|
||||||
const isPlaying = ref(false);
|
const isPlaying = ref(false);
|
||||||
const currentTime = ref(0);
|
const currentTime = ref(0);
|
||||||
const duration = ref(0);
|
const duration = ref(0);
|
||||||
@@ -589,7 +599,8 @@ const fmt = (t: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ---------------- 联动 ---------------- */
|
/* ---------------- 联动 ---------------- */
|
||||||
watch(current, async (t) => {
|
/** 切到某个视频:重置状态 → 挂播放源 → 按需播放 */
|
||||||
|
const prepare = async (t: VideoItem | null, play: boolean) => {
|
||||||
currentTime.value = 0;
|
currentTime.value = 0;
|
||||||
duration.value = 0;
|
duration.value = 0;
|
||||||
bufferedEnd.value = 0;
|
bufferedEnd.value = 0;
|
||||||
@@ -599,11 +610,13 @@ watch(current, async (t) => {
|
|||||||
ensureStageRO();
|
ensureStageRO();
|
||||||
// 重新挂接播放源:m3u8 走 hls.js,普通文件走 src(内部会销毁上一个 hls 实例)
|
// 重新挂接播放源:m3u8 走 hls.js,普通文件走 src(内部会销毁上一个 hls 实例)
|
||||||
attachSource(t.FormattedUrl);
|
attachSource(t.FormattedUrl);
|
||||||
if (resumeAfterSwitch) {
|
if (play || props.autoPlay) {
|
||||||
resumeAfterSwitch = false;
|
resumeAfterSwitch = false;
|
||||||
tryPlay();
|
tryPlay();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
watch(current, (t) => prepare(t, resumeAfterSwitch));
|
||||||
|
|
||||||
// 播放列表默认收起,由用户点击列表按钮展开
|
// 播放列表默认收起,由用户点击列表按钮展开
|
||||||
watch(
|
watch(
|
||||||
@@ -613,6 +626,17 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 外部指定了从第几个开始播(弹窗没销毁又换了视频时也要跟随)
|
||||||
|
watch(
|
||||||
|
() => props.startIndex,
|
||||||
|
(i) => {
|
||||||
|
if (i >= 0 && i < videos.value.length && i !== index.value) {
|
||||||
|
resumeAfterSwitch = true;
|
||||||
|
index.value = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch([volume, muted], () => {
|
watch([volume, muted], () => {
|
||||||
const v = videoRef.value;
|
const v = videoRef.value;
|
||||||
if (!v) return;
|
if (!v) return;
|
||||||
@@ -625,6 +649,8 @@ watch(rate, () => {
|
|||||||
|
|
||||||
let timerId = 0;
|
let timerId = 0;
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// 列表在挂载时就已就绪的情况(例如弹窗里先备好数据再打开),watch 不会触发,这里补一次
|
||||||
|
if (current.value) prepare(current.value, false);
|
||||||
document.addEventListener("click", onDocClick);
|
document.addEventListener("click", onDocClick);
|
||||||
document.addEventListener("fullscreenchange", onFullscreenChange);
|
document.addEventListener("fullscreenchange", onFullscreenChange);
|
||||||
timerId = window.setInterval(() => {
|
timerId = window.setInterval(() => {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
setupAntd,
|
setupAntd,
|
||||||
setupAssets,
|
setupAssets,
|
||||||
setupCustomComponents,
|
setupCustomComponents,
|
||||||
setupVueVideoPlayer,
|
|
||||||
setupVuePhoto,
|
setupVuePhoto,
|
||||||
} from "./plugins";
|
} from "./plugins";
|
||||||
|
|
||||||
@@ -20,8 +19,6 @@ const app = createApp(App);
|
|||||||
function setupPlugins() {
|
function setupPlugins() {
|
||||||
// 注册全局常用的ant-design-vue组件
|
// 注册全局常用的ant-design-vue组件
|
||||||
setupAntd(app);
|
setupAntd(app);
|
||||||
// 注册全局常用的VueVideoPlayer组件
|
|
||||||
setupVueVideoPlayer(app);
|
|
||||||
// 注册全局常用的VuePhoto组件
|
// 注册全局常用的VuePhoto组件
|
||||||
setupVuePhoto(app);
|
setupVuePhoto(app);
|
||||||
// 引入静态资源
|
// 引入静态资源
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
export { setupAntd } from "@/plugins/antd";
|
export { setupAntd } from "@/plugins/antd";
|
||||||
export { setupAssets } from "@/plugins/assets";
|
export { setupAssets } from "@/plugins/assets";
|
||||||
export { setupCustomComponents } from "@/plugins/customComponents";
|
export { setupCustomComponents } from "@/plugins/customComponents";
|
||||||
export { setupVueVideoPlayer } from "@/plugins/video";
|
|
||||||
export { setupVuePhoto } from "@/plugins/photo";
|
export { setupVuePhoto } from "@/plugins/photo";
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import vue3videoPlay from "vue3-video-play";
|
|
||||||
import "vue3-video-play/dist/style.css";
|
|
||||||
import type { App } from "vue";
|
|
||||||
|
|
||||||
export function setupVueVideoPlayer(app: App<Element>) {
|
|
||||||
app.use(vue3videoPlay);
|
|
||||||
}
|
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
onVisibleChange: setPicVisible,
|
onVisibleChange: setPicVisible,
|
||||||
}" :src="imageSrc" />
|
}" :src="imageSrc" />
|
||||||
<dmsFolder @on-submit="onReload"></dmsFolder>
|
<dmsFolder @on-submit="onReload"></dmsFolder>
|
||||||
<videoPlay></videoPlay>
|
<VideoPlayModal v-model:open="videoPlayModal" :videos="videoPlayList" :start-index="videoPlayIndex"
|
||||||
|
:title="videoPlayTitle" :fullscreen="width < 640" />
|
||||||
<dragModal v-model:open="showModalShare" width="60%" title="分享管理查询" :mask-closable="false" :fullscreen="width < 640"
|
<dragModal v-model:open="showModalShare" width="60%" title="分享管理查询" :mask-closable="false" :fullscreen="width < 640"
|
||||||
@ok="handleSelectShare">
|
@ok="handleSelectShare">
|
||||||
<DmsFileShareModal ref="shareEnquiry"></DmsFileShareModal>
|
<DmsFileShareModal ref="shareEnquiry"></DmsFileShareModal>
|
||||||
@@ -77,7 +78,6 @@ import { notification } from "ant-design-vue";
|
|||||||
import { SearchCriteriaResultData } from "@/data/auto/searchCriteriaResultData";
|
import { SearchCriteriaResultData } from "@/data/auto/searchCriteriaResultData";
|
||||||
import dmsFolder from "./DmsFolderModal.vue";
|
import dmsFolder from "./DmsFolderModal.vue";
|
||||||
import { orderBy } from "lodash-es";
|
import { orderBy } from "lodash-es";
|
||||||
import VideoPlay from "./PlayVideo.vue";
|
|
||||||
import { Howl } from "howler";
|
import { Howl } from "howler";
|
||||||
import { PublishVideoEntity } from "@/data/auto/publishVideoEntity";
|
import { PublishVideoEntity } from "@/data/auto/publishVideoEntity";
|
||||||
import publishVideoService from "@/service/master/publishVideoService";
|
import publishVideoService from "@/service/master/publishVideoService";
|
||||||
@@ -92,6 +92,9 @@ import { PublishPhotoEntity } from "@/data/auto/publishPhotoEntity";
|
|||||||
import MyComputer from "@/components/basic/MyComputer.vue";
|
import MyComputer from "@/components/basic/MyComputer.vue";
|
||||||
import Toolbar from "@/components/basic/Toolbar.vue";
|
import Toolbar from "@/components/basic/Toolbar.vue";
|
||||||
import OperatorStationDelete from "@/components/basic/OperatorStationDelete.vue";
|
import OperatorStationDelete from "@/components/basic/OperatorStationDelete.vue";
|
||||||
|
import VideoPlayModal from "@/components/basic/VideoPlayModal.vue";
|
||||||
|
import type { VideoItem } from "@/components/basic/VideoPlayer.vue";
|
||||||
|
import { PublishVideoDetailDisplayData } from "@/data/auto/publishVideoDetailDisplayData";
|
||||||
|
|
||||||
interface BreadcrumbItem {
|
interface BreadcrumbItem {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -137,9 +140,8 @@ const dmsFolderIsRename = ref<boolean>(false);
|
|||||||
const dmsFolderIsMove = ref<boolean>(false);
|
const dmsFolderIsMove = ref<boolean>(false);
|
||||||
const entity = ref<DmsFileEntity>(new DmsFileEntity());
|
const entity = ref<DmsFileEntity>(new DmsFileEntity());
|
||||||
const videoPlayModal = ref<boolean>(false);
|
const videoPlayModal = ref<boolean>(false);
|
||||||
const videoSrc = ref<string>("");
|
const videoPlayList = ref<VideoItem[]>([]);
|
||||||
const videoPoster = ref<string>("");
|
const videoPlayIndex = ref<number>(0);
|
||||||
const videoType = ref<string>("");
|
|
||||||
const videoPlayTitle = ref<string>("");
|
const videoPlayTitle = ref<string>("");
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
|
|
||||||
@@ -239,11 +241,6 @@ provide("dmsFolderTitle", dmsFolderTitle);
|
|||||||
provide("dmsFolderIsRename", dmsFolderIsRename);
|
provide("dmsFolderIsRename", dmsFolderIsRename);
|
||||||
provide("dmsFolderIsMove", dmsFolderIsMove);
|
provide("dmsFolderIsMove", dmsFolderIsMove);
|
||||||
provide("DmsFileEntity", entity);
|
provide("DmsFileEntity", entity);
|
||||||
provide("videoPlayModal", videoPlayModal);
|
|
||||||
provide("videoPlayTitle", videoPlayTitle);
|
|
||||||
provide("videoSrc", videoSrc);
|
|
||||||
provide("videoPoster", videoPoster);
|
|
||||||
provide("videoType", videoType);
|
|
||||||
provide("isModalPublishVideo", showModalPublishVideo);
|
provide("isModalPublishVideo", showModalPublishVideo);
|
||||||
provide("isModalPublishAudio", showModalPublishAudio);
|
provide("isModalPublishAudio", showModalPublishAudio);
|
||||||
provide("isModalPublishPhoto", showModalPublishPhoto);
|
provide("isModalPublishPhoto", showModalPublishPhoto);
|
||||||
@@ -295,29 +292,61 @@ const onChangeFolder = async (fvalue: string) => {
|
|||||||
onSearchByFilePath(fvalue);
|
onSearchByFilePath(fvalue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUrlVideoPlay = (url: string, title: string, poster: string) => {
|
/** DMS 记录 → 播放列表项(m3u8 的封面用同名 png 兜底) */
|
||||||
|
const toVideoItem = (
|
||||||
|
record: DmsFileUploadDeleteLogViewDisplayData,
|
||||||
|
): VideoItem => {
|
||||||
|
const item = new PublishVideoDetailDisplayData();
|
||||||
|
item.Title = record.OrgFileName;
|
||||||
|
item.FormattedUrl = record.Url;
|
||||||
|
item.FormattedPic = (record.FormattedPic || "").replace(/\.m3u8$/, ".png");
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 当前目录里已转码(有 Url)的视频,作为弹窗播放器的播放列表 */
|
||||||
|
const buildVideoList = (
|
||||||
|
records: DmsFileUploadDeleteLogViewDisplayData[],
|
||||||
|
): VideoItem[] =>
|
||||||
|
records
|
||||||
|
.filter(
|
||||||
|
(x) =>
|
||||||
|
x.IsDirectoryIndc != "Y" &&
|
||||||
|
fileTypePolicy.isVideo(x.OrderKey || x.OrgFileName) &&
|
||||||
|
!!x.Url,
|
||||||
|
)
|
||||||
|
.map(toVideoItem);
|
||||||
|
|
||||||
|
/** 打开视频弹窗 */
|
||||||
|
const openVideoPlay = (list: VideoItem[], index: number, title: string) => {
|
||||||
sound.value?.stop();
|
sound.value?.stop();
|
||||||
datas.value.forEach((element) => {
|
datas.value.forEach((element) => {
|
||||||
element.IsPlay = "";
|
element.IsPlay = "";
|
||||||
});
|
});
|
||||||
videoPoster.value = poster;
|
videoPlayList.value = list;
|
||||||
videoType.value = "m3u8";
|
videoPlayIndex.value = index < 0 ? 0 : index;
|
||||||
videoSrc.value = url;
|
videoPlayTitle.value = title || "视频播放";
|
||||||
videoPlayModal.value = true;
|
videoPlayModal.value = true;
|
||||||
videoPlayTitle.value = title;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onVideoPlay = async (fid: number) => {
|
/** 未转码的视频没有 Url,直接取源片路径播放 */
|
||||||
dmsFileService
|
const onSourceVideoPlay = async (
|
||||||
.FindDeleteLogM3u8Path(fid)
|
record: DmsFileUploadDeleteLogViewDisplayData,
|
||||||
.then((res) => {
|
) => {
|
||||||
videoType.value = "video/mp4";
|
try {
|
||||||
videoSrc.value = res;
|
loading.value = true;
|
||||||
videoPlayModal.value = true;
|
const url = await dmsFileService.FindDeleteLogM3u8Path(record.FileId);
|
||||||
})
|
const item = toVideoItem(record);
|
||||||
.catch(() => {
|
item.FormattedUrl = url;
|
||||||
videoPlayModal.value = false;
|
openVideoPlay([item], 0, record.OrgFileName);
|
||||||
|
} catch (error) {
|
||||||
|
notification.info({
|
||||||
|
message: "系统提示:",
|
||||||
|
description: "视频加载失败",
|
||||||
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPreviewFile = async (
|
const onPreviewFile = async (
|
||||||
@@ -531,7 +560,7 @@ const onViewPic = () => {
|
|||||||
} else if (fileTypePolicy.isImage(keys.value[0].OrgFileName)) {
|
} else if (fileTypePolicy.isImage(keys.value[0].OrgFileName)) {
|
||||||
onPreviewFile(keys.value[0].CreatedBy, keys.value[0].OrderKey);
|
onPreviewFile(keys.value[0].CreatedBy, keys.value[0].OrderKey);
|
||||||
} else if (fileTypePolicy.isVideo(keys.value[0].OrgFileName)) {
|
} else if (fileTypePolicy.isVideo(keys.value[0].OrgFileName)) {
|
||||||
onVideoPlay(keys.value[0].FileId);
|
onUrlVideoPlayItem(keys.value[0]);
|
||||||
} else {
|
} else {
|
||||||
notification.info({
|
notification.info({
|
||||||
message: "系统提示:",
|
message: "系统提示:",
|
||||||
@@ -942,7 +971,7 @@ const onOpenFile = (record: DmsFileUploadDeleteLogViewDisplayData) => {
|
|||||||
if (fileTypePolicy.isImage(record.OrgFileName)) {
|
if (fileTypePolicy.isImage(record.OrgFileName)) {
|
||||||
onPreviewFile(record.CreatedBy, record.OrderKey);
|
onPreviewFile(record.CreatedBy, record.OrderKey);
|
||||||
} else if (fileTypePolicy.isVideo(record.OrgFileName)) {
|
} else if (fileTypePolicy.isVideo(record.OrgFileName)) {
|
||||||
onVideoPlay(record.FileId);
|
onUrlVideoPlayItem(record);
|
||||||
} else if (fileTypePolicy.isAudio(record.OrgFileName)) {
|
} else if (fileTypePolicy.isAudio(record.OrgFileName)) {
|
||||||
onPlayAudio(toUploadView(record));
|
onPlayAudio(toUploadView(record));
|
||||||
} else {
|
} else {
|
||||||
@@ -988,12 +1017,21 @@ const onViewPreviewSelected = (items: DmsFileUploadDeleteLogViewDisplayData[]) =
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUrlVideoPlayItem = (record: DmsFileUploadDeleteLogViewDisplayData) => {
|
/** 播放视频:把当前目录的视频串成播放列表,从点中的那一个开始 */
|
||||||
onUrlVideoPlay(
|
const onUrlVideoPlayItem = async (
|
||||||
record.Url,
|
record: DmsFileUploadDeleteLogViewDisplayData,
|
||||||
record.OrgFileName,
|
) => {
|
||||||
record.FormattedPic.replace(".m3u8", ".png"),
|
if (!record.Url) {
|
||||||
);
|
await onSourceVideoPlay(record);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list = buildVideoList(datas.value);
|
||||||
|
let index = list.findIndex((x) => x.FormattedUrl === record.Url);
|
||||||
|
if (index < 0) {
|
||||||
|
list.unshift(toVideoItem(record));
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
openVideoPlay(list, index, record.OrgFileName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPlayAudioItem = (record: DmsFileUploadDeleteLogViewDisplayData) => {
|
const onPlayAudioItem = (record: DmsFileUploadDeleteLogViewDisplayData) => {
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
onVisibleChange: setPicVisible,
|
onVisibleChange: setPicVisible,
|
||||||
}" :src="imageSrc" />
|
}" :src="imageSrc" />
|
||||||
<dmsFolder @on-submit="onReload" @submit-start="loading = true" @submit-end="loading = false"></dmsFolder>
|
<dmsFolder @on-submit="onReload" @submit-start="loading = true" @submit-end="loading = false"></dmsFolder>
|
||||||
<videoPlay></videoPlay>
|
<VideoPlayModal v-model:open="videoPlayModal" :videos="videoPlayList" :start-index="videoPlayIndex"
|
||||||
|
:title="videoPlayTitle" :fullscreen="width < 640" />
|
||||||
<dragModal v-model:open="showModalShare" width="60%" title="分享管理查询" :mask-closable="false" :fullscreen="width < 640"
|
<dragModal v-model:open="showModalShare" width="60%" title="分享管理查询" :mask-closable="false" :fullscreen="width < 640"
|
||||||
@ok="handleSelectShare">
|
@ok="handleSelectShare">
|
||||||
<DmsFileShareModal ref="shareEnquiry"></DmsFileShareModal>
|
<DmsFileShareModal ref="shareEnquiry"></DmsFileShareModal>
|
||||||
@@ -83,7 +84,6 @@ import dmsFolder from "./DmsFolderModal.vue";
|
|||||||
import { useLoginProfileStore } from "@/store/modules/loginProfile";
|
import { useLoginProfileStore } from "@/store/modules/loginProfile";
|
||||||
import { WebSitePolicy } from "@/policy/custom/webSitePolicy";
|
import { WebSitePolicy } from "@/policy/custom/webSitePolicy";
|
||||||
import { orderBy } from "lodash-es";
|
import { orderBy } from "lodash-es";
|
||||||
import VideoPlay from "./PlayVideo.vue";
|
|
||||||
import { Howl } from "howler";
|
import { Howl } from "howler";
|
||||||
import { PublishVideoEntity } from "@/data/auto/publishVideoEntity";
|
import { PublishVideoEntity } from "@/data/auto/publishVideoEntity";
|
||||||
import publishVideoService from "@/service/master/publishVideoService";
|
import publishVideoService from "@/service/master/publishVideoService";
|
||||||
@@ -98,6 +98,9 @@ import { PublishPhotoEntity } from "@/data/auto/publishPhotoEntity";
|
|||||||
import MyComputer from "@/components/basic/MyComputer.vue";
|
import MyComputer from "@/components/basic/MyComputer.vue";
|
||||||
import Toolbar from "@/components/basic/Toolbar.vue";
|
import Toolbar from "@/components/basic/Toolbar.vue";
|
||||||
import OperatorStation from "@/components/basic/OperatorStation.vue";
|
import OperatorStation from "@/components/basic/OperatorStation.vue";
|
||||||
|
import VideoPlayModal from "@/components/basic/VideoPlayModal.vue";
|
||||||
|
import type { VideoItem } from "@/components/basic/VideoPlayer.vue";
|
||||||
|
import { PublishVideoDetailDisplayData } from "@/data/auto/publishVideoDetailDisplayData";
|
||||||
|
|
||||||
interface BreadcrumbItem {
|
interface BreadcrumbItem {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -163,9 +166,8 @@ const dmsFolderIsRename = ref<boolean>(false);
|
|||||||
const dmsFolderIsMove = ref<boolean>(false);
|
const dmsFolderIsMove = ref<boolean>(false);
|
||||||
const entity = ref<DmsFileEntity>(new DmsFileEntity());
|
const entity = ref<DmsFileEntity>(new DmsFileEntity());
|
||||||
const videoPlayModal = ref<boolean>(false);
|
const videoPlayModal = ref<boolean>(false);
|
||||||
const videoSrc = ref<string>("");
|
const videoPlayList = ref<VideoItem[]>([]);
|
||||||
const videoPoster = ref<string>("");
|
const videoPlayIndex = ref<number>(0);
|
||||||
const videoType = ref<string>("");
|
|
||||||
const videoPlayTitle = ref<string>("");
|
const videoPlayTitle = ref<string>("");
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
|
|
||||||
@@ -198,6 +200,7 @@ const toUploadView = (r: Record<string, any>): DmsFileUploadViewDisplayData =>
|
|||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
sound.value?.stop();
|
sound.value?.stop();
|
||||||
|
clearRefreshTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
const play = (src: string) => {
|
const play = (src: string) => {
|
||||||
@@ -264,11 +267,6 @@ provide("dmsFolderTitle", dmsFolderTitle);
|
|||||||
provide("dmsFolderIsRename", dmsFolderIsRename);
|
provide("dmsFolderIsRename", dmsFolderIsRename);
|
||||||
provide("dmsFolderIsMove", dmsFolderIsMove);
|
provide("dmsFolderIsMove", dmsFolderIsMove);
|
||||||
provide("DmsFileEntity", entity);
|
provide("DmsFileEntity", entity);
|
||||||
provide("videoPlayModal", videoPlayModal);
|
|
||||||
provide("videoPlayTitle", videoPlayTitle);
|
|
||||||
provide("videoSrc", videoSrc);
|
|
||||||
provide("videoPoster", videoPoster);
|
|
||||||
provide("videoType", videoType);
|
|
||||||
provide("isModalPublishVideo", showModalPublishVideo);
|
provide("isModalPublishVideo", showModalPublishVideo);
|
||||||
provide("isModalPublishAudio", showModalPublishAudio);
|
provide("isModalPublishAudio", showModalPublishAudio);
|
||||||
provide("isModalPublishPhoto", showModalPublishPhoto);
|
provide("isModalPublishPhoto", showModalPublishPhoto);
|
||||||
@@ -313,15 +311,32 @@ const onUploadSuccess = () => {
|
|||||||
spinTip.value = "上传完成,等待服务端处理...";
|
spinTip.value = "上传完成,等待服务端处理...";
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 一批文件全部传完:给后端留点时间合并分片,文件越多等得越久 */
|
/** 上传后延迟刷新的定时器,离开页面/重新开始时清掉,避免野刷新 */
|
||||||
|
let refreshTimers: number[] = [];
|
||||||
|
const clearRefreshTimers = () => {
|
||||||
|
refreshTimers.forEach((t) => clearTimeout(t));
|
||||||
|
refreshTimers = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一批文件全部传完:给后端留点时间合并分片,文件越多等得越久。
|
||||||
|
* 视频封面(jpg)由 ffmpeg 生成、可能比合并更慢,所以首刷之后再补刷两次——
|
||||||
|
* 每次查询服务端都会重新拼 ?v=,src 变了 <img> 才会重新请求,封面就能补上来。
|
||||||
|
*/
|
||||||
const onUploadComplete = (payload: { count?: number }) => {
|
const onUploadComplete = (payload: { count?: number }) => {
|
||||||
const count = payload?.count ?? 1;
|
const count = payload?.count ?? 1;
|
||||||
const sec = 2500 + (count - 1) * 1000;
|
const sec = 2500 + (count - 1) * 1000;
|
||||||
spinTip.value = "加载中...";
|
spinTip.value = "加载中...";
|
||||||
setTimeout(() => {
|
clearRefreshTimers();
|
||||||
onReSearch();
|
|
||||||
loading.value = false;
|
refreshTimers.push(
|
||||||
}, sec);
|
window.setTimeout(() => {
|
||||||
|
onReSearch();
|
||||||
|
loading.value = false;
|
||||||
|
}, sec),
|
||||||
|
);
|
||||||
|
refreshTimers.push(window.setTimeout(onReSearch, sec + 3000));
|
||||||
|
refreshTimers.push(window.setTimeout(onReSearch, sec + 6000));
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 中断时的断点信息,弹窗里展示用 */
|
/** 中断时的断点信息,弹窗里展示用 */
|
||||||
@@ -395,29 +410,57 @@ const onChangeFolder = async (fvalue: string) => {
|
|||||||
onSearchByFilePath(fvalue);
|
onSearchByFilePath(fvalue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUrlVideoPlay = (url: string, title: string, poster: string) => {
|
/** DMS 记录 → 播放列表项(m3u8 的封面用同名 png 兜底) */
|
||||||
|
const toVideoItem = (record: DmsFileUploadViewDisplayData): VideoItem => {
|
||||||
|
const item = new PublishVideoDetailDisplayData();
|
||||||
|
item.Title = record.OrgFileName;
|
||||||
|
item.FormattedUrl = record.Url;
|
||||||
|
item.FormattedPic = (record.FormattedPic || "").replace(/\.m3u8$/, ".png");
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 当前目录里已转码(有 Url)的视频,作为弹窗播放器的播放列表 */
|
||||||
|
const buildVideoList = (
|
||||||
|
records: DmsFileUploadViewDisplayData[],
|
||||||
|
): VideoItem[] =>
|
||||||
|
records
|
||||||
|
.filter(
|
||||||
|
(x) =>
|
||||||
|
x.IsDirectoryIndc != "Y" &&
|
||||||
|
fileTypePolicy.isVideo(x.OrderKey || x.OrgFileName) &&
|
||||||
|
!!x.Url,
|
||||||
|
)
|
||||||
|
.map(toVideoItem);
|
||||||
|
|
||||||
|
/** 打开视频弹窗 */
|
||||||
|
const openVideoPlay = (list: VideoItem[], index: number, title: string) => {
|
||||||
sound.value?.stop();
|
sound.value?.stop();
|
||||||
datas.value.forEach((element) => {
|
datas.value.forEach((element) => {
|
||||||
element.IsPlay = "";
|
element.IsPlay = "";
|
||||||
});
|
});
|
||||||
videoPoster.value = poster;
|
videoPlayList.value = list;
|
||||||
videoType.value = "m3u8";
|
videoPlayIndex.value = index < 0 ? 0 : index;
|
||||||
videoSrc.value = url;
|
videoPlayTitle.value = title || "视频播放";
|
||||||
videoPlayModal.value = true;
|
videoPlayModal.value = true;
|
||||||
videoPlayTitle.value = title;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onVideoPlay = async (fid: number) => {
|
/** 未转码的视频没有 Url,直接取源片路径播放 */
|
||||||
dmsFileService
|
const onSourceVideoPlay = async (record: DmsFileUploadViewDisplayData) => {
|
||||||
.FindSourceVideoPath(fid)
|
try {
|
||||||
.then((res) => {
|
loading.value = true;
|
||||||
videoType.value = "video/mp4";
|
const url = await dmsFileService.FindSourceVideoPath(record.FileId);
|
||||||
videoSrc.value = res;
|
const item = toVideoItem(record);
|
||||||
videoPlayModal.value = true;
|
item.FormattedUrl = url;
|
||||||
})
|
openVideoPlay([item], 0, record.OrgFileName);
|
||||||
.catch(() => {
|
} catch (error) {
|
||||||
videoPlayModal.value = false;
|
notification.info({
|
||||||
|
message: "系统提示:",
|
||||||
|
description: "视频加载失败",
|
||||||
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPreviewFile = async (usernameOrRecord: any, orderKey?: string) => {
|
const onPreviewFile = async (usernameOrRecord: any, orderKey?: string) => {
|
||||||
@@ -626,7 +669,7 @@ const onViewPic = () => {
|
|||||||
} else if (fileTypePolicy.isImage(keys.value[0].OrgFileName)) {
|
} else if (fileTypePolicy.isImage(keys.value[0].OrgFileName)) {
|
||||||
onPreviewFile(keys.value[0].CreatedBy, keys.value[0].OrderKey);
|
onPreviewFile(keys.value[0].CreatedBy, keys.value[0].OrderKey);
|
||||||
} else if (fileTypePolicy.isVideo(keys.value[0].OrgFileName)) {
|
} else if (fileTypePolicy.isVideo(keys.value[0].OrgFileName)) {
|
||||||
onVideoPlay(keys.value[0].FileId);
|
onUrlVideoPlayItem(keys.value[0]);
|
||||||
} else {
|
} else {
|
||||||
notification.info({
|
notification.info({
|
||||||
message: "系统提示:",
|
message: "系统提示:",
|
||||||
@@ -1065,7 +1108,7 @@ const onOpenFile = (record: DmsFileUploadViewDisplayData) => {
|
|||||||
if (fileTypePolicy.isImage(record.OrgFileName)) {
|
if (fileTypePolicy.isImage(record.OrgFileName)) {
|
||||||
onPreviewFile(record.CreatedBy, record.OrderKey);
|
onPreviewFile(record.CreatedBy, record.OrderKey);
|
||||||
} else if (fileTypePolicy.isVideo(record.OrgFileName)) {
|
} else if (fileTypePolicy.isVideo(record.OrgFileName)) {
|
||||||
onVideoPlay(record.FileId);
|
onUrlVideoPlayItem(record);
|
||||||
} else if (fileTypePolicy.isAudio(record.OrgFileName)) {
|
} else if (fileTypePolicy.isAudio(record.OrgFileName)) {
|
||||||
onPlayAudio(toUploadView(record));
|
onPlayAudio(toUploadView(record));
|
||||||
} else {
|
} else {
|
||||||
@@ -1135,12 +1178,19 @@ const onViewPreviewSelected = (items: DmsFileUploadViewDisplayData[]) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUrlVideoPlayItem = (record: DmsFileUploadViewDisplayData) => {
|
/** 播放视频:把当前目录的视频串成播放列表,从点中的那一个开始 */
|
||||||
onUrlVideoPlay(
|
const onUrlVideoPlayItem = async (record: DmsFileUploadViewDisplayData) => {
|
||||||
record.Url,
|
if (!record.Url) {
|
||||||
record.OrgFileName,
|
await onSourceVideoPlay(record);
|
||||||
record.FormattedPic.replace(".m3u8", ".png"),
|
return;
|
||||||
);
|
}
|
||||||
|
const list = buildVideoList(datas.value);
|
||||||
|
let index = list.findIndex((x) => x.FormattedUrl === record.Url);
|
||||||
|
if (index < 0) {
|
||||||
|
list.unshift(toVideoItem(record));
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
openVideoPlay(list, index, record.OrgFileName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPlayAudioItem = (record: DmsFileUploadViewDisplayData) => {
|
const onPlayAudioItem = (record: DmsFileUploadViewDisplayData) => {
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
onVisibleChange: setPicVisible,
|
onVisibleChange: setPicVisible,
|
||||||
}" :src="imageSrc" />
|
}" :src="imageSrc" />
|
||||||
<dmsFolder @on-submit="onReload" @submit-start="loading = true" @submit-end="loading = false"></dmsFolder>
|
<dmsFolder @on-submit="onReload" @submit-start="loading = true" @submit-end="loading = false"></dmsFolder>
|
||||||
<videoPlay></videoPlay>
|
<VideoPlayModal v-model:open="videoPlayModal" :videos="videoPlayList" :start-index="videoPlayIndex"
|
||||||
|
:title="videoPlayTitle" :fullscreen="width < 640" />
|
||||||
<dragModal v-model:open="showModalShare" width="60%" title="分享管理查询" :mask-closable="false" :fullscreen="width < 640"
|
<dragModal v-model:open="showModalShare" width="60%" title="分享管理查询" :mask-closable="false" :fullscreen="width < 640"
|
||||||
@ok="handleSelectShare">
|
@ok="handleSelectShare">
|
||||||
<DmsFileShareModal ref="shareEnquiry"></DmsFileShareModal>
|
<DmsFileShareModal ref="shareEnquiry"></DmsFileShareModal>
|
||||||
@@ -69,7 +70,6 @@ import { notification } from "ant-design-vue";
|
|||||||
import { SearchCriteriaResultData } from "@/data/auto/searchCriteriaResultData";
|
import { SearchCriteriaResultData } from "@/data/auto/searchCriteriaResultData";
|
||||||
import dmsFolder from "./DmsFolderModal.vue";
|
import dmsFolder from "./DmsFolderModal.vue";
|
||||||
import { orderBy } from "lodash-es";
|
import { orderBy } from "lodash-es";
|
||||||
import VideoPlay from "./PlayVideo.vue";
|
|
||||||
import { Howl } from "howler";
|
import { Howl } from "howler";
|
||||||
import { PublishVideoEntity } from "@/data/auto/publishVideoEntity";
|
import { PublishVideoEntity } from "@/data/auto/publishVideoEntity";
|
||||||
import publishVideoService from "@/service/master/publishVideoService";
|
import publishVideoService from "@/service/master/publishVideoService";
|
||||||
@@ -84,6 +84,9 @@ import { PublishPhotoEntity } from "@/data/auto/publishPhotoEntity";
|
|||||||
import MyComputerFamily from "@/components/basic/MyComputerFamily.vue";
|
import MyComputerFamily from "@/components/basic/MyComputerFamily.vue";
|
||||||
import Toolbar from "@/components/basic/Toolbar.vue";
|
import Toolbar from "@/components/basic/Toolbar.vue";
|
||||||
import OperatorStationFamily from "@/components/basic/OperatorStationFamily.vue";
|
import OperatorStationFamily from "@/components/basic/OperatorStationFamily.vue";
|
||||||
|
import VideoPlayModal from "@/components/basic/VideoPlayModal.vue";
|
||||||
|
import type { VideoItem } from "@/components/basic/VideoPlayer.vue";
|
||||||
|
import { PublishVideoDetailDisplayData } from "@/data/auto/publishVideoDetailDisplayData";
|
||||||
import { FamilyDmsFileViewEntity } from "@/data/auto/familyDmsFileViewEntity.ts";
|
import { FamilyDmsFileViewEntity } from "@/data/auto/familyDmsFileViewEntity.ts";
|
||||||
import FamilyGroupService from "@/service/master/familyGroupService";
|
import FamilyGroupService from "@/service/master/familyGroupService";
|
||||||
|
|
||||||
@@ -131,9 +134,8 @@ const dmsFolderIsRename = ref<boolean>(false);
|
|||||||
const dmsFolderIsMove = ref<boolean>(false);
|
const dmsFolderIsMove = ref<boolean>(false);
|
||||||
const entity = ref<DmsFileEntity>(new DmsFileEntity());
|
const entity = ref<DmsFileEntity>(new DmsFileEntity());
|
||||||
const videoPlayModal = ref<boolean>(false);
|
const videoPlayModal = ref<boolean>(false);
|
||||||
const videoSrc = ref<string>("");
|
const videoPlayList = ref<VideoItem[]>([]);
|
||||||
const videoPoster = ref<string>("");
|
const videoPlayIndex = ref<number>(0);
|
||||||
const videoType = ref<string>("");
|
|
||||||
const videoPlayTitle = ref<string>("");
|
const videoPlayTitle = ref<string>("");
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
const currentFamilyName = ref<string>("");
|
const currentFamilyName = ref<string>("");
|
||||||
@@ -238,11 +240,6 @@ provide("DmsFileEntity", entity);
|
|||||||
provide("dmsFolderIsFamilyGroup", true);
|
provide("dmsFolderIsFamilyGroup", true);
|
||||||
provide("dmsFolderFamilyName", currentFamilyName);
|
provide("dmsFolderFamilyName", currentFamilyName);
|
||||||
|
|
||||||
provide("videoPlayModal", videoPlayModal);
|
|
||||||
provide("videoPlayTitle", videoPlayTitle);
|
|
||||||
provide("videoSrc", videoSrc);
|
|
||||||
provide("videoPoster", videoPoster);
|
|
||||||
provide("videoType", videoType);
|
|
||||||
provide("isModalPublishVideo", showModalPublishVideo);
|
provide("isModalPublishVideo", showModalPublishVideo);
|
||||||
provide("isModalPublishAudio", showModalPublishAudio);
|
provide("isModalPublishAudio", showModalPublishAudio);
|
||||||
provide("isModalPublishPhoto", showModalPublishPhoto);
|
provide("isModalPublishPhoto", showModalPublishPhoto);
|
||||||
@@ -295,29 +292,57 @@ const onChangeFolder = async (fvalue: string) => {
|
|||||||
onSearchByFilePath(fvalue);
|
onSearchByFilePath(fvalue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUrlVideoPlay = (url: string, title: string, poster: string) => {
|
/** DMS 记录 → 播放列表项(m3u8 的封面用同名 png 兜底) */
|
||||||
|
const toVideoItem = (record: FamilyDmsFileViewDisplayData): VideoItem => {
|
||||||
|
const item = new PublishVideoDetailDisplayData();
|
||||||
|
item.Title = record.OrgFileName;
|
||||||
|
item.FormattedUrl = record.Url;
|
||||||
|
item.FormattedPic = (record.FormattedPic || "").replace(/\.m3u8$/, ".png");
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 当前目录里已转码(有 Url)的视频,作为弹窗播放器的播放列表 */
|
||||||
|
const buildVideoList = (
|
||||||
|
records: FamilyDmsFileViewDisplayData[],
|
||||||
|
): VideoItem[] =>
|
||||||
|
records
|
||||||
|
.filter(
|
||||||
|
(x) =>
|
||||||
|
x.IsDirectoryIndc != "Y" &&
|
||||||
|
fileTypePolicy.isVideo(x.OrderKey || x.OrgFileName) &&
|
||||||
|
!!x.Url,
|
||||||
|
)
|
||||||
|
.map(toVideoItem);
|
||||||
|
|
||||||
|
/** 打开视频弹窗 */
|
||||||
|
const openVideoPlay = (list: VideoItem[], index: number, title: string) => {
|
||||||
sound.value?.stop();
|
sound.value?.stop();
|
||||||
datas.value.forEach((element) => {
|
datas.value.forEach((element) => {
|
||||||
element.IsPlay = "";
|
element.IsPlay = "";
|
||||||
});
|
});
|
||||||
videoPoster.value = poster;
|
videoPlayList.value = list;
|
||||||
videoType.value = "m3u8";
|
videoPlayIndex.value = index < 0 ? 0 : index;
|
||||||
videoSrc.value = url;
|
videoPlayTitle.value = title || "视频播放";
|
||||||
videoPlayModal.value = true;
|
videoPlayModal.value = true;
|
||||||
videoPlayTitle.value = title;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onVideoPlay = async (fid: number) => {
|
/** 未转码的视频没有 Url,直接取源片路径播放 */
|
||||||
dmsFileService
|
const onSourceVideoPlay = async (record: FamilyDmsFileViewDisplayData) => {
|
||||||
.FindSourceVideoPath(fid)
|
try {
|
||||||
.then((res) => {
|
loading.value = true;
|
||||||
videoType.value = "video/mp4";
|
const url = await dmsFileService.FindSourceVideoPath(record.FileId);
|
||||||
videoSrc.value = res;
|
const item = toVideoItem(record);
|
||||||
videoPlayModal.value = true;
|
item.FormattedUrl = url;
|
||||||
})
|
openVideoPlay([item], 0, record.OrgFileName);
|
||||||
.catch(() => {
|
} catch (error) {
|
||||||
videoPlayModal.value = false;
|
notification.info({
|
||||||
|
message: "系统提示:",
|
||||||
|
description: "视频加载失败",
|
||||||
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPreviewFile = async (usernameOrRecord: any, orderKey?: string) => {
|
const onPreviewFile = async (usernameOrRecord: any, orderKey?: string) => {
|
||||||
@@ -531,7 +556,7 @@ const onViewPic = () => {
|
|||||||
} else if (fileTypePolicy.isImage(keys.value[0].OrgFileName)) {
|
} else if (fileTypePolicy.isImage(keys.value[0].OrgFileName)) {
|
||||||
onPreviewFile(keys.value[0].CreatedBy, keys.value[0].OrderKey);
|
onPreviewFile(keys.value[0].CreatedBy, keys.value[0].OrderKey);
|
||||||
} else if (fileTypePolicy.isVideo(keys.value[0].OrgFileName)) {
|
} else if (fileTypePolicy.isVideo(keys.value[0].OrgFileName)) {
|
||||||
onVideoPlay(keys.value[0].FileId);
|
onUrlVideoPlayItem(keys.value[0]);
|
||||||
} else {
|
} else {
|
||||||
notification.info({
|
notification.info({
|
||||||
message: "系统提示:",
|
message: "系统提示:",
|
||||||
@@ -1047,7 +1072,7 @@ const onOpenFile = (record: FamilyDmsFileViewDisplayData) => {
|
|||||||
if (fileTypePolicy.isImage(record.OrgFileName)) {
|
if (fileTypePolicy.isImage(record.OrgFileName)) {
|
||||||
onPreviewFile(record.CreatedBy, record.OrderKey);
|
onPreviewFile(record.CreatedBy, record.OrderKey);
|
||||||
} else if (fileTypePolicy.isVideo(record.OrgFileName)) {
|
} else if (fileTypePolicy.isVideo(record.OrgFileName)) {
|
||||||
onVideoPlay(record.FileId);
|
onUrlVideoPlayItem(record);
|
||||||
} else if (fileTypePolicy.isAudio(record.OrgFileName)) {
|
} else if (fileTypePolicy.isAudio(record.OrgFileName)) {
|
||||||
onPlayAudio(toUploadView(record));
|
onPlayAudio(toUploadView(record));
|
||||||
} else {
|
} else {
|
||||||
@@ -1111,12 +1136,19 @@ const onViewPreviewSelected = (items: FamilyDmsFileViewDisplayData[]) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUrlVideoPlayItem = (record: FamilyDmsFileViewDisplayData) => {
|
/** 播放视频:把当前目录的视频串成播放列表,从点中的那一个开始 */
|
||||||
onUrlVideoPlay(
|
const onUrlVideoPlayItem = async (record: FamilyDmsFileViewDisplayData) => {
|
||||||
record.Url,
|
if (!record.Url) {
|
||||||
record.OrgFileName,
|
await onSourceVideoPlay(record);
|
||||||
record.FormattedPic.replace(".m3u8", ".png"),
|
return;
|
||||||
);
|
}
|
||||||
|
const list = buildVideoList(datas.value);
|
||||||
|
let index = list.findIndex((x) => x.FormattedUrl === record.Url);
|
||||||
|
if (index < 0) {
|
||||||
|
list.unshift(toVideoItem(record));
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
openVideoPlay(list, index, record.OrgFileName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPlayAudioItem = (record: FamilyDmsFileViewDisplayData) => {
|
const onPlayAudioItem = (record: FamilyDmsFileViewDisplayData) => {
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
<template>
|
|
||||||
<dragModal :width="modal.width" v-model:open="modal.showModal" :title="title" :mask-closable="false">
|
|
||||||
<vue3VideoPlay ref="videoPlayerM3u8" v-if="videoType == 'm3u8'" :title="title" :src="modal.videoSrc" type="m3u8"
|
|
||||||
:autoPlay="true" />
|
|
||||||
<vue3VideoPlay ref="videoPlayerMp4" v-else :title="title" :src="modal.videoSrc" type="video/mp4"
|
|
||||||
:autoPlay="true" />
|
|
||||||
<template #footer>
|
|
||||||
<a-button type="primary" @click="handleSubmit">关闭</a-button>
|
|
||||||
</template>
|
|
||||||
</dragModal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { watch, watchEffect, inject, reactive, ref, VNode, h, unref, onMounted, onBeforeMount } from "vue";
|
|
||||||
import dragModal from "@/components/basic/DragModal.vue"
|
|
||||||
|
|
||||||
const modal = reactive({
|
|
||||||
loading: false,
|
|
||||||
showModal: false,
|
|
||||||
videoSrc: '',
|
|
||||||
width: '850px'
|
|
||||||
});
|
|
||||||
|
|
||||||
const videoPlayerM3u8 = ref()
|
|
||||||
const videoPlayerMp4 = ref()
|
|
||||||
|
|
||||||
const title = ref(inject<string>("videoPlayTitle", '视频播放'));
|
|
||||||
|
|
||||||
const videoPlayModal = inject<boolean>("videoPlayModal");
|
|
||||||
const videoSrc = inject<string>("videoSrc");
|
|
||||||
|
|
||||||
|
|
||||||
modal.showModal = videoPlayModal!;
|
|
||||||
modal.videoSrc = videoSrc!;
|
|
||||||
|
|
||||||
|
|
||||||
import { bsInfo } from "@/utils/browser"
|
|
||||||
|
|
||||||
if (bsInfo.size.sm) {
|
|
||||||
modal.width = '350px';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
modal.width = '850px';
|
|
||||||
}
|
|
||||||
|
|
||||||
const videoType = ref(inject<string>("videoType", 'm3u8'));
|
|
||||||
|
|
||||||
|
|
||||||
//const videoSrc = ref('https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8');
|
|
||||||
// 视频播放器配置
|
|
||||||
const options = reactive({
|
|
||||||
src: modal.videoSrc, //视频源
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
try {
|
|
||||||
|
|
||||||
modal.loading = true;
|
|
||||||
modal.showModal = false;
|
|
||||||
|
|
||||||
// console.log('-----------close video player -----------')
|
|
||||||
if (videoType.value == 'm3u8') {
|
|
||||||
videoPlayerM3u8.value?.pause();
|
|
||||||
videoPlayerM3u8.value?.removeAttribute('src');
|
|
||||||
videoPlayerM3u8.value?.load();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
videoPlayerMp4.value?.pause();
|
|
||||||
videoPlayerMp4.value?.removeAttribute('src');
|
|
||||||
videoPlayerMp4.value?.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
} finally {
|
|
||||||
modal.loading = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
declare module "vue3-video-play";
|
|
||||||
declare module "@worstone/vue-aplayer";
|
declare module "@worstone/vue-aplayer";
|
||||||
declare module "wow.js";
|
declare module "wow.js";
|
||||||
Reference in new issue
Block a user