@ -0,0 +1,14 @@ |
|||
<?xml version = "1.0" encoding = "UTF-8" ?> |
|||
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
xmlns:local="clr-namespace:SunlightAggregationTerminal" |
|||
x:Class="SunlightAggregationTerminal.App"> |
|||
<Application.Resources> |
|||
<ResourceDictionary> |
|||
<ResourceDictionary.MergedDictionaries> |
|||
<ResourceDictionary Source="Resources/Styles/Colors.xaml" /> |
|||
<ResourceDictionary Source="Resources/Styles/Styles.xaml" /> |
|||
</ResourceDictionary.MergedDictionaries> |
|||
</ResourceDictionary> |
|||
</Application.Resources> |
|||
</Application> |
|||
@ -0,0 +1,19 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using SunlightAggregationTerminal.Models; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
public partial class App : Application |
|||
{ |
|||
public static DataModel GlobalData { get; set;} = new DataModel(); |
|||
public App() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
protected override Window CreateWindow(IActivationState? activationState) |
|||
{ |
|||
return new Window(new AppShell()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<Shell |
|||
x:Class="SunlightAggregationTerminal.AppShell" |
|||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
xmlns:local="clr-namespace:SunlightAggregationTerminal" |
|||
Title="SunlightAggregationTerminal" |
|||
Loaded="Shell_Loaded" |
|||
Shell.FlyoutBehavior="Disabled"> |
|||
<Shell.Resources> |
|||
<ResourceDictionary> |
|||
<Style TargetType="TabBar"> |
|||
<!-- 核心代码:半透明白色 (Alpha值CC约80%不透明度) --> |
|||
<!-- 视觉上非常像磨砂玻璃,且兼容所有平台 --> |
|||
<Setter Property="Shell.TabBarBackgroundColor" Value="#CCF0F0F0" /> |
|||
<!-- 设置选中时的标题颜色(建议深色) --> |
|||
<Setter Property="Shell.TabBarTitleColor" Value="#333333" /> |
|||
<!-- 设置未选中时的图标和标题颜色 --> |
|||
<Setter Property="Shell.TabBarUnselectedColor" Value="#888888" /> |
|||
</Style> |
|||
</ResourceDictionary> |
|||
</Shell.Resources> |
|||
<TabBar> |
|||
<!-- 1 信息页面 --> |
|||
<ShellContent |
|||
Title="信息" |
|||
Icon="infofeed.png" |
|||
ContentTemplate="{DataTemplate local:InfoPage}"/> |
|||
<!-- 2 查询页面 --> |
|||
<ShellContent |
|||
Title="查询" |
|||
Icon="search.png" |
|||
ContentTemplate="{DataTemplate local:QueryPage}"/> |
|||
<!-- 3 通知页面 --> |
|||
<ShellContent |
|||
Title="通知" |
|||
Icon="ixnotifications.png" |
|||
ContentTemplate="{DataTemplate local:NotificationPage}"/> |
|||
<!-- 4 我的页面 --> |
|||
<ShellContent |
|||
Title="我" |
|||
Icon="adduserfilled.png" |
|||
ContentTemplate="{DataTemplate local:ProfilePage}"/> |
|||
|
|||
</TabBar> |
|||
</Shell> |
|||
@ -0,0 +1,35 @@ |
|||
using SunlightAggregationTerminal.Class; |
|||
using SunlightAggregationTerminal.Models; |
|||
using SunlightAggregationTerminal.View; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
public partial class AppShell : Shell |
|||
{ |
|||
public AppShell() |
|||
{ |
|||
InitializeComponent(); |
|||
this.BindingContext = new AppModels(); |
|||
} |
|||
|
|||
|
|||
private void Shell_Loaded(object sender, EventArgs e) |
|||
{ |
|||
//打开登录
|
|||
if (!App.GlobalData.LogNo) |
|||
{ |
|||
var logpage = new View.LogPage(); |
|||
Navigation.PushModalAsync(new NavigationPage(logpage)); |
|||
} |
|||
else |
|||
{//发送登录请求
|
|||
/* var dat = TcpServer.Query(""); |
|||
if (dat != null) |
|||
{//拒绝登陆时打开登录页面
|
|||
var logpage = new View.LogPage(); |
|||
Navigation.PushModalAsync(logpage); |
|||
}*/ |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,312 @@ |
|||
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(); |
|||
} |
|||
|
|||
if (SQLitedata.TableExists("Server")) |
|||
{ |
|||
CheckAndRepairTableSchemaSERVER(); |
|||
} |
|||
else |
|||
{ |
|||
CreateFreshUserTableSERVER(); |
|||
} |
|||
|
|||
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 CheckAndRepairTableSchemaSERVER() |
|||
{ |
|||
// 获取现有字段列表
|
|||
// 使用 PRAGMA table_info 获取结构
|
|||
string pragmaSql = "PRAGMA table_info('Server');"; |
|||
|
|||
// 复用现有的 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)
|
|||
// 检查 Enterprise
|
|||
if (!existingColumns.Contains("Enterprise")) |
|||
{ |
|||
string sql = "ALTER TABLE Server ADD COLUMN Enterprise TEXT NULL;"; |
|||
SQLitedata.ExecuteNonQuery(sql, null); |
|||
} |
|||
// 检查 ServerID
|
|||
if (!existingColumns.Contains("ServerID")) |
|||
{ |
|||
string sql = "ALTER TABLE Server ADD COLUMN ServerID TEXT;"; |
|||
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); |
|||
} |
|||
private static void CreateFreshUserTableSERVER() |
|||
{ |
|||
// 建表语句
|
|||
string createSql = @"
|
|||
CREATE TABLE Server ( |
|||
Enterprise TEXT, |
|||
ServerID TEXT |
|||
);";
|
|||
|
|||
// 复用现有的 ExecuteNonQuery 方法
|
|||
SQLitedata.ExecuteNonQuery(createSql, null); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -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
|
|||
} |
|||
} |
|||
@ -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();//调用连接,当连接不成功时,会抛出异常。
|
|||
} |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 946 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 309 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,9 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.InfoPage" |
|||
Title=""> |
|||
<VerticalStackLayout> |
|||
|
|||
</VerticalStackLayout> |
|||
</ContentPage> |
|||
@ -0,0 +1,9 @@ |
|||
namespace SunlightAggregationTerminal; |
|||
|
|||
public partial class InfoPage : ContentPage |
|||
{ |
|||
public InfoPage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Maui.Handlers; |
|||
using SunlightAggregationTerminal.Models; |
|||
using ZXing.Net.Maui.Controls; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
public static class MauiProgram |
|||
{ |
|||
public static MauiApp CreateMauiApp() |
|||
{ |
|||
var builder = MauiApp.CreateBuilder(); |
|||
builder |
|||
.UseMauiApp<App>() |
|||
.UseBarcodeReader() |
|||
.ConfigureFonts(fonts => |
|||
{ |
|||
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); |
|||
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); |
|||
}) |
|||
.ConfigureMauiHandlers(handlers => |
|||
{ |
|||
// 这里的 "NoUnderline" 是自定义映射名称,可以随意命名
|
|||
EntryHandler.Mapper.AppendToMapping("NoUnderline", (handler, view) => |
|||
{ |
|||
#if ANDROID
|
|||
// 将背景 tint 设为透明
|
|||
// 这会移除 Android 默认的下划线颜色
|
|||
handler.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Android.Graphics.Color.Transparent); |
|||
|
|||
// 如果想彻底移除背景绘制(不仅仅是颜色透明)
|
|||
// handler.PlatformView.Background = null;
|
|||
#endif
|
|||
}); |
|||
}); |
|||
// 将 HttpClient 注册为单例服务
|
|||
builder.Services.AddSingleton<HttpClient>(); |
|||
|
|||
builder.Services.AddSingleton<DataModel>(); |
|||
|
|||
#if DEBUG
|
|||
builder.Logging.AddDebug(); |
|||
#endif
|
|||
|
|||
return builder.Build(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
using CommunityToolkit.Mvvm.ComponentModel; |
|||
using SunlightAggregationTerminal.Class; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Data; |
|||
using System.Text; |
|||
|
|||
namespace SunlightAggregationTerminal.Models |
|||
{ |
|||
public class AppModels : ObservableObject |
|||
{ |
|||
|
|||
public static SqliteHelper sqliteHelper = SQLiteConfig.Config(Path.Combine(FileSystem.AppDataDirectory, "MyAppData.db"))!; //数据库连接路径(获取各平台的应用数据目录)
|
|||
|
|||
public AppModels() |
|||
{ |
|||
if(sqliteHelper != null) |
|||
{//获取配置信息
|
|||
sqliteHelper.Open(); |
|||
var userdata= sqliteHelper.ExecuteDataSet("select * from Users Where LogNo = 1", null); |
|||
sqliteHelper.Close(); |
|||
if (userdata != null) |
|||
{ |
|||
var dat = userdata.Tables[0].AsEnumerable().FirstOrDefault(); |
|||
if (dat != null) |
|||
{ |
|||
App.GlobalData.UserName = dat.Field<string>("UserName") ?? ""; |
|||
App.GlobalData.UserId = dat.Field<string>("UserId") ?? ""; |
|||
App.GlobalData.User = dat.Field<string>("User") ?? ""; |
|||
App.GlobalData.UserPassword = dat.Field<string>("UserPassword") ?? ""; |
|||
App.GlobalData.Enterprise = dat.Field<string>("Enterprise") ?? ""; |
|||
App.GlobalData.Department = dat.Field<string>("Department") ?? ""; |
|||
App.GlobalData.Groups = dat.Field<string>("Groups") ?? ""; |
|||
App.GlobalData.ServerID = dat.Field<string>("ServerID") ?? ""; |
|||
App.GlobalData.ProxyID = dat.Field<string>("ProxyID") ?? ""; |
|||
App.GlobalData.LogNo = Convert.ToBoolean(dat.Field<object>("LogNo")); |
|||
App.GlobalData.LocalAreaNetworkMode = Convert.ToBoolean(dat.Field<object>("LocalAreaNetworkMode")); |
|||
App.GlobalData.DarkMode = Convert.ToBoolean(dat.Field<object>("DarkMode")); |
|||
App.GlobalData.MessageNotificationMode = Convert.ToBoolean(dat.Field<object>("MessageNotificationMode")); |
|||
|
|||
TcpServer.Configuration(App.GlobalData.ServerID, App.GlobalData.User, App.GlobalData.UserPassword, dat.Field<string>("GUID") ?? "Not"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static void Updata(string sql) |
|||
{ |
|||
sqliteHelper.Open(); |
|||
sqliteHelper.ExecuteNonQuery(sql, null); |
|||
sqliteHelper.Close(); |
|||
} |
|||
|
|||
public static void INSERT(string sql) |
|||
{ |
|||
sqliteHelper.Open(); |
|||
sqliteHelper.ExecuteNonQuery(sql, null); |
|||
sqliteHelper.Close(); |
|||
} |
|||
|
|||
public static DataSet? Select(string sql) |
|||
{ |
|||
sqliteHelper.Open(); |
|||
var userdata = sqliteHelper.ExecuteDataSet(sql, null); |
|||
sqliteHelper.Close(); |
|||
|
|||
return userdata; |
|||
} |
|||
|
|||
public static string GetAppUniqueId() |
|||
{ |
|||
const string key = "sunlight_app_unique_id"; |
|||
|
|||
// 尝试从安全存储中读取
|
|||
string? id = SecureStorage.GetAsync(key).Result; |
|||
|
|||
if (string.IsNullOrEmpty(id)) |
|||
{ |
|||
// 如果不存在,生成一个新的 GUID
|
|||
id = Guid.NewGuid().ToString(); |
|||
// 保存到安全存储
|
|||
SecureStorage.SetAsync(key, id).Wait(); |
|||
} |
|||
|
|||
return id; |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using CommunityToolkit.Mvvm.ComponentModel; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
|
|||
namespace SunlightAggregationTerminal.Models |
|||
{ |
|||
#pragma warning disable CA1416
|
|||
public partial class DataModel : ObservableObject |
|||
{ |
|||
[ObservableProperty] |
|||
public partial string User { get; set; } |
|||
[ObservableProperty] |
|||
public partial string UserId { get; set; } |
|||
[ObservableProperty] |
|||
public partial string UserName { get; set; } |
|||
[ObservableProperty] |
|||
public partial string UserPassword { get; set; } |
|||
[ObservableProperty] |
|||
public partial string Enterprise { get; set; } |
|||
[ObservableProperty] |
|||
public partial string Department { get; set; } |
|||
[ObservableProperty] |
|||
public partial string ServerID { get; set; } |
|||
[ObservableProperty] |
|||
public partial string Groups { get; set; } |
|||
[ObservableProperty] |
|||
public partial string ProxyID { get; set; } |
|||
[ObservableProperty] |
|||
public partial bool LogNo { get; set; } |
|||
public bool IsNotLogNo => !LogNo; |
|||
[ObservableProperty] |
|||
public partial bool LocalAreaNetworkMode { get; set; } |
|||
[ObservableProperty] |
|||
public partial bool DarkMode { get; set; } |
|||
[ObservableProperty] |
|||
public partial bool MessageNotificationMode { get; set; } |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Data; |
|||
using System.Text; |
|||
using System.Linq; |
|||
|
|||
namespace SunlightAggregationTerminal.Models |
|||
{ |
|||
// 定义枚举
|
|||
public enum MsgType |
|||
{ |
|||
Notice, // 通知
|
|||
Message, // 信息
|
|||
System // 系统
|
|||
} |
|||
|
|||
// 定义显示用的模型
|
|||
public class NotificationItem |
|||
{ |
|||
public Int64 Id { get; set; } |
|||
public string? Title { get; set; } |
|||
public string? Content { get; set; } |
|||
public DateTime Time { get; set; } |
|||
public MsgType Type { get; set; } |
|||
} |
|||
|
|||
public static class DataService |
|||
{ |
|||
public static DataSet? data = AppModels.Select("select * from Notification Where Time > '" + DateTime.Now.AddDays(-30) + "'"); |
|||
|
|||
// 直接返回 List
|
|||
public static List<NotificationItem> _NotificationData = new List<NotificationItem>(); |
|||
public static List<NotificationItem> GetAllItems() |
|||
{ |
|||
_NotificationData.Clear(); |
|||
|
|||
if (data != null) |
|||
{ |
|||
foreach (DataRow dr in data.Tables[0].Rows) |
|||
{ |
|||
_NotificationData.Add(new NotificationItem |
|||
{ |
|||
Id = dr.Field<Int64>("Id"), |
|||
Title = dr.Field<string>("Title") , |
|||
Content = dr.Field<string>("Content"), |
|||
Time = DateTime.Parse(dr.Field<string>("Time")!), |
|||
Type = (MsgType)dr.Field<Int64>("Type") |
|||
}); |
|||
} |
|||
} |
|||
|
|||
// 倒序返回
|
|||
return _NotificationData.OrderByDescending(x => x.Time).ToList(); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.NotificationPage" |
|||
Loaded="ContentPage_Loaded" |
|||
Title="通知中心"> |
|||
<ScrollView> |
|||
<VerticalStackLayout Padding="20" Spacing="20"> |
|||
<!-- 通知卡片 --> |
|||
<Border BackgroundColor="White" |
|||
Stroke="#CCCCCC" |
|||
Margin="0,0,0,10" |
|||
StrokeShape="RoundRectangle 10"> |
|||
<Grid ColumnDefinitions="Auto,*,Auto" Padding="15" ColumnSpacing="15"> |
|||
<!-- 文字内容 --> |
|||
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center"> |
|||
<Label x:Name="NoticeItemTitle" FontAttributes="Bold" FontSize="22" TextColor="Black"/> |
|||
<Label x:Name="NoticeItemContent" FontSize="16" TextColor="Gray" LineBreakMode="WordWrap"/> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
<!-- 点击事件 --> |
|||
<Border.GestureRecognizers> |
|||
<TapGestureRecognizer Tapped="OnNoticeTapped"/> |
|||
</Border.GestureRecognizers> |
|||
</Border> |
|||
|
|||
<!-- 信息卡片 --> |
|||
<Border BackgroundColor="White" |
|||
Stroke="#CCCCCC" |
|||
Margin="0,0,0,10" |
|||
StrokeShape="RoundRectangle 10"> |
|||
<Grid ColumnDefinitions="Auto,*,Auto" Padding="15" ColumnSpacing="15"> |
|||
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center"> |
|||
<Label x:Name="MessageItemTitle" FontAttributes="Bold" FontSize="22" TextColor="Black"/> |
|||
<Label x:Name="MessageItemContent" FontSize="16" TextColor="Gray" LineBreakMode="WordWrap"/> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
<Border.GestureRecognizers> |
|||
<TapGestureRecognizer Tapped="OnMessageTapped"/> |
|||
</Border.GestureRecognizers> |
|||
</Border> |
|||
|
|||
<!-- 系统卡片 --> |
|||
<Border BackgroundColor="White" |
|||
Stroke="#CCCCCC" |
|||
Margin="0,0,0,10" |
|||
StrokeShape="RoundRectangle 10"> |
|||
<Grid ColumnDefinitions="Auto,*,Auto" Padding="15" ColumnSpacing="15"> |
|||
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center"> |
|||
<Label x:Name="SystemItemTitle" FontAttributes="Bold" FontSize="22" TextColor="Black"/> |
|||
<Label x:Name="SystemItemContent" FontSize="16" TextColor="Gray" LineBreakMode="WordWrap"/> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
<Border.GestureRecognizers> |
|||
<TapGestureRecognizer Tapped="OnSystemTapped"/> |
|||
</Border.GestureRecognizers> |
|||
</Border> |
|||
</VerticalStackLayout> |
|||
</ScrollView> |
|||
</ContentPage> |
|||
@ -0,0 +1,93 @@ |
|||
using SunlightAggregationTerminal.Models; |
|||
using System.Data; |
|||
using System.Linq; |
|||
|
|||
namespace SunlightAggregationTerminal; |
|||
|
|||
public partial class NotificationPage : ContentPage |
|||
{ |
|||
public NotificationItem NoticeItem { get; set; } = new NotificationItem(); |
|||
public NotificationItem MessageItem { get; set; } = new NotificationItem(); |
|||
public NotificationItem SystemItem { get; set; } = new NotificationItem(); |
|||
|
|||
public NotificationPage() |
|||
{ |
|||
InitializeComponent(); |
|||
this.BindingContext = this; |
|||
} |
|||
|
|||
private void ContentPage_Loaded(object sender, EventArgs e) |
|||
{ |
|||
LoadSummaryData(); |
|||
} |
|||
|
|||
private void LoadSummaryData() |
|||
{ |
|||
var allItems = DataService.GetAllItems(); |
|||
|
|||
// 筛选出 Type 为 Notice 的数据,并取第一条
|
|||
// 对应 DataTable 的 Select("Type = ...").First()
|
|||
var noticeItem = allItems.FirstOrDefault(x => x.Type == MsgType.Notice); |
|||
|
|||
// 读取数据 (注意判空,防止找不到数据时报错)
|
|||
if (noticeItem != null) |
|||
{ |
|||
NoticeItemTitle.Text = noticeItem.Title; |
|||
NoticeItemContent.Text = noticeItem.Content; |
|||
} |
|||
else |
|||
{ |
|||
// 处理没有找到数据的情况
|
|||
NoticeItemTitle.Text = "暂无通知"; |
|||
NoticeItemContent.Text = "通知"; |
|||
} |
|||
|
|||
var messageItem = allItems.FirstOrDefault(x => x.Type == MsgType.Message); |
|||
|
|||
// 读取数据 (注意判空,防止找不到数据时报错)
|
|||
if (messageItem != null) |
|||
{ |
|||
MessageItemTitle.Text = messageItem.Title; |
|||
MessageItemContent.Text = messageItem.Content; |
|||
} |
|||
else |
|||
{ |
|||
// 处理没有找到数据的情况
|
|||
MessageItemTitle.Text = "暂无通知"; |
|||
MessageItemContent.Text = "信息"; |
|||
} |
|||
var systemItem = allItems.FirstOrDefault(x => x.Type == MsgType.System); |
|||
|
|||
// 读取数据 (注意判空,防止找不到数据时报错)
|
|||
if (systemItem != null) |
|||
{ |
|||
SystemItemTitle.Text = systemItem.Title; |
|||
SystemItemContent.Text = systemItem.Content; |
|||
} |
|||
else |
|||
{ |
|||
// 处理没有找到数据的情况
|
|||
SystemItemTitle.Text = "暂无通知"; |
|||
SystemItemContent.Text = "系统信息"; |
|||
} |
|||
|
|||
} |
|||
|
|||
// 点击跳转到独立页面
|
|||
private async void OnNoticeTapped(object sender, TappedEventArgs e) |
|||
{ |
|||
await Navigation.PushAsync(new NotificationView.NoticePage()); |
|||
} |
|||
|
|||
private async void OnMessageTapped(object sender, TappedEventArgs e) |
|||
{ |
|||
await Navigation.PushAsync(new NotificationView.MessagePage()); |
|||
} |
|||
|
|||
private async void OnSystemTapped(object sender, TappedEventArgs e) |
|||
{ |
|||
await Navigation.PushAsync(new NotificationView.SystemPage()); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.NotificationView.MessagePage" |
|||
Title="信息"> |
|||
<CollectionView x:Name="CardCollectionView" |
|||
ItemsSource="{Binding MessageItems}" |
|||
RemainingItemsThreshold="5" |
|||
RemainingItemsThresholdReached="CardCollectionView_RemainingItemsThresholdReached"> |
|||
<!-- 保持滚动条 --> |
|||
<CollectionView.ItemTemplate> |
|||
<DataTemplate> |
|||
<!-- 这里定义单个卡片的 UI 结构 --> |
|||
<Border BackgroundColor="White" |
|||
Stroke="#CCCCCC" |
|||
StrokeThickness="1" |
|||
Margin="10,0,10,10" |
|||
StrokeShape="RoundRectangle 10"> |
|||
<Grid Padding="15"> |
|||
<VerticalStackLayout> |
|||
<Label Text="{Binding Title}" |
|||
FontAttributes="Bold" |
|||
FontSize="22" |
|||
TextColor="Black"/> |
|||
<Label Text="{Binding Time}" |
|||
FontSize="14" |
|||
TextColor="Black" |
|||
LineBreakMode="WordWrap"/> |
|||
<Label Text="{Binding Content}" |
|||
FontSize="16" |
|||
TextColor="Gray" |
|||
LineBreakMode="WordWrap"/> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
</DataTemplate> |
|||
</CollectionView.ItemTemplate> |
|||
</CollectionView> |
|||
</ContentPage> |
|||
@ -0,0 +1,42 @@ |
|||
using Microsoft.Maui.Controls.Shapes; |
|||
using SunlightAggregationTerminal.Models; |
|||
using System.Collections.ObjectModel; |
|||
|
|||
namespace SunlightAggregationTerminal.NotificationView; |
|||
|
|||
public partial class MessagePage : ContentPage |
|||
{ |
|||
public ObservableCollection<NotificationItem> MessageItems { get; set; } = new(); |
|||
|
|||
public MessagePage() |
|||
{ |
|||
InitializeComponent(); |
|||
this.BindingContext = this; |
|||
LoadData(); // 加载数据
|
|||
} |
|||
|
|||
private void LoadData() |
|||
{ |
|||
// 假设这是你获取数据的地方
|
|||
var allData = DataService._NotificationData; |
|||
if (allData != null) |
|||
{ |
|||
// 清空旧数据
|
|||
MessageItems.Clear(); |
|||
|
|||
// 按时间倒序,并只取最新的 N 条(例如 50 条)
|
|||
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.Message); |
|||
|
|||
// 将数据添加到集合中,UI 会自动更新
|
|||
foreach (var item in itemsToShow) |
|||
{ |
|||
MessageItems.Add(item); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.NotificationView.NoticePage" |
|||
Title="通知"> |
|||
<CollectionView x:Name="CardCollectionView" |
|||
ItemsSource="{Binding NoticeItems}" |
|||
RemainingItemsThreshold="5" |
|||
RemainingItemsThresholdReached="CardCollectionView_RemainingItemsThresholdReached"> |
|||
<!-- 保持滚动条 --> |
|||
<CollectionView.ItemTemplate> |
|||
<DataTemplate> |
|||
<!-- 这里定义单个卡片的 UI 结构 --> |
|||
<Border BackgroundColor="White" |
|||
Stroke="#CCCCCC" |
|||
StrokeThickness="1" |
|||
Margin="10,0,10,10" |
|||
StrokeShape="RoundRectangle 10"> |
|||
<Grid Padding="15"> |
|||
<VerticalStackLayout> |
|||
<Label Text="{Binding Title}" |
|||
FontAttributes="Bold" |
|||
FontSize="22" |
|||
TextColor="Black"/> |
|||
<Label Text="{Binding Time}" |
|||
FontSize="14" |
|||
TextColor="Black" |
|||
LineBreakMode="WordWrap"/> |
|||
<Label Text="{Binding Content}" |
|||
FontSize="16" |
|||
TextColor="Gray" |
|||
LineBreakMode="WordWrap"/> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
</DataTemplate> |
|||
</CollectionView.ItemTemplate> |
|||
</CollectionView> |
|||
</ContentPage> |
|||
@ -0,0 +1,43 @@ |
|||
using Microsoft.Maui.Controls.Shapes; |
|||
using SunlightAggregationTerminal.Models; |
|||
using System.Collections.ObjectModel; |
|||
using System.Data; |
|||
|
|||
namespace SunlightAggregationTerminal.NotificationView; |
|||
|
|||
public partial class NoticePage : ContentPage |
|||
{ |
|||
public ObservableCollection<NotificationItem> NoticeItems { get; set; } = new(); |
|||
public NoticePage() |
|||
{ |
|||
InitializeComponent(); |
|||
this.BindingContext = this; |
|||
LoadData(); // 加载数据
|
|||
} |
|||
|
|||
private void LoadData() |
|||
{ |
|||
// 假设这是你获取数据的地方
|
|||
var allData = DataService._NotificationData; |
|||
if (allData != null) |
|||
{ |
|||
// 清空旧数据
|
|||
NoticeItems.Clear(); |
|||
|
|||
// 按时间倒序,并只取最新的 N 条(例如 50 条)
|
|||
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.Notice); |
|||
|
|||
// 将数据添加到集合中,UI 会自动更新
|
|||
foreach (var item in itemsToShow) |
|||
{ |
|||
NoticeItems.Add(item); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.NotificationView.SystemPage" |
|||
Title="系统信息"> |
|||
<CollectionView x:Name="CardCollectionView" |
|||
ItemsSource="{Binding SystemItems}" |
|||
RemainingItemsThreshold="5" |
|||
RemainingItemsThresholdReached="CardCollectionView_RemainingItemsThresholdReached"> |
|||
<!-- 保持滚动条 --> |
|||
<CollectionView.ItemTemplate> |
|||
<DataTemplate> |
|||
<!-- 这里定义单个卡片的 UI 结构 --> |
|||
<Border BackgroundColor="White" |
|||
Stroke="#CCCCCC" |
|||
StrokeThickness="1" |
|||
Margin="10,0,10,10" |
|||
StrokeShape="RoundRectangle 10"> |
|||
<Grid Padding="15"> |
|||
<VerticalStackLayout> |
|||
<Label Text="{Binding Title}" |
|||
FontAttributes="Bold" |
|||
FontSize="22" |
|||
TextColor="Black"/> |
|||
<Label Text="{Binding Time}" |
|||
FontSize="14" |
|||
TextColor="Black" |
|||
LineBreakMode="WordWrap"/> |
|||
<Label Text="{Binding Content}" |
|||
FontSize="16" |
|||
TextColor="Gray" |
|||
LineBreakMode="WordWrap"/> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
</DataTemplate> |
|||
</CollectionView.ItemTemplate> |
|||
</CollectionView> |
|||
</ContentPage> |
|||
@ -0,0 +1,42 @@ |
|||
using Microsoft.Maui.Controls.Shapes; |
|||
using SunlightAggregationTerminal.Models; |
|||
using System.Collections.ObjectModel; |
|||
|
|||
namespace SunlightAggregationTerminal.NotificationView; |
|||
|
|||
public partial class SystemPage : ContentPage |
|||
{ |
|||
public ObservableCollection<NotificationItem> SystemItems { get; set; } = new(); |
|||
public SystemPage() |
|||
{ |
|||
InitializeComponent(); |
|||
this.BindingContext = this; |
|||
LoadData(); // 加载数据
|
|||
} |
|||
|
|||
private void LoadData() |
|||
{ |
|||
// 假设这是你获取数据的地方
|
|||
var allData = DataService._NotificationData; |
|||
if (allData != null) |
|||
{ |
|||
// 清空旧数据
|
|||
SystemItems.Clear(); |
|||
|
|||
// 按时间倒序,并只取最新的 N 条(例如 50 条)
|
|||
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.System); |
|||
|
|||
// 将数据添加到集合中,UI 会自动更新
|
|||
foreach (var item in itemsToShow) |
|||
{ |
|||
SystemItems.Add(item); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true"></application> |
|||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
|||
<uses-permission android:name="android.permission.INTERNET" /> |
|||
<uses-permission android:name="android.permission.CAMERA" /> |
|||
</manifest> |
|||
@ -0,0 +1,11 @@ |
|||
using Android.App; |
|||
using Android.Content.PM; |
|||
using Android.OS; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] |
|||
public class MainActivity : MauiAppCompatActivity |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using Android.App; |
|||
using Android.Runtime; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
[Application(UsesCleartextTraffic = true)] |
|||
public class MainApplication : MauiApplication |
|||
{ |
|||
public MainApplication(IntPtr handle, JniHandleOwnership ownership) |
|||
: base(handle, ownership) |
|||
{ |
|||
} |
|||
|
|||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<resources> |
|||
<color name="colorPrimary">#512BD4</color> |
|||
<color name="colorPrimaryDark">#2B0B98</color> |
|||
<color name="colorAccent">#2B0B98</color> |
|||
</resources> |
|||
@ -0,0 +1,10 @@ |
|||
using Foundation; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
[Register("AppDelegate")] |
|||
public class AppDelegate : MauiUIApplicationDelegate |
|||
{ |
|||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.--> |
|||
<dict> |
|||
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. --> |
|||
<key>com.apple.security.app-sandbox</key> |
|||
<true/> |
|||
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. --> |
|||
<key>com.apple.security.network.client</key> |
|||
<true/> |
|||
</dict> |
|||
</plist> |
|||
|
|||
@ -0,0 +1,40 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<!-- The Mac App Store requires you specify if the app uses encryption. --> |
|||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption --> |
|||
<!-- <key>ITSAppUsesNonExemptEncryption</key> --> |
|||
<!-- Please indicate <true/> or <false/> here. --> |
|||
|
|||
<!-- Specify the category for your app here. --> |
|||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype --> |
|||
<!-- <key>LSApplicationCategoryType</key> --> |
|||
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> --> |
|||
<key>UIDeviceFamily</key> |
|||
<array> |
|||
<integer>2</integer> |
|||
</array> |
|||
<key>LSApplicationCategoryType</key> |
|||
<string>public.app-category.lifestyle</string> |
|||
<key>UIRequiredDeviceCapabilities</key> |
|||
<array> |
|||
<string>arm64</string> |
|||
</array> |
|||
<key>UISupportedInterfaceOrientations</key> |
|||
<array> |
|||
<string>UIInterfaceOrientationPortrait</string> |
|||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|||
<string>UIInterfaceOrientationLandscapeRight</string> |
|||
</array> |
|||
<key>UISupportedInterfaceOrientations~ipad</key> |
|||
<array> |
|||
<string>UIInterfaceOrientationPortrait</string> |
|||
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
|||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|||
<string>UIInterfaceOrientationLandscapeRight</string> |
|||
</array> |
|||
<key>XSAppIconAssets</key> |
|||
<string>Assets.xcassets/appicon.appiconset</string> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,16 @@ |
|||
using ObjCRuntime; |
|||
using UIKit; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
public class Program |
|||
{ |
|||
// This is the main entry point of the application.
|
|||
static void Main(string[] args) |
|||
{ |
|||
// if you want to use a different Application Delegate class from "AppDelegate"
|
|||
// you can specify it here.
|
|||
UIApplication.Main(args, null, typeof(AppDelegate)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
<maui:MauiWinUIApplication |
|||
x:Class="SunlightAggregationTerminal.WinUI.App" |
|||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:maui="using:Microsoft.Maui" |
|||
xmlns:local="using:SunlightAggregationTerminal.WinUI"> |
|||
|
|||
</maui:MauiWinUIApplication> |
|||
@ -0,0 +1,25 @@ |
|||
using Microsoft.UI.Xaml; |
|||
|
|||
// To learn more about WinUI, the WinUI project structure,
|
|||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
|||
|
|||
namespace SunlightAggregationTerminal.WinUI |
|||
{ |
|||
/// <summary>
|
|||
/// Provides application-specific behavior to supplement the default Application class.
|
|||
/// </summary>
|
|||
public partial class App : MauiWinUIApplication |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes the singleton application object. This is the first line of authored code
|
|||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
|||
/// </summary>
|
|||
public App() |
|||
{ |
|||
this.InitializeComponent(); |
|||
} |
|||
|
|||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Package |
|||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" |
|||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" |
|||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" |
|||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" |
|||
IgnorableNamespaces="uap rescap"> |
|||
|
|||
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" /> |
|||
|
|||
<mp:PhoneIdentity PhoneProductId="40C4D887-7034-46F6-A7C2-185E7FC94FC4" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> |
|||
|
|||
<Properties> |
|||
<DisplayName>$placeholder$</DisplayName> |
|||
<PublisherDisplayName>User Name</PublisherDisplayName> |
|||
<Logo>$placeholder$.png</Logo> |
|||
</Properties> |
|||
|
|||
<Dependencies> |
|||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> |
|||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> |
|||
</Dependencies> |
|||
|
|||
<Resources> |
|||
<Resource Language="x-generate" /> |
|||
</Resources> |
|||
|
|||
<Applications> |
|||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"> |
|||
<uap:VisualElements |
|||
DisplayName="$placeholder$" |
|||
Description="$placeholder$" |
|||
Square150x150Logo="$placeholder$.png" |
|||
Square44x44Logo="$placeholder$.png" |
|||
BackgroundColor="transparent"> |
|||
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" /> |
|||
<uap:SplashScreen Image="$placeholder$.png" /> |
|||
</uap:VisualElements> |
|||
</Application> |
|||
</Applications> |
|||
|
|||
<Capabilities> |
|||
<rescap:Capability Name="runFullTrust" /> |
|||
</Capabilities> |
|||
|
|||
</Package> |
|||
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
|||
<assemblyIdentity version="1.0.0.0" name="SunlightAggregationTerminal.WinUI.app"/> |
|||
|
|||
<application xmlns="urn:schemas-microsoft-com:asm.v3"> |
|||
<windowsSettings> |
|||
<!-- The combination of below two tags have the following effect: |
|||
1) Per-Monitor for >= Windows 10 Anniversary Update |
|||
2) System < Windows 10 Anniversary Update |
|||
--> |
|||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware> |
|||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness> |
|||
|
|||
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> |
|||
</windowsSettings> |
|||
</application> |
|||
</assembly> |
|||
@ -0,0 +1,10 @@ |
|||
using Foundation; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
[Register("AppDelegate")] |
|||
public class AppDelegate : MauiUIApplicationDelegate |
|||
{ |
|||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>LSRequiresIPhoneOS</key> |
|||
<true/> |
|||
<key>UIDeviceFamily</key> |
|||
<array> |
|||
<integer>1</integer> |
|||
<integer>2</integer> |
|||
</array> |
|||
<key>UIRequiredDeviceCapabilities</key> |
|||
<array> |
|||
<string>arm64</string> |
|||
</array> |
|||
<key>UISupportedInterfaceOrientations</key> |
|||
<array> |
|||
<string>UIInterfaceOrientationPortrait</string> |
|||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|||
<string>UIInterfaceOrientationLandscapeRight</string> |
|||
</array> |
|||
<key>UISupportedInterfaceOrientations~ipad</key> |
|||
<array> |
|||
<string>UIInterfaceOrientationPortrait</string> |
|||
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
|||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|||
<string>UIInterfaceOrientationLandscapeRight</string> |
|||
</array> |
|||
<key>XSAppIconAssets</key> |
|||
<string>Assets.xcassets/appicon.appiconset</string> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,16 @@ |
|||
using ObjCRuntime; |
|||
using UIKit; |
|||
|
|||
namespace SunlightAggregationTerminal |
|||
{ |
|||
public class Program |
|||
{ |
|||
// This is the main entry point of the application.
|
|||
static void Main(string[] args) |
|||
{ |
|||
// if you want to use a different Application Delegate class from "AppDelegate"
|
|||
// you can specify it here.
|
|||
UIApplication.Main(args, null, typeof(AppDelegate)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
This is the minimum required version of the Apple Privacy Manifest for .NET MAUI apps. |
|||
The contents below are needed because of APIs that are used in the .NET framework and .NET MAUI SDK. |
|||
|
|||
You are responsible for adding extra entries as needed for your application. |
|||
|
|||
More information: https://aka.ms/maui-privacy-manifest |
|||
--> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>NSPrivacyAccessedAPITypes</key> |
|||
<array> |
|||
<dict> |
|||
<key>NSPrivacyAccessedAPIType</key> |
|||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string> |
|||
<key>NSPrivacyAccessedAPITypeReasons</key> |
|||
<array> |
|||
<string>C617.1</string> |
|||
</array> |
|||
</dict> |
|||
<dict> |
|||
<key>NSPrivacyAccessedAPIType</key> |
|||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string> |
|||
<key>NSPrivacyAccessedAPITypeReasons</key> |
|||
<array> |
|||
<string>35F9.1</string> |
|||
</array> |
|||
</dict> |
|||
<dict> |
|||
<key>NSPrivacyAccessedAPIType</key> |
|||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string> |
|||
<key>NSPrivacyAccessedAPITypeReasons</key> |
|||
<array> |
|||
<string>E174.1</string> |
|||
</array> |
|||
</dict> |
|||
<!-- |
|||
The entry below is only needed when you're using the Preferences API in your app. |
|||
<dict> |
|||
<key>NSPrivacyAccessedAPIType</key> |
|||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string> |
|||
<key>NSPrivacyAccessedAPITypeReasons</key> |
|||
<array> |
|||
<string>CA92.1</string> |
|||
</array> |
|||
</dict> --> |
|||
</array> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,224 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.ProfilePage" |
|||
Title=""> |
|||
<Grid RowDefinitions="Auto, *" |
|||
ColumnDefinitions="*, Auto" |
|||
BackgroundColor="#F5F5F5"> |
|||
<!-- 顶部个人信息区 --> |
|||
<Border Padding="20" |
|||
Grid.Row="0" |
|||
Grid.Column="0" > |
|||
<Grid RowDefinitions="Auto, *" |
|||
ColumnDefinitions="*, Auto"> |
|||
<HorizontalStackLayout VerticalOptions="Center" Spacing="15"> |
|||
<!-- 信息 --> |
|||
<VerticalStackLayout Grid.Row="0" Grid.Column="0" |
|||
VerticalOptions="Center"> |
|||
<Label Text="{Binding UserName}" |
|||
FontSize="26" |
|||
FontAttributes="Bold" |
|||
TextColor="Black" /> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="ID:" FontSize="12" TextColor="Gray" Margin="0,0,0,0"/> |
|||
<Label Text="{Binding UserId}" FontSize="12" TextColor="Gray" Margin="0,0,0,0"/> |
|||
</HorizontalStackLayout> |
|||
</VerticalStackLayout> |
|||
</HorizontalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<ScrollView Grid.Row="1" Grid.Column="0"> |
|||
<VerticalStackLayout Spacing="0" Padding="0"> |
|||
<Border BackgroundColor="White" Stroke="#CCCCCC" Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
|||
<Grid> |
|||
<VerticalStackLayout Spacing="0" Padding="0"> |
|||
<Label Text="管理" FontSize="12" TextColor="Gray" Margin="15,5,0,5" /> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0" /> |
|||
|
|||
<VerticalStackLayout> |
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="公司:" VerticalOptions="Center" /> |
|||
<Label Text="{Binding Enterprise}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
</ContentView> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
|||
|
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="部门:" VerticalOptions="Center" /> |
|||
<Label Text="{Binding Department}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
</ContentView> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
|||
|
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="组:" VerticalOptions="Center" /> |
|||
<Label Text="{Binding Groups}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
</ContentView> |
|||
</VerticalStackLayout> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
<!-- 账号与安全 --> |
|||
<Border BackgroundColor="White" Stroke="#CCCCCC" Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
|||
<Grid> |
|||
<VerticalStackLayout Spacing="0" Padding="0"> |
|||
<Label Text="账号" FontSize="12" TextColor="Gray" Margin="15,5,0,5" /> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0" /> |
|||
|
|||
<VerticalStackLayout> |
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="账号:" VerticalOptions="Center" /> |
|||
<Label Text="{Binding User}" TextColor="Gray" |
|||
VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
</ContentView> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
|||
|
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<Grid> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="姓名:" VerticalOptions="Center" /> |
|||
<Label Text="{Binding UserName}" TextColor="Gray" |
|||
VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
<Label Text=">" TextColor="Gray" |
|||
VerticalOptions="Center" HorizontalOptions="End" |
|||
Margin="0,0,10,0" FontSize="24"/> |
|||
</Grid> |
|||
<ContentView.GestureRecognizers> |
|||
<TapGestureRecognizer Tapped="UserName_Tapped"/> |
|||
</ContentView.GestureRecognizers> |
|||
</ContentView> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<Grid> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="密码:" VerticalOptions="Center" /> |
|||
<Label Text="******" TextColor="Gray" |
|||
VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
<Label Text=">" TextColor="Gray" |
|||
VerticalOptions="Center" HorizontalOptions="End" |
|||
Margin="0,0,10,0" FontSize="24"/> |
|||
</Grid> |
|||
<ContentView.GestureRecognizers> |
|||
<TapGestureRecognizer Tapped="UserPassword_Tapped"/> |
|||
</ContentView.GestureRecognizers> |
|||
</ContentView> |
|||
</VerticalStackLayout> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<!-- 通用设置 --> |
|||
<Border BackgroundColor="White" Stroke="#CCCCCC" |
|||
Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
|||
<Grid> |
|||
<VerticalStackLayout Spacing="0" Padding="0"> |
|||
<Label Text="通用" FontSize="12" |
|||
TextColor="Gray" Margin="15,10,0,5" /> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" /> |
|||
<VerticalStackLayout> |
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<Grid> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="空间清理" VerticalOptions="Center"/> |
|||
<Label Text="" TextColor="Gray" |
|||
VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
<Label Text=">" TextColor="Gray" |
|||
VerticalOptions="Center" HorizontalOptions="End" |
|||
Margin="0,0,10,0" FontSize="24"/> |
|||
</Grid> |
|||
</ContentView> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
|||
<ContentView HeightRequest="40" Padding="15,0"> |
|||
<Grid VerticalOptions="Center"> |
|||
<Label Text="消息通知" VerticalOptions="Center" /> |
|||
<Switch IsToggled="{Binding MessageNotificationMode}" HorizontalOptions="End" |
|||
Toggled="MessageNotificationMode_Toggled" VerticalOptions="Center" /> |
|||
</Grid> |
|||
</ContentView> |
|||
<ContentView HeightRequest="40" Padding="15,0"> |
|||
<Grid VerticalOptions="Center"> |
|||
<Label Text="深色模式" VerticalOptions="Center"/> |
|||
<Switch IsToggled="{Binding DarkMode}" HorizontalOptions="End" |
|||
Toggled="DarkMode_Toggled" VerticalOptions="Center"/> |
|||
</Grid> |
|||
</ContentView> |
|||
|
|||
</VerticalStackLayout> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0,0,0,0" /> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<!-- 连接设置 --> |
|||
<Border BackgroundColor="White" Stroke="#CCCCCC" Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
|||
<Grid > |
|||
<VerticalStackLayout Spacing="0" Padding="0"> |
|||
<Label Text="连接" FontSize="12" TextColor="Gray" Margin="15,10,0,5" /> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" /> |
|||
<VerticalStackLayout> |
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<Grid> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="服务器:" VerticalOptions="Center" /> |
|||
<Label Text="{Binding ServerID}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
<Label Text=">" TextColor="Gray" VerticalOptions="Center" HorizontalOptions="End" |
|||
Margin="0,0,10,0" FontSize="24"/> |
|||
</Grid> |
|||
<ContentView.GestureRecognizers> |
|||
<TapGestureRecognizer Tapped="ServerID_Tapped"/> |
|||
</ContentView.GestureRecognizers> |
|||
</ContentView> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
|||
<ContentView HeightRequest="50" Padding="15,0"> |
|||
<Grid> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Label Text="代理:" VerticalOptions="Center" /> |
|||
<Label Text="{Binding ProxyID}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
|||
</HorizontalStackLayout> |
|||
<Label Text=">" TextColor="Gray" VerticalOptions="Center" HorizontalOptions="End" |
|||
Margin="0,0,10,0" FontSize="24"/> |
|||
</Grid> |
|||
<ContentView.GestureRecognizers> |
|||
<TapGestureRecognizer Tapped="ProxyID_Tapped"/> |
|||
</ContentView.GestureRecognizers> |
|||
</ContentView> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
|||
<ContentView HeightRequest="40" Padding="15,0"> |
|||
<Grid VerticalOptions="Center"> |
|||
<Label Text="内网直连" VerticalOptions="Center" /> |
|||
<Switch IsToggled="{Binding LocalAreaNetworkMode}" HorizontalOptions="End" |
|||
Toggled="LocalAreaNetworkMode_Toggled" VerticalOptions="Center"/> |
|||
</Grid> |
|||
</ContentView> |
|||
</VerticalStackLayout> |
|||
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0,0,0,0" /> |
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<!-- 退出登录 --> |
|||
<Button x:Name="Out_Button" |
|||
Text="退出登录" |
|||
BackgroundColor="White" |
|||
TextColor="Red" |
|||
BorderColor="Red" |
|||
BorderWidth="1" |
|||
Margin="20, 30" |
|||
CornerRadius="8" |
|||
Clicked="Out_Clicked" /> |
|||
</VerticalStackLayout> |
|||
</ScrollView> |
|||
</Grid> |
|||
</ContentPage> |
|||
@ -0,0 +1,97 @@ |
|||
using CommunityToolkit.Mvvm.ComponentModel; |
|||
using SunlightAggregationTerminal.Models; |
|||
using SunlightAggregationTerminal.View; |
|||
using System.Collections.ObjectModel; |
|||
|
|||
namespace SunlightAggregationTerminal; |
|||
|
|||
public partial class ProfilePage : ContentPage |
|||
{ |
|||
public ProfilePage() |
|||
{ |
|||
InitializeComponent(); |
|||
this.BindingContext = App.GlobalData; |
|||
} |
|||
|
|||
private async void Out_Clicked(object sender, EventArgs e) |
|||
{ |
|||
bool shouldExit = await DisplayAlertAsync("退出确认", "确定要退出吗?", "是", "否"); |
|||
if (shouldExit) |
|||
{ |
|||
App.GlobalData.LogNo = false; |
|||
var logpage = new View.LogPage(); |
|||
await Navigation.PushModalAsync(logpage); |
|||
} |
|||
} |
|||
|
|||
private async void UserName_Tapped(object sender, TappedEventArgs e) |
|||
{ |
|||
string result = await DisplayPromptAsync("","姓名"); |
|||
|
|||
// 处理结果
|
|||
if (!string.IsNullOrWhiteSpace(result)) |
|||
{ |
|||
App.GlobalData.UserName=result; |
|||
string sql = @"UPDATE Users SET UserName = '" + App.GlobalData.UserName |
|||
+ "' WHERE User='" + App.GlobalData.User + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
} |
|||
private async void UserPassword_Tapped(object sender, TappedEventArgs e) |
|||
{ |
|||
string result = await DisplayPromptAsync("", "密码"); |
|||
|
|||
// 处理结果
|
|||
if (!string.IsNullOrWhiteSpace(result)) |
|||
{ |
|||
App.GlobalData.UserPassword = result; |
|||
string sql = @"UPDATE Users SET UserPassword = '" + App.GlobalData.UserPassword |
|||
+ "' WHERE User='" + App.GlobalData.User + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
} |
|||
private async void ServerID_Tapped(object sender, TappedEventArgs e) |
|||
{ |
|||
string result = await DisplayPromptAsync("", "服务器地址"); |
|||
|
|||
// 处理结果
|
|||
if (!string.IsNullOrWhiteSpace(result)) |
|||
{ |
|||
App.GlobalData.ServerID = result; |
|||
string sql = @"UPDATE Users SET ServerID = '" + App.GlobalData.ServerID |
|||
+ "' WHERE User='" + App.GlobalData.User + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
} |
|||
private async void ProxyID_Tapped(object sender, TappedEventArgs e) |
|||
{ |
|||
string result = await DisplayPromptAsync("", "代理"); |
|||
|
|||
// 处理结果
|
|||
if (!string.IsNullOrWhiteSpace(result)) |
|||
{ |
|||
App.GlobalData.ProxyID = result; |
|||
string sql = @"UPDATE Users SET ProxyID = '" + App.GlobalData.ProxyID |
|||
+ "' WHERE User='" + App.GlobalData.User + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
} |
|||
private void MessageNotificationMode_Toggled(object sender, ToggledEventArgs e) |
|||
{ |
|||
string sql = @"UPDATE Users SET MessageNotificationMode = "+ App.GlobalData.MessageNotificationMode |
|||
+ " WHERE User='" + App.GlobalData.User + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
private void DarkMode_Toggled(object sender, ToggledEventArgs e) |
|||
{ |
|||
string sql = @"UPDATE Users SET DarkMode = " + App.GlobalData.DarkMode |
|||
+ " WHERE User='" + App.GlobalData.User + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
private void LocalAreaNetworkMode_Toggled(object sender, ToggledEventArgs e) |
|||
{ |
|||
string sql = @"UPDATE Users SET LocalAreaNetworkMode = " + App.GlobalData.LocalAreaNetworkMode |
|||
+ " WHERE User='" + App.GlobalData.User + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"profiles": { |
|||
"Windows Machine": { |
|||
"commandName": "Project", |
|||
"nativeDebugging": false |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.QueryPage" |
|||
Title=""> |
|||
<Grid RowDefinitions="Auto, *" ColumnDefinitions="*, Auto"> |
|||
<Border Grid.Row="0" |
|||
Grid.Column="0" |
|||
Stroke="#CCCCCC" |
|||
StrokeThickness="1" |
|||
StrokeShape="RoundRectangle 10" |
|||
BackgroundColor="White" |
|||
Padding="0,0" |
|||
VerticalOptions="Center" |
|||
Margin="10,10,0,10"> |
|||
<Entry x:Name="ResultEntry" |
|||
Grid.Row="0" |
|||
Grid.Column="0" |
|||
FontSize="Medium" |
|||
Placeholder="等待扫码..." |
|||
VerticalOptions="Center" |
|||
BackgroundColor="Transparent" |
|||
Margin="0,0,0,0" > |
|||
</Entry> |
|||
</Border> |
|||
<!--扫码按钮--> |
|||
<Button Grid.Row="0" |
|||
Grid.Column="1" |
|||
Clicked="OnScanButtonClicked" |
|||
BackgroundColor="Transparent" |
|||
WidthRequest="60" |
|||
HeightRequest="60" |
|||
Margin="10"> |
|||
<Button.ImageSource> |
|||
<!-- 设置图标 --> |
|||
<FileImageSource File="lucidescanline.png" /> |
|||
</Button.ImageSource> |
|||
</Button> |
|||
<VerticalStackLayout> |
|||
|
|||
</VerticalStackLayout> |
|||
</Grid> |
|||
</ContentPage> |
|||
@ -0,0 +1,35 @@ |
|||
using CommunityToolkit.Mvvm.Messaging; |
|||
|
|||
namespace SunlightAggregationTerminal; |
|||
|
|||
public partial class QueryPage : ContentPage |
|||
{ |
|||
public QueryPage() |
|||
{ |
|||
InitializeComponent(); |
|||
|
|||
WeakReferenceMessenger.Default.Register<string>(this, (r, scannedValue) => |
|||
{ |
|||
ResultEntry.Text = scannedValue; |
|||
}); |
|||
} |
|||
private async void OnScanButtonClicked(object sender, EventArgs e) |
|||
{ |
|||
// 跳转到扫码页面
|
|||
await Navigation.PushAsync(new ScanPage(0)); |
|||
} |
|||
|
|||
// 处理“回车/完成”按钮点击
|
|||
/* private void OnEntryCompleted() |
|||
{ |
|||
string inputText = ResultEntry.Text; |
|||
|
|||
if (!string.IsNullOrWhiteSpace(inputText)) |
|||
{ |
|||
// 在这里处理用户手动输入的内容
|
|||
// 例如:验证格式、跳转页面、或者搜索商品
|
|||
//DisplayAlert("提示", $"你输入了: {inputText}", "确定");
|
|||
} |
|||
}*/ |
|||
|
|||
} |
|||
|
After Width: | Height: | Size: 228 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 90 KiB |
@ -0,0 +1,15 @@ |
|||
Any raw assets you want to be deployed with your application can be placed in |
|||
this directory (and child directories). Deployment of the asset to your application |
|||
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. |
|||
|
|||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> |
|||
|
|||
These files will be deployed with your package and will be accessible using Essentials: |
|||
|
|||
async Task LoadMauiAsset() |
|||
{ |
|||
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); |
|||
using var reader = new StreamReader(stream); |
|||
|
|||
var contents = reader.ReadToEnd(); |
|||
} |
|||
|
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,44 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<ResourceDictionary |
|||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> |
|||
|
|||
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml --> |
|||
|
|||
<Color x:Key="Primary">#512BD4</Color> |
|||
<Color x:Key="PrimaryDark">#ac99ea</Color> |
|||
<Color x:Key="PrimaryDarkText">#242424</Color> |
|||
<Color x:Key="Secondary">#DFD8F7</Color> |
|||
<Color x:Key="SecondaryDarkText">#9880e5</Color> |
|||
<Color x:Key="Tertiary">#2B0B98</Color> |
|||
|
|||
<Color x:Key="White">White</Color> |
|||
<Color x:Key="Black">Black</Color> |
|||
<Color x:Key="Magenta">#D600AA</Color> |
|||
<Color x:Key="MidnightBlue">#190649</Color> |
|||
<Color x:Key="OffBlack">#1f1f1f</Color> |
|||
|
|||
<Color x:Key="Gray100">#E1E1E1</Color> |
|||
<Color x:Key="Gray200">#C8C8C8</Color> |
|||
<Color x:Key="Gray300">#ACACAC</Color> |
|||
<Color x:Key="Gray400">#919191</Color> |
|||
<Color x:Key="Gray500">#6E6E6E</Color> |
|||
<Color x:Key="Gray600">#404040</Color> |
|||
<Color x:Key="Gray900">#212121</Color> |
|||
<Color x:Key="Gray950">#141414</Color> |
|||
|
|||
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/> |
|||
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/> |
|||
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/> |
|||
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/> |
|||
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/> |
|||
|
|||
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/> |
|||
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/> |
|||
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/> |
|||
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/> |
|||
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/> |
|||
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/> |
|||
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/> |
|||
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/> |
|||
</ResourceDictionary> |
|||
@ -0,0 +1,434 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<ResourceDictionary |
|||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> |
|||
|
|||
<Style TargetType="ActivityIndicator"> |
|||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="IndicatorView"> |
|||
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/> |
|||
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/> |
|||
</Style> |
|||
|
|||
<Style TargetType="Border"> |
|||
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
|||
<Setter Property="StrokeShape" Value="Rectangle"/> |
|||
<Setter Property="StrokeThickness" Value="1"/> |
|||
</Style> |
|||
|
|||
<Style TargetType="BoxView"> |
|||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="Button"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" /> |
|||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
|||
<Setter Property="FontSize" Value="14"/> |
|||
<Setter Property="BorderWidth" Value="0"/> |
|||
<Setter Property="CornerRadius" Value="8"/> |
|||
<Setter Property="Padding" Value="14,10"/> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> |
|||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
<VisualState x:Name="PointerOver" /> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="CheckBox"> |
|||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="DatePicker"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
|||
<Setter Property="FontSize" Value="14"/> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="Editor"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
|||
<Setter Property="FontSize" Value="14" /> |
|||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="Entry"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
|||
<Setter Property="FontSize" Value="14" /> |
|||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="ImageButton"> |
|||
<Setter Property="Opacity" Value="1" /> |
|||
<Setter Property="BorderColor" Value="Transparent"/> |
|||
<Setter Property="BorderWidth" Value="0"/> |
|||
<Setter Property="CornerRadius" Value="0"/> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="Opacity" Value="0.5" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
<VisualState x:Name="PointerOver" /> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="Label"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular" /> |
|||
<Setter Property="FontSize" Value="14" /> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="Label" x:Key="Headline"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> |
|||
<Setter Property="FontSize" Value="32" /> |
|||
<Setter Property="HorizontalOptions" Value="Center" /> |
|||
<Setter Property="HorizontalTextAlignment" Value="Center" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="Label" x:Key="SubHeadline"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> |
|||
<Setter Property="FontSize" Value="24" /> |
|||
<Setter Property="HorizontalOptions" Value="Center" /> |
|||
<Setter Property="HorizontalTextAlignment" Value="Center" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="Picker"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
|||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
|||
<Setter Property="FontSize" Value="14" /> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="ProgressBar"> |
|||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="RadioButton"> |
|||
<Setter Property="BackgroundColor" Value="Transparent"/> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
|||
<Setter Property="FontSize" Value="14"/> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="RefreshView"> |
|||
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="SearchBar"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
|||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> |
|||
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular" /> |
|||
<Setter Property="FontSize" Value="14" /> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="SearchHandler"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
|||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular" /> |
|||
<Setter Property="FontSize" Value="14" /> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="Shadow"> |
|||
<Setter Property="Radius" Value="15" /> |
|||
<Setter Property="Opacity" Value="0.5" /> |
|||
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" /> |
|||
<Setter Property="Offset" Value="10,10" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="Slider"> |
|||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
|||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> |
|||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> |
|||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> |
|||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="SwipeItem"> |
|||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="Switch"> |
|||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
|||
<Setter Property="ThumbColor" Value="{StaticResource White}" /> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
<VisualState x:Name="On"> |
|||
<VisualState.Setters> |
|||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" /> |
|||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
<VisualState x:Name="Off"> |
|||
<VisualState.Setters> |
|||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="TimePicker"> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
|||
<Setter Property="BackgroundColor" Value="Transparent"/> |
|||
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
|||
<Setter Property="FontSize" Value="14"/> |
|||
<Setter Property="MinimumHeightRequest" Value="44"/> |
|||
<Setter Property="MinimumWidthRequest" Value="44"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal" /> |
|||
<VisualState x:Name="Disabled"> |
|||
<VisualState.Setters> |
|||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<!-- |
|||
<Style TargetType="TitleBar"> |
|||
<Setter Property="MinimumHeightRequest" Value="32"/> |
|||
<Setter Property="VisualStateManager.VisualStateGroups"> |
|||
<VisualStateGroupList> |
|||
<VisualStateGroup x:Name="TitleActiveStates"> |
|||
<VisualState x:Name="TitleBarTitleActive"> |
|||
<VisualState.Setters> |
|||
<Setter Property="BackgroundColor" Value="Transparent" /> |
|||
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
<VisualState x:Name="TitleBarTitleInactive"> |
|||
<VisualState.Setters> |
|||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> |
|||
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" /> |
|||
</VisualState.Setters> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateGroupList> |
|||
</Setter> |
|||
</Style> |
|||
--> |
|||
|
|||
<Style TargetType="Page" ApplyToDerivedTypes="True"> |
|||
<Setter Property="Padding" Value="0"/> |
|||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="Shell" ApplyToDerivedTypes="True"> |
|||
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> |
|||
<Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> |
|||
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> |
|||
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> |
|||
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" /> |
|||
<Setter Property="Shell.NavBarHasShadow" Value="False" /> |
|||
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> |
|||
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> |
|||
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> |
|||
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="NavigationPage"> |
|||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> |
|||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> |
|||
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> |
|||
</Style> |
|||
|
|||
<Style TargetType="TabbedPage"> |
|||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" /> |
|||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> |
|||
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> |
|||
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> |
|||
</Style> |
|||
|
|||
</ResourceDictionary> |
|||
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.ScanPage" |
|||
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" |
|||
xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.Maui.Controls" |
|||
Title="扫一扫"> |
|||
<Grid> |
|||
<zxing:CameraBarcodeReaderView x:Name="barcodeReader" |
|||
BarcodesDetected="OnBarcodesDetected" |
|||
IsDetecting="True" |
|||
CameraLocation="Rear"/> |
|||
<GraphicsView x:Name="overlayGraphicsView" |
|||
IsVisible="False" |
|||
VerticalOptions="Fill" |
|||
HorizontalOptions="Fill" |
|||
BackgroundColor="Transparent" /> |
|||
</Grid> |
|||
</ContentPage> |
|||
@ -0,0 +1,53 @@ |
|||
using CommunityToolkit.Mvvm.Messaging; |
|||
using SunlightAggregationTerminal.View; |
|||
using ZXing.Multi; |
|||
using ZXing.Net.Maui; |
|||
using ZXing.QrCode.Internal; |
|||
|
|||
namespace SunlightAggregationTerminal; |
|||
|
|||
public partial class ScanPage : ContentPage |
|||
{ |
|||
private int mode; |
|||
public ScanPage(int i) |
|||
{ |
|||
InitializeComponent(); |
|||
mode = i; |
|||
} |
|||
private async void OnBarcodesDetected(object sender, BarcodeDetectionEventArgs e) |
|||
{ |
|||
var firstResult = e.Results?.FirstOrDefault(); |
|||
if (firstResult is not null) |
|||
{ |
|||
barcodeReader.IsDetecting = false; |
|||
|
|||
// 触发回调
|
|||
if (mode == 0) |
|||
{ |
|||
MainThread.BeginInvokeOnMainThread(() => |
|||
{ |
|||
// 震动
|
|||
try { Vibration.Default.Vibrate(TimeSpan.FromMilliseconds(100)); } catch { } |
|||
// 传入信息
|
|||
WeakReferenceMessenger.Default.Send(firstResult.Value); |
|||
// 等待 1.5 秒(非阻塞,界面不会卡死)
|
|||
Task.Delay(1500); |
|||
// 关闭页面
|
|||
Navigation.PopAsync(); |
|||
}); |
|||
} |
|||
if (mode == 3) |
|||
{ |
|||
MainThread.BeginInvokeOnMainThread(() => |
|||
{ |
|||
try { Vibration.Default.Vibrate(TimeSpan.FromMilliseconds(100)); } catch { } |
|||
WeakReferenceMessenger.Default.Send(firstResult.Value); |
|||
Task.Delay(1500); |
|||
// 关闭页面
|
|||
Navigation.PopModalAsync(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFrameworks>net10.0-android</TargetFrameworks> |
|||
<TargetFrameworks Condition="!$([MSBuild]::IsOSPlatform('linux'))">$(TargetFrameworks);net10.0-ios;net10.0-maccatalyst</TargetFrameworks> |
|||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net10.0-windows10.0.19041.0</TargetFrameworks> |
|||
|
|||
<!-- Note for MacCatalyst: |
|||
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64. |
|||
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>. |
|||
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated; |
|||
either BOTH runtimes must be indicated or ONLY macatalyst-x64. --> |
|||
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> --> |
|||
|
|||
<OutputType>Exe</OutputType> |
|||
<RootNamespace>SunlightAggregationTerminal</RootNamespace> |
|||
<UseMaui>true</UseMaui> |
|||
<SingleProject>true</SingleProject> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<Nullable>enable</Nullable> |
|||
|
|||
<!-- Enable XAML source generation for faster build times and improved performance. |
|||
This generates C# code from XAML at compile time instead of runtime inflation. |
|||
To disable, remove this line. |
|||
For individual files, you can override by setting Inflator metadata: |
|||
<MauiXaml Update="MyPage.xaml" Inflator="Default" /> (reverts to defaults: Runtime for Debug, XamlC for Release) |
|||
<MauiXaml Update="MyPage.xaml" Inflator="Runtime" /> (force runtime inflation) --> |
|||
<MauiXamlInflator>SourceGen</MauiXamlInflator> |
|||
|
|||
<!-- Display name --> |
|||
<ApplicationTitle>SunlightAggregationTerminal</ApplicationTitle> |
|||
|
|||
<!-- App Identifier --> |
|||
<ApplicationId>com.companyname.sunlightaggregationterminal</ApplicationId> |
|||
|
|||
<!-- Versions --> |
|||
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> |
|||
<ApplicationVersion>1</ApplicationVersion> |
|||
|
|||
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged --> |
|||
<WindowsPackageType>None</WindowsPackageType> |
|||
|
|||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion> |
|||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion> |
|||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion> |
|||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion> |
|||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<!-- App Icon --> |
|||
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /> |
|||
|
|||
<!-- Splash Screen --> |
|||
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /> |
|||
|
|||
<!-- Images --> |
|||
<MauiImage Include="Resources\Images\*" /> |
|||
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" /> |
|||
|
|||
<!-- Custom Fonts --> |
|||
<MauiFont Include="Resources\Fonts\*" /> |
|||
|
|||
<!-- Raw Assets (also remove the "Resources\Raw" prefix) --> |
|||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<None Remove="Images\adduserfilled.svg" /> |
|||
<None Remove="Images\infofeed.svg" /> |
|||
<None Remove="Images\ixnotifications.svg" /> |
|||
<None Remove="Images\lucidescanline.png" /> |
|||
<None Remove="Images\search.svg" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<MauiImage Include="Images\adduserfilled.svg" /> |
|||
<MauiImage Include="Images\infofeed.svg" /> |
|||
<MauiImage Include="Images\ixnotifications.svg" /> |
|||
<MauiImage Include="Images\lucidescanline.png" /> |
|||
<MauiImage Include="Images\search.svg" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" /> |
|||
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.7" /> |
|||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.7" /> |
|||
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.51" /> |
|||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.7" /> |
|||
<PackageReference Include="TouchSocket" Version="4.2.7" /> |
|||
<PackageReference Include="ZXing.Net.Maui.Controls" Version="0.7.4" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<MauiXaml Update="InfoPage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="NotificationPage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="NotificationView\MessagePage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="NotificationView\NoticePage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="NotificationView\SystemPage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="ProfilePage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="QueryPage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="ScanPage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="View\LogPage.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
<MauiXaml Update="View\LogWindow.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
</MauiXaml> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Folder Include="Services\" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,3 @@ |
|||
<Solution> |
|||
<Project Path="SunlightAggregationTerminal.csproj" /> |
|||
</Solution> |
|||
@ -0,0 +1,67 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.View.LogPage" |
|||
Title="登录"> |
|||
<VerticalStackLayout Padding="30" Spacing="20" |
|||
VerticalOptions="Center" |
|||
HorizontalOptions="Center" |
|||
MaximumWidthRequest="600"> |
|||
<Grid RowDefinitions="Auto, *" ColumnDefinitions="*, Auto"> |
|||
<HorizontalStackLayout VerticalOptions="Center" Spacing="15"> |
|||
<!-- 信息 --> |
|||
<VerticalStackLayout Grid.Row="0" |
|||
Grid.Column="0" |
|||
VerticalOptions="Center"> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Entry Text="服务器:" FontSize="26" TextColor="Black" /> |
|||
<Entry x:Name="Enterprise" |
|||
Text="IP" |
|||
FontSize="26" |
|||
TextColor="Gray" |
|||
WidthRequest="200" |
|||
MaximumWidthRequest="200"/> |
|||
</HorizontalStackLayout> |
|||
</VerticalStackLayout> |
|||
</HorizontalStackLayout> |
|||
<Button Grid.Row="0" Grid.Column="1" |
|||
Clicked="OnScanButtonClicked" |
|||
BackgroundColor="Transparent" |
|||
WidthRequest="60" |
|||
HeightRequest="60" > |
|||
<Button.ImageSource> |
|||
<!-- 设置图标 --> |
|||
<FileImageSource File="lucidescanline.png" /> |
|||
</Button.ImageSource> |
|||
</Button> |
|||
</Grid> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Entry Text="用户:" FontSize="26" TextColor="Black" /> |
|||
<!-- 用户名输入 --> |
|||
<Entry x:Name="UsernameEntry" |
|||
Placeholder="请输入用户名" |
|||
FontSize="26" |
|||
WidthRequest="250" |
|||
MaximumWidthRequest="250"/> |
|||
</HorizontalStackLayout> |
|||
<HorizontalStackLayout VerticalOptions="Center"> |
|||
<Entry Text="密码:" FontSize="26" TextColor="Black"/> |
|||
<!-- 密码输入 --> |
|||
<Entry x:Name="PasswordEntry" |
|||
Placeholder="请输入密码" |
|||
IsPassword="True" |
|||
FontSize="26" |
|||
WidthRequest="250" |
|||
MaximumWidthRequest="250"/> |
|||
</HorizontalStackLayout> |
|||
<!-- 登录按钮 --> |
|||
<Button Text="登 录" |
|||
BackgroundColor="#512BD4" |
|||
TextColor="White" |
|||
HeightRequest="50" |
|||
WidthRequest="100" |
|||
CornerRadius="10" |
|||
Margin="0,10,0,0" |
|||
Clicked="Log_Clicked"/> |
|||
</VerticalStackLayout> |
|||
</ContentPage> |
|||
@ -0,0 +1,59 @@ |
|||
using CommunityToolkit.Mvvm.Messaging; |
|||
using SunlightAggregationTerminal.Class; |
|||
using SunlightAggregationTerminal.Models; |
|||
using System.Data; |
|||
|
|||
namespace SunlightAggregationTerminal.View; |
|||
|
|||
public partial class LogPage : ContentPage |
|||
{ |
|||
public LogPage() |
|||
{ |
|||
InitializeComponent(); |
|||
|
|||
WeakReferenceMessenger.Default.Register<string>(this, (r, scannedValue) => |
|||
{ |
|||
Enterprise.Text = scannedValue; |
|||
}); |
|||
} |
|||
|
|||
private void OnScanButtonClicked(object sender, EventArgs e) |
|||
{ |
|||
// 跳转到扫码页面
|
|||
var scanPage = new ScanPage(3); |
|||
Navigation.PushAsync(scanPage); |
|||
} |
|||
|
|||
private async void Log_Clicked(object sender, EventArgs e)//登录
|
|||
{ |
|||
TcpServer.Configuration(Enterprise.Text, UsernameEntry.Text, PasswordEntry.Text, |
|||
Models.AppModels.GetAppUniqueId()); |
|||
|
|||
// while(!App.GlobalData.LogNo);
|
|||
/* |
|||
var temp_name = AppModels.Select("SELECT * FROM Users WHERE User='" + UsernameEntry.Text + "' LIMIT 1;"); |
|||
if (temp_name != null) |
|||
{ |
|||
//存在更新账号状态
|
|||
//var name = temp_name.Tables[0].AsEnumerable().FirstOrDefault();
|
|||
|
|||
string sql = @"UPDATE Users SET ServerID = '" + Enterprise.Text |
|||
+ "', UserPassword = '" + PasswordEntry.Text+ |
|||
"', LogNo = true WHERE User='" + UsernameEntry.Text + "';"; |
|||
AppModels.Updata(sql); |
|||
} |
|||
else |
|||
{ |
|||
//插入账号
|
|||
string sql = @"INSERT INTO Users (User,UserId ,UserName ,UserPassword ,
|
|||
Enterprise ,Department ,ServerID ,Groups , |
|||
ProxyID ,LogNo ,LocalAreaNetworkMode ,DarkMode , |
|||
MessageNotificationMode ,GUID |
|||
)VALUES('"+ UsernameEntry.Text + "','SUNLIGHT','SUNLIGHT','"+ PasswordEntry.Text +
|
|||
"','SUNLIGHT','ENGINEER','"+ Enterprise.Text + "','ENGINEER',"+ |
|||
" '',0,0,0,0,'" + Models.AppModels.GetAppUniqueId() + "');"; |
|||
AppModels.INSERT(sql); |
|||
}*/ |
|||
await Navigation.PopModalAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<Window xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
|||
x:Class="SunlightAggregationTerminal.View.LogWindow" |
|||
Title="LogWindow"> |
|||
<ContentPage> |
|||
|
|||
<!-- 登录按钮 --> |
|||
<Button Text="登 录" |
|||
BackgroundColor="#512BD4" |
|||
TextColor="White" |
|||
HeightRequest="50" |
|||
WidthRequest="100" |
|||
CornerRadius="10" |
|||
Margin="0,10,0,0"/> |
|||
</ContentPage> |
|||
</Window> |
|||
@ -0,0 +1,19 @@ |
|||
namespace SunlightAggregationTerminal.View; |
|||
|
|||
public partial class LogWindow : Window |
|||
{ |
|||
public LogWindow() |
|||
{ |
|||
InitializeComponent(); |
|||
Page = new ContentPage() |
|||
{ |
|||
Content = new VerticalStackLayout |
|||
{ |
|||
Children = { |
|||
new Label { HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, Text = "Welcome to .NET MAUI!" |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
} |
|||