Browse Source

feat:添加预览窗口

Zhenghanjv 2 tháng trước cách đây
mục cha
commit
0a751f8a84

+ 4 - 1
Platform/AI.Platform.Page/Pages/Media/Media.razor

@@ -50,7 +50,9 @@
         </div>
     </div>
 
-    <UpdateMediaDialog onCallback="OnDialogCallback" onVisibleCallback="OnDialogVisibleCallback"  @bind-IsVisible="isOpen" @bind-model="model" />
+    <UpdateMediaDialog onCallback="OnDialogCallback" onVisibleCallback="@((data) => OnDialogVisibleCallback(1,data))" @bind-IsVisible="isOpen" @bind-model="model" />
+    <MediaPreview onVisibleCallback="@((data) => OnDialogVisibleCallback(2, data))" @bind-IsVisible="isPreviewOpen" @bind-media="previewModel" />
+
 
     <Table @ref="_Table" AutoHeight TItem="MediaInfoModel" DataSource="_DataSource" PageSize="filterData.pageSize" Total="Total"
     OnChange="OnChange">
@@ -77,6 +79,7 @@
             <PropertyColumn Property="c => c.Remark" Title="备注" />
 
             <ActionColumn Width="180" Title="操作" Fixed="ColumnFixPlacement.Right">
+                <Button Type="ButtonType.Primary" Color="Color.Blue6" OnClick="@(() => ShowPreviewDialog(row))">预览</Button>
                 <Button Type="ButtonType.Primary" Color="Color.Blue6" OnClick="@(() => ShowDialog(2, row))">编辑</Button>
                 <Button Type="ButtonType.Primary" Color="Color.Red6" OnClick="@(() => ShowDialog(3, row))">删除</Button>
             </ActionColumn>

+ 32 - 4
Platform/AI.Platform.Page/Pages/Media/Media.razor.cs

@@ -73,11 +73,17 @@ public partial class Media
     private UpdateMediaDialog updateMediaDialog { set; get; } = new();
 
     /// <summary>
-    /// 标识弹窗是否显示
+    /// 标识编辑弹窗是否显示
     /// </summary>
     private bool isOpen { set; get; } = false;
 
+    /// <summary>
+    /// 标识预览弹窗是否显示
+    /// </summary>
+    private bool isPreviewOpen { set; get; } = false;
+
     private MediaDialogModel model = new MediaDialogModel();
+    private PreviewInfo previewModel = new PreviewInfo();
 
     // <summary>
     /// 站点
@@ -153,13 +159,35 @@ public partial class Media
         await Query();
     }
 
+    private async Task ShowPreviewDialog(MediaInfoModel media)
+    {
+        previewModel = new()
+        {
+            Type = media.getType(),
+            Path = media.SavePath
+        };
+
+        isPreviewOpen = true;
+    }
+
     /// <summary>
-    /// 编辑弹窗是否显示回调
+    /// 弹窗是否显示回调
     /// </summary>
     /// <param name="isOpen"></param>
-    private void OnDialogVisibleCallback(bool isOpen)
+    private void OnDialogVisibleCallback(int type, bool isOpen)
     {
-        this.isOpen = isOpen;
+        switch(type)
+        {
+            case 1:
+                this.isOpen = isOpen;
+                break;
+            case 2:
+                this.isPreviewOpen = isOpen;
+                
+                break;
+
+        }
+       
     }
 
     private async Task searchSitesAsync()

+ 149 - 0
Platform/AI.Platform.Page/Pages/Media/MediaPreview.razor

@@ -0,0 +1,149 @@
+@using AI.Platform.Page.Pages.Media.Model
+@using System.Threading.Tasks
+@using System.Text.Json
+
+@if (IsVisible)
+{
+    <div class="modal-overlay">
+        <div class="modal-content filter_box">
+            <div class="screen_box">
+                @if(Media.Type == MediaType.VIDEO)
+                {
+                    <video class="video_box" src="@(Utils.ToWebPath(Media.Path))" autoplay></video>
+                } else
+                {
+                    <div class="video_tip">视频区</div>
+                }
+                
+                @if (Media.Type == MediaType.IMAGE)
+                {
+                    <img class="image_box" src="@(Utils.ToWebPath(Media.Path))" />
+                }
+                else
+                {
+                    <div class="image_tip">图片区</div>
+                }
+                
+                <div class="nozzle_box">
+                    <img  src="@(Utils.ToWebPath("wwwroot\\images\\backgroud\\nozzle.png"))" />
+                </div>
+                
+            </div>
+
+
+
+            <div class="filter_row" style="justify-content:end;margin-top:5%;">
+                <Button Icon="plus" OnClick="onSure" Style="margin-right:2%">确定</Button>
+                <Button Icon="reload" OnClick="Close" Style="margin-right:2%">取消</Button>
+            </div>
+
+            
+        </div>
+
+    </div>
+}
+
+<style>
+    /* 遮罩层:全屏、半透明 */
+    .modal-overlay {
+        position: fixed;
+        top: 0;
+        left: 0;
+        width: 100vw;
+        height: 100vh;
+        background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色遮罩 */
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        z-index: 1000;
+    }
+
+    /* 弹窗内容:白色卡片,居中由父容器控制 */
+    .modal-content {
+        background: white;
+        border-radius: 8px;
+        width: 80%;
+        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
+        /* 注意:不要设 height: 100vh,否则会拉满全屏 */
+    }
+
+    .filter_box {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        background: #ffffff;
+        padding: 2%;
+    }
+
+    .filter_row {
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items: center;
+        width: 100%;
+        margin-top: 2%;
+    }
+
+    .screen_box{
+        width:30%;
+        height:80vh;
+        background: #2e2e2e;
+        display:flex;
+        flex-direction:column;
+        align-items:center;
+
+    }
+
+    .video_box{
+        width:90%;
+        height:30%;
+        display:flex;
+        justify-content:center;
+        align-items:center;
+        margin-top:1%;
+    }
+    .video_tip{
+        width: 90%;
+        height: 30%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-top: 1%;
+        border: solid 1px #FFFFFF;
+        color: #FFFFFF;
+    }
+
+    .image_box{
+        width: 90%;
+        height: 30%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-top: 1%;
+    }
+    .image_tip {
+        width: 90%;
+        height: 30%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-top: 1%;
+        border: solid 1px #FFFFFF;
+        color: #FFFFFF;
+    }
+
+    .nozzle_box {
+        width: 90%;
+        height: 50%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-top: 1%;
+    }
+
+    .media-container img {
+       
+        width: 50%;
+        height: 50%;
+    }
+</style>

+ 78 - 0
Platform/AI.Platform.Page/Pages/Media/MediaPreview.razor.cs

@@ -0,0 +1,78 @@
+using AI.Platform.Core;
+using AI.Platform.Core.Entity.Media;
+using AI.Platform.Page.Pages.Media.Model;
+using AI.Platform.Page.Pages.Site.Model;
+using Microsoft.AspNetCore.Components;
+
+namespace AI.Platform.Page.Pages.Media;
+
+public partial class MediaPreview
+{
+    /// <summary>
+    /// 信息回调
+    /// </summary>
+    [Parameter] public EventCallback<PreviewInfo> MediaChanged { get; set; }
+
+    /// <summary>
+    /// 打开/关闭窗口回调
+    /// </summary>
+    [Parameter] public EventCallback<bool> IsVisibleChanged { get; set; }
+
+    /// <summary>
+    /// 打开/关闭窗口回调
+    /// </summary>
+    [Parameter] public EventCallback<bool> onVisibleCallback { get; set; }
+
+    /// <summary>
+    /// 广告地址
+    /// </summary>
+    [Parameter] public PreviewInfo Media { get; set; }
+
+    /// <summary>
+    /// 配置是否弹窗
+    /// </summary>
+    [Parameter] public bool IsVisible { get; set; }
+
+    
+
+    protected override void OnParametersSet()
+    {
+        
+    }
+
+    /// <summary>
+    /// 关闭弹窗
+    /// </summary>
+    public async Task Close()
+    {
+        await OnlyClose();
+    }
+    /// <summary>
+    /// 仅关闭弹窗
+    /// </summary>
+    /// <returns></returns>
+    private async Task OnlyClose()
+    {
+        if (IsVisibleChanged.HasDelegate)
+        {
+            await IsVisibleChanged.InvokeAsync(false);
+        }
+
+        if (onVisibleCallback.HasDelegate)
+        {
+            await onVisibleCallback.InvokeAsync(false);
+        }
+    }
+
+    /// <summary>
+    /// 确定按钮事件
+    /// </summary>
+    /// <returns></returns>
+    private async Task onSure()
+    {
+        
+        await OnlyClose();
+    }
+
+    
+}

+ 34 - 0
Platform/AI.Platform.Page/Pages/Media/Model/MediaModel.cs

@@ -1,6 +1,7 @@
 using AI.Platform.Core;
 using AI.Platform.Core.Entity.Media;
 using AI.Platform.Page.Pages.Site.Model;
+using Dm.util;
 using Microsoft.AspNetCore.Components;
 using SqlSugar;
 using System;
@@ -272,5 +273,38 @@ namespace AI.Platform.Page.Pages.Media.Model
         /// 备注
         /// </summary>
         public string Remark { set; get; }
+
+        public MediaType getType()
+        {
+            if(".mp4".equals(FileExtension) || ".MP4".equals(FileExtension))
+            {
+                return MediaType.VIDEO;
+            } else
+            {
+                return MediaType.IMAGE;
+
+            }
+        }
+    }
+
+    public enum MediaType
+    {
+        VIDEO,IMAGE
+    }
+
+    /// <summary>
+    /// 用于预览窗口
+    /// </summary>
+    public class PreviewInfo
+    {
+        /// <summary>
+        /// 1:视频;2:图片
+        /// </summary>
+        public MediaType Type { set; get; }
+
+        /// <summary>
+        /// 地址
+        /// </summary>
+        public string Path { set; get; }
     }
 }

+ 25 - 0
Platform/AI.Platform.Page/Pages/Media/Utils.cs

@@ -36,5 +36,30 @@ namespace AI.Platform.Page.Pages.Media
         {
             return $"{start}-{end}";
         }
+
+        public static string ToWebPath(string relativeFilePath)
+        {
+            if (string.IsNullOrEmpty(relativeFilePath))
+                return string.Empty;
+
+            // 1. 统一斜杠
+            var path = relativeFilePath.Replace('\\', '/');
+
+            // 2. 移除开头的 "wwwroot/" 或 "wwwroot\"
+            if (path.StartsWith("wwwroot/", StringComparison.OrdinalIgnoreCase))
+            {
+                path = path.Substring("wwwroot/".Length);
+            }
+            else if (path.StartsWith("wwwroot", StringComparison.OrdinalIgnoreCase))
+            {
+                path = path.Substring("wwwroot".Length).TrimStart('/');
+            }
+
+            // 3. 对每一段进行 URL 编码(避免 / 被编码)
+            var segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+            var encodedSegments = segments.Select(Uri.EscapeDataString);
+
+            return "/" + string.Join("/", encodedSegments);
+        }
     }
 }

+ 0 - 3
Platform/AI.Platform.Service/FileService.cs

@@ -107,9 +107,6 @@ public class FileService : BaseService
         {
             siteName = siteEntity.Name;
         }
-
-        // 获取当前日期
-        var currentDate = DateTime.Now;
         // 构建目录路径
         var directoryPath = Path.Combine("wwwroot", "madia", siteName);
         // 创建目录

+ 1 - 4
Platform/AI.Platform.Web/AI.Platform.Web.csproj

@@ -28,10 +28,7 @@
   </ItemGroup>
   
   <ItemGroup>
-    <Folder Include="wwwroot\madia\01\" />
-    <Folder Include="wwwroot\madia\01\20\" />
-    <Folder Include="wwwroot\madia\01\28\" />
-    <Folder Include="wwwroot\madia\01\29\" />
+    <Folder Include="wwwroot\madia\" />
   </ItemGroup>
 
 </Project>

BIN
Platform/AI.Platform.Web/wwwroot/images/backgroud/nozzle.png