C# Avalonia 程式啟動顯示LOGO視窗(Splash Screen 啟動畫面)
C# Avalonia 程式啟動顯示LOGO視窗(Splash Screen 啟動畫面)
資料來源:https://share.gemini.google/IxlstWADaM02
https://share.gemini.google/9U4vigmzEdLM
SplashScreenWindow.cs
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace VPOS_Avalonia;
public partial class SplashScreenWindow : Window
{
public SplashScreenWindow()
{
InitializeComponent();
// 在視窗初始化時,強制計算並定位到第一螢幕
MoveToPrimaryScreen();
}
private void MoveToPrimaryScreen()
{
// 1. 強制關閉自動置中,改由手動座標控制
this.WindowStartupLocation = WindowStartupLocation.Manual;
// 2. 取得主螢幕
var primaryScreen = this.Screens.Primary;
if (primaryScreen != null)
{
var workingArea = primaryScreen.WorkingArea;
// 3. 取得你在 AXAML 中設定的寬高(若未設定則給預設值)
double width = double.IsNaN(this.Width) ? 400 : this.Width;
double height = double.IsNaN(this.Height) ? 250 : this.Height;
// 4. 考量高 DPI 縮放比例轉換
int pixelWidth = (int)(width * primaryScreen.Scaling);
int pixelHeight = (int)(height * primaryScreen.Scaling);
// 5. 計算置中座標
int centerX = workingArea.X + (workingArea.Width - pixelWidth) / 2;
int centerY = workingArea.Y + (workingArea.Height - pixelHeight) / 2;
this.Position = new PixelPoint(centerX, centerY);
}
}
}
SplashScreenWindow.axaml ~ 圓形視窗
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:anim="https://github.com/whistyun/AnimatedImage.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
x:Class="VPOS_Avalonia.SplashScreenWindow"
Title="SplashScreenWindow"
Width="250" Height="250"
CanResize="False"
WindowStartupLocation="CenterScreen"
SystemDecorations="None"
TransparencyLevelHint="Transparent"
Background="Transparent">
<Border Background="#CC2c3e50" CornerRadius="150" ClipToBounds="True">
<Grid RowDefinitions="*" Margin="10">
<Image Source="/Assets/vteam_logo.png" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<!--
使用GIF備註
▲ 在專案目錄(有 .csproj檔案) 開啟『命令提示字元』; dotnet add package AnimatedImage.Avalonia ~~version 1.0.7 (實際執行 把~ 換成 -)
▲ Window 標籤; xmlns:anim="https://github.com/whistyun/AnimatedImage.Avalonia"
▲ 元件使用; <Image Grid.Row="1" Grid.Column="0" Width="95" anim:ImageBehavior.AnimatedSource="avares://VPOS/Assets/wait00.gif"/>
-->
<Image Width="70" Height="70" anim:ImageBehavior.AnimatedSource="avares://VPOS/Assets/wait00.gif" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>
</Border>
</Window>
App.axaml.cs ~ 重點 [public override void OnFrameworkInitializationCompleted()]
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Primitives;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Remote.Protocol.Input;
using Avalonia.Styling;
using Avalonia.Themes.Fluent;
using Avalonia.Threading;
using Avalonia.VisualTree;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Tmds.DBus.Protocol;
using VPOS;
using VPOS_Avalonia.ViewModels;
using VPOS_Avalonia.Views;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace VPOS_Avalonia
{
public partial class App : Application
{
//---
//條件編譯常數宣告區,本區常數設定只要為TRUE 就是跳過該區域的程式碼
#if DEBUG
//Debug 區看除錯需求進行設定
public const bool m_blnSkipVerify = false;//是否跳過設備驗證流程
public const bool m_blnSkipSyncDBData = false;//是否跳過同步資料流程
public const bool m_blnSkipUpdata = false;//是否跳過上傳資料流程
#else
//Release 區一定是FALSE
public const bool m_blnSkipVerify = false;//是否跳過設備驗證流程
public const bool m_blnSkipSyncDBData = false;//是否跳過同步資料流程(包含設備註冊流程)直接進入登入畫面,僅供開發測試使用
public const bool m_blnSkipUpdata = false;//是否跳過上傳資料流程
#endif
//---條件編譯常數宣告區
public static SolidColorBrush Background { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush Foreground { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush Selectground { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush Disableground { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush DisableText { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush ActiveTabPageColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush OrderButtonColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush NumberButtonColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush ForegroundReverse { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush ProductButtonColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush CondimentButtonColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush HighlightButtonColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush InformationColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush DevicesTextColor { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush CartTextColor01 { get; private set; } = new(Colors.Transparent);
public static SolidColorBrush CartTextColor02 { get; private set; } = new(Colors.Transparent);
public void UpdateExtendedColor(ThemeVariant variant, Color newColor)
{
//https://gemini.google.com/share/3be0ccfbd3d1
// 1. 取得 ThemeDictionaries 集合
var dictionaries = Application.Current!.Resources.ThemeDictionaries;
// 2. 嘗試取得對應主題的字典並轉型為 ResourceDictionary
if (dictionaries.TryGetValue(variant, out var provider) &&
provider is ResourceDictionary themeDict)
{
// 3. 這樣就能使用索引器了
themeDict["MyExtendedColor"] = new SolidColorBrush(newColor);
}
//UpdateExtendedColor(ThemeVariant.Dark, Colors.Green);
//UpdateExtendedColor(ThemeVariant.Light, Colors.Green);
}
public static void SetThemeColor()
{
// 1. 定位到特定的主題字典 (以 Dark 模式為例)
if (Application.Current!.Resources.ThemeDictionaries.TryGetValue(ThemeVariant.Light, out var provider)
&& provider is ResourceDictionary themeDict)
{
if (themeDict.TryGetValue("VPOS_Background", out var obj) && obj is ISolidColorBrush s)
Background = new SolidColorBrush(s.Color);
if (themeDict.TryGetValue("VPOS_Foreground", out obj) && obj is ISolidColorBrush s1)
Foreground = new SolidColorBrush(s1.Color);
if (themeDict.TryGetValue("VPOS_Selectground", out obj) && obj is ISolidColorBrush s2)
Selectground = new SolidColorBrush(s2.Color);
if (themeDict.TryGetValue("VPOS_Disableground", out obj) && obj is ISolidColorBrush s3)
Disableground = new SolidColorBrush(s3.Color);
if (themeDict.TryGetValue("VPOS_DisableText", out obj) && obj is ISolidColorBrush s4)
DisableText = new SolidColorBrush(s4.Color);
if (themeDict.TryGetValue("VPOS_ActiveTabPageColor", out obj) && obj is ISolidColorBrush s5)
ActiveTabPageColor = new SolidColorBrush(s5.Color);
if (themeDict.TryGetValue("VPOS_OrderButtonColor", out obj) && obj is ISolidColorBrush s6)
OrderButtonColor = new SolidColorBrush(s6.Color);
if (themeDict.TryGetValue("VPOS_NumberButtonColor", out obj) && obj is ISolidColorBrush s7)
NumberButtonColor = new SolidColorBrush(s7.Color);
if (themeDict.TryGetValue("VPOS_ForegroundReverse", out obj) && obj is ISolidColorBrush s8)
ForegroundReverse = new SolidColorBrush(s8.Color);
if (themeDict.TryGetValue("VPOS_ProductButtonColor", out obj) && obj is ISolidColorBrush s9)
ProductButtonColor = new SolidColorBrush(s9.Color);
if (themeDict.TryGetValue("VPOS_CondimentButtonColor", out obj) && obj is ISolidColorBrush s10)
CondimentButtonColor = new SolidColorBrush(s10.Color);
if (themeDict.TryGetValue("VPOS_HighlightButtonColor", out obj) && obj is ISolidColorBrush s11)
HighlightButtonColor = new SolidColorBrush(s11.Color);
if (themeDict.TryGetValue("VPOS_InformationColor", out obj) && obj is ISolidColorBrush s12)
InformationColor = new SolidColorBrush(s12.Color);
if (themeDict.TryGetValue("VPOS_DevicesTextColor", out obj) && obj is ISolidColorBrush s13)
DevicesTextColor = new SolidColorBrush(s13.Color);
if (themeDict.TryGetValue("VPOS_CartTextColor01", out obj) && obj is ISolidColorBrush s14)
CartTextColor01 = new SolidColorBrush(s14.Color);
if (themeDict.TryGetValue("VPOS_CartTextColor02", out obj) && obj is ISolidColorBrush s15)
CartTextColor02 = new SolidColorBrush(s15.Color);
}
/*
var fluentTheme = Application.Current.Styles.OfType<FluentTheme>().FirstOrDefault();
if (fluentTheme != null)
{
// 取得 Light 變體的 Palette
if (fluentTheme.Palettes.TryGetValue(ThemeVariant.Light, out var palette))
{
// 直接從 Palette 資源中抓取顏色
// 注意:這裡拿到的 res 是 Color 結構
if (palette is ColorPaletteResources cpr)
{
var regionColor = cpr.RegionColor;
Background = new SolidColorBrush(regionColor);
regionColor = cpr.Accent;
Selectground = new SolidColorBrush(regionColor);
regionColor = cpr.BaseMediumLow;
Foreground = new SolidColorBrush(regionColor);
regionColor = cpr.BaseLow;
Disableground = new SolidColorBrush(regionColor);
regionColor = cpr.ErrorText;
DisableText = new SolidColorBrush(regionColor);
regionColor = cpr.AltMedium;
ActiveTabPageColor = new SolidColorBrush(regionColor);
regionColor = cpr.ChromeHigh;
OrderButtonColor = new SolidColorBrush(regionColor);
regionColor = cpr.AltMediumHigh;
NumberButtonColor = new SolidColorBrush(regionColor);
regionColor = cpr.BaseHigh;
ForegroundReverse = new SolidColorBrush(regionColor);
regionColor = cpr.ChromeMediumLow;
ProductButtonColor = new SolidColorBrush(regionColor);
regionColor = cpr.ChromeLow;
CondimentButtonColor = new SolidColorBrush(regionColor);
regionColor = cpr.ChromeWhite;
HighlightButtonColor = new SolidColorBrush(regionColor);
}
}
}
*/
}
public static void ScaleAllFonts(Control parent, double factor,double increment)//遞迴調整所有子控制項的字體大小
{
foreach (var child in parent.GetVisualDescendants())
{
if (child is Control control)
{
// 嘗試取得該控制項的 FontSize 屬性
// 這裡要注意:Avalonia 控制項多數繼承自 TemplatedControl 或 TextBlock
if (control is TextBlock tb)
{
tb.FontSize = tb.FontSize * factor + increment;
}
else if (control is TemplatedControl tc)
{
tc.FontSize = tc.FontSize * factor + increment;
}
else if(control.GetType().GetProperty("FontSize") != null)
{
// 使用反射來動態調整 FontSize
var fontSizeProp = control.GetType().GetProperty("FontSize");
if (fontSizeProp != null && fontSizeProp.PropertyType == typeof(double))
{
double currentSize = (double)fontSizeProp.GetValue(control);
fontSizeProp.SetValue(control, currentSize * factor + increment);
}
}
}
}
}
public const bool m_blnParentDir = false;//指定系統檔案所在路徑 true:上層目錄 false:同層目錄
public void DBFilesInit(bool blnInit)//DB實體檔案初始化
{
LogFile.CleanLog();
if (m_blnParentDir)
{
FileLib.DeleteFile("..\\vpos.db-shm");
FileLib.DeleteFile("..\\vpos.db-wal");
FileLib.DeleteFile("..\\vtcloud_sync.db-shm");
FileLib.DeleteFile("..\\vtcloud_sync.db-wal");
FileLib.DeleteFile("..\\takeaways.db-shm");
FileLib.DeleteFile("..\\takeaways.db-wal");
}
else
{
FileLib.DeleteFile("vpos.db-shm");
FileLib.DeleteFile("vpos.db-wal");
FileLib.DeleteFile("vtcloud_sync.db-shm");
FileLib.DeleteFile("vtcloud_sync.db-wal");
FileLib.DeleteFile("takeaways.db-shm");
FileLib.DeleteFile("takeaways.db-wal");
}
if (blnInit)
{
//---
//SQLITE資料庫使用動態產生
string StrPath = (m_blnParentDir) ? Directory.GetParent(LogFile.m_StrSysPath.Substring(0, LogFile.m_StrSysPath.Length - 1)).FullName + "\\" : LogFile.m_StrSysPath;
string StrFileNameBuf00 = StrPath + "vpos_def.db";
string StrFileNameBuf01 = StrPath + "vpos.db";
if ((File.Exists(StrFileNameBuf00)) && (!File.Exists(StrFileNameBuf01)))
{
File.Copy(StrFileNameBuf00, StrFileNameBuf01, true);
LogFile.Write("SystemNormal ; vpos.db Init");
}
else
{
if (!File.Exists(StrFileNameBuf00))
{
LogFile.Write("SystemError ; vpos_def.db missing");
}
if (!File.Exists(StrFileNameBuf01))
{
LogFile.Write("SystemError ; vpos.db missing");
}
}
StrFileNameBuf00 = StrPath + "vtcloud_sync.db";
if (!File.Exists(StrFileNameBuf00))
{
SQLDataTableModel.CreateSQLiteDatabase(StrFileNameBuf00);
}
string strTableName = "upload_data";
SQLDataTableModel.CreateSQLiteTable(StrFileNameBuf00, strTableName);//建立資料表程式
LogFile.Write("SystemNormal ; vtcloud_sync.db Init");
//---SQLITE資料庫使用動態產生
SyncDBData.DBStructRegulating();//資料庫(DB) 新增資料表 / 新增(補)欄位 / 調整欄位資料型
}
}
//---
//設備註冊 & 同步資料流程
public static bool VerifyVLCS(string terminal_sid, string api_token)//驗證設備是否為合法設備
{
bool blnResult = false;
if(m_blnSkipVerify)//條件編譯常數設定為TRUE 就是跳過該區域的程式碼
{
blnResult = true;
return blnResult;
}
string StrResult = terminal_dataGet(terminal_sid, api_token);//呼叫 /api/terminal/data API
StrResult = StrResult.Replace("\"reg_accept_unix_time\":null", "\"reg_accept_unix_time\":0");//防堵WEB輸出JSON的BUG
get_terminal_data get_terminal_dataBuf = JsonClassConvert.get_terminal_data2Class(StrResult);
if ((get_terminal_dataBuf != null) && (get_terminal_dataBuf.status == "ACCEPTED") && (get_terminal_dataBuf.data.del_flag == "N") && (get_terminal_dataBuf.data.reg_state == "Y"))
{
blnResult = true;
//---
//營業日對應運算&判斷機制:
string Strbusiness_day = ((get_terminal_dataBuf.data.descript != null) && (get_terminal_dataBuf.data.descript.business_day > 0)) ? TimeConvert.UnixTimeStampToDateTime(get_terminal_dataBuf.data.descript.business_day).ToString("yyyy-MM-dd") : DateTime.Now.ToString("yyyy-MM-dd");
if (SqliteDataAccess.m_terminal_data.Count > 0)
{
DateTime dt1 = VP_Convert.ToDateTime(Strbusiness_day);
DateTime dt2 = VP_Convert.ToDateTime(SqliteDataAccess.m_terminal_data[0].business_day);
//TimeSpan ts = dt1 - dt2;
Strbusiness_day = (string.Compare(dt1.ToString("yyyyMMdd"), dt2.ToString("yyyyMMdd")) == 1) ? Strbusiness_day : SqliteDataAccess.m_terminal_data[0].business_day;
}
//---營業日對應運算&判斷機制:
//---
//同步terminal_data
string SQL = string.Format("UPDATE terminal_data SET company_sid='{0}',terminal_name='{1}',app_version='{2}',invoice_active_state='{3}',pos_no='{4}',pid='{5}',rid='{6}',reg_submit_time='{7}',keyhook_enable='{8}',last_order_no='{9}',last_class_report_no='{10}',last_daily_report_no='{11}',client_id='{12}',client_secret='{13}',business_day='{14}',api_token_id='{15}',params='{16}',use_call_num_date='{17}',panel_styles='{18}' WHERE SID='{19}'",
get_terminal_dataBuf.data.company_sid,
get_terminal_dataBuf.data.terminal_name,
get_terminal_dataBuf.data.app_version,
get_terminal_dataBuf.data.invoice_active_state,
get_terminal_dataBuf.data.pos_no,
get_terminal_dataBuf.data.pid,
get_terminal_dataBuf.data.rid,
get_terminal_dataBuf.data.reg_submit_time,
get_terminal_dataBuf.data.keyhook_enable,
get_terminal_dataBuf.data.last_order_no,
get_terminal_dataBuf.data.last_class_report_no,
get_terminal_dataBuf.data.last_daily_report_no,
get_terminal_dataBuf.data.client_id,
get_terminal_dataBuf.data.client_secret,
Strbusiness_day,
get_terminal_dataBuf.data.api_token,
get_terminal_dataBuf.data.@params,//新增 終端設備資料表 params at 20221020
get_terminal_dataBuf.data.use_call_num_date,
get_terminal_dataBuf.data.panel_styles,
get_terminal_dataBuf.data.terminal_sid);
SQLDataTableModel.SQLiteInsertUpdateDelete(SQL);
//MainWindow.m_terminal_panel_styles = JsonClassConvert.terminal_panel_styles2Class(get_terminal_dataBuf.data.panel_styles);
//---同步terminal_data
//---
//更新vpos.vlcs
VLCS VLCSBuf = new VLCS();
VLCSBuf.terminal_sid = terminal_sid;
VLCSBuf.api_token = api_token;
VLCSBuf.machine_code = MainWindow.m_StrDeviceCode;
VLCSBuf.check_license_time = TimeConvert.DateTimeToUnixTimeStamp(DateTime.Now);
VLCSFileUpdate(VLCSBuf);
//---更新vpos.vlcs
}
return blnResult;
}
public static void VLCSFileUpdate(VLCS VLCSBuf)
{
string StrPath = (m_blnParentDir) ? Directory.GetParent(FileLib.path.Substring(0, FileLib.path.Length - 1)).FullName + "\\" : FileLib.path;
if (FileLib.IsFileExists("vpos.vlcs"))//vlcs.json
{
FileLib.DeleteFile("vpos.vlcs", StrPath, false);
}
string StrResult = StringEncrypt.AesEncrypt(JsonClassConvert.VLCS2String(VLCSBuf));
FileLib.TxtFile("vpos.vlcs", StrPath, StrResult);
}
//public static int m_intNetworkLevel = 0;//紀錄網路連線等級 0(網卡不通)、-1(GOOGLE不通)、-2(POS不通)
public bool IsRegisterDevice()//判斷是否需要註冊設備
{
bool blnResult = false;
string StrLoginInputResult = "";
LogFile.Write("IsRegisterDevice() start");
//---
//判斷vpos.vlcs檔案存在與否與正確性
if (!FileLib.IsFileExists("vpos.vlcs"))//vlcs.json
{//檔案不存在
LogFile.Write("IsRegisterDevice() file not find");
//if (SqliteDataAccess.m_terminal_data.Count > 0)
//{
// LogFile.Write("IsRegisterDevice() get data for db");
// String terminal_sid = SqliteDataAccess.m_terminal_data[0].SID;
// String api_token = SqliteDataAccess.m_terminal_data[0].api_token_id;
// if (VerifyVLCS(terminal_sid, api_token))//使用DB資料進行驗證
// {
// blnResult = false;//不用註冊;需要同步更新資料
// SyncDBData.Iint(terminal_sid, api_token);
// }
// else
// {//DB資料驗證失敗
// LogFile.Write("IsRegisterDevice() not get data for db");
// blnResult = true;//需要設備註冊
// }
//}
//else
//{//DB沒有資料
// LogFile.Write("IsRegisterDevice() not db");
// blnResult = true;//需要設備註冊
//}
blnResult = true;//需要設備註冊
}
else
{//檔案存在
LogFile.Write("IsRegisterDevice() get vpos.vlcs");
string StrVLCS = StringEncrypt.AesDecrypt(FileLib.ReadTxtFile("vpos.vlcs"));
VLCS VLCSBuf = JsonClassConvert.VLCS2Class(StrVLCS);
if ((VLCSBuf != null) && (SqliteDataAccess.m_terminal_data != null) && (SqliteDataAccess.m_terminal_data.Count > 0))
{//有vlcs檔案能用
LogFile.Write("IsRegisterDevice() read vpos.vlcs OK");
if ((VLCSBuf.terminal_sid == SqliteDataAccess.m_terminal_data[0].SID) && (VLCSBuf.api_token == SqliteDataAccess.m_terminal_data[0].api_token_id))
{//與DB資料一致
HttpsFun.m_intNetworkLevel = 0;
if (HttpsFun.WebRequestTest(ref HttpsFun.m_intNetworkLevel))//判斷是否有網路
{
string StrResult = terminal_dataGet(VLCSBuf.terminal_sid, VLCSBuf.api_token);//呼叫 /api/terminal/data API
StrResult = StrResult.Replace("\"reg_accept_unix_time\":null", "\"reg_accept_unix_time\":0");//防堵WEB輸出JSON的BUG
get_terminal_data get_terminal_dataBuf = JsonClassConvert.get_terminal_data2Class(StrResult);
if ((get_terminal_dataBuf != null) && (get_terminal_dataBuf.status == "ACCEPTED") && (get_terminal_dataBuf.data.del_flag == "N") && (get_terminal_dataBuf.data.reg_state == "Y"))
{
//---
//營業日對應運算&判斷機制:
string Strbusiness_day = ((get_terminal_dataBuf.data.descript != null) && (get_terminal_dataBuf.data.descript.business_day > 0)) ? TimeConvert.UnixTimeStampToDateTime(get_terminal_dataBuf.data.descript.business_day).ToString("yyyy-MM-dd") : DateTime.Now.ToString("yyyy-MM-dd");
if (SqliteDataAccess.m_terminal_data.Count > 0)
{
DateTime dt1 = VP_Convert.ToDateTime(Strbusiness_day);
DateTime dt2 = VP_Convert.ToDateTime(SqliteDataAccess.m_terminal_data[0].business_day);
//TimeSpan ts = dt1 - dt2;
Strbusiness_day = (string.Compare(dt1.ToString("yyyyMMdd"), dt2.ToString("yyyyMMdd")) == 1) ? Strbusiness_day : SqliteDataAccess.m_terminal_data[0].business_day;
}
//---營業日對應運算&判斷機制:
//---
//同步terminal_data
string SQL = string.Format("UPDATE terminal_data SET company_sid='{0}',terminal_name='{1}',app_version='{2}',invoice_active_state='{3}',pos_no='{4}',pid='{5}',rid='{6}',reg_submit_time='{7}',keyhook_enable='{8}',last_order_no='{9}',last_class_report_no='{10}',last_daily_report_no='{11}',client_id='{12}',client_secret='{13}',business_day='{14}',api_token_id='{15}',params='{16}',use_call_num_date='{17}',panel_styles='{18}' WHERE SID='{19}'",
get_terminal_dataBuf.data.company_sid,
get_terminal_dataBuf.data.terminal_name,
get_terminal_dataBuf.data.app_version,
get_terminal_dataBuf.data.invoice_active_state,
get_terminal_dataBuf.data.pos_no,
get_terminal_dataBuf.data.pid,
get_terminal_dataBuf.data.rid,
get_terminal_dataBuf.data.reg_submit_time,
get_terminal_dataBuf.data.keyhook_enable,
get_terminal_dataBuf.data.last_order_no,
get_terminal_dataBuf.data.last_class_report_no,
get_terminal_dataBuf.data.last_daily_report_no,
get_terminal_dataBuf.data.client_id,
get_terminal_dataBuf.data.client_secret,
Strbusiness_day,
get_terminal_dataBuf.data.api_token,
get_terminal_dataBuf.data.@params,//新增 終端設備資料表 params at 20221020
get_terminal_dataBuf.data.use_call_num_date,
get_terminal_dataBuf.data.panel_styles,
get_terminal_dataBuf.data.terminal_sid);
SQLDataTableModel.SQLiteInsertUpdateDelete(SQL);
//MainWindow.m_terminal_panel_styles = JsonClassConvert.terminal_panel_styles2Class(get_terminal_dataBuf.data.panel_styles);
//---同步terminal_data
blnResult = false;//不用註冊;需要同步更新資料
SyncDBData.Iint(VLCSBuf.terminal_sid, VLCSBuf.api_token);
}
else
{//有資料但網路驗證失敗
blnResult = true;//需要設備註冊
}
}
else
{
HttpsFun.m_intNetworkLevel *= -1;//紀錄網路連線等級 0(網卡不通)、-1(GOOGLE不通)、-2(POS不通)
blnResult = false;//不需要設備註冊
}
}
else
{//vlcs 和 DB資料不一致
LogFile.Write("IsRegisterDevice() vpos.vlcs != DB");
blnResult = true;//需要設備註冊
}
}
else
{//有vlcs檔案但是不能用
LogFile.Write("IsRegisterDevice() read vpos.vlcs Fall");
blnResult = true;//需要設備註冊 [堵死V1自動升級V2流程(vpos.vlcs 解不開 就要設備註冊)]
/*
if (SqliteDataAccess.m_terminal_data.Count > 0)
{
string terminal_sid = SqliteDataAccess.m_terminal_data[0].SID;
string api_token = SqliteDataAccess.m_terminal_data[0].api_token_id;
if (VerifyVLCS(terminal_sid, api_token))//使用DB資料進行驗證
{
LogFile.Write("IsRegisterDevice() DB data OK");
blnResult = false;//不需要設備註冊
SyncDBData.Iint(terminal_sid, api_token);
}
else
{//DB資料驗證失敗
LogFile.Write("IsRegisterDevice() DB data Fall");
blnResult = true;//需要設備註冊
}
}
else
{//DB沒有資料
LogFile.Write("IsRegisterDevice() DB has no data");
blnResult = true;//需要設備註冊
}
*/
}
}
//---判斷vpos.vlcs檔案存在與否與正確性
LogFile.Write("IsRegisterDevice() finish");
return blnResult;
}
public static string terminal_dataGet(string Username, string Password)// IsRegisterDevice() / VerifyVLCS()
{
//c# httpwebrequest basic authentication
//https://stackoverflow.com/questions/4334521/httpwebrequest-using-basic-authentication
//https://zh.wikipedia.org/zh-tw/ISO/IEC_8859-1
string username = Username;//terminal_sid
string password = Password;//api_token
string encoded = System.Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
HttpsFun.setDomainMode(1);//POS
string StrResult = HttpsFun.RESTfulAPI_get("/api/terminal/data", "", "Authorization", "Basic " + encoded);
return StrResult;
}
//---設備註冊 & 同步資料流程
public override void Initialize()
{
// 註冊編碼提供者,這樣可以使用 big5 編碼
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
AvaloniaXamlLoader.Load(this);
}
public static void ShowLoadingAndLoginUI(IClassicDesktopStyleApplicationLifetime desktop)
{
if (HttpsFun.WebRequestTest(ref HttpsFun.m_intNetworkLevel))//判斷是否有網路
{
Loading LoadingUI = new Loading();//同步本地端資料庫
LoadingUI.Closed += (s, e) =>
{
Login LoginUI = new Login();
desktop.MainWindow = LoginUI;
LoginUI.Closed += (sender, args) =>
{
if (Login.m_blnCloseApp)
{
desktop.Shutdown();//應用程式關閉。[WPF]
}
};
LoginUI.Show();
};
desktop.MainWindow = LoadingUI;
LoadingUI.Show();
}
else
{
Login LoginUI = new Login();
desktop.MainWindow = LoginUI;
LoginUI.Closed += (sender, args) =>
{
if (Login.m_blnCloseApp)
{
desktop.Shutdown();//應用程式關閉。[WPF]
}
};
LoginUI.Show();
}
}
public static void ShowAuthorizationUI(IClassicDesktopStyleApplicationLifetime desktop)
{
InvisibleWindow InvisibleWindowBuf = new InvisibleWindow();
InvisibleWindowBuf.Closed += (sender, args) =>
{
if(InvisibleWindow.m_blnResult)
{
ShowLoadingAndLoginUI(desktop);
}
else
{
desktop.Shutdown();//應用程式關閉。[WPF]
}
};
desktop.MainWindow = InvisibleWindowBuf;
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// 1. 先建立並顯示 Logo 視窗
var splashWindow = new SplashScreenWindow();
desktop.MainWindow = splashWindow;
splashWindow.Show();
LogFile.Write("App Start");
DBFilesInit(true);
HttpsFun.DomainVarInit();
SqliteDataAccess.m_terminal_data = SqliteDataAccess.terminal_dataLoad();//讀取DB設備參數資料(terminal_data)
SetThemeColor();// 確保在 Styles 載入後初始化
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;//只有在呼叫了 Shutdown() 時,應用程式才會關閉。[WPF]
if (!IsRegisterDevice())//判斷是否註冊POS
{//同步DB
ShowLoadingAndLoginUI(desktop);
}
else
{
ShowAuthorizationUI(desktop);
}
// 4. 切換主視窗並關閉 Logo 視窗
splashWindow.Close();// 關閉 Logo 視窗
}
base.OnFrameworkInitializationCompleted();
}
}
}
目的: 使用過場動畫 降低 等待程式啟動的無聊和焦慮