Compare commits

...
110 Commits
Author SHA1 Message Date
sc 40f380f95f Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-07-19 13:43:02 +08:00
Administrator f8da62df7d Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-19 13:43:01 +08:00
Administrator ff289a0221 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-11 17:02:07 +08:00
Administrator a14f490032 添加统计日期选择功能 2026-07-11 17:02:03 +08:00
Administrator af28d6eba3 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-11 16:28:05 +08:00
Administrator f80d3f4950 查询页面单号输入空数据问题修复 2026-07-11 16:28:01 +08:00
Administrator 40392fccb4 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-10 16:49:05 +08:00
Administrator 95b61a35ac Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-10 16:49:04 +08:00
Administrator ad9cd88b41 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-10 16:21:45 +08:00
Administrator 0122e98b4d Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-10 16:21:42 +08:00
Administrator 7b0517c59c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-03 14:47:41 +08:00
Administrator 18cc18740c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-03 14:47:40 +08:00
Administrator 69f2a4e4ed Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-07-03 13:03:19 +08:00
Administrator ee07bb7eca AES 2026-07-03 13:03:16 +08:00
Administrator 5f3f2ab7bb Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-23 17:28:30 +08:00
sc 2af3cccba8 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-23 17:28:28 +08:00
sc 6dbfa0610e Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-21 19:34:00 +08:00
sc 395f066568 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-21 19:33:59 +08:00
sc 2e3f894a4d Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-21 19:04:27 +08:00
sc 9e94b03bc4 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-21 19:04:25 +08:00
sc 9a3c8f0d80 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-21 19:01:24 +08:00
sc c0e21f9752 Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-21 19:01:23 +08:00
sc 7cd46d11de Merge branch 'master' of http://192.168.0.12:13000/sc/SunlightAggregationTerminal 2026-06-21 18:40:00 +08:00
Administrator a72383e422 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-21 18:39:59 +08:00
Administrator c3c4bfcd68 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-13 00:36:55 +08:00
Administrator 164c229cb2 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-13 00:36:54 +08:00
Administrator ec1112f641 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 23:57:49 +08:00
Administrator aea7c945ae Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 23:57:48 +08:00
Administrator cdacabee03 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 22:28:52 +08:00
Administrator 94d1fb6a5d Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 22:28:49 +08:00
Administrator 130bfb9d7b Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 00:18:01 +08:00
Administrator c7afb21ddf Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 00:17:59 +08:00
Administrator 822fb19d28 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 00:17:38 +08:00
Administrator 0b2d726287 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-12 00:17:36 +08:00
Administrator 3ad3523631 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-11 00:36:09 +08:00
Administrator 78aab33698 输送次数消息 2026-06-11 00:36:06 +08:00
Administrator 61ac666002 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 23:26:52 +08:00
Administrator 9f5afa0fbd Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 23:26:50 +08:00
Administrator 809cecb54f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 23:25:52 +08:00
Administrator cabba958f5 用户名和密码修改功能 2026-06-08 23:25:50 +08:00
Administrator 3852fc0142 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 18:51:51 +08:00
Administrator e52dd61baa 查询功能 2026-06-08 18:51:49 +08:00
Administrator 2d1d2bd6bc Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 01:16:23 +08:00
Administrator e4d0530cc3 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 01:16:10 +08:00
Administrator 5677817e55 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 01:13:45 +08:00
Administrator 06bbb5c8be Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-08 01:13:43 +08:00
Administrator 6d6bcb623c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-07 01:26:25 +08:00
Administrator f100d5398c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-07 01:26:22 +08:00
Administrator 0cc16df34c Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-06 23:32:42 +08:00
Administrator 3a84a4bdcc Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-06 23:32:40 +08:00
Administrator 2e44f1cfb7 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-06 23:12:51 +08:00
Administrator 70dabd0ca6 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-06 23:12:47 +08:00
Administrator ce3381e776 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-06 11:21:29 +08:00
Administrator 3f4a5a7cd8 细节信息页面修复 2026-06-06 11:21:27 +08:00
Administrator 663410c31f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-06 00:29:47 +08:00
Administrator e0c949bde9 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-06 00:29:45 +08:00
Administrator cdbf09cd7f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-04 00:02:18 +08:00
Administrator f11cb0f809 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-04 00:02:15 +08:00
Administrator 4af3fd5f46 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-03 00:36:50 +08:00
Administrator 2def1ca440 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-03 00:36:48 +08:00
Administrator 4fae724108 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-03 00:30:43 +08:00
Administrator b1070143a0 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-03 00:30:41 +08:00
Administrator 5ac35c901d Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-06-01 01:01:53 +08:00
Administrator a5f08f1f8e 公网访问相关 2026-06-01 00:52:20 +08:00
Administrator 27406f96e9 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-28 00:20:41 +08:00
Administrator b1c89a3813 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-28 00:20:39 +08:00
Administrator bfb85171f8 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-23 01:12:42 +08:00
Administrator 2334555c7b Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-23 01:12:40 +08:00
Administrator d4db376de0 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-21 23:11:12 +08:00
Administrator a485d1cb58 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-21 23:11:09 +08:00
Administrator b8ec091210 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-21 21:08:04 +08:00
Administrator cd7a6df16c 添加http连接功能 2026-05-21 21:08:01 +08:00
Administrator 848a39bb44 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-20 02:33:32 +08:00
Administrator 5bdab974cc apk 2026-05-20 02:33:30 +08:00
Administrator 8f16acf5b3 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-20 01:49:42 +08:00
Administrator 7aad6f8d1a 查询页面相关的信息 2026-05-20 01:49:40 +08:00
Administrator 64dd8ce595 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-19 01:34:43 +08:00
Administrator 321e7d84c2 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-19 01:34:41 +08:00
Administrator 7675362ff5 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-18 00:22:04 +08:00
Administrator dbb91fe0ee Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-18 00:22:02 +08:00
Administrator dc9da1925d Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-17 02:25:12 +08:00
Administrator c70e3430f9 查询细节 2026-05-17 02:25:09 +08:00
Administrator 051a36d885 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-16 00:03:36 +08:00
Administrator c3aed2461a Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-16 00:03:33 +08:00
Administrator c01b362adc Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-15 23:42:34 +08:00
Administrator 38be66b380 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-15 23:42:28 +08:00
Administrator 91d640821b Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-15 23:35:15 +08:00
Administrator 386a22cef0 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-15 23:35:13 +08:00
Administrator eb1803f835 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-15 23:19:18 +08:00
Administrator d8c28f25e2 添加细节信息 2026-05-15 23:19:15 +08:00
Administrator 4b87e98b19 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-14 01:29:47 +08:00
Administrator 24a05a6373 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-14 01:29:45 +08:00
Administrator 742b013707 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-14 01:21:22 +08:00
Administrator 954d1458d3 添加细节信息页面 2026-05-14 01:21:15 +08:00
Administrator f214801a17 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-13 02:18:21 +08:00
Administrator 035aa9b24a 添加机台细节消息页面 2026-05-13 02:18:18 +08:00
Administrator 781cf15641 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-13 02:09:50 +08:00
Administrator 50a8d7f4b2 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-13 02:09:48 +08:00
Administrator ea4420a42f Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-13 02:02:28 +08:00
Administrator 9694a80c89 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-13 02:02:26 +08:00
Administrator a19faea6cf Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-12 03:12:34 +08:00
Administrator 155aff76c7 字符串错误修正 2026-05-12 03:12:33 +08:00
Administrator b380dad8f0 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-12 02:28:59 +08:00
Administrator 8e4af75d05 info页面添加下滑刷新 2026-05-12 02:28:58 +08:00
Administrator da4c744bb3 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-12 01:28:37 +08:00
Administrator b3b42d129f InfoPage消息接收显示 2026-05-12 01:28:35 +08:00
Administrator ddaf80c1e2 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-11 02:25:45 +08:00
Administrator 7e8b05dfdf Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-11 02:25:42 +08:00
Administrator 182e201f65 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-10 03:26:38 +08:00
Administrator 2c164c1aa0 Merge branch 'master' of http://www.scserverddns.top:13000/sc/SunlightAggregationTerminal 2026-05-10 03:26:37 +08:00
37 changed files with 2669 additions and 386 deletions

No files matched your search

+6
View File
@@ -31,6 +31,12 @@
Title="查询"
Icon="search.png"
ContentTemplate="{DataTemplate local:QueryPage}"/>
<!-- 操作页面 -->
<!--
<ShellContent
Title="操作"
Icon="IcOutlinePsychologyAlt.png"
ContentTemplate="{DataTemplate local:QueryPage}"/>-->
<!-- 3 通知页面 -->
<ShellContent
Title="通知"
+4 -4
View File
@@ -27,15 +27,15 @@ namespace SunlightAggregationTerminal
await Navigation.PushModalAsync(loading);
if (await AppModels.LogIn())
{//拒绝登陆时打开登录页面
{
await loading.Navigation.PopModalAsync();
}
else
{
else
{//拒绝登陆时打开登录页面
await loading.Navigation.PopModalAsync();
var logpage = new View.LogPage();
await Navigation.PushModalAsync(logpage);
await Navigation.PushModalAsync(new NavigationPage(logpage));
}
}
+79
View File
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Runtime.Intrinsics.X86;
using System.Security.Cryptography;
using System.Text;
namespace SunlightAggregationTerminal.Class
{
public class AES
{
public static string AesEncipher(string Key, string dat) //加密
{
//压缩
byte[] plainBytes = Compress( Encoding.UTF8.GetBytes(dat));
using var sha256 = System.Security.Cryptography.SHA256.Create();
using var aes = System.Security.Cryptography.Aes.Create();
aes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes(Key));
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.GenerateIV(); // 生成随机 IV
using var enc = aes.CreateEncryptor();
byte[] cipherBytes = enc.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
//将 IV (16字节) 和 密文 拼接成一个完整的字节数组
byte[] combinedBytes = new byte[aes.IV.Length + cipherBytes.Length];
Buffer.BlockCopy(aes.IV, 0, combinedBytes, 0, aes.IV.Length);
Buffer.BlockCopy(cipherBytes, 0, combinedBytes, aes.IV.Length, cipherBytes.Length);
return Convert.ToBase64String(combinedBytes);
}
public static string AesDecrypt(string Key, string dat)//解密
{
// 解码Base64
byte[] cipherBytes = Convert.FromBase64String(dat);
using var sha256 = System.Security.Cryptography.SHA256.Create();
using var aes = System.Security.Cryptography.Aes.Create();
aes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes(Key));
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// 从字节数组中提取前 16 字节作为 IV
aes.IV = cipherBytes.AsSpan(0, 16).ToArray();
using var dec = aes.CreateDecryptor();
// 解密
byte[] bytes = dec.TransformFinalBlock(cipherBytes, 16, cipherBytes.Length - 16);
//解压缩并返回
return Encoding.UTF8.GetString(Decompress(bytes));
}
// 3. Brotli 压缩辅助方法
private static byte[] Compress(byte[] data)
{
using var output = new MemoryStream();
using (var brotli = new BrotliStream(output, CompressionLevel.Optimal))
{
brotli.Write(data, 0, data.Length);
}
return output.ToArray();
}
// 4. Brotli 解压辅助方法
private static byte[] Decompress(byte[] data)
{
using var input = new MemoryStream(data);
using var brotli = new BrotliStream(input, CompressionMode.Decompress);
using var output = new MemoryStream();
brotli.CopyTo(output);
return output.ToArray();
}
}
}
+254
View File
@@ -0,0 +1,254 @@
using CommunityToolkit.Mvvm.Messaging;
using SunlightAggregationTerminal.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using TouchSocket.Core;
namespace SunlightAggregationTerminal.Class
{
public class DataReceived
{
public class Person
{
public required string User { get; set; }
public required string Password { get; set; }
public required string IP { get; set; }
public required string Terminal { get; set; }
public required string Dat { get; set; }
}
public static string GetLocalIpSimple()
{
try
{
// 获取当前设备上所有的网络接口
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var networkInterface in networkInterfaces)
{
// 仅检查处于活动状态的网络接口
if (networkInterface.OperationalStatus != OperationalStatus.Up)
continue;
// 获取该接口下的所有单播 IP 地址
var addresses = networkInterface.GetIPProperties().UnicastAddresses;
foreach (var address in addresses)
{
// 筛选条件:必须是 IPv4、非回环地址(127.x.x.x),且通常属于局域网网段
if (address.Address.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(address.Address))
{
return address.Address.ToString();
}
}
}
}
catch (Exception ex)
{
MainThread.BeginInvokeOnMainThread(() =>
{
Application.Current!.Windows[0].Page!.DisplayAlertAsync("获取IP地址失败", ex.Message.ToString(), "是");
});
}
return ""; // 如果未找到有效IP则返回null
}
public static string ServerIP = "";
public static string ServerURL = "";
public static string ServerName = "";
public static string ServerPassword = "";
public static string ServerTerminal = "";
public static void Received(string dat)
{
if (dat.Length < 6)
{
string inf;
switch (dat)
{
case "999":
inf = "不明错误";
break;
case "990":
inf = "拒接访问账户远程访问许可证过期";
break;
case "980":
inf = "目标对象服务器不存在或已离线";
break;
case "970":
inf = "目标对象服务器不存在或已离线";
break;
default:
inf = dat;
break;
}
// MainThread.BeginInvokeOnMainThread(() =>
// {
// Application.Current!.Windows[0].Page!.DisplayAlertAsync("", inf, "是");
// });
}
else
{
try
{
Person deserializedPerson = JsonSerializer.Deserialize<Person>(dat)!;
var data = JsonSerializer.Deserialize<Dictionary<string, object>>
(AES.AesDecrypt( deserializedPerson.Terminal,deserializedPerson.Dat));
if (data != null)
{
//处理服务器发送信息
if (data.TryGetValue("Enterprise", out var val) && val != null) App.GlobalData.Enterprise = val.ToString() ?? "";
if (data.TryGetValue("Department", out val) && val != null) App.GlobalData.Department = val.ToString() ?? "";
if (data.TryGetValue("Groups", out val) && val != null) App.GlobalData.Groups = val.ToString() ?? "";
if (data.TryGetValue("UserName", out val) && val != null) App.GlobalData.UserName = val.ToString() ?? "";
if (data.TryGetValue("UserId", out val) && val != null)
{
DataReceived.Transmit("{\"Command\":\"Info\"}");
App.GlobalData.UserId = val.ToString() ?? "";
App.GlobalData.LogNo = true;
}
if (data.TryGetValue("UserData", out var value_UserData))
{
}
if (data.TryGetValue("SysData", out var value_SysData))
{
var tmp = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(value_SysData.ToString()!)!;
}
if (data.TryGetValue("Info", out val) && val != null)//机台信息接受
{
DataModel.Info_data = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(val.ToString()!)!;
InfoPage.DyeMeasurementNumber = data.GetValue("DyeMeasurementNumber").ToString();
InfoPage.ChemicalNumber = data.GetValue("ChemicalNumber").ToString();
InfoPage.PowderNumber = data.GetValue("PowderNumber").ToString();
InfoPage.DyeDissolveNumber = data.GetValue("DyeDissolveNumber").ToString();
//发送消息
WeakReferenceMessenger.Default.Send(new object());
}
if (data.TryGetValue("ChemicalStatistics", out val) && val != null)//查询接受
{
InfoChemicalStatistics.Total_data(val.ToString()!);
}
if (data.TryGetValue("Query", out val) && val != null)//查询接受
{
QueryPage.Query_data(val.ToString()!);
}
if (data.TryGetValue("QueryDetail", out val) && val != null)//
{
QueryDetail.Query_data(val.ToString()!);
}
if (data.TryGetValue("InfoMachine", out val) && val != null)//
{
InfoDetail.Info_data(val.ToString()!, data.GetValue("Type").ToString()!);
}
if (data.TryGetValue("InfoMachineHistory", out val) && val != null)//
{
InfoDetail.Info_data(val.ToString()!, data.GetValue("Type").ToString()!);
}
if (data.TryGetValue("InfoMachinePipes", out val) && val != null)//
{
InfoDetail.Info_data(val.ToString()!, "00");
}
if (data.TryGetValue("Notification", out val) && val != null)//信息通知接受
{
var dataNotification = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(val.ToString()!);
string _Title = "", _Content = "";
int _Type = 0, _id = 0;
foreach (var dataNotificationrow in dataNotification!)
{
//解析信息
if (dataNotificationrow!.TryGetValue("id", out var value_Notification_id)
&& value_Notification_id != null)
{
_id = (int)value_Notification_id;
App.GlobalData.NotificationID = _id.ToString();
}
if (dataNotificationrow!.TryGetValue("Title", out var value_Notification_Title)
&& value_Notification_Title != null)
{
_Title = value_Notification_Title.ToString() ?? "";
}
if (dataNotificationrow!.TryGetValue("Content", out var value_Notification_Content)
&& value_Notification_Content != null)
{
_Content = value_Notification_Content.ToString() ?? "";
}
if (dataNotificationrow!.TryGetValue("Type", out var value_Notification_Type)
&& value_Notification_Type != null)
{
string temp = value_Notification_Type?.ToString() ?? "";
// 转换
_Type = temp switch
{
"System" => 2,
"Message" => 1,
_ => 0
};
}
if (_id != 0)
{
//记录信息到数据库
DataSet? Notificationdata = AppModels.Select("select * from Notification where Id = " + _id);
if (Notificationdata != null)
{
if (Notificationdata.Tables[0].Rows.Count == 0)
{
AppModels.INSERT("INSERT INTO Notification (Title,Content,Time,Type,Id)VALUES('" +
_Title + "','" + _Content + "','" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") +
"','" + _Type + "'," + _id + ");");
}
}
}
}
string sql = "UPDATE Users SET NotificationID = '" + App.GlobalData.NotificationID +
"'WHERE User='" + App.GlobalData.User + "';";
AppModels.Updata(sql);
}
if (data.TryGetValue("SETUSER", out val) && val != null)//信息通知接受
{
ProfilePage._data(data.GetValue("VALUE").ToString()!,data.GetValue("KEY").ToString()!);
}
}
}
catch (Exception ex)
{
MainThread.BeginInvokeOnMainThread(() =>
{
Application.Current!.Windows[0].Page!.DisplayAlertAsync("", ex.Message.ToString(), "是");
});
}
}
}
public static void Transmit(string Dat)
{
if (App.GlobalData.LocalAreaNetworkMode)
{
TcpServer.TcpTransmit(Dat);
}
else
{
HttpServer.HttpTransmit(Dat);
}
}
}
}
+183
View File
@@ -0,0 +1,183 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using TouchSocket.Core;
using TouchSocket.Http;
using TouchSocket.Http.WebSockets;
using TouchSocket.Sockets;
using static SunlightAggregationTerminal.Class.TcpServer;
namespace SunlightAggregationTerminal.Class
{
public class HttpServer
{
public static TouchSocket.Http.HttpClient httpclient = new TouchSocket.Http.HttpClient();
public static async void Configuration(string ip, string Name, string Password, string Terminal)
{
string[] parts = ip.Split('/');
if (parts.Length >= 2)
{
DataReceived.ServerIP = parts[0];
DataReceived.ServerURL = parts[1];
}
else
{
DataReceived.ServerIP = "";
DataReceived.ServerURL = "";
}
DataReceived.ServerName = Name;
DataReceived.ServerPassword = Password;
DataReceived.ServerTerminal = Terminal;
if (string.IsNullOrWhiteSpace(ip))
{
App.GlobalData.LogNo = false;
}
else
{
await HttpClient(DataReceived.ServerIP);
}
}
public static async Task HttpClient(string url)
{
try
{
var config = new TouchSocketConfig();
#region Http设置远程服务器地址
config.SetRemoteIPHost("http://" + url);
#endregion
#region Http客户端获取断线通知
config.ConfigurePlugins(a =>
{
//处理连接断开
a.AddTcpClosedPlugin(async (c, e) =>
{
//MainThread.BeginInvokeOnMainThread(() =>
// {
// Application.Current!.Windows[0].Page!.DisplayAlertAsync("", "客户端断开连接", "是");
// });
// await e.InvokeNext();
});
//自动重连
a.UseReconnection<TouchSocket.Http.HttpClient>(options =>
{
options.PollingInterval = TimeSpan.FromSeconds(3);
});
//处理连接
a.AddTcpConnectedPlugin(async (c, e) =>
{
await e.InvokeNext();
});
});
#endregion
if (httpclient.Online)//是否重置客户端
{
await httpclient.CloseAsync();
}
//配置config
await httpclient.SetupAsync(config);
//连接
await httpclient.ConnectAsync();
HttpTransmit("{\"Command\":\"Log\"}");
}
catch (Exception ex)
{
MainThread.BeginInvokeOnMainThread(() =>
{
Application.Current!.Windows[0].Page!.DisplayAlertAsync("网络错误", ex.Message.ToString(), "是");
});
await httpclient.CloseAsync();
httpclient.Dispose();
}
}
/***发送信息处理***/
private static int HttpOutN=0;
public static async void HttpTransmit(string Dat)
{
if (!httpclient.Online) //检查连接
{
await httpclient.ConnectAsync();
}
var dat = new DataReceived.Person()
{
User = DataReceived.ServerName,
Password = AES.AesEncipher(DataReceived.ServerTerminal, DataReceived.ServerPassword),
IP = DataReceived.GetLocalIpSimple(),
Terminal = DataReceived.ServerTerminal,
Dat = AES.AesEncipher(DataReceived.ServerTerminal, Dat),
};
var request = new HttpRequest();
request.SetContent(new StringHttpContent(JsonSerializer.Serialize(dat), Encoding.UTF8, "application/scjson"))
.InitHeaders()
.SetUrl(DataReceived.ServerURL)
.SetHost(httpclient.RemoteIPHost.Host)
.AsPost();
// 创建一个超时操作,15秒后取消
using var cts = new CancellationTokenSource(1000 * 10);
try
{
using (var responseResult = await httpclient.RequestAsync(request, cts.Token))
{
var response = responseResult.Response;
// GetBodyAsync 同样需要响应取消信号,如果这里超过剩余时间也会抛出异常
var result = await response.GetBodyAsync();
DataReceived.Received(result);
}
}
catch (OperationCanceledException)
{
if (HttpOutN >= 3)
{
HttpOutN = 0;
// 专门处理超时或主动取消的情况
MainThread.BeginInvokeOnMainThread(() =>
{
Application.Current!.Windows[0].Page!.DisplayAlertAsync("网络错误", "网络请求超时,请检查网络网络连接", "是");
});
await httpclient.CloseAsync();
httpclient.Dispose();
}
else
{
HttpTransmit(Dat);//回调
HttpOutN++;
}
}
catch (Exception ex)
{
if (HttpOutN >= 3)
{
HttpOutN = 0;
MainThread.BeginInvokeOnMainThread(() =>
{
Application.Current!.Windows[0].Page!.DisplayAlertAsync("访问错误", ex.Message.ToString(), "是");
});
await httpclient.CloseAsync();
httpclient.Dispose();
}
else
{
HttpTransmit(Dat);//回调
HttpOutN++;
}
}
finally
{
}
}
}
}
+30 -4
View File
@@ -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"))
{
@@ -154,6 +160,12 @@ namespace SunlightAggregationTerminal.Class
string sql = "ALTER TABLE Users ADD COLUMN MessageNotificationMode BOOL DEFAULT (0);";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 NotificationID
if (!existingColumns.Contains("NotificationID"))
{
string sql = "ALTER TABLE Users ADD COLUMN NotificationID TEXT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
// 检查 GUID
if (!existingColumns.Contains("GUID"))
{
@@ -209,7 +221,13 @@ namespace SunlightAggregationTerminal.Class
{
string sql = "ALTER TABLE Notification ADD COLUMN Type INT;";
SQLitedata.ExecuteNonQuery(sql, null);
}
}
// 检查 id
if (!existingColumns.Contains("Id"))
{
string sql = "ALTER TABLE Notification ADD COLUMN Id INTEGER PRIMARY KEY;";
SQLitedata.ExecuteNonQuery(sql, null);
}
}
}
private static void CheckAndRepairTableSchemaSERVER()
@@ -250,7 +268,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,12 +289,14 @@ namespace SunlightAggregationTerminal.Class
Enterprise TEXT,
Department TEXT,
ServerID TEXT,
ServerHTTP TEXT,
Groups TEXT,
ProxyID TEXT,
LogNo BOOL DEFAULT (0),
LocalAreaNetworkMode BOOL DEFAULT (0),
DarkMode BOOL DEFAULT (0),
MessageNotificationMode BOOL DEFAULT (0),
NotificationID TEXT,
GUID TEXT
);";
@@ -290,7 +315,7 @@ namespace SunlightAggregationTerminal.Class
// 建表语句
string createSql = @"
CREATE TABLE Notification (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Id INTEGER PRIMARY KEY,
Title TEXT,
Content TEXT,
Time TEXT,
@@ -307,7 +332,8 @@ namespace SunlightAggregationTerminal.Class
CREATE TABLE Server (
START BOOL DEFAULT (0),
Server TEXT,
ServerID TEXT
ServerID TEXT,
ServerHTTP TEXT
);";
// 复用现有的 ExecuteNonQuery 方法
+1 -1
View File
@@ -9,7 +9,7 @@ namespace SunlightAggregationTerminal.Class
{
public class SecureJsonService
{
private static readonly byte[] _aesKey = Encoding.UTF8.GetBytes("12345678901234567890123456789012");
private static readonly byte[] _aesKey = Encoding.UTF8.GetBytes("1234567890");
/// <summary>
/// 调用一:发送端处理
+54 -116
View File
@@ -1,7 +1,11 @@
using System;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.VisualBasic;
using SunlightAggregationTerminal.Models;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Text.Json;
using TouchSocket.Core;
@@ -10,57 +14,35 @@ using TouchSocket.Sockets;
namespace SunlightAggregationTerminal.Class
{
public class TcpServer
{
public class Person
{
public required string User { get; set; }
public required string Password { get; set; }
public required string IP { get; set; }
public required string Terminal { get; set; }
public required string Dat { get; set; }
}
public static string GetLocalIpSimple()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(ip))
{
return ip.ToString();
}
}
return "No network connection";
}
public static string ServerIP = "";
public static string ServerName = "";
public static string ServerPassword = "";
public static string ServerTerminal = "";
{
public static TouchSocket.Sockets.TcpClient tcpClient = new TouchSocket.Sockets.TcpClient();
public static void Configuration(string ip, string Name, string Password, string Terminal)
public static async void Configuration(string ip, string Name, string Password, string Terminal)
{
ServerIP = ip;
ServerName = Name;
ServerPassword = Password;
ServerTerminal = Terminal;
DataReceived.ServerIP = ip;
DataReceived.ServerName = Name;
DataReceived.ServerPassword = Password;
DataReceived.ServerTerminal = Terminal;
_ = TcpClient(tcpClient, ServerIP);
await TcpClient(tcpClient, DataReceived.ServerIP);
}
// 引入发送锁,彻底解决连续发送导致的并发断连问题
private static readonly SemaphoreSlim _sendLock = new SemaphoreSlim(1, 1);
public static async void TcpTransmit(string Dat)
{
var dat = new Person()
var dat = new DataReceived.Person()
{
User = ServerName,
Password = ServerPassword,
IP = GetLocalIpSimple(),
Terminal = ServerTerminal,
User = DataReceived.ServerName,
Password = DataReceived.ServerPassword,
IP = DataReceived.GetLocalIpSimple(),
Terminal = DataReceived.ServerTerminal,
Dat = Dat
};
//SecureJsonService.CompressEncryptAndSend();
// 使用锁确保同一时间只有一个任务在发送,防止并发写入导致 Socket 异常
await _sendLock.WaitAsync();
//发送字符串数据
try
{
@@ -68,91 +50,35 @@ namespace SunlightAggregationTerminal.Class
}
catch (Exception ex)
{
await Application.Current!.Windows[0].Page!.DisplayAlertAsync("错误", ex.Message.ToString(), "是");
MainThread.BeginInvokeOnMainThread(() =>
{
Application.Current!.Windows[0].Page!.DisplayAlertAsync("错误", ex.Message.ToString(), "是");
});
}
finally
{
_sendLock.Release(); // 释放锁
}
}
public static async Task TcpClient(TouchSocket.Sockets.TcpClient tcpClient, string ip)
{
tcpClient.Connecting = (client, e) => { return EasyTask.CompletedTask; };//即将连接到服务器,此时已经创建socket,但是还未建立tcp
tcpClient.Connected = (client, e) => {
TcpServer.TcpTransmit("Log");
return EasyTask.CompletedTask; };//成功连接到服务器
tcpClient.Closing = (client, e) => { return EasyTask.CompletedTask; };//即将从服务器断开连接。此处仅主动断开才有效。
tcpClient.Closed = (client, e) => { return EasyTask.CompletedTask; };//从服务器断开连接,当连接不成功时不会触发。
tcpClient.Connected = (client, e) =>
{
TcpServer.TcpTransmit("{\"Command\":\"Log\"}");
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);
try
{
var data = JsonSerializer.Deserialize<Dictionary<string, object>>(mes);
if (data != null)
{
//处理服务器发送信息
if (data.TryGetValue("Enterprise", out var val) && val != null) App.GlobalData.Enterprise = val.ToString() ?? "";
if (data.TryGetValue("Department", out val) && val != null) App.GlobalData.Department = val.ToString() ?? "";
if (data.TryGetValue("Groups", out val) && val != null) App.GlobalData.Groups = val.ToString() ?? "";
if (data.TryGetValue("UserName", out val) && val != null) App.GlobalData.UserName = val.ToString() ?? "";
if (data.TryGetValue("UserId", out val) && val != null)
{
App.GlobalData.UserId = val.ToString() ?? "";
App.GlobalData.LogNo = true;
}
if (data.TryGetValue("UserData", out var value_UserData))
{
}
if (data.TryGetValue("SysData", out var value_SysData))
{
}
if (data.TryGetValue("Query", out val) && val != null)//查询接受
{
QueryPage.Query_data(val.ToString()!);
}
if (data.TryGetValue("Notification", out val) && val != null)//信息通知接受
{
var dataNotification = JsonSerializer.Deserialize<Dictionary<string, object>>(val.ToString()!);
string _Title = "", _Content = "";
int _Type = 0;
if (dataNotification!.TryGetValue("Title", out var value_Notification_Title))
{
_Title = value_Notification_Title.ToString() ?? "";
}
if (dataNotification!.TryGetValue("Content", out var value_Notification_Content))
{
_Content = value_Notification_Content.ToString() ?? "";
}
if (dataNotification!.TryGetValue("Type", out var value_Notification_Type))
{
string temp = value_Notification_Type?.ToString() ?? "";
// 转换
_Type = temp switch
{
"System" => 2,
"Message" => 1,
_ => 0
};
}
Models.AppModels.INSERT("INSERT INTO Notification (Title,Content,Time,Type)VALUES('" +
_Title + "','" + _Content + "','" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "','" + _Type + "');");
}
}
}
catch (Exception) { }
DataReceived.Received(mes);
return EasyTask.CompletedTask;
};
#endregion
@@ -160,12 +86,24 @@ namespace SunlightAggregationTerminal.Class
try
{
await tcpClient.SetupAsync(new TouchSocketConfig()
.SetRemoteIPHost(ip));
.SetSingleStreamDataHandlingAdapter(() => new PeriodPackageAdapter())//以超时周期和包
.SetRemoteIPHost(ip)
.ConfigurePlugins(a =>
{
a.UseReconnection<TouchSocket.Sockets.TcpClient>(options =>
{
options.PollingInterval = TimeSpan.FromSeconds(5);
});
}));
await tcpClient.ConnectAsync();//调用连接,当连接不成功时,会抛出异常。
}
catch (Exception ex)
{
await Application.Current!.Windows[0].Page!.DisplayAlertAsync("网络错误", ex.Message.ToString(), "是");
MainThread.BeginInvokeOnMainThread(() =>
{
Application.Current!.Windows[0].Page!.DisplayAlertAsync("网络错误", ex.Message.ToString(), "是");
});
}
}
}
+25
View File
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace SunlightAggregationTerminal.Converters
{
public class StringToBoolConverter : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value !=null)
{
return true;
}
return false;
}
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
// 单向绑定
throw new NotImplementedException();
}
}
}
+3 -4
View File
@@ -8,7 +8,7 @@ namespace SunlightAggregationTerminal.Converters
{
public class StringToImageConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value !=null)
{
@@ -17,7 +17,7 @@ namespace SunlightAggregationTerminal.Converters
if (value.ToString() == "252") return ImageSource.FromFile("sc252rb.png");
else if (value.ToString() == "252-2T") return ImageSource.FromFile("sc2522t.png");
else if (value.ToString() == "252RB") return ImageSource.FromFile("sc252rb.png");
else if (value.ToString() == "252RDRM") return ImageSource.FromFile("sc252rdrm.png");
else if (value.ToString() == "252RDRM") return ImageSource.FromFile("sc252rmrd.png");
else if (value.ToString() == "242W") return ImageSource.FromFile("sc242w.png");
else if (value.ToString() == "302") return ImageSource.FromFile("sc302.png");
else if (value.ToString() == "303") return ImageSource.FromFile("sc303.png");
@@ -29,9 +29,8 @@ namespace SunlightAggregationTerminal.Converters
return ImageSource.FromFile("sunlightlogo.png");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
// 通常图片转回字符串在 UI 上很少用到,可以抛出异常或留空
throw new NotImplementedException();
}
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="currentColor" d="M19.94 9.06C19.5 5.73 16.57 3 13 3C9.47 3 6.57 5.61 6.08 9l-1.93 3.48c-.41.66.07 1.52.85 1.52h1v2c0 1.1.9 2 2 2h1v3h7v-4.68a7.02 7.02 0 0 0 3.94-7.26m-5.05 5.57l-.89.42V19h-3v-3H8v-4H6.7l1.33-2.33C8.21 7.06 10.35 5 13 5c2.76 0 5 2.24 5 5c0 2.09-1.29 3.88-3.11 4.63"/><path fill="currentColor" d="M12.5 12.54c-.41 0-.74.31-.74.73c0 .41.33.74.74.74c.42 0 .73-.33.73-.74a.71.71 0 0 0-.73-.73m0-5.54c-1.03 0-1.74.67-2 1.45l.96.4c.13-.39.43-.86 1.05-.86c.95 0 1.13.89.8 1.36c-.32.45-.86.75-1.14 1.26c-.23.4-.18.87-.18 1.16h1.06c0-.55.04-.65.13-.82c.23-.42.65-.62 1.09-1.27c.4-.59.25-1.38-.01-1.8c-.31-.49-.9-.88-1.76-.88"/></svg>

After

Width:  |  Height:  |  Size: 738 B

+70
View File
@@ -0,0 +1,70 @@
<?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.InfoChemicalStatistics"
Title="耗用统计">
<Grid>
<Grid RowDefinitions="Auto, *" >
<Grid ColumnDefinitions="*, Auto" Grid.Row="0" Grid.Column="0" Margin="5">
<HorizontalStackLayout Grid.Row="0" Grid.Column="0" Margin="5,0,0,0" >
<DatePicker x:Name="StartTime" Format="yyyy年MM月dd日" FontSize="16"
MaximumWidthRequest="150" MinimumWidthRequest="130" WidthRequest="135"/>
<Label Text="~" FontSize="28"/>
<DatePicker x:Name="EndTime" Format="yyyy年MM月dd日" FontSize="16"
MaximumWidthRequest="150" MinimumWidthRequest="130" WidthRequest="135"/>
</HorizontalStackLayout>
<Button Grid.Row="0" Grid.Column="1" Text="查询" Clicked="Button_Clicked"
WidthRequest="60" Padding="5,0,5,0" Margin="20,0,0,5" />
</Grid>
<CollectionView Grid.Row="1" x:Name="CardCollectionView">
<!-- 保持滚动条 -->
<CollectionView.ItemTemplate>
<DataTemplate>
<!-- 这里定义单个卡片的 UI 结构 -->
<Border BackgroundColor="White" Stroke="#CCCCCC"
StrokeThickness="2" Margin="10,0,10,10"
StrokeShape="RoundRectangle 10">
<VerticalStackLayout>
<!-- 设备信息 -->
<HorizontalStackLayout>
<Label Text="原料: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding ProductName}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="代码: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding ProductCode}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="用量: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding TotalDispenseGrams}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="Kg" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<!-- 查询中动画页面 -->
<Grid x:Name="LoadingIndicator" BackgroundColor="Gray"
IsVisible="False" Opacity="0.9">
<VerticalStackLayout Padding="30" Spacing="10"
VerticalOptions="Center"
HorizontalOptions="Center">
<ActivityIndicator IsRunning="True"
Color="#512BD4"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Label Text="查询中..." FontAttributes="Bold"
FontSize="24" TextColor="Black"/>
</VerticalStackLayout>
</Grid>
</Grid>
</ContentPage>
+89
View File
@@ -0,0 +1,89 @@
using SunlightAggregationTerminal.Class;
using SunlightAggregationTerminal.Models;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text.Json;
using TouchSocket.Core;
namespace SunlightAggregationTerminal;
public partial class InfoChemicalStatistics : ContentPage
{
public class ChemicalTotal
{
public string? ProductName { get; set; }
public string? ProductCode { get; set; }
public float? TotalDispenseGrams { get; set; }
}
public static ObservableCollection<ChemicalTotal> ChemicalTotals { get; set; } = new();
public InfoChemicalStatistics()
{
InitializeComponent();
Dictionary<string, object> Dictionary = new Dictionary<string, object>();
Dictionary.Add("Command", "ChemicalStatistics");
DateTime StartTimee_ = (DateTime)StartTime.Date!;
Dictionary.Add("StartTime", StartTimee_.ToString("yyyy-MM-dd"));
DateTime EndTime_ = (DateTime)EndTime.Date!;
Dictionary.Add("EndTime", EndTime_.AddDays(1).ToString("yyyy-MM-dd"));
Total_Command(Dictionary.ToJsonString());
}
public async void Total_Command(string dat)
{
LoadingIndicator.IsVisible = true;
ChemicalTotals.Clear();
DataReceived.Transmit(dat);
// 创建一个 15 秒的延时任务
Task delayTask = Task.Delay(15000);
// 创建一个监测任务,不断检查变量
Task monitorTask = Task.Run(async () =>
{
while (ChemicalTotals.Count == 0)
{
// 每隔 100 毫秒检查一次,避免 CPU 占用过高
await Task.Delay(100);
}
});
// 使用 Task.WhenAny 等待任意一个任务完成
await Task.WhenAny(delayTask, monitorTask);
CardCollectionView.ItemsSource = ChemicalTotals;
LoadingIndicator.IsVisible = false;
}
public static void Total_data(string dat)
{
try
{
var data = JsonSerializer.Deserialize<List<ChemicalTotal>>(dat);
if (data != null)
{
foreach (var item in data)
{
item.TotalDispenseGrams = MathF.Round((float)item.TotalDispenseGrams! / 1000, 5);
ChemicalTotals.Add(item);
}
}
}
catch (Exception)
{
}
}
//搜索按钮
private void Button_Clicked(object sender, EventArgs e)
{
Dictionary<string, object> Dictionary = new Dictionary<string, object>();
Dictionary.Add("Command", "ChemicalStatistics");
DateTime StartTimee_ = (DateTime)StartTime.Date!;
Dictionary.Add("StartTime", StartTimee_.ToString("yyyy-MM-dd"));
DateTime EndTime_ = (DateTime)EndTime.Date!;
Dictionary.Add("EndTime", EndTime_.AddDays(1).ToString("yyyy-MM-dd"));
Total_Command(Dictionary.ToJsonString());
}
}
+179
View File
@@ -0,0 +1,179 @@
<?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.InfoDetail"
xmlns:converters="clr-namespace:SunlightAggregationTerminal.Converters"
Title="细节信息"
Loaded="ContentPage_Loaded">
<ContentPage.Resources>
<ResourceDictionary>
<converters:StringToImageConverter x:Key="StringToImageConverter" />
<converters:StringToBoolConverter x:Key="StringToBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowDefinitions="Auto, Auto, *" ColumnDefinitions="*, Auto" >
<Grid BackgroundColor="#CCCCCC" Padding="10" Grid.Row="0" Grid.Column="0" >
<HorizontalStackLayout>
<!-- 图片 -->
<Image WidthRequest="150" HeightRequest="150"
Source="{Binding Path=Model, Converter={StaticResource StringToImageConverter}}"/>
<!-- 设备状态 -->
<VerticalStackLayout>
<Label Text="{Binding Name}" FontAttributes="Bold"
FontSize="24" TextColor="Black" Padding="5"/>
<HorizontalStackLayout>
<Label Text="状态: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding State}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="机台: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding Machine}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</HorizontalStackLayout>
</Grid>
<!-- 选项 -->
<Grid Grid.Row="1" Grid.Column="0" HeightRequest="50">
<HorizontalStackLayout BackgroundColor="#F0F0F0">
<Button Text="实时信息" Clicked="Button_real" BackgroundColor="Transparent" TextColor="Black"/>
<Button Text="物料信息" Clicked="Button_machine" BackgroundColor="Transparent" TextColor="Black"/>
<Button Text="执行历史" Clicked="Button_history" BackgroundColor="Transparent" TextColor="Black"/>
<Button Text="远程控制" Clicked="Button_control" BackgroundColor="Transparent" TextColor="Black"/>
</HorizontalStackLayout>
</Grid>
<Grid x:Name="_real" Grid.Row="2" Grid.Column="0" BackgroundColor="#F0F0F0">
<!-- 设备信息 -->
<RefreshView x:Name="myCardCollectionView_" >
<CollectionView x:Name="CardCollectionView_inf" RemainingItemsThreshold="5">
<CollectionView.ItemTemplate>
<DataTemplate>
<Border BackgroundColor="White" Stroke="#CCCCCC"
StrokeThickness="2" Margin="10,0,10,10" StrokeShape="RoundRectangle 10">
<VerticalStackLayout VerticalOptions="Center">
<HorizontalStackLayout>
<Label Text="{Binding inf}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</Grid>
<!-- 设备内容 -->
<Grid x:Name="_machine" IsVisible="False" Grid.Row="2" Grid.Column="0" BackgroundColor="#F0F0F0">
<CollectionView x:Name="CardCollectionView_machine" RemainingItemsThreshold="5">
<CollectionView.ItemTemplate>
<DataTemplate>
<Border BackgroundColor="White" Stroke="#CCCCCC"
StrokeThickness="2" Margin="10,0,10,10" StrokeShape="RoundRectangle 10">
<VerticalStackLayout VerticalOptions="Center">
<HorizontalStackLayout>
<Label Text="名称: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding ProductName}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="代码: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding ProductCode}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="状态: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding ProductState}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="{Binding ProductInf}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<!-- 历史 -->
<Grid x:Name="_history" IsVisible="False" Grid.Row="2" Grid.Column="0" BackgroundColor="#F0F0F0">
<CollectionView x:Name="CardCollectionView_history" RemainingItemsThreshold="5">
<CollectionView.ItemTemplate>
<DataTemplate>
<Border BackgroundColor="White" Stroke="#CCCCCC"
StrokeThickness="2" Margin="10,0,10,10"
StrokeShape="RoundRectangle 10">
<VerticalStackLayout VerticalOptions="Center">
<HorizontalStackLayout>
<Label Text="工单: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding Dyelot}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="@" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding ReDye}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="步骤: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding StepNumber}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<BoxView HeightRequest="3" Color="#CCCCCC" />
<HorizontalStackLayout>
<Label Text="{Binding Notes}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="呼叫时间: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding CallTime}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="开始时间: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding DispenseStartTime}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="完成时间: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding DispenseEndTime}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<!-- 远程 -->
<Grid x:Name="_control" IsVisible="False" Grid.Row="2" Grid.Column="0" BackgroundColor="#F0F0F0">
</Grid>
<Grid x:Name="LoadingIndicator" Grid.Row="2" Grid.Column="0"
BackgroundColor="Gray" IsVisible="False" Opacity="0.9">
<VerticalStackLayout Padding="30" Spacing="10"
VerticalOptions="Center"
HorizontalOptions="Center">
<ActivityIndicator IsRunning="True"
Color="#512BD4"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Label Text="查询中..." FontAttributes="Bold"
FontSize="24" TextColor="Black"/>
</VerticalStackLayout>
</Grid>
</Grid>
</ContentPage>
+593
View File
@@ -0,0 +1,593 @@
using CommunityToolkit.Mvvm.ComponentModel;
using SunlightAggregationTerminal.Class;
using SunlightAggregationTerminal.Models;
using System.Collections.ObjectModel;
using System.Reflection.PortableExecutable;
using System.Text.Json;
using TouchSocket.Core;
namespace SunlightAggregationTerminal;
public class InfoMachineItem
{
public string? inf { get; set; }
}public partial class InfoDetail : ContentPage
{
public static ObservableCollection<ProbuctItem> InfoProbuctItems { get; set; } = new();
public static ObservableCollection<DyelotDetailsItem> InfoDyelotHistoryItems { get; set; } = new();
public static ObservableCollection<InfoMachineItem> InfoMachineItems { get; set; } = new();
public static InfoItem infoItem=new();
private DateTime _lastRefreshTime = DateTime.MinValue;
public InfoDetail(InfoItem item)
{
InitializeComponent();
this.BindingContext = item;
infoItem = item;
myCardCollectionView_.Refreshing += (sender, e) => {
// 防抖判断:如果距离上次刷新不足5秒,直接取消本次操作
if ((DateTime.Now - _lastRefreshTime).TotalSeconds < 1)
{
myCardCollectionView_.IsRefreshing = false;
return;
}
try
{
// 更新刷新时间
_lastRefreshTime = DateTime.Now;
InfoMachine();
myCardCollectionView_.IsRefreshing = false;
}
catch (Exception)
{
}
};
}
private void ContentPage_Loaded(object sender, EventArgs e)
{
InfoMachine();
InfoMachineItems.Clear();
InfoProbuctItems.Clear();
InfoDyelotHistoryItems.Clear();
CardCollectionView_inf.ItemsSource = InfoMachineItems;
CardCollectionView_machine.ItemsSource = InfoProbuctItems;
CardCollectionView_history.ItemsSource = InfoDyelotHistoryItems;
}
//查询
private void InfoMachine() {
Dictionary<string, object> data_ = new Dictionary<string, object>();
data_.Add("Command", "InfoMachine");
if (infoItem.Model == "252")
{
data_.Add("Type", "10");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
else if (infoItem.Model == "252-2T")
{
data_.Add("Type", "10");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
else if (infoItem.Model == "252RB")
{
data_.Add("Type", "10");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
else if (infoItem.Model == "252RDRM")
{
data_.Add("Type", "12");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
else if (infoItem.Model == "242W")
{
data_.Add("Type", "10");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
else if (infoItem.Model == "302")
{
data_.Add("Type", "20");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
else if (infoItem.Model == "303")
{
data_.Add("Type", "20");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
else if (infoItem.Model == "303PDW")
{
data_.Add("Type", "20");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_Command(data_.ToJsonString());
}
}
//设备信息
private void Button_real(object sender, EventArgs e)
{
_real.IsVisible = true;
_machine.IsVisible = false;
_history.IsVisible = false;
_control.IsVisible = false;
}
//设备内容
private async void Button_machine(object sender, EventArgs e)
{
_real.IsVisible = false;
_machine.IsVisible = true;
_history.IsVisible = false;
_control.IsVisible = false;
if (infoItem.Model == "252" || infoItem.Model == "252-2T" ||
infoItem.Model == "252RB" || infoItem.Model == "242W" ||
infoItem.Model == "252RDRM")
{
await DisplayAlertAsync("限制", "当前功能暂不可用", "是");
return;
}
if (InfoProbuctItems.Count == 0)
{
Dictionary<string, object> data_ = new Dictionary<string, object>();
data_.Add("Command", "InfoMachinePipes");
data_.Add("MachinName", infoItem.Machine!);
Query_Probuct(data_.ToJsonString());
}
}
//历史
private void Button_history(object sender, EventArgs e)
{
_real.IsVisible = false;
_machine.IsVisible = false;
_history.IsVisible = true;
_control.IsVisible = false;
if (InfoDyelotHistoryItems.Count == 0)
{
Dictionary<string, object> data_ = new Dictionary<string, object>();
data_.Add("Command", "InfoMachineHistory");
if (infoItem.Model == "252")
{
data_.Add("Type", "80");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
else if (infoItem.Model == "252-2T")
{
data_.Add("Type", "80");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
else if (infoItem.Model == "252RB")
{
data_.Add("Type", "80");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
else if (infoItem.Model == "252RDRM")
{
data_.Add("Type", "82");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
else if (infoItem.Model == "242W")
{
data_.Add("Type", "80");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
else if (infoItem.Model == "302")
{
data_.Add("Type", "90");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
else if (infoItem.Model == "303")
{
data_.Add("Type", "90");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
else if (infoItem.Model == "303PDW")
{
data_.Add("Type", "90");
data_.Add("Field", "*");
data_.Add("MachinName", infoItem.Machine!);
Query_History(data_.ToJsonString());
}
}
}
//远程
private async void Button_control(object sender, EventArgs e)
{
_real.IsVisible = false;
_machine.IsVisible = false;
_history.IsVisible = false;
_control.IsVisible = true;
await DisplayAlertAsync("限制", "当前功能暂不可用", "是");
}
//发送请求
public async void Query_Command(string dat)
{
LoadingIndicator.IsVisible = true;
InfoMachineItems.Clear();
DataReceived.Transmit(dat);
// 创建一个 秒的延时任务
Task delayTask = Task.Delay(10000);
// 创建一个监测任务,不断检查变量
Task monitorTask = Task.Run(async () =>
{
while (InfoMachineItems.Count == 0)
{
// 每隔 100 毫秒检查一次,避免 CPU 占用过高
await Task.Delay(1000);
}
});
// 使用 Task.WhenAny 等待任意一个任务完成
await Task.WhenAny(delayTask, monitorTask);
LoadingIndicator.IsVisible = false;
}
public async void Query_Probuct(string dat)
{
LoadingIndicator.IsVisible = true;
InfoProbuctItems.Clear();
DataReceived.Transmit(dat);
// 创建一个 秒的延时任务
Task delayTask = Task.Delay(10000);
// 创建一个监测任务,不断检查变量
Task monitorTask = Task.Run(async () =>
{
while (InfoProbuctItems.Count == 0)
{
// 每隔 100 毫秒检查一次,避免 CPU 占用过高
await Task.Delay(1000);
}
});
// 使用 Task.WhenAny 等待任意一个任务完成
await Task.WhenAny(delayTask, monitorTask);
LoadingIndicator.IsVisible = false;
}
public async void Query_History(string dat)
{
LoadingIndicator.IsVisible = true;
InfoDyelotHistoryItems.Clear();
DataReceived.Transmit(dat);
// 创建一个 秒的延时任务
Task delayTask = Task.Delay(10000);
// 创建一个监测任务,不断检查变量
Task monitorTask = Task.Run(async () =>
{
while (InfoDyelotHistoryItems.Count == 0)
{
// 每隔 100 毫秒检查一次,避免 CPU 占用过高
await Task.Delay(1000);
}
});
// 使用 Task.WhenAny 等待任意一个任务完成
await Task.WhenAny(delayTask, monitorTask);
LoadingIndicator.IsVisible = false;
}
public static void Info_data(string dat, string id)
{
var data = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(dat)!;
//助剂原料查询
if (id == "00")
{
foreach (var item in data!)
{
ProbuctItem probuctItem = new ProbuctItem();
probuctItem.ProductCode = item.GetValue("ProductCode").ToString()!;
probuctItem.ProductName = item.GetValue("ProductName").ToString()!;
if (item.GetValue("Enabled").ToString()! == "1")
{
probuctItem.ProductState = "启用";
}
else { probuctItem.ProductState = "停用"; }
if (item!.TryGetValue("No", out var _No) && _No != null)
{
probuctItem.ProductInf = "管路: " + _No + "\n";
}
if (item!.TryGetValue("MinLimit", out var _MinLimit) && _MinLimit != null)
{
probuctItem.ProductInf = probuctItem.ProductInf+"最少量: " + _MinLimit + "g\n";
}
if (item!.TryGetValue("MaxLimit", out var _MaxLimit) && _MaxLimit != null)
{
probuctItem.ProductInf = probuctItem.ProductInf + "最大量: " + _MinLimit + "g\n";
}
if (item!.TryGetValue("Conc", out var _Conc) && _Conc != null)
{
probuctItem.ProductInf = probuctItem.ProductInf + "浓度: " + _Conc + "\n";
}
if (item!.TryGetValue("Enabled", out var _Gravity) && _Gravity != null)
{
probuctItem.ProductInf = probuctItem.ProductInf + "比重: " + _Gravity;
}
InfoProbuctItems.Add(probuctItem);
}
if (InfoProbuctItems.Count == 0) InfoProbuctItems.Add(new ProbuctItem());
}
//染料查询
else if (id == "10")
{
foreach (var item in data!)
{
string inf_ = "染机: " + item.GetValue("Machine").ToString()! + "\n";
inf_ = inf_ + "料单: " + item.GetValue("Dyelot").ToString()!;
inf_ = inf_ + "@" + item.GetValue("ReDye").ToString()! + "\n";
inf_ = inf_ + "步骤: " + item.GetValue("StepNumber").ToString()! + "\n";
inf_ = inf_ + "流程: " + item.GetValue("Process").ToString()! + "\n";
inf_ = inf_ + "化料桶: " + item.GetValue("TankNO").ToString()! + "\n";
inf_ = inf_ + "染料桶数: " + item.GetValue("TotalNumber").ToString()!;
if (item!.TryGetValue("BarrelState", out var _Type) && _Type != null)
{
string temp = _Type?.ToString() ?? "";
// 转换
_Type = temp switch
{
"301" => "就绪",
"309" => "未准备",
_ => "无信息"
};
inf_ = inf_ + _Type;
}
inf_ = inf_ + "状态: " + item.GetValue("State").ToString()! + "\n";
InfoMachineItem infoMachineItem = new InfoMachineItem();
infoMachineItem.inf = inf_;
InfoMachineItems.Add(infoMachineItem);
}
if (InfoMachineItems.Count == 0) InfoMachineItems.Add(new InfoMachineItem());
}
//染料查询化料货架
else if (id == "12")
{
foreach (var item in data!)
{
string inf_ = "位置: " + item.GetValue("position").ToString()! + "\n";
inf_ = inf_ + "料单: " + item.GetValue("Dyelot").ToString()!;
inf_ = inf_ + "@" + item.GetValue("ReDye").ToString()! + "\n";
inf_ = inf_ + "步骤: " + item.GetValue("StepNumber").ToString()! + "\n";
if (item!.TryGetValue("BarrelType", out var _Type) && _Type != null)
{
string temp = _Type?.ToString() ?? "";
// 转换
_Type = temp switch
{
"1" => "空桶",
"2" => "染料桶",
_ => "无桶"
};
inf_ = inf_ + "类型:" + _Type;
}
if (item!.TryGetValue("BarrelState", out var _BarrelState) && _BarrelState != null)
{
string temp = _BarrelState?.ToString() ?? "";
_BarrelState = temp switch
{
"201" => "[分桶]",
_ => ""
};
inf_ = inf_ + _BarrelState;
}
inf_ = inf_ + "[" + item.GetValue("Barrelserialnumber").ToString()! + "]\n";
inf_ = inf_ + "上架时间: " + DateTime.Parse(item.GetValue("createtime").ToString() ?? "")
.ToString("yyyy-MM-dd HH:mm:ss") + "\n";
inf_ = inf_ + "状态 [" + item.GetValue("State").ToString()! + "]";
InfoMachineItem infoMachineItem = new InfoMachineItem();
infoMachineItem.inf = inf_;
InfoMachineItems.Add(infoMachineItem);
}
if (InfoMachineItems.Count == 0) InfoMachineItems.Add(new InfoMachineItem());
}
//助剂查询
else if (id == "20")
{
foreach (var item in data!)
{
string inf_ = "染机: " + item.GetValue("Machine").ToString()! + "\n";
inf_ = inf_ + "料单: " + item.GetValue("Dyelot").ToString()!;
inf_ = inf_ + "@" + item.GetValue("ReDye").ToString()! + "\n";
inf_ = inf_ + "步骤: " + item.GetValue("StepNumber").ToString()! + "\n";
inf_ = inf_ + "总浴量: " + item.GetValue("Volume").ToString()! + "\n";
inf_ = inf_ + "计量模组: " + item.GetValue("DispenseModule").ToString()! + "\n";
if (item!.TryGetValue("TankNo", out var _TankNo) && _TankNo != null)
{
inf_ = inf_ + "目标位置: " + item.GetValue("TankNo").ToString()! + "\n";
}
else {
inf_ = inf_ + "目标位置: 未指定\n" ;
}
inf_ = inf_ + "开始时间: " + DateTime.Parse(item.GetValue("DispenseStartTime").ToString() ?? "")
.ToString("yyyy-MM-dd HH:mm:ss") + "\n";
if (item!.TryGetValue("State", out var _Type) && _Type != null)
{
string temp = _Type?.ToString() ?? "";
// 转换
_Type = temp switch
{
"102" => "计量中",
"301" => "完成",
"309" => "异常",
_ => "无信息"
};
inf_ = inf_ + "状态: " + _Type;
}
InfoMachineItem infoMachineItem = new InfoMachineItem();
infoMachineItem.inf = inf_;
if (!InfoMachineItems.Any(x => x.inf == inf_))
{
InfoMachineItems.Add(infoMachineItem);
}
}
if (InfoMachineItems.Count==0) InfoMachineItems.Add(new InfoMachineItem());
}
//化料历史信息查询
else if (id == "80")
{
foreach (var item in data!)
{
DyelotDetailsItem dyelotDetailsItem = new DyelotDetailsItem();
dyelotDetailsItem.Dyelot = item.GetValue("Dyelot").ToString()!;
dyelotDetailsItem.ReDye =int.Parse( item.GetValue("ReDye").ToString()!);
dyelotDetailsItem.StepNumber = int.Parse(item.GetValue("StepNumber").ToString()!);
dyelotDetailsItem.Notes = "染机: " + item.GetValue("Machine").ToString()!+"\n";
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes +
"流程: " + item.GetValue("Process").ToString()!+"\n";
if (item!.TryGetValue("State", out var _State) && _State != null)
{
string temp = _State?.ToString() ?? "";
// 转换
_State = temp switch
{
"301" => "完成",
"309" => "异常",
_ => "无信息"
};
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + "状态: " + _State ;
}
if (item!.TryGetValue("TankNo", out var _TankNo) && _TankNo != null)
{
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + " [化料桶T" + _TankNo + "]";
}
if (item!.TryGetValue("TotalNumber", out var _TotalNumber) && _TotalNumber != null)
{
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + " [" + _TotalNumber+"桶]";
}
dyelotDetailsItem.DispenseStartTime = item.GetValue("DispenseStartTime").ToString()!.Replace("T", " ");
dyelotDetailsItem.DispenseEndTime = item.GetValue("DispenseEndTime").ToString()!.Replace("T", " ");
if (item!.TryGetValue("CallTime", out var _CallTime) && _CallTime != null)
{
if (DateTime.TryParse(_CallTime.ToString(), out DateTime dtc))
{
dyelotDetailsItem.CallTime = dtc.ToString("yyyy-MM-dd HH:mm:ss");
}
}
InfoDyelotHistoryItems.Add(dyelotDetailsItem);
}
if (InfoDyelotHistoryItems.Count == 0) InfoDyelotHistoryItems.Add(new DyelotDetailsItem());
}
//化料货架历史信息查询
else if (id == "82")
{
foreach (var item in data!)
{
DyelotDetailsItem dyelotDetailsItem = new DyelotDetailsItem();
dyelotDetailsItem.Dyelot = item.GetValue("Dyelot").ToString()!;
dyelotDetailsItem.ReDye = int.Parse(item.GetValue("ReDye").ToString()!);
dyelotDetailsItem.StepNumber = int.Parse(item.GetValue("StepNumber").ToString()!);
dyelotDetailsItem.Notes = "位置: " + item.GetValue("Position").ToString()! + "\n";
if (item!.TryGetValue("BarrelType", out var _Type) && _Type != null)
{
string temp = _Type?.ToString() ?? "";
// 转换
_Type = temp switch
{
"1" => "空桶",
"2" => "染料桶",
_ => "无桶"
};
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + "类型: " + _Type;
}
if (item!.TryGetValue("BarrelState", out var _BarrelState) && _BarrelState != null)
{
string temp = _BarrelState?.ToString() ?? "";
_BarrelState = temp switch
{
"201" => "[分桶]",
_ => ""
};
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + _BarrelState;
}
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + "[" + item.GetValue("Barrelserialnumber").ToString()! + "]\n";
if (item!.TryGetValue("State", out var _State) && _State != null)
{
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + "状态: " + _State;
}
dyelotDetailsItem.DispenseStartTime = "";
dyelotDetailsItem.DispenseEndTime = "";
dyelotDetailsItem.UsageTime = item.GetValue("Createtime").ToString()!.Replace("T", " ");
InfoDyelotHistoryItems.Add(dyelotDetailsItem);
}
if (InfoDyelotHistoryItems.Count == 0) InfoDyelotHistoryItems.Add(new DyelotDetailsItem());
}
//助剂历史信息查询
else if (id == "90")
{
foreach (var item in data!)
{
DyelotDetailsItem dyelotDetailsItem = new DyelotDetailsItem();
dyelotDetailsItem.Dyelot = item.GetValue("Dyelot").ToString()!;
dyelotDetailsItem.ReDye = int.Parse(item.GetValue("ReDye").ToString()!);
dyelotDetailsItem.StepNumber = int.Parse(item.GetValue("StepNumber").ToString()!);
dyelotDetailsItem.Notes = "染机: " + item.GetValue("Machine").ToString()! + "\n";
if (item!.TryGetValue("State", out var _State) && _State != null)
{
string temp = _State?.ToString() ?? "";
// 转换
_State = temp switch
{
"301" => "完成",
"309" => "异常",
_ => "无信息"
};
dyelotDetailsItem.Notes = dyelotDetailsItem.Notes + "状态: " + _State;
}
dyelotDetailsItem.DispenseStartTime = item.GetValue("DispenseStartTime").ToString()!.Replace("T", " ");
dyelotDetailsItem.DispenseEndTime = item.GetValue("DispenseEndTime").ToString()!.Replace("T", " ");
if (item!.TryGetValue("CallTime", out var _CallTime) && _CallTime != null)
{
if (DateTime.TryParse(_CallTime.ToString(), out DateTime dtc))
{
dyelotDetailsItem.CallTime = dtc.ToString("yyyy-MM-dd HH:mm:ss");
}
}
InfoDyelotHistoryItems.Add(dyelotDetailsItem);
}
if (InfoDyelotHistoryItems.Count == 0) InfoDyelotHistoryItems.Add(new DyelotDetailsItem());
}
}
}
+130 -59
View File
@@ -7,68 +7,139 @@
<ContentPage.Resources>
<ResourceDictionary>
<converters:StringToImageConverter x:Key="StringToImageConverter" />
<converters:StringToBoolConverter x:Key="StringToBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ScrollView>
<VerticalStackLayout Padding="20" Spacing="20">
<CollectionView x:Name="CardCollectionView"
ItemsSource="{Binding InfoItems}"
RemainingItemsThreshold="5">
<!-- 保持滚动条 -->
<CollectionView.ItemTemplate>
<DataTemplate>
<!-- 这里定义单个卡片的 UI 结构 -->
<Border BackgroundColor="White" Stroke="#CCCCCC"
StrokeThickness="2" Margin="10,0,10,10"
StrokeShape="RoundRectangle 10">
<Grid>
<!-- 定义一行 -->
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="#CCCCCC">
<Label Text="{Binding Name}" FontAttributes="Bold"
FontSize="24" TextColor="Black"
Padding="5"/>
</Grid>
<Grid Grid.Row="1">
<VerticalStackLayout>
<Grid>
<HorizontalStackLayout>
<!-- 图片 -->
<Image WidthRequest="100" HeightRequest="100"
Source="{Binding Path=Model, Converter={StaticResource StringToImageConverter}}"/>
<!-- 设备状态 -->
<VerticalStackLayout>
<HorizontalStackLayout>
<Label Text="状态: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding State}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="机台: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding Machine}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</HorizontalStackLayout>
</Grid>
<BoxView HeightRequest="3" Color="#CCCCCC" />
<HorizontalStackLayout>
<!-- 设备信息 -->
<Label Text="{Binding Information}" FontAttributes="Bold"
<RefreshView x:Name="myRefreshView_" >
<CollectionView x:Name="CardCollectionView">
<CollectionView.Header>
<Border BackgroundColor="White"
Stroke="#CCCCCC"
Margin="10,0,10,10"
StrokeThickness="5"
StrokeShape="RoundRectangle 10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="今日输送信息" Grid.Row="0" BackgroundColor="#CCCCCC"
FontAttributes="Bold" FontSize="24" TextColor="Black" Padding="5"/>
<Grid Grid.Row="1" ColumnDefinitions="Auto,*,Auto" Padding="5" ColumnSpacing="5">
<HorizontalStackLayout>
<!-- 图片 -->
<Image WidthRequest="100" HeightRequest="100" Source="sunlightlogo.png"/>
<!-- 设备状态文字内容 -->
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center">
<ContentView>
<HorizontalStackLayout VerticalOptions="Center">
<Label Text="染料称量(次): " FontAttributes="Bold"
FontSize="20" TextColor="Black"/>
<Label x:Name="_DyeMeasurementNumber" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</Grid>
</ContentView>
<ContentView>
<HorizontalStackLayout VerticalOptions="Center">
<Label Text="染料输送(次): " FontAttributes="Bold"
FontSize="20" TextColor="Black"/>
<Label x:Name="_DyeDissolveNumber" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</ContentView>
<ContentView>
<HorizontalStackLayout VerticalOptions="Center">
<Label Text="助剂输送(次): " FontAttributes="Bold"
FontSize="20" TextColor="Black"/>
<Label x:Name="_ChemicalNumber" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</ContentView>
<ContentView>
<HorizontalStackLayout VerticalOptions="Center">
<Label Text="粉剂输送(次): " FontAttributes="Bold"
FontSize="20" TextColor="Black"/>
<Label x:Name="_PowderNumber" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</ContentView>
</VerticalStackLayout>
</HorizontalStackLayout>
</Grid>
</Grid>
<!-- 点击事件 -->
<Border.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_ChemicalStatistics"/>
</Border.GestureRecognizers>
</Border>
</CollectionView.Header>
<!-- 保持滚动条 -->
<CollectionView.ItemTemplate>
<DataTemplate>
<!-- 这里定义单个卡片的 UI 结构 -->
<Border BackgroundColor="White" Stroke="#CCCCCC"
StrokeThickness="2" Margin="10,0,10,10"
StrokeShape="RoundRectangle 10">
<Grid>
<!-- 定义一行 -->
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="#CCCCCC">
<Label Text="{Binding Name}" FontAttributes="Bold"
FontSize="24" TextColor="Black" Padding="5"/>
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>
<Grid Grid.Row="1">
<VerticalStackLayout>
<Grid>
<HorizontalStackLayout>
<!-- 图片 -->
<Image WidthRequest="100" HeightRequest="100"
Source="{Binding Path=Model, Converter={StaticResource StringToImageConverter}}"/>
<!-- 设备状态 -->
<VerticalStackLayout>
<HorizontalStackLayout>
<Label Text="状态: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding State}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="机台: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding Machine}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</HorizontalStackLayout>
</Grid>
<BoxView HeightRequest="3" Color="#CCCCCC" />
<!-- 设备信息 -->
<Label Text="{Binding ModelA}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=ModelA, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding ModelB}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=ModelB, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding ModelC}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=ModelC, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding ModelD}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=ModelD, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding ModelE}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=ModelE, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding ModelF}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=ModelF, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding Information}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</VerticalStackLayout>
</Grid>
</Grid>
<!-- 点击事件 -->
<Border.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Border.GestureRecognizers>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</ContentPage>
+96 -10
View File
@@ -1,3 +1,7 @@
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific;
using SunlightAggregationTerminal.Class;
using SunlightAggregationTerminal.Models;
using System.Collections.ObjectModel;
@@ -5,22 +9,104 @@ namespace SunlightAggregationTerminal;
public partial class InfoPage : ContentPage
{
public ObservableCollection<InfoItem> InfoItems { get; set; } = new();
public static ObservableCollection<InfoItem> InfoItems { get; set; } = new();
private DateTime _lastRefreshTime = DateTime.MinValue;
public static string? DyeMeasurementNumber, ChemicalNumber, PowderNumber, DyeDissolveNumber;
public InfoPage()
{
{
InitializeComponent();
InfoItems.Add(new InfoItem { Name="202",Model= "302", State="tz",Machine="123456",Information="etggsgt\n234423\ngsgsg\nstset" });
InfoItems.Add(new InfoItem { Name = "pdw", Model = "252-2T", State = "tz", Machine = "123456", Information = "etggsgt\n234423\ngsgsg\nstset" });
InfoItems.Add(new InfoItem { Name = "pdw", Model = "242W", State = "tz", Machine = "123456", Information = "etggsgt\n234423\ngsgsg\nstset" });
CardCollectionView.ItemsSource = InfoItems;
// 注册订阅一个不携带数据的消息(使用 object 作为泛型)
WeakReferenceMessenger.Default.Register<object>(this, (r, m) =>
{
// 收到信号,直接触发函数
HandleUITrigger();
});
//注册当前页面的下滑刷新
myRefreshView_.Refreshing += (sender, e) => {
// 防抖判断:如果距离上次刷新不足5秒,直接取消本次操作
if ((DateTime.Now - _lastRefreshTime).TotalSeconds < 1)
{
myRefreshView_.IsRefreshing = false;
return;
}
try
{
// 更新刷新时间
_lastRefreshTime = DateTime.Now;
DataReceived.Transmit("{\"Command\":\"Info\"}");
}
catch (Exception)
{
}
};
}
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e)
private async void TapGestureRecognizer_ChemicalStatistics(object sender, TappedEventArgs e)
{
await Navigation.PushAsync(new InfoChemicalStatistics());
}
private void HandleUITrigger()
{
_DyeMeasurementNumber.Text = DyeMeasurementNumber;
_ChemicalNumber.Text = ChemicalNumber;
_PowderNumber.Text = PowderNumber;
_DyeDissolveNumber.Text = DyeDissolveNumber;
InfoItems.Clear();
foreach (Dictionary<string, object> List in DataModel.Info_data)
{
var mapping = new Dictionary<string, Action<InfoItem, string>>
{
{ "Name", (obj, val) => obj.Name = val },
{ "State", (obj, val) => obj.State = val },
{ "MachineName", (obj, val) => obj.MachineName = val },
{ "Machine", (obj, val) => obj.Machine = val },
{ "Information", (obj, val) => obj.Information = val },
{ "Type", (obj, val) => obj.Type = val },
{ "Model", (obj, val) => obj.Model = val },
{ "ModelA", (obj, val) => obj.ModelA = val },
{ "ModelB", (obj, val) => obj.ModelB = val },
{ "ModelC", (obj, val) => obj.ModelC = val },
{ "ModelD", (obj, val) => obj.ModelD = val },
{ "ModelE", (obj, val) => obj.ModelE = val },
{ "ModelF", (obj, val) => obj.ModelF = val }
};
var info = new InfoItem();
foreach (var (key, action) in mapping)
{
if (List.TryGetValue(key, out var val) && val != null)
{
action(info, val.ToString()!);
}
}
InfoItems.Add(info);
}
CardCollectionView.ItemsSource = InfoItems;
myRefreshView_.IsRefreshing = false;
}
~InfoPage()//关闭时注销消息
{
WeakReferenceMessenger.Default.UnregisterAll(this);
}
private async void TapGestureRecognizer_Tapped(object sender, TappedEventArgs e)
{
// 将 sender 强制转换为 BindingContext 定义在 BindableObject
if (sender is Microsoft.Maui.Controls.BindableObject bindable)
{
var context = bindable.BindingContext;
if (context is InfoItem item)
{
await Navigation.PushAsync(new InfoDetail(item));
}
}
}
}
+36 -8
View File
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using TouchSocket.Core;
namespace SunlightAggregationTerminal.Models
{
@@ -11,7 +12,7 @@ namespace SunlightAggregationTerminal.Models
{
public static SqliteHelper sqliteHelper = SQLiteConfig.Config(Path.Combine(FileSystem.AppDataDirectory, "MyAppData.db"))!; //数据库连接路径(获取各平台的应用数据目录)
private Timer timer;
public AppModels()
{
if(sqliteHelper != null)
@@ -34,19 +35,33 @@ 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"));
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");
App.GlobalData.NotificationID = dat.Field<string>("NotificationID")?? "0";
}
//启动tcp
// TcpServer.CreateCustomService();
}
}
}
}
//启动通知轮询延迟120s启动周期600s
timer = new Timer(TimerNotification, null, TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(120));
}
//轮询通知的定时任务
static void TimerNotification(object? state)
{
if (App.GlobalData.LogNo)//已经登录
{
Dictionary<string, object> NotificationDictionary = new Dictionary<string, object>();
NotificationDictionary.Add("Command", "Notification");
NotificationDictionary.Add("StartTime", App.GlobalData.NotificationID);
NotificationDictionary.Add("EndTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
DataReceived.Transmit(NotificationDictionary.ToJsonString());
}
}
public static void Updata(string sql)
@@ -76,10 +91,23 @@ namespace SunlightAggregationTerminal.Models
{
App.GlobalData.LogNo = false;
// await WebSocketServer.WebSocketClient();
//发送登录请求
TcpServer.Configuration(App.GlobalData.ServerID,
if (App.GlobalData.LocalAreaNetworkMode)
{
//tcp
TcpServer.Configuration(App.GlobalData.ServerID,
App.GlobalData.User, App.GlobalData.UserPassword,
GetAppUniqueId());
}
else
{
//http
HttpServer.Configuration(App.GlobalData.ServerHTTP,
App.GlobalData.User, App.GlobalData.UserPassword,
Models.AppModels.GetAppUniqueId());
GetAppUniqueId());
}
// 创建一个 15 秒的延时任务
Task delayTask = Task.Delay(15000);
+7
View File
@@ -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; }
@@ -35,6 +37,11 @@ namespace SunlightAggregationTerminal.Models
public partial bool DarkMode { get; set; }
[ObservableProperty]
public partial bool MessageNotificationMode { get; set; }
[ObservableProperty]
public partial string NotificationID { get; set; }
public class RefreshUISignal { }
public static List<Dictionary<string, object>> Info_data = new List<Dictionary<string, object>>();
}
}
+48 -11
View File
@@ -1,8 +1,10 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Linq;
using System.Text;
namespace SunlightAggregationTerminal.Models
{
@@ -23,30 +25,65 @@ namespace SunlightAggregationTerminal.Models
public DateTime Time { get; set; }
public MsgType Type { get; set; }
}
public class InfoItem
public partial class InfoItem
{
public string? Name { get; set; }
public string? State { get; set; }
public string? MachineName { get; set; }
public string? Machine { get; set; }
public string? Information { get; set; }
public string? Model { get; set; }
public string? Type { get; set; }
public string? A { get; set; }
public string? B { get; set; }
public string? C { get; set; }
public string? D { get; set; }
public string? E { get; set; }
public string? F { get; set; }
public string? ModelA { get; set; }
public string? ModelB { get; set; }
public string? ModelC { get; set; }
public string? ModelD { get; set; }
public string? ModelE { get; set; }
public string? ModelF { get; set; }
}
public partial class ProbuctItem
{
public string? ProductName { get; set; }
public string? ProductCode { get; set; }
public string? ProductState { get; set; }
public string? ProductInf { get; set; }
}
public class DyelotItem
{
public string? Dyelot { get; set; }
public int? ReDye { get; set; }
public int? Color { get; set; }
public string? Machine { get; set; }
public string? Program { get; set; }
public string? CreationTime { get; set; }
public string? FabricName { get; set; }
public string? ColorName { get; set; }
public string? CustomerName { get; set; }
public string? Notes { get; set; }
}
public class DyelotDetailsItem
{
public string? Dyelot { get; set; }
public int? ReDye { get; set; }
public int? StepNumber { get; set; }
public string? ProductName { get; set; }
public string? ProductCode { get; set; }
public int? ProductType { get; set; }
public string? Process { get; set; }
public double? Grams { get; set; }
public string GramsDisplay => Grams?.ToString("F2") ?? "";
public string? Created { get; set; }
public string? DispenseStartTime { get; set; }
public string? DispenseEndTime { get; set; }
public string? DispenseTime { get; set; }
public string? CallTime { get; set; }
public string? UsageTime { get; set; }
public string? Tank { get; set; }
public object? PowderTargetTank { get; set; }
public double? DispenseGrams { get; set; }
public string DispenseGramsDisplay => DispenseGrams?.ToString("F2") ?? "";
public int? DispenseResult { get; set; }
public string? Notes { get; set; }
}
public static class DataService
@@ -56,7 +93,7 @@ namespace SunlightAggregationTerminal.Models
public static List<NotificationItem> GetAllItems()
{
DataSet? data = AppModels.Select("select * from Notification Where Time > '" +
DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd HH:mm:ss.fff") + "'");
DateTime.Now.AddDays(-60).ToString("yyyy-MM-dd HH:mm:ss.fff") + "'");
_NotificationData.Clear();
+1 -2
View File
@@ -5,8 +5,7 @@
Title="信息">
<CollectionView x:Name="CardCollectionView"
ItemsSource="{Binding MessageItems}"
RemainingItemsThreshold="5"
RemainingItemsThresholdReached="CardCollectionView_RemainingItemsThresholdReached">
RemainingItemsThreshold="5">
<!-- 保持滚动条 -->
<CollectionView.ItemTemplate>
<DataTemplate>
+2 -5
View File
@@ -24,7 +24,7 @@ public partial class MessagePage : ContentPage
MessageItems.Clear();
// 按时间倒序,并只取最新的 50 条
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.Message);
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(100).Where(x => x.Type == MsgType.Message);
// 将数据添加到集合中,UI 会自动更新
foreach (var item in itemsToShow)
@@ -34,8 +34,5 @@ public partial class MessagePage : ContentPage
}
}
private void CardCollectionView_RemainingItemsThresholdReached(object sender, EventArgs e)
{
}
}
+1 -1
View File
@@ -25,7 +25,7 @@ public partial class NoticePage : ContentPage
NoticeItems.Clear();
// 按时间倒序,并只取最新的 N 条(例如 50 条)
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.Notice);
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(100).Where(x => x.Type == MsgType.Notice);
// 将数据添加到集合中,UI 会自动更新
foreach (var item in itemsToShow)
+1 -1
View File
@@ -24,7 +24,7 @@ public partial class SystemPage : ContentPage
SystemItems.Clear();
// 按时间倒序,并只取最新的 N 条(例如 50 条)
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(50).Where(x => x.Type == MsgType.System);
var itemsToShow = allData.OrderByDescending(x => x.Time).Take(100).Where(x => x.Type == MsgType.System);
// 将数据添加到集合中,UI 会自动更新
foreach (var item in itemsToShow)
+81
View File
@@ -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());
}
}
}
+19 -3
View File
@@ -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"
@@ -21,8 +23,8 @@
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"/>
<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>
@@ -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">
+72 -9
View File
@@ -3,17 +3,63 @@ using SunlightAggregationTerminal.Class;
using SunlightAggregationTerminal.Models;
using SunlightAggregationTerminal.View;
using System.Collections.ObjectModel;
using TouchSocket.Core;
namespace SunlightAggregationTerminal;
public partial class ProfilePage : ContentPage
{
private static bool SET = false;
public ProfilePage()
{
InitializeComponent();
this.BindingContext = App.GlobalData;
}
public static void _data(string v,string k)
{
if (k == "Password")
{
App.GlobalData.UserPassword = v;
string sql = @"UPDATE Users SET UserPassword = '" + App.GlobalData.UserPassword
+ "' WHERE User='" + App.GlobalData.User + "';";
AppModels.Updata(sql);
SET = false;
}
if (k == "Name")
{
App.GlobalData.UserName = v;
string sql = @"UPDATE Users SET UserName = '" + App.GlobalData.UserName
+ "' WHERE User='" + App.GlobalData.User + "';";
AppModels.Updata(sql);
SET = false;
}
}
public async void _Command(string dat)
{
DataReceived.Transmit(dat);
SET = true;
// 创建一个 秒的延时任务
Task delayTask = Task.Delay(10000);
// 创建一个监测任务,不断检查变量
Task monitorTask = Task.Run(async () =>
{
while (SET)
{
// 每隔 100 毫秒检查一次,避免 CPU 占用过高
await Task.Delay(1000);
}
});
// 使用 Task.WhenAny 等待任意一个任务完成
Task task = await Task.WhenAny(delayTask, monitorTask);
if (task==delayTask)
{ //超时
await DisplayAlertAsync("", "修改失败", "是");
}
SET = false;
}
private async void Out_Clicked(object sender, EventArgs e)
{
//退出
@@ -38,10 +84,12 @@ public partial class ProfilePage : ContentPage
// 处理结果
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);
Dictionary<string, object> data_ = new Dictionary<string, object>();
data_.Add("Command", "SETUSER");
data_.Add("USER", App.GlobalData.User);
data_.Add("KEY", "Name");
data_.Add("VALUE", result);
_Command(data_.ToJsonString());
}
}
private async void UserPassword_Tapped(object sender, TappedEventArgs e)
@@ -51,10 +99,12 @@ public partial class ProfilePage : ContentPage
// 处理结果
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);
Dictionary<string, object> data_ = new Dictionary<string, object>();
data_.Add("Command", "SETUSER");
data_.Add("USER", App.GlobalData.User);
data_.Add("KEY", "Password");
data_.Add("VALUE", result);
_Command(data_.ToJsonString());
}
}
private async void ServerID_Tapped(object sender, TappedEventArgs e)
@@ -70,6 +120,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("", "代理");
+120
View File
@@ -0,0 +1,120 @@
<?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.QueryDetail"
xmlns:converters="clr-namespace:SunlightAggregationTerminal.Converters"
Title="细节" >
<ContentPage.Resources>
<ResourceDictionary>
<converters:StringToBoolConverter x:Key="StringToBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowDefinitions="Auto, *" >
<Grid BackgroundColor="#CCCCCC" Padding="10" Grid.Row="0" Grid.Column="0">
<VerticalStackLayout>
<HorizontalStackLayout>
<Label Text="工单: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label x:Name="_Dyelot" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
<Label Text="@" FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label x:Name="_ReDye" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="机台: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label x:Name="_Machine" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="下单时间: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label x:Name="_CreationTime" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="工艺: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label x:Name="_FabricName1" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="面料: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label x:Name="_FabricName" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="客户: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label x:Name="_CustomerName" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="颜色: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label FontSize="22" BackgroundColor="Black"/>
<Label x:Name="_ColorName" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<BoxView x:Name="_Color" HeightRequest="25" />
</VerticalStackLayout>
</Grid>
<Grid x:Name="_data" Grid.Row="1" Grid.Column="0" BackgroundColor="#F0F0F0">
<CollectionView x:Name="CardCollectionView_data" RemainingItemsThreshold="5">
<CollectionView.ItemTemplate>
<DataTemplate>
<Border BackgroundColor="White" Stroke="#CCCCCC"
StrokeThickness="2" Margin="10,0,10,10"
StrokeShape="RoundRectangle 10">
<VerticalStackLayout VerticalOptions="Center">
<HorizontalStackLayout>
<Label Text="步骤: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding StepNumber}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="呼叫时间: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding CallTime}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="完成时间: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding DispenseEndTime}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="用时: " FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
<Label Text="{Binding UsageTime}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="目标地址: " FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=Tank, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding Tank}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=Tank, Converter={StaticResource StringToBoolConverter}}"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="溶解流程: " FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=Process, Converter={StaticResource StringToBoolConverter}}"/>
<Label Text="{Binding Process}" FontAttributes="Bold" FontSize="22" TextColor="Black"
IsVisible="{Binding Path=Process, Converter={StaticResource StringToBoolConverter}}"/>
</HorizontalStackLayout>
<BoxView HeightRequest="3" Color="#CCCCCC" />
<HorizontalStackLayout>
<Label Text="{Binding ProductName}" FontAttributes="Bold"
FontSize="22" TextColor="Black"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<Grid x:Name="LoadingIndicator" Grid.Row="1" Grid.Column="0"
BackgroundColor="Gray" IsVisible="False" Opacity="0.9">
<VerticalStackLayout Padding="30" Spacing="10"
VerticalOptions="Center"
HorizontalOptions="Center">
<ActivityIndicator IsRunning="True"
Color="#512BD4"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Label Text="查询中..." FontAttributes="Bold"
FontSize="24" TextColor="Black"/>
</VerticalStackLayout>
</Grid>
</Grid>
</ContentPage>
+138
View File
@@ -0,0 +1,138 @@
using SunlightAggregationTerminal.Class;
using SunlightAggregationTerminal.Models;
using System.Collections.ObjectModel;
using System.Text.Json;
using TouchSocket.Core;
namespace SunlightAggregationTerminal;
public partial class QueryDetail : ContentPage
{
public static ObservableCollection<DyelotDetailsItem> QueryDetailDyelotDetailsItems { get; set; } = new();
public QueryDetail(DyelotItem item)
{
InitializeComponent();
_Dyelot.Text = item.Dyelot;
_ReDye.Text = item.ReDye?.ToString()??"";
_Machine.Text = item.Machine;
_CreationTime.Text = item.CreationTime;
_FabricName.Text = item.FabricName;
_CustomerName.Text = item.CustomerName;
_ColorName.Text = item.ColorName;
// 如果 item.Color 为 null,则默认为透明色
_Color.Color = item.Color.HasValue ? Color.FromInt(item.Color.Value) : Colors.Gray;
Dictionary<string, object> QueryDictionary = new Dictionary<string, object>();
QueryDictionary.Add("Command", "QueryDetail");
/* QueryDictionary.Add("Field", "[Dyelot],[ReDye],[StepNumber],[ProductCode],[ProductName]," +
"[ProductType],[Grams],[Created],[DispenseStartTime],[DispenseEndTime],[DispenseTime]," +
"[DispenseGrams],[DispenseResult],[Process]");*/
QueryDictionary.Add("Field", "*");
QueryDictionary.Add("Dyelot", item.Dyelot?.ToString() ?? "");
QueryDictionary.Add("ReDye", item.ReDye?.ToString()??"");
Query_Command(QueryDictionary.ToJsonString());
}
private void Data_()
{
var processedList = QueryDetailDyelotDetailsItems
.GroupBy(item => new
{
// ?.Trim() 防止空格和 null 导致的分组偏差
Dyelot = item.Dyelot?.Trim(),
Step = item.StepNumber
})
.Select(g =>
{
var list = g.ToList();
var firstItem = list.First();
// 直接使用 Select 的重载,获取当前元素的索引 i,然后通过 list[i] 访问对应的其他字段
var combinedInfo = string.Join("\n",
list.Select((x, i) => $"原料: {list[i].ProductName} ({list[i].ProductCode})\n" +
$"目标/实际: {list[i].GramsDisplay}g / {list[i].DispenseGramsDisplay}g")
);
// 赋值给最终展示的 ProductName
firstItem.ProductName = combinedInfo;
return firstItem;
})
.ToList(); // 强制立刻执行查询
// 更新 UI 绑定的 ObservableCollection
QueryDetailDyelotDetailsItems.Clear();
foreach (var item in processedList)
{
QueryDetailDyelotDetailsItems.Add(item);
}
CardCollectionView_data.ItemsSource = QueryDetailDyelotDetailsItems;
}
public async void Query_Command(string dat)
{
LoadingIndicator.IsVisible = true;
QueryDetailDyelotDetailsItems.Clear();
DataReceived.Transmit(dat);
// 创建一个 秒的延时任务
Task delayTask = Task.Delay(10000);
// 创建一个监测任务,不断检查变量
Task monitorTask = Task.Run(async () =>
{
while (QueryDetailDyelotDetailsItems.Count == 0)
{
// 每隔 100 毫秒检查一次,避免 CPU 占用过高
await Task.Delay(1000);
}
});
// 使用 Task.WhenAny 等待任意一个任务完成
await Task.WhenAny(delayTask, monitorTask);
Data_();
LoadingIndicator.IsVisible = false;
}
public static void Query_data(string dat)
{
try
{
var data = JsonSerializer.Deserialize<List<DyelotDetailsItem>>(dat);
if (data != null)
{
//添加入显示信息
foreach (var item in data)
{
//时间处理
if (DateTime.TryParse(item.DispenseEndTime, out DateTime dte))
{
item.DispenseEndTime = dte.ToString("yyyy-MM-dd HH:mm:ss");
if (DateTime.TryParse(item.DispenseStartTime, out DateTime dtr))
{
//计算用时
item.UsageTime = $"{(int)(dte - dtr).TotalMinutes}:{(dte - dtr).Seconds:D2}";
}
}
if (DateTime.TryParse(item.CallTime, out DateTime dtc))
{
item.CallTime = dtc.ToString("yyyy-MM-dd HH:mm:ss");
}
if (item.ProductType == 1 && item.Process == null) item.Process = "未知";
if (item.ProductType == 3) item.Tank = item.PowderTargetTank.ToString();
//行信息
QueryDetailDyelotDetailsItems.Add(item);
}
if (data.Count == 0)
{//如果无信息添加空白行
QueryDetailDyelotDetailsItems.Add(new DyelotDetailsItem { });
}
}
}
catch (Exception )
{
}
}
}
+62 -110
View File
@@ -4,56 +4,40 @@
x:Class="SunlightAggregationTerminal.QueryPage"
Title="">
<Grid>
<VerticalStackLayout>
<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>
<Grid RowDefinitions="Auto, *" >
<Grid RowDefinitions="Auto, *" ColumnDefinitions="*, Auto"
Grid.Row="0" Grid.Column="0">
<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" />
</Border>
<!--扫码按钮-->
<Button Grid.Row="0"
Grid.Column="1"
Clicked="OnScanButtonClicked"
BackgroundColor="Transparent"
WidthRequest="60"
HeightRequest="60"
Margin="10">
<Button Grid.Row="0" Grid.Column="1" Clicked="OnScanButtonClicked"
BackgroundColor="Transparent" WidthRequest="80"
HeightRequest="60" Margin="10">
<Button.ImageSource>
<!-- 设置图标 -->
<FileImageSource File="lucidescanline.png" />
</Button.ImageSource>
</Button>
</Grid>
<StackLayout >
<HorizontalStackLayout>
<DatePicker Format="yyyy年MM月dd日" FontSize="18"/>
<Label Text="~" FontSize="32"/>
<DatePicker Format="yyyy年MM月dd日" FontSize="18"/>
<Button Text="搜索" Margin="5"/>
<HorizontalStackLayout Grid.Row="1" Grid.Column="0" Margin="5,0,0,0" >
<DatePicker x:Name="StartTime" Format="yyyy年MM月dd日" FontSize="16"
MaximumWidthRequest="150" MinimumWidthRequest="130" WidthRequest="135"/>
<Label Text="~" FontSize="28"/>
<DatePicker x:Name="EndTime" Format="yyyy年MM月dd日" FontSize="16"
MaximumWidthRequest="150" MinimumWidthRequest="130" WidthRequest="135"/>
</HorizontalStackLayout>
<Button Grid.Row="1" Grid.Column="1" Text="搜索" Clicked="Button_Clicked"
WidthRequest="60" Padding="5,0,5,0" Margin="20,0,0,5" />
</Grid>
</StackLayout>
<Grid>
<CollectionView x:Name="CardCollectionView"
ItemsSource="{Binding DyelotItems}"
RemainingItemsThreshold="5">
<Grid Grid.Row="1" Grid.Column="0">
<CollectionView x:Name="CardCollectionView">
<!-- 保持滚动条 -->
<CollectionView.ItemTemplate>
<DataTemplate>
@@ -61,78 +45,48 @@
<Border BackgroundColor="White"
Stroke="#CCCCCC" StrokeThickness="1"
Margin="10,0,10,10" StrokeShape="RoundRectangle 10">
<Grid Padding="15">
<VerticalStackLayout>
<HorizontalStackLayout>
<Label Text="工单: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding Dyelot}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="机台: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding Machine}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="下单时间: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding CreationTime}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="面料: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding FabricName}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="颜色: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding ColorName}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="客户: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding CustomerName}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</Grid>
<VerticalStackLayout>
<HorizontalStackLayout>
<Label Text="工单: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding Dyelot}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
<Label Text="@" FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding ReDye}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="机台: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding Machine}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="下单时间: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding CreationTime}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="工艺: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding Program}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="面料: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding FabricName}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="客户: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding CustomerName}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="颜色: " FontAttributes="Bold" FontSize="22" TextColor="Black"/>
<Label Text="{Binding ColorName}" FontAttributes="Bold" FontSize="22" TextColor="Gray"/>
</HorizontalStackLayout>
</VerticalStackLayout>
<Border.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Border.GestureRecognizers>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView ItemsSource="{Binding Items}" IsVisible="False">
<CollectionView.Header>
<!-- 表头 -->
<Grid BackgroundColor="Gray" Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="步骤" TextColor="White" FontAttributes="Bold" Grid.Column="0"/>
<Label Text="物料" TextColor="White" FontAttributes="Bold" Grid.Column="1"/>
<Label Text="状态" TextColor="White" FontAttributes="Bold" Grid.Column="2"/>
<Label Text="实际" TextColor="White" FontAttributes="Bold" Grid.Column="3"/>
<Label Text="时间" TextColor="White" FontAttributes="Bold" Grid.Column="4"/>
</Grid>
</CollectionView.Header>
<CollectionView.ItemTemplate>
<DataTemplate>
<!-- 数据行 -->
<Grid Padding="10" ColumnDefinitions="*,2*,*,*,*">
<Label Text="{Binding Id}" Grid.Column="0"/>
<Label Text="{Binding Name}" Grid.Column="1"/>
<Label Text="{Binding Start}" Grid.Column="2"/>
<Label Text="{Binding Value}" Grid.Column="3"/>
<Label Text="{Binding date}" Grid.Column="4"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</CollectionView>
</Grid>
</VerticalStackLayout>
</Grid>
<!-- 查询中动画页面 -->
<Grid x:Name="LoadingIndicator" BackgroundColor="Gray"
IsVisible="False" Opacity="0.9">
@@ -143,10 +97,8 @@
Color="#512BD4"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Label Text="查询中..."
FontAttributes="Bold"
FontSize="24"
TextColor="Black"/>
<Label Text="查询中..." FontAttributes="Bold"
FontSize="24" TextColor="Black"/>
</VerticalStackLayout>
</Grid>
</Grid>
+83 -11
View File
@@ -3,7 +3,7 @@ using SunlightAggregationTerminal.Class;
using SunlightAggregationTerminal.Models;
using System.Collections.ObjectModel;
using System.Text.Json;
using static SunlightAggregationTerminal.QueryPage;
using TouchSocket.Core;
namespace SunlightAggregationTerminal;
@@ -17,18 +17,46 @@ 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();
CardCollectionView.ItemsSource = DyelotItems;
}
//扫码按钮
private async void OnScanButtonClicked(object sender, EventArgs e)
{
ResultEntry.Text = "";
// 跳转到扫码页面
await Navigation.PushAsync(new ScanPage(0));
}
private void TapGestureRecognizer_Tapped(object sender, TappedEventArgs e)
//打开单个选项卡
private async void TapGestureRecognizer_Tapped(object sender, TappedEventArgs e)
{
if (sender is Microsoft.Maui.Controls.BindableObject bindable)
{
var context = bindable.BindingContext;
if (context is DyelotItem item)
{
await Navigation.PushAsync(new QueryDetail(item));
}
}
ResultEntry.Text = "";
}
//信息回复
@@ -42,19 +70,26 @@ public partial class QueryPage : ContentPage
{
foreach (var item in data)
{
if(item.CreationTime != null) item.CreationTime = item.CreationTime.Replace("T", " ");
DyelotItems.Add(item);
}
}
if (data.Count == 0)
{//如果无信息添加空白行
DyelotItems.Add(new DyelotItem { });
}
}
}
catch (Exception) {
}
catch (Exception) { }
}
public async void Query_Command(string dat)
{
LoadingIndicator.IsVisible = true;
DyelotItems.Clear();
TcpServer.TcpTransmit(dat);
DataReceived.Transmit(dat);
// 创建一个 15 秒的延时任务
Task delayTask = Task.Delay(15000);
@@ -72,6 +107,39 @@ public partial class QueryPage : ContentPage
LoadingIndicator.IsVisible = false;
}
private void Button_Clicked(object sender, EventArgs e)
{
if (ResultEntry.Text.Length >0)
{
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", ResultEntry.Text);
Query_Command(QueryDictionary.ToJsonString());
}
else
{
Query_data();
}
}
private void Query_data()
{
Dictionary<string, object> QueryDictionary = new Dictionary<string, object>();
QueryDictionary.Add("Command", "Query");
QueryDictionary.Add("Field", "[Dyelot],[ReDye],[Program],[Color],[CreationTime]," +
"[Batch],[OrderNo],[TotalWeight],[LiquidRatio],[TotalVolume],[Final],[UserAccount]," +
"[FabricName],[ColorName],[CustomerName],[Notes]");
DateTime StartTimee_ = (DateTime)StartTime.Date!;
QueryDictionary.Add("StartTime", StartTimee_.ToString("yyyy-MM-dd"));
DateTime EndTime_ = (DateTime)EndTime.Date!;
QueryDictionary.Add("EndTime", EndTime_.AddDays(1).ToString("yyyy-MM-dd"));
Query_Command(QueryDictionary.ToJsonString());
}
// 处理“回车/完成”按钮点击
/* private void OnEntryCompleted()
{
@@ -79,10 +147,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
View File
@@ -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);
}
}
+34 -10
View File
@@ -45,6 +45,15 @@
<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>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net10.0-android|AnyCPU'">
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net10.0-android|AnyCPU'">
<AndroidPackageFormat>apk</AndroidPackageFormat>
</PropertyGroup>
<ItemGroup>
@@ -83,15 +92,28 @@
<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" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.10" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.10" />
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.80" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.10" />
<PackageReference Include="TouchSocket" Version="4.2.10" />
<PackageReference Include="TouchSocket.Http" Version="4.2.10" />
<PackageReference Include="ZXing.Net.Maui.Controls" Version="0.10.3" />
</ItemGroup>
<ItemGroup>
<Compile Update="View\LogLoading.xaml.cs">
<DependentUpon>LogLoading.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<MauiXaml Update="InfoChemicalStatistics.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="InfoDetail.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="InfoPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
@@ -110,12 +132,18 @@
<MauiXaml Update="ProfilePage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="QueryDetail.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\LogLoading.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="View\Loading.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
@@ -124,8 +152,4 @@
</MauiXaml>
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
</Project>
+21
View File
@@ -0,0 +1,21 @@
<?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.LogLoading"
Title="LogLoading">
<Grid x:Name="LoadingIndicator" BackgroundColor="Gray"
IsVisible="True" Opacity="0.9">
<VerticalStackLayout Padding="30" Spacing="10"
VerticalOptions="Center"
HorizontalOptions="Center">
<Button Text="登 录"
BackgroundColor="#512BD4"
TextColor="White"
HeightRequest="50"
WidthRequest="100"
CornerRadius="10"
Margin="0,10,0,0"
Clicked="Button_Clicked"/>
</VerticalStackLayout>
</Grid>
</ContentPage>
+17
View File
@@ -0,0 +1,17 @@
namespace SunlightAggregationTerminal.View;
public partial class LogLoading : ContentPage
{
public LogLoading()
{
InitializeComponent();
}
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PopModalAsync();
var logpage = new View.LogPage();
await Navigation.PushModalAsync(logpage);
}
}
+39 -17
View File
@@ -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;
@@ -28,7 +29,7 @@ public partial class LogPage : ContentPage
//可用服务器列表
AppModels.sqliteHelper.Open();
var userdata = AppModels.sqliteHelper.ExecuteDataSet("select * from Server", null);
var userdata = AppModels.sqliteHelper.ExecuteDataSet("SELECT * FROM Server", null);
AppModels.sqliteHelper.Close();
Items = new ObservableCollection<ItemOption>();
@@ -39,10 +40,13 @@ public partial class LogPage : ContentPage
{
if (dataRow != null)
{
string _SERVER = dataRow.Field<string>("Server")!;
string _SERVERIP = dataRow.Field<string>("ServerID")! + "," + dataRow.Field<string>("ServerHTTP")!;
var dat = new ItemOption
{
SERVER = dataRow.Field<string>("Server") ?? "",
SERVERIP = dataRow.Field<string>("ServerID") ?? ""
SERVER = _SERVER,
SERVERIP = _SERVERIP
};
Items.Add(dat);
}
@@ -69,44 +73,62 @@ public partial class LogPage : ContentPage
{
// 跳转到扫码页面
var scanPage = new ScanPage(3);
Navigation.PushAsync(scanPage);
Navigation.PushModalAsync(scanPage);
}
private async void Log_Clicked(object sender, EventArgs e)//登录
{
LoadingIndicator.IsVisible = true;
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] ?? "";
App.GlobalData.LocalAreaNetworkMode = false;
}
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'," +
" '',1,0,0,0,'" + Models.AppModels.GetAppUniqueId() + "');";
MessageNotificationMode ,GUID ,NotificationID
)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() + "','0');";
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 Server='"+ App.GlobalData.Enterprise + "' 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);
}
+79
View File
@@ -0,0 +1,79 @@
<?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="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC 清单选项
如果想要更改 Windows 用户帐户控制级别,请使用
以下节点之一替换 requestedExecutionLevel 节点。
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
元素。
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
Windows 版本的列表。取消评论适当的元素,
Windows 将自动选择最兼容的环境。 -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
-->
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>