Administrator 2 months ago
parent
commit
2334555c7b
  1. 20
      Class/HttpServer.cs
  2. 17
      Class/SQLiteConfig.cs
  3. 6
      InfoDetail.xaml.cs
  4. 3
      Models/AppModels.cs
  5. 2
      Models/DataModel.cs
  6. 81
      Platforms/Android/NotificationService.cs
  7. 18
      ProfilePage.xaml
  8. 13
      ProfilePage.xaml.cs
  9. 1
      QueryDetail.xaml.cs
  10. 25
      QueryPage.xaml.cs
  11. 11
      Services/INotificationService.cs
  12. 9
      SunlightAggregationTerminal.csproj
  13. 41
      View/LogPage.xaml.cs

20
Class/HttpServer.cs

@ -22,7 +22,14 @@ namespace SunlightAggregationTerminal.Class
DataReceived.ServerPassword = Password;
DataReceived.ServerTerminal = Terminal;
await HttpClient(DataReceived.ServerIP);
if (string.IsNullOrWhiteSpace(ip))
{
App.GlobalData.LogNo = false;
}
else
{
await HttpClient(DataReceived.ServerIP);
}
}
public static async Task HttpClient(string url)
@ -52,13 +59,13 @@ namespace SunlightAggregationTerminal.Class
await e.InvokeNext();
});
});
config.ConfigurePlugins(a =>
/*config.ConfigurePlugins(a =>
{
a.UseReconnection<TouchSocket.Http.HttpClient>(options =>
{
options.PollingInterval = TimeSpan.FromSeconds(3);
});
});
});*/
#endregion
//配置config
@ -79,14 +86,11 @@ namespace SunlightAggregationTerminal.Class
Dat = Dat
};
var t = JsonSerializer.Serialize(dat);
var p = httpclient.RemoteIPHost.Host;
var request = new HttpRequest();
request.SetContent(new StringHttpContent(t, Encoding.UTF8, "application/scjson"))
request.SetContent(new StringHttpContent(JsonSerializer.Serialize(dat), Encoding.UTF8, "application/scjson"))
.InitHeaders()
.SetUrl("/api/user-report")
.SetHost(p)
.SetHost(httpclient.RemoteIPHost.Host)
.AsPost();
// 创建一个超时操作,10秒后取消

17
Class/SQLiteConfig.cs

@ -118,6 +118,12 @@ namespace SunlightAggregationTerminal.Class
string sql = "ALTER TABLE Users ADD COLUMN ServerID TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 ServerID
if (!existingColumns.Contains("ServerHTTP"))
{
string sql = "ALTER TABLE Users ADD COLUMN ServerHTTP TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 Group
if (!existingColumns.Contains("Groups"))
{
@ -250,7 +256,12 @@ namespace SunlightAggregationTerminal.Class
{
string sql = "ALTER TABLE Server ADD COLUMN ServerID TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
}
if (!existingColumns.Contains("ServerHTTP"))
{
string sql = "ALTER TABLE Server ADD COLUMN ServerHTTP TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
}
}
// --- 逻辑分支 表不存在,直接创建 ---
@ -266,6 +277,7 @@ namespace SunlightAggregationTerminal.Class
Enterprise TEXT,
Department TEXT,
ServerID TEXT,
ServerHTTP TEXT,
Groups TEXT,
ProxyID TEXT,
LogNo BOOL DEFAULT (0),
@ -307,7 +319,8 @@ namespace SunlightAggregationTerminal.Class
CREATE TABLE Server (
START BOOL DEFAULT (0),
Server TEXT,
ServerID TEXT
ServerID TEXT,
ServerHTTP TEXT
);";
// 复用现有的 ExecuteNonQuery 方法

6
InfoDetail.xaml.cs

@ -16,8 +16,6 @@ public partial class InfoDetail : ContentPage
InfoProbuctItems.Add(new ProbuctItem { ProductName="cs", ProductCode="cs", ProductState="", ProductInf="" });
InfoProbuctItems.Add(new ProbuctItem { ProductName = "c23s", ProductCode = "cweds", ProductState = "", ProductInf = "" });
InfoProbuctItems.Add(new ProbuctItem { ProductName = "arf", ProductCode = "af", ProductState = "", ProductInf = "" });
InfoProbuctItems.Add(new ProbuctItem { ProductName = "afars", ProductCode = "cs", ProductState = "", ProductInf = "" });
@ -26,6 +24,7 @@ public partial class InfoDetail : ContentPage
CardCollectionView_history.ItemsSource = InfoDyelotDetailsItems;
}
//设备信息
private void Button_real(object sender, EventArgs e)
{
_real.IsVisible = true;
@ -34,6 +33,7 @@ public partial class InfoDetail : ContentPage
_control.IsVisible = false;
}
//设备内容
private void Button_machine(object sender, EventArgs e)
{
_real.IsVisible = false;
@ -42,6 +42,7 @@ public partial class InfoDetail : ContentPage
_control.IsVisible = false;
}
//历史
private void Button_history(object sender, EventArgs e)
{
_real.IsVisible = false;
@ -50,6 +51,7 @@ public partial class InfoDetail : ContentPage
_control.IsVisible = false;
}
//远程
private async void Button_control(object sender, EventArgs e)
{
_real.IsVisible = false;

3
Models/AppModels.cs

@ -34,6 +34,7 @@ namespace SunlightAggregationTerminal.Models
App.GlobalData.Department = dat.Field<string>("Department") ?? "";
App.GlobalData.Groups = dat.Field<string>("Groups") ?? "";
App.GlobalData.ServerID = dat.Field<string>("ServerID") ?? "";
App.GlobalData.ServerHTTP = dat.Field<string>("ServerHTTP") ?? "";
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"));
@ -83,7 +84,7 @@ namespace SunlightAggregationTerminal.Models
else
{
//http
HttpServer.Configuration(App.GlobalData.ServerID,
HttpServer.Configuration(App.GlobalData.ServerHTTP,
App.GlobalData.User, App.GlobalData.UserPassword,
GetAppUniqueId());
}

2
Models/DataModel.cs

@ -23,6 +23,8 @@ namespace SunlightAggregationTerminal.Models
[ObservableProperty]
public partial string ServerID { get; set; }
[ObservableProperty]
public partial string ServerHTTP { get; set; }
[ObservableProperty]
public partial string Groups { get; set; }
[ObservableProperty]
public partial string ProxyID { get; set; }

81
Platforms/Android/NotificationService.cs

@ -0,0 +1,81 @@
using Android.App;
using Android.Content;
using Android.OS;
using AndroidX.Core.App;
using SunlightAggregationTerminal;
// 使用 global:: 强制指定原生安卓的命名空间
using AndroidApp = global::Android.App;
namespace SunlightAggregationTerminal.Platforms.Android
{
public class NotificationService : INotificationService
{
const string channelId = "default_channel";
const string channelName = "Default Notifications";
const string channelDescription = "Default notification channel";
public void SendNotification(string title, string message, int notificationId = 0)
{
// 1. 创建通知渠道(仅 Android 8.0 / API 26 及以上需要)
#pragma warning disable CA1416 // 暂时关闭平台兼容性警告
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channel = new AndroidApp.NotificationChannel(channelId, channelName, NotificationImportance.Default)
{
Description = channelDescription
};
// 修复点:获取系统服务并处理可能的 null 值
// 如果 GetSystemService 返回 null,则直接 return 终止方法,防止后续崩溃
var notificationManager = AndroidApp.Application.Context.GetSystemService(Context.NotificationService) as AndroidApp.NotificationManager;
if (notificationManager == null) return;
notificationManager.CreateNotificationChannel(channel);
}
#pragma warning restore CA1416 // 恢复平台兼容性警告
// 2. 构建通知内容
var intent = new Intent(AndroidApp.Application.Context, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
#pragma warning disable CA1416
// PendingIntent 同样建议做安全获取
var pendingIntent = PendingIntent.GetActivity(AndroidApp.Application.Context, 0, intent, PendingIntentFlags.Immutable | PendingIntentFlags.UpdateCurrent);
#pragma warning restore CA1416 // 恢复平台兼容性警告
NotificationCompat.Builder notificationBuilder;
// 核心兼容处理:根据系统版本选择不同的 Builder 构造方法
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
// Android 8.0+:必须传入 channelId
notificationBuilder = new NotificationCompat.Builder(AndroidApp.Application.Context, channelId);
}
else
{
#pragma warning disable CS0618
// Android 5.0 ~ 7.x:不支持 channelId,使用旧版单参数构造方法
notificationBuilder = new NotificationCompat.Builder(AndroidApp.Application.Context);
#pragma warning restore CS0618
}
var notification = notificationBuilder!
.SetContentTitle(title)!
.SetContentText(message)!
// 请确保你的 Resources/drawable 文件夹下有这个图标
//.SetSmallIcon(Resource.Drawable.abc_vector_test)!
.SetAutoCancel(true)!
.SetContentIntent(pendingIntent);
// 如果是 Android 5.0 (API 21) 及以上,还可以设置锁屏可见等特性
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
notification!.SetVisibility(NotificationCompat.VisibilityPublic);
}
// 3. 发送通知
var compatManager = NotificationManagerCompat.From(AndroidApp.Application.Context);
compatManager!.Notify(notificationId, notification!.Build());
}
}
}

18
ProfilePage.xaml

@ -2,6 +2,8 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SunlightAggregationTerminal.ProfilePage"
xmlns:vm="clr-namespace:SunlightAggregationTerminal.Models"
x:DataType="vm:DataModel"
Title="">
<Grid RowDefinitions="Auto, *"
ColumnDefinitions="*, Auto"
@ -170,7 +172,7 @@
<ContentView HeightRequest="50" Padding="15,0">
<Grid>
<HorizontalStackLayout VerticalOptions="Center">
<Label Text="服务器:" VerticalOptions="Center" />
<Label Text="服务器(TCP):" VerticalOptions="Center" />
<Label Text="{Binding ServerID}" TextColor="Gray" VerticalOptions="Center" Margin="0,0,10,0"/>
</HorizontalStackLayout>
<Label Text=">" TextColor="Gray" VerticalOptions="Center" HorizontalOptions="End"
@ -181,6 +183,20 @@
</ContentView.GestureRecognizers>
</ContentView>
<BoxView HeightRequest="1" Color="#E0E0E0" Margin="15,0" />
<ContentView HeightRequest="50" Padding="15,0">
<Grid>
<HorizontalStackLayout VerticalOptions="Center">
<Label Text="服务器(HTTP):" VerticalOptions="Center" />
<Label Text="{Binding ServerHTTP}" 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="50" Padding="15,0">
<Grid>
<HorizontalStackLayout VerticalOptions="Center">

13
ProfilePage.xaml.cs

@ -70,6 +70,19 @@ public partial class ProfilePage : ContentPage
AppModels.Updata(sql);
}
}
private async void ServerHTTP_Tapped(object sender, TappedEventArgs e)
{
string result = await DisplayPromptAsync("", "服务器地址");
// 处理结果
if (!string.IsNullOrWhiteSpace(result))
{
App.GlobalData.ServerID = result;
string sql = @"UPDATE Users SET ServerHTTP = '" + App.GlobalData.ServerID
+ "' WHERE User='" + App.GlobalData.User + "';";
AppModels.Updata(sql);
}
}
private async void ProxyID_Tapped(object sender, TappedEventArgs e)
{
string result = await DisplayPromptAsync("", "代理");

1
QueryDetail.xaml.cs

@ -52,6 +52,7 @@ public partial class QueryDetail : ContentPage
$"目标/实际: {list[i].GramsDisplay}g / {list[i].DispenseGramsDisplay}g")
);
// 赋值给最终展示的 ProductName
if (list[0].Process !=null) combinedInfo = combinedInfo + "\n溶解流程:"+ list[0].Process;
firstItem.ProductName = combinedInfo;
return firstItem;
})

25
QueryPage.xaml.cs

@ -17,7 +17,18 @@ public partial class QueryPage : ContentPage
WeakReferenceMessenger.Default.Register<string>(this, (r, scannedValue) =>
{
ResultEntry.Text = scannedValue;
ResultEntry.Text = scannedValue;
//扫码返回信息
if (!string.IsNullOrWhiteSpace(scannedValue))
{
Dictionary<string, object> QueryDictionary = new Dictionary<string, object>();
QueryDictionary.Add("Command", "QueryDyelot");
QueryDictionary.Add("Field", "[Dyelot],[ReDye],[Program],[Color],[CreationTime]," +
"[Batch],[OrderNo],[TotalWeight],[LiquidRatio],[TotalVolume],[Final],[UserAccount]," +
"[FabricName],[ColorName],[CustomerName],[Notes]");
QueryDictionary.Add("DyelotName", scannedValue);
Query_Command(QueryDictionary.ToJsonString());
}
});
Query_data();
@ -129,10 +140,14 @@ public partial class QueryPage : ContentPage
if (!string.IsNullOrWhiteSpace(inputText))
{
// 在这里处理用户手动输入的内容
// 例如:验证格式、跳转页面、或者搜索商品
//DisplayAlert("提示", $"你输入了: {inputText}", "确定");
}
Dictionary<string, object> QueryDictionary = new Dictionary<string, object>();
QueryDictionary.Add("Command", "QueryDyelot");
QueryDictionary.Add("Field", "[Dyelot],[ReDye],[Program],[Color],[CreationTime]," +
"[Batch],[OrderNo],[TotalWeight],[LiquidRatio],[TotalVolume],[Final],[UserAccount]," +
"[FabricName],[ColorName],[CustomerName],[Notes]");
QueryDictionary.Add("DyelotName", inputText);
Query_Command(QueryDictionary.ToJsonString());
}
}*/
}

11
Services/INotificationService.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SunlightAggregationTerminal
{
public interface INotificationService
{
void SendNotification(string title, string message, int notificationId = 0);
}
}

9
SunlightAggregationTerminal.csproj

@ -73,15 +73,6 @@
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<AndroidResource Remove="Services\**" />
<Compile Remove="Services\**" />
<EmbeddedResource Remove="Services\**" />
<MauiCss Remove="Services\**" />
<MauiXaml Remove="Services\**" />
<None Remove="Services\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Images\adduserfilled.svg" />
<None Remove="Images\infofeed.svg" />

41
View/LogPage.xaml.cs

@ -4,6 +4,7 @@ using SunlightAggregationTerminal.Models;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using static System.Net.Mime.MediaTypeNames;
namespace SunlightAggregationTerminal.View;
@ -42,7 +43,8 @@ public partial class LogPage : ContentPage
var dat = new ItemOption
{
SERVER = dataRow.Field<string>("Server") ?? "",
SERVERIP = dataRow.Field<string>("ServerID") ?? ""
SERVERIP = dataRow.Field<string>("ServerID") ?? "" +","+
dataRow.Field<string>("ServerHTTP") ?? ""
};
Items.Add(dat);
}
@ -76,41 +78,54 @@ public partial class LogPage : ContentPage
{
LoadingIndicator.IsVisible = true;
App.GlobalData.ServerID = SERVERIP.Text;
string[] result = SERVERIP.Text.Split(',', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
App.GlobalData.ServerID = result[0]?? "";
//判断是否有http连接信息
if (result.Length == 2)
{
App.GlobalData.ServerHTTP = result[1] ?? "";
}
else
{
App.GlobalData.LocalAreaNetworkMode = true;
}
App.GlobalData.User = UsernameEntry.Text;
App.GlobalData.UserPassword = PasswordEntry.Text;
if (await AppModels.LogIn())
{
App.GlobalData.ServerID = SERVERIP.Text;
int temp_name = AppModels.Select("SELECT * FROM Users WHERE User='" + UsernameEntry.Text + "' LIMIT 1;")!.Tables[0].Rows.Count;
if (temp_name >0)
{
//存在更新账号状态
string sql = "UPDATE Users SET ServerID = '" + SERVERIP.Text
+ "', UserPassword = '" + PasswordEntry.Text +
"', LogNo = 1 WHERE User='" + UsernameEntry.Text + "';";
string sql = "UPDATE Users SET ServerID = '" + App.GlobalData.ServerID
+ "', ServerHTTP = '" + App.GlobalData.ServerHTTP
+ "', UserPassword = '" + PasswordEntry.Text
+"', LogNo = 1 WHERE User='" + UsernameEntry.Text + "';";
AppModels.Updata(sql);
}
else
{
//插入账号
string sql = @"INSERT INTO Users (User,UserId ,UserName ,UserPassword ,
Enterprise ,Department ,ServerID ,Groups ,
Enterprise ,Department ,ServerID ,ServerHTTP ,Groups ,
ProxyID ,LogNo ,LocalAreaNetworkMode ,DarkMode ,
MessageNotificationMode ,GUID
)VALUES('" + UsernameEntry.Text + "','SUNLIGHT','SUNLIGHT','" + PasswordEntry.Text +
"','SUNLIGHT','ENGINEER','" + SERVERIP.Text + "','ENGINEER'," +
)VALUES('" + UsernameEntry.Text + "','"+ App.GlobalData.UserId +
"','" + App.GlobalData.UserName + "','" + PasswordEntry.Text +
"','"+ App.GlobalData.Enterprise + "','"+ App.GlobalData.Department +
"','" + App.GlobalData.ServerID + "','" +App.GlobalData.ServerHTTP+
"','"+ App.GlobalData.Groups + "'," +
" '',1,0,0,0,'" + Models.AppModels.GetAppUniqueId() + "');";
AppModels.INSERT(sql);
}
int temp_server = AppModels.Select("SELECT * FROM Server WHERE ServerID='" + SERVERIP.Text + "' LIMIT 1;")!.Tables[0].Rows.Count;
int temp_server = AppModels.Select("SELECT * FROM Server WHERE ServerID='' LIMIT 1;")!.Tables[0].Rows.Count;
if (temp_server == 0)
{
string sql = @"INSERT INTO Server ( Server, ServerID)VALUES('" + App.GlobalData.Enterprise + "','" +
App.GlobalData.ServerID + "');";
string sql = @"INSERT INTO Server ( Server, ServerID,ServerHTTP)VALUES('" + App.GlobalData.Enterprise + "','" +
App.GlobalData.ServerID+ App.GlobalData.ServerHTTP + "');";
AppModels.INSERT(sql);
}

Loading…
Cancel
Save