Files
CSI-Z420-Tablet-Multi-Funct…/App.xaml.cs

246 lines
8.9 KiB
C#
Raw Normal View History

2026-05-05 15:31:24 +08:00
using Microsoft.Extensions.Configuration;
using Microsoft.Data.Sqlite;
using OfficeOpenXml;
using System;
using System.IO;
2026-05-18 15:18:28 +08:00
using System.Text.Json;
2026-05-05 15:31:24 +08:00
using System.Windows;
using TabletTester2025.Data;
using TabletTester2025.Models;
using TabletTester2025.Services;
using TabletTester2025.ViewModels;
namespace TabletTester2025
{
public partial class App : Application
{
public static IPlcService PlcService { get; private set; }
public static PlcConfiguration PlcConfig { get; private set; }
public static PharmaParameters CurrentPharmaParams { get; set; } = new PharmaParameters();
2026-05-18 15:18:28 +08:00
private static readonly JsonSerializerOptions PharmaJsonOptions = new() { WriteIndented = true };
public static string PharmaParametersFilePath
{
get
{
string directory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"CSI-Z420-Tablet-Multi-Function-Tester");
return Path.Combine(directory, "pharma-standard.json");
}
}
2026-05-05 15:31:24 +08:00
2026-05-16 17:47:46 +08:00
protected override void OnStartup(StartupEventArgs e)
2026-05-05 15:31:24 +08:00
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
base.OnStartup(e);
// 读取配置
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
var configuration = builder.Build();
2026-05-06 16:41:32 +08:00
// 数据库初始化(手动建表)
2026-05-05 15:31:24 +08:00
var connectionString = configuration.GetConnectionString("DefaultConnection") ?? "Data Source=TabletTests.db";
2026-05-06 16:41:32 +08:00
using (var connection = new Microsoft.Data.Sqlite.SqliteConnection(connectionString))
2026-05-05 15:31:24 +08:00
{
2026-05-06 16:41:32 +08:00
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
CREATE TABLE IF NOT EXISTS TestBatches (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
TestTime TEXT NOT NULL,
StationId INTEGER NOT NULL,
SampleName TEXT,
--
HardnessAvg REAL,
HardnessRSD REAL,
HardnessMax REAL,
HardnessMin REAL,
HardnessTestCount INTEGER,
2026-05-18 14:06:04 +08:00
HardnessInternalMin REAL,
HardnessInternalMax REAL,
2026-05-06 16:41:32 +08:00
--
FriabilityLoss REAL,
FriabilityTargetRpm REAL,
FriabilityTargetTimeSec INTEGER,
2026-05-18 14:06:04 +08:00
FriabilityTargetRounds INTEGER,
2026-05-06 16:41:32 +08:00
FriabilityClockwise INTEGER, -- bool 0/1
FriabilityRemainingRounds INTEGER,
WeightBefore REAL,
WeightAfter REAL,
--
DisintegrationTimeSec REAL,
RemainingTubesAtEnd INTEGER,
DisintegrationTargetFreq REAL,
DisintegrationTemp REAL,
2026-05-18 14:06:04 +08:00
DisintegrationDosageForm TEXT,
DisintegrationLimitSeconds INTEGER,
2026-05-06 16:41:32 +08:00
--
2026-05-16 16:58:57 +08:00
DissolutionChannel TEXT,
2026-05-06 16:41:32 +08:00
DissolutionRate30Min REAL,
DissolutionTargetRpm REAL,
DissolutionRSquared REAL,
DissolutionSampleInterval INTEGER,
2026-05-18 09:47:22 +08:00
Dissolution1SampleInterval REAL,
Dissolution2SampleInterval REAL,
2026-05-06 16:41:32 +08:00
DissolutionUpDownFreq REAL,
2026-05-05 15:31:24 +08:00
2026-05-06 16:41:32 +08:00
--
IsQualified INTEGER,
--
HardnessPass INTEGER,
FriabilityPass INTEGER,
DisintegrationPass INTEGER,
DissolutionPass INTEGER,
--
TestType TEXT
);
";
cmd.ExecuteNonQuery();
2026-05-18 14:06:04 +08:00
var sampleCmd = connection.CreateCommand();
sampleCmd.CommandText = @"
CREATE TABLE IF NOT EXISTS DissolutionSamplePoints (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
TestBatchId INTEGER NOT NULL,
Channel INTEGER NOT NULL,
ScheduledTimeMin REAL NOT NULL,
ActualTimeMin REAL,
Percent REAL,
RecordedAt TEXT,
FOREIGN KEY(TestBatchId) REFERENCES TestBatches(Id) ON DELETE CASCADE
);
";
sampleCmd.ExecuteNonQuery();
2026-05-06 16:41:32 +08:00
}
2026-05-16 16:58:57 +08:00
EnsureColumnsExist(connectionString);
2026-05-05 15:31:24 +08:00
// 绑定药典参数
configuration.GetSection("PharmaStandard").Bind(CurrentPharmaParams);
2026-05-18 15:18:28 +08:00
LoadLocalPharmaParameters();
2026-05-05 15:31:24 +08:00
// PLC配置
PlcConfig = configuration.GetSection("Plc").Get<PlcConfiguration>();
if (PlcConfig == null)
throw new InvalidOperationException("PLC配置缺失");
2026-05-16 17:47:46 +08:00
PlcService = new ModbusTcpPlcService(PlcConfig);
2026-05-05 15:31:24 +08:00
// 业务服务
var dbService = new DatabaseService(connectionString);
var excelService = new ExcelExportService();
var alarmService = new AlarmService();
// 主窗口
var mainWindow = new MainWindow();
mainWindow.DataContext = new MainViewModel(PlcService, dbService, excelService, alarmService, PlcConfig);
MainWindow = mainWindow;
mainWindow.Show();
}
2026-05-18 15:18:28 +08:00
public static void SaveCurrentPharmaParameters()
{
string path = PharmaParametersFilePath;
string? directory = Path.GetDirectoryName(path);
if (!string.IsNullOrWhiteSpace(directory))
Directory.CreateDirectory(directory);
File.WriteAllText(path, JsonSerializer.Serialize(CurrentPharmaParams, PharmaJsonOptions));
}
private static void LoadLocalPharmaParameters()
{
string path = PharmaParametersFilePath;
if (!File.Exists(path))
return;
try
{
var local = JsonSerializer.Deserialize<PharmaParameters>(File.ReadAllText(path));
if (local != null)
CurrentPharmaParams = local;
}
catch
{
// Keep appsettings defaults if the local parameter file is damaged.
}
}
2026-05-05 15:31:24 +08:00
private void EnsureColumnsExist(string connectionString)
{
var requiredColumns = new[]
2026-05-06 16:41:32 +08:00
{
("TestBatches", "HardnessMax", "REAL", "0"),
("TestBatches", "HardnessMin", "REAL", "0"),
("TestBatches", "HardnessTestCount", "INTEGER", "6"),
2026-05-18 14:06:04 +08:00
("TestBatches", "HardnessInternalMin", "REAL", "40"),
("TestBatches", "HardnessInternalMax", "REAL", "60"),
2026-05-06 16:41:32 +08:00
("TestBatches", "FriabilityTargetRpm", "REAL", "25"),
("TestBatches", "FriabilityTargetTimeSec", "INTEGER", "240"),
2026-05-18 14:06:04 +08:00
("TestBatches", "FriabilityTargetRounds", "INTEGER", "100"),
2026-05-06 16:41:32 +08:00
("TestBatches", "FriabilityClockwise", "INTEGER", "1"),
("TestBatches", "FriabilityRemainingRounds", "INTEGER", "100"),
("TestBatches", "WeightBefore", "REAL", "0"),
("TestBatches", "WeightAfter", "REAL", "0"),
("TestBatches", "DisintegrationTargetFreq", "REAL", "31"),
("TestBatches", "DisintegrationTemp", "REAL", "37"),
2026-05-18 14:06:04 +08:00
("TestBatches", "DisintegrationDosageForm", "TEXT", "'普通片'"),
("TestBatches", "DisintegrationLimitSeconds", "INTEGER", "900"),
2026-05-16 16:58:57 +08:00
("TestBatches", "DissolutionChannel", "TEXT", "''"),
2026-05-06 16:41:32 +08:00
("TestBatches", "DissolutionTargetRpm", "REAL", "50"),
("TestBatches", "DissolutionRSquared", "REAL", "0"),
("TestBatches", "DissolutionSampleInterval", "INTEGER", "5"),
2026-05-18 09:47:22 +08:00
("TestBatches", "Dissolution1SampleInterval", "REAL", "5"),
("TestBatches", "Dissolution2SampleInterval", "REAL", "5"),
2026-05-06 16:41:32 +08:00
("TestBatches", "DissolutionUpDownFreq", "REAL", "32"),
("TestBatches", "HardnessRSD", "REAL", "0"), // 已存在但确保
("TestBatches", "RemainingTubesAtEnd", "INTEGER", "0"),
// 新增合格列
("TestBatches", "HardnessPass", "INTEGER", "0"),
("TestBatches", "FriabilityPass", "INTEGER", "0"),
("TestBatches", "DisintegrationPass", "INTEGER", "0"),
("TestBatches", "DissolutionPass", "INTEGER", "0"),
("TestBatches", "TestType", "TEXT", "")
};
2026-05-05 15:31:24 +08:00
using var connection = new SqliteConnection(connectionString);
connection.Open();
foreach (var (table, column, colType, defaultValue) in requiredColumns)
{
// 检查列是否存在
var pragmaCmd = connection.CreateCommand();
pragmaCmd.CommandText = $"PRAGMA table_info({table})";
using var reader = pragmaCmd.ExecuteReader();
bool columnExists = false;
while (reader.Read())
{
if (reader.GetString(1) == column)
{
columnExists = true;
break;
}
}
if (!columnExists)
{
// 添加缺失的列
var alterCmd = connection.CreateCommand();
alterCmd.CommandText = $"ALTER TABLE {table} ADD COLUMN {column} {colType} DEFAULT {defaultValue}";
alterCmd.ExecuteNonQuery();
System.Diagnostics.Debug.WriteLine($"已添加缺失的列: {table}.{column}");
}
}
}
}
2026-05-16 16:58:57 +08:00
}