添加添加数据库服务器表
修改扫码连接修复扫码闪退问题
No files matched your search
@@ -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();//调用连接,当连接不成功时,会抛出异常。
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><path fill-rule="evenodd" d="M362.666667,277.333333 L362.666667,341.333333 L426.666667,341.333333 L426.666667,384 L362.666667,384 L362.666667,448 L320,448 L320,384 L256,384 L256,341.333333 L320,341.333333 L320,277.333333 L362.666667,277.333333 Z M186.666667,192 C246.976162,192 296.152141,241.030193 298.573248,302.451465 L298.666667,307.2 L298.666667,320 L234.666667,320 L234.666667,384 L0,384 L0,307.2 C0,245.167377 47.6682428,194.586368 107.383368,192.09609 L112,192 L186.666667,192 Z M149.333333,3.55271368e-14 C190.570594,3.55271368e-14 224,33.4294054 224,74.6666667 C224,114.529353 192.762078,147.096031 153.430084,149.222851 L149.333333,149.333333 C108.096072,149.333333 74.6666667,115.903928 74.6666667,74.6666667 C74.6666667,34.8039808 105.904589,2.2373024 145.236582,0.110482347 L149.333333,3.55271368e-14 Z" transform="translate(64 42.667)"/></svg>
|
||||
|
After Width: | Height: | Size: 946 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="512px" height="512px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="drop" fill="#000000" transform="translate(64.000000, 85.333333)">
|
||||
<path d="M128.021333,42.688 L384.042667,42.688 L384.042667,0.0213333333 L128.021333,0.0213333333 L128.021333,42.688 Z M0.0426666667,85.3546667 L85.376,85.3546667 L85.376,1.42108547e-14 L0.0426666667,1.42108547e-14 L0.0426666667,85.3546667 Z M128.021333,128.021333 L384.042667,128.021333 L384.042667,85.3546667 L128.021333,85.3546667 L128.021333,128.021333 Z M298.688,298.688 L384.042667,298.688 L384.042667,213.333333 L298.688,213.333333 L298.688,298.688 Z M-1.42108547e-14,256.021333 L256,256.021333 L256,213.333333 L-1.42108547e-14,213.333333 L-1.42108547e-14,256.021333 Z M0.0426666667,341.354667 L256.042667,341.354667 L256.042667,298.688 L0.0426666667,298.688 L0.0426666667,341.354667 Z" id="Combined-Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 512 512"><path fill="currentColor" fill-rule="evenodd" d="M149.333 149.333V384h101.183l154.817 85.333l-.04-85.333h64.04V149.333zM426.667 192v149.333h-64.04v55.698l-101.143-55.698H192V192zm-64-128v42.667h-256v170.666H64V64z"/></svg>
|
||||
|
After Width: | Height: | Size: 309 B |
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="512px" height="512px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="icon" fill="#000000" transform="translate(42.666667, 85.333333)">
|
||||
<path d="M224,1.42108547e-14 C300.583485,1.42108547e-14 362.666667,62.0831814 362.666667,138.666667 C362.666667,169.260685 352.758877,197.540615 335.976875,220.472881 L429.476859,313.973637 L399.306965,344.143531 L305.80721,250.642814 C282.874767,267.425258 254.594461,277.333333 224,277.333333 C182.528564,277.333333 145.309244,259.127865 119.898048,230.272939 L150.156212,200.014605 C167.76564,221.187509 194.308707,234.666667 224,234.666667 C277.019336,234.666667 320,191.686003 320,138.666667 C320,85.6473307 277.019336,42.6666667 224,42.6666667 C199.739363,42.6666667 177.580626,51.6659715 160.67991,66.5084604 L130.465152,36.2951919 C155.124422,13.7519355 187.956242,1.42108547e-14 224,1.42108547e-14 Z M102.248384,38.2483876 L192,128 L102.248384,217.751611 L72.0784993,187.581721 L110.315,149.333 L7.10542736e-15,149.333333 L7.10542736e-15,106.666667 L110.316,106.666 L72.0784993,68.418278 L102.248384,38.2483876 Z" id="Combined-Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
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}", "确定");
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="456" height="456" fill="#512BD4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 228 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
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();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
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!"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||