using Check.Main.Common; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; namespace Check.Main.Dispatch { public static class ProductManager { private static readonly string _productRootPath = Path.Combine(Application.StartupPath, "Product"); private static readonly string _productListFilePath = Path.Combine(Application.StartupPath, "products.json"); // --- 公共属性和事件 --- public static List ProductList { get; private set; } = new List(); public static string CurrentProductName { get; private set; } public static ProcessConfig CurrentConfig { get; private set; } /// /// 当产品切换或配置加载后触发。 /// public static event Action OnProductChanged; /// /// 静态构造函数,在程序启动时自动执行。 /// static ProductManager() { Directory.CreateDirectory(_productRootPath); // 确保Product文件夹存在 LoadProductList(); // 默认加载列表中的第一个产品,或者创建一个默认的 SwitchToProduct(ProductList.FirstOrDefault() ?? "DefaultProduct"); } /// /// 切换到指定的产品,并加载其配置。 /// public static bool SwitchToProduct(string productName) { if (string.IsNullOrWhiteSpace(productName)) return false; ThreadSafeLogger.Log($"正在切换到产品: {productName}"); var config = LoadConfigForProduct(productName); if (config == null) { // 如果加载失败(例如新创建的产品还没有配置文件),则创建一个新的 config = new ProcessConfig(); } CurrentProductName = productName; CurrentConfig = config; // 广播产品已变更的通知 OnProductChanged?.Invoke(); return true; } /// /// 添加一个新产品。 /// public static bool AddNewProduct(string newProductName) { if (string.IsNullOrWhiteSpace(newProductName) || ProductList.Contains(newProductName)) { return false; // 名称无效或已存在 } // 创建一个全新的、空的配置 var newConfig = new ProcessConfig(); // 保存这个新产品的空配置,这也会创建文件夹 if (SaveConfigForProduct(newProductName, newConfig)) { ProductList.Add(newProductName); SaveProductList(); // 更新产品列表文件 SwitchToProduct(newProductName); // 创建后立即切换到新产品 return true; } return false; } /// /// 删除指定的产品及其所有相关配置。 /// /// 要删除的产品名称。 /// 成功删除返回 true,否则返回 false。 public static bool DeleteProduct(string productNameToDelete) { if (string.IsNullOrWhiteSpace(productNameToDelete) || !ProductList.Contains(productNameToDelete)) { ThreadSafeLogger.Log($"[警告] 尝试删除一个不存在的产品: {productNameToDelete}"); return false; // 产品不存在 } ThreadSafeLogger.Log($"正在删除产品: {productNameToDelete}..."); try { // 1. 从产品列表中移除 ProductList.Remove(productNameToDelete); SaveProductList(); // 更新列表文件 // 2. 删除对应的配置文件夹 var safeFolderName = GetSafeFolderName(productNameToDelete); var productDir = Path.Combine(_productRootPath, safeFolderName); if (Directory.Exists(productDir)) { Directory.Delete(productDir, true); // true 表示递归删除所有子文件和子文件夹 } ThreadSafeLogger.Log($"产品 '{productNameToDelete}' 已成功删除。"); // 3. 如果被删除的是当前活动产品,则需要切换到一个新的有效产品 if (CurrentProductName == productNameToDelete) { // 切换到列表中的第一个产品,或者如果列表为空,则创建一个默认产品 string nextProduct = ProductList.FirstOrDefault() ?? "DefaultProduct"; SwitchToProduct(nextProduct); } else { // 如果删除的不是当前产品,我们仍然需要触发一次事件, // 以便UI(主要是下拉列表)能够刷新它的数据源。 OnProductChanged?.Invoke(); } return true; } catch (Exception ex) { ThreadSafeLogger.Log($"[错误] 删除产品 '{productNameToDelete}' 失败: {ex.Message}"); // 如果出错,最好把刚删除的项加回来,保持状态一致性 if (!ProductList.Contains(productNameToDelete)) { ProductList.Add(productNameToDelete); } return false; } } /// /// 为当前产品保存更改。 /// public static void SaveCurrentProductConfig() { if (CurrentConfig != null && !string.IsNullOrWhiteSpace(CurrentProductName)) { SaveConfigForProduct(CurrentProductName, CurrentConfig); } } #region 文件操作辅助方法 private static void LoadProductList() { try { if (File.Exists(_productListFilePath)) { var json = File.ReadAllText(_productListFilePath); ProductList = JsonConvert.DeserializeObject>(json) ?? new List(); } } catch (Exception ex) { ThreadSafeLogger.Log($"[错误] 加载产品列表失败: {ex.Message}"); ProductList = new List(); } } private static void SaveProductList() { try { var json = JsonConvert.SerializeObject(ProductList, Newtonsoft.Json.Formatting.Indented); File.WriteAllText(_productListFilePath, json); } catch (Exception ex) { ThreadSafeLogger.Log($"[错误] 保存产品列表失败: {ex.Message}"); } } private static ProcessConfig LoadConfigForProduct(string productName) { var safeFolderName = GetSafeFolderName(productName); var configPath = Path.Combine(_productRootPath, safeFolderName, "config.xml"); if (!File.Exists(configPath)) return null; try { XmlSerializer serializer = new XmlSerializer(typeof(ProcessConfig)); using (var fs = new FileStream(configPath, FileMode.Open, FileAccess.Read)) { return (ProcessConfig)serializer.Deserialize(fs); } } catch (Exception ex) { ThreadSafeLogger.Log($"[错误] 加载产品 '{productName}' 的配置失败: {ex.Message}"); return null; } } private static bool SaveConfigForProduct(string productName, ProcessConfig config) { try { var safeFolderName = GetSafeFolderName(productName); var productDir = Path.Combine(_productRootPath, safeFolderName); Directory.CreateDirectory(productDir); // 确保文件夹存在 var configPath = Path.Combine(productDir, "config.xml"); XmlSerializer serializer = new XmlSerializer(typeof(ProcessConfig)); using (var fs = new FileStream(configPath, FileMode.Create, FileAccess.Write)) { serializer.Serialize(fs, config); } return true; } catch (Exception ex) { ThreadSafeLogger.Log($"[错误] 保存产品 '{productName}' 的配置失败: {ex.Message}"); return false; } } private static string GetSafeFolderName(string productName) { // 移除所有不适合做文件夹名称的字符 string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); Regex r = new Regex(string.Format("[{0}]", Regex.Escape(invalidChars))); return r.Replace(productName, ""); } #endregion } }