From 1fca2167068e9ef2c079ec742f20313fc6697ab1 Mon Sep 17 00:00:00 2001
From: alielie <alielie@git.com>
Date: 星期一, 03 三月 2025 09:18:33 +0800
Subject: [PATCH] 完善代码;

---
 HMI.SettingControl/SettingControl.xaml.cs            |   49 
 HMI.IOMonitor/IPManageModal.xaml.cs                  |  126 +
 HMI.UI/DpUtil/GridHelper.cs                          |   67 
 WPFProject/Controls/MainTabControl.xaml              |   25 
 HMI.UI/DpUtil/TreeViewHelper.cs                      |   11 
 HMI.DataViewer/DataViewer.xaml                       |  287 ++-
 HMI.Core/Util/MSMQHelper.cs                          |  144 +
 HMI.Base/HMI.Base.csproj                             |   19 
 HMI.IOMonitor/packages.config                        |    2 
 HMI.AlermInfoManage/Properties/Settings.Designer.cs  |   22 
 HMI.Core/Entity/NotifyBase.cs                        |    2 
 HMI.IOMonitor/IOMonitor.xaml                         |  308 ++-
 HMI.MenuManage/MenuManage.xaml.cs                    |   62 
 HMI.MenuManage/RoleManage.xaml                       |    4 
 HMI.Core/Setting/SystemSetting.cs                    |   19 
 WPFProject/LoadingWindow.xaml.cs                     |    8 
 HMI.MenuManage/Modal/RoleModal.xaml                  |    2 
 HMI.AlermInfoManage/AlarmSettingList.xaml.cs         |  215 ++
 HMI.DataViewer/HMI.DataViewer.csproj                 |   14 
 HMI.ParameterManage/ParameterModal.xaml              |    2 
 WPFProject/Utils/MainToastHandler.cs                 |   28 
 HMI.AlermInfoManage/Properties/AssemblyInfo.cs       |    6 
 WPFProject/PanuonWindow.xaml.cs                      |   12 
 HMI.ParameterManage/ParameterManage.xaml             |    4 
 HMI.DataViewer/DataViewer.xaml.cs                    |  196 ++
 HMI.MenuManage/RoleManage.xaml.cs                    |  170 +
 HMI.DataViewer/DbSettingModal.xaml.cs                |  248 +++
 WPFProject/App.config                                |   10 
 HMI.UI/Util/ToastHelper.cs                           |  108 +
 HMI.UnitTest/MainWindow.xaml.cs                      |    2 
 HMI.AlermInfoManage/Entity/AlarmText.cs              |   59 
 HMI.DataViewer/Entity/QueryData.cs                   |   36 
 WPFProject/MainWindow.xaml                           |    2 
 HMI.MenuManage/Model/MenuManageModel.cs              |   10 
 HMI.UI/Style/MsgBoxStyle.xaml                        |    8 
 HMI.IOMonitor/Entity/DIO.cs                          |   61 
 HMI.MenuManage/Model/UserManageModel.cs              |   19 
 HMI.AlermInfoManage/AlarmSettingList.xaml            |  133 +
 HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml     |    4 
 HMI.UI/Util/MsgBoxHelper.cs                          |   43 
 HMI.MenuManage/UserManage.xaml.cs                    |  131 +
 WPFProject/Controls/MinInnerWindow.xaml              |    4 
 HMI.IOMonitor/Entity/IPManage.cs                     |   18 
 HMI.AlermInfoManage/packages.config                  |    2 
 WPFProject/Libs/SQLite.Interop.dll                   |    0 
 HMI.ParameterManage/ProductModal.xaml                |    2 
 HMI.MenuManage/Model/RoleManageModel.cs              |   13 
 HMI.AlermInfoManage/AlarmInfoManage.xaml             |   26 
 HMI.AlermInfoManage/Entity/AimSetting.cs             |    2 
 HMI.Core/Util/XmlHelper.cs                           |   32 
 HMI.Core/HMI.Core.csproj                             |    4 
 HMI.UI/Style/FormStyle.xaml                          |   32 
 WPFProject/WPFProject.csproj                         |   19 
 HMI.IOMonitor/HMI.IOMonitor.csproj                   |   31 
 HMI.UI/Style/PanuonResource.xaml                     |   53 
 WPFProject/PanuonWindow.xaml                         |    8 
 HMI.AlermInfoManage/HMI.AlarmInfoManage.csproj       |   57 
 HMI.DataViewer/Entity/QueryCondition.cs              |   50 
 HMI.DataViewer/DbSettingModal.xaml                   |  113 +
 WPFProject/WPFProject.sln                            |   16 
 HMI.UI/Style/BaseWindow.xaml                         |    2 
 HMI.AlermInfoManage/AlarmInfoManage.xaml.cs          |  405 +++++
 Libs/OpcInterface.dll                                |    0 
 HMI.AlermInfoManage/Model/XmlModel.cs                |   36 
 HMI.DataViewer/Entity/DataBase_Setting.cs            |  106 +
 HMI.UI/DpUtil/StackPanelHelper.cs                    |   40 
 HMI.AlermInfoManage/Properties/Resources.Designer.cs |   19 
 HMI.UI/DpUtil/FormGroupHelper.cs                     |    3 
 HMI.SettingControl/SystemConfig.xaml.cs              |   18 
 HMI.MenuManage/Modal/MenuModal.xaml                  |    2 
 WPFProject/SQLite.Interop.dll                        |    0 
 HMI.Core/Entity/SelectBase.cs                        |   15 
 HMI.Core/Util/HexUtil.cs                             |   16 
 HMI.Core/Util/SqliteHelper.cs                        |    6 
 HMI.IOMonitor/IPManageModal.xaml                     |   40 
 HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml.cs  |  134 +
 WPFProject/TestWindow.xaml                           |    2 
 HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml.cs  |   33 
 HMI.MenuManage/Modal/UserModal.xaml                  |    2 
 HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml     |   47 
 HMI.AlermInfoManage/Model/UIModel.cs                 |   37 
 HMI.MenuManage/MenuManage.xaml                       |    4 
 HMI.MenuManage/UserManage.xaml                       |    4 
 /dev/null                                            |   65 
 HMI.Base/DtConverter.cs                              |   28 
 HMI.UI/Resources/Font/iconfont.ttf                   |    0 
 Libs/SimensDriver.dll                                |    0 
 HMI.UI/Style/WindowResources.xaml                    |   12 
 HMI.AlermInfoManage/Entity/AlarmSetting.cs           |   24 
 HMI.IOMonitor/IOMonitor.xaml.cs                      |  477 +++++
 WPFProject/App.xaml.cs                               |   18 
 HMI.SettingControl/SystemConfig.xaml                 |   19 
 HMI.SettingControl/SettingControl.xaml               |   18 
 HMI.UI/Style/Colors.xaml                             |   22 
 HMI.UI/HMI.UI.csproj                                 |    6 
 95 files changed, 4,167 insertions(+), 653 deletions(-)

diff --git a/HMI.AlermInfoManage/AlermInfoManage.xaml b/HMI.AlermInfoManage/AlarmInfoManage.xaml
similarity index 84%
rename from HMI.AlermInfoManage/AlermInfoManage.xaml
rename to HMI.AlermInfoManage/AlarmInfoManage.xaml
index 7e66085..81ccab8 100644
--- a/HMI.AlermInfoManage/AlermInfoManage.xaml
+++ b/HMI.AlermInfoManage/AlarmInfoManage.xaml
@@ -1,10 +1,10 @@
-锘�<hb:PluginControl x:Class="HMI.AlermInfoManage.AlermInfoManage"
+锘�<hb:PluginControl x:Class="HMI.AlarmInfoManage.AlarmInfoManage"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base"
-             xmlns:local="clr-namespace:HMI.AlermInfoManage"
+             xmlns:local="clr-namespace:HMI.AlarmInfoManage"
              xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI"
              xmlns:pw="https://opensource.panuon.com/wpf"
              xmlns:pu="https://opensource.panuon.com/wpf-ui"
@@ -29,18 +29,24 @@
     <Border Style="{StaticResource CardBoarder}">
         <StackPanel>
             <DockPanel Margin="0,0,0,10">
-                <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe934;" Style="{StaticResource DangerButton}">鍒犻櫎</Button>
-                <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
-pu:IconHelper.FontFamily="{StaticResource iconfont}"
-pu:ButtonHelper.Icon="&#xe631;" Margin="0,0,10,0" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
-                <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
-            pu:IconHelper.FontFamily="{StaticResource iconfont}"
-            pu:ButtonHelper.Icon="&#xe61a;" Margin="0,0,10,0" x:Name="addBtn" Click="Button_Click">鏂板</Button>
+                <StackPanel DockPanel.Dock="Right" Style="{StaticResource ButtonGroup}">
+                    <Button Style="{StaticResource PrimaryButton}"
+pu:ButtonHelper.Icon="&#xe94d;" x:Name="settingBtn" Click="Button_Click">璁剧疆</Button>
+                    <Button Style="{StaticResource PrimaryButton}" 
+pu:ButtonHelper.Icon="&#xe631;" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
+                    <Button Style="{StaticResource PrimaryButton}"
+pu:ButtonHelper.Icon="&#xe639;" x:Name="importBtn" Click="Button_Click">瀵煎叆</Button>
+                </StackPanel>
+                <!--<Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe934;" 
+                        Style="{StaticResource DangerButton}">鍒犻櫎</Button>-->
+                
+                
+                
                 <TextBlock DockPanel.Dock="Left" FontSize="{StaticResource TitleFontSize}" 
                            VerticalAlignment="Center" HorizontalAlignment="Left" Text="鎶ヨ淇℃伅鍒楄〃"/>
             </DockPanel>
 
-            <DataGrid x:Name="table" Style="{StaticResource DefaultDataGrid}" ItemsSource="{Binding DataSource}">
+            <DataGrid x:Name="table" Style="{StaticResource DefaultDataGrid}" ItemsSource="{Binding Datasource}">
                 <DataGrid.Columns>
                     <DataGridTemplateColumn Header="" Width="Auto" CanUserResize="False">
                         <DataGridTemplateColumn.CellTemplate>
diff --git a/HMI.AlermInfoManage/AlarmInfoManage.xaml.cs b/HMI.AlermInfoManage/AlarmInfoManage.xaml.cs
new file mode 100644
index 0000000..a2cbbc5
--- /dev/null
+++ b/HMI.AlermInfoManage/AlarmInfoManage.xaml.cs
@@ -0,0 +1,405 @@
+锘縰sing HMI.AlarmInfoManage.Entity;
+using HMI.AlarmInfoManage.Model;
+using HMI.Base;
+using HMI.Core.Setting;
+using HMI.Core.Util;
+using HMI.UI.Util;
+using Microsoft.Win32;
+using NPOI.SS.Formula.Functions;
+using NPOI.XSSF.UserModel;
+using Sharp7;
+using SimensDriver;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Timers;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace HMI.AlarmInfoManage
+{
+    /// <summary>
+    /// UserControl1.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class AlarmInfoManage : PluginControl
+    {
+        private string blockPath;
+        private string markPath;
+        private string textSettingPath;
+        private Simens plc = new Simens();
+        private XmlUIModel Model;
+
+        private bool isHaveAlarm;
+        private bool isNewAlarm;
+
+        private SqliteHelper sqliteHelper;
+
+        private Timer MonitorTimer;
+        private Timer PcTimer;
+
+        /// <summary>
+        /// pc璀﹀憡鏁板瓧淇″彿
+        /// </summary>
+        private int isPcAlarmnumber = 0;
+
+        /// <summary>
+        /// 褰撳墠鎶ヨ淇℃伅
+        /// </summary>
+        private string currentInfo = null;
+
+        /// <summary>
+        /// 鎺ユ敹鎶ヨ鐨勯槦鍒�
+        /// </summary>
+        private MSMQHelper alarmQueue = new MSMQHelper("LTHMI_Alarm");
+        /// <summary>
+        /// 鏃ュ織鐢熸垚鍣�
+        /// </summary>
+        private MSMQHelper loggeralarm = new MSMQHelper("LTHMI_Logger");
+        /// <summary>
+        /// 鍒锋柊鎶ヨ鐨勯槦鍒�
+        /// </summary>
+        private MSMQHelper alarmRefershToMain = new MSMQHelper("LTHMI_Alarm_Rrfresh");
+
+        /// <summary>
+        /// 鎶ヨ
+        /// </summary>
+        private byte[] alarmCodeBytes;
+        /// <summary>
+        /// 鎶ヨ淇℃伅缂撳瓨
+        /// </summary>
+        private List<AlarmText> currentAlarmCachePlc = new List<AlarmText>();
+        /// <summary>
+        /// PLC鎶ヨ淇℃伅缂撳瓨
+        /// </summary>
+        private List<AlarmText> preAlarmCachePlc = new List<AlarmText>();
+        /// <summary>
+        /// 鎶ヨ淇℃伅缂撳瓨
+        /// </summary>
+        private List<AlarmText> currentAlarmCachePc = new List<AlarmText>();
+
+        /// <summary>
+        /// 浠g爜绠$悊
+        /// </summary>
+        private List<AlarmSetting> alarmSettings = new List<AlarmSetting>();
+        // <summary>
+        /// 鏍囧織浣嶆姤璀︾鐞�
+        /// </summary>
+        private List<AlarmSetting> signAlarmSetting = new List<AlarmSetting>();
+        /// <summary>
+        /// 鎶ヨ鏂囨湰鍒楄〃
+        /// </summary>
+        private List<AlarmText> alarmTexts = new List<AlarmText>();
+        /// <summary>
+        /// 浼犺嚦涓荤獥浣撶殑鎶ヨ淇℃伅
+        /// </summary>
+        private List<AlarmText> currentAlarmCachePlcToMain = new List<AlarmText>();
+
+        private AlarmText alarm;
+        private SystemSetting systemSetting;
+
+
+        public AlarmInfoManage()
+        {
+            systemSetting = SystemSetting.Instance;
+            InitializeComponent();
+        }
+
+        public override void InitFinish()
+        {
+            Model = new XmlUIModel(BaseFolder);
+            DataContext = Model;
+        }
+
+        private void Button_Click(object sender, RoutedEventArgs e)
+        {
+            Button btn = sender as Button;
+            switch (btn.Name)
+            {
+                case "settingBtn":
+                    OpenSettingWindow();
+                    break;
+                case "importBtn":
+                    ImportText();
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        private void OpenSettingWindow()
+        {
+            AlarmSettingList listModal = new AlarmSettingList(blockPath, markPath, log)
+            {
+                Owner = Window.GetWindow(this)
+            };
+            listModal.ShowDialog();
+        }
+
+        private void ImportText()
+        {
+            try
+            {
+                OpenFileDialog openDialog = new OpenFileDialog();
+                openDialog.Filter = "Files (*.xlsm)|*.xlsm";
+                if (openDialog.ShowDialog() == true)
+                {
+                    this.ImportExcelAlarmText(openDialog.FileName);
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("AlarmText Import Failed.", ex);
+                ToastHelper.Error(Window.GetWindow(this), $"瀵煎叆澶辫触锛亄ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 瀵煎叆鎶ヨ浠g爜鏂囨湰
+        /// </summary>
+        /// <param name="excelFile">鐢靛瓙璁捐琛ㄦ牸鏂囦欢</param>
+        private void ImportExcelAlarmText(string excelFile)
+        {
+            int index = 0;
+
+            try
+            {
+                if (excelFile.IndexOf(".xlsm") < 0)
+                {
+                    this.Warning("浠呮敮鎸亁lsm鏍煎紡鏂囦欢");
+                    return;
+                }
+
+                this.alarmTexts.Clear();
+                XSSFWorkbook workbook = new XSSFWorkbook(excelFile);
+                XSSFSheet sheet = (XSSFSheet)workbook.GetSheet("sheet1");
+                XSSFRow row = null;
+
+                for (int i = 2; i < (sheet.LastRowNum + 1); i++)
+                {
+                    index = i;
+                    row = (XSSFRow)sheet.GetRow(i);
+                    if (row != null)
+                    {
+                        AlarmText alarm = new AlarmText();
+                        alarm.AlarmCode = row.Cells[0].StringCellValue;
+                        alarm.OpNo = row.Cells[1].StringCellValue;
+                        alarm.ModuleNo = row.Cells[2].StringCellValue;
+                        alarm.ModuleName_CN = row.Cells[3].StringCellValue;
+                        alarm.ModuleName_EN = row.Cells[4].StringCellValue;
+                        alarm.MAlarmCode = row.Cells[5].StringCellValue;
+                        alarm.MAlarmText_CN = row.Cells[6].StringCellValue;
+                        alarm.MAlarmText_EN = row.Cells[7].StringCellValue;
+                        this.alarmTexts.Add(alarm);
+                    }
+                }
+
+                if (sheet.LastRowNum > 0)
+                {
+                    XmlHelper.SerializeToXml(textSettingPath, this.alarmTexts);
+                }
+
+                this.Success("瀵煎叆鎴愬姛");
+            }
+            catch (Exception ex)
+            {
+                log.Error($"Row {index} AlarmText Import Failed.", ex);
+                this.Error($"绗瑊index}琛屽鍏ュ紓甯革紒{ex.Message}");
+            }
+        }
+
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            if (!string.IsNullOrEmpty(systemSetting.PlcIp))
+            {
+                if (this.plc.isConnection)
+                {
+                    this.plc.Simens_S7_ConnectPLC(systemSetting.PlcIp, 102, 0, 1, string.Empty);
+                }
+            }
+            MonitorTimer = new Timer
+            {
+                Interval = 100,
+            };
+            MonitorTimer.Elapsed += MonitorTimer_Elapsed;
+
+            PcTimer = new Timer
+            {
+                Interval = 100,
+            };
+            PcTimer.Elapsed += PcTimer_Elapsed; ;
+
+            Loaded -= UserControl_Loaded;
+        }
+
+        private void PcTimer_Elapsed(object sender, ElapsedEventArgs e)
+        {
+            try
+            {
+                PcTimer.Enabled = false;
+                this.alarmQueue.Receive(100, out string MessageID, out string MsgStr);
+                if (MessageID != string.Empty)
+                {
+                    log.Info(MsgStr);
+                    switch (MessageID)
+                    {
+                        case "Clear":
+                            ////this.currentAlarmCachePc.RemoveAll(alarm => alarm.Source == "PC");
+                            this.currentAlarmCachePc.Clear();
+                            this.RefershAlarm();
+                            break;
+                        default:
+                            AlarmText aalarm = this.alarmTexts.Find(alarm => alarm.AlarmCode == MsgStr);
+                            aalarm.Source = "PC";
+                            aalarm.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+                            if ((aalarm != null) && (this.currentAlarmCachePc.Find(alarm => alarm.AlarmCode == aalarm.AlarmCode) == null))
+                            {
+                                this.currentAlarmCachePc.Add(aalarm);
+                                this.RefershAlarm();
+                                this.isPcAlarmnumber = this.currentAlarmCachePc.Count;
+                            }
+
+                            break;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("PcTimer Execute Failed", ex);
+            }
+            finally
+            {
+                PcTimer.Enabled = true;
+            }
+        }
+
+        private void MonitorTimer_Elapsed(object sender, ElapsedEventArgs e)
+        {
+            try
+            {
+                this.MonitorTimer.Enabled = false;
+                isHaveAlarm = false;
+                foreach (var item in signAlarmSetting)
+                {
+                    isHaveAlarm = isHaveAlarm ||
+                        this.plc.Simens_S7_ReadBool_DB(item.DBAddress, item.StartAddress, item.Length);
+                }
+
+                ////鏈夋姤璀�
+                if (isHaveAlarm)
+                {
+                    this.isNewAlarm = false;
+                    this.currentAlarmCachePlc.Clear();
+                    RefreshDBSetting();
+                    for (int i = 0; i < ((int)alarmCodeBytes.Length / 4); i++)
+                    {
+                        int code = S7.GetDIntAt(alarmCodeBytes, 4 * i);
+                        ////鏈夋姤璀�
+                        if (code != 0)
+                        {
+                            string acode = string.Format("{0:d10}", code);
+                            alarm = this.alarmTexts.Find(item => item.AlarmCode == acode);
+                            if (alarm != null)
+                            {
+                                alarm.Source = "PLC";
+                                alarm.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+                                this.currentAlarmCachePlc.Add(alarm);
+                                ////鏈夋柊鎶ヨ
+                                if (this.preAlarmCachePlc.Find(alarm => alarm.AlarmCode == acode) == null)
+                                {
+                                    this.isNewAlarm = true;
+                                    this.SendLogMsg(alarm.ModuleName_CN + alarm.MAlarmText_CN);
+                                }
+                            }
+                        }
+                    }
+
+                    ////鏈夋柊鎶ヨ鍜屾姤璀﹀噺灏戞椂鍒锋柊鎶ヨ琛�
+                    if (this.isNewAlarm || (this.currentAlarmCachePlc.Count != this.preAlarmCachePlc.Count))
+                    {
+                        this.currentAlarmCachePlcToMain = XmlHelper.DeepClone(this.currentAlarmCachePlc);
+                        this.RefershAlarm();
+                    }
+
+                    this.preAlarmCachePlc.Clear();
+                    this.preAlarmCachePlc = XmlHelper.DeepClone(this.currentAlarmCachePlc);
+                }
+                else
+                {
+                    if (this.preAlarmCachePlc.Count != 0 || this.currentAlarmCachePlcToMain.Count != 0 || this.currentAlarmCachePlc.Count != 0)
+                    {
+                        this.preAlarmCachePlc.Clear();
+                        this.currentAlarmCachePlcToMain.Clear();
+                        this.currentAlarmCachePlc.Clear();
+                        this.RefershAlarm();
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("sdadsa", ex);
+            }
+            finally
+            {
+                this.MonitorTimer.Enabled = true;
+            }
+        }
+
+        /// <summary>
+        /// 鍒锋柊鎶ヨ鍧椾俊鎭�
+        /// </summary>
+        private void RefreshDBSetting()
+        {
+            List<byte> bytes = new List<byte>();
+            foreach (var item in alarmSettings)
+            {
+                byte[] itemalarmCodeBytes = this.plc.Simens_S7_ReadBytes_DB("DB", item.DBAddress, item.StartAddress, item.Length);
+                bytes.AddRange(itemalarmCodeBytes.ToList());
+            }
+            alarmCodeBytes = bytes.ToArray();
+        }
+
+        /// <summary>
+        /// 鍒锋柊鎶ヨ淇℃伅
+        /// </summary>
+        private void RefershAlarm()
+        {
+            this.alarmRefershToMain.Send("AlarmRefersh", string.Empty);
+
+            foreach (AlarmText alarm in this.currentAlarmCachePlc)
+            {
+                this.currentInfo = alarm.ModuleName_CN + alarm.MAlarmText_CN;
+                Model.Datasource.Add(alarm);
+                string sqladd = string.Format("INSERT INTO Alarm (source, alarmcode, alarminfo, time) VALUES( '{0}','{1}','{2}','{3}');",
+                    alarm.Source, alarm.AlarmCode, this.currentInfo, alarm.Time);
+                sqliteHelper.ExecuteSql(sqladd);
+            }
+
+            foreach (AlarmText alarm in this.currentAlarmCachePc)
+            {
+
+                Model.Datasource.Add(alarm);
+                string sqladd2 = string.Format("INSERT INTO Alarm (source, alarmcode, alarminfo, time) VALUES( '{0}','{1}','{2}','{3}');", alarm.Source, alarm.AlarmCode, this.currentInfo, alarm.Time);
+                this.sqliteHelper.ExecuteSql(sqladd2);
+            }
+        }
+
+        /// <summary>
+        /// 鍙戦�佹棩蹇楁秷鎭�
+        /// </summary>
+        /// <param name="Msg">鏃ュ織娑堟伅</param>
+        private void SendLogMsg(string Msg)
+        {
+            string LogMsg = "{\"Type\":\"Alarm\",\"Source\":\"" + alarm.Source + "\",\"Msg\":\"" + Msg + "\",\"Time\":\"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}";
+            this.loggeralarm.Send("Log", LogMsg);
+        }
+
+        public override void SetBaseFolder(string folder)
+        {
+            base.SetBaseFolder(folder);
+            blockPath = Path.Combine(BaseFolder, "BlockSetting.xml");
+            markPath = Path.Combine(BaseFolder, "MarkSetting.xml");
+            textSettingPath = Path.Combine(BaseFolder, "textSetting.xml");
+        }
+    }
+}
diff --git a/HMI.AlermInfoManage/AlermInfoManage_Setting.xaml b/HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml
similarity index 90%
rename from HMI.AlermInfoManage/AlermInfoManage_Setting.xaml
rename to HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml
index c468c29..611a9c1 100644
--- a/HMI.AlermInfoManage/AlermInfoManage_Setting.xaml
+++ b/HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml
@@ -1,9 +1,9 @@
-锘�<UserControl x:Class="HMI.AlermInfoManage.AlermInfoManage_Setting"
+锘�<UserControl x:Class="HMI.AlarmInfoManage.AlarmInfoManage_Setting"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
-             xmlns:local="clr-namespace:HMI.AlermInfoManage"
+             xmlns:local="clr-namespace:HMI.AlarmInfoManage"
             xmlns:pw="https://opensource.panuon.com/wpf"
             xmlns:pu="https://opensource.panuon.com/wpf-ui"
              Loaded="UserControl_Loaded"
diff --git a/HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml.cs b/HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml.cs
new file mode 100644
index 0000000..0baf7dd
--- /dev/null
+++ b/HMI.AlermInfoManage/AlarmInfoManage_Setting.xaml.cs
@@ -0,0 +1,33 @@
+锘縰sing HMI.AlarmInfoManage.Entity;
+using HMI.Core.Util;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace HMI.AlarmInfoManage
+{
+    /// <summary>
+    /// AlarmInfoManage_Setting.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class AlarmInfoManage_Setting : UserControl
+    {
+        public AlarmInfoManage_Setting()
+        {
+            InitializeComponent();
+        }
+
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            DataContext = AimSetting.Instance.GetModel();
+        }
+
+        private void Button_Click(object sender, RoutedEventArgs e)
+        {
+            AimSettingModel model = (AimSettingModel)DataContext;
+
+            AimSetting newSetting = AimSetting.FromModel(model);
+
+            XmlHelper.SerializeToXml(PathHelper.ConfigFolder + "\\AimSetting.xml", model);
+
+        }
+    }
+}
diff --git a/HMI.AlermInfoManage/AlarmSettingList.xaml b/HMI.AlermInfoManage/AlarmSettingList.xaml
new file mode 100644
index 0000000..fcc2bf0
--- /dev/null
+++ b/HMI.AlermInfoManage/AlarmSettingList.xaml
@@ -0,0 +1,133 @@
+锘�<pu:WindowX x:Class="HMI.AlarmInfoManage.AlarmSettingList"
+            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+            xmlns:local="clr-namespace:HMI.AlarmInfoManage"
+            xmlns:pw="https://opensource.panuon.com/wpf"
+            xmlns:pu="https://opensource.panuon.com/wpf-ui"
+            xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI"
+            xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI"
+            mc:Ignorable="d"
+            Title="{Binding SelectedValue,Mode=OneWay}"
+            SizeToContent="Height"
+            Width="800"
+            Height="600"
+            BorderBrush="#3E3E45"
+            BorderThickness="1"
+            Foreground="Black"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
+            pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
+            pu:WindowXCaption.Foreground="#FFF"
+            pu:WindowXModalDialog.Buttons="OK"
+            pu:WindowXModalDialog.OKButtonContent="鍏抽棴"
+            Loaded="WindowX_Loaded"
+            WindowStartupLocation="CenterScreen"
+            pu:WindowXModalDialog.ButtonPanelMargin="0,30,10,10">
+    <Window.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <pu:StyleDictionary Includes="TabControl"/>
+                <ResourceDictionary Source="/HMI.UI;component/Resources/Font/Font.xaml"/>
+                <ResourceDictionary Source="/HMI.UI;component/Style/Colors.xaml"/>
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
+    </Window.Resources>
+
+    <Grid Margin="10">
+        <Border BorderThickness="1" BorderBrush="Gray">
+            <Grid>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="Auto"/>
+                    <RowDefinition Height="Auto"/>
+                    <RowDefinition />
+                </Grid.RowDefinitions>
+
+                <ListBox ItemsSource="{Binding Items}" SelectedValue="{Binding SelectedValue}" BorderThickness="0">
+                    <ListBox.ItemsPanel>
+                        <ItemsPanelTemplate>
+                            <StackPanel Orientation="Horizontal"/>
+                        </ItemsPanelTemplate>
+                    </ListBox.ItemsPanel>
+                    <ListBox.ItemContainerStyle>
+                        <Style TargetType="ListBoxItem">
+                            <Setter Property="Margin" Value="0"/>
+                            <Setter Property="Padding" Value="0"/>
+                            <Setter Property="Template">
+                                <Setter.Value>
+                                    <ControlTemplate TargetType="ListBoxItem">
+                                        <Border x:Name="border" Background="LightGray" 
+Padding="10" Margin="0" BorderThickness="0">
+                                            <!-- 鍐呭鍛堢幇鍣� -->
+                                            <StackPanel>
+                                                <ContentPresenter  Content="{TemplateBinding Content}" 
+                   ContentStringFormat="{TemplateBinding ContentStringFormat}" 
+                   ContentTemplate="{TemplateBinding ContentTemplate}"  />
+                                            </StackPanel>
+                                        </Border>
+
+                                        <ControlTemplate.Triggers>
+                                            <Trigger Property="IsSelected" Value="True">
+                                                <Setter TargetName="border" Property="Background" Value="White"/>
+                                            </Trigger>
+                                        </ControlTemplate.Triggers>
+                                    </ControlTemplate>
+                                </Setter.Value>
+                            </Setter>
+                        </Style>
+                    </ListBox.ItemContainerStyle>
+                </ListBox>
+
+                <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" 
+                            Margin="0,0,0,10"
+                                    dp:StackPanelHelper.ChildSpace="10">
+                    <Button Style="{StaticResource PrimaryButton}" pu:ButtonHelper.Icon="&#xe631;" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
+                    <Button Style="{StaticResource PrimaryButton}" pu:ButtonHelper.Icon="&#xe631;" x:Name="addBtn" Click="Button_Click">鏂板</Button>
+                    <Button Style="{StaticResource DangerButton}" pu:ButtonHelper.Icon="&#xe631;" x:Name="delBatchBtn" Click="Button_Click">鍒犻櫎</Button>
+                </StackPanel>
+
+                <DataGrid x:Name="table" Grid.Row="2"
+         Style="{StaticResource DefaultDataGrid}" ItemsSource="{Binding Datasource}">
+                    <DataGrid.Columns>
+                        <DataGridTemplateColumn Header="" Width="Auto" CanUserResize="False">
+                            <DataGridTemplateColumn.CellTemplate>
+                                <DataTemplate>
+                                    <CheckBox VerticalAlignment="Center" 
+                                              IsChecked="{Binding IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
+                                </DataTemplate>
+                            </DataGridTemplateColumn.CellTemplate>
+                        </DataGridTemplateColumn>
+                        <DataGridTemplateColumn Header="#" CanUserResize="False">
+                            <DataGridTemplateColumn.CellTemplate>
+                                <DataTemplate>
+                                    <TextBlock Text="{Binding Converter={StaticResource rowNumber},
+RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
+                                </DataTemplate>
+                            </DataGridTemplateColumn.CellTemplate>
+                        </DataGridTemplateColumn>
+                        <DataGridTextColumn Width="*" Binding="{Binding DBAddress}" Header="DB鍦板潃" />
+                        <DataGridTextColumn Width="*" Binding="{Binding StartAddress}" Header="璧峰鍦板潃" />
+                        <DataGridTextColumn Width="*" Binding="{Binding Length}" Header="DB闀垮害" />
+                        <DataGridTemplateColumn Header="鎿嶄綔" Width="100" IsReadOnly="True" CanUserResize="False">
+                            <DataGridTemplateColumn.CellTemplate>
+                                <DataTemplate>
+                                    <StackPanel Orientation="Horizontal">
+                                        <Button x:Name="editBtn" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}" 
+                                                Style="{StaticResource RowLink}" 
+        Margin="0,0,10,0" 
+        Click="Button_Click"
+        DataContext="{Binding }">缂栬緫</Button>
+                                        <Button x:Name="delBtn" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}" 
+                                                Style="{StaticResource DangerLinkButton}" 
+        DataContext="{Binding }"
+        Click="Button_Click">鍒犻櫎</Button>
+                                    </StackPanel>
+                                </DataTemplate>
+                            </DataGridTemplateColumn.CellTemplate>
+                        </DataGridTemplateColumn>
+                    </DataGrid.Columns>
+                </DataGrid>
+            </Grid>
+        </Border>
+    </Grid>
+</pu:WindowX>
diff --git a/HMI.AlermInfoManage/AlarmSettingList.xaml.cs b/HMI.AlermInfoManage/AlarmSettingList.xaml.cs
new file mode 100644
index 0000000..04a2a06
--- /dev/null
+++ b/HMI.AlermInfoManage/AlarmSettingList.xaml.cs
@@ -0,0 +1,215 @@
+锘縰sing HMI.AlarmInfoManage.Entity;
+using HMI.Core.Util;
+using HMI.UI.Util;
+using log4net;
+using Panuon.WPF.UI;
+using System;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace HMI.AlarmInfoManage
+{
+    /// <summary>
+    /// AlarmSettingList.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class AlarmSettingList : WindowX
+    {
+        private ILog log;
+        public AlarmSettingList(string blockFile, string markFile, ILog log)
+        {
+            this.blockFile = blockFile;
+            this.markFile = markFile;
+            this.log = log;
+            DataContext = this;
+            InitializeComponent();
+        }
+
+        private readonly string blockFile;
+        private readonly string markFile;
+
+        private ObservableCollection<AlarmSetting> datasource;
+
+        public ObservableCollection<AlarmSetting> Datasource
+        {
+            get => datasource;
+            set { Set(ref datasource, value); }
+        }
+
+        private ObservableCollection<AlarmSetting> markDatasource;
+
+        public ObservableCollection<AlarmSetting> MarkDatasource
+        {
+            get => markDatasource;
+            set { Set(ref markDatasource, value); }
+        }
+
+        private ObservableCollection<string> items =
+            new ObservableCollection<string> { "DB鍧楁姤璀�", "鏍囧織浣嶆姤璀�" };
+
+        public ObservableCollection<string> Items
+        {
+            get => items;
+            set { Set(ref items, value); }
+        }
+
+        private string selectedValue;
+
+        public string SelectedValue
+        {
+            get { return selectedValue; }
+            set
+            {
+                Set(ref selectedValue, value);
+                LoadData();
+            }
+        }
+
+        private void Button_Click(object sender, RoutedEventArgs e)
+        {
+            Button btn = sender as Button;
+            DataGridRow row = btn?.Tag as DataGridRow;
+            switch (btn.Name)
+            {
+                case "refreshBtn":
+                    LoadData();
+                    break;
+                case "addBtn":
+                    AddData(new AlarmSetting());
+                    break;
+                case "delBatchBtn":
+                    DeleteBatchData();
+                    break;
+                case "editBtn":
+                    EditData(row.GetIndex(), btn.DataContext as AlarmSetting);
+                    break;
+                case "delBtn":
+                    DeleteData(row.GetIndex());
+                    break;
+                default:
+                    break;
+            }
+
+        }
+
+        private void LoadData()
+        {
+            try
+            {
+                ObservableCollection<AlarmSetting> datasource = new ObservableCollection<AlarmSetting>();
+                if (SelectedValue == "DB鍧楁姤璀�" && File.Exists(blockFile))
+                {
+                    datasource =
+                        XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(blockFile);
+                }
+                else if (SelectedValue == "鏍囧織浣嶆姤璀�" && File.Exists(markFile))
+                {
+                    datasource =
+                        XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(markFile);
+                }
+                Datasource = datasource;
+            }
+            catch (Exception ex)
+            {
+                ToastHelper.Error(this, $"鍔犺浇閿欒锛亄ex.Message}");
+            }
+        }
+
+        private void AddData(AlarmSetting data)
+        {
+            try
+            {
+                var file = SelectedValue == "DB鍧楁姤璀�" ? blockFile : markFile;
+                var modal = new AlarmSettingModal(log)
+                {
+                    Title = $"鏂板{SelectedValue}",
+                    Owner = Window.GetWindow(this),
+                };
+                if (modal.Open(-1, data, Datasource, file) == true)
+                {
+                    LoadData();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Add AlarmSetting Failed.", ex);
+                ToastHelper.Error(this, $"鏂板澶辫触锛亄ex.Message}");
+            }
+        }
+
+        private void EditData(int index, AlarmSetting data)
+        {
+            try
+            {
+                var file = SelectedValue == "DB鍧楁姤璀�" ? blockFile : markFile;
+                var modal = new AlarmSettingModal(log)
+                {
+                    Title = $"缂栬緫{SelectedValue}",
+                    Owner = Window.GetWindow(this),
+                };
+                if (modal.Open(index, data, Datasource, file) == true)
+                {
+                    LoadData();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Edit AlarmSetting Failed.", ex);
+                ToastHelper.Error(this, $"缂栬緫澶辫触锛亄ex.Message}");
+            }
+        }
+        private void DeleteData(int index)
+        {
+            try
+            {
+                if (MsgBoxHelper.WarnMessage(Window.GetWindow(this), "纭畾瑕佸垹闄よ椤瑰悧锛熻鎿嶄綔涓嶅彲閫�") == MessageBoxResult.OK)
+                {
+                    var file = SelectedValue == "DB鍧楁姤璀�" ? blockFile : markFile;
+                    var temp = XmlHelper.DeepClone(Datasource);
+
+                    temp.RemoveAt(index);
+                    XmlHelper.SerializeToXml(file, temp);
+                    LoadData();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Delete AlarmSetting Failed.", ex);
+                ToastHelper.Error(this, $"鍒犻櫎澶辫触锛亄ex.Message}");
+            }
+        }
+        private void DeleteBatchData()
+        {
+            try
+            {
+                var temp = Datasource.Where(e => e.IsSelected).ToList();
+                if (temp == null || temp.Count <= 0)
+                {
+                    ToastHelper.Warning(Window.GetWindow(this), "璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
+                    return;
+                }
+
+                if (MsgBoxHelper.WarnMessage(Window.GetWindow(this), $"纭畾瑕佸垹闄temp.Count}椤规暟鎹悧锛熻鎿嶄綔涓嶅彲閫�") == MessageBoxResult.OK)
+                {
+                    var file = SelectedValue == "DB鍧楁姤璀�" ? blockFile : markFile;
+                    temp = Datasource.Where(e => !e.IsSelected).ToList();
+                    XmlHelper.SerializeToXml(file, temp);
+                    LoadData();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Delete Batch AlarmSetting Failed.", ex);
+                ToastHelper.Error(this, $"鍒犻櫎澶辫触锛亄ex.Message}");
+            }
+        }
+
+        private void WindowX_Loaded(object sender, RoutedEventArgs e)
+        {
+            SelectedValue = "DB鍧楁姤璀�";
+            Loaded -= WindowX_Loaded;
+        }
+    }
+}
diff --git a/HMI.AlermInfoManage/AlermInfoManage.xaml.cs b/HMI.AlermInfoManage/AlermInfoManage.xaml.cs
deleted file mode 100644
index 7656b46..0000000
--- a/HMI.AlermInfoManage/AlermInfoManage.xaml.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-锘縰sing System.Windows;
-using HMI.Base;
-
-namespace HMI.AlermInfoManage
-{
-    /// <summary>
-    /// UserControl1.xaml 鐨勪氦浜掗�昏緫
-    /// </summary>
-    public partial class AlermInfoManage : PluginControl
-    {
-
-        public AlermInfoManage()
-        {
-            InitializeComponent();
-        }
-
-        private void Button_Click(object sender, RoutedEventArgs e)
-        {
-
-        }
-
-        private void UserControl_Loaded(object sender, RoutedEventArgs e)
-        {
-
-        }
-    }
-}
diff --git a/HMI.AlermInfoManage/AlermInfoManage_Setting.xaml.cs b/HMI.AlermInfoManage/AlermInfoManage_Setting.xaml.cs
deleted file mode 100644
index 358cea4..0000000
--- a/HMI.AlermInfoManage/AlermInfoManage_Setting.xaml.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-锘縰sing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-using HMI.AlermInfoManage.Entity;
-using HMI.Core.Util;
-
-namespace HMI.AlermInfoManage
-{
-    /// <summary>
-    /// AlermInfoManage_Setting.xaml 鐨勪氦浜掗�昏緫
-    /// </summary>
-    public partial class AlermInfoManage_Setting : UserControl
-    {
-        public AlermInfoManage_Setting()
-        {
-            InitializeComponent();
-        }
-
-        private void UserControl_Loaded(object sender, RoutedEventArgs e)
-        {
-            DataContext = AimSetting.Instance.GetModel();
-        }
-
-        private void Button_Click(object sender, RoutedEventArgs e)
-        {
-            AimSettingModel model = (AimSettingModel)DataContext;
-
-            AimSetting newSetting = AimSetting.FromModel(model);
-
-            XmlHelper.SerializeToXml(PathHelper.ConfigFolder + "\\AimSetting.xml", model);
-
-        }
-    }
-}
diff --git a/HMI.AlermInfoManage/Entity/AimSetting.cs b/HMI.AlermInfoManage/Entity/AimSetting.cs
index 5ae2606..c9ab22a 100644
--- a/HMI.AlermInfoManage/Entity/AimSetting.cs
+++ b/HMI.AlermInfoManage/Entity/AimSetting.cs
@@ -1,7 +1,7 @@
 锘縰sing HMI.Core.Entity;
 using HMI.Core.Util;
 
-namespace HMI.AlermInfoManage.Entity
+namespace HMI.AlarmInfoManage.Entity
 {
     public class AimSetting
     {
diff --git a/HMI.AlermInfoManage/Entity/AlarmSetting.cs b/HMI.AlermInfoManage/Entity/AlarmSetting.cs
new file mode 100644
index 0000000..d612d6a
--- /dev/null
+++ b/HMI.AlermInfoManage/Entity/AlarmSetting.cs
@@ -0,0 +1,24 @@
+锘縰sing HMI.Core.Entity;
+
+namespace HMI.AlarmInfoManage.Entity
+{
+    public class AlarmSetting : SelectBase
+    {
+        public static readonly string BLOCK_TYPE = "BLOCK";
+        public static readonly string MARK_TYPE = "MARK";
+        /// <summary>
+        /// 寮�濮婦B鍦板潃
+        /// </summary>
+        public int DBAddress { get; set; }
+
+        /// <summary>
+        /// 璧峰Byte浣�
+        /// </summary>
+        public int StartAddress { get; set; }
+
+        /// <summary>
+        /// 闀垮害
+        /// </summary>
+        public int Length { get; set; }
+    }
+}
diff --git a/HMI.AlermInfoManage/Entity/AlarmText.cs b/HMI.AlermInfoManage/Entity/AlarmText.cs
new file mode 100644
index 0000000..e431b70
--- /dev/null
+++ b/HMI.AlermInfoManage/Entity/AlarmText.cs
@@ -0,0 +1,59 @@
+锘縰sing System.Xml.Serialization;
+
+namespace HMI.AlarmInfoManage.Entity
+{
+    public class AlarmText
+    {
+        /// <summary>
+        /// 鎶ヨ浠g爜
+        /// </summary>
+        public string AlarmCode { get; set; }
+
+        /// <summary>
+        /// 宸ヤ綅缂栧彿
+        /// </summary>
+        public string OpNo { get; set; }
+
+        /// <summary>
+        /// 妯″潡缂栧彿
+        /// </summary>
+        public string ModuleNo { get; set; }
+
+        /// <summary>
+        /// 妯″潡鍚嶇О(CN)
+        /// </summary>
+        public string ModuleName_CN { get; set; }
+
+        /// <summary>
+        /// 妯″潡鍚嶇О(EN)
+        /// </summary>
+        public string ModuleName_EN { get; set; }
+
+
+        /// <summary>
+        /// 妯″潡鎶ヨ浠g爜
+        /// </summary>
+        public string MAlarmCode { get; set; }
+
+        /// <summary>
+        /// 妯″潡鎶ヨ鏂囨湰(CN)
+        /// </summary>
+        public string MAlarmText_CN { get; set; }
+
+        /// <summary>
+        /// 妯″潡鎶ヨ鏂囨湰(EN)
+        /// </summary>
+        public string MAlarmText_EN { get; set; }
+
+        /// <summary>
+        /// 鎶ヨ鏃堕棿
+        /// </summary>
+        public string Time { get; set; }
+
+        /// <summary>
+        /// 鎶ヨ鏉ユ簮
+        /// </summary> 
+        [XmlIgnore]
+        public string Source { get; set; }
+    }
+}
diff --git a/HMI.AlermInfoManage/HMI.AlermInfoManage.csproj b/HMI.AlermInfoManage/HMI.AlarmInfoManage.csproj
similarity index 66%
rename from HMI.AlermInfoManage/HMI.AlermInfoManage.csproj
rename to HMI.AlermInfoManage/HMI.AlarmInfoManage.csproj
index ad1dded..01f1a03 100644
--- a/HMI.AlermInfoManage/HMI.AlermInfoManage.csproj
+++ b/HMI.AlermInfoManage/HMI.AlarmInfoManage.csproj
@@ -6,8 +6,8 @@
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ProjectGuid>{945C2577-4558-45E3-891A-096CB3047304}</ProjectGuid>
     <OutputType>library</OutputType>
-    <RootNamespace>HMI.AlermInfoManage</RootNamespace>
-    <AssemblyName>HMI.AlermInfoManage</AssemblyName>
+    <RootNamespace>HMI.AlarmInfoManage</RootNamespace>
+    <AssemblyName>HMI.AlarmInfoManage</AssemblyName>
     <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
@@ -50,14 +50,32 @@
     <ErrorReport>prompt</ErrorReport>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
+    </Reference>
     <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
       <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OOXML, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OOXML.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OpenXml4Net, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXml4Net.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OpenXmlFormats, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXmlFormats.dll</HintPath>
     </Reference>
     <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
     </Reference>
     <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
+    </Reference>
+    <Reference Include="SimensDriver">
+      <HintPath>..\Libs\SimensDriver.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
@@ -77,24 +95,42 @@
     <Reference Include="PresentationFramework" />
   </ItemGroup>
   <ItemGroup>
-    <Page Include="AlermInfoManage.xaml">
+    <Page Include="AlarmInfoManage.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
-    <Compile Include="AlermInfoManage.xaml.cs">
-      <DependentUpon>AlermInfoManage.xaml</DependentUpon>
+    <Compile Include="AlarmInfoManage.xaml.cs">
+      <DependentUpon>AlarmInfoManage.xaml</DependentUpon>
       <SubType>Code</SubType>
     </Compile>
-    <Page Include="AlermInfoManage_Setting.xaml">
+    <Page Include="AlarmInfoManage_Setting.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="AlarmSettingList.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Modal\AlarmSettingModal.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
     </Page>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="AlermInfoManage_Setting.xaml.cs">
-      <DependentUpon>AlermInfoManage_Setting.xaml</DependentUpon>
+    <Compile Include="AlarmInfoManage_Setting.xaml.cs">
+      <DependentUpon>AlarmInfoManage_Setting.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="AlarmSettingList.xaml.cs">
+      <DependentUpon>AlarmSettingList.xaml</DependentUpon>
     </Compile>
     <Compile Include="Entity\AimSetting.cs" />
+    <Compile Include="Entity\AlarmSetting.cs" />
+    <Compile Include="Entity\AlarmText.cs" />
+    <Compile Include="Modal\AlarmSettingModal.xaml.cs">
+      <DependentUpon>AlarmSettingModal.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Model\XmlModel.cs" />
+    <Compile Include="Model\UIModel.cs" />
     <Compile Include="Properties\AssemblyInfo.cs">
       <SubType>Code</SubType>
     </Compile>
@@ -132,5 +168,10 @@
       <Name>HMI.UI</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>copy /Y "$(TargetPath)" "$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)\Plugin\$(TargetFileName)" 
+copy /Y "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)\Plugin\$(TargetName).pdb"</PostBuildEvent>
+  </PropertyGroup>
 </Project>
\ No newline at end of file
diff --git a/HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml b/HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml
new file mode 100644
index 0000000..36941a7
--- /dev/null
+++ b/HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml
@@ -0,0 +1,47 @@
+锘�<pu:WindowX x:Class="HMI.AlarmInfoManage.AlarmSettingModal"
+            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+            xmlns:local="clr-namespace:HMI.AlarmInfoManage"
+            xmlns:pw="https://opensource.panuon.com/wpf"
+            xmlns:pu="https://opensource.panuon.com/wpf-ui"
+            xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI"
+            xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI"
+            mc:Ignorable="d"
+            Title="Form"
+            SizeToContent="Height"
+            Width="600"
+            WindowStartupLocation="CenterOwner"
+            BorderBrush="#3E3E45"
+            BorderThickness="1"
+            Foreground="Black"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
+            pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
+            pu:WindowXCaption.Foreground="#FFF"
+            pu:WindowXCaption.Buttons="Close"
+            pu:WindowXModalDialog.Buttons="OKCancel"
+            pu:WindowXModalDialog.CancelButtonContent="鍙栨秷"
+            pu:WindowXModalDialog.OKButtonContent="淇濆瓨"
+            pu:WindowXModalDialog.ButtonPanelMargin="0,30,10,10">
+    <Grid Margin="10">
+        <StackPanel x:Name="formPanel">
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True"
+                                ui:FormGroupHelper.ValidateMethod="ValidateDBAddress"
+                          Header="DB鍦板潃" GroupName="MyFormGroup">
+                <pu:NumberInput Style="{StaticResource FormNumberInput}" 
+                                x:Name="dbAddress" Interval="1"/>
+            </pu:FormGroup>
+
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True" 
+              Header="璧峰鍦板潃" GroupName="MyFormGroup">
+                <pu:NumberInput Style="{StaticResource FormNumberInput}" x:Name="startAddress" Interval="1"/>
+            </pu:FormGroup>
+
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True" 
+              Header="闀垮害" GroupName="MyFormGroup">
+                <pu:NumberInput Style="{StaticResource FormNumberInput}" x:Name="length" Interval="1"/>
+            </pu:FormGroup>
+        </StackPanel>
+    </Grid>
+</pu:WindowX>
diff --git a/HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml.cs b/HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml.cs
new file mode 100644
index 0000000..57ac994
--- /dev/null
+++ b/HMI.AlermInfoManage/Modal/AlarmSettingModal.xaml.cs
@@ -0,0 +1,134 @@
+锘縰sing HMI.AlarmInfoManage.Entity;
+using HMI.Core.Util;
+using HMI.UI;
+using HMI.UI.Util;
+using log4net;
+using Panuon.WPF.UI;
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+
+namespace HMI.AlarmInfoManage
+{
+    /// <summary>
+    /// ModalWindow.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class AlarmSettingModal : WindowX
+    {
+        public AlarmSettingModal(ILog log)
+        {
+            this.log = log;
+            this.DataContext = this;
+            InitializeComponent();
+        }
+        private ILog log;
+        public string FilePath { get; private set; }
+        public int DataIndex { get; private set; }
+        public AlarmSetting Data { get; private set; }
+        public ObservableCollection<AlarmSetting> Datasource { get; private set; }
+
+        private bool _isProcessing;
+
+        protected override void OnClosing(CancelEventArgs e)
+        {
+            //Press Continue Button
+            if (DialogResult == true)
+            {
+                if (_isProcessing)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                var okButton = WindowXModalDialog.GetOKButton(this);
+                try
+                {
+                    _isProcessing = true;
+                    ButtonHelper.SetIsPending(okButton, true);
+                    if (!ValidateForm())
+                    {
+                        e.Cancel = true;
+                        return;
+                    }
+
+                    SaveOrUpdateData();
+                }
+                catch (Exception ex)
+                {
+                    log.Error("AlarmSetting Form Submit Failed.", ex);
+                    ToastHelper.Error(this, $"鏈煡寮傚父锛亄ex.Message}");
+                    e.Cancel = true;
+                    return;
+                }
+                finally
+                {
+                    _isProcessing = false;
+                    ButtonHelper.SetIsPending(okButton, false);
+                }
+            }
+            base.OnClosing(e);
+        }
+
+        public bool ValidateDBAddress(object value, out string err)
+        {
+            err = null;
+            int dbAddress = Convert.ToInt32(value);
+            if (Datasource.FirstOrDefault(e => e.DBAddress == dbAddress) != null)
+            {
+                err = "DB鍦板潃宸插瓨鍦�";
+                return false;
+            }
+            return true;
+        }
+
+        private bool ValidateForm()
+        {
+            bool flag = FormGroupHelper.ValidateForm(formPanel);
+            if (flag)
+            {
+                Data.DBAddress = Convert.ToInt32(dbAddress.Value);
+                Data.StartAddress = Convert.ToInt32(startAddress.Value);
+                Data.Length = Convert.ToInt32(length.Value);
+            }
+            return flag;
+        }
+
+        public bool? Open(int index, AlarmSetting data,
+            ObservableCollection<AlarmSetting> dataSource,
+            string filePath)
+        {
+            FilePath = filePath;
+            DataIndex = index;
+            Data = data;
+            Datasource = dataSource;
+            dbAddress.Value = Data.DBAddress;
+            startAddress.Value = Data.StartAddress;
+            length.Value = Data.Length;
+            return this.ShowDialog();
+        }
+
+        private void SaveOrUpdateData()
+        {
+            if (DataIndex == -1)
+            {
+                InsertData(Data);
+            }
+            else
+            {
+                UpdateData(DataIndex, Data);
+            }
+        }
+
+        public void InsertData(AlarmSetting data)
+        {
+            Datasource.Add(data);
+            XmlHelper.SerializeToXml(FilePath, Datasource);
+        }
+
+        public void UpdateData(int index, AlarmSetting data)
+        {
+            Datasource[index] = data;
+            XmlHelper.SerializeToXml(FilePath, Datasource);
+        }
+    }
+}
diff --git a/HMI.AlermInfoManage/Model/UIModel.cs b/HMI.AlermInfoManage/Model/UIModel.cs
new file mode 100644
index 0000000..507d736
--- /dev/null
+++ b/HMI.AlermInfoManage/Model/UIModel.cs
@@ -0,0 +1,37 @@
+锘縰sing HMI.AlarmInfoManage.Entity;
+using HMI.Core.Entity;
+using HMI.Core.Util;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.IO;
+
+namespace HMI.AlarmInfoManage.Model
+{
+    public class UIModel : NotifyBase
+    {
+        public SqliteHelper sqliteHelper;
+
+        private ObservableCollection<AlarmSetting> datasource;
+
+        public ObservableCollection<AlarmSetting> Datasource
+        {
+            get { return datasource; }
+            set { Set(ref datasource, value); }
+        }
+
+        public UIModel(string filePath)
+        {
+            if (!File.Exists(filePath))
+            {
+                SqliteHelper.CreateDatabase(filePath);
+            }
+            sqliteHelper = new SqliteHelper(filePath);
+        }
+
+        public void LoadData() { 
+            ObservableCollection<AlarmSetting> list = new ObservableCollection<AlarmSetting>();
+            DataTable dt = sqliteHelper.GetDataTable("SELECT * FROM alerm_setting;");
+
+        }
+    }
+}
diff --git a/HMI.AlermInfoManage/Model/XmlModel.cs b/HMI.AlermInfoManage/Model/XmlModel.cs
new file mode 100644
index 0000000..f1eb4b1
--- /dev/null
+++ b/HMI.AlermInfoManage/Model/XmlModel.cs
@@ -0,0 +1,36 @@
+锘縰sing HMI.AlarmInfoManage.Entity;
+using HMI.Core.Entity;
+using HMI.Core.Util;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HMI.AlarmInfoManage.Model
+{
+    public class XmlUIModel : NotifyBase
+    {
+        public string FileFolder { get; private set; }
+        public string AlermTextPath { get; private set; }
+        public string AlermSettingPath { get; private set; }
+
+        private ObservableCollection<AlarmText> datasource = new ObservableCollection<AlarmText>();
+
+        public ObservableCollection<AlarmText> Datasource
+        {
+            get { return datasource; }
+            set { Set(ref datasource, value); }
+        }
+
+        public XmlUIModel(string FileFolder)
+        {
+            this.FileFolder = FileFolder;
+            this.AlermTextPath = Path.Combine(FileFolder, "AlermText.xml");
+            this.AlermSettingPath = Path.Combine(FileFolder, "AlermSetting.xml");
+        }
+    }
+}
diff --git a/HMI.AlermInfoManage/Properties/AssemblyInfo.cs b/HMI.AlermInfoManage/Properties/AssemblyInfo.cs
index 7dc26f0..c982da7 100644
--- a/HMI.AlermInfoManage/Properties/AssemblyInfo.cs
+++ b/HMI.AlermInfoManage/Properties/AssemblyInfo.cs
@@ -8,11 +8,11 @@
 // 鏈夊叧绋嬪簭闆嗙殑涓�鑸俊鎭敱浠ヤ笅
 // 鎺у埗銆傛洿鏀硅繖浜涚壒鎬у�煎彲淇敼
 // 涓庣▼搴忛泦鍏宠仈鐨勪俊鎭��
-[assembly: AssemblyTitle("HMI.AlermInfoManage")]
+[assembly: AssemblyTitle("HMI.AlarmInfoManage")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("Organization")]
-[assembly: AssemblyProduct("HMI.AlermInfoManage")]
+[assembly: AssemblyProduct("HMI.AlarmInfoManage")]
 [assembly: AssemblyCopyright("Copyright 漏 Organization 2025")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
@@ -51,4 +51,4 @@
 //
 [assembly: AssemblyVersion("1.0.0.0")]
 [assembly: AssemblyFileVersion("1.0.0.0")]
-[assembly: PluginClassName("HMI.AlermInfoManage.AlermInfoManage")]
+[assembly: PluginClassName("HMI.AlarmInfoManage.AlarmInfoManage")]
diff --git a/HMI.AlermInfoManage/Properties/Resources.Designer.cs b/HMI.AlermInfoManage/Properties/Resources.Designer.cs
index ea89dfe..587bd37 100644
--- a/HMI.AlermInfoManage/Properties/Resources.Designer.cs
+++ b/HMI.AlermInfoManage/Properties/Resources.Designer.cs
@@ -1,24 +1,25 @@
 锘�//------------------------------------------------------------------------------
 // <auto-generated>
 //     姝や唬鐮佺敱宸ュ叿鐢熸垚銆�
-//     杩愯鏃剁増鏈�: 4.0.30319.42000
+//     杩愯鏃剁増鏈�:4.0.30319.42000
 //
-//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳藉鑷翠笉姝g‘鐨勮涓猴紝濡傛灉
-//     閲嶆柊鐢熸垚浠g爜锛屽垯鎵�鍋氭洿鏀瑰皢涓㈠け銆�
+//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋�
+//     閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便��
 // </auto-generated>
 //------------------------------------------------------------------------------
 
-namespace HMI.AlermInfoManage.Properties {
+namespace HMI.AlarmInfoManage.Properties {
+    using System;
     
     
     /// <summary>
-    ///   寮虹被鍨嬭祫婧愮被锛岀敤浜庢煡鎵炬湰鍦板寲瀛楃涓茬瓑銆�
+    ///   涓�涓己绫诲瀷鐨勮祫婧愮被锛岀敤浜庢煡鎵炬湰鍦板寲鐨勫瓧绗︿覆绛夈��
     /// </summary>
     // 姝ょ被鏄敱 StronglyTypedResourceBuilder
     // 绫婚�氳繃绫讳技浜� ResGen 鎴� Visual Studio 鐨勫伐鍏疯嚜鍔ㄧ敓鎴愮殑銆�
     // 鑻ヨ娣诲姞鎴栫Щ闄ゆ垚鍛橈紝璇风紪杈� .ResX 鏂囦欢锛岀劧鍚庨噸鏂拌繍琛� ResGen
     // (浠� /str 浣滀负鍛戒护閫夐」)锛屾垨閲嶆柊鐢熸垚 VS 椤圭洰銆�
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class Resources {
@@ -32,13 +33,13 @@
         }
         
         /// <summary>
-        ///   杩斿洖姝ょ被浣跨敤鐨勭紦瀛� ResourceManager 瀹炰緥銆�
+        ///   杩斿洖姝ょ被浣跨敤鐨勭紦瀛樼殑 ResourceManager 瀹炰緥銆�
         /// </summary>
         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
         internal static global::System.Resources.ResourceManager ResourceManager {
             get {
-                if ((resourceMan == null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HMI.AlermInfoManage.Properties.Resources", typeof(Resources).Assembly);
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HMI.AlarmInfoManage.Properties.Resources", typeof(Resources).Assembly);
                     resourceMan = temp;
                 }
                 return resourceMan;
diff --git a/HMI.AlermInfoManage/Properties/Settings.Designer.cs b/HMI.AlermInfoManage/Properties/Settings.Designer.cs
index 0110c48..80b1e31 100644
--- a/HMI.AlermInfoManage/Properties/Settings.Designer.cs
+++ b/HMI.AlermInfoManage/Properties/Settings.Designer.cs
@@ -1,28 +1,24 @@
 锘�//------------------------------------------------------------------------------
 // <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.42000
+//     姝や唬鐮佺敱宸ュ叿鐢熸垚銆�
+//     杩愯鏃剁増鏈�:4.0.30319.42000
 //
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
+//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋�
+//     閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便��
 // </auto-generated>
 //------------------------------------------------------------------------------
 
-namespace HMI.AlermInfoManage.Properties
-{
+namespace HMI.AlarmInfoManage.Properties {
     
     
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
-    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
-    {
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
         
         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
         
-        public static Settings Default
-        {
-            get
-            {
+        public static Settings Default {
+            get {
                 return defaultInstance;
             }
         }
diff --git a/HMI.AlermInfoManage/packages.config b/HMI.AlermInfoManage/packages.config
index 63cdc53..bc20bca 100644
--- a/HMI.AlermInfoManage/packages.config
+++ b/HMI.AlermInfoManage/packages.config
@@ -1,6 +1,8 @@
 锘�<?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="log4net" version="3.0.3" targetFramework="net472" />
+  <package id="NPOI" version="2.4.1" targetFramework="net472" />
   <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
   <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
+  <package id="SharpZipLib" version="1.0.0" targetFramework="net472" />
 </packages>
\ No newline at end of file
diff --git a/HMI.Base/DtConverter.cs b/HMI.Base/DtConverter.cs
new file mode 100644
index 0000000..c5d9b0c
--- /dev/null
+++ b/HMI.Base/DtConverter.cs
@@ -0,0 +1,28 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Data;
+using System.Reflection;
+
+namespace HMI.Base
+{
+    public class DtConverter
+    {
+        public static void DoConvert<T>(DataTable dataTable, ICollection<T> target) where T : new()
+        {
+            var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
+
+            foreach (DataRow row in dataTable.Rows)
+            {
+                var item = new T();
+                foreach (var property in properties)
+                {
+                    if (dataTable.Columns.Contains(property.Name) && row[property.Name] != DBNull.Value)
+                    {
+                        property.SetValue(item, Convert.ChangeType(row[property.Name], property.PropertyType));
+                    }
+                }
+                target.Add(item);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/HMI.Base/HMI.Base.csproj b/HMI.Base/HMI.Base.csproj
index 423b990..efb3a2c 100644
--- a/HMI.Base/HMI.Base.csproj
+++ b/HMI.Base/HMI.Base.csproj
@@ -31,6 +31,24 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <LangVersion>7.3</LangVersion>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <LangVersion>7.3</LangVersion>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
       <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
@@ -53,6 +71,7 @@
     <Reference Include="PresentationFramework" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="DtConverter.cs" />
     <Compile Include="PluginControl.cs" />
     <Compile Include="PluginInfo.cs" />
     <Compile Include="PluginLoader.cs" />
diff --git a/HMI.Core/Entity/NotifyBase.cs b/HMI.Core/Entity/NotifyBase.cs
index ae2c761..548084b 100644
--- a/HMI.Core/Entity/NotifyBase.cs
+++ b/HMI.Core/Entity/NotifyBase.cs
@@ -29,8 +29,6 @@
             }
         }
         #endregion
-
-
     }
 
     public class RelayCommand<T> : ICommand
diff --git a/HMI.Core/Entity/SelectBase.cs b/HMI.Core/Entity/SelectBase.cs
new file mode 100644
index 0000000..8b94dab
--- /dev/null
+++ b/HMI.Core/Entity/SelectBase.cs
@@ -0,0 +1,15 @@
+锘縰sing System.Xml.Serialization;
+
+namespace HMI.Core.Entity
+{
+    public class SelectBase : NotifyBase
+    {
+        private bool isSelected;
+        [XmlIgnore]
+        public virtual bool IsSelected
+        {
+            get => isSelected;
+            set { Set(ref isSelected, value); }
+        }
+    }
+}
diff --git a/HMI.Core/HMI.Core.csproj b/HMI.Core/HMI.Core.csproj
index c170457..3f23aae 100644
--- a/HMI.Core/HMI.Core.csproj
+++ b/HMI.Core/HMI.Core.csproj
@@ -69,6 +69,7 @@
     <Reference Include="System.Data.SQLite.Linq">
       <HintPath>..\Libs\System.Data.SQLite.Linq.dll</HintPath>
     </Reference>
+    <Reference Include="System.Messaging" />
     <Reference Include="System.Numerics" />
     <Reference Include="System.Web" />
     <Reference Include="System.Xml.Linq" />
@@ -89,12 +90,15 @@
     <Compile Include="Annotation\InitAttribute.cs" />
     <Compile Include="Entity\NotifyBase.cs" />
     <Compile Include="Entity\Param.cs" />
+    <Compile Include="Entity\SelectBase.cs" />
     <Compile Include="Event\TabChange.cs" />
     <Compile Include="Exceptions\FormValidateException.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Setting\SystemSetting.cs" />
     <Compile Include="Util\BeanUtil.cs" />
     <Compile Include="Util\DllHelper.cs" />
+    <Compile Include="Util\HexUtil.cs" />
+    <Compile Include="Util\MSMQHelper.cs" />
     <Compile Include="Util\PathHelper.cs" />
     <Compile Include="Util\SqliteHelper.cs" />
     <Compile Include="Util\UtilContainer.cs" />
diff --git a/HMI.Core/Setting/SystemSetting.cs b/HMI.Core/Setting/SystemSetting.cs
index 774d75b..b2fe7be 100644
--- a/HMI.Core/Setting/SystemSetting.cs
+++ b/HMI.Core/Setting/SystemSetting.cs
@@ -8,6 +8,9 @@
     public class SystemSetting
     {
         public static SystemSetting Instance { get; private set; }
+        /// <summary>
+        /// 绯荤粺璁剧疆鏀瑰彉浜嬩欢
+        /// </summary>
         public static event EventHandler<SystemSetting> SystemSettingChanged;
 
         static SystemSetting()
@@ -22,6 +25,8 @@
 
         public string LogoPath { get; private set; }
         public string WindowTitle { get; private set; }
+        public string PlcIp { get; private set; }
+        public bool PlcEnabled { get; private set; }
 
         private static void LoadFromXml()
         {
@@ -74,5 +79,19 @@
             get => windowTitle;
             set { Set(ref windowTitle, value); }
         }
+
+        private string plcIp;
+        public string PlcIp
+        {
+            get => plcIp;
+            set { Set(ref plcIp, value); }
+        }
+
+        private bool plcEnabled;
+        public bool PlcEnabled
+        {
+            get => plcEnabled;
+            set { Set(ref plcEnabled, value); }
+        }
     }
 }
diff --git a/HMI.Core/Util/HexUtil.cs b/HMI.Core/Util/HexUtil.cs
new file mode 100644
index 0000000..546bd63
--- /dev/null
+++ b/HMI.Core/Util/HexUtil.cs
@@ -0,0 +1,16 @@
+锘縰sing System;
+
+namespace HMI.Core.Util
+{
+    public class HexUtil
+    {
+        public static byte[] ToBytesFromHexString(string hexString)
+        {
+            //浠� ' ' 鍒嗗壊瀛楃涓诧紝骞跺幓鎺夌┖瀛楃
+            string[] chars = hexString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+            byte[] returnBytes;
+            returnBytes = BitConverter.GetBytes(Convert.ToInt32(chars[0]));
+            return returnBytes;
+        }
+    }
+}
diff --git a/HMI.Core/Util/MSMQHelper.cs b/HMI.Core/Util/MSMQHelper.cs
new file mode 100644
index 0000000..14c8125
--- /dev/null
+++ b/HMI.Core/Util/MSMQHelper.cs
@@ -0,0 +1,144 @@
+锘�//-----------------------------------------------------------------------
+// <copyright file="MSMQHelper.cs" company="iPilotWhale">
+//      Suzhou Linktron Systems Co.,Ltd . All rights reserved.
+// </copyright>
+// <author>娓╁悜瓒�</author>
+// <description>娑堟伅闃熷垪鎿嶄綔杈呭姪绫�</description>
+//-----------------------------------------------------------------------
+using System;
+using System.Messaging;
+
+namespace HMI.Core.Util
+{
+    /// <summary>
+    /// 娑堟伅闃熷垪鎿嶄綔绫�
+    /// </summary>
+    public class MSMQHelper
+    {
+        /// <summary>
+        /// 娑堟伅闃熷垪鍚嶇О
+        /// </summary>
+        private string msmqName = string.Empty;
+
+        /// <summary>
+        /// 娑堟伅闃熷垪璺緞
+        /// </summary>
+        private string msmqPath = string.Empty;
+
+        /// <summary>
+        /// 瑕佹搷浣滅殑娑堟伅闃熷垪
+        /// </summary>
+        private MessageQueue msgQueue = null;
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="Name">娑堟伅闃熷垪鍚嶇О</param>
+        public MSMQHelper(string Name)
+        {
+            try
+            {
+                this.msmqName = Name;
+                this.msmqPath = ".\\private$\\" + this.msmqName;
+                if (MessageQueue.Exists(this.msmqPath))
+                {
+                    // 濡傛灉褰撳墠娑堟伅闃熷垪宸茬粡瀛樺湪
+                    this.msgQueue = new MessageQueue(this.msmqPath);
+                }
+                else
+                {
+                    // 濡傛灉娑堟伅闃熷垪涓嶅瓨鍦紝鍒欏垱寤烘秷鎭鍨�
+                    this.msgQueue = MessageQueue.Create(this.msmqPath);
+                }
+                this.msgQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
+            }
+            catch(Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+        }
+
+        /// <summary>
+        /// 鍙戦�佹秷鎭�
+        /// </summary>
+        /// <param name="MessageID">娑堟伅ID</param>
+        /// <param name="MsgString">瑕佸彂閫佺殑瀛楃涓�</param>
+        public void Send(string MessageID,string MsgString)
+        {
+            try
+            {
+                this.msgQueue.Send(MsgString, MessageID);
+            }
+            catch(Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+        }
+
+        /// <summary>
+        /// 鎺ユ敹娑堟伅闃熷垪涓殑娑堟伅
+        /// </summary>
+        /// <param name="TimeOut">瓒呮椂鏃堕棿(ms)</param>
+        /// <param name="MessageID">娑堟伅ID</param>
+        /// <param name="MsgString">娑堟伅鍐呭</param>
+        public void Receive(long TimeOut,out string MessageID,out string MsgString)
+        {
+            try
+            {
+                MessageID = string.Empty;
+                MsgString = string.Empty;
+                TimeSpan Time = new TimeSpan(TimeOut*10000);
+                Message MsgReceived = null;
+                try
+                {
+                    MsgReceived = this.msgQueue.Receive(Time);
+                }
+                catch(Exception ex)
+                {
+                    // do nothing
+                }
+                
+                if(MsgReceived!=null)
+                {
+                    MessageID = MsgReceived.Label;
+                    MsgString = MsgReceived.Body.ToString();
+                }
+            }
+            catch(Exception ex)
+            {
+                throw new Exception("鎺ユ敹娑堟伅澶辫触:" + ex.Message);
+            }
+        }
+
+        /// <summary>
+        /// 娓呴櫎娑堟伅闃熷垪涓殑娑堟伅
+        /// </summary>
+        public void Clear()
+        {
+            try
+            {
+                this.msgQueue.Purge();
+            }
+            catch(Exception ex)
+            {
+                throw new Exception("娓呴櫎娑堟伅闃熷垪澶辫触:" + ex.Message);
+            }
+        }
+
+        /// <summary>
+        /// 鍏抽棴褰撳墠闃熷垪
+        /// </summary>
+        public void Close()
+        {
+            this.msgQueue.Close();
+        }
+
+        /// <summary>
+        /// 鍒犻櫎褰撳墠闃熷垪
+        /// </summary>
+        public void Delete()
+        {
+            MessageQueue.Delete(this.msmqPath);
+        }
+    }
+}
diff --git a/HMI.Core/Util/SqliteHelper.cs b/HMI.Core/Util/SqliteHelper.cs
index 34502b6..6d7ca57 100644
--- a/HMI.Core/Util/SqliteHelper.cs
+++ b/HMI.Core/Util/SqliteHelper.cs
@@ -1,8 +1,6 @@
 锘縰sing System;
 using System.Collections.Generic;
 using System.Data;
-using System.Data.Common;
-using System.Data.Odbc;
 using System.Data.SQLite;
 
 namespace HMI.Core.Util
@@ -188,7 +186,7 @@
             }
             catch (Exception ex)
             {
-                throw new Exception("鑾峰彇瀛楁鍚嶇О澶辫触:" + ex.Message);
+                throw new Exception("鑾峰彇琛ㄥ瓧娈靛悕绉板け璐�:" + ex.Message);
             }
         }
 
@@ -210,7 +208,7 @@
             }
             catch (Exception ex)
             {
-                throw new Exception("鑾峰彇瀛楁鍚嶇О澶辫触:" + ex.Message);
+                throw new Exception("鑾峰彇琛ㄥ悕澶辫触:" + ex.Message);
             }
         }
 
diff --git a/HMI.Core/Util/XmlHelper.cs b/HMI.Core/Util/XmlHelper.cs
index d0dba0d..6006684 100644
--- a/HMI.Core/Util/XmlHelper.cs
+++ b/HMI.Core/Util/XmlHelper.cs
@@ -1,6 +1,10 @@
 锘縰sing System;
+using System.CodeDom;
+using System.Collections.Generic;
 using System.IO;
 using System.Reflection;
+using System.Text;
+using System.Web.UI.WebControls;
 using System.Xml;
 using System.Xml.Serialization;
 using static System.Net.WebRequestMethods;
@@ -9,19 +13,27 @@
 {
     public static class XmlHelper
     {
+
+        static readonly XmlSerializerNamespaces DEFAULT_NS = new XmlSerializerNamespaces();
+
+        static XmlHelper()
+        {
+            DEFAULT_NS.Add("", "");
+        }
+
         /// <summary>
         /// serialize object to xml file.
         /// </summary>
         /// <param name="path">the path to save the xml file</param>
         /// <param name="obj">the object you want to serialize</param>
         public static void SerializeToXml(string path, object obj)
-        { 
+        {
             XmlSerializer serializer = new XmlSerializer(obj.GetType());
             string content = string.Empty;
             //serialize
             using (StringWriter writer = new StringWriter())
             {
-                serializer.Serialize(writer, obj);
+                serializer.Serialize(writer, obj, DEFAULT_NS);
                 content = writer.ToString();
             }
             //save to file
@@ -45,13 +57,15 @@
                 return (T)serializer.Deserialize(reader);
             }
         }
-        public static bool ReadFromXml<T>(T obj, string path) {
+        public static bool ReadFromXml<T>(T obj, string path)
+        {
             XmlDocument xd = new XmlDocument();
             xd.Load(path);
 
             Type type = typeof(T);
             XmlNode root = xd.SelectSingleNode(type.Name);
-            if (root == null) {
+            if (root == null)
+            {
                 return false;
             }
 
@@ -70,5 +84,15 @@
             return true;
         }
 
+        public static T DeepClone<T>(T data)
+        {
+            using (MemoryStream stream = new MemoryStream())
+            {
+                XmlSerializer serializer = new XmlSerializer(typeof(T));
+                serializer.Serialize(stream, data);
+                stream.Seek(0, SeekOrigin.Begin);
+                return (T)serializer.Deserialize(stream);
+            }
+        }
     }
 }
diff --git a/HMI.DataViewer/DataViewer.xaml b/HMI.DataViewer/DataViewer.xaml
index ebd4758..6e97d35 100644
--- a/HMI.DataViewer/DataViewer.xaml
+++ b/HMI.DataViewer/DataViewer.xaml
@@ -9,7 +9,9 @@
              xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI"
              xmlns:pw="https://opensource.panuon.com/wpf"
              xmlns:pu="https://opensource.panuon.com/wpf-ui"
-             xmlns:dp="clr-namespace:HMI.UI;assembly=HMI.UI"
+             xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI"
+             Background="{StaticResource WorkspaceBackground}"
+             Loaded="PluginControl_Loaded"
              d:DesignHeight="450" d:DesignWidth="800">
     <UserControl.Resources>
         <ResourceDictionary>
@@ -23,105 +25,210 @@
             <uic:DataGridRowNumberConverter x:Key="rowNumber"/>
         </ResourceDictionary>
     </UserControl.Resources>
+    <Border Style="{StaticResource CardBoarder}">
+        <Grid dp:GridHelper.Space="10">
+            <Grid.RowDefinitions>
+                <RowDefinition Height="Auto"/>
+                <RowDefinition Height="Auto"/>
+                <RowDefinition/>
+            </Grid.RowDefinitions>
 
-    <Grid>
-        <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="7*"/>
-            <ColumnDefinition Width="3*"/>
-        </Grid.ColumnDefinitions>
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="7*"/>
+                <ColumnDefinition Width="3*"/>
+            </Grid.ColumnDefinitions>
 
-        <Border Style="{StaticResource CardBoarder}" Margin="0,0,2,0">
-            <StackPanel>
-                <DockPanel Margin="0,0,0,10">
-                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe934;" Style="{StaticResource DangerButton}">鍒犻櫎</Button>
-                    <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
-pu:IconHelper.FontFamily="{StaticResource iconfont}"
-pu:ButtonHelper.Icon="&#xe631;" Margin="0,0,10,0" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
-                    <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
-            pu:IconHelper.FontFamily="{StaticResource iconfont}"
-            pu:ButtonHelper.Icon="&#xe61a;" Margin="0,0,10,0" x:Name="addBtn" Click="Button_Click">鏂板</Button>
-                    <TextBlock DockPanel.Dock="Left" FontSize="{StaticResource TitleFontSize}" 
-                           VerticalAlignment="Center" HorizontalAlignment="Left" Text="鑿滃崟鍒楄〃"/>
-                </DockPanel>
+            <DockPanel Grid.ColumnSpan="2">
+                <StackPanel DockPanel.Dock="Right" Style="{StaticResource ButtonGroup}">
+                    <Button Style="{StaticResource AddBtn}" x:Name="addBtn" Click="Button_Click"/>
+                    <Button Style="{StaticResource RfhBtn}" x:Name="rfhBtn" Click="Button_Click"/>
+                    <Button Style="{StaticResource DelBtn}" x:Name="delBtn" Click="Button_Click"/>
+                </StackPanel>
+                <TextBlock Style="{StaticResource TitleBox}" Text="鏁版嵁鏌ヨ"/>
+            </DockPanel>
 
-                <DataGrid Grid.Column="1" x:Name="table" Style="{StaticResource DefaultDataGrid}" ItemsSource="{Binding DataSource}">
+            <!--<Grid>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition/>
+                    <ColumnDefinition/>
+                </Grid.ColumnDefinitions>
+            </Grid>-->
+            <StackPanel Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Left" Style="{StaticResource ButtonGroup}">
+
+                <TextBlock Style="{StaticResource TitleBox}" Text="寮�濮嬫椂闂�"/>
+                <pu:DateTimePicker Width="190" Style="{StaticResource TimePicker}" SelectedDateTime="{x:Null}" x:Name="startTimeInput"/>
+                <TextBlock Style="{StaticResource TitleBox}" Text="缁撴潫鏃堕棿"/>
+                <pu:DateTimePicker Width="190" Style="{StaticResource TimePicker}" SelectedDateTime="{x:Null}" x:Name="endTimeInput"/>
+
+                <Button Style="{StaticResource PrimaryButton}" pu:ButtonHelper.Icon="&#xe752;" 
+                        x:Name="srhBtn" Click="Button_Click">鏌ヨ</Button>
+
+                <Button Style="{StaticResource PrimaryButton}" pu:ButtonHelper.Icon="&#xe752;" 
+                        x:Name="resetBtn" Click="Button_Click">閲嶇疆</Button>
+
+                <Menu x:Name="anyBtn" >
+                    <MenuItem Header="鍒嗘瀽">
+                        <MenuItem Header="CPK" />
+                        <MenuItem Header="RandR" />
+                    </MenuItem>
+                </Menu>
+
+            </StackPanel>
+
+            <DockPanel Grid.Row="2" Grid.ColumnSpan="2" Margin="0,10,0,0">
+                <pu:Drawer DockPanel.Dock="Left" x:Name="DrwMenu" MinWidth="34" MaxWidth="400"
+                           ShadowColor="{x:Null}"
+                           AnimationDuration="0" BorderThickness="2,2,0,2" BorderBrush="{StaticResource CommonBoarder}">
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="Auto"/>
+                            <RowDefinition/>
+                        </Grid.RowDefinitions>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition/>
+                            <ColumnDefinition Width="Auto"/>
+                        </Grid.ColumnDefinitions>
+
+                        <DockPanel Grid.ColumnSpan="2" Background="{StaticResource CommonBoarder}">
+                            <ToggleButton Grid.Column="1" x:Name="drawerBtn" BorderThickness="0"
+                                          DockPanel.Dock="Right"
+                                          Background="Transparent"
+                                          Width="34" Height="34" HorizontalAlignment="Right"
+                                          RenderTransformOrigin="0.5,0.5"
+                                          FontFamily="{StaticResource iconfont}"
+                                          Content="&#xe60e;" IsChecked="{Binding IsOpen, ElementName=DrwMenu, Mode=TwoWay}">
+                                <ToggleButton.Style>
+                                    <Style TargetType="ToggleButton">
+                                        <Style.Triggers>
+                                            <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu}" Value="False">
+                                                <Setter Property="RenderTransform">
+                                                    <Setter.Value>
+                                                        <RotateTransform Angle="-90"/>
+                                                    </Setter.Value>
+                                                </Setter>
+                                            </DataTrigger>
+                                            <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu}" Value="True">
+                                                <Setter Property="Background" Value="Red"/>
+                                                <Setter Property="RenderTransform">
+                                                    <Setter.Value>
+                                                        <RotateTransform Angle="90"/>
+                                                    </Setter.Value>
+                                                </Setter>
+                                            </DataTrigger>
+                                            <Trigger Property="IsChecked" Value="True">
+                                                <Setter Property="Background" Value="Red"/>
+                                            </Trigger>
+                                        </Style.Triggers>
+                                    </Style>
+                                </ToggleButton.Style>
+                            </ToggleButton>
+                            
+                            <TextBlock Text="楂樼骇鏌ヨ" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+                        </DockPanel>
+
+                        <Grid Grid.Row="1">
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="Auto"/>
+                                <RowDefinition/>
+                            </Grid.RowDefinitions>
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="Auto"/>
+                                <ColumnDefinition/>
+                            </Grid.ColumnDefinitions>
+
+                            <DockPanel Margin="10,10,10,0" Grid.ColumnSpan="2">
+                                <Label Content="閫夋嫨鏌ヨ椤圭洰"/>
+                                <ComboBox Grid.Column="1" x:Name="programInput" SelectionChanged="programInput_SelectionChanged"/>
+                            </DockPanel>
+                           
+                            <DataGrid Margin="10" Grid.Row="1" Grid.ColumnSpan="2" Style="{StaticResource DefaultDataGrid}"
+                                      IsReadOnly="False"
+                                      BorderThickness="0"
+                                      ItemsSource="{Binding Datas}">
+                                <DataGrid.Columns>
+                                    <DataGridTemplateColumn Header="#" IsReadOnly="True" CanUserResize="False">
+                                        <DataGridTemplateColumn.CellTemplate>
+                                            <DataTemplate>
+                                                <TextBlock Text="{Binding Converter={StaticResource rowNumber},
+RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
+                                            </DataTemplate>
+                                        </DataGridTemplateColumn.CellTemplate>
+                                    </DataGridTemplateColumn>
+                                    <DataGridTextColumn IsReadOnly="True" Width="*" Binding="{Binding Key}" Header="绛涢�夋潯浠�" />
+
+                                    <DataGridTemplateColumn Width="*" Header="瀵规瘮鏂瑰紡">
+                                        <DataGridTemplateColumn.CellTemplate>
+                                            <DataTemplate>
+                                                <TextBlock Text="{Binding Condition}"/>
+                                            </DataTemplate>
+                                        </DataGridTemplateColumn.CellTemplate>
+                                        <DataGridTemplateColumn.CellEditingTemplate>
+                                            <DataTemplate>
+                                                <ComboBox SelectedValue="{Binding Condition}" 
+                                                          SelectedValuePath="Content" >
+                                                    <ComboBoxItem Content="="/>
+                                                    <ComboBoxItem Content="&lt;"/>
+                                                    <ComboBoxItem Content="&gt;"/>
+                                                    <ComboBoxItem Content="&lt;="/>
+                                                    <ComboBoxItem Content="&gt;="/>
+                                                </ComboBox>
+                                            </DataTemplate>
+                                        </DataGridTemplateColumn.CellEditingTemplate>
+                                    </DataGridTemplateColumn>
+
+                                    <DataGridTextColumn Width="*" Binding="{Binding Value}" Header="绛涢�夊��" >
+                                        <DataGridTextColumn.HeaderTemplate>
+                                            <DataTemplate>
+                                                <StackPanel Orientation="Horizontal">
+                                                    <TextBlock Text="*" Foreground="Red" />
+                                                    <ContentControl Content="{Binding }"/>
+                                                </StackPanel>
+                                            </DataTemplate>
+                                        </DataGridTextColumn.HeaderTemplate>
+                                    </DataGridTextColumn>
+                                </DataGrid.Columns>
+
+                            </DataGrid>
+                        </Grid>
+
+                        <Label Grid.Row="1" Grid.Column="1"  Width="100" Height="34"
+                               VerticalContentAlignment="Center"
+                               HorizontalContentAlignment="Center"
+                                   Content="楂樼骇鏌ヨ"
+                                   FontSize="16">
+                            <Label.LayoutTransform>
+                                <RotateTransform CenterX="25" CenterY="25" Angle="270"/>
+                            </Label.LayoutTransform>
+
+                            <Label.Style>
+                                <Style TargetType="Label">
+                                    <Style.Triggers>
+                                        <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu,Mode=OneWay}" Value="True">
+                                            <Setter Property="Visibility" Value="Collapsed"/>
+                                        </DataTrigger>
+                                        <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu}" Value="False">
+                                            <Setter Property="Visibility" Value="Visible"/>
+                                        </DataTrigger>
+                                    </Style.Triggers>
+                                </Style>
+                            </Label.Style>
+                        </Label>
+                    </Grid>
+                </pu:Drawer>
+
+                <DataGrid BorderThickness="2" BorderBrush="{StaticResource CommonBoarder}" x:Name="dataTable" Style="{StaticResource DefaultDataGrid}">
                     <DataGrid.Columns>
-                        <DataGridTemplateColumn Header="" Width="Auto" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <CheckBox VerticalAlignment="Center" IsChecked="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                        <DataGridTemplateColumn Header="#" CanUserResize="False">
+                        <DataGridTemplateColumn Header="#" IsReadOnly="True" CanUserResize="False">
                             <DataGridTemplateColumn.CellTemplate>
                                 <DataTemplate>
                                     <TextBlock Text="{Binding Converter={StaticResource rowNumber},
-                    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                        <DataGridTextColumn Binding="{Binding Code}" Header="鑿滃崟缂栧彿" />
-                        <DataGridTextColumn Binding="{Binding Name}" Header="鑿滃崟鍚嶇О" />
-                        <DataGridTextColumn Binding="{Binding Level}" Header="绛夌骇" />
-                        <DataGridTextColumn Binding="{Binding Type}" Header="绫诲瀷" />
-                        <DataGridTextColumn Binding="{Binding Name}" Header="鑿滃崟鍚嶇О" />
-                        <DataGridTextColumn Binding="{Binding ParentCode}" Header="鐖惰彍鍗曠紪鍙�" />
-                        <DataGridTextColumn Binding="{Binding ParentName}" Header="鐖惰彍鍗曞悕绉�" />
-                        <DataGridTextColumn Width="*" Binding="{Binding DllPath}" Header="Dll璺緞" />
-                        <DataGridTextColumn Width="*" Binding="{Binding ClassName}" Header="绫诲悕" />
-                        <DataGridTemplateColumn Header="鎿嶄綔" Width="100" IsReadOnly="True" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <StackPanel Orientation="Horizontal">
-                                        <Button x:Name="editBtn" Style="{StaticResource LinkButton}" 
-                            Margin="0,0,10,0" 
-                            Click="Button_Click"
-                            DataContext="{Binding }">缂栬緫</Button>
-                                        <Button x:Name="delBtn" Style="{StaticResource DangerLinkButton}" 
-                            DataContext="{Binding }"
-                            Click="Button_Click">鍒犻櫎</Button>
-                                    </StackPanel>
-
-                                    <DataTemplate.Triggers>
-                                        <DataTrigger Binding="{Binding Path=IsMouseOver,
-                        RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}" 
-                                 Value="True">
-                                            <Setter TargetName="editBtn" Property="Foreground" Value="#FFF"/>
-                                        </DataTrigger>
-                                        <DataTrigger Binding="{Binding Path=IsSelected,
-                        RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}" 
-                                 Value="True">
-                                            <Setter TargetName="editBtn" Property="Foreground" Value="#FFF"/>
-                                        </DataTrigger>
-                                    </DataTemplate.Triggers>
+RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
                                 </DataTemplate>
                             </DataGridTemplateColumn.CellTemplate>
                         </DataGridTemplateColumn>
                     </DataGrid.Columns>
                 </DataGrid>
-            </StackPanel>
-        </Border>
-
-        <Border Grid.Column="1" Style="{StaticResource CardBoarder}" Margin="2,0,0,0">
-            <StackPanel>
-                <DockPanel Margin="0,0,0,10" >
-                    <TextBlock DockPanel.Dock="Left" FontSize="{StaticResource TitleFontSize}" 
-                   VerticalAlignment="Center" HorizontalAlignment="Left" Text="鑿滃崟缁撴瀯"/>
-                </DockPanel>
-
-                <TreeView x:Name="treeViewer" Style="{StaticResource DefaultTreeView}" ItemsSource="{Binding TreeDataSource}">
-                    <TreeView.ItemTemplate>
-                        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
-                            <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
-                                <Image Width="{StaticResource ContentFontSize}" Height="{StaticResource ContentFontSize}" Margin="5" 
-                                       Source="{Binding IconPath,Converter={StaticResource path2Image},Mode=OneWay}"/>
-                                <TextBlock VerticalAlignment="Center" FontSize="{StaticResource ContentFontSize}" Text="{Binding Name}"/>
-                            </StackPanel>
-                        </HierarchicalDataTemplate>
-                    </TreeView.ItemTemplate>
-                </TreeView>
-            </StackPanel>
-        </Border>
-    </Grid>
+            </DockPanel>
+        </Grid>
+    </Border>
 </hb:PluginControl>
diff --git a/HMI.DataViewer/DataViewer.xaml.cs b/HMI.DataViewer/DataViewer.xaml.cs
index 7616abc..0b7ca90 100644
--- a/HMI.DataViewer/DataViewer.xaml.cs
+++ b/HMI.DataViewer/DataViewer.xaml.cs
@@ -1,6 +1,16 @@
-锘縰sing System.Windows;
+锘縰sing HMI.Base;
+using HMI.Core.Util;
+using HMI.DataViewer.Entity;
+using HMI.UI.Util;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Windows;
 using System.Windows.Controls;
-using HMI.Base;
+using System.Windows.Data;
 
 namespace HMI.DataViewer
 {
@@ -11,12 +21,194 @@
     {
         public DataViewer()
         {
+            DataContext = this;
             InitializeComponent();
         }
 
+        private string SourceFilePath;
+
+        private ObservableCollection<DataBase_Setting> settings = new ObservableCollection<DataBase_Setting>();
+        public ObservableCollection<DataBase_Setting> Settings
+        {
+            get => settings;
+            set { Set(ref settings, value); }
+        }
+
+        private ObservableCollection<QueryData> datas = new ObservableCollection<QueryData>();
+        public ObservableCollection<QueryData> Datas
+        {
+            get => datas;
+            set { Set(ref datas, value); }
+        }
+
+        private Dictionary<string, DataBase_Setting> Map = new Dictionary<string, DataBase_Setting>();
+
         private void Button_Click(object sender, RoutedEventArgs e)
         {
+            Button btn = sender as Button;
+            switch (btn.Name)
+            {
+                case "addBtn":
+                    OpenSettingModal(new DataBase_Setting());
+                    break;
+                case "rfhBtn":
+                    break;
+                case "delBtn":
+                    break;
+                case "srhBtn":
+                    SearchData();
+                    break;
+                case "resetBtn":
+                    ResetDataTable();
+                    break;
+                default:
+                    break;
+            }
+        }
 
+
+        private void OpenSettingModal(DataBase_Setting data)
+        {
+            DbSettingModal modal = new DbSettingModal(log)
+            {
+                Title = "鏂板鏁版嵁婧�",
+                Owner = Window.GetWindow(this)
+            };
+            if (modal.Open(-1, data, Settings, SourceFilePath) == true)
+            {
+                LoadData();
+            }
+        }
+
+        private void SearchData()
+        {
+            string program = programInput.Text;
+            if (!Map.ContainsKey(program))
+            {
+                ToastHelper.Error(Window.GetWindow(this), "鍙傛暟寮傚父锛岃鍒锋柊閲嶈瘯");
+                return;
+            }
+
+            var datas = Datas?.Where(d => !string.IsNullOrEmpty(d.Value)).ToList();
+            if (datas == null || datas.Count <= 0)
+            {
+                ToastHelper.Warning(Window.GetWindow(this), "璇疯缃煡璇㈡潯浠跺��");
+                return;
+            }
+
+            DataBase_Setting setting = Map[program];
+            
+
+            string fields = string.Join(",", Datas?.Select(d => $"[{d.Key}]").ToList());
+
+            string conditon = string.Join(" AND ", datas.Select(d => $"[{d.Key}] {d.Condition} '{d.Value}'").ToList());
+            string timeCol = setting.TimeCol;
+            if (string.IsNullOrEmpty(timeCol))
+            {
+                timeCol = "time";
+            }
+            if (!string.IsNullOrEmpty(startTimeInput.Text))
+            {
+                conditon += $" AND {timeCol} >= '{startTimeInput.Text}'";
+            }
+            if (!string.IsNullOrEmpty(endTimeInput.Text))
+            {
+                conditon += $" AND {timeCol} < '{endTimeInput.Text}'";
+            }
+            conditon = string.IsNullOrEmpty(conditon) ? string.Empty : $" WHERE {conditon}";
+            
+            SqliteHelper helper = null;
+            string sql = string.Empty;
+            try
+            {
+                helper = new SqliteHelper(setting.DBFilePath);
+                sql = $"SELECT {fields} FROM {setting.TableName} {conditon}";
+                DataTable dt = helper.GetDataTable(sql);
+
+                dataTable.ItemsSource = dt.DefaultView;
+            }
+            catch (Exception ex)
+            {
+                log.Error($"Select Data Failed. SQL: {sql}", ex);
+                ToastHelper.Error(Window.GetWindow(this), $"鏌ヨ澶辫触锛亄ex.Message}");
+
+            }
+            finally
+            {
+                helper?.Close();
+            }
+        }
+
+        private void ResetDataTable()
+        {
+            startTimeInput.SelectedDateTime = null;
+            endTimeInput.SelectedDateTime = null;
+            dataTable.ItemsSource = null;
+            foreach (var data in Datas)
+            {
+                data.Value = null;
+            }
+        }
+
+        public override void SetBaseFolder(string folder)
+        {
+            base.SetBaseFolder(folder);
+            SourceFilePath = Path.Combine(BaseFolder, "SourceData.setting");
+        }
+
+        private void PluginControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            LoadData();
+            Loaded -= PluginControl_Loaded;
+        }
+
+        private void LoadData()
+        {
+            if (File.Exists(SourceFilePath))
+            {
+                List<string> names = new List<string>();
+                Settings = XmlHelper.DeserializeFromXml<ObservableCollection<DataBase_Setting>>(SourceFilePath);
+                Map.Clear();
+                foreach (var data in Settings)
+                {
+                    Map.Add(data.Program, data);
+                    names.Add(data.Program);
+                }
+                programInput.ItemsSource = names;
+            }
+        }
+
+        private void programInput_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            var key = e.AddedItems[0].ToString();
+            if (!Map.ContainsKey(key))
+            {
+                ToastHelper.Error(Window.GetWindow(this), "鍙傛暟寮傚父锛岃鍒锋柊閲嶈瘯");
+                return;
+            }
+            DataBase_Setting setting = Map[key];
+            Datas = new ObservableCollection<QueryData>(
+                setting?.Condition?.Select(d => new QueryData { Key = d.Key, Name = d.Desc, Condition = "=" }).ToList());
+
+            var temp = dataTable.Columns[0];
+            dataTable.Columns.Clear();
+            dataTable.Columns.Add(temp);
+            foreach (var data in Datas)
+            {
+                AddDataGridTextColumn(data.Name, data.Key);
+            }
+        }
+
+        private void AddDataGridTextColumn(string header, string bindingPath)
+        {
+            DataGridTextColumn textColumn = new DataGridTextColumn
+            {
+                Header = header,
+                Binding = new Binding(bindingPath)
+                ,
+                Width = new DataGridLength(1, DataGridLengthUnitType.Star)
+            };
+            dataTable.Columns.Add(textColumn);
         }
     }
 }
diff --git a/HMI.DataViewer/DbSettingModal.xaml b/HMI.DataViewer/DbSettingModal.xaml
new file mode 100644
index 0000000..b91d95f
--- /dev/null
+++ b/HMI.DataViewer/DbSettingModal.xaml
@@ -0,0 +1,113 @@
+锘�<pu:WindowX x:Class="HMI.DataViewer.DbSettingModal"
+            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+            xmlns:local="clr-namespace:HMI.DataViewer"
+            xmlns:pw="https://opensource.panuon.com/wpf"
+            xmlns:pu="https://opensource.panuon.com/wpf-ui"
+            xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI"
+            xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI"
+            xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI"
+            mc:Ignorable="d"
+            Title="Form"
+            SizeToContent="Height"
+            Width="800"
+            WindowStartupLocation="CenterOwner"
+            BorderBrush="#3E3E45"
+            BorderThickness="1"
+            Foreground="Black"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
+            pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
+            pu:WindowXCaption.Foreground="#FFF"
+            pu:WindowXCaption.Buttons="Close"
+            pu:WindowXModalDialog.Buttons="OKCancel"
+            pu:WindowXModalDialog.CancelButtonContent="鍙栨秷"
+            pu:WindowXModalDialog.OKButtonContent="淇濆瓨"
+            pu:WindowXModalDialog.ButtonPanelMargin="0,30,10,10">
+    <Grid Margin="10">
+        <StackPanel x:Name="formPanel">
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True" Header="鍚嶇О" GroupName="MyFormGroup">
+                <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="programInput"/>
+            </pu:FormGroup>
+
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True" Header="鏁版嵁鏂囦欢" GroupName="MyFormGroup">
+                <Grid>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition/>
+                        <ColumnDefinition Width="Auto"/>
+                    </Grid.ColumnDefinitions>
+                    <TextBox Style="{StaticResource EditorTextBoxStyle}" IsReadOnly="True" x:Name="dbFilePathInput"/>
+                    <Button Style="{StaticResource SearchButton}" x:Name="searchBtn" Click="Button_Click" Grid.Column="1"/>
+                </Grid>
+            </pu:FormGroup>
+
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True" Header="鏁版嵁琛�" GroupName="MyFormGroup">
+                <ComboBox Style="{StaticResource FormComboxStyle}" SelectedValuePath="Content" 
+                          x:Name="tableNameInput" SelectionChanged="ComboxSelectionChanged"/>
+            </pu:FormGroup>
+
+            <pu:FormGroup Header="瀛楁璁剧疆" Orientation="Vertical" GroupName="MyFormGroup">
+                <Grid dp:GridHelper.Space="10">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition/>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition/>
+                    </Grid.ColumnDefinitions>
+
+                    <DataGrid Style="{StaticResource DefaultDataGrid}"
+                              BorderThickness="1"
+                              pu:DataGridHelper.ColumnHeaderFontSize="12"
+                              SelectionMode="Extended"
+                              ItemsSource="{Binding Columns}" x:Name="columnTable">
+                        <DataGrid.Columns>
+                            <DataGridTemplateColumn Header="#" CanUserResize="False">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <TextBlock Text="{Binding Converter={StaticResource rowNumber},
+RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>
+                            <DataGridTextColumn Width="*" Binding="{Binding }" Header="瀛楁鍚�" />
+                        </DataGrid.Columns>
+                    </DataGrid>
+
+                    <StackPanel Grid.Column="1" VerticalAlignment="Stretch" dp:StackPanelHelper.ChildSpace="10">
+                        <Button Style="{StaticResource PrimaryButton}" x:Name="selectAllBtn" Click="Button_Click">鍏ㄩ��</Button>
+                        <Button Style="{StaticResource PrimaryButton}" x:Name="addBtn" Click="Button_Click">娣诲姞</Button>
+                        <Button Style="{StaticResource PrimaryButton}" x:Name="delBtn" Click="Button_Click">鍒犻櫎</Button>
+                    </StackPanel>
+
+                    <DataGrid Grid.Column="2" Style="{StaticResource DefaultDataGrid}"
+                              BorderThickness="1"
+                              IsReadOnly="False"
+                              pu:DataGridHelper.ColumnHeaderFontSize="12"
+                              ItemsSource="{Binding Conditions}" x:Name="conditionTable">
+                        <DataGrid.Columns>
+                            <DataGridTemplateColumn Header="#" CanUserResize="False" IsReadOnly="True">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <TextBlock Text="{Binding Converter={StaticResource rowNumber},
+RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>
+                            <DataGridTextColumn Width="*" IsReadOnly="True" Binding="{Binding Key}" Header="瀛楁鍚�" />
+                            <DataGridTextColumn Width="*" Binding="{Binding Desc}" Header="鏄剧ず鍚�" />
+                            <DataGridTemplateColumn Width="*" Header="鏄犲皠鏃堕棿" IsReadOnly="True">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <RadioButton IsChecked="{Binding IsTimeCol,Mode=OneWay}" 
+                                                     Click="RadioButton_Click"
+                                                     ></RadioButton>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>
+                        </DataGrid.Columns>
+                    </DataGrid>
+                </Grid>
+            </pu:FormGroup>
+        </StackPanel>
+    </Grid>
+</pu:WindowX>
diff --git a/HMI.DataViewer/DbSettingModal.xaml.cs b/HMI.DataViewer/DbSettingModal.xaml.cs
new file mode 100644
index 0000000..31bf8f0
--- /dev/null
+++ b/HMI.DataViewer/DbSettingModal.xaml.cs
@@ -0,0 +1,248 @@
+锘縰sing HMI.Core.Util;
+using HMI.DataViewer.Entity;
+using HMI.UI;
+using HMI.UI.Util;
+using log4net;
+using Microsoft.Win32;
+using Panuon.WPF.UI;
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Controls;
+
+namespace HMI.DataViewer
+{
+    /// <summary>
+    /// ModalWindow.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class DbSettingModal : WindowX
+    {
+        public DbSettingModal(ILog log)
+        {
+            this.log = log;
+            this.DataContext = this;
+            InitializeComponent();
+        }
+        private ILog log;
+        public string FilePath { get; private set; }
+        public int DataIndex { get; private set; }
+        public DataBase_Setting Data { get; private set; }
+        public ObservableCollection<DataBase_Setting> Datasource { get; private set; }
+
+        private SqliteHelper helper;
+        public SqliteHelper Helper
+        {
+            get => helper;
+            set
+            {
+                if (helper == value) return;
+                helper?.Close();
+                helper = value;
+            }
+        }
+
+        private ObservableCollection<string> columns = new ObservableCollection<string>();
+        public ObservableCollection<string> Columns
+        {
+            get => columns;
+            set { Set(ref columns, value); }
+        }
+
+        private ObservableCollection<QueryCondition> conditions =
+            new ObservableCollection<QueryCondition>();
+        public ObservableCollection<QueryCondition> Conditions
+        {
+            get => conditions;
+            set { Set(ref conditions, value); }
+        }
+
+
+        private bool _isProcessing;
+
+        protected override void OnClosing(CancelEventArgs e)
+        {
+            //Press Continue Button
+            if (DialogResult == true)
+            {
+                if (_isProcessing)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                var okButton = WindowXModalDialog.GetOKButton(this);
+                try
+                {
+                    _isProcessing = true;
+                    ButtonHelper.SetIsPending(okButton, true);
+                    if (!ValidateForm())
+                    {
+                        e.Cancel = true;
+                        return;
+                    }
+
+                    SaveOrUpdateData();
+                    Helper?.Close();
+                }
+                catch (Exception ex)
+                {
+                    log.Error("IPManage Form Submit Failed.", ex);
+                    ToastHelper.Error(this, $"鏈煡寮傚父锛亄ex.Message}");
+                    e.Cancel = true;
+                    return;
+                }
+                finally
+                {
+                    _isProcessing = false;
+                    ButtonHelper.SetIsPending(okButton, false);
+                }
+            }
+            base.OnClosing(e);
+        }
+
+        public bool ValidateDBAddress(object value, out string err)
+        {
+            err = null;
+
+            return true;
+        }
+
+        private bool ValidateForm()
+        {
+            bool flag = FormGroupHelper.ValidateForm(formPanel);
+            if (flag)
+            {
+                Data.Program = programInput.Text;
+                Data.DBFilePath = dbFilePathInput.Text;
+                Data.TableName = tableNameInput.Text;
+                Data.TimeCol = Conditions.FirstOrDefault(c => c.IsTimeCol)?.Key;
+                Data.Condition = Conditions;
+            }
+            return flag;
+        }
+
+        public bool? Open(int index, DataBase_Setting data,
+            ObservableCollection<DataBase_Setting> dataSource,
+            string filePath)
+        {
+            FilePath = filePath;
+            DataIndex = index;
+            Data = data;
+            Datasource = dataSource;
+
+            programInput.Text = Data.Program;
+            dbFilePathInput.Text = Data.DBFilePath;
+            tableNameInput.Text = Data.TableName;
+            
+            return this.ShowDialog();
+        }
+
+        private void SaveOrUpdateData()
+        {
+            if (DataIndex == -1)
+            {
+                InsertData(Data);
+            }
+            else
+            {
+                UpdateData(DataIndex, Data);
+            }
+        }
+
+        public void InsertData(DataBase_Setting data)
+        {
+            Datasource.Add(data);
+            XmlHelper.SerializeToXml(FilePath, Datasource);
+        }
+
+        public void UpdateData(int index, DataBase_Setting data)
+        {
+            Datasource[index] = data;
+            XmlHelper.SerializeToXml(FilePath, Datasource);
+        }
+
+        private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
+        {
+            Button btn = sender as Button;
+            switch (btn.Name) {
+                case "searchBtn":
+                    OpenSelectDbDialog();
+                    break;
+                case "selectAllBtn":
+                    SelectAll();
+                    break;
+                case "addBtn":
+                    AddCondition();
+                    break;
+                case "delBtn":
+                    break;
+                default:
+                    break;
+            }
+
+            
+        }
+
+        private void OpenSelectDbDialog()
+        {
+            string BasePath = PathHelper.IconFolder;
+
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+            openFileDialog.Filter = "(*.db)|*.db";
+            openFileDialog.InitialDirectory = BasePath;
+            openFileDialog.Title = "閫夋嫨鏁版嵁搴撴枃浠�";
+            openFileDialog.Multiselect = false;
+
+            if (openFileDialog.ShowDialog() == true)
+            {
+                string FileName = openFileDialog.FileName;
+                dbFilePathInput.Text = FileName;
+                Helper = new SqliteHelper(FileName);
+                string[] tableNames = Helper.GetAllTableInFile();
+                tableNameInput.ItemsSource = tableNames;
+            }
+        }
+
+        private void SelectAll()
+        {
+            columnTable.SelectAll();
+            AddCondition();
+        }
+
+        private void AddCondition()
+        {
+            if (columnTable.SelectedItems == null || columnTable.SelectedItems.Count <= 0) return;
+            var temp = new ObservableCollection<QueryCondition>();
+            foreach (var column in columnTable.SelectedItems)
+            {
+                temp.Add(new QueryCondition { Key = column.ToString(), Desc = column.ToString() });
+            }
+            Conditions = temp;
+        }
+
+
+        private void ComboxSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
+        {
+            string[] cols = Helper.GetColumnNameFromTable(e.AddedItems[0].ToString());
+            Columns = new ObservableCollection<string>(cols);
+        }
+
+        private void RadioButton_Click(object sender, System.Windows.RoutedEventArgs e)
+        {
+            RadioButton btn = sender as RadioButton;
+            var condition = btn.DataContext as QueryCondition;
+            if (condition.IsTimeCol == true)
+            {
+                condition.IsTimeCol = false;
+            }
+            else
+            {
+                condition.IsTimeCol = true;
+                foreach (var c in Conditions)
+                {
+                    if (c != condition) c.IsTimeCol = false;
+                }
+            }
+        }
+    }
+}
diff --git a/HMI.DataViewer/Entity/DataBase_Setting.cs b/HMI.DataViewer/Entity/DataBase_Setting.cs
new file mode 100644
index 0000000..a1c12d1
--- /dev/null
+++ b/HMI.DataViewer/Entity/DataBase_Setting.cs
@@ -0,0 +1,106 @@
+锘縰sing HMI.Core.Entity;
+using HMI.Core.Util;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace HMI.DataViewer.Entity
+{
+    /// <summary>
+    /// 鏁版嵁搴撻厤缃被
+    /// </summary>
+    [Serializable]
+    public class DataBase_Setting : NotifyBase
+    {
+        /// <summary>
+        /// 鏁版嵁搴撴枃浠惰矾寰�
+        /// </summary>
+        private string dBFilePath = string.Empty;
+
+        /// <summary>
+        /// 鏁版嵁搴撴搷浣滅被
+        /// </summary>
+        private SqliteHelper sql = null;
+
+        /// <summary>
+        /// 鏁版嵁琛ㄥ悕绉�
+        /// </summary>
+        private string tableName = string.Empty;
+
+        /// <summary>
+        /// 璁惧畾绋嬪簭鍚�
+        /// </summary>
+        private string program = string.Empty;
+
+        private string timeCol = string.Empty;
+
+        /// <summary>
+        /// 楂樼骇鏌ヨ鏉′欢
+        /// </summary>
+        private ObservableCollection<QueryCondition> condition = new ObservableCollection<QueryCondition>();
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        public DataBase_Setting()
+        {
+            // do nothing
+        }
+
+        /// <summary>
+        /// 鏁版嵁搴撴枃浠剁殑瀛樺偍璺緞
+        /// </summary>
+        public string DBFilePath
+        {
+            get => dBFilePath;
+            set { Set(ref dBFilePath, value); }
+        }
+        
+        public string TimeCol
+        {
+            get => timeCol;
+            set { Set(ref timeCol, value); }
+        }
+
+        /// <summary>
+        /// 鏁版嵁搴撴搷浣滃彞鏌�
+        /// </summary>
+        [XmlIgnore]
+        public SqliteHelper SQL
+        {
+            get { return this.sql; }
+            set { this.sql = value; }
+        }
+
+        /// <summary>
+        /// 楂樼骇鏌ヨ鏉′欢
+        /// </summary>
+        public ObservableCollection<QueryCondition> Condition
+        {
+            get { return this.condition; }
+            set { Set(ref condition, value); }
+        }
+
+        /// <summary>
+        /// 鏁版嵁琛ㄥ悕绉�
+        /// </summary>
+        public string TableName
+        {
+            get { return this.tableName; }
+            set { Set(ref tableName, value); }
+        }
+
+        /// <summary>
+        /// 璁惧畾绋嬪簭鍚�
+        /// </summary>
+        public string Program
+        {
+            get { return this.program; }
+            set { Set(ref program, value); }
+        }
+    }
+}
diff --git a/HMI.DataViewer/Entity/QueryCondition.cs b/HMI.DataViewer/Entity/QueryCondition.cs
new file mode 100644
index 0000000..e4a3781
--- /dev/null
+++ b/HMI.DataViewer/Entity/QueryCondition.cs
@@ -0,0 +1,50 @@
+锘縰sing HMI.Core.Entity;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HMI.DataViewer.Entity
+{
+    /// <summary>
+    /// 绛涢�夋潯浠剁被
+    /// </summary>
+    public class QueryCondition : NotifyBase
+    {
+        /// <summary>
+        /// 鏌ヨ鐨勯敭鍊�
+        /// </summary>
+        private string key = string.Empty;
+
+        /// <summary>
+        /// 閿�兼弿杩�
+        /// </summary>
+        private string desc = string.Empty;
+
+        /// <summary>
+        /// 鏌ヨ鐨勯敭鍊�
+        /// </summary>
+        public string Key
+        {
+            get { return this.key; }
+            set { Set(ref key, value); }
+        }
+
+        /// <summary>
+        /// 閿�兼弿杩�
+        /// </summary>
+        public string Desc
+        {
+            get { return this.desc; }
+            set { Set(ref desc, value); }
+        }
+
+        private bool isTimeCol;
+        public bool IsTimeCol
+        {
+            get => isTimeCol;
+            set { Set(ref isTimeCol, value); }
+        }
+    }
+}
diff --git a/HMI.DataViewer/Entity/QueryData.cs b/HMI.DataViewer/Entity/QueryData.cs
new file mode 100644
index 0000000..16adfea
--- /dev/null
+++ b/HMI.DataViewer/Entity/QueryData.cs
@@ -0,0 +1,36 @@
+锘縰sing HMI.Core.Entity;
+
+namespace HMI.DataViewer.Entity
+{
+    public class QueryData : NotifyBase
+    {
+        private string key;
+        private string name;
+        private string condition;
+        private string _value;
+
+        public string Key
+        {
+            get => key;
+            set => Set(ref key, value);
+        }
+
+        public string Name
+        {
+            get => name;
+            set => Set(ref name, value);
+        }
+
+        public string Condition
+        {
+            get => condition;
+            set => Set(ref condition, value);
+        }
+
+        public string Value
+        {
+            get => _value;
+            set => Set(ref _value, value);
+        }
+    }
+}
diff --git a/HMI.DataViewer/HMI.DataViewer.csproj b/HMI.DataViewer/HMI.DataViewer.csproj
index 3a115ca..175f913 100644
--- a/HMI.DataViewer/HMI.DataViewer.csproj
+++ b/HMI.DataViewer/HMI.DataViewer.csproj
@@ -85,8 +85,18 @@
       <DependentUpon>DataViewer.xaml</DependentUpon>
       <SubType>Code</SubType>
     </Compile>
+    <Page Include="DbSettingModal.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Entity\QueryCondition.cs" />
+    <Compile Include="Entity\DataBase_Setting.cs" />
+    <Compile Include="DbSettingModal.xaml.cs">
+      <DependentUpon>DbSettingModal.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Entity\QueryData.cs" />
     <Compile Include="Properties\AssemblyInfo.cs">
       <SubType>Code</SubType>
     </Compile>
@@ -125,4 +135,8 @@
     </ProjectReference>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>copy /Y "$(TargetPath)" "$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)\Plugin\$(TargetFileName)" 
+copy /Y "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)bin\$(PlatformName)\$(ConfigurationName)\Plugin\$(TargetName).pdb"</PostBuildEvent>
+  </PropertyGroup>
 </Project>
\ No newline at end of file
diff --git a/HMI.IOMonitor/Entity/DIO.cs b/HMI.IOMonitor/Entity/DIO.cs
new file mode 100644
index 0000000..a0ef04c
--- /dev/null
+++ b/HMI.IOMonitor/Entity/DIO.cs
@@ -0,0 +1,61 @@
+锘縰sing HMI.Core.Entity;
+using System;
+
+namespace HMI.IOMonitor.Entity
+{
+    /// <summary>
+    /// DIO灞炴�х被
+    /// </summary>
+    [Serializable]
+    public class DIO :NotifyBase
+    {
+        public DIO()
+        {
+        }
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="diotype">DIO绫诲瀷</param>
+        /// <param name="name">DIO鍚嶇О</param>
+        /// <param name="no">DIO缂栧彿</param>
+        /// <param name="value">DIO鐨勫��</param>
+        public DIO(string diotype, string name, string no, bool value)
+        {
+            this.DIOType = diotype;
+            this.Name = name;
+            this.No = no;
+            this.Value = value;
+        }
+
+
+        /// <summary>
+        /// DIO绫诲瀷
+        /// </summary>
+        private string dIOType;
+        public string DIOType { get => dIOType; set { Set(ref dIOType, value); } }
+
+        /// <summary>
+        /// 绾紪鍙�
+        /// </summary>
+        private decimal dioNo;
+        public decimal DIO_No { get => dioNo; set { Set(ref dioNo, value); } }
+
+        /// <summary>
+        /// 鍚嶇О
+        /// </summary>
+        private string name;
+        public string Name { get => name; set { Set(ref name, value); } }
+
+        /// <summary>
+        /// DIO缂栧彿
+        /// </summary>
+        public string No { get; set; }
+
+        ////[XmlIgnore]
+
+        /// <summary>
+        /// DIO鐨勫��
+        /// </summary>
+        public bool Value { get; set; }
+    }
+}
diff --git a/HMI.IOMonitor/Entity/DioData.cs b/HMI.IOMonitor/Entity/DioData.cs
deleted file mode 100644
index 3aa4595..0000000
--- a/HMI.IOMonitor/Entity/DioData.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-锘縰sing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace HMI.IOMonitor.Entity
-{
-    public class DioData
-    {
-    }
-}
diff --git a/HMI.IOMonitor/Entity/IPManage.cs b/HMI.IOMonitor/Entity/IPManage.cs
new file mode 100644
index 0000000..cffec4c
--- /dev/null
+++ b/HMI.IOMonitor/Entity/IPManage.cs
@@ -0,0 +1,18 @@
+锘縩amespace HMI.IOMonitor.Entity
+{
+    /// <summary>
+    /// IP绠$悊绫�
+    /// </summary>
+    public class IPManage
+    {
+        /// <summary>
+        /// itag
+        /// </summary>
+        public string DItag { get; set; }
+
+        /// <summary>
+        /// qtag
+        /// </summary>
+        public string DQtag { get; set; }
+    }
+}
diff --git a/HMI.IOMonitor/HMI.IOMonitor.csproj b/HMI.IOMonitor/HMI.IOMonitor.csproj
index a8c39f4..9e31d40 100644
--- a/HMI.IOMonitor/HMI.IOMonitor.csproj
+++ b/HMI.IOMonitor/HMI.IOMonitor.csproj
@@ -50,14 +50,35 @@
     <ErrorReport>prompt</ErrorReport>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
+    </Reference>
     <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
       <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OOXML, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OOXML.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OpenXml4Net, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXml4Net.dll</HintPath>
+    </Reference>
+    <Reference Include="NPOI.OpenXmlFormats, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
+      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXmlFormats.dll</HintPath>
+    </Reference>
+    <Reference Include="OpcInterface">
+      <HintPath>..\Libs\OpcInterface.dll</HintPath>
     </Reference>
     <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
     </Reference>
     <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
+    </Reference>
+    <Reference Include="SimensDriver">
+      <HintPath>..\Libs\SimensDriver.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
@@ -77,11 +98,19 @@
     <Reference Include="PresentationFramework" />
   </ItemGroup>
   <ItemGroup>
+    <Page Include="IPManageModal.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="IOMonitor.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
-    <Compile Include="Entity\DioData.cs" />
+    <Compile Include="IPManageModal.xaml.cs">
+      <DependentUpon>IPManageModal.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Entity\DIO.cs" />
+    <Compile Include="Entity\IPManage.cs" />
     <Compile Include="IOMonitor.xaml.cs">
       <DependentUpon>IOMonitor.xaml</DependentUpon>
       <SubType>Code</SubType>
diff --git a/HMI.IOMonitor/IOMonitor.xaml b/HMI.IOMonitor/IOMonitor.xaml
index 26a0da3..3cd6837 100644
--- a/HMI.IOMonitor/IOMonitor.xaml
+++ b/HMI.IOMonitor/IOMonitor.xaml
@@ -9,118 +9,222 @@
              xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI"
              xmlns:pw="https://opensource.panuon.com/wpf"
              xmlns:pu="https://opensource.panuon.com/wpf-ui"
-             xmlns:dp="clr-namespace:HMI.UI;assembly=HMI.UI"
-             mc:Ignorable="d" 
-             Padding="10"
+             xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI"
+             mc:Ignorable="d"
              Loaded="UserControl_Loaded"
              Background="{StaticResource WorkspaceBackground}"
              d:DesignHeight="450" d:DesignWidth="800">
-    <Grid>
-        <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="5*"/>
-            <ColumnDefinition Width="5*"/>
-        </Grid.ColumnDefinitions>
 
-        <Border Style="{StaticResource CardBoarder}" Margin="0,0,2,0">
-            <StackPanel>
-                <DockPanel Margin="0,0,0,10">
-                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe934;" Style="{StaticResource DangerButton}">鍒犻櫎</Button>
-                    <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
-pu:IconHelper.FontFamily="{StaticResource iconfont}"
-pu:ButtonHelper.Icon="&#xe631;" Margin="0,0,10,0" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
-                    <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
-            pu:IconHelper.FontFamily="{StaticResource iconfont}"
-            pu:ButtonHelper.Icon="&#xe61a;" Margin="0,0,10,0" x:Name="addBtn" Click="Button_Click">鏂板</Button>
-                    <TextBlock DockPanel.Dock="Left" FontSize="{StaticResource TitleFontSize}" 
-                           VerticalAlignment="Center" HorizontalAlignment="Left" Text="鑿滃崟鍒楄〃"/>
-                </DockPanel>
+    <UserControl.Resources>
+        <Style TargetType="Label">
+            <Setter Property="VerticalContentAlignment" Value="Center"/>
+            <Setter Property="VerticalAlignment" Value="Center"/>
+        </Style>
+        <CollectionViewSource x:Key="disFilter" Source="{Binding Dis}" Filter="CollectionViewSource_Filter"/>
+        <CollectionViewSource x:Key="dosFilter" Source="{Binding Dos}" Filter="CollectionViewSource_Filter"/>
+    </UserControl.Resources>
 
-                <DataGrid Grid.Column="1" x:Name="diTable" Style="{StaticResource DefaultDataGrid}" ItemsSource="{Binding DataSource}">
-                    <DataGrid.Columns>
-                        <DataGridTemplateColumn Header="" Width="Auto" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <CheckBox VerticalAlignment="Center" IsChecked="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                        <DataGridTemplateColumn Header="#" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <TextBlock Text="{Binding Converter={StaticResource rowNumber},
-                    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                        <DataGridTextColumn Width="*" Binding="{Binding Code}" Header="缂栧彿" />
-                        <DataGridTextColumn Width="*" Binding="{Binding Name}" Header="鍚嶇О" />
-                        <DataGridTextColumn Width="*" Binding="{Binding Type}" Header="绫诲瀷" />
-                        <DataGridTextColumn Width="*" Binding="{Binding Value}" Header="DI鍊�" />
-                        <DataGridTemplateColumn Header="鎿嶄綔" Width="100" IsReadOnly="True" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <StackPanel Orientation="Horizontal">
-                                        <Button x:Name="editBtn" Style="{StaticResource RowLink}" 
-                            Margin="0,0,10,0" 
-                            Click="Button_Click"
-                            DataContext="{Binding }">缂栬緫</Button>
-                                        <Button x:Name="delBtn" Style="{StaticResource DangerLinkButton}" 
-                            DataContext="{Binding }"
-                            Click="Button_Click">鍒犻櫎</Button>
-                                    </StackPanel>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                    </DataGrid.Columns>
-                </DataGrid>
-            </StackPanel>
-        </Border>
+    <Border Grid.Row="1" Style="{StaticResource CardBoarder}">
+        <Grid dp:GridHelper.Space="10">
+            <Grid.RowDefinitions>
+                <RowDefinition Height="Auto"/>
+                <RowDefinition/>
+            </Grid.RowDefinitions>
 
-        <Border Grid.Column="1" Style="{StaticResource CardBoarder}" Margin="2,0,0,0">
-            <StackPanel>
-                <DockPanel Margin="0,0,0,10" >
-                    <TextBlock DockPanel.Dock="Left" FontSize="{StaticResource TitleFontSize}" 
-                   VerticalAlignment="Center" HorizontalAlignment="Left" Text="鑿滃崟缁撴瀯"/>
-                </DockPanel>
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="5*"/>
+                <ColumnDefinition Width="5*"/>
+            </Grid.ColumnDefinitions>
 
-                <DataGrid Grid.Column="1" x:Name="doTable" Style="{StaticResource DefaultDataGrid}" ItemsSource="{Binding DataSource}">
-                    <DataGrid.Columns>
-                        <DataGridTemplateColumn Header="" Width="Auto" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <CheckBox VerticalAlignment="Center" IsChecked="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                        <DataGridTemplateColumn Header="#" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <TextBlock Text="{Binding Converter={StaticResource rowNumber},
+            <DockPanel Grid.Row="0" Grid.ColumnSpan="2">
+                <StackPanel DockPanel.Dock="Right" Style="{StaticResource ButtonGroup}">
+                    <Button Style="{StaticResource PrimaryButton}" x:Name="addBtn" Click="Button_Click">鏂板</Button>
+                    <Button Style="{StaticResource PrimaryButton}" x:Name="importBtn" Click="Button_Click">瀵煎叆</Button>
+                </StackPanel>
+                
+                <TextBlock DockPanel.Dock="Left" VerticalAlignment="Center" 
+                       FontSize="{StaticResource TitleFontSize}" Text="DIO鐩戞帶"/>
+            </DockPanel>
+
+            <Border Grid.Row="1" Style="{StaticResource CardBoarder}" Padding="0">
+                <Grid dp:GridHelper.Space="10">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition />
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="Auto"/>
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="Auto"/>
+                        <RowDefinition Height="Auto"/>
+                        <RowDefinition Height="Auto"/>
+                        <RowDefinition/>
+                    </Grid.RowDefinitions>
+
+                    <Label Grid.Row="0" Grid.Column="0" Content="DI鍚嶇О"
+                       FontSize="{StaticResource TitleFontSize}"/>
+                    <ComboBox Grid.Row="0" Grid.Column="1" x:Name="diName" 
+                          IsEditable="True" Style="{StaticResource FormComboxStyle}"/>
+
+                    <Button Style="{StaticResource PrimaryButton}" Grid.Row="0" Grid.Column="2" 
+                        x:Name="diSelect" Click="Button_Click"
+                        >DI鏌ヨ</Button>
+                    <Button Style="{StaticResource PrimaryButton}" Grid.Row="0" Grid.Column="3"
+                        x:Name="diReset" Click="Button_Click">DI閲嶇疆</Button>
+
+                    <Label Grid.Row="1" Grid.Column="0" Content="DI缂栧彿"
+       FontSize="{StaticResource TitleFontSize}"/>
+                    <ComboBox Grid.Row="1" Grid.Column="1" x:Name="diCode" 
+                          IsEditable="True"
+                          Style="{StaticResource FormComboxStyle}"/>
+
+                    <Label Grid.Row="2" Grid.Column="0" Content="DI鍒嗙粍"
+       FontSize="{StaticResource TitleFontSize}"/>
+                    <ComboBox Grid.Row="2" Grid.Column="1" x:Name="diGroup" 
+                          IsEditable="True" Style="{StaticResource FormComboxStyle}"/>
+
+                    <DataGrid Grid.Row="3" Grid.ColumnSpan="4" x:Name="diTable" Style="{StaticResource DefaultDataGrid}" 
+                          ItemsSource="{Binding Source={StaticResource disFilter}}">
+
+                        <DataGrid.RowStyle>
+                            <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Static pu:StyleKeys.DataGridRowStyle}}">
+                                <Style.Triggers>
+                                    <DataTrigger Binding="{Binding Value}" Value="True">
+                                        <Setter Property="Background" Value="{StaticResource DangerColor}"/>
+                                        <Setter Property="Foreground" Value="{StaticResource DangerColorContrast}"/>
+                                    </DataTrigger>
+                                </Style.Triggers>
+                            </Style>
+                        </DataGrid.RowStyle>
+                        <DataGrid.Columns>
+                            <!--<DataGridTemplateColumn Header="" Width="Auto" CanUserResize="False">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <CheckBox VerticalAlignment="Center" IsChecked="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>-->
+                            <DataGridTemplateColumn Header="#" CanUserResize="False">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <TextBlock Text="{Binding Converter={StaticResource rowNumber},
     RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                        <DataGridTextColumn Width="*" Binding="{Binding Code}" Header="缂栧彿"/>
-                        <DataGridTextColumn Width="*" Binding="{Binding Name}" Header="鍚嶇О" />
-                        <DataGridTextColumn Width="*" Binding="{Binding Type}" Header="绫诲瀷" />
-                        <DataGridTextColumn Width="*" Binding="{Binding Value}" Header="DO鍊�" />
-                        <DataGridTemplateColumn Header="鎿嶄綔" Width="100" IsReadOnly="True" CanUserResize="False">
-                            <DataGridTemplateColumn.CellTemplate>
-                                <DataTemplate>
-                                    <StackPanel Orientation="Horizontal" ui:StackPanelHelper.ChildSpace="10">
-                                        <Button x:Name="editBtn" Style="{StaticResource RowLink}"
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>
+                            <DataGridTextColumn Width="*" Binding="{Binding Code}" Header="缂栧彿" />
+                            <DataGridTextColumn Width="*" Binding="{Binding Name}" Header="鍚嶇О" />
+                            <DataGridTextColumn Width="*" Binding="{Binding Type}" Header="绫诲瀷" />
+                            <DataGridTextColumn Width="*" Binding="{Binding Value}" Header="DI鍊�" />
+                            <!--<DataGridTemplateColumn Header="鎿嶄綔" Width="100" IsReadOnly="True" CanUserResize="False">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <StackPanel Orientation="Horizontal">
+                                            <Button x:Name="editBtn" Style="{StaticResource RowLink}" 
+            Margin="0,0,10,0" 
             Click="Button_Click"
             DataContext="{Binding }">缂栬緫</Button>
-                                        <Button x:Name="delBtn" Style="{StaticResource DangerLinkButton}" 
+                                            <Button x:Name="delBtn" Style="{StaticResource DangerLinkButton}" 
             DataContext="{Binding }"
             Click="Button_Click">鍒犻櫎</Button>
-                                    </StackPanel>
-                                </DataTemplate>
-                            </DataGridTemplateColumn.CellTemplate>
-                        </DataGridTemplateColumn>
-                    </DataGrid.Columns>
-                </DataGrid>
-            </StackPanel>
-        </Border>
-    </Grid>
+                                        </StackPanel>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>-->
+                        </DataGrid.Columns>
+                    </DataGrid>
+                </Grid>
+
+
+            </Border>
+
+            <Border Grid.Row="1" Grid.Column="1" Style="{StaticResource CardBoarder}" Padding="0">
+                <Grid dp:GridHelper.Space="10">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition />
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="Auto"/>
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="Auto"/>
+                        <RowDefinition Height="Auto"/>
+                        <RowDefinition Height="Auto"/>
+                        <RowDefinition/>
+                    </Grid.RowDefinitions>
+
+                    <Label Grid.Row="0" Grid.Column="0" Content="DO鍚嶇О"
+                   FontSize="{StaticResource TitleFontSize}"/>
+                    <ComboBox Grid.Row="0" Grid.Column="1" x:Name="doName"
+                          IsEditable="True" Style="{StaticResource FormComboxStyle}"/>
+
+                    <Button Style="{StaticResource PrimaryButton}" Grid.Row="0" Grid.Column="2"
+                        x:Name="doSelect" Click="Button_Click">DO鏌ヨ</Button>
+                    <Button Style="{StaticResource PrimaryButton}" Grid.Row="0" Grid.Column="3"
+                        x:Name="doReset" Click="Button_Click"
+                        >DO閲嶇疆</Button>
+
+                    <Label Grid.Row="1" Grid.Column="0" Content="DO缂栧彿"
+   FontSize="{StaticResource TitleFontSize}"/>
+                    <ComboBox Grid.Row="1" Grid.Column="1" x:Name="doCode"
+                          IsEditable="True" Style="{StaticResource FormComboxStyle}"/>
+
+                    <Label Grid.Row="2" Grid.Column="0" Content="DO鍒嗙粍"
+   FontSize="{StaticResource TitleFontSize}"/>
+                    <ComboBox Grid.Row="2" Grid.Column="1" x:Name="doGroup"
+                          IsEditable="True" Style="{StaticResource FormComboxStyle}"/>
+
+                    <DataGrid Grid.Row="3" Grid.ColumnSpan="4" x:Name="doTable" Style="{StaticResource DefaultDataGrid}" 
+                      ItemsSource="{Binding Source={StaticResource dosFilter}}">
+                        <DataGrid.RowStyle>
+                            <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Static pu:StyleKeys.DataGridRowStyle}}">
+                                <Style.Triggers>
+                                    <DataTrigger Binding="{Binding Value}" Value="True">
+                                        <Setter Property="Background" Value="{StaticResource DangerColor}"/>
+                                        <Setter Property="Foreground" Value="{StaticResource DangerColorContrast}"/>
+                                    </DataTrigger>
+                                </Style.Triggers>
+                            </Style>
+                        </DataGrid.RowStyle>
+                        <DataGrid.Columns>
+                            <!--<DataGridTemplateColumn Header="" Width="Auto" CanUserResize="False">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <CheckBox VerticalAlignment="Center" IsChecked="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>-->
+                            <DataGridTemplateColumn Header="#" CanUserResize="False">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <TextBlock Text="{Binding Converter={StaticResource rowNumber},
+RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>
+                            <DataGridTextColumn Width="*" Binding="{Binding Code}" Header="缂栧彿" />
+                            <DataGridTextColumn Width="*" Binding="{Binding Name}" Header="鍚嶇О" />
+                            <DataGridTextColumn Width="*" Binding="{Binding Type}" Header="绫诲瀷" />
+                            <DataGridTextColumn Width="*" Binding="{Binding Value}" Header="DO鍊�" />
+                            <!--<DataGridTemplateColumn Header="鎿嶄綔" Width="100" IsReadOnly="True" CanUserResize="False">
+                                <DataGridTemplateColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <StackPanel Orientation="Horizontal">
+                                            <Button x:Name="editBtn" Style="{StaticResource RowLink}" 
+        Margin="0,0,10,0" 
+        Click="Button_Click"
+        DataContext="{Binding }">缂栬緫</Button>
+                                            <Button x:Name="delBtn" Style="{StaticResource DangerLinkButton}" 
+        DataContext="{Binding }"
+        Click="Button_Click">鍒犻櫎</Button>
+                                        </StackPanel>
+                                    </DataTemplate>
+                                </DataGridTemplateColumn.CellTemplate>
+                            </DataGridTemplateColumn>-->
+                        </DataGrid.Columns>
+                    </DataGrid>
+                </Grid>
+            </Border>
+        </Grid>
+    </Border>
 </hb:PluginControl>
\ No newline at end of file
diff --git a/HMI.IOMonitor/IOMonitor.xaml.cs b/HMI.IOMonitor/IOMonitor.xaml.cs
index cae019c..99394ff 100644
--- a/HMI.IOMonitor/IOMonitor.xaml.cs
+++ b/HMI.IOMonitor/IOMonitor.xaml.cs
@@ -1,8 +1,26 @@
-锘縰sing System.Windows;
+锘縰sing System.Collections.Generic;
+using System.Configuration;
+using System;
+using System.Windows;
 using System.Windows.Controls;
 using HMI.Base;
 using HMI.Core.Api;
+using HMI.IOMonitor.Entity;
 using log4net;
+using System.Linq;
+using System.IO;
+using HMI.Core.Util;
+using System.Collections.ObjectModel;
+using HMI.Core.Setting;
+using HMI.UI.Util;
+using System.Timers;
+using System.Windows.Media;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using Microsoft.Win32;
+using NPOI.SS.UserModel;
+using NPOI.XSSF.UserModel;
+using NPOI.HSSF.UserModel;
 
 namespace HMI.IOMonitor
 {
@@ -11,19 +29,474 @@
     /// </summary>
     public partial class IOMonitor : PluginControl
     {
+        public string SettingFilePath { get; private set; }
+        public string DataFilePath { get; private set; }
+        /// <summary>
+        /// DIO鍦板潃
+        /// </summary>
+        private string DITag = string.Empty;
+        private string DQTag = string.Empty;
+        private SystemSetting systemSetting;
+        private Timer MonitorTimer;
+        private OpcInterface.OpcInterface lTSCADAApi = new OpcInterface.OpcInterface();
+
+
+        /// <summary>
+        /// The diosde 鍙嶅簭鍒楀寲鐨凞IO瀵硅薄
+        /// </summary>
+        private List<DIO> diosde = new List<DIO>();
+        /// <summary>The dis
+        /// DI鍙e璞�
+        /// </summary>
+        private ObservableCollection<DIO> _dis = new ObservableCollection<DIO>() {
+            new DIO(null,null,null,false),
+            new DIO(null,null,null,true),
+        };
+        public ObservableCollection<DIO> Dis
+        {
+            get => _dis;
+            set { Set(ref _dis, value); }
+        }
+
+        private ObservableCollection<DIO> _dos = new ObservableCollection<DIO>() {
+            new DIO(null,null,null,false),
+            new DIO(null,null,null,true),
+        };
+        public ObservableCollection<DIO> Dos
+        {
+            get => _dos;
+            set { Set(ref _dos, value); }
+        }
+
+        private ObservableCollection<IPManage> iPManages = new ObservableCollection<IPManage>();
+
+        public ObservableCollection<IPManage> IPManages
+        {
+            get { return iPManages; }
+            set { Set(ref iPManages, value); }
+        }
+
+
         public IOMonitor()
         {
+            systemSetting = SystemSetting.Instance;
+            MonitorTimer = new Timer()
+            {
+                Interval = 100
+            };
+            MonitorTimer.Elapsed += MonitorTimer_Elapsed;
+            DataContext = this;
             InitializeComponent();
+        }
+
+        private void MonitorTimer_Elapsed(object sender, ElapsedEventArgs e)
+        {
+            MonitorTimer.Enabled = false;
+            try
+            {
+                // stopwatch.Start();
+                if (lTSCADAApi.DoFctReadSingle(DITag, out string resulti, out string errMsgi))
+                {
+                    byte[] stri = HexUtil.ToBytesFromHexString(resulti);
+                    Array.Reverse(stri);
+                    if (stri != null)
+                    {
+                        for (int i = 0; i < Dis.Count; i++)
+                        {
+                            Dis[i].Value = Convert.ToBoolean(GetValue(stri, "bool", Dis[i].DIO_No.ToString()));
+                        }
+                    }
+                }
+
+                if (lTSCADAApi.DoFctReadSingle(DQTag, out string resulto, out string errMsgo))
+                {
+                    byte[] stro = HexUtil.ToBytesFromHexString(resulto);
+                    if (stro != null)
+                    {
+                        for (int i = 0; i < Dos.Count; i++)
+                        {
+                            Dos[i].Value = Convert.ToBoolean(GetValue(stro, "bool", Dos[i].DIO_No.ToString()));
+                        }
+                    }
+                }
+
+                //stopwatch.Stop();
+            }
+            catch (Exception ex)
+            {
+                log.Warn("MonitorTimer_Elapsed Execute Failed.", ex);
+                MonitorTimer.Enabled = true;
+                return;
+            }
+            finally
+            {
+                this.MonitorTimer.Enabled = true;
+            }
+        }
+
+        /// <summary>
+        /// 鍒濆鍖栨柟娉�
+        /// </summary>
+        private void LoadData()
+        {
+            diosde.Clear();
+            //Dis.Clear();
+            //Dos.Clear();
+
+            diName.Items.Clear();
+            doName.Items.Clear();
+            diGroup.Items.Clear();
+            doGroup.Items.Clear();
+            try
+            {
+                this.diosde = XmlHelper.DeserializeFromXml<List<DIO>>(DataFilePath);
+            }
+            catch (Exception ex)
+            {
+                MsgBoxHelper.Error(this, ex.Message);
+            }
+
+            if (diosde.Count != 0)
+            {
+                for (int i = 0; i < diosde.Count; i++)
+                {
+                    switch (diosde[i].DIOType)
+                    {
+                        case "I":
+                            Dis.Add(diosde[i]);
+                            break;
+                        case "Q":
+                            Dos.Add(diosde[i]);
+                            break;
+                        case "X":
+                            Dis.Add(diosde[i]);
+                            break;
+                        case "Y":
+                            Dos.Add(diosde[i]);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+
+                Dis = new ObservableCollection<DIO>(Dis.OrderByDescending(t => t.DIO_No).ToList());
+                Dos = new ObservableCollection<DIO>(Dos.OrderByDescending(t => t.DIO_No).ToList());
+                List<string> listnew1 = new List<string>();
+                foreach (var item in Dis)
+                {
+                    listnew1.Add(item.Name);
+                }
+
+                diName.ItemsSource = listnew1;
+                List<string> listnew2 = new List<string>();
+                foreach (var item in Dos)
+                {
+                    listnew2.Add(item.Name);
+                }
+
+                doName.ItemsSource = listnew2;
+                List<string> listDis = new List<string>();
+                int digroupmax = int.Parse(Dis[0].DIO_No.ToString().Split('.')[0]);
+                switch (digroupmax % 2)
+                {
+                    case 1:
+                        for (int i = 0; i < digroupmax; i++)
+                        {
+                            listDis.Add(i.ToString() + @".&" + (i + 1).ToString() + ".");
+                        }
+
+                        break;
+                    case 0:
+                        if (digroupmax >= 0)
+                        {
+                            for (int i = 0; i < (digroupmax - 1); i++)
+                            {
+                                listDis.Add(i.ToString() + @".&" + (i + 1).ToString() + ".");
+                            }
+
+                            listDis.Add(digroupmax.ToString() + ".");
+                        }
+
+                        break;
+                    default:
+                        break;
+                }
+
+                int dogroupmax = int.Parse(Dos[0].DIO_No.ToString().Split('.')[0]);
+
+                diGroup.ItemsSource = listDis;
+                List<string> listDos = new List<string>();
+                switch (dogroupmax % 2)
+                {
+                    case 1:
+                        for (int i = 0; i < dogroupmax; i++)
+                        {
+                            listDos.Add(i.ToString() + @".&" + (i + 1).ToString() + ".");
+                        }
+
+                        break;
+                    case 0:
+                        if (dogroupmax >= 0)
+                        {
+                            for (int i = 0; i < (dogroupmax - 1); i++)
+                            {
+                                listDos.Add(i.ToString() + @".&" + (i + 1).ToString() + ".");
+                            }
+
+                            listDos.Add(dogroupmax.ToString() + ".");
+                        }
+
+                        break;
+                    default:
+                        break;
+                }
+
+                doGroup.ItemsSource = listDos;
+                diCode.ItemsSource = Dis;
+                doCode.ItemsSource = Dos;
+            }
+            else
+            {
+                //
+            }
         }
 
         private void UserControl_Loaded(object sender, RoutedEventArgs e)
         {
-
+            LoadData();
+            Loaded -= UserControl_Loaded;
         }
 
         private void Button_Click(object sender, RoutedEventArgs e)
         {
+            Button btn = sender as Button;
+            switch (btn.Name)
+            {
+                case "addBtn":
+                    OpenAddModal();
+                    break;
+                case "importBtn":
+                    ImportFromExcel();
+                    break;
+                case "diSelect":
+                    CollectionViewSource disFilter = this.Resources["disFilter"] as CollectionViewSource;
+                    disFilter?.View.Refresh();
+                    break;
+                case "diReset":
+                    ResetInput("di");
+                    break;
+                case "doSelect":
+                    CollectionViewSource dosFilter = this.Resources["dosFilter"] as CollectionViewSource;
+                    dosFilter?.View.Refresh();
+                    break;
+                case "doReset":
+                    ResetInput("do");
+                    break;
+                default:
+                    break;
+            }
+        }
 
+        private void OpenAddModal()
+        {
+            IPManageModal modal = new IPManageModal(log)
+            {
+                Title = "鏂板",
+                Owner = Window.GetWindow(this),
+            };
+            if (modal.Open(-1, new IPManage(), IPManages, SettingFilePath) == true)
+            {
+                this.Success("鏂板鎴愬姛");
+            }
+        }
+
+        private void ImportFromExcel()
+        {
+            IWorkbook workbook = null;
+            OpenFileDialog dialog = new OpenFileDialog();
+            ////璇ュ�肩‘瀹氭槸鍚﹀彲浠ラ�夋嫨澶氫釜鏂囦欢
+            dialog.Multiselect = false;
+            dialog.Title = "璇烽�夋嫨鏂囦欢";
+            dialog.Filter = "execl鏂囦欢(*.xlsx;*.xls)|*.xlsx;*.xls";
+            if (dialog.ShowDialog() == true)
+            {
+                MonitorTimer.Enabled = false;
+                string file = dialog.FileName;
+                try
+                {
+                    FileStream fileStream1 = new FileStream(@file, FileMode.Open, FileAccess.Read);
+                    if (file.IndexOf(".xlsx") >= 0)
+                    {
+                        workbook = new XSSFWorkbook(fileStream1);
+                    }
+                    else if (file.IndexOf(".xls") >= 0)
+                    {
+                        workbook = new HSSFWorkbook(fileStream1);
+                    }
+
+                    ISheet sheet = workbook.GetSheetAt(0);
+                    List<DIO> dios1 = new List<DIO>();
+                    IRow row;
+                    for (int i = 1; i < (sheet.LastRowNum + 1); i++)
+                    {
+                        DIO[] dIO = new DIO[sheet.LastRowNum];
+                        row = sheet.GetRow(i);
+                        DIO diotest = new DIO();
+                        if (row != null)
+                        {
+                            dIO[i - 1] = new DIO();
+                            dIO[i - 1].Name = row.GetCell(4).ToString();
+                            dIO[i - 1].No = row.GetCell(3).ToString();
+                            dIO[i - 1].Value = false;
+                            dIO[i - 1].DIO_No = Convert.ToDecimal(dIO[i - 1].No.Substring(2));
+                            if (row.GetCell(3).ToString().IndexOf("I") >= 0)
+                            {
+                                dIO[i - 1].DIOType = "I";
+                            }
+                            else if (row.GetCell(3).ToString().IndexOf("Q") >= 0)
+                            {
+                                dIO[i - 1].DIOType = "Q";
+                            }
+                            else if (row.GetCell(3).ToString().IndexOf("X") >= 0)
+                            {
+                                dIO[i - 1].DIOType = "X";
+                            }
+                            else if (row.GetCell(3).ToString().IndexOf("Y") >= 0)
+                            {
+                                dIO[i - 1].DIOType = "Y";
+                            }
+
+                            dios1.Add(dIO[i - 1]);
+                        }
+                    }
+
+                    fileStream1.Close();
+                    workbook.Close();
+                    XmlHelper.SerializeToXml(SettingFilePath, dios1);
+                    lock (this)
+                    {
+                        MonitorTimer.Stop();
+                        LoadData();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    log.Error("Import Failed.", ex);
+                    MsgBoxHelper.Error(this, $"瀵煎叆澶辫触锛亄ex.Message}");
+                }
+            }
+        }
+
+        private void ResetInput(string flag)
+        {
+            if (flag == "di")
+            {
+                diName.Text = "";
+                diCode.Text = "";
+                diGroup.Text = "";
+                CollectionViewSource source = this.Resources["disFilter"] as CollectionViewSource;
+                source?.View.Refresh();
+            }
+            else
+            {
+                doName.Text = "";
+                doCode.Text = "";
+                doGroup.Text = "";
+                CollectionViewSource source = this.Resources["dosFilter"] as CollectionViewSource;
+                source?.View.Refresh();
+            }
+        }
+
+        private string GetValue(byte[] bt, string valueType, string address)
+        {
+            string[] str = address.Split('.');
+            switch (valueType.ToLower())
+            {
+                case "bool":
+                    return Snap7.S7.GetBitAt(bt, int.Parse(str[0]), int.Parse(str[1])).ToString();
+                default:
+                    return "false";
+            }
+        }
+
+
+        public override void SetBaseFolder(string folder)
+        {
+            base.SetBaseFolder(folder);
+            this.SettingFilePath = Path.Combine(BaseFolder, "Setting.xml");
+            this.DataFilePath = Path.Combine(BaseFolder, "Data.xml");
+        }
+
+        public override object Active()
+        {
+            try
+            {
+                if (File.Exists(SettingFilePath))
+                {
+                    ObservableCollection<IPManage> datas =
+                        XmlHelper.DeserializeFromXml<ObservableCollection<IPManage>>(SettingFilePath);
+                    IPManages = datas;
+
+                    DITag = IPManages[0].DItag;
+                    DQTag = IPManages[0].DQtag;
+                }
+                else
+                {
+                    IPManage tag = new IPManage();
+                    tag.DItag = "";
+                    tag.DQtag = "";
+                    IPManages.Add(tag);
+                    XmlHelper.SerializeToXml(SettingFilePath, IPManages);
+                }
+                if (systemSetting.PlcEnabled)
+                {
+                    if (!lTSCADAApi.Connect2("127.0.0.1", 6543, 18888, out string errMsg))
+                    {
+                        MsgBoxHelper.Error(this, errMsg);
+                    }
+                    else
+                    {
+                        this.MonitorTimer.Start();
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Active Execute Failed.", ex);
+                MsgBoxHelper.ErrorMessage(this, $"鎻掍欢婵�娲诲け璐ワ紒{ex.Message}");
+            }
+            return null;
+        }
+
+        private void CollectionViewSource_Filter(object sender, System.Windows.Data.FilterEventArgs e)
+        {
+            DIO data = e.Item as DIO;
+            if (data == null) return;
+
+            CollectionViewSource source = sender as CollectionViewSource;
+            DIO param = new DIO();
+            if (source.Source == Dis)
+            {
+                param.Name = diName.Text;
+                param.No = diCode.Text;
+            }
+            else
+            {
+                param.Name = doName.Text;
+                param.No = doCode.Text;
+            }
+
+            if (!string.IsNullOrEmpty(param.Name) && data.Name != param.Name)
+            {
+                e.Accepted = false;
+                return;
+            }
+            if (!string.IsNullOrEmpty(param.No) && data.No != param.No)
+            {
+                e.Accepted = false;
+                return;
+            }
+            e.Accepted = true;
         }
     }
 }
diff --git a/HMI.IOMonitor/IPManageModal.xaml b/HMI.IOMonitor/IPManageModal.xaml
new file mode 100644
index 0000000..963a325
--- /dev/null
+++ b/HMI.IOMonitor/IPManageModal.xaml
@@ -0,0 +1,40 @@
+锘�<pu:WindowX x:Class="HMI.IOMonitor.IPManageModal"
+            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+            xmlns:local="clr-namespace:HMI.IOMonitor"
+            xmlns:pw="https://opensource.panuon.com/wpf"
+            xmlns:pu="https://opensource.panuon.com/wpf-ui"
+            xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI"
+            xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI"
+            mc:Ignorable="d"
+            Title="Form"
+            SizeToContent="Height"
+            Width="600"
+            WindowStartupLocation="CenterOwner"
+            BorderBrush="#3E3E45"
+            BorderThickness="1"
+            Foreground="Black"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
+            pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
+            pu:WindowXCaption.Foreground="#FFF"
+            pu:WindowXCaption.Buttons="Close"
+            pu:WindowXModalDialog.Buttons="OKCancel"
+            pu:WindowXModalDialog.CancelButtonContent="鍙栨秷"
+            pu:WindowXModalDialog.OKButtonContent="淇濆瓨"
+            pu:WindowXModalDialog.ButtonPanelMargin="0,30,10,10">
+    <Grid Margin="10">
+        <StackPanel x:Name="formPanel">
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True" 
+  Header="I鐐硅鍙栨爣绛�" GroupName="MyFormGroup">
+                <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="iTag"/>
+            </pu:FormGroup>
+
+            <pu:FormGroup ui:FormGroupHelper.IsRequired="True" 
+  Header="Q鐐硅鍙栨爣绛�" GroupName="MyFormGroup">
+                <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="qTag"/>
+            </pu:FormGroup>
+        </StackPanel>
+    </Grid>
+</pu:WindowX>
diff --git a/HMI.IOMonitor/IPManageModal.xaml.cs b/HMI.IOMonitor/IPManageModal.xaml.cs
new file mode 100644
index 0000000..fbec583
--- /dev/null
+++ b/HMI.IOMonitor/IPManageModal.xaml.cs
@@ -0,0 +1,126 @@
+锘縰sing HMI.Core.Util;
+using HMI.IOMonitor.Entity;
+using HMI.UI;
+using HMI.UI.Util;
+using log4net;
+using Panuon.WPF.UI;
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace HMI.IOMonitor
+{
+    /// <summary>
+    /// ModalWindow.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class IPManageModal : WindowX
+    {
+        public IPManageModal(ILog log)
+        {
+            this.log = log;
+            this.DataContext = this;
+            InitializeComponent();
+        }
+        private ILog log;
+        public string FilePath { get; private set; }
+        public int DataIndex { get; private set; }
+        public IPManage Data { get; private set; }
+        public ObservableCollection<IPManage> Datasource { get; private set; }
+
+        private bool _isProcessing;
+
+        protected override void OnClosing(CancelEventArgs e)
+        {
+            //Press Continue Button
+            if (DialogResult == true)
+            {
+                if (_isProcessing)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                var okButton = WindowXModalDialog.GetOKButton(this);
+                try
+                {
+                    _isProcessing = true;
+                    ButtonHelper.SetIsPending(okButton, true);
+                    if (!ValidateForm())
+                    {
+                        e.Cancel = true;
+                        return;
+                    }
+
+                    SaveOrUpdateData();
+                }
+                catch (Exception ex)
+                {
+                    log.Error("IPManage Form Submit Failed.", ex);
+                    ToastHelper.Error(this, $"鏈煡寮傚父锛亄ex.Message}");
+                    e.Cancel = true;
+                    return;
+                }
+                finally
+                {
+                    _isProcessing = false;
+                    ButtonHelper.SetIsPending(okButton, false);
+                }
+            }
+            base.OnClosing(e);
+        }
+
+        public bool ValidateDBAddress(object value, out string err)
+        {
+            err = null;
+            
+            return true;
+        }
+
+        private bool ValidateForm()
+        {
+            bool flag = FormGroupHelper.ValidateForm(formPanel);
+            if (flag)
+            {
+                Data.DItag =iTag.Text;
+                Data.DQtag = qTag.Text;
+            }
+            return flag;
+        }
+
+        public bool? Open(int index, IPManage data,
+            ObservableCollection<IPManage> dataSource,
+            string filePath)
+        {
+            FilePath = filePath;
+            DataIndex = index;
+            Data = data;
+            Datasource = dataSource;
+            iTag.Text = Data.DItag;
+            qTag.Text = Data.DQtag;
+            return this.ShowDialog();
+        }
+
+        private void SaveOrUpdateData()
+        {
+            if (DataIndex == -1)
+            {
+                InsertData(Data);
+            }
+            else
+            {
+                UpdateData(DataIndex, Data);
+            }
+        }
+
+        public void InsertData(IPManage data)
+        {
+            Datasource.Add(data);
+            XmlHelper.SerializeToXml(FilePath, Datasource);
+        }
+
+        public void UpdateData(int index, IPManage data)
+        {
+            Datasource[index] = data;
+            XmlHelper.SerializeToXml(FilePath, Datasource);
+        }
+    }
+}
diff --git a/HMI.IOMonitor/packages.config b/HMI.IOMonitor/packages.config
index 63cdc53..bc20bca 100644
--- a/HMI.IOMonitor/packages.config
+++ b/HMI.IOMonitor/packages.config
@@ -1,6 +1,8 @@
 锘�<?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="log4net" version="3.0.3" targetFramework="net472" />
+  <package id="NPOI" version="2.4.1" targetFramework="net472" />
   <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
   <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
+  <package id="SharpZipLib" version="1.0.0" targetFramework="net472" />
 </packages>
\ No newline at end of file
diff --git a/HMI.MenuManage/MenuManage.xaml b/HMI.MenuManage/MenuManage.xaml
index 0044f48..3d0f51a 100644
--- a/HMI.MenuManage/MenuManage.xaml
+++ b/HMI.MenuManage/MenuManage.xaml
@@ -36,7 +36,9 @@
         <Border Style="{StaticResource CardBoarder}" Margin="0,0,2,0">
             <StackPanel>
                 <DockPanel Margin="0,0,0,10">
-                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe934;" Style="{StaticResource DangerButton}">鍒犻櫎</Button>
+                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe934;" 
+                            x:Name="deleteBatchBtn"
+                            Style="{StaticResource DangerButton}" Click="Button_Click" Cursor="Hand">鍒犻櫎</Button>
                     <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
 pu:IconHelper.FontFamily="{StaticResource iconfont}"
 pu:ButtonHelper.Icon="&#xe631;" Margin="0,0,10,0" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
diff --git a/HMI.MenuManage/MenuManage.xaml.cs b/HMI.MenuManage/MenuManage.xaml.cs
index 25585e7..1e4a0e5 100644
--- a/HMI.MenuManage/MenuManage.xaml.cs
+++ b/HMI.MenuManage/MenuManage.xaml.cs
@@ -1,5 +1,7 @@
 锘縰sing System;
+using System.Collections.Generic;
 using System.ComponentModel;
+using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Windows;
 using System.Windows.Controls;
@@ -16,29 +18,8 @@
     /// </summary>
     public partial class MenuManage : PluginControl
     {
-        #region ...
-        public virtual event PropertyChangedEventHandler PropertyChanged;
-
-        protected virtual void RaisePropertyChanged(string name)
-        {
-
-            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
-        }
-
-        protected void RaiseAndSetIfChanged<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
-        {
-            old = @new;
-            if (propertyName != null)
-            {
-                RaisePropertyChanged(propertyName);
-            }
-        }
-        #endregion
-
         #region 灞炴��
         private MenuManageModel Model;
-        private ILog log;
-
         #endregion
 
         public MenuManage()
@@ -74,6 +55,7 @@
                 catch (Exception ex)
                 {
                     log.Error("Add Menu Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鏂板澶辫触锛亄ex.Message}");
                 }
             }
             else if (btn.Name == "refreshBtn")
@@ -85,9 +67,34 @@
                 catch (Exception ex)
                 {
                     log.Error("Refresh Menu List Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鍒锋柊澶辫触锛亄ex.Message}");
                 }
             }
-            else if (btn.Name == "deleteBtn") { }
+            else if (btn.Name == "deleteBatchBtn")
+            {
+                try
+                {
+                    List<string> ids = Model.DataSource.Where(x => x.Selected).Select(x => x.Id).ToList();
+                    if (ids == null || ids.Count <= 0)
+                    {
+                        ToastHelper.Warning(Window.GetWindow(this), "璇烽�夋嫨瑕佸垹闄ょ殑鑿滃崟锛�");
+                        return;
+                    }
+
+                    var res = MsgBoxHelper.WarnMessage(Window.GetWindow(this),
+                        $"纭畾鍒犻櫎閫変腑鐨刐{ids.Count}]鏉¤彍鍗曞悧锛熻鎿嶄綔涓嶅彲閫嗭紒");
+                    if (res == MessageBoxResult.OK)
+                    {
+                        Model.DeleteMenuByIds(ids);
+                        Model.LoadData();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    log.Error("Delete Menu Batch Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鍒犻櫎澶辫触锛亄ex.Message}");
+                }
+            }
             else if (btn.Name == "editBtn")
             {
                 try
@@ -107,8 +114,8 @@
                 }
                 catch (Exception ex)
                 {
-
                     log.Error("Edit Menu Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"缂栬緫澶辫触锛亄ex.Message}");
                 }
             }
             else if (btn.Name == "delBtn")
@@ -116,7 +123,8 @@
                 try
                 {
                     var data = (MenuData)((Button)sender).DataContext;
-                    var res = MsgBoxHelper.WarnMessage(Window.GetWindow(this), $"纭畾鍒犻櫎[{data.Name}]鍚楋紵璇ユ搷浣滀笉鍙�嗭紒");
+                    var res = MsgBoxHelper.WarnMessage(Window.GetWindow(this),
+                        $"纭畾鍒犻櫎鑿滃崟[{data.Name}]鍚楋紵璇ユ搷浣滀笉鍙�嗭紒");
                     if (res == MessageBoxResult.OK)
                     {
                         Model.DeleteMenuById(data.Id);
@@ -126,6 +134,7 @@
                 catch (Exception ex)
                 {
                     log.Error("Delete Menu Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鍒犻櫎澶辫触锛亄ex.Message}");
                 }
             }
         }
@@ -139,11 +148,6 @@
         private void treeViewer_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
         {
             table.SelectedItem = e.NewValue;
-        }
-
-        public void SetLogger(ILog logger)
-        {
-            this.log = logger;
         }
     }
 }
diff --git a/HMI.MenuManage/Modal/MenuModal.xaml b/HMI.MenuManage/Modal/MenuModal.xaml
index 310e995..798b8fa 100644
--- a/HMI.MenuManage/Modal/MenuModal.xaml
+++ b/HMI.MenuManage/Modal/MenuModal.xaml
@@ -14,7 +14,7 @@
             BorderBrush="#3E3E45"
             BorderThickness="1"
             Foreground="Black"
-            pu:WindowXCaption.Background="{StaticResource MainBorder}"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
             pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
             pu:WindowXCaption.Foreground="#FFF"
             pu:WindowXCaption.Buttons="Close"
diff --git a/HMI.MenuManage/Modal/RoleModal.xaml b/HMI.MenuManage/Modal/RoleModal.xaml
index 734f03e..23215cb 100644
--- a/HMI.MenuManage/Modal/RoleModal.xaml
+++ b/HMI.MenuManage/Modal/RoleModal.xaml
@@ -14,7 +14,7 @@
             BorderBrush="#3E3E45"
             BorderThickness="1"
             Foreground="Black"
-            pu:WindowXCaption.Background="{StaticResource MainBorder}"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
             pu:WindowXCaption.Foreground="#FFF"
             pu:WindowXCaption.Buttons="Close"
             pu:WindowXModalDialog.Buttons="OKCancel"
diff --git a/HMI.MenuManage/Modal/UserModal.xaml b/HMI.MenuManage/Modal/UserModal.xaml
index 6556a6f..eec9385 100644
--- a/HMI.MenuManage/Modal/UserModal.xaml
+++ b/HMI.MenuManage/Modal/UserModal.xaml
@@ -15,7 +15,7 @@
             BorderBrush="#3E3E45"
             BorderThickness="1"
             Foreground="Black"
-            pu:WindowXCaption.Background="{StaticResource MainBorder}"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
             pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
             pu:WindowXCaption.Foreground="#FFF"
             pu:WindowXCaption.Buttons="Close"
diff --git a/HMI.MenuManage/Model/MenuManageModel.cs b/HMI.MenuManage/Model/MenuManageModel.cs
index da797c0..e12f5a6 100644
--- a/HMI.MenuManage/Model/MenuManageModel.cs
+++ b/HMI.MenuManage/Model/MenuManageModel.cs
@@ -3,6 +3,7 @@
 using System.Collections.ObjectModel;
 using System.Data;
 using System.IO;
+using System.Linq;
 using HMI.Core.Entity;
 using HMI.Core.Util;
 using HMI.MenuManage.Entity;
@@ -103,8 +104,15 @@
 
         public void DeleteMenuById(string id)
         {
-            string sql = $"DELETE FROM menu WHERE id = {id}";
+            string sql = $"DELETE FROM menu WHERE id = {id};";
             sqliteHelper.ExecuteSql(sql);
         }
+
+        public void DeleteMenuByIds(IEnumerable<string> ids)
+        {
+            List<string> sqls = ids.Select(id => $"DELETE FROM menu WHERE id = {id};")
+                .ToList();
+            sqliteHelper.ExecuteBatchSql(sqls);
+        }
     }
 }
diff --git a/HMI.MenuManage/Model/RoleManageModel.cs b/HMI.MenuManage/Model/RoleManageModel.cs
index 5ca0cbf..936f240 100644
--- a/HMI.MenuManage/Model/RoleManageModel.cs
+++ b/HMI.MenuManage/Model/RoleManageModel.cs
@@ -2,6 +2,7 @@
 using System.Collections.ObjectModel;
 using System.Data;
 using System.IO;
+using System.Windows.Markup;
 using HMI.Core.Entity;
 using HMI.Core.Util;
 using HMI.MenuManage.Entity;
@@ -101,6 +102,18 @@
             });
         }
 
+        public void DeleteRoleByCodes(IEnumerable<string> codes)
+        {
+            List<string> sqls = new List<string>();
+            foreach (string code in codes)
+            {
+                sqls.Add($"DELETE FROM role WHERE code = '{code}';");
+                sqls.Add($"DELETE FROM role_menu_rel WHERE roleCode = '{code}';");
+                sqls.Add($"DELETE FROM user_role_rel WHERE roleCode = '{code}';");
+            }
+            sqliteHelper.ExecuteBatchSql(sqls);
+        }
+
         public void SaveRelData(RoleData role)
         {
             if (role == null) return;
diff --git a/HMI.MenuManage/Model/UserManageModel.cs b/HMI.MenuManage/Model/UserManageModel.cs
index a2ede62..42fafc2 100644
--- a/HMI.MenuManage/Model/UserManageModel.cs
+++ b/HMI.MenuManage/Model/UserManageModel.cs
@@ -94,5 +94,24 @@
         {
             UserRoleRelHelper.SaveUserRoleRel(sqliteHelper, Roles, SelectedUser, null, null);
         }
+
+        public void DeleteUserByUsername(string username)
+        {
+            sqliteHelper.ExecuteBatchSql(new List<string> {
+            $"DELETE FROM user WHERE username = '{username}';",
+            $"DELETE FROM user_role_rel WHERE username = '{username}';"
+            });
+        }
+
+        public void DeleteUserByUsernames(IEnumerable<string> usernames)
+        {
+            List<string> sqls = new List<string>();
+            foreach (string username in usernames)
+            {
+                sqls.Add($"DELETE FROM user WHERE username = '{username}';");
+                sqls.Add($"DELETE FROM user_role_rel WHERE username = '{username}';");
+            }
+            sqliteHelper.ExecuteBatchSql(sqls);
+        }
     }
 }
diff --git a/HMI.MenuManage/RoleManage.xaml b/HMI.MenuManage/RoleManage.xaml
index 99eb89c..76d589a 100644
--- a/HMI.MenuManage/RoleManage.xaml
+++ b/HMI.MenuManage/RoleManage.xaml
@@ -35,7 +35,9 @@
         <Border Style="{StaticResource CardBoarder}" Margin="0,0,2,0">
             <StackPanel>
                 <DockPanel Margin="0,0,0,10">
-                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe61a;" Style="{StaticResource DangerButton}">鍒犻櫎</Button>
+                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe61a;" 
+                            Style="{StaticResource DangerButton}"
+                            x:Name="deleteBatchBtn" Click="Button_Click">鍒犻櫎</Button>
                     <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}"
 pu:ButtonHelper.Icon="&#xe631;" Margin="0,0,10,0" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
                     <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}"
diff --git a/HMI.MenuManage/RoleManage.xaml.cs b/HMI.MenuManage/RoleManage.xaml.cs
index 15df9a5..8b3300a 100644
--- a/HMI.MenuManage/RoleManage.xaml.cs
+++ b/HMI.MenuManage/RoleManage.xaml.cs
@@ -1,15 +1,13 @@
-锘縰sing System;
-using System.ComponentModel;
-using System.Runtime.CompilerServices;
-using System.Windows;
-using System.Windows.Controls;
-using log4net;
-using log4net.Repository.Hierarchy;
-using Panuon.WPF.UI;
-using HMI.Core.Api;
+锘縰sing HMI.Base;
 using HMI.MenuManage.Entity;
 using HMI.MenuManage.Model;
-using HMI.Base;
+using HMI.UI.Util;
+using Panuon.WPF.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
 
 namespace HMI.MenuManage
 {
@@ -18,29 +16,8 @@
     /// </summary>
     public partial class RoleManage : PluginControl
     {
-        #region ...
-        public virtual event PropertyChangedEventHandler PropertyChanged;
-
-        protected virtual void RaisePropertyChanged(string name)
-        {
-
-            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
-        }
-
-        protected void RaiseAndSetIfChanged<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
-        {
-            old = @new;
-            if (propertyName != null)
-            {
-                RaisePropertyChanged(propertyName);
-            }
-        }
-        #endregion
-
         #region 灞炴��
         private RoleManageModel Model;
-        private ILog log;
-
         #endregion
 
         public RoleManage()
@@ -60,26 +37,6 @@
         #region 灞炴��
 
         #endregion
-
-        public object Active()
-        {
-            return null;
-        }
-
-        public object DeActive()
-        {
-            return null;
-        }
-
-        public object Init()
-        {
-            return null;
-        }
-
-        public void OnTabChange(object sender, object args)
-        {
-        }
-
         private void Button_Click(object sender, RoutedEventArgs e)
         {
             try
@@ -87,48 +44,112 @@
                 Button btn = (Button)sender;
                 if (btn.Name == "addBtn")
                 {
-                    RoleModal modal = new RoleModal
+                    try
                     {
-                        Title = "鏂板瑙掕壊",
-                        Owner = Window.GetWindow(this),
-                        sqliteHelper = Model.sqliteHelper
-                    };
-                    if (modal.Open(new RoleData()) == true)
+                        RoleModal modal = new RoleModal
+                        {
+                            Title = "鏂板瑙掕壊",
+                            Owner = Window.GetWindow(this),
+                            sqliteHelper = Model.sqliteHelper
+                        };
+                        if (modal.Open(new RoleData()) == true)
+                        {
+                            Model.LoadData();
+                        }
+                    }
+                    catch (Exception ex)
                     {
-                        Model.LoadData();
+                        log.Error("Add Role Failed.", ex);
+                        ToastHelper.Error(Window.GetWindow(this), $"鏂板澶辫触锛亄ex.Message}");
                     }
                 }
                 else if (btn.Name == "refreshBtn")
                 {
-                    Model.LoadData();
+                    try
+                    {
+                        Model.LoadData();
+                    }
+                    catch (Exception ex)
+                    {
+                        log.Error("Refresh Role Failed.", ex);
+                        ToastHelper.Error(Window.GetWindow(this), $"鍒锋柊澶辫触锛亄ex.Message}");
+                    }
                 }
                 else if (btn.Name == "menuBtn")
                 {
-                    Model.LoadRelData((RoleData)btn.DataContext);
+                    try
+                    {
+                        Model.LoadRelData((RoleData)btn.DataContext);
+                    }
+                    catch (Exception ex)
+                    {
+                        log.Error("Load Role-Menu Failed.", ex);
+                        ToastHelper.Error(Window.GetWindow(this), $"鍒锋柊瑙掕壊澶辫触锛亄ex.Message}");
+                    }
                 }
                 else if (btn.Name == "editBtn")
                 {
-                    RoleModal modal = new RoleModal
+                    try
                     {
-                        Title = "缂栬緫瑙掕壊",
-                        Owner = Window.GetWindow(this),
-                        sqliteHelper = Model.sqliteHelper
-                    };
-                    if (modal.Open((RoleData)btn.DataContext) == true)
+                        RoleModal modal = new RoleModal
+                        {
+                            Title = "缂栬緫瑙掕壊",
+                            Owner = Window.GetWindow(this),
+                            sqliteHelper = Model.sqliteHelper
+                        };
+                        if (modal.Open((RoleData)btn.DataContext) == true)
+                        {
+                            Model.LoadData();
+                        }
+                    }
+                    catch (Exception ex)
                     {
-                        Model.LoadData();
+                        log.Error("Edit Role Failed.", ex);
+                        ToastHelper.Error(Window.GetWindow(this), $"缂栬緫澶辫触锛亄ex.Message}");
+                    }
+                }
+                else if (btn.Name == "deleteBatchBtn")
+                {
+                    try
+                    {
+                        List<string> codes = Model.DataSource.Where(x => x.Selected).Select(x => x.Code).ToList();
+                        if (codes == null || codes.Count <= 0)
+                        {
+                            ToastHelper.Warning(Window.GetWindow(this), "璇烽�夋嫨瑕佸垹闄ょ殑瑙掕壊锛�");
+                            return;
+                        }
+
+                        var res = MsgBoxHelper.WarnMessage(Window.GetWindow(this),
+                            $"纭畾鍒犻櫎閫変腑鐨刐{codes.Count}]鏉¤鑹插悧锛熻鎿嶄綔涓嶅彲閫嗭紒");
+                        if (res == MessageBoxResult.OK)
+                        {
+                            Model.DeleteRoleByCodes(codes);
+                            Model.LoadData();
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        log.Error("Delete Role Batch Failed.", ex);
+                        ToastHelper.Error(Window.GetWindow(this), $"鍒犻櫎澶辫触锛亄ex.Message}");
                     }
                 }
                 else if (btn.Name == "delBtn")
                 {
                     try
                     {
-                        Model.DelSingleData((RoleData)btn.DataContext);
+                        var data = (RoleData)((Button)sender).DataContext;
+                        var res = MsgBoxHelper.WarnMessage(Window.GetWindow(this),
+                            $"纭畾鍒犻櫎瑙掕壊[{data.Name}]鍚楋紵璇ユ搷浣滀笉鍙�嗭紒");
+                        if (res == MessageBoxResult.OK)
+                        {
+                            Model.DelSingleData(data);
+                            Model.LoadData();
+                        }
                     }
                     catch (Exception ex)
                     {
                         log.Error("Delete Role Failed.", ex);
-                        Panuon.WPF.UI.Toast.Show((WindowX)Window.GetWindow(this), "鍒犻櫎澶辫触", ToastPosition.Top);
+                        Toast.Show((WindowX)Window.GetWindow(this), "鍒犻櫎澶辫触", ToastPosition.Top);
                     }
                 }
                 else if (btn.Name == "saveMenuBtn")
@@ -136,24 +157,19 @@
                     try
                     {
                         Model.SaveRelData(Model.SelectedValue);
-                        Panuon.WPF.UI.Toast.Show((WindowX)Window.GetWindow(this), "淇濆瓨鎴愬姛", ToastPosition.Top);
+                        Toast.Show((WindowX)Window.GetWindow(this), "淇濆瓨鎴愬姛", ToastPosition.Top);
                     }
                     catch (Exception ex)
                     {
                         log.Error("Save Role-Menu Failed.", ex);
-                        Panuon.WPF.UI.Toast.Show((WindowX)Window.GetWindow(this), "淇濆瓨澶辫触", ToastPosition.Top);
+                        Toast.Show((WindowX)Window.GetWindow(this), "淇濆瓨澶辫触", ToastPosition.Top);
                     }
                 }
             }
             catch (Exception ex)
             {
-                log.Error("123", ex);
+                log.Error("Something Error...", ex);
             }
-        }
-
-        public void SetLogger(ILog logger)
-        {
-            this.log = logger;
         }
     }
 }
diff --git a/HMI.MenuManage/UserManage.xaml b/HMI.MenuManage/UserManage.xaml
index 7c8650a..38551b9 100644
--- a/HMI.MenuManage/UserManage.xaml
+++ b/HMI.MenuManage/UserManage.xaml
@@ -32,7 +32,9 @@
         <Border Style="{StaticResource CardBoarder}" Margin="0,0,2,0">
             <StackPanel>
                 <DockPanel Margin="0,0,0,10">
-                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe60f;" Style="{StaticResource DangerButton}">鍒犻櫎</Button>
+                    <Button DockPanel.Dock="Right" pu:ButtonHelper.Icon="&#xe60f;" 
+                            Style="{StaticResource DangerButton}"
+                            x:Name="deleteBatchBtn" Click="Button_Click">鍒犻櫎</Button>
                     <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" 
                             pu:ButtonHelper.Icon="&#xe631;" Margin="0,0,10,0" x:Name="refreshBtn" Click="Button_Click">鍒锋柊</Button>
                     <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}"
diff --git a/HMI.MenuManage/UserManage.xaml.cs b/HMI.MenuManage/UserManage.xaml.cs
index 05d575f..e4bd390 100644
--- a/HMI.MenuManage/UserManage.xaml.cs
+++ b/HMI.MenuManage/UserManage.xaml.cs
@@ -1,12 +1,12 @@
-锘縰sing System;
-using System.Windows;
-using System.Windows.Controls;
-using HMI.Base;
-using HMI.Core.Api;
+锘縰sing HMI.Base;
 using HMI.MenuManage.Entity;
 using HMI.MenuManage.Model;
 using HMI.UI.Util;
-using log4net;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
 
 namespace HMI.MenuManage
 {
@@ -16,7 +16,7 @@
     public partial class UserManage : PluginControl
     {
         UserManageModel Model;
-        private ILog log;
+
         public UserManage()
         {
             Model = new UserManageModel();
@@ -36,35 +36,103 @@
             Button btn = (Button)sender;
             if (btn.Name == "addBtn")
             {
-                UserModal userModal = new UserModal
+                try
                 {
-                    Title = "鏂板鐢ㄦ埛",
-                    Owner = Window.GetWindow(this),
-                    sqliteHelper = Model.sqliteHelper
-                };
-                if (userModal.Open(new UserData()) == true)
+                    UserModal userModal = new UserModal
+                    {
+                        Title = "鏂板鐢ㄦ埛",
+                        Owner = Window.GetWindow(this),
+                        sqliteHelper = Model.sqliteHelper
+                    };
+                    if (userModal.Open(new UserData()) == true)
+                    {
+                        Model.LoadData();
+                    }
+                }
+                catch (Exception ex)
                 {
-                    Model.LoadData();
+                    log.Error("Add User Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鏂板澶辫触锛亄ex.Message}");
                 }
             }
             else if (btn.Name == "refreshBtn")
             {
-                Model.LoadData();
-            }
-            else if (btn.Name == "editBtn")
-            {
-                UserModal userModal = new UserModal
-                {
-                    Title = "缂栬緫鐢ㄦ埛",
-                    Owner = Window.GetWindow(this),
-                    sqliteHelper = Model.sqliteHelper
-                };
-                if (userModal.Open((UserData)btn.DataContext) == true)
+                try
                 {
                     Model.LoadData();
                 }
+                catch (Exception ex)
+                {
+                    log.Error("Refresh User Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鍒锋柊澶辫触锛亄ex.Message}");
+                }
             }
-            else if (btn.Name == "delBtn") { }
+            else if (btn.Name == "editBtn")
+            {
+                try
+                {
+                    UserModal userModal = new UserModal
+                    {
+                        Title = "缂栬緫鐢ㄦ埛",
+                        Owner = Window.GetWindow(this),
+                        sqliteHelper = Model.sqliteHelper
+                    };
+                    if (userModal.Open((UserData)btn.DataContext) == true)
+                    {
+                        Model.LoadData();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    log.Error("Edit User Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"缂栬緫澶辫触锛亄ex.Message}");
+                }
+            }
+            else if (btn.Name == "deleteBatchBtn")
+            {
+                try
+                {
+                    List<string> usernames = Model.DataSource.Where(x => x.Selected).Select(x => x.Username).ToList();
+                    if (usernames == null || usernames.Count <= 0)
+                    {
+                        ToastHelper.Warning(Window.GetWindow(this), "璇烽�夋嫨瑕佸垹闄ょ殑鐢ㄦ埛锛�");
+                        return;
+                    }
+
+                    var res = MsgBoxHelper.WarnMessage(Window.GetWindow(this),
+                        $"纭畾鍒犻櫎閫変腑鐨刐{usernames.Count}]鏉$敤鎴峰悧锛熻鎿嶄綔涓嶅彲閫嗭紒");
+                    if (res == MessageBoxResult.OK)
+                    {
+                        Model.DeleteUserByUsernames(usernames);
+                        Model.LoadData();
+                        ToastHelper.Success(Window.GetWindow(this), "鍒犻櫎鎴愬姛");
+                    }
+                }
+                catch (Exception ex)
+                {
+                    log.Error("Delete User Batch Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鍒犻櫎澶辫触锛亄ex.Message}");
+                }
+            }
+            else if (btn.Name == "delBtn")
+            {
+                try
+                {
+                    var data = (UserData)((Button)sender).DataContext;
+                    var res = MsgBoxHelper.WarnMessage(Window.GetWindow(this),
+                        $"纭畾鍒犻櫎鐢ㄦ埛[{data.Name}]鍚楋紵璇ユ搷浣滀笉鍙�嗭紒");
+                    if (res == MessageBoxResult.OK)
+                    {
+                        Model.DeleteUserByUsername(data.Username);
+                        Model.LoadData();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    log.Error("Delete User Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"鍒犻櫎澶辫触锛亄ex.Message}");
+                }
+            }
             else if (btn.Name == "saveRoleBtn")
             {
                 try
@@ -76,18 +144,9 @@
                 catch (Exception ex)
                 {
                     log.Error("Update User-Role Rel Failed.", ex);
+                    ToastHelper.Error(Window.GetWindow(this), $"淇濆瓨澶辫触锛亄ex.Message}");
                 }
             }
-        }
-
-        public void SetLogger(ILog logger)
-        {
-            log = logger;
-        }
-
-        public void SetBaseFolder(string folder)
-        {
-            throw new NotImplementedException();
         }
     }
 }
diff --git a/HMI.ParameterManage/ParameterManage.xaml b/HMI.ParameterManage/ParameterManage.xaml
index c87940f..bad6c5f 100644
--- a/HMI.ParameterManage/ParameterManage.xaml
+++ b/HMI.ParameterManage/ParameterManage.xaml
@@ -8,7 +8,7 @@
              xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI"
              xmlns:pw="https://opensource.panuon.com/wpf"
              xmlns:pu="https://opensource.panuon.com/wpf-ui"
-             xmlns:dp="clr-namespace:HMI.UI;assembly=HMI.UI"
+             xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI"
              xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base"
              mc:Ignorable="d" 
              Padding="10"
@@ -55,7 +55,7 @@
                         <DataGridTemplateColumn Header="鎿嶄綔" Width="100" IsReadOnly="True" CanUserResize="False">
                             <DataGridTemplateColumn.CellTemplate>
                                 <DataTemplate>
-                                    <StackPanel Orientation="Horizontal" ui:StackPanelHelper.ChildSpace="10">
+                                    <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10">
                                         <Button x:Name="editProductBtn" Style="{StaticResource RowLink}"  DataContext="{Binding }"
                     Click="Button_Click">缂栬緫</Button>
                                         <Button x:Name="delProductBtn" Style="{StaticResource DangerLinkButton}"
diff --git a/HMI.ParameterManage/ParameterModal.xaml b/HMI.ParameterManage/ParameterModal.xaml
index ba73ce9..08bc442 100644
--- a/HMI.ParameterManage/ParameterModal.xaml
+++ b/HMI.ParameterManage/ParameterModal.xaml
@@ -16,7 +16,7 @@
             BorderBrush="#3E3E45"
             BorderThickness="1"
             Foreground="Black"
-            pu:WindowXCaption.Background="{StaticResource MainBorder}"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
             pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
             pu:WindowXCaption.Foreground="#FFF"
             pu:WindowXCaption.Buttons="Close"
diff --git a/HMI.ParameterManage/ProductModal.xaml b/HMI.ParameterManage/ProductModal.xaml
index fcaf3df..dd216e1 100644
--- a/HMI.ParameterManage/ProductModal.xaml
+++ b/HMI.ParameterManage/ProductModal.xaml
@@ -15,7 +15,7 @@
             BorderBrush="#3E3E45"
             BorderThickness="1"
             Foreground="Black"
-            pu:WindowXCaption.Background="{StaticResource MainBorder}"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
             pu:WindowXModalDialog.ButtonStyle="{StaticResource ModalButton}"
             pu:WindowXCaption.Foreground="#FFF"
             pu:WindowXCaption.Buttons="Close"
diff --git a/HMI.SettingControl/SettingControl.xaml b/HMI.SettingControl/SettingControl.xaml
index 3116895..70b3828 100644
--- a/HMI.SettingControl/SettingControl.xaml
+++ b/HMI.SettingControl/SettingControl.xaml
@@ -36,23 +36,7 @@
                 <TextBlock VerticalAlignment="Center" Text="绯荤粺璁剧疆" Margin="0,0,0,10"
                            FontSize="{StaticResource TitleFontSize}" />
                 <TabControl Grid.Row="1"
-pu:TabControlHelper.HeaderPanelAlignment="Front"
-pu:TabControlHelper.ItemsBackground="{StaticResource PrimaryColorContract}"
-pu:TabControlHelper.ItemsForeground="{StaticResource PrimaryColor}"
-                            
-pu:TabControlHelper.ItemsHeight="40"
-pu:TabControlHelper.ItemsHorizontalHeaderAlignment="Left"
-pu:TabControlHelper.ItemsHoverBackground="{StaticResource SecondPrimaryColor}"
-pu:TabControlHelper.ItemsHoverForeground="{StaticResource SecondPrimaryColorContract}"
-pu:TabControlHelper.ItemsRibbonLineMargin="0,5,0,5"
-pu:TabControlHelper.ItemsRibbonLineThickness="4"
-pu:TabControlHelper.ItemsRibbonLineVisibility="Visible"
-pu:TabControlHelper.ItemsSelectedBackground="{StaticResource PrimaryColor}"
-pu:TabControlHelper.ItemsSelectedForeground="{StaticResource PrimaryColorContract}"
-pu:TabControlHelper.ItemsSelectedRibbonLineBrush="#FFFFFF"
-pu:TabControlHelper.ItemsSelectedRibbonLineThickness="2"
-TabStripPlacement="Left"
-        BorderThickness="0"
+
         BorderBrush="{StaticResource CommonBoarder}"
         ItemsSource="{Binding TabItems}">
 
diff --git a/HMI.SettingControl/SettingControl.xaml.cs b/HMI.SettingControl/SettingControl.xaml.cs
index 6390b40..9ee7841 100644
--- a/HMI.SettingControl/SettingControl.xaml.cs
+++ b/HMI.SettingControl/SettingControl.xaml.cs
@@ -14,62 +14,13 @@
     /// </summary>
     public partial class SettingControl : PluginControl
     {
-        #region ...
-        public virtual event PropertyChangedEventHandler PropertyChanged;
-
-        protected virtual void Set(string name)
-        {
-
-            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
-        }
-
-        protected void Set<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
-        {
-            old = @new;
-            if (propertyName != null)
-            {
-                Set(propertyName);
-            }
-        }
-        #endregion
-
         #region 灞炴��
-        private ILog log;
         private ObservableCollection<TabItem> tabItems;
 
         public ObservableCollection<TabItem> TabItems
         {
             get { return tabItems; }
             set { Set(ref tabItems, value); }
-        }
-
-        #endregion
-
-        #region PluginApi
-
-        public object Init()
-        {
-            return null;
-        }
-
-        public object Active()
-        {
-            return null;
-        }
-
-        public object DeActive()
-        {
-            return null;
-        }
-
-        public void OnTabChange(object sender, object args)
-        {
-
-        }
-
-        public void SetLogger(ILog logger)
-        {
-            log = logger;
         }
         #endregion
 
diff --git a/HMI.SettingControl/SystemConfig.xaml b/HMI.SettingControl/SystemConfig.xaml
index 27114f5..cc84c83 100644
--- a/HMI.SettingControl/SystemConfig.xaml
+++ b/HMI.SettingControl/SystemConfig.xaml
@@ -25,10 +25,12 @@
     
     <Grid>
         <Grid.RowDefinitions>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="Auto"/>
             <RowDefinition/>
             <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
-        <GroupBox Header="绋嬪簭璁剧疆" Padding="10">
+        <GroupBox Header="鍩虹璁剧疆" Padding="10">
             <StackPanel>
                 <pu:FormGroup Header="Logo" GroupName="MyFormGroup">
                     <TextBox Text="{Binding LogoPath}"/>
@@ -39,7 +41,20 @@
                 </pu:FormGroup>
             </StackPanel>
         </GroupBox>
-        <DockPanel Grid.Row="1" LastChildFill="False">
+
+        <GroupBox Grid.Row="1"  Header="PLC璁剧疆" Padding="10">
+            <StackPanel>
+                <pu:FormGroup Header="PLC Ip" GroupName="MyFormGroup">
+                    <TextBox Text="{Binding PlcIp}"/>
+                </pu:FormGroup>
+
+                <pu:FormGroup Header="鏄惁鍚敤" GroupName="MyFormGroup">
+                    <CheckBox IsChecked="{Binding PlcEnabled,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
+                </pu:FormGroup>
+            </StackPanel>
+        </GroupBox>
+
+        <DockPanel Grid.Row="3" LastChildFill="False">
             <Button DockPanel.Dock="Right" Style="{StaticResource PrimaryButton}" Click="Button_Click">淇濆瓨</Button>
         </DockPanel>
     </Grid>
diff --git a/HMI.SettingControl/SystemConfig.xaml.cs b/HMI.SettingControl/SystemConfig.xaml.cs
index cb7ec96..1e75505 100644
--- a/HMI.SettingControl/SystemConfig.xaml.cs
+++ b/HMI.SettingControl/SystemConfig.xaml.cs
@@ -1,6 +1,8 @@
-锘縰sing System.Windows.Controls;
+锘縰sing System;
+using System.Windows.Controls;
 using HMI.Core.Setting;
 using HMI.Core.Util;
+using HMI.UI.Util;
 
 namespace HMI.SettingControl
 {
@@ -19,9 +21,17 @@
 
         private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
         {
-            SystemSettingModel settingModel = (SystemSettingModel)DataContext;
-            XmlHelper.SerializeToXml(PathHelper.ConfigFolder + "\\SystemConfig.xml",settingModel);
-            SystemSetting.ReLoad();
+            try
+            {
+                SystemSettingModel settingModel = (SystemSettingModel)DataContext;
+                XmlHelper.SerializeToXml(PathHelper.ConfigFolder + "\\SystemConfig.xml", settingModel);
+                SystemSetting.ReLoad();
+                this.Success("淇濆瓨鎴愬姛");
+            }
+            catch (Exception ex)
+            {
+                this.Error($"淇濆瓨澶辫触锛亄ex.Message}");
+            }
         }
     }
 }
diff --git a/HMI.UI/DpUtil/FormGroupHelper.cs b/HMI.UI/DpUtil/FormGroupHelper.cs
index 245a054..3447885 100644
--- a/HMI.UI/DpUtil/FormGroupHelper.cs
+++ b/HMI.UI/DpUtil/FormGroupHelper.cs
@@ -62,7 +62,7 @@
                 {
                     object content = fg.Content;
                     object value = GetValidateValue(content);
-                    if (GetIsRequired(fg) && string.IsNullOrEmpty(value.ToString()))
+                    if (value != null && GetIsRequired(fg) && string.IsNullOrEmpty(value.ToString()))
                     {
                         fg.ValidateResult = ValidateResult.Error;
                         fg.Message = $"{fg.Header}涓嶈兘涓虹┖";
@@ -93,6 +93,7 @@
             if (content is ComboBox cBox) return cBox.Text;
 
             if (content is Panel panel) return GetValidateValue(panel.Children);
+            if (content is NumberInput numberInput) return numberInput.Value;
             return null;
         }
     }
diff --git a/HMI.UI/DpUtil/GridHelper.cs b/HMI.UI/DpUtil/GridHelper.cs
new file mode 100644
index 0000000..70fc48d
--- /dev/null
+++ b/HMI.UI/DpUtil/GridHelper.cs
@@ -0,0 +1,67 @@
+锘縰sing System.Windows;
+using System.Windows.Controls;
+
+namespace HMI.UI.DpUtil
+{
+    public class GridHelper
+    {
+        public static double GetSpace(DependencyObject obj)
+        {
+            return (double)obj.GetValue(SpaceProperty);
+        }
+        public static void SetSpace(DependencyObject obj, double value)
+        {
+            obj.SetValue(SpaceProperty, value);
+        }
+        public static readonly DependencyProperty SpaceProperty =
+            DependencyProperty.RegisterAttached("Space", typeof(double), typeof(Grid),
+                new PropertyMetadata(0d, OnShowBorderChanged));
+
+        private static void OnShowBorderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            if (d is Grid grid)
+            {
+                if (e.Property == SpaceProperty)
+                {
+                    grid.Loaded += GridSpaceOnLoaded;
+                    return;
+                }
+            }
+        }
+
+        private static void GridSpaceOnLoaded(object sender, RoutedEventArgs e)
+        {
+            if (!(sender is Grid grid)) return;
+            RefreshGridSpace(grid);
+            grid.Loaded -= GridSpaceOnLoaded;
+        }
+
+        public static void RefreshGridSpace(Grid grid)
+        {
+            double space = GetSpace(grid);
+            if (space <= 0)
+            {
+                return;
+            }
+
+            var rowCount = grid.RowDefinitions.Count;
+            var columnCount = grid.ColumnDefinitions.Count;
+            int totalCount = rowCount * columnCount;
+
+            if (grid.Children == null) return;
+            foreach (FrameworkElement cell in grid.Children)
+            {
+                int row = Grid.GetRow(cell);
+                int col = Grid.GetColumn(cell);
+                int rowSpan = Grid.GetRowSpan(cell);
+                int colSpan = Grid.GetColumnSpan(cell);
+
+                cell.Margin = new Thickness(space,
+                    space,
+                    (col + colSpan) == columnCount ? space : 0,
+                    (row + rowSpan) == rowCount ? space : 0);
+            }
+        }
+
+    }
+}
diff --git a/HMI.UI/DpUtil/StackPanelHelper.cs b/HMI.UI/DpUtil/StackPanelHelper.cs
index 3c5c84a..ffe05eb 100644
--- a/HMI.UI/DpUtil/StackPanelHelper.cs
+++ b/HMI.UI/DpUtil/StackPanelHelper.cs
@@ -1,7 +1,7 @@
 锘縰sing System.Windows;
 using System.Windows.Controls;
 
-namespace HMI.UI
+namespace HMI.UI.DpUtil
 {
     public class StackPanelHelper
     {
@@ -20,19 +20,35 @@
             new PropertyMetadata(0d, (d, e) =>
             {
                 if (!(d is StackPanel sp)) return;
-                if (sp.Children == null) return;
-                var children = sp.Children;
-                double space = (double)e.NewValue;
-                if (sp.Orientation == Orientation.Horizontal)
+                sp.Loaded += Sp_Loaded;
+            }));
+
+        private static void Sp_Loaded(object sender, RoutedEventArgs e)
+        {
+            var sp = sender as StackPanel;
+            var children = sp.Children;
+            if (sp.Children == null) return;
+            double space = GetChildSpace(sp);
+            if (sp.Orientation == Orientation.Horizontal)
+            {
+                for (int i = 0; i < children.Count; i++)
                 {
-                    for (int i = 0; i < children.Count; i++)
+                    if (children[i] is FrameworkElement ui)
                     {
-                        if (children[i] is FrameworkElement ui)
-                        {
-                            ui.Margin = new Thickness(0, 0, (i == children.Count - 1) ? 0 : space, 0);
-                        }
+                        ui.Margin = new Thickness(0, 0, (i == children.Count - 1) ? 0 : space, 0);
                     }
                 }
-            }));
+            }
+            else
+            {
+                for (int i = 0; i < children.Count; i++)
+                {
+                    if (children[i] is FrameworkElement ui)
+                    {
+                        ui.Margin = new Thickness(0, 0, 0, (i == children.Count - 1) ? 0 : space);
+                    }
+                }
+            }
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/HMI.UI/DpUtil/TreeViewHelper.cs b/HMI.UI/DpUtil/TreeViewHelper.cs
index e29c50a..5346549 100644
--- a/HMI.UI/DpUtil/TreeViewHelper.cs
+++ b/HMI.UI/DpUtil/TreeViewHelper.cs
@@ -1,14 +1,9 @@
 锘縰sing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Controls;
-using System.Windows.Media;
-using System.Windows;
 using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
 
-namespace HMI.UI
+namespace HMI.UI.DpUtil
 {
     public class TreeViewHelper
     {
diff --git a/HMI.UI/HMI.UI.csproj b/HMI.UI/HMI.UI.csproj
index 9032440..9c5efce 100644
--- a/HMI.UI/HMI.UI.csproj
+++ b/HMI.UI/HMI.UI.csproj
@@ -83,6 +83,7 @@
     <Compile Include="Converter\DataGridRowNumberConverter.cs" />
     <Compile Include="Converter\PathImageConverter.cs" />
     <Compile Include="DpUtil\FormGroupHelper.cs" />
+    <Compile Include="DpUtil\GridHelper.cs" />
     <Compile Include="DpUtil\StackPanelHelper.cs" />
     <Compile Include="DpUtil\TreeViewHelper.cs" />
     <Compile Include="Style\BaseWindow.xaml.cs">
@@ -96,7 +97,6 @@
     <Resource Include="Resources\Font\Font.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Resource>
     <Page Include="Style\MsgBoxStyle.xaml">
       <SubType>Designer</SubType>
@@ -151,9 +151,7 @@
       <Generator>SettingsSingleFileGenerator</Generator>
       <LastGenOutput>Settings.Designer.cs</LastGenOutput>
     </None>
-    <Resource Include="Resources\Font\iconfont.ttf">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Resource>
+    <Resource Include="Resources\Font\iconfont.ttf" />
   </ItemGroup>
   <ItemGroup>
     <Resource Include="Resources\Icon\xinzeng_1.png" />
diff --git a/HMI.UI/Resources/Font/iconfont.ttf b/HMI.UI/Resources/Font/iconfont.ttf
index 927cfcc..25f6106 100644
--- a/HMI.UI/Resources/Font/iconfont.ttf
+++ b/HMI.UI/Resources/Font/iconfont.ttf
Binary files differ
diff --git a/HMI.UI/Style/BaseWindow.xaml b/HMI.UI/Style/BaseWindow.xaml
index 340ee2e..8edae15 100644
--- a/HMI.UI/Style/BaseWindow.xaml
+++ b/HMI.UI/Style/BaseWindow.xaml
@@ -26,7 +26,7 @@
                                 <RowDefinition/>
                             </Grid.RowDefinitions>
 
-                            <Grid Grid.Row="0" Background="{StaticResource MainBorder}">
+                            <Grid Grid.Row="0" Background="{StaticResource PrimaryColor}">
                                 <Grid.ColumnDefinitions>
                                     <ColumnDefinition/>
                                     <ColumnDefinition Width="Auto"/>
diff --git a/HMI.UI/Style/Colors.xaml b/HMI.UI/Style/Colors.xaml
index c9a7668..7b7ba9c 100644
--- a/HMI.UI/Style/Colors.xaml
+++ b/HMI.UI/Style/Colors.xaml
@@ -4,12 +4,12 @@
     <Brush x:Key="TableHeaderBackground">#fafafa</Brush>
     <Brush x:Key="TableBoarder">#e8e8e8</Brush>
     <Brush x:Key="CommonBoarder">#e8e8e8</Brush>
-    
-    
-    <Brush x:Key="PrimaryColor">#0d4d84</Brush>
+
+
+    <Brush x:Key="PrimaryColor">#22448b</Brush>
     <Brush x:Key="PrimaryColorContract">#FFF</Brush>
-    
-    <Brush x:Key="SecondPrimaryColor">#3692e1</Brush>
+
+    <Brush x:Key="SecondPrimaryColor">#0092e0</Brush>
     <Brush x:Key="SecondPrimaryColorContract">#FFF</Brush>
     
     <Brush x:Key="DangerColor">#d64343</Brush>
@@ -21,19 +21,7 @@
     <Brush x:Key="WarningColor">#e17933</Brush>
     <Brush x:Key="WarningColorContract">#FFF</Brush>
 
-    <Brush x:Key="WindowBar">#0d4d84</Brush>
-    <Brush x:Key="MainBorder">#0d4d84</Brush>
-    <Brush x:Key="MainMenu">#1d6eb2</Brush>
-    <Brush x:Key="ChildBorder">#3692e1</Brush>
-    <Brush x:Key="MainStatusBar">#1d6eb2</Brush>
-
     <Brush x:Key="SecondaryImportant">Orange</Brush>
     <Brush x:Key="Important">#e17933</Brush>
     <Brush x:Key="ImportantFont">#FFF</Brush>
-
-
-    <Brush x:Key="ButtonColor">#103156</Brush>
-    <Brush x:Key="ButtonSelected">#02579E</Brush>
-    <Brush x:Key="ButtonFont">White</Brush>
-    <Brush x:Key="ButtonFontSelected">White</Brush>
 </ResourceDictionary>
\ No newline at end of file
diff --git a/HMI.UI/Style/FormStyle.xaml b/HMI.UI/Style/FormStyle.xaml
index 9056d01..42eb600 100644
--- a/HMI.UI/Style/FormStyle.xaml
+++ b/HMI.UI/Style/FormStyle.xaml
@@ -95,6 +95,24 @@
         </Style.Triggers>
     </Style>
 
+    <Style x:Key="FormNumberInput" TargetType="pu:NumberInput" BasedOn="{StaticResource {x:Type pu:NumberInput}}">
+        <Setter Property="pu:TextBoxHelper.FocusedBorderBrush" Value="#6CBCEA" />
+        <Setter Property="pu:TextBoxHelper.FocusedShadowColor" Value="#6CBCEA" />
+        <Setter Property="pu:TextBoxHelper.CornerRadius" Value="0" />
+        <Setter Property="pu:TextBoxHelper.WatermarkForeground" Value="#4A4A4A" />
+        <Setter Property="pu:TextBoxHelper.FocusedWatermarkForeground" Value="#AAAAAA" />
+        <Setter Property="Height" Value="35" />
+        <Setter Property="Padding" Value="5,0" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="Foreground" Value="Black" />
+        <Setter Property="VerticalContentAlignment" Value="Center"/>
+        <Style.Triggers>
+            <Trigger Property="IsReadOnly" Value="True">
+                <Setter Property="Background" Value="LightGray"/>
+            </Trigger>
+        </Style.Triggers>
+    </Style>
+
     <Style x:Key="MultilineEditorTextBoxStyle" TargetType="TextBox" BasedOn="{StaticResource EditorTextBoxStyle}">
         <Setter Property="Height" Value="100" />
         <Setter Property="Padding" Value="5,10" />
@@ -130,7 +148,7 @@
 
     <Style x:Key="FormComboxStyle" TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
         <Setter Property="pu:ComboBoxHelper.CornerRadius" Value="0"/>
-        <Setter Property="pu:ComboBoxHelper.ItemsHoverBackground" Value="{StaticResource WindowBar}"/>
+        <Setter Property="pu:ComboBoxHelper.ItemsHoverBackground" Value="{StaticResource SecondPrimaryColor}"/>
         <Setter Property="pu:ComboBoxHelper.ItemsHoverForeground" Value="#FFF"/>
         <Setter Property="pu:ComboBoxHelper.ItemsSelectedForeground" Value="Black"/>
         <Setter Property="pu:ComboBoxHelper.HoverBorderBrush" Value="#007ACC" />
@@ -145,4 +163,16 @@
         <Setter Property="Foreground" Value="Black" />
         <Setter Property="SelectedValuePath" Value="Content"/>
     </Style>
+
+    <Style x:Key="TimePicker" TargetType="pu:DateTimePicker">
+        <Setter Property="Height" Value="35"/>
+        <Setter Property="ClearButtonVisibility" Value="Visible"/>
+        <Setter Property="ItemsCheckedBackground" Value="{StaticResource PrimaryColor}"/>
+        <Setter Property="ItemsCheckedForeground" Value="{StaticResource SecondPrimaryColorContract}"/>
+        <Setter Property="ItemsHoverBackground" Value="{StaticResource SecondPrimaryColor}"/>
+        <Setter Property="ItemsHoverForeground" Value="{StaticResource SecondPrimaryColorContract}"/>
+        <Setter Property="TextStringFormat" Value="yyyy-MM-dd HH:mm:ss"/>
+        <Setter Property="Mode" Value="DateTime"/>
+    </Style>
+
 </ResourceDictionary>
\ No newline at end of file
diff --git a/HMI.UI/Style/MsgBoxStyle.xaml b/HMI.UI/Style/MsgBoxStyle.xaml
index f782ed6..35fc189 100644
--- a/HMI.UI/Style/MsgBoxStyle.xaml
+++ b/HMI.UI/Style/MsgBoxStyle.xaml
@@ -130,4 +130,12 @@
         </pu:ToastSettings.LabelStyle>
     </pu:ToastSettings>
 
+    <pu:ToastSettings x:Key="toastError" Spacing="25">
+        <pu:ToastSettings.LabelStyle>
+            <Style TargetType="Label" BasedOn="{StaticResource {x:Static pu:Toast.LabelStyleKey}}">
+                <Setter Property="Background" Value="{StaticResource DangerColor}" />
+                <Setter Property="Foreground" Value="{StaticResource DangerColorContrast}" />
+            </Style>
+        </pu:ToastSettings.LabelStyle>
+    </pu:ToastSettings>
 </ResourceDictionary>
\ No newline at end of file
diff --git a/HMI.UI/Style/PanuonResource.xaml b/HMI.UI/Style/PanuonResource.xaml
index 18b061f..792c26e 100644
--- a/HMI.UI/Style/PanuonResource.xaml
+++ b/HMI.UI/Style/PanuonResource.xaml
@@ -4,10 +4,10 @@
                     xmlns:sys="clr-namespace:System;assembly=mscorlib"
                     xmlns:pw="https://opensource.panuon.com/wpf"
                     xmlns:pu="https://opensource.panuon.com/wpf-ui"
-             xmlns:dp="clr-namespace:HMI.UI;assembly=HMI.UI">
+             xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI">
     <ResourceDictionary.MergedDictionaries>
         <ResourceDictionary Source="/HMI.UI;component/Style/Colors.xaml"/>
-        <pu:StyleDictionary Includes="TextBox,ComboBox,Button,DataGrid,TreeView" />
+        <pu:StyleDictionary Includes="TextBox,ComboBox,Button,DataGrid,TreeView,Menu" />
         <ResourceDictionary Source="/HMI.UI;component/Resources/Font/Font.xaml"/>
     </ResourceDictionary.MergedDictionaries>
 
@@ -15,7 +15,7 @@
     <sys:Double x:Key="ContentFontSize">16</sys:Double>
 
     <Style x:Key="PrimaryButton" TargetType="Button" BasedOn="{StaticResource {x:Static pu:StyleKeys.ButtonStyle}}">
-        <Setter Property="Background" Value="{StaticResource WindowBar}"/>
+        <Setter Property="Background" Value="{StaticResource PrimaryColor}"/>
         <Setter Property="Foreground" Value="#FFF"/>
         <Setter Property="pu:IconHelper.FontFamily" Value="{StaticResource iconfont}"/>
         <Setter Property="pu:IconHelper.Margin" Value="0,0,10,0"/>
@@ -33,6 +33,21 @@
     <Style x:Key="DangerButton" TargetType="Button" BasedOn="{StaticResource PrimaryButton}">
         <Setter Property="Background" Value="{StaticResource DangerColor}"/>
         <Setter Property="Foreground" Value="{StaticResource DangerColorContrast}"/>
+    </Style>
+
+    <Style x:Key="AddBtn" TargetType="Button" BasedOn="{StaticResource PrimaryButton}">
+        <Setter Property="pu:ButtonHelper.Icon" Value="&#xe6a1;"/>
+        <Setter Property="Content" Value="鏂板"/>
+    </Style>
+
+    <Style x:Key="RfhBtn" TargetType="Button" BasedOn="{StaticResource PrimaryButton}">
+        <Setter Property="pu:ButtonHelper.Icon" Value="&#xe6a1;"/>
+        <Setter Property="Content" Value="鍒锋柊"/>
+    </Style>
+
+    <Style x:Key="DelBtn" TargetType="Button" BasedOn="{StaticResource DangerButton}">
+        <Setter Property="pu:ButtonHelper.Icon" Value="&#xe6a1;"/>
+        <Setter Property="Content" Value="鍒犻櫎"/>
     </Style>
 
     <Style x:Key="LinkButton" TargetType="Button" BasedOn="{StaticResource {x:Static pu:StyleKeys.ButtonStyle}}">
@@ -72,6 +87,7 @@
             </Style>
             <Style TargetType="TextBlock">
                 <Setter Property="VerticalAlignment" Value="Center"/>
+                <Setter Property="Padding" Value="10"/>
             </Style>
         </Style.Resources>
 
@@ -80,12 +96,12 @@
         <Setter Property="pu:DataGridHelper.ColumnHeaderSeparatorBrush" Value="{StaticResource TableBoarder}"/>
         <Setter Property="pu:DataGridHelper.ColumnHeaderSeparatorVisibility" Value="Visible"/>
         <Setter Property="pu:DataGridHelper.ColumnHeaderVerticalContentAlignment" Value="Center"/>
-        <Setter Property="pu:DataGridHelper.RowHeaderBackground" Value="#ffffff"/>
+        <Setter Property="pu:DataGridHelper.RowHeaderBackground" Value="White"/>
         <Setter Property="pu:DataGridHelper.RowHeaderSeparatorBrush" Value="{StaticResource PrimaryColor}"/>
         <Setter Property="pu:DataGridHelper.RowHoverForeground" Value="{StaticResource SecondPrimaryColorContract}"/>
         <Setter Property="pu:DataGridHelper.RowHoverBackground" Value="{StaticResource SecondPrimaryColor}"/>
         <Setter Property="pu:DataGridHelper.RowSelectedBackground" Value="{StaticResource PrimaryColor}"/>
-        <Setter Property="pu:DataGridHelper.RowSelectedForeground" Value="#ffffff"/>
+        <Setter Property="pu:DataGridHelper.RowSelectedForeground" Value="White"/>
         <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource TableBoarder}"/>
         <Setter Property="VerticalGridLinesBrush" Value="{StaticResource TableBoarder}"/>
         <Setter Property="BorderBrush" Value="{StaticResource TableBoarder}" />
@@ -96,11 +112,13 @@
         <Setter Property="RowHeaderWidth" Value="0"/>
         <Setter Property="IsReadOnly" Value="True"/>
         <Setter Property="GridLinesVisibility" Value="All"/>
-        <Setter Property="BorderThickness" Value="1,1,0,0"/>
+        <Setter Property="BorderThickness" Value="0"/>
         <Setter Property="FontSize" Value="{StaticResource ContentFontSize}"/>
         <Setter Property="RowHeight" Value="24"/>
         <Setter Property="ForceCursor" Value="True"/>
         <Setter Property="SelectionMode" Value="Single"/>
+        <Setter Property="pu:DataGridHelper.ColumnHeaderBorderThickness" Value="0"/>
+        <Setter Property="pu:DataGridHelper.ColumnHeaderPadding" Value="0"/>
     </Style>
 
     <Style x:Key="DefaultTreeView" TargetType="TreeView" BasedOn="{StaticResource {x:Static pu:StyleKeys.TreeViewStyle}}">
@@ -130,4 +148,27 @@
             </DataTrigger>
         </Style.Triggers>
     </Style>
+
+    <Style x:Key="DefaultTabControl" TargetType="TabControl">
+        <Setter Property="pu:TabControlHelper.ItemsHorizontalHeaderAlignment" Value="Left"/>
+        <Setter Property="pu:TabControlHelper.ItemsHoverBackground" Value="{StaticResource SecondPrimaryColor}"/>
+        <Setter Property="pu:TabControlHelper.ItemsHoverForeground" Value="{StaticResource SecondPrimaryColorContract}"/>
+        <Setter Property="pu:TabControlHelper.ItemsRibbonLineMargin" Value="0,5,0,5"/>
+        <Setter Property="pu:TabControlHelper.ItemsRibbonLineThickness" Value="4"/>
+        <Setter Property="pu:TabControlHelper.ItemsRibbonLineVisibility" Value="Visible"/>
+        <Setter Property="pu:TabControlHelper.ItemsSelectedRibbonLineBrush" Value="{StaticResource PrimaryColor}"/>
+        <Setter Property="pu:TabControlHelper.ItemsSelectedRibbonLineThickness" Value="2"/>
+    </Style>
+
+    <Style x:Key="ButtonGroup" TargetType="StackPanel">
+        <Setter Property="Orientation" Value="Horizontal"/>
+        <Setter Property="HorizontalAlignment" Value="Right"/>
+        <Setter Property="VerticalAlignment" Value="Center"/>
+        <Setter Property="dp:StackPanelHelper.ChildSpace" Value="10"/>
+    </Style>
+
+    <Style x:Key="TitleBox" TargetType="TextBlock">
+        <Setter Property="VerticalAlignment" Value="Center"/>
+        <Setter Property="FontSize" Value="{StaticResource TitleFontSize}"/>
+    </Style>
 </ResourceDictionary>
\ No newline at end of file
diff --git a/HMI.UI/Style/WindowResources.xaml b/HMI.UI/Style/WindowResources.xaml
index 46d1925..2cf9e7a 100644
--- a/HMI.UI/Style/WindowResources.xaml
+++ b/HMI.UI/Style/WindowResources.xaml
@@ -8,8 +8,8 @@
     </ResourceDictionary.MergedDictionaries>
 
     <Style x:Key="WindowButton" TargetType="Button">
-        <Setter Property="Background" Value="{StaticResource MainBorder}"/>
-        <Setter Property="ui:DpPlugin.HoverColor" Value="{StaticResource ChildBorder}"/>
+        <Setter Property="Background" Value="{StaticResource PrimaryColor}"/>
+        <Setter Property="ui:DpPlugin.HoverColor" Value="{StaticResource SecondPrimaryColor}"/>
         <Setter Property="FontFamily" Value="{StaticResource iconfont}"/>
         <Setter Property="FontWeight" Value="SemiBold"/>
         <Setter Property="Foreground" Value="White"/>
@@ -49,8 +49,8 @@
     <Style x:Key="ChildWindowButton" BasedOn="{StaticResource WindowButton}" TargetType="Button">
         <Setter Property="FontSize" Value="15"/>
         <Setter Property="Width" Value="30"/>
-        <Setter Property="Background" Value="{StaticResource ChildBorder}"/>
-        <Setter Property="ui:DpPlugin.HoverColor" Value="{StaticResource MainBorder}"/>
+        <Setter Property="Background" Value="{StaticResource SecondPrimaryColor}"/>
+        <Setter Property="ui:DpPlugin.HoverColor" Value="{StaticResource PrimaryColor}"/>
     </Style>
 
     <Style x:Key="ChildWindowCloseButton" BasedOn="{StaticResource ChildWindowButton}" TargetType="Button">
@@ -58,9 +58,9 @@
     </Style>
 
     <Style x:Key="LinkButton" TargetType="Button">
-        <Setter Property="ui:DpPlugin.HoverColor" Value="{StaticResource ChildBorder}"/>
+        <Setter Property="ui:DpPlugin.HoverColor" Value="{StaticResource SecondPrimaryColor}"/>
         <Setter Property="FontFamily" Value="{StaticResource iconfont}"/>
-        <Setter Property="Foreground" Value="{StaticResource ChildBorder}"/>
+        <Setter Property="Foreground" Value="{StaticResource SecondPrimaryColor}"/>
 
         <Setter Property="Template">
             <Setter.Value>
diff --git a/HMI.UI/Util/MsgBoxHelper.cs b/HMI.UI/Util/MsgBoxHelper.cs
index 2f0e3df..496b435 100644
--- a/HMI.UI/Util/MsgBoxHelper.cs
+++ b/HMI.UI/Util/MsgBoxHelper.cs
@@ -1,6 +1,7 @@
 锘縰sing Panuon.WPF.UI;
 using System.Windows;
 using Panuon.WPF.UI.Configurations;
+using System.Windows.Threading;
 
 namespace HMI.UI.Util
 {
@@ -15,12 +16,12 @@
             DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
         {
             var setting = Application.Current.FindResource("MsgBoxWarn") as MessageBoxXSetting;
-            return MessageBoxX.Show(owner, message, caption, button, icon, defaultButton, setting, countdown);
+            return ShowMessage(owner, message, caption, button, icon, defaultButton, setting, countdown);
         }
         #endregion
 
         #region Error
-        public static MessageBoxResult ErrorMessage(Window owner,
+        public static MessageBoxResult ErrorMessage(DependencyObject owner,
             string message,
             string caption = "閿欒",
             MessageBoxButton button = MessageBoxButton.OKCancel,
@@ -28,7 +29,18 @@
             DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
         {
             var setting = Application.Current.FindResource("MsgBoxError") as MessageBoxXSetting;
-            return MessageBoxX.Show(owner, message, caption, button, icon, defaultButton, setting, countdown);
+            return ShowMessage(owner, message, caption, button, icon, defaultButton, setting, countdown);
+        }
+
+        public static MessageBoxResult Error(DependencyObject owner,
+            string message,
+            string caption = "閿欒",
+            MessageBoxButton button = MessageBoxButton.OK,
+            MessageBoxIcon icon = MessageBoxIcon.Error,
+            DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
+        {
+            var setting = Application.Current.FindResource("MsgBoxError") as MessageBoxXSetting;
+            return ShowMessage(owner, message, caption, button, icon, defaultButton, setting, countdown);
         }
         #endregion
 
@@ -41,8 +53,31 @@
             DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
         {
             var setting = Application.Current.FindResource("MsgBoxInfo") as MessageBoxXSetting;
-            return MessageBoxX.Show(owner, message, caption, button, icon, defaultButton, setting, countdown);
+            return ShowMessage(owner, message, caption, button, icon, defaultButton, setting, countdown);
         }
         #endregion
+
+        public static MessageBoxResult ShowMessage(DependencyObject owner,
+            string message,
+            string caption,
+            MessageBoxButton button,
+            MessageBoxIcon icon,
+            DefaultButton defaultButton, MessageBoxXSetting setting, int? countdown)
+        {
+            MessageBoxResult res = MessageBoxResult.None;
+            Application.Current.Dispatcher.Invoke(() =>
+            {
+                if (owner is Window window)
+                {
+                    res = MessageBoxX.Show(window, message, caption, button, icon, defaultButton, setting, countdown);
+                }
+                else
+                {
+                    window = Window.GetWindow(owner);
+                    res = MessageBoxX.Show(window, message, caption, button, icon, defaultButton, setting, countdown);
+                }
+            });
+            return res;
+        }
     }
 }
diff --git a/HMI.UI/Util/ToastHelper.cs b/HMI.UI/Util/ToastHelper.cs
index 7f32e02..6410963 100644
--- a/HMI.UI/Util/ToastHelper.cs
+++ b/HMI.UI/Util/ToastHelper.cs
@@ -1,5 +1,6 @@
 锘縰sing Panuon.WPF.UI;
 using System.Windows;
+using System.Windows.Controls;
 
 namespace HMI.UI.Util
 {
@@ -12,6 +13,18 @@
                 ToastWindow targetWindow);
 
         void Warning(Window window,
+                string message,
+                MessageBoxIcon icon,
+                ToastPosition position, double offset, int durationMs,
+                ToastWindow targetWindow);
+
+        void Error(Window window,
+                string message,
+                MessageBoxIcon icon,
+                ToastPosition position, double offset, int durationMs,
+                ToastWindow targetWindow);
+
+        void Info(Window window,
                 string message,
                 MessageBoxIcon icon,
                 ToastPosition position, double offset, int durationMs,
@@ -44,5 +57,100 @@
         {
             Instance.Warning(window, message, icon, position, offset, durationMs, targetWindow);
         }
+
+        public static void Error(Window window,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Error,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            Instance.Error(window, message, icon, position, offset, durationMs, targetWindow);
+        }
+
+        public static void Info(Window window,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Info,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            Instance.Info(window, message, icon, position, offset, durationMs, targetWindow);
+        }
+    }
+
+    public static class ToastUtil
+    {
+
+        public static void Success(this Window window,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Success,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Success(window, message, icon, position, offset, durationMs, targetWindow);
+        }
+
+        public static void Warning(this Window window,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Warning,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Warning(window, message, icon, position, offset, durationMs, targetWindow);
+        }
+
+        public static void Error(this Window window,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Error,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Error(window, message, icon, position, offset, durationMs, targetWindow);
+        }
+
+        public static void Info(this Window window,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Info,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Info(window, message, icon, position, offset, durationMs, targetWindow);
+        }
+
+
+        public static void Success(this UserControl control,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Success,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Success(Window.GetWindow(control), message, icon, position, offset, durationMs, targetWindow);
+        }
+
+        public static void Warning(this UserControl control,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Warning,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Warning(Window.GetWindow(control), message, icon, position, offset, durationMs, targetWindow);
+        }
+
+        public static void Error(this UserControl control,
+            string message,
+            MessageBoxIcon icon = MessageBoxIcon.Error,
+            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+            ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Error(Window.GetWindow(control), message, icon, position, offset, durationMs, targetWindow);
+        }
+
+        public static void Info(this UserControl control,
+           string message,
+           MessageBoxIcon icon = MessageBoxIcon.Error,
+           ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
+           ToastWindow targetWindow = ToastWindow.ActiveWindow)
+        {
+            ToastHelper.Info(Window.GetWindow(control), message, icon, position, offset, durationMs, targetWindow);
+        }
     }
 }
diff --git a/HMI.UnitTest/MainWindow.xaml.cs b/HMI.UnitTest/MainWindow.xaml.cs
index ba897eb..d6a2c49 100644
--- a/HMI.UnitTest/MainWindow.xaml.cs
+++ b/HMI.UnitTest/MainWindow.xaml.cs
@@ -25,7 +25,7 @@
         {
             InitializeComponent();
             page.Children.Clear();
-            page.Children.Add(new SettingControl());
+            //page.Children.Add(new SettingControl());
         }
     }
 }
diff --git a/Libs/OpcInterface.dll b/Libs/OpcInterface.dll
new file mode 100644
index 0000000..67ba8ec
--- /dev/null
+++ b/Libs/OpcInterface.dll
Binary files differ
diff --git a/Libs/SimensDriver.dll b/Libs/SimensDriver.dll
new file mode 100644
index 0000000..c215ad6
--- /dev/null
+++ b/Libs/SimensDriver.dll
Binary files differ
diff --git a/WPFProject/App.config b/WPFProject/App.config
index 6c4d0d1..7f7c188 100644
--- a/WPFProject/App.config
+++ b/WPFProject/App.config
@@ -1,8 +1,8 @@
 锘�<?xml version="1.0" encoding="utf-8"?>
 <configuration>
-    <startup> 
-        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
-    </startup>
+	<startup>
+		<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
+	</startup>
 	<runtime>
 		<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
 			<probing privatePath="Libs;ThirdParty;Plugin;" />
@@ -18,6 +18,10 @@
 				<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
 				<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
 			</dependentAssembly>
+			<dependentAssembly>
+				<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+				<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
+			</dependentAssembly>
 		</assemblyBinding>
 	</runtime>
 </configuration>
\ No newline at end of file
diff --git a/WPFProject/App.xaml.cs b/WPFProject/App.xaml.cs
index 2715cec..882f867 100644
--- a/WPFProject/App.xaml.cs
+++ b/WPFProject/App.xaml.cs
@@ -1,14 +1,8 @@
-锘縰sing System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows;
-using HMI.UI.Util;
-using System.Windows.Markup;
+锘縰sing HMI.UI.Util;
 using log4net;
 using Panuon.WPF.UI;
+using System;
+using System.Windows;
 
 namespace WPFProject
 {
@@ -26,10 +20,12 @@
 
         private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
         {
-            log.Error("鏈煡寮傚父", e.ExceptionObject as Exception);
+            var ex = e.ExceptionObject as Exception;
+            log.Error("UnhandledException.", ex);
             Dispatcher.Invoke(() =>
             {
-                MsgBoxHelper.ErrorMessage(Current.MainWindow, $"鍙戠敓鏈煡寮傚父锛佺▼搴忓嵆灏嗗叧闂�", "閿欒", MessageBoxButton.OK,
+                MsgBoxHelper.ErrorMessage(Current.MainWindow, $"鍙戠敓鏈煡寮傚父锛佺▼搴忓嵆灏嗗叧闂璡r\n{ex?.Message}",
+                    "閿欒", MessageBoxButton.OK,
                     MessageBoxIcon.Error, DefaultButton.YesOK, 5);
             });
         }
diff --git a/WPFProject/Controls/MainTabControl.xaml b/WPFProject/Controls/MainTabControl.xaml
index e2655f1..2949177 100644
--- a/WPFProject/Controls/MainTabControl.xaml
+++ b/WPFProject/Controls/MainTabControl.xaml
@@ -13,29 +13,33 @@
             </ResourceDictionary.MergedDictionaries>
 
             <Style TargetType="ListBox" x:Key="ListBoxItemStyle1">
-                <Setter Property="Background" Value="{StaticResource MainMenu}"/>
+                <Setter Property="Background" Value="{StaticResource PrimaryColor}"/>
                 <Setter Property="ItemContainerStyle">
                     <Setter.Value>
                         <Style TargetType="ListBoxItem">
                             <Setter Property="Margin" Value="0"/>
                             <Setter Property="Padding" Value="0"/>
+                            <Setter Property="Foreground" Value="{StaticResource PrimaryColorContract}"/>
                             <Setter Property="Template">
                                 <Setter.Value>
                                     <ControlTemplate TargetType="ListBoxItem">
-                                        <Border x:Name="border" Background="{StaticResource MainMenu}" 
-                                                Padding="10" Margin="0" BorderThickness="0,0,1,0" BorderBrush="Gray">
+                                        <Border x:Name="border" Background="{StaticResource PrimaryColor}" 
+                                                Padding="10" Margin="0" BorderThickness="0,0,1,1" 
+                                                BorderBrush="Gray">
                                             <!-- 鍐呭鍛堢幇鍣� -->
                                             <StackPanel>
-                                                <ContentPresenter  Content="{TemplateBinding Content}" 
+                                                <ContentPresenter x:Name="cp" Content="{TemplateBinding Content}" 
                                                                    ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                                                                    ContentTemplate="{TemplateBinding ContentTemplate}"  />
                                             </StackPanel>
-
                                         </Border>
 
                                         <ControlTemplate.Triggers>
                                             <Trigger Property="IsSelected" Value="True">
-                                                <Setter TargetName="border" Property="Background" Value="{StaticResource ButtonSelected}" />
+                                                <Setter TargetName="border" Property="Background" 
+                                                        Value="{StaticResource WorkspaceBackground}"/>
+                                                <Setter Property="Foreground" Value="{StaticResource PrimaryColor}"/>
+                                                <Setter TargetName="border" Property="BorderThickness" Value="0,0,0,0"/>
                                             </Trigger>
 
                                             <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=(ItemsControl.AlternationIndex)}" Value="0">
@@ -43,7 +47,8 @@
                                             </DataTrigger>
 
                                             <Trigger Property="IsMouseOver" Value="True">
-                                                <Setter TargetName="border" Property="Background" Value="Red" />
+                                                <Setter TargetName="border" Property="Background" Value="{StaticResource SecondPrimaryColor}" />
+                                                <Setter Property="Foreground" Value="{StaticResource SecondPrimaryColorContract}" />
                                             </Trigger>
                                         </ControlTemplate.Triggers>
                                     </ControlTemplate>
@@ -64,8 +69,8 @@
                         <DataTemplate>
                             <StackPanel Orientation="Horizontal" VerticalAlignment="Center" >
                                 <Image Width="20" Height="20" Margin="5" Source="{Binding Icon}"/>
-                                <Label x:Name="txt" Visibility="Visible" BorderThickness="0" 
-                                       Foreground="{StaticResource PrimaryColorContract}"
+                                <Label x:Name="txt" BorderThickness="0" 
+                                       Foreground="{Binding Foreground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem}}"
                                        FontWeight="Bold" 
                                        FontSize="16"
                                        VerticalContentAlignment="Center" 
@@ -103,7 +108,7 @@
                  Visibility="{Binding MenuVisibility}"
                  SelectedItem="{Binding SelectedSubMenu}" AlternationCount="{Binding SubMenuItemsCount}"
                  SelectionChanged="SubMenu_SelectionChanged"
-BorderThickness="0,0,0,1" ItemsSource="{Binding SubMenuItems}">
+BorderThickness="0" ItemsSource="{Binding SubMenuItems}">
         </ListBox>
 
         <Border x:Name="page"  Grid.Row="2" BorderThickness="0" Margin="0" Padding="0">
diff --git a/WPFProject/Controls/MinInnerWindow.xaml b/WPFProject/Controls/MinInnerWindow.xaml
index 03defd0..714ab63 100644
--- a/WPFProject/Controls/MinInnerWindow.xaml
+++ b/WPFProject/Controls/MinInnerWindow.xaml
@@ -16,8 +16,8 @@
         </ResourceDictionary>
     </UserControl.Resources>
 
-    <StackPanel Background="{StaticResource ChildBorder}" Orientation="Horizontal">
-        <Label BorderBrush="{StaticResource MainBorder}" Foreground="#FFF" BorderThickness="2,0,0,0" VerticalContentAlignment="Center" ToolTip="{Binding Title}" Content="{Binding Title}"/>
+    <StackPanel Background="{StaticResource SecondPrimaryColor}" Orientation="Horizontal">
+        <Label BorderBrush="{StaticResource PrimaryColor}" Foreground="#FFF" BorderThickness="2,0,0,0" VerticalContentAlignment="Center" ToolTip="{Binding Title}" Content="{Binding Title}"/>
         <Button Style="{StaticResource ChildWindowButton}" Click="Max_Click" >&#xe602;</Button>
         <Button Style="{StaticResource ChildWindowCloseButton}" Click="CLose_Click">&#xe609;</Button>
     </StackPanel>
diff --git a/WPFProject/Libs/SQLite.Interop.dll b/WPFProject/Libs/SQLite.Interop.dll
new file mode 100644
index 0000000..f666eab
--- /dev/null
+++ b/WPFProject/Libs/SQLite.Interop.dll
Binary files differ
diff --git a/WPFProject/LoadingWindow.xaml.cs b/WPFProject/LoadingWindow.xaml.cs
index a9755db..6a857bb 100644
--- a/WPFProject/LoadingWindow.xaml.cs
+++ b/WPFProject/LoadingWindow.xaml.cs
@@ -1,4 +1,5 @@
-锘縰sing System.Windows;
+锘縰sing System.Threading.Tasks;
+using System.Windows;
 using HMI.Base;
 
 namespace WPFProject
@@ -23,7 +24,10 @@
 
         private void Loader_LoadMessageAppend(object sender, string e)
         {
-            Console.Text += $"{e}\r\n";
+            Dispatcher.BeginInvoke(() =>
+            {
+                Console.Text = Console.Text+$"{e}\r\n";
+            });
         }
 
         private void Button_Click(object sender, RoutedEventArgs e)
diff --git a/WPFProject/MainWindow.xaml b/WPFProject/MainWindow.xaml
index 1b5359a..e4a2783 100644
--- a/WPFProject/MainWindow.xaml
+++ b/WPFProject/MainWindow.xaml
@@ -54,6 +54,6 @@
         </ctl:MenuTabControl>-->
 
 
-        <StatusBar Grid.Row="2" Background="{StaticResource MainStatusBar}">99999</StatusBar>
+        <StatusBar Grid.Row="2" Background="{StaticResource PrimaryColor}">99999</StatusBar>
     </Grid>
 </Window>
diff --git a/WPFProject/PanuonWindow.xaml b/WPFProject/PanuonWindow.xaml
index 4f54589..885e305 100644
--- a/WPFProject/PanuonWindow.xaml
+++ b/WPFProject/PanuonWindow.xaml
@@ -11,15 +11,15 @@
             WindowStartupLocation="CenterOwner"
             WindowState="Maximized"
             x:Name="window"
-            BorderBrush="{StaticResource MainBorder}"
+            BorderBrush="{StaticResource PrimaryColor}"
             Loaded="window_Loaded"
-            pu:WindowXCaption.Background="{StaticResource MainBorder}"
+            pu:WindowXCaption.Background="{StaticResource PrimaryColor}"
             pu:WindowXCaption.Foreground="#FFF" d:DesignHeight="115.146" d:DesignWidth="341.223">
 
     <pu:WindowXCaption.HeaderTemplate>
         <DataTemplate>
             <StackPanel DataContext="{Binding ElementName=window}" Orientation="Horizontal"
-                    Margin="5,0,0,0">
+                        Height="100" Margin="5,0,0,0">
                 <Image Source="{Binding WindowLogo}"
                    RenderOptions.BitmapScalingMode="HighQuality"
                    Height="{StaticResource TitleFontSize}" />
@@ -53,6 +53,6 @@
         <!--<ctl:MenuTabControl Grid.Row="1" x:Name="menuTab" OnTabChange="menuTab_OnTabChange"> </ctl:MenuTabControl>-->
 
 
-        <StatusBar Grid.Row="1" Background="{StaticResource MainStatusBar}">99999</StatusBar>
+        <StatusBar Grid.Row="1" Background="{StaticResource PrimaryColor}">99999</StatusBar>
     </Grid>
 </pu:WindowX>
diff --git a/WPFProject/PanuonWindow.xaml.cs b/WPFProject/PanuonWindow.xaml.cs
index d59e870..26e4d35 100644
--- a/WPFProject/PanuonWindow.xaml.cs
+++ b/WPFProject/PanuonWindow.xaml.cs
@@ -1,15 +1,13 @@
-锘縰sing System;
+锘縰sing HMI.Core.Setting;
+using HMI.Core.Util;
+using HMI.UI.Util;
+using Panuon.WPF.UI;
+using System;
 using System.IO;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
-using HandyControl.Tools.Extension;
-using HMI.Core.Api;
-using HMI.Core.Setting;
-using HMI.Core.Util;
-using HMI.UI.Util;
-using Panuon.WPF.UI;
 using WPFProject.Utils;
 
 namespace WPFProject
diff --git a/WPFProject/SQLite.Interop.dll b/WPFProject/SQLite.Interop.dll
new file mode 100644
index 0000000..f666eab
--- /dev/null
+++ b/WPFProject/SQLite.Interop.dll
Binary files differ
diff --git a/WPFProject/TestWindow.xaml b/WPFProject/TestWindow.xaml
index 0e9ddb6..211a661 100644
--- a/WPFProject/TestWindow.xaml
+++ b/WPFProject/TestWindow.xaml
@@ -32,6 +32,6 @@
         <!--<ctl:MenuTabControl Grid.Row="1" x:Name="menuTab" OnTabChange="menuTab_OnTabChange"> </ctl:MenuTabControl>-->
 
 
-        <StatusBar Grid.Row="1" Background="{StaticResource MainStatusBar}">99999</StatusBar>
+        <StatusBar Grid.Row="1" Background="{StaticResource PrimaryColor}">99999</StatusBar>
     </Grid>
 </ui:BaseWindow>
diff --git a/WPFProject/Utils/MainToastHandler.cs b/WPFProject/Utils/MainToastHandler.cs
index ed44805..f35686b 100644
--- a/WPFProject/Utils/MainToastHandler.cs
+++ b/WPFProject/Utils/MainToastHandler.cs
@@ -38,5 +38,33 @@
                 Toast.Show(wx, message, icon, position, 0, durationMs, setting);
             }
         }
+
+        public void Error(Window window, string message, MessageBoxIcon icon, ToastPosition position, double offset, int durationMs, ToastWindow targetWindow)
+        {
+            var setting = Application.Current.FindResource("toastError") as ToastSetting;
+            if (window is PanuonWindow pw)
+            {
+                double num = 20 + (pw.menuTab.MenuVisibility == Visibility.Visible ? pw.menuTab.Menu.ActualHeight + pw.menuTab.SubMenu.ActualHeight : 0);
+                Toast.Show(pw, message, icon, position, num, durationMs, setting);
+            }
+            else if (window is WindowX wx)
+            {
+                Toast.Show(wx, message, icon, position, 0, durationMs, setting);
+            }
+        }
+
+        public void Info(Window window, string message, MessageBoxIcon icon, ToastPosition position, double offset, int durationMs, ToastWindow targetWindow)
+        {
+            var setting = Application.Current.FindResource("toastError") as ToastSetting;
+            if (window is PanuonWindow pw)
+            {
+                double num = 20 + (pw.menuTab.MenuVisibility == Visibility.Visible ? pw.menuTab.Menu.ActualHeight + pw.menuTab.SubMenu.ActualHeight : 0);
+                Toast.Show(pw, message, icon, position, num, durationMs, setting);
+            }
+            else if (window is WindowX wx)
+            {
+                Toast.Show(wx, message, icon, position, 0, durationMs, setting);
+            }
+        }
     }
 }
diff --git a/WPFProject/WPFProject.csproj b/WPFProject/WPFProject.csproj
index 354471f..b5336b6 100644
--- a/WPFProject/WPFProject.csproj
+++ b/WPFProject/WPFProject.csproj
@@ -328,6 +328,9 @@
       <Generator>ResXFileCodeGenerator</Generator>
       <LastGenOutput>Resources.Designer.cs</LastGenOutput>
     </EmbeddedResource>
+    <Content Include="Libs\SQLite.Interop.dll">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
     <Content Include="log4net.config">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>
@@ -350,13 +353,17 @@
     <Resource Include="Resources\Icon\xinzeng_1.png" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\HMI.AlermInfoManage\HMI.AlermInfoManage.csproj">
+    <ProjectReference Include="..\HMI.AlermInfoManage\HMI.AlarmInfoManage.csproj">
       <Project>{945c2577-4558-45e3-891a-096cb3047304}</Project>
-      <Name>HMI.AlermInfoManage</Name>
+      <Name>HMI.AlarmInfoManage</Name>
     </ProjectReference>
     <ProjectReference Include="..\HMI.Base\HMI.Base.csproj">
       <Project>{2a6f9720-a890-4036-9d73-41a0dae28341}</Project>
       <Name>HMI.Base</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HMI.DataViewer\HMI.DataViewer.csproj">
+      <Project>{a580de4a-34e7-4efe-ad2c-0871396000e9}</Project>
+      <Name>HMI.DataViewer</Name>
     </ProjectReference>
     <ProjectReference Include="..\HMI.IOMonitor\HMI.IOMonitor.csproj">
       <Project>{f7663c79-7047-42f3-b129-73a2575ee7c6}</Project>
@@ -388,11 +395,13 @@
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>
   </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Config\" />
+    <Folder Include="Plugin\" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
     <PostBuildEvent>copy /Y "$(TargetDir)HMI.MenuManage.dll" "$(TargetDir)\Plugin\HMI.MenuManage.dll" 
-copy /Y "$(TargetDir)HMI.MenuManage.pdb" "$(TargetDir)\Plugin\HMI.MenuManage.pdb"
-copy /Y "$(TargetDir)HMI.AlermInfoManage.dll" "$(TargetDir)\Plugin\HMI.AlermInfoManage.dll" 
-copy /Y "$(TargetDir)HMI.AlermInfoManage.pdb" "$(TargetDir)\Plugin\HMI.AlermInfoManage.pdb"</PostBuildEvent>
+copy /Y "$(TargetDir)HMI.MenuManage.pdb" "$(TargetDir)\Plugin\HMI.MenuManage.pdb"</PostBuildEvent>
   </PropertyGroup>
 </Project>
\ No newline at end of file
diff --git a/WPFProject/WPFProject.sln b/WPFProject/WPFProject.sln
index 4201d5e..92be340 100644
--- a/WPFProject/WPFProject.sln
+++ b/WPFProject/WPFProject.sln
@@ -19,7 +19,7 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.UnitTest", "..\HMI.UnitTest\HMI.UnitTest.csproj", "{325A7F52-FE51-44F0-B3AC-5F42F5356605}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.AlermInfoManage", "..\HMI.AlermInfoManage\HMI.AlermInfoManage.csproj", "{945C2577-4558-45E3-891A-096CB3047304}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.AlarmInfoManage", "..\HMI.AlermInfoManage\HMI.AlarmInfoManage.csproj", "{945C2577-4558-45E3-891A-096CB3047304}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.SettingControl", "..\HMI.SettingControl\HMI.SettingControl.csproj", "{3DD748AC-9708-49AD-B846-659214035588}"
 EndProject
@@ -30,6 +30,8 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.IOMonitor", "..\HMI.IOMonitor\HMI.IOMonitor.csproj", "{F7663C79-7047-42F3-B129-73A2575EE7C6}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.ParameterManage", "..\HMI.ParameterManage\HMI.ParameterManage.csproj", "{736CD77D-B81E-4866-BB00-84B0B57110F0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonLibs", "..\..\HMI.Old\Framework\CommonLibs\CommonLibs\CommonLibs.csproj", "{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -121,8 +123,8 @@
 		{3DD748AC-9708-49AD-B846-659214035588}.Release|x64.Build.0 = Release|Any CPU
 		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Debug|x64.Build.0 = Debug|Any CPU
+		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Debug|x64.ActiveCfg = Debug|x64
+		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Debug|x64.Build.0 = Debug|x64
 		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Release|Any CPU.Build.0 = Release|Any CPU
 		{2A6F9720-A890-4036-9D73-41A0DAE28341}.Release|x64.ActiveCfg = Release|Any CPU
@@ -151,6 +153,14 @@
 		{736CD77D-B81E-4866-BB00-84B0B57110F0}.Release|Any CPU.Build.0 = Release|Any CPU
 		{736CD77D-B81E-4866-BB00-84B0B57110F0}.Release|x64.ActiveCfg = Release|Any CPU
 		{736CD77D-B81E-4866-BB00-84B0B57110F0}.Release|x64.Build.0 = Release|Any CPU
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Debug|x64.ActiveCfg = Debug|x64
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Debug|x64.Build.0 = Debug|x64
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Release|x64.ActiveCfg = Release|x64
+		{0212E104-4E85-4F9F-AA70-FC4FAC25C3E5}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/WPFProject/test.xml b/WPFProject/test.xml
deleted file mode 100644
index 8a72696..0000000
--- a/WPFProject/test.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-16"?>
-<ArrayOfProgram xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-  <Program>
-    <Name>123</Name>
-    <Sequences>
-      <Sequence>
-        <Name>S123</Name>
-        <Steps>
-          <Step>
-            <Index>0</Index>
-            <Name>000</Name>
-          </Step>
-          <Step>
-            <Index>0</Index>
-            <Name>111</Name>
-          </Step>
-        </Steps>
-      </Sequence>
-      <Sequence>
-        <Name>S223</Name>
-        <Steps>
-          <Step>
-            <Index>0</Index>
-            <Name>000</Name>
-          </Step>
-          <Step>
-            <Index>0</Index>
-            <Name>111</Name>
-          </Step>
-        </Steps>
-      </Sequence>
-    </Sequences>
-  </Program>
-  <Program>
-    <Name>223</Name>
-    <Sequences>
-      <Sequence>
-        <Name>D123</Name>
-        <Steps>
-          <Step>
-            <Index>0</Index>
-            <Name>000</Name>
-          </Step>
-          <Step>
-            <Index>0</Index>
-            <Name>111</Name>
-          </Step>
-        </Steps>
-      </Sequence>
-      <Sequence>
-        <Name>D223</Name>
-        <Steps>
-          <Step>
-            <Index>0</Index>
-            <Name>000</Name>
-          </Step>
-          <Step>
-            <Index>0</Index>
-            <Name>111</Name>
-          </Step>
-        </Steps>
-      </Sequence>
-    </Sequences>
-  </Program>
-</ArrayOfProgram>
\ No newline at end of file

--
Gitblit v1.9.1