@ -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,34 @@ |
|||||
|
using SunlightAggregationTerminal.Class; |
||||
|
using SunlightAggregationTerminal.Models; |
||||
|
|
||||
|
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(logpage); |
||||
|
} |
||||
|
else |
||||
|
{//发送登录请求
|
||||
|
/* var dat = TcpServer.Query(""); |
||||
|
if (dat != null) |
||||
|
{//拒绝登陆时打开登录页面
|
||||
|
var logpage = new View.LogPage(); |
||||
|
Navigation.PushModalAsync(logpage); |
||||
|
}*/ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,255 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.Class |
||||
|
{ |
||||
|
|
||||
|
public class SQLiteConfig() |
||||
|
{ |
||||
|
|
||||
|
public static SqliteHelper SQLitedata = null!; //定义数据库
|
||||
|
|
||||
|
public static SqliteHelper? Config(string dat) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
SQLitedata = new SqliteHelper(dat); //数据库连接路径(获取各平台的应用数据目录)
|
||||
|
SQLitedata.Open(); //打开数据库
|
||||
|
if (SQLitedata.TableExists("Users")) |
||||
|
{ |
||||
|
CheckAndRepairTableSchema(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
CreateFreshUserTable(); |
||||
|
} |
||||
|
|
||||
|
if (SQLitedata.TableExists("Notification")) |
||||
|
{ |
||||
|
CheckAndRepairTableSchemaNotification(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
CreateFreshUserTableNotification(); |
||||
|
} |
||||
|
|
||||
|
SQLitedata.Close(); |
||||
|
|
||||
|
return SQLitedata; |
||||
|
} |
||||
|
catch (Exception) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// --- 逻辑分支 表存在,检查字段完整性 ---
|
||||
|
private static void CheckAndRepairTableSchema() |
||||
|
{ |
||||
|
// 获取现有字段列表
|
||||
|
// 使用 PRAGMA table_info 获取结构
|
||||
|
string pragmaSql = "PRAGMA table_info('Users');"; |
||||
|
|
||||
|
// 复用现有的 ExecuteReader 方法
|
||||
|
// ExecuteReader 返回 null 代表出错,否则返回 DataReader
|
||||
|
using (var reader = SQLitedata.ExecuteReader(pragmaSql, null)) |
||||
|
{ |
||||
|
if (reader == null) return; |
||||
|
|
||||
|
var existingColumns = new List<string>(); |
||||
|
while (reader.Read()) |
||||
|
{ |
||||
|
// PRAGMA table_info 返回结果的第2列(Index=1)是列名
|
||||
|
string colName = reader.GetString(1); |
||||
|
existingColumns.Add(colName); |
||||
|
} |
||||
|
reader.Close(); // 记得关闭 Reader
|
||||
|
|
||||
|
// 检查并添加缺失字段 (直接拼接 SQL)
|
||||
|
// 检查 User
|
||||
|
if (!existingColumns.Contains("User")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN User TEXT NOT NULL;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 UserId
|
||||
|
if (!existingColumns.Contains("UserId")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN UserId TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 UserName
|
||||
|
if (!existingColumns.Contains("UserName")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN UserName TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 UserPassword
|
||||
|
if (!existingColumns.Contains("UserPassword")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN UserPassword TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 Enterprise
|
||||
|
if (!existingColumns.Contains("Enterprise")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN Enterprise TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 Department
|
||||
|
if (!existingColumns.Contains("Department")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN Department TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 ServerID
|
||||
|
if (!existingColumns.Contains("ServerID")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN ServerID TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 Group
|
||||
|
if (!existingColumns.Contains("Groups")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN Groups TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 ProxyID
|
||||
|
if (!existingColumns.Contains("ProxyID")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN ProxyID TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 LogNo
|
||||
|
if (!existingColumns.Contains("LogNo")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN LogNo BOOL DEFAULT (0);"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 LocalAreaNetworkMode
|
||||
|
if (!existingColumns.Contains("LocalAreaNetworkMode")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN LocalAreaNetworkMode BOOL DEFAULT (0);"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 LocalAreaNetworkMode
|
||||
|
if (!existingColumns.Contains("DarkMode")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN DarkMode BOOL DEFAULT (0);"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 LocalAreaNetworkMode
|
||||
|
if (!existingColumns.Contains("MessageNotificationMode")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN MessageNotificationMode BOOL DEFAULT (0);"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 GUID
|
||||
|
if (!existingColumns.Contains("GUID")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Users ADD COLUMN GUID TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
string sqlupdata = "UPDATE Users SET GUID = '"+ Models.AppModels.GetAppUniqueId() + "';"; |
||||
|
SQLitedata.ExecuteNonQuery(sqlupdata, null); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
private static void CheckAndRepairTableSchemaNotification() |
||||
|
{ |
||||
|
// 获取现有字段列表
|
||||
|
// 使用 PRAGMA table_info 获取结构
|
||||
|
string pragmaSql = "PRAGMA table_info('Notification');"; |
||||
|
|
||||
|
// 复用现有的 ExecuteReader 方法
|
||||
|
// ExecuteReader 返回 null 代表出错,否则返回 DataReader
|
||||
|
using (var reader = SQLitedata.ExecuteReader(pragmaSql, null)) |
||||
|
{ |
||||
|
if (reader == null) return; |
||||
|
|
||||
|
var existingColumns = new List<string>(); |
||||
|
while (reader.Read()) |
||||
|
{ |
||||
|
// PRAGMA table_info 返回结果的第2列(Index=1)是列名
|
||||
|
string colName = reader.GetString(1); |
||||
|
existingColumns.Add(colName); |
||||
|
} |
||||
|
reader.Close(); // 记得关闭 Reader
|
||||
|
|
||||
|
// 检查并添加缺失字段 (直接拼接 SQL)
|
||||
|
// 检查 Title
|
||||
|
if (!existingColumns.Contains("Title")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Notification ADD COLUMN Title TEXT NULL;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 Content
|
||||
|
if (!existingColumns.Contains("Content")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Notification ADD COLUMN Content TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 Time
|
||||
|
if (!existingColumns.Contains("Time")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Notification ADD COLUMN Time TEXT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
// 检查 Type
|
||||
|
if (!existingColumns.Contains("Type")) |
||||
|
{ |
||||
|
string sql = "ALTER TABLE Notification ADD COLUMN Type INT;"; |
||||
|
SQLitedata.ExecuteNonQuery(sql, null); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
// --- 逻辑分支 表不存在,直接创建 ---
|
||||
|
private static void CreateFreshUserTable() |
||||
|
{ |
||||
|
// 建表语句
|
||||
|
string createSql = @"
|
||||
|
CREATE TABLE Users ( |
||||
|
User TEXT NOT NULL, |
||||
|
UserId TEXT, |
||||
|
UserName TEXT, |
||||
|
UserPassword TEXT, |
||||
|
Enterprise TEXT, |
||||
|
Department TEXT, |
||||
|
ServerID TEXT, |
||||
|
Groups TEXT, |
||||
|
ProxyID TEXT, |
||||
|
LogNo BOOL DEFAULT (0), |
||||
|
LocalAreaNetworkMode BOOL DEFAULT (0), |
||||
|
DarkMode BOOL DEFAULT (0), |
||||
|
MessageNotificationMode BOOL DEFAULT (0), |
||||
|
GUID TEXT |
||||
|
);";
|
||||
|
|
||||
|
// 复用现有的 ExecuteNonQuery 方法
|
||||
|
SQLitedata.ExecuteNonQuery(createSql, null); |
||||
|
|
||||
|
string Sql = @"
|
||||
|
INSERT INTO Users (User,UserId ,UserName ,UserPassword ,Enterprise ,Department ,ServerID ,Groups ,ProxyID ,LogNo ,LocalAreaNetworkMode ,DarkMode ,MessageNotificationMode ,GUID |
||||
|
)VALUES('SUNLIGHT','SUNLIGHT','SUNLIGHT','SUNLIGHT','SUNLIGHT','ENGINEER','TEST','ENGINEER','',0,0,0,0,'"+ Models.AppModels.GetAppUniqueId() + "');";
|
||||
|
|
||||
|
// 复用现有的 ExecuteNonQuery 方法
|
||||
|
SQLitedata.ExecuteNonQuery(Sql, null); |
||||
|
} |
||||
|
private static void CreateFreshUserTableNotification() |
||||
|
{ |
||||
|
// 建表语句
|
||||
|
string createSql = @"
|
||||
|
CREATE TABLE Notification ( |
||||
|
Id INTEGER PRIMARY KEY AUTOINCREMENT, |
||||
|
Title TEXT, |
||||
|
Content TEXT, |
||||
|
Time TEXT, |
||||
|
Type INT |
||||
|
);";
|
||||
|
|
||||
|
// 复用现有的 ExecuteNonQuery 方法
|
||||
|
SQLitedata.ExecuteNonQuery(createSql, null); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,504 @@ |
|||||
|
using Microsoft.Data.Sqlite; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Data; |
||||
|
using System.Data.Common; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
|
||||
|
namespace SunlightAggregationTerminal.Class |
||||
|
{ |
||||
|
public class ClsLock : IDisposable |
||||
|
{ |
||||
|
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); |
||||
|
|
||||
|
public IDisposable Read() |
||||
|
{ |
||||
|
_lock.EnterReadLock(); |
||||
|
return new DisposableAction(() => _lock.ExitReadLock()); |
||||
|
} |
||||
|
|
||||
|
public void Dispose() => _lock?.Dispose(); |
||||
|
|
||||
|
private class DisposableAction : IDisposable |
||||
|
{ |
||||
|
private readonly Action _action; |
||||
|
public DisposableAction(Action action) => _action = action; |
||||
|
public void Dispose() => _action?.Invoke(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class SqliteHelper |
||||
|
{ |
||||
|
#region 字段
|
||||
|
private SqliteTransaction? dbTrans = null!; |
||||
|
private static readonly Dictionary<string, ClsLock> RWL = new Dictionary<string, ClsLock>(); |
||||
|
private readonly string mDataFile; |
||||
|
private readonly string mPassWord = ""; |
||||
|
private readonly string lockName = ""; |
||||
|
private SqliteConnection mConn = null!; |
||||
|
#endregion
|
||||
|
|
||||
|
#region 构造函数
|
||||
|
public SqliteHelper(string dataFile) |
||||
|
{ |
||||
|
this.mDataFile = dataFile ?? throw new ArgumentNullException(nameof(dataFile)); |
||||
|
this.mDataFile = dataFile; // 注意:原代码有两次赋值,保留逻辑
|
||||
|
if (!RWL.ContainsKey(dataFile)) |
||||
|
{ |
||||
|
lockName = dataFile; |
||||
|
RWL.Add(dataFile, new ClsLock()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public SqliteHelper(string dataFile, string PassWord) |
||||
|
{ |
||||
|
this.mDataFile = dataFile ?? throw new ArgumentNullException(nameof(dataFile)); |
||||
|
this.mPassWord = PassWord ?? throw new ArgumentNullException(nameof(PassWord)); |
||||
|
this.mDataFile = dataFile; |
||||
|
if (!RWL.ContainsKey(dataFile)) |
||||
|
{ |
||||
|
lockName = dataFile; |
||||
|
RWL.Add(dataFile, new ClsLock()); |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 打开/关闭 数据库
|
||||
|
// 注意:Microsoft.Data.Sqlite.Core 不支持连接字符串构建器,需手动拼接
|
||||
|
// 加密支持通常需要 Microsoft.Data.Sqlite.Core + SQLitePCLRaw.bundle_green (且加密功能可能受限)
|
||||
|
|
||||
|
public void Open() |
||||
|
{ |
||||
|
// 构建连接字符串
|
||||
|
var connectionString = $"Data Source={mDataFile}"; |
||||
|
if (!string.IsNullOrWhiteSpace(mPassWord)) |
||||
|
{ |
||||
|
connectionString += $";Password={mPassWord}"; // 注意:原生 Microsoft.Data.Sqlite 不支持加密
|
||||
|
// 如果需要加密,通常需要使用 SQLitePCLRaw 的特定提供程序或第三方库
|
||||
|
} |
||||
|
|
||||
|
mConn = new SqliteConnection(connectionString); |
||||
|
|
||||
|
// 如果文件不存在,Open() 会自动创建数据库文件
|
||||
|
// 但表结构需要你自己执行 CREATE TABLE
|
||||
|
mConn.Open(); |
||||
|
|
||||
|
Console.WriteLine("The database was opened successfully"); |
||||
|
} |
||||
|
|
||||
|
public void Close() |
||||
|
{ |
||||
|
if (this.mConn != null) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
this.mConn.Close(); |
||||
|
// 注意:不要在这里移除 RWL,因为这是静态的,可能影响其他实例
|
||||
|
// if (RWL.ContainsKey(LockName)) { RWL.Remove(LockName); }
|
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
Console.WriteLine("Shutdown failed"); |
||||
|
} |
||||
|
} |
||||
|
Console.WriteLine("The database was shut down successfully"); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 事务
|
||||
|
public void BeginTrain() |
||||
|
{ |
||||
|
EnsureConnection(); |
||||
|
dbTrans = mConn.BeginTransaction(); |
||||
|
} |
||||
|
|
||||
|
public void DBCommit() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
dbTrans?.Commit(); |
||||
|
dbTrans?.Dispose(); |
||||
|
dbTrans = null; // 提交后置空
|
||||
|
} |
||||
|
catch (Exception) |
||||
|
{ |
||||
|
dbTrans?.Rollback(); |
||||
|
dbTrans?.Dispose(); |
||||
|
dbTrans = null; |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 工具
|
||||
|
// OpenConnection 逻辑已合并到 Open() 方法中,因为 SqliteConnection 构造函数只接受字符串
|
||||
|
|
||||
|
public SqliteConnection Connection |
||||
|
{ |
||||
|
get { return mConn; } |
||||
|
private set { mConn = value ?? throw new ArgumentNullException(); } |
||||
|
} |
||||
|
|
||||
|
protected void EnsureConnection() |
||||
|
{ |
||||
|
if (this.mConn == null) |
||||
|
{ |
||||
|
throw new Exception("SQLiteManager.Connection=null"); |
||||
|
} |
||||
|
if (mConn.State != ConnectionState.Open) |
||||
|
{ |
||||
|
mConn.Open(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public string GetDataFile() => this.mDataFile; |
||||
|
|
||||
|
public bool TableExists(string table) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(table)) return false; |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
// 注意:参数化查询在表名/列名上无效,这里使用字符串拼接(需确保table变量安全)
|
||||
|
// 或者使用 PRAGMA table_info(table_name)
|
||||
|
var sql = $"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='{table}'"; |
||||
|
|
||||
|
using (var cmd = new SqliteCommand(sql, Connection)) |
||||
|
{ |
||||
|
var result = cmd.ExecuteScalar(); |
||||
|
return Convert.ToInt32(result) > 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public bool Vacuum() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
using (var Command = new SqliteCommand("VACUUM", Connection)) |
||||
|
{ |
||||
|
Command.ExecuteNonQuery(); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
catch (Exception) // SqliteException
|
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 将 IDataReader 转换为 DataSet
|
||||
|
/// </summary>
|
||||
|
/// <param name="reader">已经执行了查询的 DataReader</param>
|
||||
|
/// <returns>包含数据的 DataSet</returns>
|
||||
|
public DataSet ReaderToDataSet(IDataReader reader) |
||||
|
{ |
||||
|
DataSet ds = new DataSet(); |
||||
|
|
||||
|
do |
||||
|
{ |
||||
|
DataTable schemaTable = reader.GetSchemaTable()!; |
||||
|
DataTable dataTable = new DataTable(); |
||||
|
|
||||
|
if (schemaTable != null) |
||||
|
{ |
||||
|
// 创建列
|
||||
|
foreach (DataRow schemaRow in schemaTable.Rows) |
||||
|
{ |
||||
|
string colName = schemaRow["ColumnName"].ToString()!; |
||||
|
Type dataType = (Type)schemaRow["DataType"]; |
||||
|
|
||||
|
// 防止列名重复
|
||||
|
string uniqueColName = colName; |
||||
|
int i = 1; |
||||
|
while (dataTable.Columns.Contains(uniqueColName)) |
||||
|
{ |
||||
|
uniqueColName = colName + i++; |
||||
|
} |
||||
|
|
||||
|
DataColumn column = new DataColumn(uniqueColName, dataType); |
||||
|
dataTable.Columns.Add(column); |
||||
|
} |
||||
|
|
||||
|
// 读取行
|
||||
|
while (reader.Read()) |
||||
|
{ |
||||
|
object[] values = new object[dataTable.Columns.Count]; |
||||
|
for (int i = 0; i < dataTable.Columns.Count; i++) |
||||
|
{ |
||||
|
values[i] = reader.IsDBNull(i) ? DBNull.Value : reader.GetValue(i); |
||||
|
} |
||||
|
dataTable.Rows.Add(values); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// 如果没有 Schema (例如 "SELECT 1" 这种标量查询)
|
||||
|
// 需要手动创建列
|
||||
|
for (int i = 0; i < reader.FieldCount; i++) |
||||
|
{ |
||||
|
dataTable.Columns.Add("Column" + i); |
||||
|
} |
||||
|
while (reader.Read()) |
||||
|
{ |
||||
|
object[] values = new object[reader.FieldCount]; |
||||
|
reader.GetValues(values); |
||||
|
dataTable.Rows.Add(values); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ds.Tables.Add(dataTable); |
||||
|
} while (reader.NextResult()); // 处理多个结果集
|
||||
|
|
||||
|
return ds; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
|
||||
|
#region 执行SQL (Reader & Scalar)
|
||||
|
|
||||
|
public SqliteDataReader? ExecuteReader(string sql, SqliteParameter[]? paramArr) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(sql)) throw new ArgumentNullException(nameof(sql)); |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
// 注意:using 语句会立即释放 Reader,导致无法读取
|
||||
|
// 这里的 RWL 锁在 using 外部处理,或者调用方自己处理锁
|
||||
|
// 这里简化逻辑,直接返回 Reader,调用方需自行管理连接状态
|
||||
|
var cmd = new SqliteCommand(sql, Connection); |
||||
|
|
||||
|
if (paramArr != null) |
||||
|
{ |
||||
|
cmd.Parameters.AddRange(paramArr); |
||||
|
} |
||||
|
|
||||
|
// CommandBehavior.CloseConnection 确保 Reader 关闭时连接也关闭
|
||||
|
// 但这里我们管理连接,所以不加
|
||||
|
try |
||||
|
{ |
||||
|
// 注意:不要在这里 Dispose Command,否则 Reader 会失效
|
||||
|
// 返回 Reader,由调用方在读取完毕后关闭
|
||||
|
return cmd.ExecuteReader(); |
||||
|
} |
||||
|
catch(Exception ex) |
||||
|
{ |
||||
|
Console.WriteLine("[SQLITE_ExecuteReader:err]" + ex.ToString()); |
||||
|
cmd?.Dispose(); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public DataSet? ExecuteDataSet(string sql, SqliteParameter[]? paramArr) |
||||
|
{ |
||||
|
var dat = ExecuteReader(sql, paramArr); |
||||
|
if (dat == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
return ReaderToDataSet(dat); |
||||
|
} |
||||
|
|
||||
|
// ExecuteScalar
|
||||
|
public object? ExecuteScalar(string sql, SqliteParameter[]? paramArr) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(sql)) throw new ArgumentNullException(nameof(sql)); |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
using (RWL[lockName].Read()) |
||||
|
{ |
||||
|
using (var cmd = new SqliteCommand(sql, Connection)) |
||||
|
{ |
||||
|
if (paramArr != null) |
||||
|
{ |
||||
|
cmd.Parameters.AddRange(paramArr); |
||||
|
} |
||||
|
try |
||||
|
{ |
||||
|
return cmd.ExecuteScalar(); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Console.WriteLine("[SQLITE_ExecuteScalar:err]" + ex.ToString()); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// QueryOne (返回字典或对象)
|
||||
|
public Dictionary<string, object?>? QueryOne(string table, string conditionCol, object conditionVal) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(table)) return null; |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
string sql = $"SELECT * FROM [{table}]"; // 使用 [] 防止关键字冲突
|
||||
|
var parameters = new List<SqliteParameter>(); |
||||
|
|
||||
|
if (!string.IsNullOrEmpty(conditionCol)) |
||||
|
{ |
||||
|
sql += $" WHERE [{conditionCol}] = @{conditionCol}"; |
||||
|
parameters.Add(new SqliteParameter($"@{conditionCol}", conditionVal)); |
||||
|
} |
||||
|
|
||||
|
using (var cmd = new SqliteCommand(sql, Connection)) |
||||
|
{ |
||||
|
cmd.Parameters.AddRange(parameters.ToArray()); |
||||
|
using (var reader = cmd.ExecuteReader()) |
||||
|
{ |
||||
|
if (reader.Read()) |
||||
|
{ |
||||
|
var dict = new Dictionary<string, object?>(); |
||||
|
for (int i = 0; i < reader.FieldCount; i++) |
||||
|
{ |
||||
|
var value = reader.GetValue(i); |
||||
|
if (value == DBNull.Value) value = null; |
||||
|
dict[reader.GetName(i)] = value; |
||||
|
} |
||||
|
return dict; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 增 删 改
|
||||
|
// 注意:参数前缀统一为 @
|
||||
|
|
||||
|
public int InsertData(string table, Dictionary<string, object> entity) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(table)) throw new ArgumentNullException(nameof(table)); |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
string sql = BuildInsert(table, entity); |
||||
|
var parameters = BuildParamArray(entity); |
||||
|
return ExecuteNonQuery(sql, parameters); |
||||
|
} |
||||
|
|
||||
|
public int Update(string table, Dictionary<string, object> entity, string where, SqliteParameter[]? whereParams) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(table)) throw new ArgumentNullException(nameof(table)); |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
string sql = BuildUpdate(table, entity); |
||||
|
var parameters = BuildParamArray(entity); |
||||
|
|
||||
|
if (!string.IsNullOrEmpty(where)) |
||||
|
{ |
||||
|
sql += " WHERE " + where; |
||||
|
if (whereParams != null) |
||||
|
{ |
||||
|
var combined = new SqliteParameter[parameters.Length + whereParams.Length]; |
||||
|
parameters.CopyTo(combined, 0); |
||||
|
whereParams.CopyTo(combined, parameters.Length); |
||||
|
parameters = combined; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ExecuteNonQuery(sql, parameters); |
||||
|
} |
||||
|
|
||||
|
public int Delete(string table, string where, SqliteParameter[]? whereParams) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(table)) return 0; |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
string sql = $"DELETE FROM [{table}]"; |
||||
|
if (!string.IsNullOrEmpty(where)) |
||||
|
{ |
||||
|
sql += " WHERE " + where; |
||||
|
} |
||||
|
|
||||
|
return ExecuteNonQuery(sql, whereParams); |
||||
|
} |
||||
|
|
||||
|
public int ExecuteNonQuery(string sql, SqliteParameter[]? paramArr) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(sql)) throw new ArgumentNullException(nameof(sql)); |
||||
|
EnsureConnection(); |
||||
|
|
||||
|
using (RWL[lockName].Read()) // 注意:写操作通常建议用 Write 锁
|
||||
|
{ |
||||
|
using (var cmd = new SqliteCommand(sql, Connection)) |
||||
|
{ |
||||
|
if (paramArr != null) |
||||
|
{ |
||||
|
cmd.Parameters.AddRange(paramArr); |
||||
|
} |
||||
|
try |
||||
|
{ |
||||
|
return cmd.ExecuteNonQuery(); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Console.WriteLine("[SQLITE_ExecuteScalar:err]" + ex.ToString()); |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 构建 SQL 和 参数的方法保持不变,仅泛型类型变更
|
||||
|
private SqliteParameter[] BuildParamArray(Dictionary<string, object> entity) |
||||
|
{ |
||||
|
var list = new List<SqliteParameter>(); |
||||
|
foreach (string key in entity.Keys) |
||||
|
{ |
||||
|
// 注意:参数名必须包含 @ 前缀
|
||||
|
list.Add(new SqliteParameter($"@{key}", entity[key])); |
||||
|
} |
||||
|
return list.ToArray(); |
||||
|
} |
||||
|
|
||||
|
private string BuildInsert(string table, Dictionary<string, object> entity) |
||||
|
{ |
||||
|
var buf = new StringBuilder(); |
||||
|
buf.Append("INSERT INTO ").Append(table).Append(" ("); |
||||
|
var cols = new List<string>(); |
||||
|
var vals = new List<string>(); |
||||
|
foreach (string key in entity.Keys) |
||||
|
{ |
||||
|
cols.Add(key); |
||||
|
vals.Add($"@{key}"); |
||||
|
} |
||||
|
buf.Append(string.Join(",", cols)).Append(") VALUES ("); |
||||
|
buf.Append(string.Join(",", vals)).Append(")"); |
||||
|
return buf.ToString(); |
||||
|
} |
||||
|
|
||||
|
private string BuildUpdate(string table, Dictionary<string, object> entity) |
||||
|
{ |
||||
|
var buf = new StringBuilder(); |
||||
|
buf.Append("UPDATE ").Append(table).Append(" SET "); |
||||
|
var sets = new List<string>(); |
||||
|
foreach (string key in entity.Keys) |
||||
|
{ |
||||
|
sets.Add($"{key} = @{key}"); |
||||
|
} |
||||
|
buf.Append(string.Join(",", sets)); |
||||
|
return buf.ToString(); |
||||
|
} |
||||
|
|
||||
|
// 辅助方法:DataRow 转 Dictionary (由于没有 DataTable,通常直接从 Reader 转)
|
||||
|
// 这里保留原方法签名,但实际使用中可能需要调整
|
||||
|
public Dictionary<string, object?> DataTableToDictionary(DataTable dataTable) |
||||
|
{ |
||||
|
var result = new Dictionary<string, object?>(); |
||||
|
if (dataTable.Rows.Count > 0) |
||||
|
{ |
||||
|
var row = dataTable.Rows[0]; |
||||
|
foreach (DataColumn column in dataTable.Columns) |
||||
|
{ |
||||
|
var value = row[column]; |
||||
|
if (value == DBNull.Value) value = null; |
||||
|
result[column.ColumnName] = value; |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
#endregion
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using TouchSocket.Core; |
||||
|
using TouchSocket.Sockets; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.Class |
||||
|
{ |
||||
|
public class TcpServer |
||||
|
{ |
||||
|
public static string ServerIP = ""; |
||||
|
public static string ServerName = ""; |
||||
|
public static string ServerPassword = ""; |
||||
|
public static string ServerTerminal = ""; |
||||
|
|
||||
|
public static TcpClient tcpClient = new TcpClient(); |
||||
|
|
||||
|
public static void Configuration(string ip, string Name, string Password, string Terminal) |
||||
|
{ |
||||
|
ServerIP = ip; |
||||
|
ServerName = Name; |
||||
|
ServerPassword = Password; |
||||
|
ServerTerminal = Terminal; |
||||
|
} |
||||
|
public static async void Query(string Dat) |
||||
|
{ |
||||
|
|
||||
|
//发送字符串数据
|
||||
|
await tcpClient.SendAsync("hello"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private static async Task CreateCustomService() |
||||
|
{ |
||||
|
tcpClient.Config.SetRemoteIPHost(ServerIP); |
||||
|
|
||||
|
tcpClient.Connecting = (client, e) => { return EasyTask.CompletedTask; };//即将连接到服务器,此时已经创建socket,但是还未建立tcp
|
||||
|
tcpClient.Connected = (client, e) => { return EasyTask.CompletedTask; };//成功连接到服务器
|
||||
|
tcpClient.Closing = (client, e) => { return EasyTask.CompletedTask; };//即将从服务器断开连接。此处仅主动断开才有效。
|
||||
|
tcpClient.Closed = (client, e) => { return EasyTask.CompletedTask; };//从服务器断开连接,当连接不成功时不会触发。
|
||||
|
#region Tcp客户端使用Received异步委托接收数据
|
||||
|
tcpClient.Received = (client, e) => |
||||
|
{ |
||||
|
//从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
|
||||
|
var mes = e.Memory.Span.ToString(Encoding.UTF8); |
||||
|
tcpClient.Logger.Info($"客户端接收到信息:{mes}"); |
||||
|
return EasyTask.CompletedTask; |
||||
|
}; |
||||
|
#endregion
|
||||
|
|
||||
|
await tcpClient.ConnectAsync();//调用连接,当连接不成功时,会抛出异常。
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
After Width: | Height: | Size: 946 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 309 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.InfoPage" |
||||
|
Title=""> |
||||
|
<VerticalStackLayout> |
||||
|
|
||||
|
</VerticalStackLayout> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace SunlightAggregationTerminal; |
||||
|
|
||||
|
public partial class InfoPage : ContentPage |
||||
|
{ |
||||
|
public InfoPage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Maui.Handlers; |
||||
|
using SunlightAggregationTerminal.Models; |
||||
|
using ZXing.Net.Maui.Controls; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal |
||||
|
{ |
||||
|
public static class MauiProgram |
||||
|
{ |
||||
|
public static MauiApp CreateMauiApp() |
||||
|
{ |
||||
|
var builder = MauiApp.CreateBuilder(); |
||||
|
builder |
||||
|
.UseMauiApp<App>() |
||||
|
.UseBarcodeReader() |
||||
|
.ConfigureFonts(fonts => |
||||
|
{ |
||||
|
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); |
||||
|
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); |
||||
|
}) |
||||
|
.ConfigureMauiHandlers(handlers => |
||||
|
{ |
||||
|
// 这里的 "NoUnderline" 是自定义映射名称,可以随意命名
|
||||
|
EntryHandler.Mapper.AppendToMapping("NoUnderline", (handler, view) => |
||||
|
{ |
||||
|
#if ANDROID
|
||||
|
// 将背景 tint 设为透明
|
||||
|
// 这会移除 Android 默认的下划线颜色
|
||||
|
handler.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Android.Graphics.Color.Transparent); |
||||
|
|
||||
|
// 如果想彻底移除背景绘制(不仅仅是颜色透明)
|
||||
|
// handler.PlatformView.Background = null;
|
||||
|
#endif
|
||||
|
}); |
||||
|
}); |
||||
|
// 将 HttpClient 注册为单例服务
|
||||
|
builder.Services.AddSingleton<HttpClient>(); |
||||
|
|
||||
|
builder.Services.AddSingleton<DataModel>(); |
||||
|
|
||||
|
#if DEBUG
|
||||
|
builder.Logging.AddDebug(); |
||||
|
#endif
|
||||
|
|
||||
|
return builder.Build(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,89 @@ |
|||||
|
using CommunityToolkit.Mvvm.ComponentModel; |
||||
|
using SunlightAggregationTerminal.Class; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Data; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.Models |
||||
|
{ |
||||
|
public class AppModels : ObservableObject |
||||
|
{ |
||||
|
|
||||
|
public static SqliteHelper sqliteHelper = SQLiteConfig.Config(Path.Combine(FileSystem.AppDataDirectory, "MyAppData.db"))!; //数据库连接路径(获取各平台的应用数据目录)
|
||||
|
|
||||
|
public AppModels() |
||||
|
{ |
||||
|
if(sqliteHelper != null) |
||||
|
{//获取配置信息
|
||||
|
sqliteHelper.Open(); |
||||
|
var userdata= sqliteHelper.ExecuteDataSet("select * from Users Where LogNo = 1", null); |
||||
|
sqliteHelper.Close(); |
||||
|
if (userdata != null) |
||||
|
{ |
||||
|
var dat = userdata.Tables[0].AsEnumerable().FirstOrDefault(); |
||||
|
if (dat != null) |
||||
|
{ |
||||
|
App.GlobalData.UserName = dat.Field<string>("UserName") ?? ""; |
||||
|
App.GlobalData.UserId = dat.Field<string>("UserId") ?? ""; |
||||
|
App.GlobalData.User = dat.Field<string>("User") ?? ""; |
||||
|
App.GlobalData.UserPassword = dat.Field<string>("UserPassword") ?? ""; |
||||
|
App.GlobalData.Enterprise = dat.Field<string>("Enterprise") ?? ""; |
||||
|
App.GlobalData.Department = dat.Field<string>("Department") ?? ""; |
||||
|
App.GlobalData.Groups = dat.Field<string>("Groups") ?? ""; |
||||
|
App.GlobalData.ServerID = dat.Field<string>("ServerID") ?? ""; |
||||
|
App.GlobalData.ProxyID = dat.Field<string>("ProxyID") ?? ""; |
||||
|
App.GlobalData.LogNo = Convert.ToBoolean(dat.Field<object>("LogNo")); |
||||
|
App.GlobalData.LocalAreaNetworkMode = Convert.ToBoolean(dat.Field<object>("LocalAreaNetworkMode")); |
||||
|
App.GlobalData.DarkMode = Convert.ToBoolean(dat.Field<object>("DarkMode")); |
||||
|
App.GlobalData.MessageNotificationMode = Convert.ToBoolean(dat.Field<object>("MessageNotificationMode")); |
||||
|
|
||||
|
TcpServer.Configuration(App.GlobalData.ServerID, App.GlobalData.User, App.GlobalData.UserPassword, dat.Field<string>("GUID") ?? "Not"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void Updata(string sql) |
||||
|
{ |
||||
|
sqliteHelper.Open(); |
||||
|
sqliteHelper.ExecuteNonQuery(sql, null); |
||||
|
sqliteHelper.Close(); |
||||
|
} |
||||
|
|
||||
|
public static void INSERT(string sql) |
||||
|
{ |
||||
|
sqliteHelper.Open(); |
||||
|
sqliteHelper.ExecuteNonQuery(sql, null); |
||||
|
sqliteHelper.Close(); |
||||
|
} |
||||
|
|
||||
|
public static DataSet? Select(string sql) |
||||
|
{ |
||||
|
sqliteHelper.Open(); |
||||
|
var userdata = sqliteHelper.ExecuteDataSet(sql, null); |
||||
|
sqliteHelper.Close(); |
||||
|
|
||||
|
return userdata; |
||||
|
} |
||||
|
|
||||
|
public static string GetAppUniqueId() |
||||
|
{ |
||||
|
const string key = "sunlight_app_unique_id"; |
||||
|
|
||||
|
// 尝试从安全存储中读取
|
||||
|
string? id = SecureStorage.GetAsync(key).Result; |
||||
|
|
||||
|
if (string.IsNullOrEmpty(id)) |
||||
|
{ |
||||
|
// 如果不存在,生成一个新的 GUID
|
||||
|
id = Guid.NewGuid().ToString(); |
||||
|
// 保存到安全存储
|
||||
|
SecureStorage.SetAsync(key, id).Wait(); |
||||
|
} |
||||
|
|
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
using CommunityToolkit.Mvvm.ComponentModel; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.Models |
||||
|
{ |
||||
|
#pragma warning disable CA1416
|
||||
|
public partial class DataModel : ObservableObject |
||||
|
{ |
||||
|
[ObservableProperty] |
||||
|
public partial string User { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string UserId { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string UserName { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string UserPassword { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string Enterprise { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string Department { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string ServerID { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string Groups { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial string ProxyID { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial bool LogNo { get; set; } |
||||
|
public bool IsNotLogNo => !LogNo; |
||||
|
[ObservableProperty] |
||||
|
public partial bool LocalAreaNetworkMode { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial bool DarkMode { get; set; } |
||||
|
[ObservableProperty] |
||||
|
public partial bool MessageNotificationMode { get; set; } |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Data; |
||||
|
using System.Text; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.Models |
||||
|
{ |
||||
|
// 定义枚举
|
||||
|
public enum MsgType |
||||
|
{ |
||||
|
Notice, // 通知
|
||||
|
Message, // 信息
|
||||
|
System // 系统
|
||||
|
} |
||||
|
|
||||
|
// 定义显示用的模型
|
||||
|
public class NotificationItem |
||||
|
{ |
||||
|
public Int64 Id { get; set; } |
||||
|
public string? Title { get; set; } |
||||
|
public string? Content { get; set; } |
||||
|
public DateTime Time { get; set; } |
||||
|
public MsgType Type { get; set; } |
||||
|
} |
||||
|
|
||||
|
public static class DataService |
||||
|
{ |
||||
|
public static DataSet? data = AppModels.Select("select * from Notification Where Time > '" + DateTime.Now.AddDays(-30) + "'"); |
||||
|
|
||||
|
// 直接返回 List
|
||||
|
public static List<NotificationItem> _NotificationData = new List<NotificationItem>(); |
||||
|
public static List<NotificationItem> GetAllItems() |
||||
|
{ |
||||
|
_NotificationData.Clear(); |
||||
|
|
||||
|
if (data != null) |
||||
|
{ |
||||
|
foreach (DataRow dr in data.Tables[0].Rows) |
||||
|
{ |
||||
|
_NotificationData.Add(new NotificationItem |
||||
|
{ |
||||
|
Id = dr.Field<Int64>("Id"), |
||||
|
Title = dr.Field<string>("Title") , |
||||
|
Content = dr.Field<string>("Content"), |
||||
|
Time = DateTime.Parse(dr.Field<string>("Time")!), |
||||
|
Type = (MsgType)dr.Field<Int64>("Type") |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 倒序返回
|
||||
|
return _NotificationData.OrderByDescending(x => x.Time).ToList(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.NotificationPage" |
||||
|
Loaded="ContentPage_Loaded" |
||||
|
Title="通知中心"> |
||||
|
<ScrollView> |
||||
|
<VerticalStackLayout Padding="20" Spacing="20"> |
||||
|
<!-- 通知卡片 --> |
||||
|
<Border BackgroundColor="White" |
||||
|
Stroke="#CCCCCC" |
||||
|
Margin="0,0,0,10" |
||||
|
StrokeShape="RoundRectangle 10"> |
||||
|
<Grid ColumnDefinitions="Auto,*,Auto" Padding="15" ColumnSpacing="15"> |
||||
|
<!-- 文字内容 --> |
||||
|
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center"> |
||||
|
<Label x:Name="NoticeItemTitle" FontAttributes="Bold" FontSize="22" TextColor="Black"/> |
||||
|
<Label x:Name="NoticeItemContent" FontSize="16" TextColor="Gray" LineBreakMode="WordWrap"/> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
<!-- 点击事件 --> |
||||
|
<Border.GestureRecognizers> |
||||
|
<TapGestureRecognizer Tapped="OnNoticeTapped"/> |
||||
|
</Border.GestureRecognizers> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- 信息卡片 --> |
||||
|
<Border BackgroundColor="White" |
||||
|
Stroke="#CCCCCC" |
||||
|
Margin="0,0,0,10" |
||||
|
StrokeShape="RoundRectangle 10"> |
||||
|
<Grid ColumnDefinitions="Auto,*,Auto" Padding="15" ColumnSpacing="15"> |
||||
|
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center"> |
||||
|
<Label x:Name="MessageItemTitle" FontAttributes="Bold" FontSize="22" TextColor="Black"/> |
||||
|
<Label x:Name="MessageItemContent" FontSize="16" TextColor="Gray" LineBreakMode="WordWrap"/> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
<Border.GestureRecognizers> |
||||
|
<TapGestureRecognizer Tapped="OnMessageTapped"/> |
||||
|
</Border.GestureRecognizers> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- 系统卡片 --> |
||||
|
<Border BackgroundColor="White" |
||||
|
Stroke="#CCCCCC" |
||||
|
Margin="0,0,0,10" |
||||
|
StrokeShape="RoundRectangle 10"> |
||||
|
<Grid ColumnDefinitions="Auto,*,Auto" Padding="15" ColumnSpacing="15"> |
||||
|
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center"> |
||||
|
<Label x:Name="SystemItemTitle" FontAttributes="Bold" FontSize="22" TextColor="Black"/> |
||||
|
<Label x:Name="SystemItemContent" FontSize="16" TextColor="Gray" LineBreakMode="WordWrap"/> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
<Border.GestureRecognizers> |
||||
|
<TapGestureRecognizer Tapped="OnSystemTapped"/> |
||||
|
</Border.GestureRecognizers> |
||||
|
</Border> |
||||
|
</VerticalStackLayout> |
||||
|
</ScrollView> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,93 @@ |
|||||
|
using SunlightAggregationTerminal.Models; |
||||
|
using System.Data; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal; |
||||
|
|
||||
|
public partial class NotificationPage : ContentPage |
||||
|
{ |
||||
|
public NotificationItem NoticeItem { get; set; } = new NotificationItem(); |
||||
|
public NotificationItem MessageItem { get; set; } = new NotificationItem(); |
||||
|
public NotificationItem SystemItem { get; set; } = new NotificationItem(); |
||||
|
|
||||
|
public NotificationPage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
this.BindingContext = this; |
||||
|
} |
||||
|
|
||||
|
private void ContentPage_Loaded(object sender, EventArgs e) |
||||
|
{ |
||||
|
LoadSummaryData(); |
||||
|
} |
||||
|
|
||||
|
private void LoadSummaryData() |
||||
|
{ |
||||
|
var allItems = DataService.GetAllItems(); |
||||
|
|
||||
|
// 筛选出 Type 为 Notice 的数据,并取第一条
|
||||
|
// 对应 DataTable 的 Select("Type = ...").First()
|
||||
|
var noticeItem = allItems.FirstOrDefault(x => x.Type == MsgType.Notice); |
||||
|
|
||||
|
// 读取数据 (注意判空,防止找不到数据时报错)
|
||||
|
if (noticeItem != null) |
||||
|
{ |
||||
|
NoticeItemTitle.Text = noticeItem.Title; |
||||
|
NoticeItemContent.Text = noticeItem.Content; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// 处理没有找到数据的情况
|
||||
|
NoticeItemTitle.Text = "暂无通知"; |
||||
|
NoticeItemContent.Text = "通知"; |
||||
|
} |
||||
|
|
||||
|
var messageItem = allItems.FirstOrDefault(x => x.Type == MsgType.Message); |
||||
|
|
||||
|
// 读取数据 (注意判空,防止找不到数据时报错)
|
||||
|
if (messageItem != null) |
||||
|
{ |
||||
|
MessageItemTitle.Text = messageItem.Title; |
||||
|
MessageItemContent.Text = messageItem.Content; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// 处理没有找到数据的情况
|
||||
|
MessageItemTitle.Text = "暂无通知"; |
||||
|
MessageItemContent.Text = "信息"; |
||||
|
} |
||||
|
var systemItem = allItems.FirstOrDefault(x => x.Type == MsgType.System); |
||||
|
|
||||
|
// 读取数据 (注意判空,防止找不到数据时报错)
|
||||
|
if (systemItem != null) |
||||
|
{ |
||||
|
SystemItemTitle.Text = systemItem.Title; |
||||
|
SystemItemContent.Text = systemItem.Content; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// 处理没有找到数据的情况
|
||||
|
SystemItemTitle.Text = "暂无通知"; |
||||
|
SystemItemContent.Text = "系统信息"; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// 点击跳转到独立页面
|
||||
|
private async void OnNoticeTapped(object sender, TappedEventArgs e) |
||||
|
{ |
||||
|
await Navigation.PushAsync(new NotificationView.NoticePage()); |
||||
|
} |
||||
|
|
||||
|
private async void OnMessageTapped(object sender, TappedEventArgs e) |
||||
|
{ |
||||
|
await Navigation.PushAsync(new NotificationView.MessagePage()); |
||||
|
} |
||||
|
|
||||
|
private async void OnSystemTapped(object sender, TappedEventArgs e) |
||||
|
{ |
||||
|
await Navigation.PushAsync(new NotificationView.SystemPage()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.NotificationView.MessagePage" |
||||
|
Title="信息"> |
||||
|
<CollectionView x:Name="CardCollectionView" |
||||
|
ItemsSource="{Binding MessageItems}" |
||||
|
RemainingItemsThreshold="5" |
||||
|
RemainingItemsThresholdReached="CardCollectionView_RemainingItemsThresholdReached"> |
||||
|
<!-- 保持滚动条 --> |
||||
|
<CollectionView.ItemTemplate> |
||||
|
<DataTemplate> |
||||
|
<!-- 这里定义单个卡片的 UI 结构 --> |
||||
|
<Border BackgroundColor="White" |
||||
|
Stroke="#CCCCCC" |
||||
|
StrokeThickness="1" |
||||
|
Margin="10,0,10,10" |
||||
|
StrokeShape="RoundRectangle 10"> |
||||
|
<Grid Padding="15"> |
||||
|
<VerticalStackLayout> |
||||
|
<Label Text="{Binding Title}" |
||||
|
FontAttributes="Bold" |
||||
|
FontSize="22" |
||||
|
TextColor="Black"/> |
||||
|
<Label Text="{Binding Time}" |
||||
|
FontSize="14" |
||||
|
TextColor="Black" |
||||
|
LineBreakMode="WordWrap"/> |
||||
|
<Label Text="{Binding Content}" |
||||
|
FontSize="16" |
||||
|
TextColor="Gray" |
||||
|
LineBreakMode="WordWrap"/> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
</DataTemplate> |
||||
|
</CollectionView.ItemTemplate> |
||||
|
</CollectionView> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,42 @@ |
|||||
|
using Microsoft.Maui.Controls.Shapes; |
||||
|
using SunlightAggregationTerminal.Models; |
||||
|
using System.Collections.ObjectModel; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.NotificationView; |
||||
|
|
||||
|
public partial class MessagePage : ContentPage |
||||
|
{ |
||||
|
public ObservableCollection<NotificationItem> MessageItems { get; set; } = new(); |
||||
|
|
||||
|
public MessagePage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
this.BindingContext = this; |
||||
|
LoadData(); // 加载数据
|
||||
|
} |
||||
|
|
||||
|
private void LoadData() |
||||
|
{ |
||||
|
// 假设这是你获取数据的地方
|
||||
|
var allData = DataService._NotificationData; |
||||
|
if (allData != null) |
||||
|
{ |
||||
|
// 清空旧数据
|
||||
|
MessageItems.Clear(); |
||||
|
|
||||
|
// 按时间倒序,并只取最新的 N 条(例如 50 条)
|
||||
|
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.Message); |
||||
|
|
||||
|
// 将数据添加到集合中,UI 会自动更新
|
||||
|
foreach (var item in itemsToShow) |
||||
|
{ |
||||
|
MessageItems.Add(item); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.NotificationView.NoticePage" |
||||
|
Title="通知"> |
||||
|
<CollectionView x:Name="CardCollectionView" |
||||
|
ItemsSource="{Binding NoticeItems}" |
||||
|
RemainingItemsThreshold="5" |
||||
|
RemainingItemsThresholdReached="CardCollectionView_RemainingItemsThresholdReached"> |
||||
|
<!-- 保持滚动条 --> |
||||
|
<CollectionView.ItemTemplate> |
||||
|
<DataTemplate> |
||||
|
<!-- 这里定义单个卡片的 UI 结构 --> |
||||
|
<Border BackgroundColor="White" |
||||
|
Stroke="#CCCCCC" |
||||
|
StrokeThickness="1" |
||||
|
Margin="10,0,10,10" |
||||
|
StrokeShape="RoundRectangle 10"> |
||||
|
<Grid Padding="15"> |
||||
|
<VerticalStackLayout> |
||||
|
<Label Text="{Binding Title}" |
||||
|
FontAttributes="Bold" |
||||
|
FontSize="22" |
||||
|
TextColor="Black"/> |
||||
|
<Label Text="{Binding Time}" |
||||
|
FontSize="14" |
||||
|
TextColor="Black" |
||||
|
LineBreakMode="WordWrap"/> |
||||
|
<Label Text="{Binding Content}" |
||||
|
FontSize="16" |
||||
|
TextColor="Gray" |
||||
|
LineBreakMode="WordWrap"/> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
</DataTemplate> |
||||
|
</CollectionView.ItemTemplate> |
||||
|
</CollectionView> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,43 @@ |
|||||
|
using Microsoft.Maui.Controls.Shapes; |
||||
|
using SunlightAggregationTerminal.Models; |
||||
|
using System.Collections.ObjectModel; |
||||
|
using System.Data; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.NotificationView; |
||||
|
|
||||
|
public partial class NoticePage : ContentPage |
||||
|
{ |
||||
|
public ObservableCollection<NotificationItem> NoticeItems { get; set; } = new(); |
||||
|
public NoticePage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
this.BindingContext = this; |
||||
|
LoadData(); // 加载数据
|
||||
|
} |
||||
|
|
||||
|
private void LoadData() |
||||
|
{ |
||||
|
// 假设这是你获取数据的地方
|
||||
|
var allData = DataService._NotificationData; |
||||
|
if (allData != null) |
||||
|
{ |
||||
|
// 清空旧数据
|
||||
|
NoticeItems.Clear(); |
||||
|
|
||||
|
// 按时间倒序,并只取最新的 N 条(例如 50 条)
|
||||
|
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.Notice); |
||||
|
|
||||
|
// 将数据添加到集合中,UI 会自动更新
|
||||
|
foreach (var item in itemsToShow) |
||||
|
{ |
||||
|
NoticeItems.Add(item); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.NotificationView.SystemPage" |
||||
|
Title="系统信息"> |
||||
|
<CollectionView x:Name="CardCollectionView" |
||||
|
ItemsSource="{Binding SystemItems}" |
||||
|
RemainingItemsThreshold="5" |
||||
|
RemainingItemsThresholdReached="CardCollectionView_RemainingItemsThresholdReached"> |
||||
|
<!-- 保持滚动条 --> |
||||
|
<CollectionView.ItemTemplate> |
||||
|
<DataTemplate> |
||||
|
<!-- 这里定义单个卡片的 UI 结构 --> |
||||
|
<Border BackgroundColor="White" |
||||
|
Stroke="#CCCCCC" |
||||
|
StrokeThickness="1" |
||||
|
Margin="10,0,10,10" |
||||
|
StrokeShape="RoundRectangle 10"> |
||||
|
<Grid Padding="15"> |
||||
|
<VerticalStackLayout> |
||||
|
<Label Text="{Binding Title}" |
||||
|
FontAttributes="Bold" |
||||
|
FontSize="22" |
||||
|
TextColor="Black"/> |
||||
|
<Label Text="{Binding Time}" |
||||
|
FontSize="14" |
||||
|
TextColor="Black" |
||||
|
LineBreakMode="WordWrap"/> |
||||
|
<Label Text="{Binding Content}" |
||||
|
FontSize="16" |
||||
|
TextColor="Gray" |
||||
|
LineBreakMode="WordWrap"/> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
</DataTemplate> |
||||
|
</CollectionView.ItemTemplate> |
||||
|
</CollectionView> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,42 @@ |
|||||
|
using Microsoft.Maui.Controls.Shapes; |
||||
|
using SunlightAggregationTerminal.Models; |
||||
|
using System.Collections.ObjectModel; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.NotificationView; |
||||
|
|
||||
|
public partial class SystemPage : ContentPage |
||||
|
{ |
||||
|
public ObservableCollection<NotificationItem> SystemItems { get; set; } = new(); |
||||
|
public SystemPage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
this.BindingContext = this; |
||||
|
LoadData(); // 加载数据
|
||||
|
} |
||||
|
|
||||
|
private void LoadData() |
||||
|
{ |
||||
|
// 假设这是你获取数据的地方
|
||||
|
var allData = DataService._NotificationData; |
||||
|
if (allData != null) |
||||
|
{ |
||||
|
// 清空旧数据
|
||||
|
SystemItems.Clear(); |
||||
|
|
||||
|
// 按时间倒序,并只取最新的 N 条(例如 50 条)
|
||||
|
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.System); |
||||
|
|
||||
|
// 将数据添加到集合中,UI 会自动更新
|
||||
|
foreach (var item in itemsToShow) |
||||
|
{ |
||||
|
SystemItems.Add(item); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
|
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true"></application> |
||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
||||
|
<uses-permission android:name="android.permission.INTERNET" /> |
||||
|
<uses-permission android:name="android.permission.CAMERA" /> |
||||
|
</manifest> |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Android.App; |
||||
|
using Android.Content.PM; |
||||
|
using Android.OS; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal |
||||
|
{ |
||||
|
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] |
||||
|
public class MainActivity : MauiAppCompatActivity |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using Android.App; |
||||
|
using Android.Runtime; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal |
||||
|
{ |
||||
|
[Application(UsesCleartextTraffic = true)] |
||||
|
public class MainApplication : MauiApplication |
||||
|
{ |
||||
|
public MainApplication(IntPtr handle, JniHandleOwnership ownership) |
||||
|
: base(handle, ownership) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<resources> |
||||
|
<color name="colorPrimary">#512BD4</color> |
||||
|
<color name="colorPrimaryDark">#2B0B98</color> |
||||
|
<color name="colorAccent">#2B0B98</color> |
||||
|
</resources> |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Foundation; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal |
||||
|
{ |
||||
|
[Register("AppDelegate")] |
||||
|
public class AppDelegate : MauiUIApplicationDelegate |
||||
|
{ |
||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
|
<plist version="1.0"> |
||||
|
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.--> |
||||
|
<dict> |
||||
|
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. --> |
||||
|
<key>com.apple.security.app-sandbox</key> |
||||
|
<true/> |
||||
|
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. --> |
||||
|
<key>com.apple.security.network.client</key> |
||||
|
<true/> |
||||
|
</dict> |
||||
|
</plist> |
||||
|
|
||||
@ -0,0 +1,40 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
|
<plist version="1.0"> |
||||
|
<dict> |
||||
|
<!-- The Mac App Store requires you specify if the app uses encryption. --> |
||||
|
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption --> |
||||
|
<!-- <key>ITSAppUsesNonExemptEncryption</key> --> |
||||
|
<!-- Please indicate <true/> or <false/> here. --> |
||||
|
|
||||
|
<!-- Specify the category for your app here. --> |
||||
|
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype --> |
||||
|
<!-- <key>LSApplicationCategoryType</key> --> |
||||
|
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> --> |
||||
|
<key>UIDeviceFamily</key> |
||||
|
<array> |
||||
|
<integer>2</integer> |
||||
|
</array> |
||||
|
<key>LSApplicationCategoryType</key> |
||||
|
<string>public.app-category.lifestyle</string> |
||||
|
<key>UIRequiredDeviceCapabilities</key> |
||||
|
<array> |
||||
|
<string>arm64</string> |
||||
|
</array> |
||||
|
<key>UISupportedInterfaceOrientations</key> |
||||
|
<array> |
||||
|
<string>UIInterfaceOrientationPortrait</string> |
||||
|
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
|
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
|
</array> |
||||
|
<key>UISupportedInterfaceOrientations~ipad</key> |
||||
|
<array> |
||||
|
<string>UIInterfaceOrientationPortrait</string> |
||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
||||
|
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
|
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
|
</array> |
||||
|
<key>XSAppIconAssets</key> |
||||
|
<string>Assets.xcassets/appicon.appiconset</string> |
||||
|
</dict> |
||||
|
</plist> |
||||
@ -0,0 +1,16 @@ |
|||||
|
using ObjCRuntime; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal |
||||
|
{ |
||||
|
public class Program |
||||
|
{ |
||||
|
// This is the main entry point of the application.
|
||||
|
static void Main(string[] args) |
||||
|
{ |
||||
|
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
|
// you can specify it here.
|
||||
|
UIApplication.Main(args, null, typeof(AppDelegate)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
<maui:MauiWinUIApplication |
||||
|
x:Class="SunlightAggregationTerminal.WinUI.App" |
||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
xmlns:maui="using:Microsoft.Maui" |
||||
|
xmlns:local="using:SunlightAggregationTerminal.WinUI"> |
||||
|
|
||||
|
</maui:MauiWinUIApplication> |
||||
@ -0,0 +1,25 @@ |
|||||
|
using Microsoft.UI.Xaml; |
||||
|
|
||||
|
// To learn more about WinUI, the WinUI project structure,
|
||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
|
||||
|
namespace SunlightAggregationTerminal.WinUI |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||
|
/// </summary>
|
||||
|
public partial class App : MauiWinUIApplication |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
|
/// </summary>
|
||||
|
public App() |
||||
|
{ |
||||
|
this.InitializeComponent(); |
||||
|
} |
||||
|
|
||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Package |
||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" |
||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" |
||||
|
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" |
||||
|
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" |
||||
|
IgnorableNamespaces="uap rescap"> |
||||
|
|
||||
|
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" /> |
||||
|
|
||||
|
<mp:PhoneIdentity PhoneProductId="40C4D887-7034-46F6-A7C2-185E7FC94FC4" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> |
||||
|
|
||||
|
<Properties> |
||||
|
<DisplayName>$placeholder$</DisplayName> |
||||
|
<PublisherDisplayName>User Name</PublisherDisplayName> |
||||
|
<Logo>$placeholder$.png</Logo> |
||||
|
</Properties> |
||||
|
|
||||
|
<Dependencies> |
||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> |
||||
|
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> |
||||
|
</Dependencies> |
||||
|
|
||||
|
<Resources> |
||||
|
<Resource Language="x-generate" /> |
||||
|
</Resources> |
||||
|
|
||||
|
<Applications> |
||||
|
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"> |
||||
|
<uap:VisualElements |
||||
|
DisplayName="$placeholder$" |
||||
|
Description="$placeholder$" |
||||
|
Square150x150Logo="$placeholder$.png" |
||||
|
Square44x44Logo="$placeholder$.png" |
||||
|
BackgroundColor="transparent"> |
||||
|
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" /> |
||||
|
<uap:SplashScreen Image="$placeholder$.png" /> |
||||
|
</uap:VisualElements> |
||||
|
</Application> |
||||
|
</Applications> |
||||
|
|
||||
|
<Capabilities> |
||||
|
<rescap:Capability Name="runFullTrust" /> |
||||
|
</Capabilities> |
||||
|
|
||||
|
</Package> |
||||
@ -0,0 +1,17 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
||||
|
<assemblyIdentity version="1.0.0.0" name="SunlightAggregationTerminal.WinUI.app"/> |
||||
|
|
||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3"> |
||||
|
<windowsSettings> |
||||
|
<!-- The combination of below two tags have the following effect: |
||||
|
1) Per-Monitor for >= Windows 10 Anniversary Update |
||||
|
2) System < Windows 10 Anniversary Update |
||||
|
--> |
||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware> |
||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness> |
||||
|
|
||||
|
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> |
||||
|
</windowsSettings> |
||||
|
</application> |
||||
|
</assembly> |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Foundation; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal |
||||
|
{ |
||||
|
[Register("AppDelegate")] |
||||
|
public class AppDelegate : MauiUIApplicationDelegate |
||||
|
{ |
||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
|
<plist version="1.0"> |
||||
|
<dict> |
||||
|
<key>LSRequiresIPhoneOS</key> |
||||
|
<true/> |
||||
|
<key>UIDeviceFamily</key> |
||||
|
<array> |
||||
|
<integer>1</integer> |
||||
|
<integer>2</integer> |
||||
|
</array> |
||||
|
<key>UIRequiredDeviceCapabilities</key> |
||||
|
<array> |
||||
|
<string>arm64</string> |
||||
|
</array> |
||||
|
<key>UISupportedInterfaceOrientations</key> |
||||
|
<array> |
||||
|
<string>UIInterfaceOrientationPortrait</string> |
||||
|
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
|
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
|
</array> |
||||
|
<key>UISupportedInterfaceOrientations~ipad</key> |
||||
|
<array> |
||||
|
<string>UIInterfaceOrientationPortrait</string> |
||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
||||
|
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
|
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
|
</array> |
||||
|
<key>XSAppIconAssets</key> |
||||
|
<string>Assets.xcassets/appicon.appiconset</string> |
||||
|
</dict> |
||||
|
</plist> |
||||
@ -0,0 +1,16 @@ |
|||||
|
using ObjCRuntime; |
||||
|
using UIKit; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal |
||||
|
{ |
||||
|
public class Program |
||||
|
{ |
||||
|
// This is the main entry point of the application.
|
||||
|
static void Main(string[] args) |
||||
|
{ |
||||
|
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
|
// you can specify it here.
|
||||
|
UIApplication.Main(args, null, typeof(AppDelegate)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!-- |
||||
|
This is the minimum required version of the Apple Privacy Manifest for .NET MAUI apps. |
||||
|
The contents below are needed because of APIs that are used in the .NET framework and .NET MAUI SDK. |
||||
|
|
||||
|
You are responsible for adding extra entries as needed for your application. |
||||
|
|
||||
|
More information: https://aka.ms/maui-privacy-manifest |
||||
|
--> |
||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
|
<plist version="1.0"> |
||||
|
<dict> |
||||
|
<key>NSPrivacyAccessedAPITypes</key> |
||||
|
<array> |
||||
|
<dict> |
||||
|
<key>NSPrivacyAccessedAPIType</key> |
||||
|
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string> |
||||
|
<key>NSPrivacyAccessedAPITypeReasons</key> |
||||
|
<array> |
||||
|
<string>C617.1</string> |
||||
|
</array> |
||||
|
</dict> |
||||
|
<dict> |
||||
|
<key>NSPrivacyAccessedAPIType</key> |
||||
|
<string>NSPrivacyAccessedAPICategorySystemBootTime</string> |
||||
|
<key>NSPrivacyAccessedAPITypeReasons</key> |
||||
|
<array> |
||||
|
<string>35F9.1</string> |
||||
|
</array> |
||||
|
</dict> |
||||
|
<dict> |
||||
|
<key>NSPrivacyAccessedAPIType</key> |
||||
|
<string>NSPrivacyAccessedAPICategoryDiskSpace</string> |
||||
|
<key>NSPrivacyAccessedAPITypeReasons</key> |
||||
|
<array> |
||||
|
<string>E174.1</string> |
||||
|
</array> |
||||
|
</dict> |
||||
|
<!-- |
||||
|
The entry below is only needed when you're using the Preferences API in your app. |
||||
|
<dict> |
||||
|
<key>NSPrivacyAccessedAPIType</key> |
||||
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string> |
||||
|
<key>NSPrivacyAccessedAPITypeReasons</key> |
||||
|
<array> |
||||
|
<string>CA92.1</string> |
||||
|
</array> |
||||
|
</dict> --> |
||||
|
</array> |
||||
|
</dict> |
||||
|
</plist> |
||||
@ -0,0 +1,224 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.ProfilePage" |
||||
|
Title=""> |
||||
|
<Grid RowDefinitions="Auto, *" |
||||
|
ColumnDefinitions="*, Auto" |
||||
|
BackgroundColor="#F5F5F5"> |
||||
|
<!-- 顶部个人信息区 --> |
||||
|
<Border Padding="20" |
||||
|
Grid.Row="0" |
||||
|
Grid.Column="0" > |
||||
|
<Grid RowDefinitions="Auto, *" |
||||
|
ColumnDefinitions="*, Auto"> |
||||
|
<HorizontalStackLayout VerticalOptions="Center" Spacing="15"> |
||||
|
<!-- 信息 --> |
||||
|
<VerticalStackLayout Grid.Row="0" Grid.Column="0" |
||||
|
VerticalOptions="Center"> |
||||
|
<Label Text="{Binding UserName}" |
||||
|
FontSize="26" |
||||
|
FontAttributes="Bold" |
||||
|
TextColor="Black" /> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="ID:" FontSize="12" TextColor="Gray" Margin="0,0,0,0"/> |
||||
|
<Label Text="{Binding UserId}" FontSize="12" TextColor="Gray" Margin="0,0,0,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
</VerticalStackLayout> |
||||
|
</HorizontalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
|
||||
|
<ScrollView Grid.Row="1" Grid.Column="0"> |
||||
|
<VerticalStackLayout Spacing="0" Padding="0"> |
||||
|
<Border BackgroundColor="White" Stroke="#CCCCCC" Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
||||
|
<Grid> |
||||
|
<VerticalStackLayout Spacing="0" Padding="0"> |
||||
|
<Label Text="管理" FontSize="12" TextColor="Gray" Margin="15,5,0,5" /> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0" /> |
||||
|
|
||||
|
<VerticalStackLayout> |
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="公司:" VerticalOptions="Center" /> |
||||
|
<Label Text="{Binding Enterprise}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
</ContentView> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
||||
|
|
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="部门:" VerticalOptions="Center" /> |
||||
|
<Label Text="{Binding Department}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
</ContentView> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
||||
|
|
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="组:" VerticalOptions="Center" /> |
||||
|
<Label Text="{Binding Groups}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
</ContentView> |
||||
|
</VerticalStackLayout> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
<!-- 账号与安全 --> |
||||
|
<Border BackgroundColor="White" Stroke="#CCCCCC" Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
||||
|
<Grid> |
||||
|
<VerticalStackLayout Spacing="0" Padding="0"> |
||||
|
<Label Text="账号" FontSize="12" TextColor="Gray" Margin="15,5,0,5" /> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0" /> |
||||
|
|
||||
|
<VerticalStackLayout> |
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="账号:" VerticalOptions="Center" /> |
||||
|
<Label Text="{Binding User}" TextColor="Gray" |
||||
|
VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
</ContentView> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
||||
|
|
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<Grid> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="姓名:" VerticalOptions="Center" /> |
||||
|
<Label Text="{Binding UserName}" TextColor="Gray" |
||||
|
VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
<Label Text=">" TextColor="Gray" |
||||
|
VerticalOptions="Center" HorizontalOptions="End" |
||||
|
Margin="0,0,10,0" FontSize="24"/> |
||||
|
</Grid> |
||||
|
<ContentView.GestureRecognizers> |
||||
|
<TapGestureRecognizer Tapped="UserName_Tapped"/> |
||||
|
</ContentView.GestureRecognizers> |
||||
|
</ContentView> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<Grid> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="密码:" VerticalOptions="Center" /> |
||||
|
<Label Text="******" TextColor="Gray" |
||||
|
VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
<Label Text=">" TextColor="Gray" |
||||
|
VerticalOptions="Center" HorizontalOptions="End" |
||||
|
Margin="0,0,10,0" FontSize="24"/> |
||||
|
</Grid> |
||||
|
<ContentView.GestureRecognizers> |
||||
|
<TapGestureRecognizer Tapped="UserPassword_Tapped"/> |
||||
|
</ContentView.GestureRecognizers> |
||||
|
</ContentView> |
||||
|
</VerticalStackLayout> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- 通用设置 --> |
||||
|
<Border BackgroundColor="White" Stroke="#CCCCCC" |
||||
|
Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
||||
|
<Grid> |
||||
|
<VerticalStackLayout Spacing="0" Padding="0"> |
||||
|
<Label Text="通用" FontSize="12" |
||||
|
TextColor="Gray" Margin="15,10,0,5" /> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" /> |
||||
|
<VerticalStackLayout> |
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<Grid> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="空间清理" VerticalOptions="Center"/> |
||||
|
<Label Text="" TextColor="Gray" |
||||
|
VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
<Label Text=">" TextColor="Gray" |
||||
|
VerticalOptions="Center" HorizontalOptions="End" |
||||
|
Margin="0,0,10,0" FontSize="24"/> |
||||
|
</Grid> |
||||
|
</ContentView> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
||||
|
<ContentView HeightRequest="40" Padding="15,0"> |
||||
|
<Grid VerticalOptions="Center"> |
||||
|
<Label Text="消息通知" VerticalOptions="Center" /> |
||||
|
<Switch IsToggled="{Binding MessageNotificationMode}" HorizontalOptions="End" |
||||
|
Toggled="MessageNotificationMode_Toggled" VerticalOptions="Center" /> |
||||
|
</Grid> |
||||
|
</ContentView> |
||||
|
<ContentView HeightRequest="40" Padding="15,0"> |
||||
|
<Grid VerticalOptions="Center"> |
||||
|
<Label Text="深色模式" VerticalOptions="Center"/> |
||||
|
<Switch IsToggled="{Binding DarkMode}" HorizontalOptions="End" |
||||
|
Toggled="DarkMode_Toggled" VerticalOptions="Center"/> |
||||
|
</Grid> |
||||
|
</ContentView> |
||||
|
|
||||
|
</VerticalStackLayout> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0,0,0,0" /> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- 连接设置 --> |
||||
|
<Border BackgroundColor="White" Stroke="#CCCCCC" Margin="5,5,5,0" StrokeShape="RoundRectangle 10"> |
||||
|
<Grid > |
||||
|
<VerticalStackLayout Spacing="0" Padding="0"> |
||||
|
<Label Text="连接" FontSize="12" TextColor="Gray" Margin="15,10,0,5" /> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" /> |
||||
|
<VerticalStackLayout> |
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<Grid> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="服务器:" VerticalOptions="Center" /> |
||||
|
<Label Text="{Binding ServerID}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
<Label Text=">" TextColor="Gray" VerticalOptions="Center" HorizontalOptions="End" |
||||
|
Margin="0,0,10,0" FontSize="24"/> |
||||
|
</Grid> |
||||
|
<ContentView.GestureRecognizers> |
||||
|
<TapGestureRecognizer Tapped="ServerID_Tapped"/> |
||||
|
</ContentView.GestureRecognizers> |
||||
|
</ContentView> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
||||
|
<ContentView HeightRequest="50" Padding="15,0"> |
||||
|
<Grid> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="代理:" VerticalOptions="Center" /> |
||||
|
<Label Text="{Binding ProxyID}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/> |
||||
|
</HorizontalStackLayout> |
||||
|
<Label Text=">" TextColor="Gray" VerticalOptions="Center" HorizontalOptions="End" |
||||
|
Margin="0,0,10,0" FontSize="24"/> |
||||
|
</Grid> |
||||
|
<ContentView.GestureRecognizers> |
||||
|
<TapGestureRecognizer Tapped="ProxyID_Tapped"/> |
||||
|
</ContentView.GestureRecognizers> |
||||
|
</ContentView> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" /> |
||||
|
<ContentView HeightRequest="40" Padding="15,0"> |
||||
|
<Grid VerticalOptions="Center"> |
||||
|
<Label Text="内网直连" VerticalOptions="Center" /> |
||||
|
<Switch IsToggled="{Binding LocalAreaNetworkMode}" HorizontalOptions="End" |
||||
|
Toggled="LocalAreaNetworkMode_Toggled" VerticalOptions="Center"/> |
||||
|
</Grid> |
||||
|
</ContentView> |
||||
|
</VerticalStackLayout> |
||||
|
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="0,0,0,0" /> |
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- 退出登录 --> |
||||
|
<Button x:Name="Out_Button" |
||||
|
Text="退出登录" |
||||
|
BackgroundColor="White" |
||||
|
TextColor="Red" |
||||
|
BorderColor="Red" |
||||
|
BorderWidth="1" |
||||
|
Margin="20, 30" |
||||
|
CornerRadius="8" |
||||
|
Clicked="Out_Clicked" /> |
||||
|
</VerticalStackLayout> |
||||
|
</ScrollView> |
||||
|
</Grid> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,97 @@ |
|||||
|
using CommunityToolkit.Mvvm.ComponentModel; |
||||
|
using SunlightAggregationTerminal.Models; |
||||
|
using SunlightAggregationTerminal.View; |
||||
|
using System.Collections.ObjectModel; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal; |
||||
|
|
||||
|
public partial class ProfilePage : ContentPage |
||||
|
{ |
||||
|
public ProfilePage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
this.BindingContext = App.GlobalData; |
||||
|
} |
||||
|
|
||||
|
private async void Out_Clicked(object sender, EventArgs e) |
||||
|
{ |
||||
|
bool shouldExit = await DisplayAlertAsync("退出确认", "确定要退出吗?", "是", "否"); |
||||
|
if (shouldExit) |
||||
|
{ |
||||
|
App.GlobalData.LogNo = false; |
||||
|
var logpage = new View.LogPage(); |
||||
|
await Navigation.PushModalAsync(logpage); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async void UserName_Tapped(object sender, TappedEventArgs e) |
||||
|
{ |
||||
|
string result = await DisplayPromptAsync("","姓名"); |
||||
|
|
||||
|
// 处理结果
|
||||
|
if (!string.IsNullOrWhiteSpace(result)) |
||||
|
{ |
||||
|
App.GlobalData.UserName=result; |
||||
|
string sql = @"UPDATE Users SET UserName = '" + App.GlobalData.UserName |
||||
|
+ "' WHERE User='" + App.GlobalData.User + "';"; |
||||
|
AppModels.Updata(sql); |
||||
|
} |
||||
|
} |
||||
|
private async void UserPassword_Tapped(object sender, TappedEventArgs e) |
||||
|
{ |
||||
|
string result = await DisplayPromptAsync("", "密码"); |
||||
|
|
||||
|
// 处理结果
|
||||
|
if (!string.IsNullOrWhiteSpace(result)) |
||||
|
{ |
||||
|
App.GlobalData.UserPassword = result; |
||||
|
string sql = @"UPDATE Users SET UserPassword = '" + App.GlobalData.UserPassword |
||||
|
+ "' WHERE User='" + App.GlobalData.User + "';"; |
||||
|
AppModels.Updata(sql); |
||||
|
} |
||||
|
} |
||||
|
private async void ServerID_Tapped(object sender, TappedEventArgs e) |
||||
|
{ |
||||
|
string result = await DisplayPromptAsync("", "服务器地址"); |
||||
|
|
||||
|
// 处理结果
|
||||
|
if (!string.IsNullOrWhiteSpace(result)) |
||||
|
{ |
||||
|
App.GlobalData.ServerID = result; |
||||
|
string sql = @"UPDATE Users SET ServerID = '" + App.GlobalData.ServerID |
||||
|
+ "' WHERE User='" + App.GlobalData.User + "';"; |
||||
|
AppModels.Updata(sql); |
||||
|
} |
||||
|
} |
||||
|
private async void ProxyID_Tapped(object sender, TappedEventArgs e) |
||||
|
{ |
||||
|
string result = await DisplayPromptAsync("", "代理"); |
||||
|
|
||||
|
// 处理结果
|
||||
|
if (!string.IsNullOrWhiteSpace(result)) |
||||
|
{ |
||||
|
App.GlobalData.ProxyID = result; |
||||
|
string sql = @"UPDATE Users SET ProxyID = '" + App.GlobalData.ProxyID |
||||
|
+ "' WHERE User='" + App.GlobalData.User + "';"; |
||||
|
AppModels.Updata(sql); |
||||
|
} |
||||
|
} |
||||
|
private void MessageNotificationMode_Toggled(object sender, ToggledEventArgs e) |
||||
|
{ |
||||
|
string sql = @"UPDATE Users SET MessageNotificationMode = "+ App.GlobalData.MessageNotificationMode |
||||
|
+ " WHERE User='" + App.GlobalData.User + "';"; |
||||
|
AppModels.Updata(sql); |
||||
|
} |
||||
|
private void DarkMode_Toggled(object sender, ToggledEventArgs e) |
||||
|
{ |
||||
|
string sql = @"UPDATE Users SET DarkMode = " + App.GlobalData.DarkMode |
||||
|
+ " WHERE User='" + App.GlobalData.User + "';"; |
||||
|
AppModels.Updata(sql); |
||||
|
} |
||||
|
private void LocalAreaNetworkMode_Toggled(object sender, ToggledEventArgs e) |
||||
|
{ |
||||
|
string sql = @"UPDATE Users SET LocalAreaNetworkMode = " + App.GlobalData.LocalAreaNetworkMode |
||||
|
+ " WHERE User='" + App.GlobalData.User + "';"; |
||||
|
AppModels.Updata(sql); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"profiles": { |
||||
|
"Windows Machine": { |
||||
|
"commandName": "Project", |
||||
|
"nativeDebugging": false |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.QueryPage" |
||||
|
Title=""> |
||||
|
<Grid RowDefinitions="Auto, *" ColumnDefinitions="*, Auto"> |
||||
|
<Border Grid.Row="0" |
||||
|
Grid.Column="0" |
||||
|
Stroke="#CCCCCC" |
||||
|
StrokeThickness="1" |
||||
|
StrokeShape="RoundRectangle 10" |
||||
|
BackgroundColor="White" |
||||
|
Padding="0,0" |
||||
|
VerticalOptions="Center" |
||||
|
Margin="10,10,0,10"> |
||||
|
<Entry x:Name="ResultEntry" |
||||
|
Grid.Row="0" |
||||
|
Grid.Column="0" |
||||
|
FontSize="Medium" |
||||
|
Placeholder="等待扫码..." |
||||
|
VerticalOptions="Center" |
||||
|
BackgroundColor="Transparent" |
||||
|
Margin="0,0,0,0" > |
||||
|
</Entry> |
||||
|
</Border> |
||||
|
<!--扫码按钮--> |
||||
|
<Button Grid.Row="0" |
||||
|
Grid.Column="1" |
||||
|
Clicked="OnScanButtonClicked" |
||||
|
BackgroundColor="Transparent" |
||||
|
WidthRequest="60" |
||||
|
HeightRequest="60" |
||||
|
Margin="10"> |
||||
|
<Button.ImageSource> |
||||
|
<!-- 设置图标 --> |
||||
|
<FileImageSource File="lucidescanline.png" /> |
||||
|
</Button.ImageSource> |
||||
|
</Button> |
||||
|
<VerticalStackLayout> |
||||
|
|
||||
|
</VerticalStackLayout> |
||||
|
</Grid> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,38 @@ |
|||||
|
namespace SunlightAggregationTerminal; |
||||
|
|
||||
|
public partial class QueryPage : ContentPage |
||||
|
{ |
||||
|
// 定义一个静态的回调动作
|
||||
|
public static Action<string>? OnScanQuery; |
||||
|
|
||||
|
public QueryPage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
OnScanQuery = (result) => |
||||
|
{ |
||||
|
MainThread.BeginInvokeOnMainThread(() => |
||||
|
{ |
||||
|
ResultEntry.Text = result; |
||||
|
}); |
||||
|
}; |
||||
|
} |
||||
|
private async void OnScanButtonClicked(object sender, EventArgs e) |
||||
|
{ |
||||
|
// 跳转到扫码页面
|
||||
|
await Navigation.PushAsync(new ScanPage(0)); |
||||
|
} |
||||
|
|
||||
|
// 处理“回车/完成”按钮点击
|
||||
|
/* private void OnEntryCompleted() |
||||
|
{ |
||||
|
string inputText = ResultEntry.Text; |
||||
|
|
||||
|
if (!string.IsNullOrWhiteSpace(inputText)) |
||||
|
{ |
||||
|
// 在这里处理用户手动输入的内容
|
||||
|
// 例如:验证格式、跳转页面、或者搜索商品
|
||||
|
//DisplayAlert("提示", $"你输入了: {inputText}", "确定");
|
||||
|
} |
||||
|
}*/ |
||||
|
|
||||
|
} |
||||
|
After Width: | Height: | Size: 228 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 90 KiB |
@ -0,0 +1,15 @@ |
|||||
|
Any raw assets you want to be deployed with your application can be placed in |
||||
|
this directory (and child directories). Deployment of the asset to your application |
||||
|
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. |
||||
|
|
||||
|
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> |
||||
|
|
||||
|
These files will be deployed with your package and will be accessible using Essentials: |
||||
|
|
||||
|
async Task LoadMauiAsset() |
||||
|
{ |
||||
|
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); |
||||
|
using var reader = new StreamReader(stream); |
||||
|
|
||||
|
var contents = reader.ReadToEnd(); |
||||
|
} |
||||
|
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,44 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<ResourceDictionary |
||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> |
||||
|
|
||||
|
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml --> |
||||
|
|
||||
|
<Color x:Key="Primary">#512BD4</Color> |
||||
|
<Color x:Key="PrimaryDark">#ac99ea</Color> |
||||
|
<Color x:Key="PrimaryDarkText">#242424</Color> |
||||
|
<Color x:Key="Secondary">#DFD8F7</Color> |
||||
|
<Color x:Key="SecondaryDarkText">#9880e5</Color> |
||||
|
<Color x:Key="Tertiary">#2B0B98</Color> |
||||
|
|
||||
|
<Color x:Key="White">White</Color> |
||||
|
<Color x:Key="Black">Black</Color> |
||||
|
<Color x:Key="Magenta">#D600AA</Color> |
||||
|
<Color x:Key="MidnightBlue">#190649</Color> |
||||
|
<Color x:Key="OffBlack">#1f1f1f</Color> |
||||
|
|
||||
|
<Color x:Key="Gray100">#E1E1E1</Color> |
||||
|
<Color x:Key="Gray200">#C8C8C8</Color> |
||||
|
<Color x:Key="Gray300">#ACACAC</Color> |
||||
|
<Color x:Key="Gray400">#919191</Color> |
||||
|
<Color x:Key="Gray500">#6E6E6E</Color> |
||||
|
<Color x:Key="Gray600">#404040</Color> |
||||
|
<Color x:Key="Gray900">#212121</Color> |
||||
|
<Color x:Key="Gray950">#141414</Color> |
||||
|
|
||||
|
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/> |
||||
|
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/> |
||||
|
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/> |
||||
|
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/> |
||||
|
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/> |
||||
|
|
||||
|
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/> |
||||
|
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/> |
||||
|
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/> |
||||
|
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/> |
||||
|
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/> |
||||
|
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/> |
||||
|
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/> |
||||
|
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/> |
||||
|
</ResourceDictionary> |
||||
@ -0,0 +1,434 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<ResourceDictionary |
||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> |
||||
|
|
||||
|
<Style TargetType="ActivityIndicator"> |
||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="IndicatorView"> |
||||
|
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/> |
||||
|
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Border"> |
||||
|
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
||||
|
<Setter Property="StrokeShape" Value="Rectangle"/> |
||||
|
<Setter Property="StrokeThickness" Value="1"/> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="BoxView"> |
||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Button"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
||||
|
<Setter Property="FontSize" Value="14"/> |
||||
|
<Setter Property="BorderWidth" Value="0"/> |
||||
|
<Setter Property="CornerRadius" Value="8"/> |
||||
|
<Setter Property="Padding" Value="14,10"/> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
<VisualState x:Name="PointerOver" /> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="CheckBox"> |
||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="DatePicker"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
||||
|
<Setter Property="FontSize" Value="14"/> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Editor"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
||||
|
<Setter Property="FontSize" Value="14" /> |
||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Entry"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
||||
|
<Setter Property="FontSize" Value="14" /> |
||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="ImageButton"> |
||||
|
<Setter Property="Opacity" Value="1" /> |
||||
|
<Setter Property="BorderColor" Value="Transparent"/> |
||||
|
<Setter Property="BorderWidth" Value="0"/> |
||||
|
<Setter Property="CornerRadius" Value="0"/> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="Opacity" Value="0.5" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
<VisualState x:Name="PointerOver" /> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Label"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" /> |
||||
|
<Setter Property="FontSize" Value="14" /> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Label" x:Key="Headline"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="FontSize" Value="32" /> |
||||
|
<Setter Property="HorizontalOptions" Value="Center" /> |
||||
|
<Setter Property="HorizontalTextAlignment" Value="Center" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Label" x:Key="SubHeadline"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="FontSize" Value="24" /> |
||||
|
<Setter Property="HorizontalOptions" Value="Center" /> |
||||
|
<Setter Property="HorizontalTextAlignment" Value="Center" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Picker"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
||||
|
<Setter Property="FontSize" Value="14" /> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="ProgressBar"> |
||||
|
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="RadioButton"> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent"/> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
||||
|
<Setter Property="FontSize" Value="14"/> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="RefreshView"> |
||||
|
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="SearchBar"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> |
||||
|
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" /> |
||||
|
<Setter Property="FontSize" Value="14" /> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="SearchHandler"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" /> |
||||
|
<Setter Property="FontSize" Value="14" /> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Shadow"> |
||||
|
<Setter Property="Radius" Value="15" /> |
||||
|
<Setter Property="Opacity" Value="0.5" /> |
||||
|
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="Offset" Value="10,10" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Slider"> |
||||
|
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> |
||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> |
||||
|
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> |
||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="SwipeItem"> |
||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Switch"> |
||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="ThumbColor" Value="{StaticResource White}" /> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
<VisualState x:Name="On"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" /> |
||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
<VisualState x:Name="Off"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="TimePicker"> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent"/> |
||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/> |
||||
|
<Setter Property="FontSize" Value="14"/> |
||||
|
<Setter Property="MinimumHeightRequest" Value="44"/> |
||||
|
<Setter Property="MinimumWidthRequest" Value="44"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="CommonStates"> |
||||
|
<VisualState x:Name="Normal" /> |
||||
|
<VisualState x:Name="Disabled"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- |
||||
|
<Style TargetType="TitleBar"> |
||||
|
<Setter Property="MinimumHeightRequest" Value="32"/> |
||||
|
<Setter Property="VisualStateManager.VisualStateGroups"> |
||||
|
<VisualStateGroupList> |
||||
|
<VisualStateGroup x:Name="TitleActiveStates"> |
||||
|
<VisualState x:Name="TitleBarTitleActive"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="BackgroundColor" Value="Transparent" /> |
||||
|
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
<VisualState x:Name="TitleBarTitleInactive"> |
||||
|
<VisualState.Setters> |
||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> |
||||
|
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" /> |
||||
|
</VisualState.Setters> |
||||
|
</VisualState> |
||||
|
</VisualStateGroup> |
||||
|
</VisualStateGroupList> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
--> |
||||
|
|
||||
|
<Style TargetType="Page" ApplyToDerivedTypes="True"> |
||||
|
<Setter Property="Padding" Value="0"/> |
||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="Shell" ApplyToDerivedTypes="True"> |
||||
|
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> |
||||
|
<Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> |
||||
|
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> |
||||
|
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> |
||||
|
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" /> |
||||
|
<Setter Property="Shell.NavBarHasShadow" Value="False" /> |
||||
|
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> |
||||
|
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="NavigationPage"> |
||||
|
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> |
||||
|
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style TargetType="TabbedPage"> |
||||
|
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" /> |
||||
|
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> |
||||
|
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> |
||||
|
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> |
||||
|
</Style> |
||||
|
|
||||
|
</ResourceDictionary> |
||||
@ -0,0 +1,19 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
||||
|
x:Class="SunlightAggregationTerminal.ScanPage" |
||||
|
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" |
||||
|
xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.Maui.Controls" |
||||
|
Title="扫一扫"> |
||||
|
<Grid> |
||||
|
<zxing:CameraBarcodeReaderView x:Name="barcodeReader" |
||||
|
BarcodesDetected="OnBarcodesDetected" |
||||
|
IsDetecting="True" |
||||
|
CameraLocation="Rear"/> |
||||
|
<GraphicsView x:Name="overlayGraphicsView" |
||||
|
IsVisible="False" |
||||
|
VerticalOptions="Fill" |
||||
|
HorizontalOptions="Fill" |
||||
|
BackgroundColor="Transparent" /> |
||||
|
</Grid> |
||||
|
</ContentPage> |
||||
@ -0,0 +1,30 @@ |
|||||
|
using SunlightAggregationTerminal.View; |
||||
|
using ZXing.Multi; |
||||
|
using ZXing.Net.Maui; |
||||
|
|
||||
|
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) QueryPage.OnScanQuery?.Invoke(firstResult.Value); |
||||
|
if (mode == 3) LogPage.OnScanProfile?.Invoke(firstResult.Value); |
||||
|
|
||||
|
await Navigation.PopAsync(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -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,65 @@ |
|||||
|
<?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="LogPage"> |
||||
|
|
||||
|
<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"> |
||||
|
<Label Text="服务器:" FontSize="26" TextColor="Black" /> |
||||
|
<Entry x:Name="Enterprise" |
||||
|
Text="IP" |
||||
|
FontSize="26" |
||||
|
TextColor="Gray" |
||||
|
WidthRequest="300"/> |
||||
|
</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"> |
||||
|
<Label Text="用户:" FontSize="26" TextColor="Black" /> |
||||
|
<!-- 用户名输入 --> |
||||
|
<Entry x:Name="UsernameEntry" |
||||
|
Placeholder="请输入用户名" |
||||
|
FontSize="26" |
||||
|
WidthRequest="380"/> |
||||
|
</HorizontalStackLayout> |
||||
|
<HorizontalStackLayout VerticalOptions="Center"> |
||||
|
<Label Text="密码:" FontSize="26" TextColor="Black"/> |
||||
|
<!-- 密码输入 --> |
||||
|
<Entry x:Name="PasswordEntry" |
||||
|
Placeholder="请输入密码" |
||||
|
IsPassword="True" |
||||
|
FontSize="26" |
||||
|
WidthRequest="380"/> |
||||
|
</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,61 @@ |
|||||
|
using SunlightAggregationTerminal.Class; |
||||
|
using SunlightAggregationTerminal.Models; |
||||
|
using System.Data; |
||||
|
|
||||
|
namespace SunlightAggregationTerminal.View; |
||||
|
|
||||
|
public partial class LogPage : ContentPage |
||||
|
{ |
||||
|
public static Action<string>? OnScanProfile; |
||||
|
public LogPage() |
||||
|
{ |
||||
|
InitializeComponent(); |
||||
|
OnScanProfile = (result) => |
||||
|
{ |
||||
|
MainThread.BeginInvokeOnMainThread(() => |
||||
|
{ |
||||
|
Enterprise.Text = result; |
||||
|
}); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
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,6 @@ |
|||||
|
<?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"> |
||||
|
</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!" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
||||