Browse Source

Person添加成员(ip)

项目目录修改
master
忱 沈 1 week ago
parent
commit
c2d15699ab
  1. 9
      App.xaml
  2. 17
      App.xaml.cs
  3. 10
      AssemblyInfo.cs
  4. 48
      ConvertMoels/StatenConvert.cs
  5. 48
      ConvertMoels/StatenERRConvert.cs
  6. 72
      MainWindow.xaml
  7. 115
      MainWindow.xaml.cs
  8. 387
      ResourceLanguage.Designer.cs
  9. 228
      ResourceLanguage.resx
  10. 39
      SunlightAggregationManager.csproj
  11. 3
      SunlightAggregationManager.slnx
  12. 209
      UserClass/AsyncTcpServer.cs
  13. 79
      UserClass/DataBase.cs
  14. 83
      UserClass/IniFile.cs
  15. 75
      UserClass/NetFwManger.cs
  16. 510
      UserClass/SqliteHelper.cs
  17. 62
      UserClass/TextWriter.cs
  18. 12
      UserWindow/UserSet.xaml
  19. 25
      UserWindow/UserSet.xaml.cs
  20. 38
      View/SettingPage.xaml
  21. 157
      View/SettingPage.xaml.cs
  22. 13
      View/StatePage.xaml
  23. 33
      View/StatePage.xaml.cs
  24. 114
      View/UserPage.xaml
  25. 90
      View/UserPage.xaml.cs
  26. 17
      View/imgQR.xaml
  27. 105
      View/imgQR.xaml.cs
  28. 31
      View/logPage.xaml
  29. 143
      View/logPage.xaml.cs
  30. 231
      ViewModel/MainWindowViewModel.cs

9
App.xaml

@ -0,0 +1,9 @@
<Application x:Class="SunlightAggregationManager.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SunlightAggregationManager"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

17
App.xaml.cs

@ -0,0 +1,17 @@
using SunlightAggregationManager.UserClass;
using System.Configuration;
using System.Data;
using System.Windows;
using System.Windows.Controls;
namespace SunlightAggregationManager
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

10
AssemblyInfo.cs

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

48
ConvertMoels/StatenConvert.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Controls;
/// <summary>
/// 运行状态变换器
/// 输入:状态码
/// 输出:状态文字
/// </summary>
namespace SunlightAggregationManager.ConvertMoels
{
internal class StatenConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
{
return "";
}
else
{
string Staten = "";
var i = value.ToString();
if (i == "10") Staten = ResourceLanguage.ERR;//异常
if (i == "15") Staten = ResourceLanguage.Offine;//离线
if (i == "20") Staten = ResourceLanguage.Online;//在线
if (i == "99") Staten = ResourceLanguage.Disable;//禁用
return Staten;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

48
ConvertMoels/StatenERRConvert.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Controls;
namespace SunlightAggregationManager.ConvertMoels
{
internal class StatenERRConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
{
return "black";
}
else
{
if (value.ToString() == "99")
{
return "red";//零返回红色
}
else if (value.ToString() == "10")
{
return "yellow";//零返回黄色
}
else if (value.ToString() == "20")
{
return "green";//零返回绿
}
else
{
return "black";//非零返回黑色
}
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

72
MainWindow.xaml

@ -0,0 +1,72 @@
<Window x:Class="SunlightAggregationManager.MainWindow"
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:SunlightAggregationManager"
mc:Ignorable="d"
Loaded="Window_Loaded"
Title="SUNLIGHT" Height="720" Width="1280" WindowStyle="None" ResizeMode="NoResize">
<Grid>
<Grid x:Name="GridTitle" Height="50" VerticalAlignment="Top" Background="#FF006361" Margin="0,0,0,0" MouseDown="GridTitle_MouseDown">
<TextBlock Text="Sunlight Aggregation Manager (SERVER)" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22" Foreground="White"/>
<Button HorizontalAlignment="Right" Margin="0,0,5,0" VerticalAlignment="Center" Width="50" Click="exit_Click"
Background="#FF006361" BorderBrush="#FF006361" >
<!-- 按钮内容:矢量图标 -->
<Viewbox Width="50" Height="40">
<Path x:Name="IconPath_exit" Data="M4,2 H14v20H4V2zm2,2v16h6V4H6zm12 8-4-4v3H8v2h6v3l4-4z" Fill="White" />
</Viewbox>
</Button>
<Button HorizontalAlignment="Right" Margin="0,0,65,0" VerticalAlignment="Center" Width="50" Click="maximize_Click"
Background="#FF006361" BorderBrush="#FF006361">
<!-- 最大化图标:一个空心的矩形 -->
<Viewbox Width="50" Height="40">
<Path x:Name="IconPath_maximize" Data="M4,2 H15 V15 H4 Z" Fill="White" />
</Viewbox>
</Button>
<Button HorizontalAlignment="Right" Margin="0,0,125,0" VerticalAlignment="Center" Width="50" Click="minimize_Click"
Background="#FF006361" BorderBrush="#FF006361">
<!-- 最小化图标:一条横线 -->
<Viewbox Width="50" Height="40">
<Path x:Name="IconPath_minimize" Data="M2,2 H18 " Stroke="White" StrokeThickness="2" />
</Viewbox>
</Button>
</Grid>
<Grid x:Name="GridMenu" Width="200" HorizontalAlignment="Left" Background="#FF00204E" Margin="0,50,0,0" >
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" Foreground="#FF1368BD" Background="{x:Null}" >
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_state">
<TextBlock Text="{x:Static local:ResourceLanguage.state}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_serve">
<TextBlock Text="{x:Static local:ResourceLanguage.serve}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_log">
<TextBlock Text="{x:Static local:ResourceLanguage.log}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_machine">
<TextBlock Text="{x:Static local:ResourceLanguage.machine}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_extend">
<TextBlock Text="{x:Static local:ResourceLanguage.extend}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_user">
<TextBlock Text="{x:Static local:ResourceLanguage.user}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_Action">
<TextBlock Text="{x:Static local:ResourceLanguage.Action}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_set">
<TextBlock Text="{x:Static local:ResourceLanguage.set}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
<ListViewItem Height="60" MouseLeftButtonUp="ListViewItem_MouseLeftButtonUp_help">
<TextBlock Text="{x:Static local:ResourceLanguage.help}" VerticalAlignment="Center" Margin="20 10" Foreground="White" HorizontalAlignment="Center" FontSize="24"/>
</ListViewItem>
</ListView>
</Grid>
<Grid x:Name="state" Margin="200,50,0,0">
<TextBox x:Name="LOG" TextWrapping="Wrap" Margin="5,200,5,5" FontSize="16"/>
</Grid>
<ContentControl x:Name="Picture" Margin="200,50,0,0" Visibility="Hidden"/>
</Grid>
</Window>

115
MainWindow.xaml.cs

@ -0,0 +1,115 @@
using SunlightAggregationManager.UserClass;
using SunlightAggregationManager.ViewModel;
using System.Text;
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;
namespace SunlightAggregationManager
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
GlobalLogManager.RegisterTarget(LOG);
DataContext = new MainWindowViewModel();
}
//标题栏拖动
private void GridTitle_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
DragMove();
}
//最大
private void maximize_Click(object sender, RoutedEventArgs e)
{
if (WindowState == WindowState.Maximized)
{ WindowState = WindowState.Normal; }
else
{ WindowState = WindowState.Maximized; }
}
//最小
private void minimize_Click(object sender, RoutedEventArgs e)
{
if (WindowState == WindowState.Minimized)
{ WindowState = WindowState.Normal; }
else
{ WindowState = WindowState.Minimized; }
}
//关闭
private void exit_Click(object sender, RoutedEventArgs e)
{
// 关闭整个应用程序
System.Windows.Application.Current.Shutdown();
}
private void ListViewItem_MouseLeftButtonUp_state(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Visible;
Picture.Visibility= Visibility.Collapsed;
}
private void ListViewItem_MouseLeftButtonUp_serve(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
}
private void ListViewItem_MouseLeftButtonUp_log(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.logPage();
}
private void ListViewItem_MouseLeftButtonUp_machine(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
}
private void ListViewItem_MouseLeftButtonUp_extend(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
}
private void ListViewItem_MouseLeftButtonUp_user(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.UserPage();
}
private void ListViewItem_MouseLeftButtonUp_Action(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
}
private void ListViewItem_MouseLeftButtonUp_set(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.SettingPage();
}
private void ListViewItem_MouseLeftButtonUp_help(object sender, MouseButtonEventArgs e)
{
state.Visibility = Visibility.Collapsed;
Picture.Visibility = Visibility.Visible;
Picture.Content = new View.imgQR();
}
}
}

387
ResourceLanguage.Designer.cs

@ -0,0 +1,387 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace SunlightAggregationManager {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class ResourceLanguage {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal ResourceLanguage() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SunlightAggregationManager.ResourceLanguage", typeof(ResourceLanguage).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似 行为 的本地化字符串。
/// </summary>
public static string Action {
get {
return ResourceManager.GetString("Action", resourceCulture);
}
}
/// <summary>
/// 查找类似 删除 的本地化字符串。
/// </summary>
public static string Delete {
get {
return ResourceManager.GetString("Delete", resourceCulture);
}
}
/// <summary>
/// 查找类似 部门 的本地化字符串。
/// </summary>
public static string Department {
get {
return ResourceManager.GetString("Department", resourceCulture);
}
}
/// <summary>
/// 查找类似 禁用 的本地化字符串。
/// </summary>
public static string Disable {
get {
return ResourceManager.GetString("Disable", resourceCulture);
}
}
/// <summary>
/// 查找类似 启用 的本地化字符串。
/// </summary>
public static string Enable {
get {
return ResourceManager.GetString("Enable", resourceCulture);
}
}
/// <summary>
/// 查找类似 启用HTTP 的本地化字符串。
/// </summary>
public static string EnableHTTP {
get {
return ResourceManager.GetString("EnableHTTP", resourceCulture);
}
}
/// <summary>
/// 查找类似 启用TCP 的本地化字符串。
/// </summary>
public static string EnableTCP {
get {
return ResourceManager.GetString("EnableTCP", resourceCulture);
}
}
/// <summary>
/// 查找类似 启用TLS1.2 的本地化字符串。
/// </summary>
public static string EnableTLS {
get {
return ResourceManager.GetString("EnableTLS", resourceCulture);
}
}
/// <summary>
/// 查找类似 错误 的本地化字符串。
/// </summary>
public static string ERR {
get {
return ResourceManager.GetString("ERR", resourceCulture);
}
}
/// <summary>
/// 查找类似 扩展 的本地化字符串。
/// </summary>
public static string extend {
get {
return ResourceManager.GetString("extend", resourceCulture);
}
}
/// <summary>
/// 查找类似 组 的本地化字符串。
/// </summary>
public static string Groups {
get {
return ResourceManager.GetString("Groups", resourceCulture);
}
}
/// <summary>
/// 查找类似 帮助 的本地化字符串。
/// </summary>
public static string help {
get {
return ResourceManager.GetString("help", resourceCulture);
}
}
/// <summary>
/// 查找类似 历史 的本地化字符串。
/// </summary>
public static string history {
get {
return ResourceManager.GetString("history", resourceCulture);
}
}
/// <summary>
/// 查找类似 信息 的本地化字符串。
/// </summary>
public static string information {
get {
return ResourceManager.GetString("information", resourceCulture);
}
}
/// <summary>
/// 查找类似 语言 的本地化字符串。
/// </summary>
public static string Language {
get {
return ResourceManager.GetString("Language", resourceCulture);
}
}
/// <summary>
/// 查找类似 最后行为时间 的本地化字符串。
/// </summary>
public static string LastActionTime {
get {
return ResourceManager.GetString("LastActionTime", resourceCulture);
}
}
/// <summary>
/// 查找类似 最后登录地址 的本地化字符串。
/// </summary>
public static string LastLoginIP {
get {
return ResourceManager.GetString("LastLoginIP", resourceCulture);
}
}
/// <summary>
/// 查找类似 最后登录终端 的本地化字符串。
/// </summary>
public static string LastLoginTerminal {
get {
return ResourceManager.GetString("LastLoginTerminal", resourceCulture);
}
}
/// <summary>
/// 查找类似 最后登录时间 的本地化字符串。
/// </summary>
public static string LastLoginTime {
get {
return ResourceManager.GetString("LastLoginTime", resourceCulture);
}
}
/// <summary>
/// 查找类似 最后下线时间 的本地化字符串。
/// </summary>
public static string LastOfflineTime {
get {
return ResourceManager.GetString("LastOfflineTime", resourceCulture);
}
}
/// <summary>
/// 查找类似 日志 的本地化字符串。
/// </summary>
public static string log {
get {
return ResourceManager.GetString("log", resourceCulture);
}
}
/// <summary>
/// 查找类似 设备 的本地化字符串。
/// </summary>
public static string machine {
get {
return ResourceManager.GetString("machine", resourceCulture);
}
}
/// <summary>
/// 查找类似 模式 的本地化字符串。
/// </summary>
public static string Mode {
get {
return ResourceManager.GetString("Mode", resourceCulture);
}
}
/// <summary>
/// 查找类似 姓名 的本地化字符串。
/// </summary>
public static string Name {
get {
return ResourceManager.GetString("Name", resourceCulture);
}
}
/// <summary>
/// 查找类似 离线 的本地化字符串。
/// </summary>
public static string Offine {
get {
return ResourceManager.GetString("Offine", resourceCulture);
}
}
/// <summary>
/// 查找类似 在线 的本地化字符串。
/// </summary>
public static string Online {
get {
return ResourceManager.GetString("Online", resourceCulture);
}
}
/// <summary>
/// 查找类似 密码 的本地化字符串。
/// </summary>
public static string Password {
get {
return ResourceManager.GetString("Password", resourceCulture);
}
}
/// <summary>
/// 查找类似 查询 的本地化字符串。
/// </summary>
public static string query {
get {
return ResourceManager.GetString("query", resourceCulture);
}
}
/// <summary>
/// 查找类似 保存 的本地化字符串。
/// </summary>
public static string save {
get {
return ResourceManager.GetString("save", resourceCulture);
}
}
/// <summary>
/// 查找类似 服务 的本地化字符串。
/// </summary>
public static string serve {
get {
return ResourceManager.GetString("serve", resourceCulture);
}
}
/// <summary>
/// 查找类似 服务器 的本地化字符串。
/// </summary>
public static string SERVER {
get {
return ResourceManager.GetString("SERVER", resourceCulture);
}
}
/// <summary>
/// 查找类似 设置 的本地化字符串。
/// </summary>
public static string set {
get {
return ResourceManager.GetString("set", resourceCulture);
}
}
/// <summary>
/// 查找类似 数据库 的本地化字符串。
/// </summary>
public static string SQL {
get {
return ResourceManager.GetString("SQL", resourceCulture);
}
}
/// <summary>
/// 查找类似 状态 的本地化字符串。
/// </summary>
public static string state {
get {
return ResourceManager.GetString("state", resourceCulture);
}
}
/// <summary>
/// 查找类似 测试 的本地化字符串。
/// </summary>
public static string Test {
get {
return ResourceManager.GetString("Test", resourceCulture);
}
}
/// <summary>
/// 查找类似 用户 的本地化字符串。
/// </summary>
public static string user {
get {
return ResourceManager.GetString("user", resourceCulture);
}
}
}
}

228
ResourceLanguage.resx

@ -0,0 +1,228 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Action" xml:space="preserve">
<value>行为</value>
</data>
<data name="Delete" xml:space="preserve">
<value>删除</value>
</data>
<data name="Department" xml:space="preserve">
<value>部门</value>
</data>
<data name="Disable" xml:space="preserve">
<value>禁用</value>
</data>
<data name="Enable" xml:space="preserve">
<value>启用</value>
</data>
<data name="EnableHTTP" xml:space="preserve">
<value>启用HTTP</value>
</data>
<data name="EnableTCP" xml:space="preserve">
<value>启用TCP</value>
</data>
<data name="EnableTLS" xml:space="preserve">
<value>启用TLS1.2</value>
</data>
<data name="ERR" xml:space="preserve">
<value>错误</value>
</data>
<data name="extend" xml:space="preserve">
<value>扩展</value>
</data>
<data name="Groups" xml:space="preserve">
<value>组</value>
</data>
<data name="help" xml:space="preserve">
<value>帮助</value>
</data>
<data name="history" xml:space="preserve">
<value>历史</value>
</data>
<data name="information" xml:space="preserve">
<value>信息</value>
</data>
<data name="Language" xml:space="preserve">
<value>语言</value>
</data>
<data name="LastActionTime" xml:space="preserve">
<value>最后行为时间</value>
</data>
<data name="LastLoginIP" xml:space="preserve">
<value>最后登录地址</value>
</data>
<data name="LastLoginTerminal" xml:space="preserve">
<value>最后登录终端</value>
</data>
<data name="LastLoginTime" xml:space="preserve">
<value>最后登录时间</value>
</data>
<data name="LastOfflineTime" xml:space="preserve">
<value>最后下线时间</value>
</data>
<data name="log" xml:space="preserve">
<value>日志</value>
</data>
<data name="machine" xml:space="preserve">
<value>设备</value>
</data>
<data name="Mode" xml:space="preserve">
<value>模式</value>
</data>
<data name="Name" xml:space="preserve">
<value>姓名</value>
</data>
<data name="Offine" xml:space="preserve">
<value>离线</value>
</data>
<data name="Online" xml:space="preserve">
<value>在线</value>
</data>
<data name="Password" xml:space="preserve">
<value>密码</value>
</data>
<data name="query" xml:space="preserve">
<value>查询</value>
</data>
<data name="save" xml:space="preserve">
<value>保存</value>
</data>
<data name="serve" xml:space="preserve">
<value>服务</value>
</data>
<data name="SERVER" xml:space="preserve">
<value>服务器</value>
</data>
<data name="set" xml:space="preserve">
<value>设置</value>
</data>
<data name="SQL" xml:space="preserve">
<value>数据库</value>
</data>
<data name="state" xml:space="preserve">
<value>状态</value>
</data>
<data name="Test" xml:space="preserve">
<value>测试</value>
</data>
<data name="user" xml:space="preserve">
<value>用户</value>
</data>
</root>

39
SunlightAggregationManager.csproj

@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="7.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.5" />
<PackageReference Include="Net.Codecrete.QrCodeGenerator" Version="2.1.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.9.1" />
<PackageReference Include="TouchSocket" Version="4.2.3" />
<PackageReference Include="vocaluxe.dependencies.netfwtypelib" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="ResourceLanguage.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ResourceLanguage.resx</DependentUpon>
</Compile>
<Compile Update="View\imgQR.xaml.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="ResourceLanguage.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>ResourceLanguage.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

3
SunlightAggregationManager.slnx

@ -0,0 +1,3 @@
<Solution>
<Project Path="SunlightAggregationManager.csproj" />
</Solution>

209
UserClass/AsyncTcpServer.cs

@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text;
using TouchSocket.Core;
using TouchSocket.Sockets;
using SunlightAggregationManager.ViewModel;
using System.Security.Cryptography.Pkcs;
namespace SunlightAggregationManager.UserClass
{
public class AsyncTcpServer
{
public class Person
{
public required string User { get; set; }
public required string Password { get; set; }
public required string IP { get; set; }
public required string Terminal { get; set; }
public required string Dat { get; set; }
}
public static TcpService service = new TcpService();
public static async Task TcpMain(int port1 ,int port2)
{
NetFwManger.AllowPort(port1, "TCP");//开放7790端口
NetFwManger.AllowPort(port2, "TCP");//开放7790端口
//TcpService service = new TcpService();
service.Connecting = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在连接
service.Connected = (client, e) => {return EasyTask.CompletedTask;};//有客户端成功连接
service.Closing = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在断开连接,只有当主动断开时才有效。
service.Closed = (client, e) => {
//离线记录
Dictionary<string, object> myDictOff = new Dictionary<string, object>();
myDictOff.Add("State", 15);
myDictOff.Add("LastActionTime", DateTime.Now);
myDictOff.Add("LastOfflineTime", DateTime.Now);
myDictOff.Add("Note", "Offline");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "LinkID='" + client.Id + "'", myDictOff);
Console.WriteLine("[Offline]IP[" + client.IP + "]ID["+ client.Id + "]");
return EasyTask.CompletedTask;
};//有客户端断开连接
service.Received = (client, e) =>{
string DAT = e.Memory.Span.ToString(Encoding.UTF8);
try
{
Person? deserializedPerson = JsonSerializer.Deserialize<Person>(DAT);
var _user = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "State", "User='" + deserializedPerson?.User +
"' and Password ='" + deserializedPerson?.Password + "'");
if (_user != null)
{
string _dat = _user?.ToString() ?? "0";
if (_dat != "99")
{
if (_dat == "20")
{//行为
Dictionary<string, object> myDict = new Dictionary<string, object>();
myDict.Add("LinkID", client.Id);
myDict.Add("LastLoginIP", deserializedPerson?.IP ?? client.IP);
myDict.Add("LastActionTime", DateTime.Now);
myDict.Add("Note", deserializedPerson?.Dat ?? "unknown");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + deserializedPerson?.User + "'", myDict);
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]Note[" + (deserializedPerson?.Dat ?? "unknown") + "]");
}
else
{//首次登录记录
Dictionary<string, object> myDict = new Dictionary<string, object>();
myDict.Add("State", 20);
myDict.Add("LinkID", client.Id);
myDict.Add("LastLoginIP", deserializedPerson?.IP ?? client.IP);
myDict.Add("LastLoginTime", DateTime.Now);
myDict.Add("LastLoginTerminal", deserializedPerson?.Terminal ?? "unknown device");
myDict.Add("LastActionTime", DateTime.Now);
myDict.Add("Note", deserializedPerson?.Dat ?? "unknown");
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + deserializedPerson?.User + "'", myDict);
Console.WriteLine("[Log on]User[" + deserializedPerson?.User + "]IP[" + deserializedPerson?.IP ?? client.IP +
"]ID[" + client.Id + "]Terminal[" + (deserializedPerson?.Terminal ?? "unknown device") + "]");
}
}
else
{//停用账号关闭连接
client.SendAsync("Account Deactivated");
foreach (var item in AsyncTcpServer.service.Clients)
{
if (item.Id == client.Id)
{
item.CloseAsync();
//在断开连接后,释放对象。
item.Dispose();
}
}
}
}
else
{ //无效账号关闭连接
client.SendAsync("Invalid Account");
foreach (var item in AsyncTcpServer.service.Clients)
{
if (item.Id == client.Id)
{
item.CloseAsync();
item.Dispose();
}
}
}
}
catch (Exception ex)
{//错误
Console.WriteLine("Tcp:" + ex.ToString());
client.SendAsync("Target instruction parsing error manager will close connection");
foreach (var item in AsyncTcpServer.service.Clients)
{
if (item.Id == client.Id)
{
item.CloseAsync();
item.Dispose();
}
}
}
//string DAT = e.ByteBlock.Span.ToString(Encoding.UTF8).Substring(5);
//string SYSDAT = "";// = e.ByteBlock.Span.ToString(Encoding.ASCII).Substring(5);
// string SYSKEY = "";
// if (DAT.Length >= 16) SYSKEY = DAT.Substring(0, 16);
// if (DAT.Length > 16) SYSDAT = DAT.Substring(16);
return EasyTask.CompletedTask;
};
await service.SetupAsync(new TouchSocketConfig()//载入配置
// .SetMaxBufferSize(1024 * 1024 * 100)
//.SetMinBufferSize(1024 * 1024)
.SetListenIPHosts(new IPHost[] { new IPHost(port1), new IPHost(port2) })//同时监听两个地址
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
})
.ConfigurePlugins(a =>
{
})
);
await service.StartAsync();//启动
Console.WriteLine("TCP Port:"+ port1.ToString());
Console.WriteLine("TCP Port:"+ port2.ToString());
Console.WriteLine("TCP SERVER:START");
}
}
class MyTcpService : TcpService<MyTcpSessionClient>
{
protected override MyTcpSessionClient NewClient()
{
return new MyTcpSessionClient();
}
}
class MyTcpSessionClient : TcpSessionClient
{
internal void SetDataHandlingAdapter(SingleStreamDataHandlingAdapter adapter)
{
base.SetAdapter(adapter);
}
}
/// <summary>
/// 此插件实现,按照不同端口,使用不同适配器。
/// <list type="bullet">
/// <item>7789端口:使用"**"结尾的数据</item>
/// <item>7790端口:使用"##"结尾的数据</item>
/// </list>
/// </summary>
internal class DifferentProtocolPlugin : PluginBase, ITcpConnectingPlugin, ITcpReceivedPlugin
{
public async Task OnTcpConnecting(ITcpSession client, ConnectingEventArgs e)
{
if (client is MyTcpSessionClient sessionClient)
{
if (sessionClient.ServicePort == 7789)
{
sessionClient.SetDataHandlingAdapter(new TerminatorPackageAdapter("**"));
}
else
{
sessionClient.SetDataHandlingAdapter(new TerminatorPackageAdapter("##"));
}
}
await e.InvokeNext();
}
public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e)
{
//如果是自定义适配器,此处解析时,可以判断e.RequestInfo的类型
if (client is ITcpSessionClient sessionClient)
{
sessionClient.Logger.Info($"{sessionClient.GetIPPort()}收到数据,服务器端口:{sessionClient.ServicePort},数据:{e.Memory.Span.ToString(Encoding.UTF8)}");
}
await e.InvokeNext();
}
}
}

79
UserClass/DataBase.cs

@ -0,0 +1,79 @@
using CommunityToolkit.Mvvm.Input;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using TouchSocket.Sockets;
namespace SunlightAggregationManager.UserClass
{
public class DataBase
{
private string DB_NAME = null!;
private string DB_TYPE = null!;
private string DB_ID = null!;
private string DB_IP = null!;
private string DB_PASSWORD = null!;
public void Config(string ip, string name, string type, string id, string password)
{
DB_IP = ip;
DB_ID = id;
DB_NAME = name;
DB_TYPE = type;
DB_PASSWORD = password;
_= ConfigAsync();
}
public async Task ConfigAsync()
{
await Task.Delay(3000);
//进入后台线程操作
await Task.Run(() =>
{
try
{
// 构建连接字符串
var builder = new SqlConnectionStringBuilder
{
DataSource = DB_IP,
InitialCatalog = DB_NAME,
IntegratedSecurity = DB_TYPE == "Windows Authentication",
TrustServerCertificate = true,
ConnectTimeout = 5
};
if (!builder.IntegratedSecurity)
{
builder.UserID = DB_ID;
builder.Password = DB_PASSWORD;
}
//连接数据库
using var conn_SC = new SqlConnection(builder.ConnectionString);
conn_SC.Open();
using (var cmd = new SqlCommand("SELECT 1", conn_SC))
{
cmd.ExecuteReader();
}
}
catch (Exception ex)
{
Console.WriteLine("DataBase Link timeout\n"+ex.ToString());
// 失败处理
return; // 直接返回,不执行后续代码
}
Console.WriteLine("DataBase Link succeed");
});
}
public void Database(string dat)
{
}
}
}

83
UserClass/IniFile.cs

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Input;
namespace SunlightAggregationManager.UserClass
{
internal class IniFile
{
public class IniFiles
{
public string path;
[DllImport("kernel32")] //返回0表示失败,非0为成功
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")] //返回取得字符串缓冲区的长度
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
/// <summary>
/// 保存ini文件的路径
/// 调用示例:var ini = IniFiles("C:\file.ini");
/// </summary>
/// <param name="INIPath"></param>
public IniFiles(string iniPath)
{
this.path = iniPath;
}
/// <summary>
/// 写Ini文件
/// 调用示例:ini.IniWritevalue("Server","name","localhost");
/// </summary>
/// <param name="Section">[缓冲区]</param>
/// <param name="Key">键</param>
/// <param name="value">值</param>
public void IniWritevalue(string Section, string Key, string? value)
{
// 确保路径有效
if (!File.Exists(path))
{
// 如果文件不存在,创建一个空的
using (FileStream fs = File.Create(path)) { }
}
// 处理 null 值,避免 API 调用出现问题
string safeValue = value ?? string.Empty;
long result = WritePrivateProfileString(Section, Key, safeValue, path);
if (result==0)
{
// 可以选择抛出异常或记录日志
// throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
/// <summary>
/// 读Ini文件
/// 调用示例:ini.IniWritevalue("Server","name");
/// </summary>
/// <param name="Section">[缓冲区]</param>
/// <param name="Key">键</param>
/// <returns>值</returns>
public string IniReadvalue(string Section, string Key)
{
try
{
if (!File.Exists(path))
{
return string.Empty;
}
var sb = new StringBuilder(4096);
GetPrivateProfileString(Section, Key, string.Empty, sb, sb.Capacity, path);
return sb.ToString();
}
catch (Exception)
{//错误返回0
return "0";
}
}
}
}
}

75
UserClass/NetFwManger.cs

@ -0,0 +1,75 @@
using NetFwTypeLib;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace SunlightAggregationManager.UserClass
{
public class NetFwManger
{
private static string GetName(int port, string protocol)
{
return "port-" + protocol + "-" + port;
}
public static void AllowPort(int port, string protocol)
{
DelPort(port, protocol);
//创建一个INetFwRule对象
Type type = Type.GetTypeFromProgID("HNetCfg.FwRule") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwRule? rule = (INetFwRule?)Activator.CreateInstance(type);
//设置规则的属性
rule?.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW; //允许连接
rule?.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN; //入站规则
rule?.Enabled = true; //启用规则
rule?.InterfaceTypes = "All"; //适用于所有网络接口
rule?.Name = GetName(port, protocol); //规则名称
if (protocol.ToLower() == "tcp")
{
rule?.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP; //TCP协议
}
else
{
rule?.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP; //UDP协议
}
rule?.LocalPorts = "" + port; //本地端口号
//获取FirewallPolicy对象
Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwPolicy2? policy = (INetFwPolicy2?)Activator.CreateInstance(policyType);
//将规则添加到防火墙策略中
policy?.Rules.Add(rule);
}
public static void DelPort(int port, string protocol)
{
//获取FirewallPolicy对象
Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2") ?? throw new
InvalidOperationException("Failed to retrieve HNetCfg.FwRule type. Ensure the COM component is registered.");
INetFwPolicy2? policy = (INetFwPolicy2?)Activator.CreateInstance(policyType);
//获取现有的规则集合
INetFwRules? rules = policy?.Rules;
if (rules != null)
{
//查找名称的规则并删除它
foreach (INetFwRule rule in rules)
{
if (rule.Name == GetName(port, protocol))
{
rules.Remove(rule.Name);
Console.WriteLine(@"Firewall rule deleted successfully.");
break;
}
}
}
}
}
}

510
UserClass/SqliteHelper.cs

@ -0,0 +1,510 @@
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SunlightAggregationManager.UserClass
{
// 辅助锁类 (代码中引用了 ClsLock,这里提供一个简单的实现或占位)
// 请根据实际情况替换为你项目中的 ClsLock,或使用 ReaderWriterLockSlim
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
}
}

62
UserClass/TextWriter.cs

@ -0,0 +1,62 @@
using System;
using System.IO;
using System.Text;
using System.Windows; // WPF 的核心命名空间
using System.Windows.Controls; // WPF TextBox 所在的命名空间
using System.Windows.Threading; // 用于 Dispatcher
namespace SunlightAggregationManager.UserClass
{
public class ControlWriter : TextWriter
{
private readonly TextBox _textbox;
public ControlWriter(TextBox textbox)
{
_textbox = textbox;
}
public override void Write(char value) => AppendText(DateTime.Now + ": " + value.ToString());
public override void Write(string? value) => AppendText(DateTime.Now + ": " + value);
public override void WriteLine(string? value) => AppendText(DateTime.Now + ": "+value + Environment.NewLine);
private void AppendText(string text)
{
if (!_textbox.Dispatcher.CheckAccess())
{
_textbox.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => AppendText(text)));
return;
}
_textbox.AppendText(text);
_textbox.ScrollToEnd();
}
public override Encoding Encoding => Encoding.UTF8;
}
//全局日志管理器
public static class GlobalLogManager
{
private static ControlWriter? _currentWriter;
// 【核心功能】注册目标 TextBox
// 子页面加载时调用这个方法
public static void RegisterTarget(TextBox logBox)
{
// 创建新的 Writer
_currentWriter = new ControlWriter(logBox);
// 【关键】将 Console 的输出重定向到这个 Writer
// 这样 Console.WriteLine("...") 就会自动写入到 logBox 中
Console.SetOut(_currentWriter);
Console.WriteLine("Start");
}
//提供一个直接写入的方法(如果不使用 Console.WriteLine)
public static void Write(string message)
{
_currentWriter?.WriteLine(message);
}
}
}

12
UserWindow/UserSet.xaml

@ -0,0 +1,12 @@
<Window x:Class="SunlightAggregationManager.UserWindow.UserSet"
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:SunlightAggregationManager.UserWindow"
mc:Ignorable="d"
Title="UserSet" Height="450" Width="800" WindowStyle="None" >
<Grid>
</Grid>
</Window>

25
UserWindow/UserSet.xaml.cs

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
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.Shapes;
namespace SunlightAggregationManager.UserWindow
{
/// <summary>
/// UserSet.xaml 的交互逻辑
/// </summary>
public partial class UserSet : Window
{
public UserSet()
{
InitializeComponent();
}
}
}

38
View/SettingPage.xaml

@ -0,0 +1,38 @@
<UserControl x:Class="SunlightAggregationManager.View.SettingPage"
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:SunlightAggregationManager.View"
xmlns:lang="clr-namespace:SunlightAggregationManager"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1080">
<Grid>
<ComboBox HorizontalAlignment="Left" Height="40" Margin="150,10,0,0" x:Name="comboBoxLanguage" VerticalAlignment="Top" Width="400" FontSize="24"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,10,0,0" TextWrapping="Wrap" Text="{x:Static lang:ResourceLanguage.Language}" VerticalAlignment="Top" Width="120" FontSize="25" Padding="0,0,0,0"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,60,0,0" TextWrapping="Wrap" Text="{x:Static lang:ResourceLanguage.SERVER}" VerticalAlignment="Top" Width="120" FontSize="25"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,110,0,0" TextWrapping="Wrap" Text="{x:Static lang:ResourceLanguage.Mode}" VerticalAlignment="Top" Width="120" FontSize="25"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,160,0,0" TextWrapping="Wrap" Text="{x:Static lang:ResourceLanguage.SQL}" VerticalAlignment="Top" Width="120" FontSize="25"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,210,0,0" TextWrapping="Wrap" Text="{x:Static lang:ResourceLanguage.user}" VerticalAlignment="Top" Width="120" FontSize="25"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,260,0,0" TextWrapping="Wrap" Text="{x:Static lang:ResourceLanguage.Password}" VerticalAlignment="Top" Width="120" FontSize="25"/>
<TextBox x:Name="TEXT_SQLIP" HorizontalAlignment="Left" Height="40" Margin="150,60,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="400" FontSize="24"/>
<ComboBox x:Name="TEXT_SQMOD" Height="40" Margin="150,110,0,0" VerticalAlignment="Top" Width="400" FontSize="24" HorizontalAlignment="Left"/>
<TextBox x:Name="TEXT_SQLNAME" HorizontalAlignment="Left" Height="40" Margin="150,160,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="400" FontSize="24"/>
<TextBox x:Name="TEXT_SQLUSER" HorizontalAlignment="Left" Height="40" Margin="150,210,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="400" FontSize="24"/>
<TextBox x:Name="TEXT_SQLPASWORD" HorizontalAlignment="Left" Height="40" Margin="150,260,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="400" FontSize="24"/>
<Button Content="{x:Static lang:ResourceLanguage.Test}" HorizontalAlignment="Left" Height="35" Margin="370,335,0,0" VerticalAlignment="Top" Width="80" Click="test_Click"/>
<TextBlock HorizontalAlignment="Left" Height="40" Margin="10,335,0,0" x:Name="textlog" TextWrapping="Wrap" Text="------------" VerticalAlignment="Top" Width="140" FontSize="20"/>
<CheckBox x:Name="EnableTCP" Content="{x:Static lang:ResourceLanguage.EnableTCP}" HorizontalAlignment="Left" Margin="600,10,0,0" VerticalAlignment="Top" Height="40" Width="300" FontSize="24"
Checked="EnableTCP_Checked" Unchecked="EnableTCP_Unchecked"/>
<CheckBox x:Name="EnableHTTP" Content="{x:Static lang:ResourceLanguage.EnableHTTP}" HorizontalAlignment="Left" Margin="600,60,0,0" VerticalAlignment="Top" Height="40" Width="300" FontSize="24"
Checked="EnableHTTP_Checked" Unchecked="EnableHTTP_Unchecked"/>
<CheckBox x:Name="EnableTLS" Content="{x:Static lang:ResourceLanguage.EnableTLS}" HorizontalAlignment="Left" Margin="600,110,0,0" VerticalAlignment="Top" Height="40" Width="300" FontSize="24"
Checked="EnableTLS_Checked" Unchecked="EnableTLS_Unchecked"/>
<Button Content="{x:Static lang:ResourceLanguage.save}" HorizontalAlignment="Right" Height="35" Margin="470,335,0,0" VerticalAlignment="Bottom" Width="80" Click="save_Click"/>
</Grid>
</UserControl>

157
View/SettingPage.xaml.cs

@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
//using System.Data.SqlClient;
using Microsoft.Data.SqlClient;
using System.Text;
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;
namespace SunlightAggregationManager.View
{
/// <summary>
/// SettingPage.xaml 的交互逻辑
/// </summary>
public partial class SettingPage : UserControl
{
//调用配置文件
private readonly UserClass.IniFile.IniFiles Configini = new UserClass.IniFile.IniFiles(Convert.ToString(System.AppDomain.CurrentDomain.BaseDirectory) + "Configini.ini");
public SettingPage()
{
InitializeComponent();
string[] Language = { "en-US", "zh-CN", "zh-TW" };
string[] SQMOD = { "Windows Authentication", "SQL SERVER" };
comboBoxLanguage.ItemsSource = Language;
TEXT_SQMOD.ItemsSource = SQMOD;
try
{
comboBoxLanguage.Text = Configini.IniReadvalue("SYS", "Language");
TEXT_SQLIP.Text = Configini.IniReadvalue("SQL_SERVER", "SQL1"); //读配置文件
TEXT_SQLNAME.Text = Configini.IniReadvalue("SQL_SERVER", "SQL2");
TEXT_SQMOD.Text = Configini.IniReadvalue("SQL_SERVER", "SQL3");
TEXT_SQLUSER.Text = Configini.IniReadvalue("SQL_SERVER", "SQL4");
TEXT_SQLPASWORD.Text = Configini.IniReadvalue("SQL_SERVER", "SQL5");
}
catch (Exception) { }
}
private async void test_Click(object sender, RoutedEventArgs e)
{
// UI 更新:显示正在测试
textlog.Text = "TEST";
// 建议使用静态缓存的画笔,避免频繁创建对象导致内存抖动
textlog.Foreground = Brushes.Blue;
try
{
// 构建连接字符串
var builder = new SqlConnectionStringBuilder
{
DataSource = TEXT_SQLIP.Text,
InitialCatalog = TEXT_SQLNAME.Text,
IntegratedSecurity = TEXT_SQMOD.Text == "Windows Authentication",
TrustServerCertificate = true
};
if (!builder.IntegratedSecurity)
{
builder.UserID = TEXT_SQLUSER.Text;
builder.Password = TEXT_SQLPASWORD.Text;
}
// 异步连接数据库
await using var conn_SC = new SqlConnection(builder.ConnectionString);
// 使用 OpenAsync 代替 Open,避免卡死界面
await conn_SC.OpenAsync();
using (var cmd = new SqlCommand("SELECT 1", conn_SC))
{
cmd.ExecuteReader();
}
}
catch (Exception)
{
// 失败处理
textlog.Text = "Link timeout";
textlog.Foreground = Brushes.Red;
return; // 直接返回,不执行后续代码
}
// 成功处理
textlog.Text = "Link succeed";
textlog.Foreground = Brushes.Green;
Console.WriteLine("IP = "+TEXT_SQLIP.Text);
Console.WriteLine("DataBase = " + TEXT_SQLNAME.Text);
Console.WriteLine("Link succeed");
// 弹出对话框本身会阻塞 UI 线程
MessageBoxResult SqlShow = System.Windows.MessageBox.Show(
"Whether the connection is successfully saved",
"SQL",
MessageBoxButton.YesNo,
MessageBoxImage.Information);
if (SqlShow == MessageBoxResult.Yes)
{
Configini.IniWritevalue("SQL_SERVER", "SQL1", TEXT_SQLIP.Text);
Configini.IniWritevalue("SQL_SERVER", "SQL2", TEXT_SQLNAME.Text);
Configini.IniWritevalue("SQL_SERVER", "SQL3", TEXT_SQMOD.SelectedValue?.ToString());
Configini.IniWritevalue("SQL_SERVER", "SQL4", TEXT_SQLUSER.Text);
Configini.IniWritevalue("SQL_SERVER", "SQL5", TEXT_SQLPASWORD.Text);
Console.WriteLine("Save database settings");
}
}
private void save_Click(object sender, RoutedEventArgs e)
{
Configini.IniWritevalue("SYS", "Language", comboBoxLanguage.SelectedValue?.ToString());
Configini.IniWritevalue("SQL_SERVER", "SQL1", TEXT_SQLIP.Text);
Configini.IniWritevalue("SQL_SERVER", "SQL2", TEXT_SQLNAME.Text);
Configini.IniWritevalue("SQL_SERVER", "SQL3", TEXT_SQMOD.SelectedValue?.ToString());
Configini.IniWritevalue("SQL_SERVER", "SQL4", TEXT_SQLUSER.Text);
Configini.IniWritevalue("SQL_SERVER", "SQL5", TEXT_SQLPASWORD.Text);
Console.WriteLine("Save global settings");
}
//是否启用tcp
private void EnableTCP_Checked(object sender, RoutedEventArgs e)
{
Configini.IniWritevalue("NETWORK", "TCP", "1");
}
private void EnableTCP_Unchecked(object sender, RoutedEventArgs e)
{
Configini.IniWritevalue("NETWORK", "TCP", "0");
}
private void EnableHTTP_Checked(object sender, RoutedEventArgs e)
{
Configini.IniWritevalue("NETWORK", "HTTP", "1");
}
private void EnableHTTP_Unchecked(object sender, RoutedEventArgs e)
{
Configini.IniWritevalue("NETWORK", "HTTP", "0");
}
private void EnableTLS_Checked(object sender, RoutedEventArgs e)
{
Configini.IniWritevalue("NETWORK", "TLS", "1");
}
private void EnableTLS_Unchecked(object sender, RoutedEventArgs e)
{
Configini.IniWritevalue("NETWORK", "TLS", "0");
}
}
}

13
View/StatePage.xaml

@ -0,0 +1,13 @@
<UserControl x:Class="SunlightAggregationManager.View.StatePage"
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:SunlightAggregationManager.View"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1080">
<Grid>
<TextBox x:Name="LOG" TextWrapping="Wrap" Margin="5,200,5,5" FontSize="16"/>
</Grid>
</UserControl>

33
View/StatePage.xaml.cs

@ -0,0 +1,33 @@
using Net.Codecrete.QrCodeGenerator;
using SunlightAggregationManager.UserClass;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
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 static System.Net.WebRequestMethods;
namespace SunlightAggregationManager.View
{
/// <summary>
/// StatePage.xaml 的交互逻辑
/// </summary>
public partial class StatePage : UserControl
{
public StatePage()
{
InitializeComponent();
}
}
}

114
View/UserPage.xaml

@ -0,0 +1,114 @@
<UserControl x:Class="SunlightAggregationManager.View.UserPage"
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:SunlightAggregationManager.View"
xmlns:ConvertMoels="clr-namespace:SunlightAggregationManager.ConvertMoels"
xmlns:lang="clr-namespace:SunlightAggregationManager"
xmlns:viewmodel="clr-namespace:SunlightAggregationManager.ViewModel"
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel}"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1080">
<!--设定变换器-->
<UserControl.Resources>
<ConvertMoels:StatenConvert x:Key="StatenConvert"/>
<ConvertMoels:StatenERRConvert x:Key="StatenERRConvert"/>
</UserControl.Resources>
<Grid>
<DataGrid x:Name="DataGridmachinesdata"
ItemsSource="{Binding UserData.DefaultView}"
SelectionChanged="DataGridmachinesdata_SelectionChanged"
SelectionMode="Single"
AlternationCount="2"
IsReadOnly="True"
FontSize="26"
Margin="5,5,5,5"
AutoGenerateColumns="False"
MinColumnWidth="30"
HorizontalGridLinesBrush="#FFC9C9C9"
VerticalGridLinesBrush="#FFC9C9C9"
GridLinesVisibility="All"
BorderBrush="#CCCCCC"
BorderThickness="1,1,1,1"
ColumnHeaderHeight="40"
HorizontalContentAlignment="Right"
CanUserReorderColumns="False"
VerticalContentAlignment="Center">
<DataGrid.RowStyle >
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Height" Value="40" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#FFF0F0F0" />
<Setter Property="Height" Value="40" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="MinWidth" Value="20"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#FFC0C0C0"/>
<Setter Property="BorderBrush" Value="#FFC0C0C0"/>
<Setter Property="Foreground" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="{x:Static lang:ResourceLanguage.information}" Click="MenuItem_Information"/>
<MenuItem Header="{x:Static lang:ResourceLanguage.Offine}" Click="MenuItem_Offine"/>
<MenuItem Header="{x:Static lang:ResourceLanguage.Enable}" Click="MenuItem_Enable"/>
<MenuItem Header="{x:Static lang:ResourceLanguage.Disable}" Click="MenuItem_Disable"/>
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Columns>
<!--列信息绑定-->
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.user}" Width="200" FontSize="26"
Binding="{Binding User}" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Name}" Width="200" FontSize="26"
Binding="{Binding Name}" MaxWidth="200" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.state}" Width="120" FontSize="26"
MaxWidth="120" MinWidth="120" CanUserReorder="False">
<!--事件名称:工作状态数字转文字显示,转换器StatenConvert-->
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="{Binding Path=State,Converter={StaticResource StatenConvert}}">
</Setter>
<Setter Property="Foreground" Value="{Binding Path=State,Converter={StaticResource StatenERRConvert}}">
</Setter>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Department}" Width="150" FontSize="26"
Binding="{Binding Department}" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.LastLoginIP}" Width="250" FontSize="26"
Binding="{Binding LastLoginIP}" MinWidth="250" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.LastLoginTerminal}" Width="300" FontSize="26"
Binding="{Binding LastLoginTerminal}" MinWidth="300" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.LastLoginTime}" Width="300" FontSize="26"
Binding="{Binding LastLoginTime}" MinWidth="300" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.LastActionTime}" Width="300" FontSize="26"
Binding="{Binding LastActionTime}" MinWidth="300" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.LastOfflineTime}" Width="300" FontSize="26"
Binding="{Binding LastOfflineTime}" MinWidth="300" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.Groups}" Width="200" FontSize="26"
Binding="{Binding Groups}" MinWidth="200" CanUserReorder="False"/>
<DataGridTextColumn Header="{x:Static lang:ResourceLanguage.information}" Width="*" FontSize="26"
Binding="{Binding Note}" MinWidth="200" CanUserReorder="False"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>

90
View/UserPage.xaml.cs

@ -0,0 +1,90 @@
using SunlightAggregationManager.UserClass;
using SunlightAggregationManager.ViewModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
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 System.Xml.Linq;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace SunlightAggregationManager.View
{
/// <summary>
/// UserPage.xaml 的交互逻辑
/// </summary>
public partial class UserPage : UserControl
{
public UserPage()
{
InitializeComponent();
}
private string user_id = "";
private void DataGridmachinesdata_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int rownum = DataGridmachinesdata.SelectedIndex;//获取鼠标选中行并定义变量
if (rownum != -1)//判断鼠标定位是否有效
{
var row_ = DataGridmachinesdata.Columns[0].GetCellContent(DataGridmachinesdata.Items[rownum]);
if (row_ is TextBlock textBlock)
{
user_id = textBlock.Text;//定位第0列,
}
}
}
private void MenuItem_Information(object sender, RoutedEventArgs e)//信息
{
}
private async void MenuItem_Offine(object sender, RoutedEventArgs e)//下线
{
var _state = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "State", "User='" + user_id + "'");
var _user = MainWindowViewModel.Selet_Memory(MainWindowViewModel._userData, "LinkID", "User='" + user_id +"'");
if ((_user != null)&&(_state?.ToString()=="20"))
{
foreach (var item in AsyncTcpServer.service.Clients)
{
if (item.Id == _user.ToString())
{
await item.CloseAsync();
//在断开连接后,释放对象。
item.Dispose();
}
}
}
}
private void MenuItem_Enable(object sender, RoutedEventArgs e)//启用账号
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + user_id + "'", "0", "State");
}
private void MenuItem_Disable(object sender, RoutedEventArgs e)//停用账号
{
MainWindowViewModel.Updata_Memory(MainWindowViewModel._userData, "User='" + user_id + "'", "99", "State");
}
}
}

17
View/imgQR.xaml

@ -0,0 +1,17 @@
<UserControl x:Class="SunlightAggregationManager.View.imgQR"
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:SunlightAggregationManager.View"
mc:Ignorable="d"
Loaded="imgQR_Loaded"
d:DesignHeight="720" d:DesignWidth="1080">
<Grid>
<TextBlock Text="APP" Margin="300,100,20,10" Foreground="Black" HorizontalAlignment="Left" FontSize="48" VerticalAlignment="Top"/>
<TextBlock Text="LINK" VerticalAlignment="Top" Margin="0,100,300,10" Foreground="Black" HorizontalAlignment="Right" FontSize="48"/>
<Image x:Name="imgQR_app" MinWidth="300" MinHeight="300" MaxWidth="300" MaxHeight="300" Width="300" Height="300" Stretch="Uniform" Margin="200,0,0,0" HorizontalAlignment="Left"/>
<Image x:Name="imgQR_link" MinWidth="300" MinHeight="300" MaxWidth="300" MaxHeight="300" Width="300" Height="300" Stretch="Uniform" HorizontalAlignment="Right" Margin="0,0,200,0"/>
</Grid>
</UserControl>

105
View/imgQR.xaml.cs

@ -0,0 +1,105 @@
using Net.Codecrete.QrCodeGenerator;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
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.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static System.Net.WebRequestMethods;
namespace SunlightAggregationManager.View
{
/// <summary>
/// StatePage.xaml 的交互逻辑
/// </summary>
public partial class imgQR : UserControl
{
//调用配置文件
private readonly UserClass.IniFile.IniFiles Configini = new UserClass.IniFile.IniFiles(Convert.ToString(System.AppDomain.CurrentDomain.BaseDirectory) + "Configini.ini");
public imgQR()
{
InitializeComponent();
}
/// <summary>
/// 生成二维码
/// 调用示例: imgQR_CREATE("TEST", imgQR);;
/// </summary>
/// <param name="data">[字符串]</param>
/// <param name="Image">Image控件</param>
void imgQR_CREATE(string DAT, System.Windows.Controls.Image image)
{
// 生成二维码对象
QrCode qr = QrCode.EncodeText(DAT, QrCode.Ecc.Medium);
// 手动绘制 Bitmap (不使用扩展方法)
int scale = 10; // 每个点的像素大小
int border = 4; // 边距
int size = (qr.Size + border * 2) * scale;
// 创建位图
using (Bitmap bmp = new Bitmap(size, size))
{
using (Graphics gfx = Graphics.FromImage(bmp))
{
// 填充背景(白色)
gfx.Clear(System.Drawing.Color.White);
// 绘制二维码点阵(黑色)
using (System.Drawing.Brush brush = new SolidBrush(System.Drawing.Color.Black))
{
for (int y = 0; y < qr.Size; y++)
{
for (int x = 0; x < qr.Size; x++)
{
if (qr.GetModule(x, y))
{
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(
(x + border) * scale,
(y + border) * scale,
scale, scale);
gfx.FillRectangle(brush, rect);
}
}
}
}
}
// 转换为 WPF 的 BitmapImage 并显示
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.Position = 0;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = ms;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
// 赋值给 Image 控件 (假设控件名为 imgQR)
image.Source = bitmapImage;
}
}
}
private void imgQR_Loaded(object sender, RoutedEventArgs e)
{
string text_APP = "TEST"; // 要生成二维码的内容
string text_LINK = Configini.IniReadvalue("SYS", "LINK"); // 要生成二维码的内容
imgQR_CREATE(text_APP, imgQR_app);
imgQR_CREATE(text_LINK, imgQR_link);
}
}
}

31
View/logPage.xaml

@ -0,0 +1,31 @@
<UserControl x:Class="SunlightAggregationManager.View.logPage"
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:SunlightAggregationManager.View"
mc:Ignorable="d"
Loaded="logPage_Loaded"
d:DesignHeight="720" d:DesignWidth="1080">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="600"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ComboBox Height="45" x:Name="comboBox_log" VerticalAlignment="Top" FontSize="20" Background="#FF90BEFF"
DropDownClosed="comboBox_log_DropDownClosed" BorderBrush="#FF00204E" Padding="1,1,1,1"/>
<DataGrid Grid.Column="0" x:Name="gridLog" Margin="0,50,0,0" HeadersVisibility ="Column"
IsReadOnly="True" AutoGenerateColumns="False" MouseDoubleClick="DataGrid_gridLogClick" >
<DataGrid.Columns>
<!--列信息绑定-->
<DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="195" MaxWidth="195" MinWidth="195" CanUserReorder="False"/>
<DataGridTextColumn Binding="{Binding Length}" Header="Volume" Width="50" MaxWidth="150" MinWidth="100" CanUserReorder="False"/>
<DataGridTextColumn Binding="{Binding CreationTimeUtc}" Header="Creation time" Width="150" MaxWidth="150" MinWidth="150" CanUserReorder="False"/>
<DataGridTextColumn Binding="{Binding LastWriteTimeUtc}" Header="Last modified time" Width="150" MaxWidth="150" MinWidth="150" CanUserReorder="False"/>
</DataGrid.Columns>
</DataGrid>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" Background="#FF00204E"/>
<RichTextBox Grid.Column="2" x:Name="Logtext" IsReadOnly="True" Background="White" SelectionBrush="White"/>
</Grid>
</UserControl>

143
View/logPage.xaml.cs

@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
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;
namespace SunlightAggregationManager.View
{
/// <summary>
/// logPage.xaml 的交互逻辑
/// </summary>
public partial class logPage : UserControl
{
public logPage()
{
InitializeComponent();
}
private readonly string Log_time = DateTime.Now.ToString("yyyy-MM-dd");
DataTable logdataTable = new DataTable(); //建立缓存
long TEXT_L;
private void logPage_Loaded(object sender, RoutedEventArgs e)//页面打开事件
{
comboBox_log.ItemsSource = new string[3] { "Log", "ERR", "Exchange" };
comboBox_log.Text = "Log";
logdataTable.Columns.Add("Name", typeof(string));
logdataTable.Columns.Add("Length", typeof(int));
logdataTable.Columns.Add("CreationTimeUtc", typeof(string));
logdataTable.Columns.Add("LastWriteTimeUtc", typeof(string));
DirectoryInfo loginfo = new DirectoryInfo(System.Environment.CurrentDirectory + "\\Log"); //new文件夹
logdataTable.Clear();
foreach (var item in loginfo.GetFiles())
{
DataRow FileRow = logdataTable.NewRow();
FileRow["Name"] = item.Name;
FileRow["Length"] = item.Length / 1024;
FileRow["CreationTimeUtc"] = item.CreationTimeUtc;
FileRow["LastWriteTimeUtc"] = item.LastWriteTimeUtc;
logdataTable.Rows.Add(FileRow);
}
logdataTable.DefaultView.Sort = "Name DESC";
gridLog.ItemsSource = logdataTable.DefaultView.ToTable().DefaultView;
}
private void LOG_file()//建立列表
{
DirectoryInfo loginfo = new DirectoryInfo(System.Environment.CurrentDirectory + "\\" + comboBox_log.Text); //new文件夹
logdataTable.Clear();
foreach (var item in loginfo.GetFiles())
{
DataRow FileRow = logdataTable.NewRow();
FileRow["Name"] = item.Name;
FileRow["Length"] = item.Length / 1024;
FileRow["CreationTimeUtc"] = item.CreationTimeUtc;
FileRow["LastWriteTimeUtc"] = item.LastWriteTimeUtc;
logdataTable.Rows.Add(FileRow);
}
logdataTable.DefaultView.Sort = "Name DESC";
gridLog.ItemsSource = logdataTable.DefaultView.ToTable().DefaultView;
}
private void DataGrid_gridLogClick(object sender, MouseButtonEventArgs e)//数据表双击事件
{
int rownum = gridLog.SelectedIndex;//获取鼠标选中行并定义变量
if (rownum != -1)//判断鼠标定位是否有效
{
/*定位选中行及指定列单元格文本信息*/
//获取单元格内容
var cellContent = gridLog.Columns[0].GetCellContent(gridLog.Items[rownum]);
//安全转换为 TextBlock 并获取文本
var textValue = (cellContent as TextBlock)?.Text;
if (!string.IsNullOrEmpty(textValue))
{
LOGDATA_file(textValue);//
}
var Content_L = gridLog.Columns[1].GetCellContent(gridLog.Items[rownum]);
var Value_L = (Content_L as TextBlock)?.Text.ToString();
if (!string.IsNullOrEmpty(Value_L))
{
TEXT_L = long.Parse(Value_L) * 1024 + 1024;
}
}
}
/// <summary>
/// 读取文件显示到前端
/// 调用示例: LOGDATA_file(file path);
/// </summary>
/// <param name="path">文件路径</param>
private async void LOGDATA_file(string dat) //读取文件显示到前端
{
Logtext.SelectAll();
Logtext.Cut();
Logtext.Document = new FlowDocument();
string filePath = System.Environment.CurrentDirectory + "\\" + comboBox_log.Text + "\\";
try
{
Logtext.AppendText("Loading...");
string log_ = "";
string log_DAT = await Task<string>.Run(() =>
{
// 使用StreamReader读取文件
using (StreamReader reader = new StreamReader(filePath + dat))
{
// 读取文件直到文件的末尾
while (!reader.EndOfStream)
{
// 添加文件的每一行到RichTextBox
log_ = log_ + reader.ReadLine() + "\n";
}
}
return log_;
});
Logtext.SelectAll();
Logtext.Cut();
Logtext.AppendText(log_DAT);
}
catch (Exception ex)
{
// 处理可能发生的任何异常
MessageBox.Show("Error reading file: " + ex.Message);
}
}
private void comboBox_log_DropDownClosed(object sender, EventArgs e)
{
LOG_file();
}
}
}

231
ViewModel/MainWindowViewModel.cs

@ -0,0 +1,231 @@
using CommunityToolkit.Mvvm;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SunlightAggregationManager.UserClass;
using System;
using System.Collections.Generic;
using System.Data;
using System.Net;
using System.Reflection.PortableExecutable;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using System.Xml.Linq;
namespace SunlightAggregationManager.ViewModel
{
public partial class MainWindowViewModel : ObservableObject
{
//调用配置文件
private static UserClass.IniFile.IniFiles Configini = new UserClass.IniFile.IniFiles(Convert.ToString(System.AppDomain.CurrentDomain.BaseDirectory) + "Configini.ini");
public static string SQLIP=""; //读配置文件
public static string SQLNAME="";
public static string SQMOD= "";
public static string SQLUSER = "";
public static string SQLPASWORD = "";
public static string MachineName = "SERVER";
public static string TCP_E = "0";
public static string HTTP_E = "0";
public static string TLS_E = "0";
public static UserClass.SqliteHelper SQLiteHelpers = null!; //定义数据库
private readonly string DBAddress = Environment.CurrentDirectory + "\\DataBase\\SunlightAggregationManager.db"; //数据库路径
public static DataTable ActionLog = new DataTable();
[ObservableProperty]
public static DataTable _machines = new DataTable(); //设备表缓存
[ObservableProperty]
public static DataTable _userData = new DataTable();
public MainWindowViewModel()
{
SQLIP = Configini.IniReadvalue("SQL_SERVER", "SQL1"); //读配置文件
SQLNAME = Configini.IniReadvalue("SQL_SERVER", "SQL2");
SQMOD = Configini.IniReadvalue("SQL_SERVER", "SQL3");
SQLUSER = Configini.IniReadvalue("SQL_SERVER", "SQL4");
SQLPASWORD = Configini.IniReadvalue("SQL_SERVER", "SQL5");
MachineName = Configini.IniReadvalue("SYS", "Name");
TCP_E = Configini.IniReadvalue("NETWORK", "TCP");
HTTP_E = Configini.IniReadvalue("NETWORK", "HTTP");
TLS_E = Configini.IniReadvalue("NETWORK", "TLS");
//本地数据库(sqlite)
try
{
SQLiteHelpers = new UserClass.SqliteHelper(DBAddress); //数据库连接路径
SQLiteHelpers.Open(); //打开数据库
UserData = SQLiteHelpers.ExecuteDataSet("select * from USER order by UserID asc", null)?.Tables[0] ?? new DataTable();
Machines = SQLiteHelpers.ExecuteDataSet("select * from Machines order by ID asc", null)?.Tables[0] ?? new DataTable();
ActionLog = (SQLiteHelpers.ExecuteDataSet("select * from ActionLog", null)?.Tables[0] ?? new DataTable()).Clone();
// SQLiteHelpers.Close();
if (UserData.Columns.Contains("UserID"))
{
UserData.Columns.Remove("UserID");
}
DataRow[] dataRows = UserData.Select("State<90");
foreach (DataRow row in dataRows)
{
row["State"] = 0;
row["LinkID"] = 0;
}
UserData.RowChanged += UserData_Updata;//注册userdata表更新事件
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
//运行数据库
DataBase dataBase = new DataBase();
dataBase.Config(SQLIP, SQLNAME, SQMOD, SQLUSER, SQLPASWORD);
if (TCP_E == "1")//启动tcp(内网直连)
{
int P1, P2;
try
{
P1 =int.Parse( Configini.IniReadvalue("NETWORK", "TCP_PORT1"));
}
catch (Exception) { P1 = 7789; }
try
{
P2 = int.Parse(Configini.IniReadvalue("NETWORK", "TCP_PORT2"));
}
catch (Exception) { P2 = 7790; }
using var _ = AsyncTcpServer.TcpMain(P1,P2);
}
}
private void UserData_Updata(object sender, DataRowChangeEventArgs e)
{
Dictionary<string, object> row_entity = new Dictionary<string, object>();
Dictionary<string, object> userlog = new Dictionary<string, object>();
if (e.Action == DataRowAction.Change)
{
//修改的行回传
foreach (DataColumn col in UserData.Columns)
{
row_entity.Add(col.ColumnName, e.Row.Field<object>(col.ColumnName) ?? DBNull.Value);//传入字段和值(值允许为空)
if (ActionLog.Columns.Contains(col.ColumnName))//添加到行为记录表
{
userlog.Add(col.ColumnName, e.Row.Field<object>(col.ColumnName) ?? DBNull.Value);//传入字段和值(值允许为空)
}
}
SQLiteHelpers.Update("USER", row_entity,"User='"+ e.Row.Field<object>("User")+"'", null);
userlog.Add("Action", "Command");
userlog.Add("Time", DateTime.Now.ToString("yyyy-MM-dd dd:HH:mm:ss:fff"));
SQLiteHelpers.InsertData("ActionLog", userlog);
}
if (e.Action == DataRowAction.Add)
{
//添加的行回传
foreach (DataColumn col in UserData.Columns)
{
row_entity.Add(col.ColumnName, e.Row.Field<object>(col.ColumnName) ?? DBNull.Value);//传入字段和值(值允许为空)
}
SQLiteHelpers.InsertData("USER", row_entity);
userlog.Add("Time", DateTime.Now.ToString("yyyy-MM-dd dd:HH:mm:ss:fff"));
userlog.Add("Action", "New Account");
userlog.Add("Name", MachineName);
userlog.Add("Terminal", "Terminal");
userlog.Add("Note", "User = "+ e.Row.Field<object>("User"));
SQLiteHelpers.InsertData("ActionLog", userlog);
}
if (e.Action == DataRowAction.Delete)
{
//删除的行回传
SQLiteHelpers.Delete("USER", "User='" + e.Row.Field<object>("User") + "'", null);
userlog.Add("Time", DateTime.Now.ToString("yyyy-MM-dd dd:HH:mm:ss:fff"));
userlog.Add("Action", "Delete Account");
userlog.Add("Name", MachineName);
userlog.Add("Terminal", "Terminal");
userlog.Add("Note", "User = " + e.Row.Field<object>("User"));
SQLiteHelpers.InsertData("ActionLog", userlog);
}
}
public static object? Selet_Memory(DataTable DB, string name, string? key)//查询
{
try
{
lock (DB)
{
DataRow drEmployee = DB.Select(key).First();
object? index = drEmployee.Field<object>(name);
return index;
}
}
catch (Exception ex)
{
Console.WriteLine("SDTD:" + ex.ToString());
return null;
}
}
public static void Updata_Memory(DataTable DB, string key, string? Value, string name)//更新数据
{
try
{
lock (DB)
{
var dr = DB.Select(key);
if (dr.Length > 0)
{
DataRow drEmployee = dr.First();
drEmployee.BeginEdit();
drEmployee[name] = Value;
drEmployee.EndEdit();
drEmployee.AcceptChanges();
// drEmployee.ClearErrors();
}
}
}
catch (Exception ex)
{
Console.WriteLine("SDTD:" + ex.ToString());
}
}
public static void Updata_Memory(DataTable DB, string key, Dictionary<string, object> Value)//更新数据
{
try
{
lock (DB)
{
var dr = DB.Select(key);
if (dr.Length > 0)
{
DataRow drEmployee = dr.First();
drEmployee.BeginEdit();
foreach (KeyValuePair<string, object> kvp in Value)
{
drEmployee[kvp.Key] = kvp.Value;
}
drEmployee.EndEdit();
drEmployee.AcceptChanges();
// drEmployee.ClearErrors();
}
}
}
catch (Exception ex)
{
Console.WriteLine("SDTD:" + ex.ToString());
}
}
}
}
Loading…
Cancel
Save