From d89bbfdd748109020f3255c80918d0f60b6e842c Mon Sep 17 00:00:00 2001
From: wxw <Administrator@DESKTOP-5BIMHQ3>
Date: 星期五, 06 九月 2024 16:56:01 +0800
Subject: [PATCH] Merge branch 'master' into wxw

---
 Admin.NET/Admin.NET.Core/Service/Log/SysLogExService.cs                 |   86 +++++
 Admin.NET/Admin.NET.Core/Service/Log/SysLogOpService.cs                 |   84 +++++
 Admin.NET/WCS.Application/PLC/PLCUtil.cs                                |   63 ++-
 Admin.NET/Admin.NET.Core/Service/Log/Dto/ExportLogDto.cs                |   68 ++++
 Admin.NET/Admin.NET.Core/Service/Log/SysLogDiffService.cs               |   58 +++
 Admin.NET/Admin.NET.Core/Service/Log/Dto/LogInput.cs                    |   73 ++++
 Admin.NET/WCS.Application/Hub/PlcHub.cs                                 |   12 
 Web/src/views/device/deviceMonitor/index.vue                            |   24 +
 Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoInput.cs |    6 
 Admin.NET/WCS.Application/Service/Config/SysConfigService.cs            |   17 +
 Web/src/views/device/alarmManage/index.vue                              |   25 -
 Admin.NET/Admin.NET.Core/Service/Log/SysLogVisService.cs                |   72 ++++
 Admin.NET/Admin.NET.Core/Service/Log/Dto/LogVisOutput.cs                |   35 ++
 Admin.NET/WCS.Application/PLC/PLCTaskAction.cs                          |   18 
 Web/src/views/device/deviceMonitor/component/setting.vue                |  198 +++++++++++++
 Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs   |   35 ++
 16 files changed, 819 insertions(+), 55 deletions(-)

diff --git a/Admin.NET/Admin.NET.Core/Service/Log/Dto/ExportLogDto.cs b/Admin.NET/Admin.NET.Core/Service/Log/Dto/ExportLogDto.cs
new file mode 100644
index 0000000..bd99c03
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Log/Dto/ExportLogDto.cs
@@ -0,0 +1,68 @@
+锘�// Admin.NET 椤圭洰鐨勭増鏉冦�佸晢鏍囥�佷笓鍒╁拰鍏朵粬鐩稿叧鏉冨埄鍧囧彈鐩稿簲娉曞緥娉曡鐨勪繚鎶ゃ�備娇鐢ㄦ湰椤圭洰搴旈伒瀹堢浉鍏虫硶寰嬫硶瑙勫拰璁稿彲璇佺殑瑕佹眰銆�
+//
+// 鏈」鐩富瑕侀伒寰� MIT 璁稿彲璇佸拰 Apache 璁稿彲璇侊紙鐗堟湰 2.0锛夎繘琛屽垎鍙戝拰浣跨敤銆傝鍙瘉浣嶄簬婧愪唬鐮佹爲鏍圭洰褰曚腑鐨� LICENSE-MIT 鍜� LICENSE-APACHE 鏂囦欢銆�
+//
+// 涓嶅緱鍒╃敤鏈」鐩粠浜嬪嵄瀹冲浗瀹跺畨鍏ㄣ�佹壈涔辩ぞ浼氱З搴忋�佷镜鐘粬浜哄悎娉曟潈鐩婄瓑娉曞緥娉曡绂佹鐨勬椿鍔紒浠讳綍鍩轰簬鏈」鐩簩娆″紑鍙戣�屼骇鐢熺殑涓�鍒囨硶寰嬬籂绾峰拰璐d换锛屾垜浠笉鎵挎媴浠讳綍璐d换锛�
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// 瀵煎嚭鏃ュ織鏁版嵁
+/// </summary>
+[ExcelExporter(Name = "鏃ュ織鏁版嵁", TableStyle = OfficeOpenXml.Table.TableStyles.None, AutoFitAllColumn = true)]
+public class ExportLogDto
+{
+    /// <summary>
+    /// 璁板綍鍣ㄧ被鍒悕绉�
+    /// </summary>
+    [ExporterHeader(DisplayName = "璁板綍鍣ㄧ被鍒悕绉�", IsBold = true)]
+    public string LogName { get; set; }
+
+    /// <summary>
+    /// 鏃ュ織绾у埆
+    /// </summary>
+    [ExporterHeader(DisplayName = "鏃ュ織绾у埆", IsBold = true)]
+    public string LogLevel { get; set; }
+
+    /// <summary>
+    /// 浜嬩欢Id
+    /// </summary>
+    [ExporterHeader(DisplayName = "浜嬩欢Id", IsBold = true)]
+    public string EventId { get; set; }
+
+    /// <summary>
+    /// 鏃ュ織娑堟伅
+    /// </summary>
+    [ExporterHeader(DisplayName = "鏃ュ織娑堟伅", IsBold = true)]
+    public string Message { get; set; }
+
+    /// <summary>
+    /// 寮傚父瀵硅薄
+    /// </summary>
+    [ExporterHeader(DisplayName = "寮傚父瀵硅薄", IsBold = true)]
+    public string Exception { get; set; }
+
+    /// <summary>
+    /// 褰撳墠鐘舵�佸��
+    /// </summary>
+    [ExporterHeader(DisplayName = "褰撳墠鐘舵�佸��", IsBold = true)]
+    public string State { get; set; }
+
+    /// <summary>
+    /// 鏃ュ織璁板綍鏃堕棿
+    /// </summary>
+    [ExporterHeader(DisplayName = "鏃ュ織璁板綍鏃堕棿", IsBold = true)]
+    public DateTime LogDateTime { get; set; }
+
+    /// <summary>
+    /// 绾跨▼Id
+    /// </summary>
+    [ExporterHeader(DisplayName = "绾跨▼Id", IsBold = true)]
+    public int ThreadId { get; set; }
+
+    /// <summary>
+    /// 璇锋眰璺熻釜Id
+    /// </summary>
+    [ExporterHeader(DisplayName = "璇锋眰璺熻釜Id", IsBold = true)]
+    public string TraceId { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Log/Dto/LogInput.cs b/Admin.NET/Admin.NET.Core/Service/Log/Dto/LogInput.cs
new file mode 100644
index 0000000..c342f4b
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Log/Dto/LogInput.cs
@@ -0,0 +1,73 @@
+锘�// Admin.NET 椤圭洰鐨勭増鏉冦�佸晢鏍囥�佷笓鍒╁拰鍏朵粬鐩稿叧鏉冨埄鍧囧彈鐩稿簲娉曞緥娉曡鐨勪繚鎶ゃ�備娇鐢ㄦ湰椤圭洰搴旈伒瀹堢浉鍏虫硶寰嬫硶瑙勫拰璁稿彲璇佺殑瑕佹眰銆�
+//
+// 鏈」鐩富瑕侀伒寰� MIT 璁稿彲璇佸拰 Apache 璁稿彲璇侊紙鐗堟湰 2.0锛夎繘琛屽垎鍙戝拰浣跨敤銆傝鍙瘉浣嶄簬婧愪唬鐮佹爲鏍圭洰褰曚腑鐨� LICENSE-MIT 鍜� LICENSE-APACHE 鏂囦欢銆�
+//
+// 涓嶅緱鍒╃敤鏈」鐩粠浜嬪嵄瀹冲浗瀹跺畨鍏ㄣ�佹壈涔辩ぞ浼氱З搴忋�佷镜鐘粬浜哄悎娉曟潈鐩婄瓑娉曞緥娉曡绂佹鐨勬椿鍔紒浠讳綍鍩轰簬鏈」鐩簩娆″紑鍙戣�屼骇鐢熺殑涓�鍒囨硶寰嬬籂绾峰拰璐d换锛屾垜浠笉鎵挎媴浠讳綍璐d换锛�
+
+namespace Admin.NET.Core.Service;
+
+public class PageOpLogInput : PageVisLogInput
+{
+    /// <summary>
+    /// 妯″潡鍚嶇О
+    /// </summary>
+    public string? ControllerName { get; set; }
+}
+
+public class PageExLogInput : PageOpLogInput
+{
+}
+
+public class PageVisLogInput : PageLogInput
+{
+    /// <summary>
+    /// 鏂规硶鍚嶇О
+    ///</summary>
+    public string? ActionName { get; set; }
+}
+
+public class PageLogInput : BasePageInput
+{
+    /// <summary>
+    /// 寮�濮嬫椂闂�
+    /// </summary>
+    public DateTime? StartTime { get; set; }
+
+    /// <summary>
+    /// 缁撴潫鏃堕棿
+    /// </summary>
+    public DateTime? EndTime { get; set; }
+
+    /// <summary>
+    /// 璐﹀彿
+    /// </summary>
+    public string? Account { get; set; }
+
+    /// <summary>
+    /// 鎿嶄綔鐢ㄦ椂
+    /// </summary>
+    public long? Elapsed { get; set; }
+
+    /// <summary>
+    /// 鐘舵��
+    /// </summary>
+    public string Status { get; set; }
+
+    /// <summary>
+    /// IP鍦板潃
+    /// </summary>
+    public string? RemoteIp { get; set; }
+}
+
+public class LogInput
+{
+    /// <summary>
+    /// 寮�濮嬫椂闂�
+    /// </summary>
+    public DateTime? StartTime { get; set; }
+
+    /// <summary>
+    /// 缁撴潫鏃堕棿
+    /// </summary>
+    public DateTime? EndTime { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Log/Dto/LogVisOutput.cs b/Admin.NET/Admin.NET.Core/Service/Log/Dto/LogVisOutput.cs
new file mode 100644
index 0000000..8e69aaf
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Log/Dto/LogVisOutput.cs
@@ -0,0 +1,35 @@
+锘�// Admin.NET 椤圭洰鐨勭増鏉冦�佸晢鏍囥�佷笓鍒╁拰鍏朵粬鐩稿叧鏉冨埄鍧囧彈鐩稿簲娉曞緥娉曡鐨勪繚鎶ゃ�備娇鐢ㄦ湰椤圭洰搴旈伒瀹堢浉鍏虫硶寰嬫硶瑙勫拰璁稿彲璇佺殑瑕佹眰銆�
+//
+// 鏈」鐩富瑕侀伒寰� MIT 璁稿彲璇佸拰 Apache 璁稿彲璇侊紙鐗堟湰 2.0锛夎繘琛屽垎鍙戝拰浣跨敤銆傝鍙瘉浣嶄簬婧愪唬鐮佹爲鏍圭洰褰曚腑鐨� LICENSE-MIT 鍜� LICENSE-APACHE 鏂囦欢銆�
+//
+// 涓嶅緱鍒╃敤鏈」鐩粠浜嬪嵄瀹冲浗瀹跺畨鍏ㄣ�佹壈涔辩ぞ浼氱З搴忋�佷镜鐘粬浜哄悎娉曟潈鐩婄瓑娉曞緥娉曡绂佹鐨勬椿鍔紒浠讳綍鍩轰簬鏈」鐩簩娆″紑鍙戣�屼骇鐢熺殑涓�鍒囨硶寰嬬籂绾峰拰璐d换锛屾垜浠笉鎵挎媴浠讳綍璐d换锛�
+
+namespace Admin.NET.Core.Service;
+
+public class LogVisOutput
+{
+    /// <summary>
+    /// 鐧诲綍鍦扮偣
+    /// </summary>
+    public string Location { get; set; }
+
+    /// <summary>
+    /// 缁忓害
+    /// </summary>
+    public double? Longitude { get; set; }
+
+    /// <summary>
+    /// 缁村害
+    /// </summary>
+    public double? Latitude { get; set; }
+
+    /// <summary>
+    /// 鐪熷疄濮撳悕
+    /// </summary>
+    public string RealName { get; set; }
+
+    /// <summary>
+    /// 鏃ュ織鏃堕棿
+    /// </summary>
+    public DateTime? LogDateTime { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Log/SysLogDiffService.cs b/Admin.NET/Admin.NET.Core/Service/Log/SysLogDiffService.cs
new file mode 100644
index 0000000..8db3141
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Log/SysLogDiffService.cs
@@ -0,0 +1,58 @@
+锘�// Admin.NET 椤圭洰鐨勭増鏉冦�佸晢鏍囥�佷笓鍒╁拰鍏朵粬鐩稿叧鏉冨埄鍧囧彈鐩稿簲娉曞緥娉曡鐨勪繚鎶ゃ�備娇鐢ㄦ湰椤圭洰搴旈伒瀹堢浉鍏虫硶寰嬫硶瑙勫拰璁稿彲璇佺殑瑕佹眰銆�
+//
+// 鏈」鐩富瑕侀伒寰� MIT 璁稿彲璇佸拰 Apache 璁稿彲璇侊紙鐗堟湰 2.0锛夎繘琛屽垎鍙戝拰浣跨敤銆傝鍙瘉浣嶄簬婧愪唬鐮佹爲鏍圭洰褰曚腑鐨� LICENSE-MIT 鍜� LICENSE-APACHE 鏂囦欢銆�
+//
+// 涓嶅緱鍒╃敤鏈」鐩粠浜嬪嵄瀹冲浗瀹跺畨鍏ㄣ�佹壈涔辩ぞ浼氱З搴忋�佷镜鐘粬浜哄悎娉曟潈鐩婄瓑娉曞緥娉曡绂佹鐨勬椿鍔紒浠讳綍鍩轰簬鏈」鐩簩娆″紑鍙戣�屼骇鐢熺殑涓�鍒囨硶寰嬬籂绾峰拰璐d换锛屾垜浠笉鎵挎媴浠讳綍璐d换锛�
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 绯荤粺宸紓鏃ュ織鏈嶅姟 馃З
+/// </summary>
+[ApiDescriptionSettings(Order = 330)]
+public class SysLogDiffService : IDynamicApiController, ITransient
+{
+    private readonly SqlSugarRepository<SysLogDiff> _sysLogDiffRep;
+
+    public SysLogDiffService(SqlSugarRepository<SysLogDiff> sysLogDiffRep)
+    {
+        _sysLogDiffRep = sysLogDiffRep;
+    }
+
+    /// <summary>
+    /// 鑾峰彇宸紓鏃ュ織鍒嗛〉鍒楄〃 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("鑾峰彇宸紓鏃ュ織鍒嗛〉鍒楄〃")]
+    public async Task<SqlSugarPagedList<SysLogDiff>> Page(PageLogInput input)
+    {
+        return await _sysLogDiffRep.AsQueryable()
+            .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
+            .OrderBy(u => u.CreateTime, OrderByType.Desc)
+            .ToPagedListAsync(input.Page, input.PageSize);
+    }
+
+    /// <summary>
+    /// 鑾峰彇宸紓鏃ュ織璇︽儏 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("鑾峰彇宸紓鏃ュ織璇︽儏")]
+    public async Task<SysLogDiff> GetDetail(long id)
+    {
+        return await _sysLogDiffRep.GetFirstAsync(u => u.Id == id);
+    }
+
+    /// <summary>
+    /// 娓呯┖宸紓鏃ュ織 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(Name = "Clear"), HttpPost]
+    [DisplayName("娓呯┖宸紓鏃ュ織")]
+    public void Clear()
+    {
+        _sysLogDiffRep.AsSugarClient().DbMaintenance.TruncateTable<SysLogDiff>();
+    }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Log/SysLogExService.cs b/Admin.NET/Admin.NET.Core/Service/Log/SysLogExService.cs
new file mode 100644
index 0000000..2519a26
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Log/SysLogExService.cs
@@ -0,0 +1,86 @@
+锘�// Admin.NET 椤圭洰鐨勭増鏉冦�佸晢鏍囥�佷笓鍒╁拰鍏朵粬鐩稿叧鏉冨埄鍧囧彈鐩稿簲娉曞緥娉曡鐨勪繚鎶ゃ�備娇鐢ㄦ湰椤圭洰搴旈伒瀹堢浉鍏虫硶寰嬫硶瑙勫拰璁稿彲璇佺殑瑕佹眰銆�
+//
+// 鏈」鐩富瑕侀伒寰� MIT 璁稿彲璇佸拰 Apache 璁稿彲璇侊紙鐗堟湰 2.0锛夎繘琛屽垎鍙戝拰浣跨敤銆傝鍙瘉浣嶄簬婧愪唬鐮佹爲鏍圭洰褰曚腑鐨� LICENSE-MIT 鍜� LICENSE-APACHE 鏂囦欢銆�
+//
+// 涓嶅緱鍒╃敤鏈」鐩粠浜嬪嵄瀹冲浗瀹跺畨鍏ㄣ�佹壈涔辩ぞ浼氱З搴忋�佷镜鐘粬浜哄悎娉曟潈鐩婄瓑娉曞緥娉曡绂佹鐨勬椿鍔紒浠讳綍鍩轰簬鏈」鐩簩娆″紑鍙戣�屼骇鐢熺殑涓�鍒囨硶寰嬬籂绾峰拰璐d换锛屾垜浠笉鎵挎媴浠讳綍璐d换锛�
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 绯荤粺寮傚父鏃ュ織鏈嶅姟 馃З
+/// </summary>
+[ApiDescriptionSettings(Order = 350)]
+public class SysLogExService : IDynamicApiController, ITransient
+{
+    private readonly SqlSugarRepository<SysLogEx> _sysLogExRep;
+
+    public SysLogExService(SqlSugarRepository<SysLogEx> sysLogExRep)
+    {
+        _sysLogExRep = sysLogExRep;
+    }
+
+    /// <summary>
+    /// 鑾峰彇寮傚父鏃ュ織鍒嗛〉鍒楄〃 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("鑾峰彇寮傚父鏃ュ織鍒嗛〉鍒楄〃")]
+    public async Task<SqlSugarPagedList<SysLogEx>> Page(PageExLogInput input)
+    {
+        return await _sysLogExRep.AsQueryable()
+            .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account == input.Account)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.ControllerName), u => u.ControllerName == input.ControllerName)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.ActionName), u => u.ActionName == input.ActionName)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.RemoteIp), u => u.RemoteIp == input.RemoteIp)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Elapsed.ToString()), u => u.Elapsed >= input.Elapsed)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Status) && input.Status == "200", u => u.Status == input.Status)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Status) && input.Status != "200", u => u.Status != input.Status)
+            //.OrderBy(u => u.CreateTime, OrderByType.Desc)
+            .IgnoreColumns(u => new { u.RequestParam, u.ReturnResult, u.Message })
+            .OrderBuilder(input)
+            .ToPagedListAsync(input.Page, input.PageSize);
+    }
+
+    /// <summary>
+    /// 鑾峰彇寮傚父鏃ュ織璇︽儏 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("鑾峰彇寮傚父鏃ュ織璇︽儏")]
+    public async Task<SysLogEx> GetDetail(long id)
+    {
+        return await _sysLogExRep.GetFirstAsync(u => u.Id == id);
+    }
+
+    /// <summary>
+    /// 娓呯┖寮傚父鏃ュ織 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(Name = "Clear"), HttpPost]
+    [DisplayName("娓呯┖寮傚父鏃ュ織")]
+    public void Clear()
+    {
+        _sysLogExRep.AsSugarClient().DbMaintenance.TruncateTable<SysLogEx>();
+    }
+
+    /// <summary>
+    /// 瀵煎嚭寮傚父鏃ュ織 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(Name = "Export"), NonUnify]
+    [DisplayName("瀵煎嚭寮傚父鏃ュ織")]
+    public async Task<IActionResult> ExportLogEx(LogInput input)
+    {
+        var logExList = await _sysLogExRep.AsQueryable()
+            .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()),
+                    u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime)
+            .OrderBy(u => u.CreateTime, OrderByType.Desc)
+            .Select<ExportLogDto>().ToListAsync();
+
+        IExcelExporter excelExporter = new ExcelExporter();
+        var res = await excelExporter.ExportAsByteArray(logExList);
+        return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "寮傚父鏃ュ織.xlsx" };
+    }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Log/SysLogOpService.cs b/Admin.NET/Admin.NET.Core/Service/Log/SysLogOpService.cs
new file mode 100644
index 0000000..7d3d2d2
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Log/SysLogOpService.cs
@@ -0,0 +1,84 @@
+锘�// Admin.NET 椤圭洰鐨勭増鏉冦�佸晢鏍囥�佷笓鍒╁拰鍏朵粬鐩稿叧鏉冨埄鍧囧彈鐩稿簲娉曞緥娉曡鐨勪繚鎶ゃ�備娇鐢ㄦ湰椤圭洰搴旈伒瀹堢浉鍏虫硶寰嬫硶瑙勫拰璁稿彲璇佺殑瑕佹眰銆�
+//
+// 鏈」鐩富瑕侀伒寰� MIT 璁稿彲璇佸拰 Apache 璁稿彲璇侊紙鐗堟湰 2.0锛夎繘琛屽垎鍙戝拰浣跨敤銆傝鍙瘉浣嶄簬婧愪唬鐮佹爲鏍圭洰褰曚腑鐨� LICENSE-MIT 鍜� LICENSE-APACHE 鏂囦欢銆�
+//
+// 涓嶅緱鍒╃敤鏈」鐩粠浜嬪嵄瀹冲浗瀹跺畨鍏ㄣ�佹壈涔辩ぞ浼氱З搴忋�佷镜鐘粬浜哄悎娉曟潈鐩婄瓑娉曞緥娉曡绂佹鐨勬椿鍔紒浠讳綍鍩轰簬鏈」鐩簩娆″紑鍙戣�屼骇鐢熺殑涓�鍒囨硶寰嬬籂绾峰拰璐d换锛屾垜浠笉鎵挎媴浠讳綍璐d换锛�
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 绯荤粺鎿嶄綔鏃ュ織鏈嶅姟 馃З
+/// </summary>
+[ApiDescriptionSettings(Order = 360)]
+public class SysLogOpService : IDynamicApiController, ITransient
+{
+    private readonly SqlSugarRepository<SysLogOp> _sysLogOpRep;
+
+    public SysLogOpService(SqlSugarRepository<SysLogOp> sysLogOpRep)
+    {
+        _sysLogOpRep = sysLogOpRep;
+    }
+
+    /// <summary>
+    /// 鑾峰彇鎿嶄綔鏃ュ織鍒嗛〉鍒楄〃 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("鑾峰彇鎿嶄綔鏃ュ織鍒嗛〉鍒楄〃")]
+    public async Task<SqlSugarPagedList<SysLogOp>> Page(PageOpLogInput input)
+    {
+        return await _sysLogOpRep.AsQueryable()
+            .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account == input.Account)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.RemoteIp), u => u.RemoteIp == input.RemoteIp)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.ControllerName), u => u.ControllerName == input.ControllerName)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.ActionName), u => u.ActionName == input.ActionName)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Elapsed.ToString()), u => u.Elapsed >= input.Elapsed)
+            //.OrderBy(u => u.CreateTime, OrderByType.Desc)
+            .IgnoreColumns(u => new { u.RequestParam, u.ReturnResult, u.Message })
+            .OrderBuilder(input)
+            .ToPagedListAsync(input.Page, input.PageSize);
+    }
+
+    /// <summary>
+    /// 鑾峰彇鎿嶄綔鏃ュ織璇︽儏 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("鑾峰彇鎿嶄綔鏃ュ織璇︽儏")]
+    public async Task<SysLogOp> GetDetail(long id)
+    {
+        return await _sysLogOpRep.GetFirstAsync(u => u.Id == id);
+    }
+
+    /// <summary>
+    /// 娓呯┖鎿嶄綔鏃ュ織 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(Name = "Clear"), HttpPost]
+    [DisplayName("娓呯┖鎿嶄綔鏃ュ織")]
+    public void Clear()
+    {
+        _sysLogOpRep.AsSugarClient().DbMaintenance.TruncateTable<SysLogOp>();
+    }
+
+    /// <summary>
+    /// 瀵煎嚭鎿嶄綔鏃ュ織 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(Name = "Export"), NonUnify]
+    [DisplayName("瀵煎嚭鎿嶄綔鏃ュ織")]
+    public async Task<IActionResult> ExportLogOp(LogInput input)
+    {
+        var logOpList = await _sysLogOpRep.AsQueryable()
+            .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()),
+                    u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime)
+            .OrderBy(u => u.CreateTime, OrderByType.Desc)
+            .Select<ExportLogDto>().ToListAsync();
+
+        IExcelExporter excelExporter = new ExcelExporter();
+        var res = await excelExporter.ExportAsByteArray(logOpList);
+        return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "鎿嶄綔鏃ュ織.xlsx" };
+    }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Log/SysLogVisService.cs b/Admin.NET/Admin.NET.Core/Service/Log/SysLogVisService.cs
new file mode 100644
index 0000000..9c681fd
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Service/Log/SysLogVisService.cs
@@ -0,0 +1,72 @@
+锘�// Admin.NET 椤圭洰鐨勭増鏉冦�佸晢鏍囥�佷笓鍒╁拰鍏朵粬鐩稿叧鏉冨埄鍧囧彈鐩稿簲娉曞緥娉曡鐨勪繚鎶ゃ�備娇鐢ㄦ湰椤圭洰搴旈伒瀹堢浉鍏虫硶寰嬫硶瑙勫拰璁稿彲璇佺殑瑕佹眰銆�
+//
+// 鏈」鐩富瑕侀伒寰� MIT 璁稿彲璇佸拰 Apache 璁稿彲璇侊紙鐗堟湰 2.0锛夎繘琛屽垎鍙戝拰浣跨敤銆傝鍙瘉浣嶄簬婧愪唬鐮佹爲鏍圭洰褰曚腑鐨� LICENSE-MIT 鍜� LICENSE-APACHE 鏂囦欢銆�
+//
+// 涓嶅緱鍒╃敤鏈」鐩粠浜嬪嵄瀹冲浗瀹跺畨鍏ㄣ�佹壈涔辩ぞ浼氱З搴忋�佷镜鐘粬浜哄悎娉曟潈鐩婄瓑娉曞緥娉曡绂佹鐨勬椿鍔紒浠讳綍鍩轰簬鏈」鐩簩娆″紑鍙戣�屼骇鐢熺殑涓�鍒囨硶寰嬬籂绾峰拰璐d换锛屾垜浠笉鎵挎媴浠讳綍璐d换锛�
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 绯荤粺璁块棶鏃ュ織鏈嶅姟 馃З
+/// </summary>
+[ApiDescriptionSettings(Order = 340)]
+public class SysLogVisService : IDynamicApiController, ITransient
+{
+    private readonly SqlSugarRepository<SysLogVis> _sysLogVisRep;
+
+    public SysLogVisService(SqlSugarRepository<SysLogVis> sysLogVisRep)
+    {
+        _sysLogVisRep = sysLogVisRep;
+    }
+
+    /// <summary>
+    /// 鑾峰彇璁块棶鏃ュ織鍒嗛〉鍒楄〃 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [SuppressMonitor]
+    [DisplayName("鑾峰彇璁块棶鏃ュ織鍒嗛〉鍒楄〃")]
+    public async Task<SqlSugarPagedList<SysLogVis>> Page(PageVisLogInput input)
+    {
+        return await _sysLogVisRep.AsQueryable()
+            .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account == input.Account)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.ActionName), u => u.ActionName == input.ActionName)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.RemoteIp), u => u.RemoteIp == input.RemoteIp)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Elapsed.ToString()), u => u.Elapsed >= input.Elapsed)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Status) && input.Status == "200", u => u.Status == input.Status)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Status) && input.Status != "200", u => u.Status != input.Status)
+            .OrderBy(u => u.CreateTime, OrderByType.Desc)
+            .ToPagedListAsync(input.Page, input.PageSize);
+    }
+
+    /// <summary>
+    /// 娓呯┖璁块棶鏃ュ織 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [ApiDescriptionSettings(Name = "Clear"), HttpPost]
+    [DisplayName("娓呯┖璁块棶鏃ュ織")]
+    public void Clear()
+    {
+        _sysLogVisRep.AsSugarClient().DbMaintenance.TruncateTable<SysLogVis>();
+    }
+
+    /// <summary>
+    /// 鑾峰彇璁块棶鏃ュ織鍒楄〃 馃敄
+    /// </summary>
+    /// <returns></returns>
+    [DisplayName("鑾峰彇璁块棶鏃ュ織鍒楄〃")]
+    public async Task<List<LogVisOutput>> GetList()
+    {
+        return await _sysLogVisRep.AsQueryable()
+            .Where(u => u.Longitude > 0 && u.Longitude > 0)
+            .Select(u => new LogVisOutput
+            {
+                Location = u.Location,
+                Longitude = u.Longitude,
+                Latitude = u.Latitude,
+                RealName = u.RealName,
+                LogDateTime = u.LogDateTime
+            }).ToListAsync();
+    }
+}
\ No newline at end of file
diff --git a/Admin.NET/WCS.Application/Hub/PlcHub.cs b/Admin.NET/WCS.Application/Hub/PlcHub.cs
index de41681..2cf316f 100644
--- a/Admin.NET/WCS.Application/Hub/PlcHub.cs
+++ b/Admin.NET/WCS.Application/Hub/PlcHub.cs
@@ -10,10 +10,11 @@
 public class PlcHub : Hub<IPlcHub>
 {
     private readonly IHubContext<PlcHub, IPlcHub> _plcHubContext;
-
-    public PlcHub(IHubContext<PlcHub, IPlcHub> plcHubContext)
+    private readonly SysConfigService _sysConfigService;
+    public PlcHub(IHubContext<PlcHub, IPlcHub> plcHubContext, SysConfigService sysConfigService)
     {
         _plcHubContext = plcHubContext;
+        _sysConfigService = sysConfigService;
     }
     /// <summary>
     /// 涓嬪彂PLC杩炴帴鐘舵��
@@ -48,13 +49,20 @@
                 PLCTaskAction.Init();
             else
                 PLCTaskAction.Stop();
+            await _sysConfigService.UpdateConfigValue("sys_RunningState", context.BoRunningState.Value);
         }
         //鑴辨満妯″紡
         if (context.BoOffline.HasValue)
+        {
             PLCTaskAction.boOffline = context.BoOffline.Value;
+            await _sysConfigService.UpdateConfigValue("sys_Offline", context.BoOffline.Value);
+        }
         //鑷埛鏂�
         if (context.BoRefresh.HasValue)
+        {
             PLCTaskAction.boRefresh = context.BoRefresh.Value;
+            await _sysConfigService.UpdateConfigValue("sys_Refresh", context.BoRefresh.Value);
+        }
         await _plcHubContext.Clients.All.UpdateService(new PLCServiceModel() { BoRunningState = PLCTaskAction.boRunningState, BoRefresh = PLCTaskAction.boRefresh, BoOffline = PLCTaskAction.boOffline });
     }
 }
diff --git a/Admin.NET/WCS.Application/PLC/PLCTaskAction.cs b/Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
index 69e9e93..a7eff8f 100644
--- a/Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
+++ b/Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -19,6 +19,7 @@
     private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
     private static readonly SysCacheService sysCacheService = App.GetRequiredService<SysCacheService>();
     private static readonly IHubContext<PlcHub, IPlcHub> _plcHubContext = App.GetService<IHubContext<PlcHub, IPlcHub>>();
+    private static readonly SysConfigService _sysConfigService = App.GetService<SysConfigService>();
 
     private static List<WcsPlc> listPlc = new List<WcsPlc>();
     private static List<WcsDevice> listPlcDevice = new List<WcsDevice>();
@@ -37,6 +38,9 @@
     {
         //璁㈤槄浜嬩欢
         DeviceValueChangeEvent += PLCService.OnChangeEvent;
+        boRunningState = _sysConfigService.GetConfigValue<bool>("sys_RunningState").Result;
+        boOffline = _sysConfigService.GetConfigValue<bool>("sys_Offline").Result;
+        boRefresh = _sysConfigService.GetConfigValue<bool>("sys_Refresh").Result;
     }
     /// <summary>
     /// 鍒濆鍖朠LC杩炴帴
@@ -60,18 +64,20 @@
             var plc = new PLCUtil(modPlc);
             listPlcUtil.Add(plc);
         }
-        cts = new CancellationTokenSource();
-        boRunningState = true;
         _plcHubContext.Clients.All.UpdateService(new PLCServiceModel()
         {
             BoRunningState = boRunningState,
             BoOffline = boOffline,
             BoRefresh = boRefresh
         });
-        StartRead();
-        ConnectionStatus();
-        StartWatchAlarm();
-        StartWatchPosition();
+        if (boRunningState)
+        {
+            cts = new CancellationTokenSource();
+            StartRead();
+            ConnectionStatus();
+            StartWatchAlarm();
+            StartWatchPosition();
+        }
     }
     /// <summary>
     /// 寮�鍚鍙杙lc绾跨▼
diff --git a/Admin.NET/WCS.Application/PLC/PLCUtil.cs b/Admin.NET/WCS.Application/PLC/PLCUtil.cs
index 27e6c55..0caf17a 100644
--- a/Admin.NET/WCS.Application/PLC/PLCUtil.cs
+++ b/Admin.NET/WCS.Application/PLC/PLCUtil.cs
@@ -53,41 +53,55 @@
                 address = DbNumber + "." + Pos;
             else
                 address = DbNumber + Pos;
+            return this.GetPlcDBValue(PosType, address, Length);
+        }
+    }
+    /// <summary>
+    /// 璇诲彇PLC鍊�
+    /// </summary>
+    /// <param name="PosType">瀛楃绫诲瀷</param>
+    /// <param name="Pos">鍋忕Щ閲�/鍦板潃</param>
+    /// <param name="Length">闀垮害锛堝瓧绗︿覆锛�</param>
+    /// <returns></returns>
+    public (IoTClient.Result, dynamic value) GetPlcDBValue(PLCDataTypeEnum PosType, string Pos, int? Length = 0)
+    {
+        lock (OLock)
+        {
             dynamic result = null;
             switch (PosType)
             {
                 case PLCDataTypeEnum.Bit:
-                    result = _client.ReadBoolean(address);
+                    result = _client.ReadBoolean(Pos);
                     break;
                 case PLCDataTypeEnum.Byte:
-                    result = _client.ReadByte(address);
+                    result = _client.ReadByte(Pos);
                     break;
                 case PLCDataTypeEnum.Short:
-                    result = _client.ReadInt16(address);
+                    result = _client.ReadInt16(Pos);
                     break;
                 case PLCDataTypeEnum.UShort:
-                    result = _client.ReadUInt16(address);
+                    result = _client.ReadUInt16(Pos);
                     break;
                 case PLCDataTypeEnum.Int:
-                    result = _client.ReadInt32(address);
+                    result = _client.ReadInt32(Pos);
                     break;
                 case PLCDataTypeEnum.UInt:
-                    result = _client.ReadUInt32(address);
+                    result = _client.ReadUInt32(Pos);
                     break;
                 case PLCDataTypeEnum.Long:
-                    result = _client.ReadInt64(address);
+                    result = _client.ReadInt64(Pos);
                     break;
                 case PLCDataTypeEnum.ULong:
-                    result = _client.ReadUInt64(address);
+                    result = _client.ReadUInt64(Pos);
                     break;
                 case PLCDataTypeEnum.Float:
-                    result = _client.ReadFloat(address);
+                    result = _client.ReadFloat(Pos);
                     break;
                 case PLCDataTypeEnum.Double:
-                    result = _client.ReadDouble(address);
+                    result = _client.ReadDouble(Pos);
                     break;
                 case PLCDataTypeEnum.String:
-                    result = _client.ReadString(address, Convert.ToUInt16(Length));
+                    result = _client.ReadString(Pos, Convert.ToUInt16(Length));
                     break;
                 default:
                     result = new IoTClient.Result<object>();
@@ -159,6 +173,13 @@
             address = DbNumber + "." + Pos;
         else
             address = DbNumber + Pos;
+        return this.SetPlcDBValue(PosType, address, Pos, Value);
+    }
+    /// <summary>
+    /// 鍐欏叆PLC鍊�
+    /// </summary>
+    public IoTClient.Result SetPlcDBValue(PLCDataTypeEnum PosType, string Pos, string Value)
+    {
         switch (PosType)
         {
             case PLCDataTypeEnum.Bit:
@@ -173,25 +194,25 @@
                         throw new Exception("鍐欏叆鍊奸敊璇�");
                     }
                 }
-                return _client.Write(address, bit);
+                return _client.Write(Pos, bit);
             case PLCDataTypeEnum.Byte:
-                return _client.Write(address, byte.Parse(Value));
+                return _client.Write(Pos, byte.Parse(Value));
             case PLCDataTypeEnum.Short:
-                return _client.Write(address, short.Parse(Value));
+                return _client.Write(Pos, short.Parse(Value));
             case PLCDataTypeEnum.UShort:
-                return _client.Write(address, ushort.Parse(Value));
+                return _client.Write(Pos, ushort.Parse(Value));
             case PLCDataTypeEnum.Int:
-                return _client.Write(address, int.Parse(Value));
+                return _client.Write(Pos, int.Parse(Value));
             case PLCDataTypeEnum.UInt:
-                return _client.Write(address, uint.Parse(Value));
+                return _client.Write(Pos, uint.Parse(Value));
             case PLCDataTypeEnum.Long:
-                return _client.Write(address, long.Parse(Value));
+                return _client.Write(Pos, long.Parse(Value));
             case PLCDataTypeEnum.ULong:
-                return _client.Write(address, ulong.Parse(Value));
+                return _client.Write(Pos, ulong.Parse(Value));
             case PLCDataTypeEnum.Float:
-                return _client.Write(address, float.Parse(Value));
+                return _client.Write(Pos, float.Parse(Value));
             case PLCDataTypeEnum.Double:
-                return _client.Write(address, float.Parse(Value));
+                return _client.Write(Pos, float.Parse(Value));
             default:
                 return new IoTClient.Result();
         }
diff --git a/Admin.NET/WCS.Application/Service/Config/SysConfigService.cs b/Admin.NET/WCS.Application/Service/Config/SysConfigService.cs
index 2c691a9..ea1ddc9 100644
--- a/Admin.NET/WCS.Application/Service/Config/SysConfigService.cs
+++ b/Admin.NET/WCS.Application/Service/Config/SysConfigService.cs
@@ -107,4 +107,21 @@
 
         _sysCacheService.Remove($"{CacheConst.KeyConfig}{config.Code}");
     }
+    /// <summary>
+    /// 鏇存柊鍙傛暟閰嶇疆鍊�
+    /// </summary>
+    /// <param name="code"></param>
+    /// <param name="value"></param>
+    /// <returns></returns>
+    [NonAction]
+    public async Task UpdateConfigValue(string code, bool value)
+    {
+        var config = await _sysConfigRep.GetFirstAsync(u => u.Code == code);
+        if (config == null) return;
+
+        config.Value = value?"True":"False";
+        await _sysConfigRep.AsUpdateable(config).ExecuteCommandAsync();
+
+        _sysCacheService.Remove($"{CacheConst.KeyConfig}{config.Code}");
+    }
 }
diff --git a/Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoInput.cs b/Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoInput.cs
index 11f5067..25b843b 100644
--- a/Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoInput.cs
+++ b/Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoInput.cs
@@ -200,3 +200,9 @@
 {
 
 }
+
+public class ResetInput
+{
+    [Required(ErrorMessage = "妤煎眰涓嶈兘涓虹┖")]
+    public int layer { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs b/Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs
index e2eef27..27f6373 100644
--- a/Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs
+++ b/Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs
@@ -1,4 +1,5 @@
-锘縰sing Microsoft.AspNetCore.SignalR;
+锘縰sing Admin.NET.Core.Service;
+using Microsoft.AspNetCore.SignalR;
 
 namespace WCS.Application;
 
@@ -10,10 +11,12 @@
 {
     private readonly SqlSugarRepository<WcsAlarmInfo> _wcsAlarmInfoRep;
     private readonly IHubContext<PlcHub, IPlcHub> _plcHubContext;
-    public WcsAlarmInfoService(SqlSugarRepository<WcsAlarmInfo> wcsAlarmInfoRep, IHubContext<PlcHub, IPlcHub> plcHubContext)
+    private readonly SysDictDataService _dictDataService;
+    public WcsAlarmInfoService(SqlSugarRepository<WcsAlarmInfo> wcsAlarmInfoRep, IHubContext<PlcHub, IPlcHub> plcHubContext, SysDictDataService dictDataService)
     {
         _wcsAlarmInfoRep = wcsAlarmInfoRep;
         _plcHubContext = plcHubContext;
+        _dictDataService = dictDataService;
     }
 
     /// <summary>
@@ -121,13 +124,35 @@
     [HttpPost]
     [ApiDescriptionSettings(Name = "Reset")]
     [DisplayName("澶嶄綅鎶ヨ")]
-    public async Task Reset()
+    public async Task Reset(ResetInput input)
     {
         //娴嬭瘯鎺ㄦ暟鎹敤鐨�
-        await _plcHubContext.Clients.All.PublicAlarm(new List<WcsAlarmInfo>() { new WcsAlarmInfo() { Id = 100, StationNum = "260", AlarmCode = "MB102", AlarmName = "鏈夌墿鍝侀伄鎸�", AlarmTime = DateTime.Now, Status = YesNoEnum.N } });
+        //await _plcHubContext.Clients.All.PublicAlarm(new List<WcsAlarmInfo>() { new WcsAlarmInfo() { Id = 100, StationNum = "260", AlarmCode = "MB102", AlarmName = "鏈夌墿鍝侀伄鎸�", AlarmTime = DateTime.Now, Status = YesNoEnum.Y } });
         //await _plcHubContext.Clients.All.PublicAlarm(new WcsAlarmInfo() { Id = 100, StationNum = "260", AlarmCode = "MB102", AlarmName = "鏈夌墿鍝侀伄鎸�", AlarmTime = DateTime.Now, Status = YesNoEnum.Y });
+        var modPlc = await _wcsAlarmInfoRep.Context.Queryable<WcsPlc>().Where(s => s.Type == PLCTypeEnum.ConveyorLine && s.Text == (input.layer.ToString() + "灞傛墭鐩樿緭閫佺嚎")).FirstAsync();
+        if (modPlc == null)
+            throw Oops.Bah("鏈壘鍒拌緭閫佺嚎PLC");
+        var listDict = await _dictDataService.GetDataList("reset_alarm");
+        var value = listDict.FirstOrDefault(s => s.Code == input.layer.ToString());
+        if (value == null)
+            throw Oops.Bah("鏈壘鍒板浣嶅湴鍧�锛岃鍦ㄥ瓧鍏哥鐞嗕腑璁剧疆");
+        PLCUtil modUtil = new PLCUtil(modPlc);
+        switch (input.layer)
+        {
+            case 1:
+                break;
+            case 2:
+                {
+                    modUtil.SetPlcDBValue(PLCDataTypeEnum.Bit, value.Value, "1");
+                }
+                break;
+            case 3:
+                break;
+            default:
+                break;
+        }
+        modUtil.Close();
 
-        //throw Oops.Bah("寮�鍙戜腑");
     }
 
 
diff --git a/Web/src/views/device/alarmManage/index.vue b/Web/src/views/device/alarmManage/index.vue
index 4013f0a..55db218 100644
--- a/Web/src/views/device/alarmManage/index.vue
+++ b/Web/src/views/device/alarmManage/index.vue
@@ -18,9 +18,9 @@
 			</el-col>
 			<el-col :span="19">
 				<div class="card-page">
-					<el-button type="primary" :plain="isPlain1" @click="floorTogglePlain(1)">涓�灞傚钩闈�</el-button>
-					<el-button type="primary" :plain="isPlain2" @click="floorTogglePlain(2)">浜屽眰骞抽潰</el-button>
-					<el-button type="primary" :plain="isPlain3" @click="floorTogglePlain(3)">涓夊眰骞抽潰</el-button>
+					<el-button type="primary" :plain="layer != 1" @click="floorTogglePlain(1)">涓�灞傚钩闈�</el-button>
+					<el-button type="primary" :plain="layer != 2" @click="floorTogglePlain(2)">浜屽眰骞抽潰</el-button>
+					<el-button type="primary" :plain="layer != 3" @click="floorTogglePlain(3)">涓夊眰骞抽潰</el-button>
 				</div>
 				<div style="margin: 40px; height: 50%;">
 					<div class="grid-container-line">
@@ -56,6 +56,7 @@
 import 'splitpanes/dist/splitpanes.css';
 import { listWcsAlarmInfo, resetWcsAlarmInfo } from '/@/api/wcs/wcsAlarmInfo';
 import { signalR } from './signalR';
+import { ElMessageBox, ElMessage } from "element-plus";
 //杩炴帴signalR 鐩戝惉鍙樻洿
 onMounted(async () => {
 	signalR.off('PublicAlarm');
@@ -1950,32 +1951,22 @@
 
 //澶嶄綅鎶ヨ
 const reset = async () => {
-	await resetWcsAlarmInfo();
+	await resetWcsAlarmInfo({ layer: layer.value });
+	ElMessage.success("澶嶄綅鎴愬姛");
 	// await handleQuery();
 }
 
-
-const isPlain1 = ref(false);//涓�灞�
-const isPlain2 = ref(true);//浜屽眰
-const isPlain3 = ref(true);//涓夊眰
+const layer = ref(1);
 //鍒囨崲灞傚钩闈�
 function floorTogglePlain(buttonNumber) {
+	layer.value = buttonNumber;
 	if (buttonNumber === 1) {
-		isPlain1.value = false;
-		isPlain2.value = true;
-		isPlain3.value = true;
 		//鍒囨崲杈撻�佺嚎鏁版嵁
 		cellsData.value = cellsDataOne.value;
 	} else if (buttonNumber === 2) {
-		isPlain2.value = false;
-		isPlain1.value = true;
-		isPlain3.value = true;
 		//鍒囨崲杈撻�佺嚎鏁版嵁
 		cellsData.value = cellsDataTwo.value;
 	} else if (buttonNumber === 3) {
-		isPlain3.value = false;
-		isPlain1.value = true;
-		isPlain2.value = true;
 		//鍒囨崲杈撻�佺嚎鏁版嵁
 		cellsData.value = cellsDataThree.value;
 	}
diff --git a/Web/src/views/device/deviceMonitor/component/setting.vue b/Web/src/views/device/deviceMonitor/component/setting.vue
new file mode 100644
index 0000000..c663b22
--- /dev/null
+++ b/Web/src/views/device/deviceMonitor/component/setting.vue
@@ -0,0 +1,198 @@
+<template>
+	<div class="wcsAlarmInfo-container">
+		<el-dialog v-model="isShowDialog" :width="800" draggable="" :close-on-click-modal="false">
+			<template #header>
+				<div class="dialog-header">
+					<span>{{ props.title }}</span>
+				</div>
+			</template>
+
+			<el-card class="box-card" shadow="hover">
+				<template #header>
+					<div class="card-header">
+						
+						<div>
+							<span>宸ヤ綅鍙凤細</span>
+							<el-select v-model="stationValue" placeholder="璇烽�夋嫨" filterable value-key="stationNum"
+								style="width: 200px;">
+								<el-option v-for="item in listStationsData" :key="item.id" :label="item.stationNum"
+									:value="item">
+								</el-option>
+							</el-select>
+							<el-button style="margin-left: 10px;">鑷姩</el-button>
+						</div>
+						<div>
+							<div :class="['lineStatus', stationValue.status ? 'device-status-0' : 'device-status-1']"></div>
+						</div>
+					</div>
+				</template>
+				<div>
+					<el-form label-position="left" label-width="80px">
+						<el-row :gutter="25">
+							<el-col :span="12">
+								<el-form-item label="璧峰宸ヤ綅">
+									<el-input v-model="stationValue.startLocatNo"></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="鐩殑宸ヤ綅">
+									<el-input v-model="stationValue.endLocatNo"></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="PLC">
+									<el-input v-model="stationValue.plc"></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="WCS">
+									<el-input v-model="stationValue.wcs"></el-input>
+								</el-form-item>
+							</el-col>
+							
+							<el-col :span="12">
+								<el-form-item label="鍙栬揣鎺�">
+									<el-input ></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="鏀捐揣鎺�">
+									<el-input ></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="鍙栬揣鍒�">
+									<el-input ></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="鏀捐揣鍒�">
+									<el-input ></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="鍙栬揣灞�">
+									<el-input ></el-input>
+								</el-form-item>
+							</el-col>
+							<el-col :span="12">
+								<el-form-item label="鏀捐揣灞�">
+									<el-input ></el-input>
+								</el-form-item>
+							</el-col>
+						</el-row>
+					</el-form>
+					<div style="text-align: center;margin: 10px;">
+						<el-button class="button" size="large">鍐欏叆鏁版嵁</el-button>
+					</div>
+				</div>
+				<template #footer>
+					<div class="card-footer">
+						<el-button class="button" size="large">姝�&nbsp;&nbsp;&nbsp;&nbsp;杞�</el-button>
+						<el-button class="button" size="large">鍙�&nbsp;&nbsp;&nbsp;&nbsp;杞�</el-button>
+						<el-button class="button" size="large">绉绘牻涓婂崌</el-button>
+						<el-button class="button" size="large">绉绘牻涓嬮檷</el-button>
+					</div>
+				</template>
+			</el-card>
+
+			<!-- <template #footer>
+				<span class="dialog-footer">
+					<el-button @click="closeDialog" type="primary">鍏� 闂�</el-button>
+				</span>
+			</template> -->
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts" setup>
+import { ref, defineModel } from 'vue';
+const listStationsData = defineModel<any>("listStationsData")
+const stationValue = defineModel<any>("stationValue")
+
+const props = defineProps({
+	title: {
+		type: String,
+		default: '',
+	}
+});
+// const emit = defineEmits<{ (e: "update:listStationsData", value: Array<any>): void, (e: "update:stationValue", value): void }>()
+
+// const handlestationChange = () => {
+// 	emit('update:listStationsData', listStationsData.value);
+// 	emit('update:stationValue', stationValue);
+// };
+
+const isShowDialog = ref(false);
+
+const openDialog = async (row: any) => {
+	console.log(listStationsData.value);
+	debugger;
+	isShowDialog.value = true;
+};
+
+const closeDialog = () => {
+	isShowDialog.value = false;
+};
+
+defineExpose({ openDialog });
+</script>
+
+<style>
+.el-col {
+	margin-bottom: 15px;
+}
+
+.card-header {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	color: #fff;
+	padding: 10px;
+	border-radius: 10px 10px 0 0;
+}
+
+.card-footer {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.text {
+	font-size: 14px;
+	color: #fff;
+}
+
+.item {
+	margin-bottom: 18px;
+}
+
+.box-card {
+	width: 100%;
+	background: linear-gradient(135deg, #66ccff, #3399ff);
+	border-radius: 10px;
+	color: #fff;
+}
+
+.dialog-footer {
+	display: flex;
+	justify-content: flex-end;
+	padding: 10px;
+}
+
+.lineStatus {
+    right: 0;
+    height: 20px;
+    width: 20px;
+    border-radius: 50%;
+    background-color: #67C23A;
+}
+
+.device-status-0 {
+    background-color: #67C23A;
+}
+
+.device-status-1 {
+    background-color: red;
+}
+</style>
\ No newline at end of file
diff --git a/Web/src/views/device/deviceMonitor/index.vue b/Web/src/views/device/deviceMonitor/index.vue
index 8865fab..03e945c 100644
--- a/Web/src/views/device/deviceMonitor/index.vue
+++ b/Web/src/views/device/deviceMonitor/index.vue
@@ -11,7 +11,7 @@
                         <el-option v-for="item in lineOptions" :key="item.id" :label="item.text"
                             :value="item.id"></el-option>
                     </el-select>
-                    <el-select v-model="stationValue" placeholder="璇烽�夋嫨" style="margin-top: 10px;"
+                    <el-select v-model="stationValue" placeholder="璇烽�夋嫨" style="margin-top: 10px;" filterable
                         value-key="stationNum">
                         <el-option v-for="item in listStationsData" :key="item.id" :label="item.stationNum"
                             :value="item">
@@ -53,7 +53,7 @@
                     <el-form label-position="left" label-width="80px">
                         <el-form-item>
                             <el-button>鍐欏叆</el-button>
-                            <el-button>璁剧疆</el-button>
+                            <el-button @click="openDialog">璁剧疆</el-button>
                         </el-form-item>
                     </el-form>
                 </div>
@@ -100,13 +100,13 @@
                         <el-form label-position="left">
                             <el-form-item>
                                 <el-button>鍐欏叆</el-button>
-                                <el-button>璁剧疆</el-button>
                             </el-form-item>
                         </el-form>
                     </div>
                 </el-card>
             </div>
         </el-main>
+        <setting ref="settingDialogRef" :title="title" v-model:listStationsData="listStationsData" v-model:stationValue="stationValue" />
     </el-container>
 </template>
 
@@ -116,11 +116,14 @@
 import { getDictDataItem as di, getDictDataList as dl } from '/@/utils/dict-utils';
 import { listWcsPlc } from '/@/api/wcs/wcsPlc';
 
+import setting from '/@/views/device/deviceMonitor/component/setting.vue'
+
 const stations = ref<any>([]);
 const listStationsData = ref<any>([]);
 const listStackingMachineData = ref<any>([]);
 const lineOptions = ref<any>([]);
 const lineValue = ref(1);
+const title = ref<string>('');
 const stationValue = ref<any>({
     taskNo: '',
     taskType: '',
@@ -130,7 +133,11 @@
     wcs: '',
     status: false
 });
-
+const settingDialogRef = ref();
+// 鎵撳紑鎵撳嵃椤甸潰
+const openDialog = async () => {
+    settingDialogRef.value.openDialog(stationValue);
+}
 // 鏌ヨ鎿嶄綔
 const handleQuery = async () => {
     var listplc = await listWcsPlc({ type: 1 });
@@ -146,11 +153,14 @@
         listStationsData.value = stations.value[lineValue.value];
         stationValue.value = listStationsData.value[0];
     }
+    title.value = listStationsData.value[0].text;
 };
+
 handleQuery();
 
 const handleLineChange = (field: string, value: number) => {
     listStationsData.value = stations.value[value];
+    title.value = lineOptions.value.filter(s => s.id == value)[0].text;
     if (listStationsData.value.length > 0)
         stationValue.value = listStationsData.value[0];
 };
@@ -166,6 +176,12 @@
     margin-bottom: 10px;
 }
 
+.el-button {
+    background-color: #fff;
+    border-color: #fff;
+    color: #000000;
+}
+
 .linefix {
     border-bottom: 1px solid rgb(197, 195, 195);
     display: flex;

--
Gitblit v1.8.0