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
rBVSXo2>&@SI2afT1Q;0F|9HMrSP>wWG$Dw
+    /// 用户在线时长查询对象
+    /// 
+    public class UserOnlineLogQueryDto : PagerInfo 
+    {
+        public int? UserId { get; set; }
+        public string UserIP { get; set; }
+        public DateTime? BeginAddTime { get; set; }
+        public DateTime? EndAddTime { get; set; }
+    }
+
+    /// 
+    /// 用户在线时长输入输出对象
+    /// 
+    public class UserOnlineLogDto
+    {
+        [Required(ErrorMessage = "Id不能为空")]
+        [ExcelColumn(Name = "Id")]
+        [ExcelColumnName("Id")]
+        [JsonConverter(typeof(ValueToStringConverter))]
+        public long Id { get; set; }
+
+        [Required(ErrorMessage = "用户id不能为空")]
+        [ExcelColumn(Name = "用户id")]
+        [ExcelColumnName("用户id")]
+        public long UserId { get; set; }
+
+        [Required(ErrorMessage = "在线时长(分)不能为空")]
+        [ExcelColumn(Name = "在线时长(分)")]
+        [ExcelColumnName("在线时长(分)")]
+        public double OnlineTime { get; set; }
+
+        [ExcelColumn(Name = "结束时间", Format = "yyyy-MM-dd HH:mm:ss", Width = 20)]
+        [ExcelColumnName("结束时间")]
+        public DateTime? AddTime { get; set; }
+
+        [ExcelColumn(Name = "地址位置")]
+        [ExcelColumnName("地址位置")]
+        public string Location { get; set; }
+
+        [ExcelColumn(Name = "用户IP")]
+        [ExcelColumnName("用户IP")]
+        public string UserIP { get; set; }
+
+        [ExcelColumn(Name = "备注")]
+        [ExcelColumnName("备注")]
+        public string Remark { get; set; }
+
+        [ExcelColumn(Name = "登录时间", Format = "yyyy-MM-dd HH:mm:ss", Width = 20)]
+        [ExcelColumnName("登录时间")]
+        public DateTime? LoginTime { get; set; }
+
+        [ExcelColumn(Name = "今日在线时长")]
+        [ExcelColumnName("今日在线时长")]
+        public string TodayOnlineTime { get; set; }
+
+        [ExcelColumn(Name = "登录平台")]
+        [ExcelColumnName("登录平台")]
+        public string Platform { get; set; }
+        [ExcelColumn(Name = "用户昵称")]
+        public string NickName { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/ZR.ServiceCore/Model/UserOnlineLog.cs b/ZR.ServiceCore/Model/UserOnlineLog.cs
new file mode 100644
index 00000000..6e341bf5
--- /dev/null
+++ b/ZR.ServiceCore/Model/UserOnlineLog.cs
@@ -0,0 +1,54 @@
+
+namespace ZR.ServiceCore.Model
+{
+    /// 
+    /// 用户在线时长
+    /// 
+    [SugarTable("UserOnlineLog")]
+    public class UserOnlineLog
+    {
+        /// 
+        /// Id 
+        /// 
+        [SugarColumn(IsPrimaryKey = true, IsIdentity = false)]
+        public long Id { get; set; }
+
+        /// 
+        /// 用户id 
+        /// 
+        public long UserId { get; set; }
+
+        /// 
+        /// 在线时长(分) 
+        /// 
+        public double OnlineTime { get; set; }
+        /// 
+        /// 今日在线时长
+        /// 
+        public double TodayOnlineTime { get; set; }
+
+        /// 
+        /// 结束时间 
+        /// 
+        public DateTime? AddTime { get; set; }
+
+        /// 
+        /// 地址位置 
+        /// 
+        public string Location { get; set; }
+
+        /// 
+        /// 用户IP 
+        /// 
+        public string UserIP { get; set; }
+        public DateTime LoginTime { get; set; }
+        /// 
+        /// 备注 
+        /// 
+        public string Remark { get; set; }
+        /// 
+        /// 登录平台
+        /// 
+        public string Platform { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/ZR.ServiceCore/Services/IService/IUserOnlineLogService.cs b/ZR.ServiceCore/Services/IService/IUserOnlineLogService.cs
new file mode 100644
index 00000000..0a5e7318
--- /dev/null
+++ b/ZR.ServiceCore/Services/IService/IUserOnlineLogService.cs
@@ -0,0 +1,18 @@
+using ZR.Model;
+using ZR.ServiceCore.Model;
+using ZR.ServiceCore.Model.Dto;
+
+namespace ZR.ServiceCore.Monitor.IMonitorService
+{
+    /// 
+    /// 用户在线时长service接口
+    /// 
+    public interface IUserOnlineLogService : IBaseService
+    {
+        PagedInfo GetList(UserOnlineLogQueryDto parm);
+
+        UserOnlineLog AddUserOnlineLog(UserOnlineLog parm);
+
+        PagedInfo ExportList(UserOnlineLogQueryDto parm);
+    }
+}
diff --git a/ZR.ServiceCore/Services/UserOnlineLogService.cs b/ZR.ServiceCore/Services/UserOnlineLogService.cs
new file mode 100644
index 00000000..1566b30c
--- /dev/null
+++ b/ZR.ServiceCore/Services/UserOnlineLogService.cs
@@ -0,0 +1,88 @@
+using Infrastructure.Attribute;
+using ZR.Model;
+using ZR.Model.System;
+using ZR.Repository;
+using ZR.ServiceCore.Model;
+using ZR.ServiceCore.Model.Dto;
+using ZR.ServiceCore.Monitor.IMonitorService;
+
+namespace ZR.ServiceCore.Monitor
+{
+    /// 
+    /// 用户在线时长Service业务层处理
+    /// 
+    [AppService(ServiceType = typeof(IUserOnlineLogService), ServiceLifetime = LifeTime.Transient)]
+    public class UserOnlineLogService : BaseService, IUserOnlineLogService
+    {
+        /// 
+        /// 查询用户在线时长列表
+        /// 
+        /// 
+        /// 
+        public PagedInfo GetList(UserOnlineLogQueryDto parm)
+        {
+            var predicate = QueryExp(parm);
+
+            var response = Queryable()
+                //.OrderBy("Id desc")
+                .Where(predicate.ToExpression())
+                .LeftJoin((it, u) => it.UserId == u.UserId)
+                .Select((it, u) => new UserOnlineLogDto()
+                {
+                    NickName = u.NickName
+                }, true)
+                .ToPage(parm);
+
+            return response;
+        }
+
+        /// 
+        /// 添加用户在线时长
+        /// 
+        /// 
+        /// 
+        public UserOnlineLog AddUserOnlineLog(UserOnlineLog model)
+        {
+            if (model.OnlineTime >= 0.5)
+            {
+                Insertable(model).ExecuteReturnSnowflakeId();
+            }
+            return model;
+        }
+
+        /// 
+        /// 导出用户在线时长
+        /// 
+        /// 
+        /// 
+        public PagedInfo ExportList(UserOnlineLogQueryDto parm)
+        {
+            var predicate = QueryExp(parm);
+
+            var response = Queryable()
+                .Where(predicate.ToExpression())
+                .Select((it) => new UserOnlineLogDto()
+                {
+                }, true)
+                .ToPage(parm);
+
+            return response;
+        }
+
+        /// 
+        /// 查询导出表达式
+        /// 
+        /// 
+        /// 
+        private static Expressionable QueryExp(UserOnlineLogQueryDto parm)
+        {
+            var predicate = Expressionable.Create();
+
+            predicate = predicate.AndIF(parm.UserId != null, it => it.UserId == parm.UserId);
+            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.UserIP), it => it.UserIP == parm.UserIP);
+            predicate = predicate.AndIF(parm.BeginAddTime == null, it => it.AddTime >= DateTime.Now.ToShortDateString().ParseToDateTime());
+            predicate = predicate.AndIF(parm.BeginAddTime != null, it => it.AddTime >= parm.BeginAddTime);
+            return predicate;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ZR.ServiceCore/Signalr/MessageHub.cs b/ZR.ServiceCore/Signalr/MessageHub.cs
index a21d728a..a3e73dd0 100644
--- a/ZR.ServiceCore/Signalr/MessageHub.cs
+++ b/ZR.ServiceCore/Signalr/MessageHub.cs
@@ -6,6 +6,7 @@
 using System.Web;
 using UAParser;
 using ZR.ServiceCore.Model.Dto;
+using ZR.ServiceCore.Monitor.IMonitorService;
 using ZR.ServiceCore.Services;
 
 namespace ZR.ServiceCore.Signalr
@@ -21,11 +22,13 @@ public class MessageHub : Hub
         //private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
         private readonly ISysNoticeService SysNoticeService;
         private readonly ISysUserService UserService;
+        private readonly IUserOnlineLogService UserOnlineLogService;
 
-        public MessageHub(ISysNoticeService noticeService, ISysUserService userService)
+        public MessageHub(ISysNoticeService noticeService, ISysUserService userService, IUserOnlineLogService userOnlineLogService)
         {
             SysNoticeService = noticeService;
             UserService = userService;
+            UserOnlineLogService = userOnlineLogService;
         }
 
         private ApiResult SendNotice()
@@ -130,8 +133,21 @@ public override Task OnDisconnectedAsync(Exception exception)
                 if (userInfo != null)
                 {
                     userInfo.TodayOnlineTime += user?.OnlineTime ?? 0;
+
+                    UserOnlineLogService.AddUserOnlineLog(new Model.UserOnlineLog()
+                    {
+                        UserId = user.Userid,
+                        AddTime = DateTime.Now,
+                        Location = user?.Location,
+                        OnlineTime = user.OnlineTime,
+                        UserIP = user.UserIP,
+                        TodayOnlineTime = userInfo.TodayOnlineTime,
+                        Platform = user.Platform,
+                        Remark = user.Browser,
+                        LoginTime = user.LoginTime,
+                    });
                 }
-                Log.WriteLine(ConsoleColor.Red, msg: $"用户{user?.Name}离开了,已在线{userInfo?.TodayOnlineTime}分,当前已连接{onlineClients.Count}个");
+                Log.WriteLine(ConsoleColor.Red, msg: $"用户{user?.Name}离开了,已在线{userInfo?.TodayOnlineTime}分种,当前已连接{onlineClients.Count}个");
             }
             return base.OnDisconnectedAsync(exception);
         }
diff --git a/ZR.ServiceCore/SqlSugar/DataPermi.cs b/ZR.ServiceCore/SqlSugar/DataPermi.cs
index 0de5d4b1..a07f0847 100644
--- a/ZR.ServiceCore/SqlSugar/DataPermi.cs
+++ b/ZR.ServiceCore/SqlSugar/DataPermi.cs
@@ -1,6 +1,7 @@
 using Infrastructure;
 using SqlSugar.IOC;
 using ZR.Model.System;
+using ZR.ServiceCore.Model;
 
 namespace ZR.ServiceCore.SqlSugar
 {
@@ -84,6 +85,7 @@ public static void FilterData(int configId)
             db.QueryFilter.AddTableFilter(expUser.ToExpression());
             db.QueryFilter.AddTableFilter(expRole.ToExpression());
             db.QueryFilter.AddTableFilter(expLoginlog.ToExpression());
+            db.QueryFilter.AddTableFilter(f => f.UserId == user.UserId, QueryFilterProvider.FilterJoinPosition.Where);
         }
     }
 }
diff --git a/ZR.ServiceCore/SqlSugar/InitTable.cs b/ZR.ServiceCore/SqlSugar/InitTable.cs
index 47c07bff..f565cd75 100644
--- a/ZR.ServiceCore/SqlSugar/InitTable.cs
+++ b/ZR.ServiceCore/SqlSugar/InitTable.cs
@@ -52,6 +52,7 @@ public static void InitDb()
             db.CodeFirst.InitTables(typeof(EmailTpl));
             db.CodeFirst.InitTables(typeof(SmsCodeLog));
             db.CodeFirst.InitTables(typeof(EmailLog));
+            db.CodeFirst.InitTables(typeof(UserOnlineLog));
         }
     }
 }
From e332e2599a7801b4e71cd864ab864ece6270f18f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=8D=E5=81=9A=E7=A0=81=E5=86=9C?= <599854767@qq.com>
Date: Thu, 28 Mar 2024 07:09:34 +0800
Subject: [PATCH 10/23] =?UTF-8?q?:zap:fix=E5=90=AF=E5=8A=A8=E8=AD=A6?=
 =?UTF-8?q?=E5=91=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
 ZR.Admin.WebApi/Controllers/CommonController.cs | 4 ++--
 ZR.ServiceCore/Model/Dto/UploadDto.cs           | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/ZR.Admin.WebApi/Controllers/CommonController.cs b/ZR.Admin.WebApi/Controllers/CommonController.cs
index 5afea0c9..9564017e 100644
--- a/ZR.Admin.WebApi/Controllers/CommonController.cs
+++ b/ZR.Admin.WebApi/Controllers/CommonController.cs
@@ -86,9 +86,9 @@ public IActionResult SendMsg(string msg, string toUser = "")
         [ActionPermissionFilter(Permission = "common")]
         public async Task UploadFile([FromForm] UploadDto uploadDto, StoreType storeType = StoreType.LOCAL)
         {
-            IFormFile formFile = uploadDto.File;
-            if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空");
+            if (uploadDto?.File == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空");
             SysFile file = new();
+            IFormFile formFile = uploadDto.File;
             string fileExt = Path.GetExtension(formFile.FileName);//文件后缀
             double fileSize = Math.Round(formFile.Length / 1024.0, 2);//文件大小KB
 
diff --git a/ZR.ServiceCore/Model/Dto/UploadDto.cs b/ZR.ServiceCore/Model/Dto/UploadDto.cs
index a629cbf5..4e1a3218 100644
--- a/ZR.ServiceCore/Model/Dto/UploadDto.cs
+++ b/ZR.ServiceCore/Model/Dto/UploadDto.cs
@@ -7,15 +7,15 @@ public class UploadDto
         /// 
         /// 自定文件名
         /// 
-        public string? FileName { get; set; }
+        public string FileName { get; set; }
         /// 
         /// 存储目录
         /// 
-        public string? FileDir { get; set; }
+        public string FileDir { get; set; }
         /// 
         /// 文件名生成类型 1 原文件名 2 自定义 3 自动生成
         /// 
         public int FileNameType { get; set; }
-        public IFormFile? File { get; set; }
+        public IFormFile File { get; set; }
     }
 }
From 9f3acff77476ee00814c63ff69b3feee09293b6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=8D=E5=81=9A=E7=A0=81=E5=86=9C?= <599854767@qq.com>
Date: Thu, 28 Mar 2024 18:36:16 +0800
Subject: [PATCH 11/23] =?UTF-8?q?:zap:vue2=E5=A2=9E=E5=8A=A0=E5=8D=A0?=
 =?UTF-8?q?=E4=BD=8D=E9=A1=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
 ZR.Vue/src/views/dataScreen/index.vue         |  4 ++++
 ZR.Vue/src/views/index.vue                    | 12 +++++++++++-
 ZR.Vue/src/views/monitor/UserOnlineLog.vue    |  3 +++
 ZR.Vue/src/views/monitor/onlineuser/index.vue |  2 +-
 4 files changed, 19 insertions(+), 2 deletions(-)
 create mode 100644 ZR.Vue/src/views/dataScreen/index.vue
 create mode 100644 ZR.Vue/src/views/monitor/UserOnlineLog.vue
diff --git a/ZR.Vue/src/views/dataScreen/index.vue b/ZR.Vue/src/views/dataScreen/index.vue
new file mode 100644
index 00000000..64db54d3
--- /dev/null
+++ b/ZR.Vue/src/views/dataScreen/index.vue
@@ -0,0 +1,4 @@
+
+  
+
+
diff --git a/ZR.Vue/src/views/index.vue b/ZR.Vue/src/views/index.vue
index 4dbe4650..0f1a30dd 100644
--- a/ZR.Vue/src/views/index.vue
+++ b/ZR.Vue/src/views/index.vue
@@ -1,6 +1,5 @@
 
   
-    
 
     
       
         
@@ -176,6 +175,17 @@ export default {
       version: defaultSettings.version,
     }
   },
+  mounted() {
+    this.$notify({
+      title: 'Vue2停止更新公告',
+      message:
+        'Vue2已不再更新新功能,请使用Vue3版本 https://gitee.com/izory/ZRAdmin-vue ',
+      position: 'bottom-right',
+      type: 'warning',
+      dangerouslyUseHTMLString: true,
+      duration: 0,
+    })
+  },
   methods: {
     goTarget(href) {
       window.open(href, '_blank')
diff --git a/ZR.Vue/src/views/monitor/UserOnlineLog.vue b/ZR.Vue/src/views/monitor/UserOnlineLog.vue
new file mode 100644
index 00000000..45c24ccd
--- /dev/null
+++ b/ZR.Vue/src/views/monitor/UserOnlineLog.vue
@@ -0,0 +1,3 @@
+
+  
+
diff --git a/ZR.Vue/src/views/monitor/onlineuser/index.vue b/ZR.Vue/src/views/monitor/onlineuser/index.vue
index 35251324..45c24ccd 100644
--- a/ZR.Vue/src/views/monitor/onlineuser/index.vue
+++ b/ZR.Vue/src/views/monitor/onlineuser/index.vue
@@ -1,3 +1,3 @@
 
-  请升级至vue3
+  
 
From cbc236dc646777f63068b47b0a65db0db053f215 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=8D=E5=81=9A=E7=A0=81=E5=86=9C?= <599854767@qq.com>
Date: Thu, 28 Mar 2024 18:36:46 +0800
Subject: [PATCH 12/23] =?UTF-8?q?:zap:=E4=BC=98=E5=8C=96=E7=A7=8D=E5=AD=90?=
 =?UTF-8?q?=E6=95=B0=E6=8D=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
 ZR.Admin.WebApi/wwwroot/data.xlsx | Bin 39318 -> 39488 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/ZR.Admin.WebApi/wwwroot/data.xlsx b/ZR.Admin.WebApi/wwwroot/data.xlsx
index 18345c0de72a1747c959de4d587cf52800be34e5..592a0c85f4a90ad84f1f50e2b339b4f5c51327a6 100644
GIT binary patch
delta 26542
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