From ef218c411376789bfd2bc9d513834f942523e789 Mon Sep 17 00:00:00 2001
From: Falcon <12919280+falconfly@user.noreply.gitee.com>
Date: Fri, 24 Oct 2025 13:23:01 +0800
Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90=E5=9F=BA?=
 =?UTF-8?q?=E7=A1=80=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
 PrivateBox/DataContext/CryptionKey.cs  |  18 ++++
 PrivateBox/DataContext/CrytionItem.cs  |  22 +++++
 PrivateBox/DataContext/DbContext.cs    |  39 +++++++-
 PrivateBox/DataContext/DbEntityBase.cs |  24 +++++
 PrivateBox/DataContext/UserKeys.cs     |  12 ---
 PrivateBox/InputDlgBox.Designer.cs     |  84 +++++++++++++++++
 PrivateBox/InputDlgBox.cs              |  36 ++++++++
 PrivateBox/InputDlgBox.resx            | 120 +++++++++++++++++++++++++
 PrivateBox/MainForm.Designer.cs        |  46 +++++++---
 PrivateBox/MainForm.cs                 |  86 ++++++++++++++++--
 PrivateBox/MainForm.resx               |  12 +--
 11 files changed, 452 insertions(+), 47 deletions(-)
 create mode 100644 PrivateBox/DataContext/CryptionKey.cs
 create mode 100644 PrivateBox/DataContext/CrytionItem.cs
 create mode 100644 PrivateBox/DataContext/DbEntityBase.cs
 delete mode 100644 PrivateBox/DataContext/UserKeys.cs
 create mode 100644 PrivateBox/InputDlgBox.Designer.cs
 create mode 100644 PrivateBox/InputDlgBox.cs
 create mode 100644 PrivateBox/InputDlgBox.resx
diff --git a/PrivateBox/DataContext/CryptionKey.cs b/PrivateBox/DataContext/CryptionKey.cs
new file mode 100644
index 0000000..69dcbcb
--- /dev/null
+++ b/PrivateBox/DataContext/CryptionKey.cs
@@ -0,0 +1,18 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace PrivateBox.DataContext
+{
+    /// 
+    /// 用户保密键
+    /// 
+    public class CryptionKey:DbEntityBase
+    {
+        /// 
+        /// 用于加密的键
+        /// 
+        [Required]
+        public string? Key { get; set; }
+
+    }
+
+}
diff --git a/PrivateBox/DataContext/CrytionItem.cs b/PrivateBox/DataContext/CrytionItem.cs
new file mode 100644
index 0000000..a664b0a
--- /dev/null
+++ b/PrivateBox/DataContext/CrytionItem.cs
@@ -0,0 +1,22 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace PrivateBox.DataContext
+{
+    /// 
+    /// 加密项
+    /// 
+    public class CrytionItem:DbEntityBase
+    {
+        /// 
+        /// 加密项名称
+        /// 
+        [Required]
+        [MaxLength(200)]
+        public string? ItemName { get; set; }
+        /// 
+        /// 加密项值
+        /// 
+        [SqlSugar.SugarColumn(ColumnDataType ="text")]
+        public string? ItemValue { get; set; }
+    }
+}
diff --git a/PrivateBox/DataContext/DbContext.cs b/PrivateBox/DataContext/DbContext.cs
index a805fd9..e8d3fc8 100644
--- a/PrivateBox/DataContext/DbContext.cs
+++ b/PrivateBox/DataContext/DbContext.cs
@@ -1,6 +1,8 @@
 using Microsoft.Extensions.DependencyInjection;
+using PrivateBox.DataContext;
 using SqlSugar;
 using System.Runtime.CompilerServices;
+using System.Text;
 
 namespace PrivateBox
 {
@@ -11,24 +13,53 @@ namespace PrivateBox
     {
         public AppConfig Config { get; init; }
 
-        public DbContext(IServiceProvider provider,AppConfig config) : base(new ConnectionConfig {
+        /// 
+        /// 数据库是否已经初始化
+        /// 
+        private static bool IsInited = false;
+
+        public DbContext(AppConfig config) : base(new ConnectionConfig {
             DbType = DbType.Sqlite,
             ConnectionString = config.SqliteFileName,
             IsAutoCloseConnection = false,
 
         }) {
             this.Config = config;
+            DbInit();
         }
 
         /// 
         /// 初始化数据库
         /// 
         public void DbInit() {
+            if(IsInited) {
+                return;
+            }
             this.CodeFirst.SetStringDefaultLength(200);
-            //db.CodeFirst.InitTables();
-            //db.CodeFirst.InitTables();
-            //db.CodeFirst.InitTables();
+            this.CodeFirst.InitTables();
+            this.CodeFirst.InitTables();
+            IsInited = true;
+        }
 
+        /// 
+        /// 获取加密用的key
+        /// 
+        /// 加密用的key
+        public string GetCrytionKey() {
+            var qu = this.Queryable().ToList();
+            if(qu.Any() && !string.IsNullOrEmpty(qu.First().Key)) {
+                return qu.First().Key;
+            }
+            var keyChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnobqrstuvwxyz1234567890".ToArray();
+            StringBuilder key = new(36);
+            Random rd = new Random();
+            for(int i = 0;i < key.Capacity;i++) {
+                int index = (int)rd.NextInt64(0,keyChars.Length);
+                var k = keyChars[index];
+                key.Append(k);
+            }
+            this.Insertable(new CryptionKey { Key = key.ToString() }).ExecuteCommand();
+            return key.ToString();
         }
     }
 }
diff --git a/PrivateBox/DataContext/DbEntityBase.cs b/PrivateBox/DataContext/DbEntityBase.cs
new file mode 100644
index 0000000..223af0a
--- /dev/null
+++ b/PrivateBox/DataContext/DbEntityBase.cs
@@ -0,0 +1,24 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace PrivateBox.DataContext
+{
+    /// 
+    /// 用户保密键
+    /// 
+    public abstract class DbEntityBase
+    {
+        /// 
+        /// 键ID
+        /// 
+        [StringLength(36)]
+        [Key, Required]
+        public string Id { get; set; } = Guid.NewGuid().ToString();
+
+        /// 
+        /// 键创建时间
+        /// 
+        [Required]
+        public DateTime CreateTime { get; set; } = DateTime.Now;
+    }
+
+}
diff --git a/PrivateBox/DataContext/UserKeys.cs b/PrivateBox/DataContext/UserKeys.cs
deleted file mode 100644
index d250449..0000000
--- a/PrivateBox/DataContext/UserKeys.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace PrivateBox.DataContext
-{
-    internal class UserKeys
-    {
-    }
-}
diff --git a/PrivateBox/InputDlgBox.Designer.cs b/PrivateBox/InputDlgBox.Designer.cs
new file mode 100644
index 0000000..917481b
--- /dev/null
+++ b/PrivateBox/InputDlgBox.Designer.cs
@@ -0,0 +1,84 @@
+namespace PrivateBox
+{
+    partial class InputDlgBox
+    {
+        /// 
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        /// 
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing) {
+            if(disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// 
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent() {
+            textBox1 = new TextBox();
+            btOk = new Button();
+            btCancel = new Button();
+            SuspendLayout();
+            // 
+            // textBox1
+            // 
+            textBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
+            textBox1.Location = new Point(12,12);
+            textBox1.Multiline = true;
+            textBox1.Name = "textBox1";
+            textBox1.Size = new Size(555,65);
+            textBox1.TabIndex = 0;
+            // 
+            // btOk
+            // 
+            btOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
+            btOk.Location = new Point(12,93);
+            btOk.Name = "btOk";
+            btOk.Size = new Size(75,23);
+            btOk.TabIndex = 1;
+            btOk.Text = "确定";
+            btOk.UseVisualStyleBackColor = true;
+            // 
+            // btCancel
+            // 
+            btCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+            btCancel.Location = new Point(487,93);
+            btCancel.Name = "btCancel";
+            btCancel.Size = new Size(75,23);
+            btCancel.TabIndex = 2;
+            btCancel.Text = "取消";
+            btCancel.UseVisualStyleBackColor = true;
+            // 
+            // InputDlgBox
+            // 
+            AcceptButton = btOk;
+            AutoScaleDimensions = new SizeF(7F,17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            CancelButton = btCancel;
+            ClientSize = new Size(574,128);
+            Controls.Add(btCancel);
+            Controls.Add(btOk);
+            Controls.Add(textBox1);
+            Name = "InputDlgBox";
+            Text = "输入值";
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private TextBox textBox1;
+        private Button btOk;
+        private Button btCancel;
+    }
+}
\ No newline at end of file
diff --git a/PrivateBox/InputDlgBox.cs b/PrivateBox/InputDlgBox.cs
new file mode 100644
index 0000000..0b7cc4e
--- /dev/null
+++ b/PrivateBox/InputDlgBox.cs
@@ -0,0 +1,36 @@
+namespace PrivateBox
+{
+    public partial class InputDlgBox:Form
+    {
+        public InputDlgBox() {
+            InitializeComponent();
+
+            this.Load += InputDlgBox_Load;
+        }
+
+        public InputDlgBox(string title,string msg) : this() {
+            this.Text = title;
+            this.textBox1.Text = msg;
+        }
+
+        private void InputDlgBox_Load(object? sender,EventArgs e) {
+            this.btOk.Click += BtOk_Click;
+        }
+
+        private void BtOk_Click(object? sender,EventArgs e) {
+            this.DialogResult = DialogResult.OK;
+            this.Hide();
+        }
+
+        private int msg;
+
+        /// 
+        /// 输入的信息
+        /// 
+        public string Msg {
+            get { return this.textBox1.Text; }
+            set { this.textBox1.Text = value; }
+        }
+
+    }
+}
diff --git a/PrivateBox/InputDlgBox.resx b/PrivateBox/InputDlgBox.resx
new file mode 100644
index 0000000..a395bff
--- /dev/null
+++ b/PrivateBox/InputDlgBox.resx
@@ -0,0 +1,120 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+
\ No newline at end of file
diff --git a/PrivateBox/MainForm.Designer.cs b/PrivateBox/MainForm.Designer.cs
index a88ee60..5004d8a 100644
--- a/PrivateBox/MainForm.Designer.cs
+++ b/PrivateBox/MainForm.Designer.cs
@@ -25,13 +25,16 @@
         /// the contents of this method with the code editor.
         /// 
         private void InitializeComponent() {
+            components = new System.ComponentModel.Container();
             System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
             toolStripContainer1 = new ToolStripContainer();
             splitContainer1 = new SplitContainer();
             lbKeyList = new ListBox();
+            menuKeyList = new ContextMenuStrip(components);
+            KeyListAddNew = new ToolStripMenuItem();
+            KeyListRemove = new ToolStripMenuItem();
             splitContainer2 = new SplitContainer();
             toolStrip1 = new ToolStrip();
-            btEdit = new ToolStripButton();
             btSave = new ToolStripButton();
             btCancel = new ToolStripButton();
             tbMessage = new RichTextBox();
@@ -41,6 +44,7 @@
             splitContainer1.Panel1.SuspendLayout();
             splitContainer1.Panel2.SuspendLayout();
             splitContainer1.SuspendLayout();
+            menuKeyList.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)splitContainer2).BeginInit();
             splitContainer2.Panel1.SuspendLayout();
             splitContainer2.Panel2.SuspendLayout();
@@ -81,6 +85,7 @@
             // 
             // lbKeyList
             // 
+            lbKeyList.ContextMenuStrip = menuKeyList;
             lbKeyList.Dock = DockStyle.Fill;
             lbKeyList.FormattingEnabled = true;
             lbKeyList.ItemHeight = 17;
@@ -89,6 +94,26 @@
             lbKeyList.Size = new Size(285,379);
             lbKeyList.TabIndex = 0;
             // 
+            // menuKeyList
+            // 
+            menuKeyList.Items.AddRange(new ToolStripItem[] { KeyListAddNew,KeyListRemove });
+            menuKeyList.Name = "menuKeyList";
+            menuKeyList.Size = new Size(101,48);
+            // 
+            // KeyListAddNew
+            // 
+            KeyListAddNew.Name = "KeyListAddNew";
+            KeyListAddNew.Size = new Size(100,22);
+            KeyListAddNew.Text = "新增";
+            KeyListAddNew.Click += KeyListAddNew_Click;
+            // 
+            // KeyListRemove
+            // 
+            KeyListRemove.Name = "KeyListRemove";
+            KeyListRemove.Size = new Size(100,22);
+            KeyListRemove.Text = "删除";
+            KeyListRemove.Click += KeyListRemove_Click;
+            // 
             // splitContainer2
             // 
             splitContainer2.Dock = DockStyle.Fill;
@@ -109,23 +134,13 @@
             // 
             // toolStrip1
             // 
-            toolStrip1.Items.AddRange(new ToolStripItem[] { btEdit,btSave,btCancel });
+            toolStrip1.Items.AddRange(new ToolStripItem[] { btSave,btCancel });
             toolStrip1.Location = new Point(0,0);
             toolStrip1.Name = "toolStrip1";
             toolStrip1.Size = new Size(467,27);
             toolStrip1.TabIndex = 0;
             toolStrip1.Text = "toolStrip1";
             // 
-            // btEdit
-            // 
-            btEdit.DisplayStyle = ToolStripItemDisplayStyle.Text;
-            btEdit.Image = (Image)resources.GetObject("btEdit.Image");
-            btEdit.ImageTransparentColor = Color.Magenta;
-            btEdit.Margin = new Padding(3);
-            btEdit.Name = "btEdit";
-            btEdit.Size = new Size(36,21);
-            btEdit.Text = "编辑";
-            // 
             // btSave
             // 
             btSave.DisplayStyle = ToolStripItemDisplayStyle.Text;
@@ -135,6 +150,7 @@
             btSave.Name = "btSave";
             btSave.Size = new Size(36,21);
             btSave.Text = "保存";
+            btSave.Click += btSave_Click;
             // 
             // btCancel
             // 
@@ -145,6 +161,7 @@
             btCancel.Name = "btCancel";
             btCancel.Size = new Size(36,21);
             btCancel.Text = "取消";
+            btCancel.Click += btCancel_Click;
             // 
             // tbMessage
             // 
@@ -170,6 +187,7 @@
             splitContainer1.Panel2.ResumeLayout(false);
             ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();
             splitContainer1.ResumeLayout(false);
+            menuKeyList.ResumeLayout(false);
             splitContainer2.Panel1.ResumeLayout(false);
             splitContainer2.Panel1.PerformLayout();
             splitContainer2.Panel2.ResumeLayout(false);
@@ -188,8 +206,10 @@
         private RichTextBox tbMessage;
         private SplitContainer splitContainer2;
         private ToolStrip toolStrip1;
-        private ToolStripButton btEdit;
         private ToolStripButton btSave;
         private ToolStripButton btCancel;
+        private ContextMenuStrip menuKeyList;
+        private ToolStripMenuItem KeyListAddNew;
+        private ToolStripMenuItem KeyListRemove;
     }
 }
\ No newline at end of file
diff --git a/PrivateBox/MainForm.cs b/PrivateBox/MainForm.cs
index 9dafedb..b86ea5e 100644
--- a/PrivateBox/MainForm.cs
+++ b/PrivateBox/MainForm.cs
@@ -1,22 +1,90 @@
 using Microsoft.Extensions.DependencyInjection;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
+using PrivateBox.DataContext;
 
 namespace PrivateBox
 {
     public partial class MainForm:Form
     {
         public IEncryptionService Encrytion { get; init; }
+        public DbContext Db { get; init; }
+        public string CrytionKey { get; init; }
+
         public MainForm(IServiceProvider provider) {
             InitializeComponent();
             this.Encrytion = provider.GetRequiredService();
+            this.Db = provider.GetRequiredService();
+            this.CrytionKey = this.Db.GetCrytionKey();
+
+            this.Load += (s,d) => {
+                RefreshKeyList();
+            };
+
+            this.lbKeyList.SelectedIndexChanged += LbKeyList_SelectedIndexChanged;
+        }
+
+        private void LbKeyList_SelectedIndexChanged(object? sender,EventArgs e) {
+            this.tbMessage.Text = "";
+            if(this.lbKeyList.SelectedItem == null) {
+                return;
+            }
+            var k = this.lbKeyList.SelectedItem.ToString();
+            var qu = this.Db.Queryable().Where(a => a.ItemName == k).ToList();
+            if(qu.Any()) {
+                var i = qu.First();
+                i.ItemValue = string.IsNullOrEmpty(i.ItemValue) ? "" : this.Encrytion.Decrypt(qu.First().ItemValue,this.CrytionKey);
+                this.tbMessage.Text = i.ItemValue;
+                this.tbMessage.Tag = i;
+            }
+        }
+
+        private void RefreshKeyList() {
+            this.lbKeyList.Items.Clear();
+            var qu = this.Db.Queryable().Select(a => a.ItemName).ToList();
+            foreach(var i in qu) {
+                this.lbKeyList.Items.Add(i);
+            }
+        }
+
+        private void KeyListAddNew_Click(object sender,EventArgs e) {
+            var dlg = new InputDlgBox("输入键值","");
+            if(dlg.ShowDialog() == DialogResult.OK) {
+                var key = dlg.Msg;
+                var qu = this.Db.Queryable().Where(a => a.ItemName == key).ToList();
+                if(qu.Any()) {
+                    return;
+                }
+                this.Db.Insertable(new CrytionItem {
+                    ItemName = key,ItemValue = "",
+                }).ExecuteCommand();
+                RefreshKeyList();
+            }
+        }
+
+        private void KeyListRemove_Click(object sender,EventArgs e) {
+            if(this.lbKeyList.SelectedItem == null) {
+                return;
+            }
+            var sItem = this.lbKeyList.SelectedItem.ToString();
+            this.Db.Deleteable().Where(a => a.ItemName == sItem).ExecuteCommand();
+            RefreshKeyList();
+        }
+
+        private void btSave_Click(object sender,EventArgs e) {
+            var tag = this.tbMessage.Tag as CrytionItem;
+            if(tag == null) {
+                return;
+            }
+            tag.ItemValue = this.tbMessage.Text;
+            var val = this.Encrytion.Encrypt(tag.ItemValue,this.CrytionKey);
+            this.Db.Updateable()
+                .Where(a => a.ItemName == tag.ItemName)
+                .SetColumns(a => a.ItemValue == val)
+                .ExecuteCommand();
+        }
+
+        private void btCancel_Click(object sender,EventArgs e) {
+            var tag = this.tbMessage.Tag as CrytionItem;
+            this.tbMessage.Text = tag.ItemValue;
         }
     }
 }
diff --git a/PrivateBox/MainForm.resx b/PrivateBox/MainForm.resx
index a03afcd..6a50d3a 100644
--- a/PrivateBox/MainForm.resx
+++ b/PrivateBox/MainForm.resx
@@ -117,19 +117,13 @@
   
     System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   
+  
+    127, 17
+  
   
     17, 17
   
   
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb
-        J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj
-        CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN
-        AAAAAElFTkSuQmCC
-
-  
   
     
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8