فهرست منبع

feat:增加设备管理页

Zhenghanjv 2 ماه پیش
والد
کامیت
543052b9d3

+ 0 - 0
Platform/AI.Platform.Page/Pages/Media/Component.razor


+ 7 - 7
Platform/AI.Platform.Page/Pages/Media/Media.razor

@@ -1,5 +1,6 @@
 @page "/media/list"
 @using AI.Platform.Core.Entity.Media
+@using AI.Platform.Page.Pages.Media.Model;
 @attribute [ReuseTabsPage(Title = "广告列表")]
 
 <Spin Spinning="Loading">
@@ -51,11 +52,12 @@
 
     <UpdateMediaDialog onCallback="OnDialogCallback" onVisibleCallback="OnDialogVisibleCallback"  @bind-IsVisible="isOpen" @bind-model="model" />
 
-    <Table @ref="_Table" AutoHeight TItem="MediaEntity" DataSource="_DataSource" PageSize="filterData.pageSize" Total="Total"
+    <Table @ref="_Table" AutoHeight TItem="MediaInfoModel" DataSource="_DataSource" PageSize="filterData.pageSize" Total="Total"
     OnChange="OnChange">
         <ColumnDefinitions Context="row">
             <PropertyColumn Property="c => c.FileName" Title="文件名" />
-            <PropertyColumn Property="c => c.Uploader" Title="上传人" />
+            <PropertyColumn Property="c => c.MediaUploader" Title="上传人" />
+            <PropertyColumn Property="c => c.SiteName" Title="油站" />
             <PropertyColumn Property="c=>c.MediaState" Title="文件状态">
                 @{
                     var tag = row.MediaState == 1 ? "可用" : "禁用";
@@ -63,18 +65,16 @@
                 }
                 <Tag Color="@color">@tag</Tag>
             </PropertyColumn>
-            <PropertyColumn Property="c => Utils.MachineStateJsonToString(c.MachineState)" Title="油机状态" />
+            <PropertyColumn Property="c => Utils.MachineStateJsonToString(c.MachineStateList)" Title="油机状态" />
             <PropertyColumn Property="c => c.StartTime" Title="播放时段">
                 @{
                     var tag = $"{row.StartTime}-{row.EndTime}";
                 }
                 <Tag>@tag</Tag>
             </PropertyColumn>
-            @* <PropertyColumn Property="c => c.EndTime" Title="结束播放时间" /> *@
-            <PropertyColumn Property="c => Utils.JoinDateTime(c.EffectiveTime,c.FailureTime)" Title="有效时间段" />
-            @* <PropertyColumn Property="c => c.FailureTime" Title="失效日期" /> *@
-            <PropertyColumn Property="c => c.CreateTime" Title="创建日期" />
+            <PropertyColumn Property="c => Utils.JoinDateTime(c.EffecitiveTime,c.FailureTime)" Title="有效时间段" />
             <PropertyColumn Property="c => c.EditTime" Title="修改日期" />
+            <PropertyColumn Property="c => c.Remark" Title="备注" />
 
             <ActionColumn Width="180" Title="操作" Fixed="ColumnFixPlacement.Right">
                 <Button Type="ButtonType.Primary" Color="Color.Blue6" OnClick="@(() => ShowDialog(2, row))">编辑</Button>

+ 61 - 12
Platform/AI.Platform.Page/Pages/Media/Media.razor.cs

@@ -1,6 +1,8 @@
 using AI.Platform.Core;
 using AI.Platform.Core.Entity.Media;
+using AI.Platform.Core.Entity.Site;
 using AI.Platform.Page.Pages.Media.Model;
+using AI.Platform.Page.Pages.Site.Model;
 using AntDesign;
 using AntDesign.TableModels;
 using Dm.util;
@@ -23,6 +25,8 @@ public partial class Media
     /// 数据库仓储
     /// </summary>
     [Inject] SqlSugarRepository<MediaEntity> _Repository { get; set; }
+
+    [Inject] SqlSugarRepository<SiteEntity> _SiteRepository { get; set; }
     /// <summary>
     /// 
     /// </summary>
@@ -38,7 +42,7 @@ public partial class Media
     /// <summary>
     /// 广告列表信息
     /// </summary>
-    private List<MediaEntity> _DataSource;
+    private List<MediaInfoModel> _DataSource;
     /// <summary>
     ///
     /// </summary>
@@ -74,32 +78,38 @@ public partial class Media
 
     private MediaDialogModel model = new MediaDialogModel();
 
+    // <summary>
+    /// 站点
+    /// </summary>
+    private List<SiteInfo> Sites;
+
     /// <summary>
     /// 打开编辑弹窗
     /// </summary>
     /// <param name="type">类型:1:新增;2:编辑;3:删除</param>
     /// <param name="media">广告信息</param>
     /// <returns></returns>
-    private async Task ShowDialog(int type,MediaEntity? media)
+    private async Task ShowDialog(int type, MediaInfoModel? media)
     {
         model = new MediaDialogModel();
         model.Type = type;
-        if(type == 2 || type == 3)
+        model.siteInfos = Sites;
+        if (type == 2 || type == 3)
         {
             model.Id = media?.Id;
-            model.GroupID = media?.GroupID ?? "";
-            model.BusinessUnitID = media?.BusinessUnitID ?? "";
+            model.GroupID = media?.GroupID ?? -1;
+            model.BusinessUnitID = media?.BusinessUnitID ?? -1;
             model.FileName = media?.FileName ?? "";
             model.GuidFileName = media?.GuidFileName ?? "";
             model.FileExtension = media?.FileExtension ?? "";
-            model.SavePath = media?.LocalPath ?? "";
-            model.MediaUploader = media?.Uploader ?? "";
+            model.SavePath = media?.SavePath ?? "";
+            model.MediaUploader = media?.MediaUploader ?? "";
             model.StartTime = media?.StartTime;
             model.EndTime = media?.EndTime;
-            model.EffecitiveTime = media?.EffectiveTime;
+            model.EffecitiveTime = media?.EffecitiveTime;
             model.FailureTime = media?.FailureTime;
             model.MediaState = media?.MediaState ?? 0;
-            model.MachineStateList = JsonSerializer.Deserialize<List<string>>(media?.MachineState ?? "[]");
+            model.MachineStateList = JsonSerializer.Deserialize<List<string>>(media?.MachineStateList ?? "[]");
             model.Remark = media?.Remark ?? "";
         }
 
@@ -121,7 +131,7 @@ public partial class Media
             case 2:
                 MediaEntity mediaEntity = model.ToCompany();
                 await _Repository.Context.Updateable(mediaEntity).
-                    UpdateColumns(it => new { it.MediaState,it.MachineState, it.StartTime, it.EndTime ,it.EffectiveTime,it.FailureTime,it.Remark })
+                    UpdateColumns(it => new { it.GroupId,it.BusinessUnitId,  it.MediaState,it.MachineState, it.StartTime, it.EndTime ,it.EffectiveTime,it.FailureTime,it.Remark })
                     .ExecuteCommandAsync();
                 break;
             case 3:
@@ -144,12 +154,29 @@ public partial class Media
         this.isOpen = isOpen;
     }
 
+    private async Task searchSitesAsync()
+    {
+        if (Global.CurrentUser.Account == "admin")
+        {
+            Sites = await _SiteRepository.AsQueryable()
+                .Select<SiteInfo>()
+                .ToListAsync();
+        }
+        else
+        {
+            Sites = await _SiteRepository.AsQueryable()
+                .Where(it => it.Id == Global.CurrentUser.SiteId || it.ParentId == Global.CurrentUser.SiteId)
+                .Select<SiteInfo>()
+                .ToListAsync();
+        }
+    }
+
     /// <summary>
     /// 表格查询
     /// </summary>
     /// <param name="query"></param>
     /// <returns></returns>
-    private async Task OnChange(QueryModel<MediaEntity> query)
+    private async Task OnChange(QueryModel<MediaInfoModel> query)
         => await Query();
 
     /// <summary>
@@ -161,6 +188,7 @@ public partial class Media
         Loading = true;
 
         var query =  _Repository.AsQueryable()
+            .LeftJoin<SiteEntity>((media,site) => media.BusinessUnitId == site.Id)
             .WhereIF(filterData.searchFileName != null, it => it.FileName.Contains(filterData.searchFileName))
             .WhereIF(filterData.searchMediaUploader != null, it => it.Uploader.Contains(filterData.searchMediaUploader))
             .WhereIF(filterData.searchMediaState != null && filterData.searchMediaState != -1, it => it.MediaState == filterData.searchMediaState)
@@ -181,7 +209,27 @@ public partial class Media
 
         Total = await query.CountAsync();
         _DataSource = await query
-            .OrderByDescending(it => it.EditTime)
+            .Select((media, site) => new MediaInfoModel()
+            {
+                Id = media.Id,
+                GroupID = media.GroupId,
+                BusinessUnitID = media.BusinessUnitId,
+                SavePath = media.LocalPath,
+                FileName = media.FileName,
+                GuidFileName = media.GuidFileName,
+                FileExtension = media.FileExtension,
+                MediaUploader = media.Uploader,
+                MachineStateList = media.MachineState,
+                MediaState = media.MediaState,
+                SiteName = site.Name,
+                StartTime = media.StartTime,
+                EndTime = media.EndTime,
+                EffecitiveTime = media.EffectiveTime,
+                FailureTime = media.FailureTime,
+                EditTime = media.EditTime,
+                Remark = media.Remark,
+            })
+            .OrderByDescending(media => media.EditTime)
             .Skip((filterData.currentPage - 1) * filterData.pageSize)
             .Take(filterData.pageSize)
             .ToListAsync();
@@ -266,6 +314,7 @@ public partial class Media
         {
             await NavigationManager.RedirectLogin(IJSRuntime);
             await Query();
+            await searchSitesAsync();
         }
     }
 

+ 100 - 4
Platform/AI.Platform.Page/Pages/Media/Model/MediaModel.cs

@@ -1,5 +1,6 @@
 using AI.Platform.Core;
 using AI.Platform.Core.Entity.Media;
+using AI.Platform.Page.Pages.Site.Model;
 using Microsoft.AspNetCore.Components;
 using SqlSugar;
 using System;
@@ -31,12 +32,12 @@ namespace AI.Platform.Page.Pages.Media.Model
         /// <summary>
         /// 集团ID
         /// </summary>
-        public string GroupID { get; set; }
+        public long GroupID { get; set; }
 
         /// <summary>
         /// 站点ID
         /// </summary>
-        public string BusinessUnitID { get; set; }
+        public long BusinessUnitID { get; set; }
 
         /// <summary>
         /// 文件名
@@ -98,14 +99,18 @@ namespace AI.Platform.Page.Pages.Media.Model
         /// </summary>
         public string Remark { set; get; }
 
+        /// <summary>
+        /// 可选择站点
+        /// </summary>
+        public List<SiteInfo> siteInfos { set; get; }
 
         public MediaEntity ToCompany()
         {
             var media = new MediaEntity()
             {
                 LocalPath = SavePath,
-                GroupID = this.GroupID ?? "",
-                BusinessUnitID = this.BusinessUnitID ?? "",
+                GroupId = this.GroupID,
+                BusinessUnitId = this.BusinessUnitID,
                 FileName = FileName,
                 FileExtension = this.FileExtension,
                 GuidFileName = this.GuidFileName,
@@ -141,4 +146,95 @@ namespace AI.Platform.Page.Pages.Media.Model
             return MachineStateList;
         }
     }
+
+
+    /// <summary>
+    /// 用于显示广告列表数据
+    /// </summary>
+    public class MediaInfoModel
+    {
+        /// <summary>
+        /// 表id
+        /// </summary>
+        public long? Id { get; set; }
+
+        /// <summary>
+        /// 集团ID
+        /// </summary>
+        public long GroupID { get; set; }
+
+        /// <summary>
+        /// 站点ID
+        /// </summary>
+        public long BusinessUnitID { get; set; }
+
+        /// <summary>
+        /// 站名
+        /// </summary>
+        public string SiteName { set; get; }
+
+        /// <summary>
+        /// 文件名
+        /// </summary>
+        public string FileName { set; get; }
+
+        /// <summary>
+        /// 文件后缀
+        /// </summary>
+        public string FileExtension { set; get; }
+
+        /// <summary>
+        /// guid文件名
+        /// </summary>
+        public string GuidFileName { set; get; }
+
+        /// <summary>
+        /// 保存到服务器的地址
+        /// </summary>
+        public string SavePath { set; get; }
+
+        /// <summary>
+        /// 文件开始播放时间
+        /// </summary>
+        public int? StartTime { set; get; }
+
+        /// <summary>
+        /// 文件结束播放时间
+        /// </summary>
+        public int? EndTime { set; get; }
+
+        /// <summary>
+        /// 文件生效时间
+        /// </summary>
+        public DateTime EffecitiveTime { set; get; }
+
+        /// <summary>
+        /// 文件失效时间
+        /// </summary>
+        public DateTime FailureTime { set; get; }
+
+        /// <summary>
+        /// 修改时间
+        /// </summary>
+        public DateTime? EditTime { set; get; }
+        /// <summary>
+        /// 文件油机状态
+        /// </summary>
+        public string MachineStateList { set; get; }
+
+        /// <summary>
+        /// 文件广告状态 0:禁用;1:可用
+        /// </summary>
+        public int MediaState { set; get; }
+
+        /// <summary>
+        /// 文件上传人
+        /// </summary>
+        public string MediaUploader { set; get; } = Global.CurrentUser.NickName;
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        public string Remark { set; get; }
+    }
 }

+ 33 - 7
Platform/AI.Platform.Page/Pages/Media/UpdateMediaDialog.razor

@@ -15,7 +15,7 @@
 
                 <div class="filter_row">
                     <span>广告状态</span>
-                    <SimpleSelect DefaultValue="@Model.MediaState.ToString()" OnSelectedItemChanged="OnSelectItemChange" Style="width:30%">
+                    <SimpleSelect DefaultValue="@Model.MediaState.ToString()" OnSelectedItemChanged="@(data => OnSelectItemChange(1, data))" Style="width:30%">
                         <SelectOptions>
                             <SimpleSelectOption Value="0" Label="禁用" style="width:30%" />
                             <SimpleSelectOption Value="1" Label="可用" style="width:30%" />
@@ -41,8 +41,17 @@
                     <span style="margin-right:5%">播放时段</span><RangePicker TValue="DateTime?[]" Value="playRange" Picker="DatePickerType.Time" Format="@("HH")" OnChange="@(date => onDateChage(date, 2))" />
                 </div>
 
-                <div class="filter_row" style="justify-content:start">
-                    <span>备注</span><Input Placeholder="备注" @bind-Value="Model.Remark" />
+                <div class="filter_row">
+                    <span>下发油站</span>
+                    <SimpleSelect DefaultValue="@Model.BusinessUnitID.ToString()" OnSelectedItemChanged="@(data => OnSelectItemChange(2, data))" style="width:30%">
+                        <SelectOptions>
+                            @foreach (var department in Model.siteInfos)
+                            {
+                                <SimpleSelectOption Value="@department.Id.ToString()" Label="@department.Name" style="width:30%" />
+                            }
+                        </SelectOptions>
+                    </SimpleSelect>
+                    <span>备注</span><Input Placeholder="备注" @bind-Value="Model.Remark" style="width:30%" />
                 </div>
             }
 
@@ -193,13 +202,29 @@
     /// <summary>
     /// 单选选择器选择事件
     /// </summary>
+    /// <param name="type">1:油机状态;2:站点</param>
     /// <param name="value">选择的值</param>
-    private void OnSelectItemChange(string value)
+    private void OnSelectItemChange(int type, string value)
     {
         Console.WriteLine(value);
-        int state = -1;
-        int.TryParse(value, out state);
-        Model.MediaState = state;
+        switch (type)
+        {
+            case 1:
+                int state = -1;
+                int.TryParse(value, out state);
+                Model.MediaState = state;
+                break;
+            case 2:
+                var siteinfo = Model.siteInfos.Find(it => it.Id.ToString().Equals(value));
+                if (siteinfo != null)
+                {
+                    Model.GroupID = siteinfo.ParentId;
+                    Model.BusinessUnitID = siteinfo.Id;
+                }
+
+                break;
+        }
+        
     }
 
     /// <summary>
@@ -210,6 +235,7 @@
     {
         Console.WriteLine(values);
         Model.MachineStateList = values.ToList();
+        
     }
 
     /// <summary>

+ 109 - 0
Platform/AI.Platform.Page/Pages/Site/Model/SiteModel.cs

@@ -1,4 +1,5 @@
 using AI.Platform.Core;
+using AI.Platform.Core.Entity.Device;
 using AI.Platform.Core.Entity.Site;
 using SqlSugar;
 using System;
@@ -118,9 +119,117 @@ namespace AI.Platform.Page.Pages.Site.Model
         /// </summary>
         public long Id { get; set; }
 
+        /// <summary>
+        /// 父站点id
+        /// </summary>
+        public long ParentId { get; set; }
+
         /// <summary>
         /// 站名
         /// </summary>
         public string Name { get; set; }
     }
+
+    /// <summary>
+    /// 用于显示设备列表
+    /// </summary>
+    public class SnInfo
+    {
+        /// <summary>
+        /// Id
+        /// </summary>
+        public long Id { get; set; }
+
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public DateTime? CreateTime { get; set; }
+
+        /// <summary>
+        /// 站点id
+        /// </summary>
+        public long SiteId { get; set; }
+
+        /// <summary>
+        /// 站名
+        /// </summary>
+        public string siteName { get; set; }
+
+        /// <summary>
+        /// 设备SN
+        /// </summary>
+        public string sn { get; set; }
+
+        /// <summary>
+        /// 修改时间
+        /// </summary>
+        public DateTime EditTime { get; set; }
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        public string Remark { get; set; }
+    }
+
+    /// <summary>
+    /// 设备编辑弹框传递数据
+    /// </summary>
+    public class ScrrenDialogModel
+    {
+        /// <summary>
+        /// 弹窗类型:1:新增;2:编辑;3:删除
+        /// </summary>
+        public int Type { get; set; }
+
+        /// <summary>
+        /// Id
+        /// </summary>
+        public long? Id { get; set; }
+
+        /// <summary>
+        /// 站点id
+        /// </summary>
+        public long SiteId { get; set; }
+
+        /// <summary>
+        /// 站名
+        /// </summary>
+        public string siteName { get; set; }
+
+        /// <summary>
+        /// 设备SN
+        /// </summary>
+        public string sn { get; set; }
+
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public DateTime createTime { get; set; }
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        public string Remark { get; set; }
+
+        /// <summary>
+        /// 可供选择的站点
+        /// </summary>
+        public List<SiteInfo> Sites { get; set; }
+
+        public ScreentEntity ToCompany()
+        {
+            ScreentEntity screentEntity = new ScreentEntity()
+            {
+                sn = sn,
+                SiteId = SiteId,
+                CreateTime = createTime,
+                EditTime = DateTime.Now,
+                Remark = Remark
+            };
+
+            if(Id != null) screentEntity.Id = (long)Id;
+
+            return screentEntity;
+        }
+    }
 }

+ 68 - 0
Platform/AI.Platform.Page/Pages/Site/Screen.razor

@@ -0,0 +1,68 @@
+@page "/site/screen"
+@using AI.Platform.Core.Entity.Site
+@using AI.Platform.Page.Pages.Site.Model
+@attribute [ReuseTabsPage(Title = "设备管理")]
+
+<Spin Spinning="Loading">
+    <div  class="filter_box">
+        <div class="filter_row" style="justify-content:start">
+            <span>站名</span><Input Placeholder="请输入要查找的站名" @bind-Value="filterData.siteName" Style="width:30%" />
+            <span>设备码</span><Input Placeholder="请输入要查找的设备码" @bind-Value="filterData.sn" Style="width:30%" />
+        </div>
+
+        <div class="filter_row" style="justify-content:start">
+            <Button Icon="search" OnClick="Query" Style="margin-right:2%">查询</Button>
+            <Button Icon="reload" OnClick="HandleReset" Style="margin-right:2%">重置</Button>
+            <Button Icon="upload" OnClick="@(() => ShowDialog(1, null))">新增</Button>
+        </div>
+    </div>
+
+    <UpdateScreenDialog onCallback="OnDialogCallback" onVisibleCallback="OnDialogVisibleCallback" @bind-IsVisible="isOpen" @bind-model="model" />
+
+    <Table @ref="_Table" AutoHeight TItem="SnInfo" DataSource="_DataSource" PageSize="filterData.pageSize" Total="Total"
+    OnChange="OnChange">
+        <ColumnDefinitions Context="row">
+            <PropertyColumn Property="c => c.siteName" Title="站名" />
+            <PropertyColumn Property="c => c.sn" Title="设备码" />
+            <PropertyColumn Property="c => c.CreateTime" Title="创建时间" />
+            <PropertyColumn Property="c => c.EditTime" Title="修改时间" />
+            <PropertyColumn Property="c => c.Remark" Title="备注" />
+
+            <ActionColumn Width="180" Title="操作" Fixed="ColumnFixPlacement.Right">
+                <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>
+        </ColumnDefinitions>
+
+        <PaginationTemplate>
+            <Pagination Class="@(context.PaginationClass + " my-custom-pagination")"
+                        Total="Total"
+                        PageSize="filterData.pageSize"
+                        Current="filterData.currentPage"
+                        ShowSizeChanger="true"
+                        ShowQuickJumper="true"
+                        OnChange="OnPageChange"
+                        ShowTotal="showTotal" />
+        </PaginationTemplate>
+    </Table>
+</Spin>
+
+<style>
+    .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%;
+    }
+
+</style>

+ 254 - 0
Platform/AI.Platform.Page/Pages/Site/Screen.razor.cs

@@ -0,0 +1,254 @@
+using AI.Platform.Core;
+using AI.Platform.Core.Entity.Device;
+using AI.Platform.Core.Entity.Site;
+using AI.Platform.Page.Pages.Site.Model;
+using AntDesign;
+using AntDesign.TableModels;
+using Dm.util;
+using Microsoft.AspNetCore.Components;
+using Microsoft.JSInterop;
+using SqlSugar;
+using System.Data.Common;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace AI.Platform.Page.Pages.Site;
+
+public partial class Screen
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    [Inject] NavigationManager NavigationManager { get; set; }
+    /// <summary>
+    /// 数据库仓储
+    /// </summary>
+    [Inject] SqlSugarRepository<ScreentEntity> _Repository { get; set; }
+
+    /// <summary>
+    /// 站点
+    /// </summary>
+    [Inject] SqlSugarRepository<SiteEntity> _SiteRepository { get; set; }
+    /// <summary>
+    /// 
+    /// </summary>
+    [Inject] IJSRuntime IJSRuntime { get; set; }
+    /// <summary>
+    ///
+    /// </summary>
+    private ITable _Table;
+    
+    /// <summary>
+    /// 站点列表信息
+    /// </summary>
+    private List<SnInfo> _DataSource;
+    
+    /// <summary>
+    /// 总条数
+    /// </summary>
+    private int Total = 0;
+    /// <summary>
+    /// 加载
+    /// </summary>
+    private bool Loading = false;
+
+    /// <summary>
+    /// 查询过滤条件
+    /// </summary>
+    private FilterData filterData { set; get; } = new();
+
+    /// <summary>
+    /// 编辑弹窗
+    /// </summary>
+    private UpdateScreenDialog updateMediaDialog { set; get; } = new();
+
+    /// <summary>
+    /// 标识弹窗是否显示
+    /// </summary>
+    private bool isOpen { set; get; } = false;
+
+    private ScrrenDialogModel model = new ScrrenDialogModel();
+
+    // <summary>
+    /// 站点
+    /// </summary>
+    private List<SiteInfo> Sites;
+
+    /// <summary>
+    /// 打开编辑弹窗
+    /// </summary>
+    /// <param name="type">类型:1:新增;2:编辑;3:删除</param>
+    /// <param name="snInfo">大屏信息</param>
+    /// <returns></returns>
+    private async Task ShowDialog(int type, SnInfo? snInfo)
+    {
+        model = new ScrrenDialogModel();
+        model.Type = type;
+        model.Sites = Sites;
+        if(type == 2 || type == 3)
+        {
+            model.sn = snInfo?.sn?? "";
+            model.SiteId = snInfo?.SiteId ?? -1;
+            model.siteName = snInfo?.siteName ?? "";
+            model.Id = snInfo?.Id;
+            model.Remark = snInfo?.Remark ?? "";
+        }
+
+        isOpen = true;
+    }
+    
+    /// <summary>
+    /// 编辑弹窗信息回调
+    /// </summary>
+    /// <param name="model"></param>
+    private async Task OnDialogCallback(ScrrenDialogModel model)
+    {
+        switch (model.Type)
+        {
+            case 1:
+                await _Repository.InsertAsync(model.ToCompany());
+                break;
+            case 2:
+                ScreentEntity siteEntity = model.ToCompany();
+                await _Repository.Context.Updateable(siteEntity).
+                    UpdateColumns(it => new { it.sn,it.SiteId, it.Remark})
+                    .ExecuteCommandAsync();
+                break;
+            case 3:
+                await _Repository.DeleteByIdAsync(model.Id);
+                break;
+        }
+        await Query();
+    }
+
+    /// <summary>
+    /// 编辑弹窗是否显示回调
+    /// </summary>
+    /// <param name="isOpen"></param>
+    private void OnDialogVisibleCallback(bool isOpen)
+    {
+        this.isOpen = isOpen;
+    }
+
+    /// <summary>
+    /// 表格查询
+    /// </summary>
+    /// <param name="query"></param>
+    /// <returns></returns>
+    private async Task OnChange(QueryModel<SnInfo> query)
+        => await Query();
+
+    /// <summary>
+    /// 查
+    /// </summary>
+    /// <returns></returns>
+    private async Task Query()
+    {
+        Loading = true;
+
+        var query = _Repository.AsQueryable()
+            .LeftJoin<SiteEntity>((screen, site) => screen.SiteId == site.Id);
+
+        query = query
+            .WhereIF(filterData.siteName.IsNotNullOrEmpty(),(screent,site) => site.Name.Contains(filterData.siteName))
+            .WhereIF(filterData.sn.IsNotNullOrEmpty(),it => it.sn.Contains(filterData.sn));
+
+        Total = await query.CountAsync();
+
+        _DataSource = await query
+            .Select((screen,site) => new SnInfo() 
+            {
+                Id = screen.Id,
+                sn = screen.sn,
+                SiteId = screen.SiteId,
+                siteName = site.Name,
+                CreateTime = screen.CreateTime,
+                EditTime = screen.EditTime,
+                Remark = screen.Remark,
+            })
+            .Skip((filterData.currentPage - 1) * filterData.pageSize)
+            .Take(filterData.pageSize)
+            .ToListAsync();
+
+            Loading = false;
+    }
+
+    Func<PaginationTotalContext, string> showTotal = ctx => $"总数 {ctx.Total} ";
+
+    private async Task OnPageChange(PaginationEventArgs args)
+    {
+        filterData.pageSize = args.PageSize;
+        filterData.currentPage = args.Page;
+        await Query();
+    }
+
+    /// <summary>
+    /// 清空查询条件
+    /// </summary>
+    private void HandleReset()
+    {
+
+    }
+
+    private async Task searchSitesAsync()
+    {
+        if (Global.CurrentUser.Account == "admin")
+        {
+            Sites = await _SiteRepository.AsQueryable()
+                .Select<SiteInfo>()
+                .ToListAsync();
+        }
+        else
+        {
+            Sites = await _SiteRepository.AsQueryable()
+                .Where(it => it.Id == Global.CurrentUser.SiteId || it.ParentId == Global.CurrentUser.SiteId)
+                .Select<SiteInfo>()
+                .ToListAsync();
+        }
+    }
+
+    protected override async void OnInitialized()
+    {
+
+    }
+
+    protected override async Task OnAfterRenderAsync(bool firstRender)
+    {
+        if (firstRender)
+        {
+            await NavigationManager.RedirectLogin(IJSRuntime);
+            await Query();
+            await searchSitesAsync();
+        }
+    }
+
+    private async Task OnChange(QueryModel<SystemMenu> query)
+        => await Query();
+
+
+    /// <summary>
+    /// 查找条件
+    /// </summary>
+    public class FilterData
+    {
+        /// <summary>
+        /// 页码
+        /// </summary>
+        public int currentPage { set; get; } = 1;
+
+        /// <summary>
+        /// 页数
+        /// </summary>
+        public int pageSize { set; get; } = 10;
+
+        /// <summary>
+        /// 要查找的站名
+        /// </summary>
+        public string? siteName { set; get; }
+
+        /// <summary>
+        /// 要查找的SN
+        /// </summary>
+        public string? sn{ set; get; }
+    }
+}

+ 92 - 0
Platform/AI.Platform.Page/Pages/Site/UpdateScreenDialog.razor

@@ -0,0 +1,92 @@
+@using AI.Platform.Page.Pages.Site.Model
+@using System.Threading.Tasks
+@using System.Text.Json
+
+@if (IsVisible)
+{
+    <div class="modal-overlay">
+        <div class="modal-content filter_box">
+            @if (Model?.Type == 1 || Model?.Type == 2)
+            {
+                <div class="filter_row">
+                    <span>设备码</span><Input Placeholder="设备码" @bind-Value="Model.sn" Style="width:30%" />
+
+                    <span>站点</span>
+                    <Select @bind-Value="Model.SiteId"
+                            Style="width:30%"
+                            TItemValue="long"
+                            TItem="string"
+                            DefaultActiveFirstOption="true" EnableSearch AllowClear>
+                        <SelectOptions>
+                            @foreach (var department in Model.Sites)
+                            {
+                                <SelectOption TItemValue="long" TItem="string" Value="@department.Id" Label="@department.Name" />
+                            }
+                        </SelectOptions>
+                    </Select>
+                    
+                </div>
+
+                <div class="filter_row" style="justify-content:start">
+                    <span>备注</span><Input Placeholder="备注" @bind-Value="Model.Remark" Style="width:30%" />
+
+                </div>
+            }
+
+            
+
+            @if (Model?.Type == 3)
+            {
+                <h3>是否删除设备?@(Model.sn)</h3>
+            }
+
+            <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%;
+    }
+</style>

+ 91 - 0
Platform/AI.Platform.Page/Pages/Site/UpdateScreenDialog.razor.cs

@@ -0,0 +1,91 @@
+using AI.Platform.Core;
+using AI.Platform.Core.Entity.Site;
+using AI.Platform.Page.Pages.Site.Model;
+using Microsoft.AspNetCore.Components;
+
+namespace AI.Platform.Page.Pages.Site;
+
+public partial class UpdateScreenDialog
+{
+
+    /// <summary>
+    /// 信息回调
+    /// </summary>
+    [Parameter] public EventCallback<ScrrenDialogModel> ModelChanged { get; set; }
+
+    /// <summary>
+    /// 打开/关闭窗口回调
+    /// </summary>
+    [Parameter] public EventCallback<bool> IsVisibleChanged { get; set; }
+
+    /// <summary>
+    /// 信息回调
+    /// </summary>
+    [Parameter] public EventCallback<ScrrenDialogModel> onCallback { get; set; }
+
+    /// <summary>
+    /// 打开/关闭窗口回调
+    /// </summary>
+    [Parameter] public EventCallback<bool> onVisibleCallback { get; set; }
+
+    /// <summary>
+    /// 数据
+    /// </summary>
+    [Parameter] public ScrrenDialogModel Model { 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()
+    {
+        if (ModelChanged.HasDelegate)
+        {
+            await ModelChanged.InvokeAsync(Model);
+        }
+
+        if (onCallback.HasDelegate)
+        {
+            await onCallback.InvokeAsync(Model);
+        }
+        await OnlyClose();
+    }
+
+    
+}

+ 2 - 1
Platform/AI.Platform.Service/FileService.cs

@@ -119,7 +119,8 @@ public class FileService : BaseService
             msg = "上传成功",
             fileName = file.FileName,
             guidName = fileName,
-            savePath = filePath
+            savePath = filePath,
+            extension = fileExtension
         };
     }
 }

+ 8 - 2
Platform/AI.Platform.Tool/Entity/Device/ScreentEntity.cs

@@ -9,9 +9,15 @@ namespace AI.Platform.Core.Entity.Device
     public class ScreentEntity: EntityBaseLite
     {
         [SugarColumn(ColumnDescription = "站点id")]
-        public long SiteID { get; set; }
+        public long SiteId { get; set; }
 
         [SugarColumn(ColumnDescription = "设备SN", IsNullable = false)]
-        public string SN { get; set; }
+        public string sn { get; set; }
+
+        [SugarColumn(ColumnDescription = "修改时间", IsNullable = false)]
+        public DateTime EditTime { get; set; }
+
+        [SugarColumn(ColumnDescription = "备注", IsNullable = false)]
+        public string Remark { get; set; }
     }
 }

+ 4 - 4
Platform/AI.Platform.Tool/Entity/Media/MediaEntity.cs

@@ -8,11 +8,11 @@ namespace AI.Platform.Core.Entity.Media
     [SugarTable(null,"广告列表")]
     public class MediaEntity: EntityBaseLite
     {
-        [SugarColumn(ColumnDescription = "集团ID", IsNullable = false,DefaultValue = "")]
-        public string GroupID {  get; set; }
+        [SugarColumn(ColumnDescription = "集团ID", IsNullable = false)]
+        public long GroupId {  get; set; }
 
-        [SugarColumn(ColumnDescription = "站点ID", IsNullable = false, DefaultValue = "")]
-        public string BusinessUnitID { get; set; }
+        [SugarColumn(ColumnDescription = "站点ID", IsNullable = false)]
+        public long BusinessUnitId { get; set; }
 
         [SugarColumn(ColumnDescription = "广告文件本地存储路径", IsNullable = false, DefaultValue = "")]
         public string LocalPath { get; set; }

+ 5 - 2
Platform/AI.Platform.Tool/Entity/System/SystemMenu.cs

@@ -99,10 +99,13 @@ public class SystemMenuSeedData : ISeedData<SystemMenu>
             new SystemMenu() { Id = 18, ParentId = 19, Path="/report/shiftSettlementDailyReport", Name="班结日报表", Key="report.shiftSettlementDailyReport", Icon="snippets", Sort=1, Enabled=true, CreateTime = DateTime.Now },
             new SystemMenu() { Id = 20, ParentId = 19, Path="/report/shiftSalesReport", Name="班次销售报表", Key="report.shiftSalesReport", Icon="snippets", Sort=1, Enabled=true, CreateTime = DateTime.Now },
 
-             new SystemMenu() { Id = 21, ParentId = 0, Path="/media", Name="媒体管理", Key="media", Icon="appstore", Sort=1, Enabled=true, CreateTime = DateTime.Now },
+            new SystemMenu() { Id = 21, ParentId = 0, Path="/media", Name="媒体管理", Key="media", Icon="appstore", Sort=1, Enabled=true, CreateTime = DateTime.Now },
             new SystemMenu() { Id = 22, ParentId = 21, Path="/media/list", Name="广告列表", Key="media.list", Icon="snippets", Sort=1, Enabled=true, CreateTime = DateTime.Now },
 
-             new SystemMenu() { Id = 23, ParentId = 0, Path="/site", Name="站点管理", Key="site", Icon="appstore", Sort=1, Enabled=true, CreateTime = DateTime.Now },
+            new SystemMenu() { Id = 23, ParentId = 0, Path="/site", Name="站点管理", Key="site", Icon="appstore", Sort=1, Enabled=true, CreateTime = DateTime.Now },
             new SystemMenu() { Id = 24, ParentId = 23, Path="/site/list", Name="站点列表", Key="site.list", Icon="snippets", Sort=1, Enabled=true, CreateTime = DateTime.Now },
+            new SystemMenu() { Id = 25, ParentId = 23, Path="/site/screen", Name="设备管理", Key="site.screen", Icon="snippets", Sort=1, Enabled=true, CreateTime = DateTime.Now }
+
+            
         ];
 }