添加项目文件。

This commit is contained in:
sc committed 2026-05-01 14:44:49 +08:00
1 parent 6c0af56ea9
commit 54eaa8a836
64 files changed
+3176

No files matched your search

+255
View File
@@ -0,0 +1,255 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SunlightAggregationTerminal.Class
{
public class SQLiteConfig()
{
public static SqliteHelper SQLitedata = null!; //定义数据库
public static SqliteHelper? Config(string dat)
{
try
{
SQLitedata = new SqliteHelper(dat); //数据库连接路径(获取各平台的应用数据目录)
SQLitedata.Open(); //打开数据库
if (SQLitedata.TableExists("Users"))
{
CheckAndRepairTableSchema();
}
else
{
CreateFreshUserTable();
}
if (SQLitedata.TableExists("Notification"))
{
CheckAndRepairTableSchemaNotification();
}
else
{
CreateFreshUserTableNotification();
}
SQLitedata.Close();
return SQLitedata;
}
catch (Exception)
{
return null;
}
}
// --- 逻辑分支 表存在,检查字段完整性 ---
private static void CheckAndRepairTableSchema()
{
// 获取现有字段列表
// 使用 PRAGMA table_info 获取结构
string pragmaSql = "PRAGMA table_info('Users');";
// 复用现有的 ExecuteReader 方法
// ExecuteReader 返回 null 代表出错,否则返回 DataReader
using (var reader = SQLitedata.ExecuteReader(pragmaSql, null))
{
if (reader == null) return;
var existingColumns = new List<string>();
while (reader.Read())
{
// PRAGMA table_info 返回结果的第2列(Index=1)是列名
string colName = reader.GetString(1);
existingColumns.Add(colName);
}
reader.Close(); // 记得关闭 Reader
// 检查并添加缺失字段 (直接拼接 SQL)
// 检查 User
if (!existingColumns.Contains("User"))
{
string sql = "ALTER TABLE Users ADD COLUMN User TEXT NOT NULL;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 UserId
if (!existingColumns.Contains("UserId"))
{
string sql = "ALTER TABLE Users ADD COLUMN UserId TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 UserName
if (!existingColumns.Contains("UserName"))
{
string sql = "ALTER TABLE Users ADD COLUMN UserName TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 UserPassword
if (!existingColumns.Contains("UserPassword"))
{
string sql = "ALTER TABLE Users ADD COLUMN UserPassword TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 Enterprise
if (!existingColumns.Contains("Enterprise"))
{
string sql = "ALTER TABLE Users ADD COLUMN Enterprise TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 Department
if (!existingColumns.Contains("Department"))
{
string sql = "ALTER TABLE Users ADD COLUMN Department TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 ServerID
if (!existingColumns.Contains("ServerID"))
{
string sql = "ALTER TABLE Users ADD COLUMN ServerID TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 Group
if (!existingColumns.Contains("Groups"))
{
string sql = "ALTER TABLE Users ADD COLUMN Groups TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 ProxyID
if (!existingColumns.Contains("ProxyID"))
{
string sql = "ALTER TABLE Users ADD COLUMN ProxyID TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 LogNo
if (!existingColumns.Contains("LogNo"))
{
string sql = "ALTER TABLE Users ADD COLUMN LogNo BOOL DEFAULT (0);";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 LocalAreaNetworkMode
if (!existingColumns.Contains("LocalAreaNetworkMode"))
{
string sql = "ALTER TABLE Users ADD COLUMN LocalAreaNetworkMode BOOL DEFAULT (0);";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 LocalAreaNetworkMode
if (!existingColumns.Contains("DarkMode"))
{
string sql = "ALTER TABLE Users ADD COLUMN DarkMode BOOL DEFAULT (0);";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 LocalAreaNetworkMode
if (!existingColumns.Contains("MessageNotificationMode"))
{
string sql = "ALTER TABLE Users ADD COLUMN MessageNotificationMode BOOL DEFAULT (0);";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 GUID
if (!existingColumns.Contains("GUID"))
{
string sql = "ALTER TABLE Users ADD COLUMN GUID TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
string sqlupdata = "UPDATE Users SET GUID = '"+ Models.AppModels.GetAppUniqueId() + "';";
SQLitedata.ExecuteNonQuery(sqlupdata, null);
}
}
}
private static void CheckAndRepairTableSchemaNotification()
{
// 获取现有字段列表
// 使用 PRAGMA table_info 获取结构
string pragmaSql = "PRAGMA table_info('Notification');";
// 复用现有的 ExecuteReader 方法
// ExecuteReader 返回 null 代表出错,否则返回 DataReader
using (var reader = SQLitedata.ExecuteReader(pragmaSql, null))
{
if (reader == null) return;
var existingColumns = new List<string>();
while (reader.Read())
{
// PRAGMA table_info 返回结果的第2列(Index=1)是列名
string colName = reader.GetString(1);
existingColumns.Add(colName);
}
reader.Close(); // 记得关闭 Reader
// 检查并添加缺失字段 (直接拼接 SQL)
// 检查 Title
if (!existingColumns.Contains("Title"))
{
string sql = "ALTER TABLE Notification ADD COLUMN Title TEXT NULL;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 Content
if (!existingColumns.Contains("Content"))
{
string sql = "ALTER TABLE Notification ADD COLUMN Content TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 Time
if (!existingColumns.Contains("Time"))
{
string sql = "ALTER TABLE Notification ADD COLUMN Time TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 Type
if (!existingColumns.Contains("Type"))
{
string sql = "ALTER TABLE Notification ADD COLUMN Type INT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
}
}
// --- 逻辑分支 表不存在,直接创建 ---
private static void CreateFreshUserTable()
{
// 建表语句
string createSql = @"
CREATE TABLE Users (
User TEXT NOT NULL,
UserId TEXT,
UserName TEXT,
UserPassword TEXT,
Enterprise TEXT,
Department TEXT,
ServerID TEXT,
Groups TEXT,
ProxyID TEXT,
LogNo BOOL DEFAULT (0),
LocalAreaNetworkMode BOOL DEFAULT (0),
DarkMode BOOL DEFAULT (0),
MessageNotificationMode BOOL DEFAULT (0),
GUID TEXT
);";
// 复用现有的 ExecuteNonQuery 方法
SQLitedata.ExecuteNonQuery(createSql, null);
string Sql = @"
INSERT INTO Users (User,UserId ,UserName ,UserPassword ,Enterprise ,Department ,ServerID ,Groups ,ProxyID ,LogNo ,LocalAreaNetworkMode ,DarkMode ,MessageNotificationMode ,GUID
)VALUES('SUNLIGHT','SUNLIGHT','SUNLIGHT','SUNLIGHT','SUNLIGHT','ENGINEER','TEST','ENGINEER','',0,0,0,0,'"+ Models.AppModels.GetAppUniqueId() + "');";
// 复用现有的 ExecuteNonQuery 方法
SQLitedata.ExecuteNonQuery(Sql, null);
}
private static void CreateFreshUserTableNotification()
{
// 建表语句
string createSql = @"
CREATE TABLE Notification (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Title TEXT,
Content TEXT,
Time TEXT,
Type INT
);";
// 复用现有的 ExecuteNonQuery 方法
SQLitedata.ExecuteNonQuery(createSql, null);
}
}
}
+504
View File
@@ -0,0 +1,504 @@
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SunlightAggregationTerminal.Class
{
public class ClsLock : IDisposable
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public IDisposable Read()
{
_lock.EnterReadLock();
return new DisposableAction(() => _lock.ExitReadLock());
}
public void Dispose() => _lock?.Dispose();
private class DisposableAction : IDisposable
{
private readonly Action _action;
public DisposableAction(Action action) => _action = action;
public void Dispose() => _action?.Invoke();
}
}
public class SqliteHelper
{
#region 字段
private SqliteTransaction? dbTrans = null!;
private static readonly Dictionary<string, ClsLock> RWL = new Dictionary<string, ClsLock>();
private readonly string mDataFile;
private readonly string mPassWord = "";
private readonly string lockName = "";
private SqliteConnection mConn = null!;
#endregion
#region 构造函数
public SqliteHelper(string dataFile)
{
this.mDataFile = dataFile ?? throw new ArgumentNullException(nameof(dataFile));
this.mDataFile = dataFile; // 注意:原代码有两次赋值,保留逻辑
if (!RWL.ContainsKey(dataFile))
{
lockName = dataFile;
RWL.Add(dataFile, new ClsLock());
}
}
public SqliteHelper(string dataFile, string PassWord)
{
this.mDataFile = dataFile ?? throw new ArgumentNullException(nameof(dataFile));
this.mPassWord = PassWord ?? throw new ArgumentNullException(nameof(PassWord));
this.mDataFile = dataFile;
if (!RWL.ContainsKey(dataFile))
{
lockName = dataFile;
RWL.Add(dataFile, new ClsLock());
}
}
#endregion
#region 打开/关闭 数据库
// 注意:Microsoft.Data.Sqlite.Core 不支持连接字符串构建器,需手动拼接
// 加密支持通常需要 Microsoft.Data.Sqlite.Core + SQLitePCLRaw.bundle_green (且加密功能可能受限)
public void Open()
{
// 构建连接字符串
var connectionString = $"Data Source={mDataFile}";
if (!string.IsNullOrWhiteSpace(mPassWord))
{
connectionString += $";Password={mPassWord}"; // 注意:原生 Microsoft.Data.Sqlite 不支持加密
// 如果需要加密,通常需要使用 SQLitePCLRaw 的特定提供程序或第三方库
}
mConn = new SqliteConnection(connectionString);
// 如果文件不存在,Open() 会自动创建数据库文件
// 但表结构需要你自己执行 CREATE TABLE
mConn.Open();
Console.WriteLine("The database was opened successfully");
}
public void Close()
{
if (this.mConn != null)
{
try
{
this.mConn.Close();
// 注意:不要在这里移除 RWL,因为这是静态的,可能影响其他实例
// if (RWL.ContainsKey(LockName)) { RWL.Remove(LockName); }
}
catch
{
Console.WriteLine("Shutdown failed");
}
}
Console.WriteLine("The database was shut down successfully");
}
#endregion
#region 事务
public void BeginTrain()
{
EnsureConnection();
dbTrans = mConn.BeginTransaction();
}
public void DBCommit()
{
try
{
dbTrans?.Commit();
dbTrans?.Dispose();
dbTrans = null; // 提交后置空
}
catch (Exception)
{
dbTrans?.Rollback();
dbTrans?.Dispose();
dbTrans = null;
}
}
#endregion
#region 工具
// OpenConnection 逻辑已合并到 Open() 方法中,因为 SqliteConnection 构造函数只接受字符串
public SqliteConnection Connection
{
get { return mConn; }
private set { mConn = value ?? throw new ArgumentNullException(); }
}
protected void EnsureConnection()
{
if (this.mConn == null)
{
throw new Exception("SQLiteManager.Connection=null");
}
if (mConn.State != ConnectionState.Open)
{
mConn.Open();
}
}
public string GetDataFile() => this.mDataFile;
public bool TableExists(string table)
{
if (string.IsNullOrEmpty(table)) return false;
EnsureConnection();
// 注意:参数化查询在表名/列名上无效,这里使用字符串拼接(需确保table变量安全)
// 或者使用 PRAGMA table_info(table_name)
var sql = $"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='{table}'";
using (var cmd = new SqliteCommand(sql, Connection))
{
var result = cmd.ExecuteScalar();
return Convert.ToInt32(result) > 0;
}
}
public bool Vacuum()
{
try
{
using (var Command = new SqliteCommand("VACUUM", Connection))
{
Command.ExecuteNonQuery();
}
return true;
}
catch (Exception) // SqliteException
{
return false;
}
}
/// <summary>
/// 将 IDataReader 转换为 DataSet
/// </summary>
/// <param name="reader">已经执行了查询的 DataReader</param>
/// <returns>包含数据的 DataSet</returns>
public DataSet ReaderToDataSet(IDataReader reader)
{
DataSet ds = new DataSet();
do
{
DataTable schemaTable = reader.GetSchemaTable()!;
DataTable dataTable = new DataTable();
if (schemaTable != null)
{
// 创建列
foreach (DataRow schemaRow in schemaTable.Rows)
{
string colName = schemaRow["ColumnName"].ToString()!;
Type dataType = (Type)schemaRow["DataType"];
// 防止列名重复
string uniqueColName = colName;
int i = 1;
while (dataTable.Columns.Contains(uniqueColName))
{
uniqueColName = colName + i++;
}
DataColumn column = new DataColumn(uniqueColName, dataType);
dataTable.Columns.Add(column);
}
// 读取行
while (reader.Read())
{
object[] values = new object[dataTable.Columns.Count];
for (int i = 0; i < dataTable.Columns.Count; i++)
{
values[i] = reader.IsDBNull(i) ? DBNull.Value : reader.GetValue(i);
}
dataTable.Rows.Add(values);
}
}
else
{
// 如果没有 Schema (例如 "SELECT 1" 这种标量查询)
// 需要手动创建列
for (int i = 0; i < reader.FieldCount; i++)
{
dataTable.Columns.Add("Column" + i);
}
while (reader.Read())
{
object[] values = new object[reader.FieldCount];
reader.GetValues(values);
dataTable.Rows.Add(values);
}
}
ds.Tables.Add(dataTable);
} while (reader.NextResult()); // 处理多个结果集
return ds;
}
#endregion
#region 执行SQL (Reader & Scalar)
public SqliteDataReader? ExecuteReader(string sql, SqliteParameter[]? paramArr)
{
if (string.IsNullOrEmpty(sql)) throw new ArgumentNullException(nameof(sql));
EnsureConnection();
// 注意:using 语句会立即释放 Reader,导致无法读取
// 这里的 RWL 锁在 using 外部处理,或者调用方自己处理锁
// 这里简化逻辑,直接返回 Reader,调用方需自行管理连接状态
var cmd = new SqliteCommand(sql, Connection);
if (paramArr != null)
{
cmd.Parameters.AddRange(paramArr);
}
// CommandBehavior.CloseConnection 确保 Reader 关闭时连接也关闭
// 但这里我们管理连接,所以不加
try
{
// 注意:不要在这里 Dispose Command,否则 Reader 会失效
// 返回 Reader,由调用方在读取完毕后关闭
return cmd.ExecuteReader();
}
catch(Exception ex)
{
Console.WriteLine("[SQLITE_ExecuteReader:err]" + ex.ToString());
cmd?.Dispose();
return null;
}
}
public DataSet? ExecuteDataSet(string sql, SqliteParameter[]? paramArr)
{
var dat = ExecuteReader(sql, paramArr);
if (dat == null)
{
return null;
}
return ReaderToDataSet(dat);
}
// ExecuteScalar
public object? ExecuteScalar(string sql, SqliteParameter[]? paramArr)
{
if (string.IsNullOrEmpty(sql)) throw new ArgumentNullException(nameof(sql));
EnsureConnection();
using (RWL[lockName].Read())
{
using (var cmd = new SqliteCommand(sql, Connection))
{
if (paramArr != null)
{
cmd.Parameters.AddRange(paramArr);
}
try
{
return cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine("[SQLITE_ExecuteScalar:err]" + ex.ToString());
return null;
}
}
}
}
// QueryOne (返回字典或对象)
public Dictionary<string, object?>? QueryOne(string table, string conditionCol, object conditionVal)
{
if (string.IsNullOrEmpty(table)) return null;
EnsureConnection();
string sql = $"SELECT * FROM [{table}]"; // 使用 [] 防止关键字冲突
var parameters = new List<SqliteParameter>();
if (!string.IsNullOrEmpty(conditionCol))
{
sql += $" WHERE [{conditionCol}] = @{conditionCol}";
parameters.Add(new SqliteParameter($"@{conditionCol}", conditionVal));
}
using (var cmd = new SqliteCommand(sql, Connection))
{
cmd.Parameters.AddRange(parameters.ToArray());
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
var dict = new Dictionary<string, object?>();
for (int i = 0; i < reader.FieldCount; i++)
{
var value = reader.GetValue(i);
if (value == DBNull.Value) value = null;
dict[reader.GetName(i)] = value;
}
return dict;
}
}
}
return null;
}
#endregion
#region 增 删 改
// 注意:参数前缀统一为 @
public int InsertData(string table, Dictionary<string, object> entity)
{
if (string.IsNullOrEmpty(table)) throw new ArgumentNullException(nameof(table));
EnsureConnection();
string sql = BuildInsert(table, entity);
var parameters = BuildParamArray(entity);
return ExecuteNonQuery(sql, parameters);
}
public int Update(string table, Dictionary<string, object> entity, string where, SqliteParameter[]? whereParams)
{
if (string.IsNullOrEmpty(table)) throw new ArgumentNullException(nameof(table));
EnsureConnection();
string sql = BuildUpdate(table, entity);
var parameters = BuildParamArray(entity);
if (!string.IsNullOrEmpty(where))
{
sql += " WHERE " + where;
if (whereParams != null)
{
var combined = new SqliteParameter[parameters.Length + whereParams.Length];
parameters.CopyTo(combined, 0);
whereParams.CopyTo(combined, parameters.Length);
parameters = combined;
}
}
return ExecuteNonQuery(sql, parameters);
}
public int Delete(string table, string where, SqliteParameter[]? whereParams)
{
if (string.IsNullOrEmpty(table)) return 0;
EnsureConnection();
string sql = $"DELETE FROM [{table}]";
if (!string.IsNullOrEmpty(where))
{
sql += " WHERE " + where;
}
return ExecuteNonQuery(sql, whereParams);
}
public int ExecuteNonQuery(string sql, SqliteParameter[]? paramArr)
{
if (string.IsNullOrEmpty(sql)) throw new ArgumentNullException(nameof(sql));
EnsureConnection();
using (RWL[lockName].Read()) // 注意:写操作通常建议用 Write 锁
{
using (var cmd = new SqliteCommand(sql, Connection))
{
if (paramArr != null)
{
cmd.Parameters.AddRange(paramArr);
}
try
{
return cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine("[SQLITE_ExecuteScalar:err]" + ex.ToString());
return 0;
}
}
}
}
// 构建 SQL 和 参数的方法保持不变,仅泛型类型变更
private SqliteParameter[] BuildParamArray(Dictionary<string, object> entity)
{
var list = new List<SqliteParameter>();
foreach (string key in entity.Keys)
{
// 注意:参数名必须包含 @ 前缀
list.Add(new SqliteParameter($"@{key}", entity[key]));
}
return list.ToArray();
}
private string BuildInsert(string table, Dictionary<string, object> entity)
{
var buf = new StringBuilder();
buf.Append("INSERT INTO ").Append(table).Append(" (");
var cols = new List<string>();
var vals = new List<string>();
foreach (string key in entity.Keys)
{
cols.Add(key);
vals.Add($"@{key}");
}
buf.Append(string.Join(",", cols)).Append(") VALUES (");
buf.Append(string.Join(",", vals)).Append(")");
return buf.ToString();
}
private string BuildUpdate(string table, Dictionary<string, object> entity)
{
var buf = new StringBuilder();
buf.Append("UPDATE ").Append(table).Append(" SET ");
var sets = new List<string>();
foreach (string key in entity.Keys)
{
sets.Add($"{key} = @{key}");
}
buf.Append(string.Join(",", sets));
return buf.ToString();
}
// 辅助方法:DataRow 转 Dictionary (由于没有 DataTable,通常直接从 Reader 转)
// 这里保留原方法签名,但实际使用中可能需要调整
public Dictionary<string, object?> DataTableToDictionary(DataTable dataTable)
{
var result = new Dictionary<string, object?>();
if (dataTable.Rows.Count > 0)
{
var row = dataTable.Rows[0];
foreach (DataColumn column in dataTable.Columns)
{
var value = row[column];
if (value == DBNull.Value) value = null;
result[column.ColumnName] = value;
}
}
return result;
}
#endregion
}
}
+54
View File
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Text;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace SunlightAggregationTerminal.Class
{
public class TcpServer
{
public static string ServerIP = "";
public static string ServerName = "";
public static string ServerPassword = "";
public static string ServerTerminal = "";
public static TcpClient tcpClient = new TcpClient();
public static void Configuration(string ip, string Name, string Password, string Terminal)
{
ServerIP = ip;
ServerName = Name;
ServerPassword = Password;
ServerTerminal = Terminal;
}
public static async void Query(string Dat)
{
//发送字符串数据
await tcpClient.SendAsync("hello");
}
private static async Task CreateCustomService()
{
tcpClient.Config.SetRemoteIPHost(ServerIP);
tcpClient.Connecting = (client, e) => { return EasyTask.CompletedTask; };//即将连接到服务器,此时已经创建socket,但是还未建立tcp
tcpClient.Connected = (client, e) => { return EasyTask.CompletedTask; };//成功连接到服务器
tcpClient.Closing = (client, e) => { return EasyTask.CompletedTask; };//即将从服务器断开连接。此处仅主动断开才有效。
tcpClient.Closed = (client, e) => { return EasyTask.CompletedTask; };//从服务器断开连接,当连接不成功时不会触发。
#region Tcp客户端使用Received异步委托接收数据
tcpClient.Received = (client, e) =>
{
//从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
var mes = e.Memory.Span.ToString(Encoding.UTF8);
tcpClient.Logger.Info($"客户端接收到信息:{mes}");
return EasyTask.CompletedTask;
};
#endregion
await tcpClient.ConnectAsync();//调用连接,当连接不成功时,会抛出异常。
}
}
}