Files
test_demo/MX-PD-盘古 - new/PanGu.DieBonderApp/MainShell/Recipe/Models/RecipeManager.cs
Shi.Ji e31d3560bb 添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
2026-05-18 11:43:09 +08:00

461 lines
15 KiB
C#

using MainShell.Filewritable;
using System;
using System.IO;
using System.Linq;
namespace MainShell.Recipe.Models
{
public class RecipeManager
{
public event EventHandler RecipesChanged;
// 记录上次加载的基板配方名(放在根目录)
private string LastLoadedFile => Path.Combine(Paths.RecipeBasePath, "last_loaded.txt");
public CarrierRecipe CurrentCarrierRecipe { get; private set; }
public SubstrateRecipe CurrentSubstrateRecipe { get; private set; }
public WaferRecipe CurrentWaferRecipe { get; private set; }
public ProcessRecipe CurrentProcessRecipe { get; private set; }
public RecipeManager()
{
var lastLoaded = LoadLastLoadedRecipe();
if (!string.IsNullOrWhiteSpace(lastLoaded))
{
// 构造阶段不主动抛事件,避免初始化期无意义通知
SwitchSubstrateRecipeInternal(lastLoaded, cascade: true, notify: false);
}
}
public void SaveLastLoadedRecipe(string recipeName)
{
var dir = Path.GetDirectoryName(LastLoadedFile);
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
File.WriteAllText(LastLoadedFile, recipeName ?? string.Empty);
}
public string LoadLastLoadedRecipe()
{
if (!File.Exists(LastLoadedFile))
return string.Empty;
return File.ReadAllText(LastLoadedFile).Trim();
}
public void SwitchCarrierRecipe(string carrierRecipeName)
{
SwitchCarrierRecipeInternal(carrierRecipeName, notify: true);
}
public void SwitchSubstrateRecipe(string substrateRecipeName)
{
// 需求:切换基板时自动切换芯片;切换芯片时自动切换工艺
SwitchSubstrateRecipeInternal(substrateRecipeName, cascade: true, notify: true);
}
public void SwitchWaferRecipe(string waferRecipeName)
{
// 需求:切换芯片时自动切换工艺
SwitchWaferRecipeInternal(waferRecipeName, cascade: true, notify: true);
}
public void SwitchProcessRecipe(string processRecipeName)
{
SwitchProcessRecipeInternal(processRecipeName, notify: true);
}
private void SwitchCarrierRecipeInternal(string carrierRecipeName, bool notify)
{
if (string.IsNullOrWhiteSpace(carrierRecipeName))
return;
CurrentCarrierRecipe = CurrentCarrierRecipe ?? new CarrierRecipe();
CurrentCarrierRecipe.RecipeName = carrierRecipeName;
var path = Path.Combine(Paths.CarrierRecipe, carrierRecipeName, CurrentCarrierRecipe.FileName);
CurrentCarrierRecipe.Read(path);
var substrateName = GetFirstSubstrateName(CurrentCarrierRecipe);
if (!string.IsNullOrWhiteSpace(substrateName))
{
// 向下级联,但由最外层统一通知
SwitchSubstrateRecipeInternal(substrateName, cascade: true, notify: false);
}
else
{
ClearSubstrateRecipeInternal(false);
}
if (notify)
RaiseRecipesChanged();
}
private void SwitchSubstrateRecipeInternal(string substrateRecipeName, bool cascade, bool notify)
{
if (string.IsNullOrWhiteSpace(substrateRecipeName))
return;
CurrentSubstrateRecipe = CurrentSubstrateRecipe ?? new SubstrateRecipe();
CurrentSubstrateRecipe.RecipeName = substrateRecipeName;
var path = Path.Combine(Paths.SubstrateRecipe, substrateRecipeName, CurrentSubstrateRecipe.FileName);
CurrentSubstrateRecipe.Read(path);
SaveLastLoadedRecipe(substrateRecipeName);
if (cascade)
{
var waferName = GetFirstWaferName(CurrentSubstrateRecipe);
if (!string.IsNullOrWhiteSpace(waferName))
{
SwitchWaferRecipeInternal(waferName, cascade: true, notify: false);
}
else
{
// 没有关联芯片时,清空下游当前引用,避免残留旧状态
CurrentWaferRecipe = null;
CurrentProcessRecipe = null;
}
}
if (notify)
RaiseRecipesChanged();
}
private void SwitchWaferRecipeInternal(string waferRecipeName, bool cascade, bool notify)
{
if (string.IsNullOrWhiteSpace(waferRecipeName))
return;
CurrentWaferRecipe = CurrentWaferRecipe ?? new WaferRecipe();
CurrentWaferRecipe.RecipeName = waferRecipeName;
var path = Path.Combine(Paths.WaferRecipe, waferRecipeName, CurrentWaferRecipe.FileName);
CurrentWaferRecipe.Read(path);
if (cascade)
{
var processName = CurrentWaferRecipe.ProcessRecipeName;
if (!string.IsNullOrWhiteSpace(processName))
{
SwitchProcessRecipeInternal(processName, notify: false);
}
else
{
CurrentProcessRecipe = null;
}
}
if (notify)
RaiseRecipesChanged();
}
private void SwitchProcessRecipeInternal(string processRecipeName, bool notify)
{
if (string.IsNullOrWhiteSpace(processRecipeName))
return;
CurrentProcessRecipe = CurrentProcessRecipe ?? new ProcessRecipe();
CurrentProcessRecipe.RecipeName = processRecipeName;
var path = Path.Combine(Paths.ProcessRecipe, processRecipeName, CurrentProcessRecipe.FileName);
CurrentProcessRecipe.Read(path);
if (notify)
RaiseRecipesChanged();
}
private static string GetFirstSubstrateName(CarrierRecipe carrierRecipe)
{
if (carrierRecipe == null ||
carrierRecipe.SubstrateSelectInfos == null ||
carrierRecipe.SubstrateSelectInfos.Count == 0)
{
return string.Empty;
}
return carrierRecipe.SubstrateSelectInfos[0].SubstrateName;
}
private static string GetFirstWaferName(SubstrateRecipe substrateRecipe)
{
if (substrateRecipe == null ||
substrateRecipe.WaferSelectInfos == null ||
substrateRecipe.WaferSelectInfos.Count == 0)
{
return string.Empty;
}
var inUse = substrateRecipe.WaferSelectInfos
.FirstOrDefault(x => x != null && x.IsUse && !string.IsNullOrWhiteSpace(x.WaferRecipeName));
if (inUse != null)
return inUse.WaferRecipeName;
var firstValid = substrateRecipe.WaferSelectInfos
.FirstOrDefault(x => x != null && !string.IsNullOrWhiteSpace(x.WaferRecipeName));
return firstValid != null ? firstValid.WaferRecipeName : string.Empty;
}
private void RaiseRecipesChanged()
{
RecipesChanged?.Invoke(this, EventArgs.Empty);
}
public void DeleteCarrierRecipe(string recipeName)
{
DeleteRecipeFolder(Paths.CarrierRecipe, recipeName, out _);
}
public bool DeleteCarrierRecipe(string recipeName, out string error)
{
return DeleteRecipeFolder(Paths.CarrierRecipe, recipeName, out error);
}
public void DeleteSubstrateRecipe(string recipeName)
{
DeleteRecipeFolder(Paths.SubstrateRecipe, recipeName, out _);
}
public bool DeleteSubstrateRecipe(string recipeName, out string error)
{
return DeleteRecipeFolder(Paths.SubstrateRecipe, recipeName, out error);
}
public void DeleteWaferRecipe(string recipeName)
{
DeleteRecipeFolder(Paths.WaferRecipe, recipeName, out _);
}
public bool DeleteWaferRecipe(string recipeName, out string error)
{
return DeleteRecipeFolder(Paths.WaferRecipe, recipeName, out error);
}
public void DeleteProcessRecipe(string recipeName)
{
DeleteRecipeFolder(Paths.ProcessRecipe, recipeName, out _);
}
public bool DeleteProcessRecipe(string recipeName, out string error)
{
return DeleteRecipeFolder(Paths.ProcessRecipe, recipeName, out error);
}
public bool DeleteRecipeFolder(string baseFolder, string recipeName, out string error)
{
error = null;
if (string.IsNullOrWhiteSpace(baseFolder) || string.IsNullOrWhiteSpace(recipeName))
{
error = "配方名称不能为空";
return false;
}
var path = Path.Combine(baseFolder, recipeName);
if (!Directory.Exists(path))
{
error = "配方目录不存在";
return false;
}
try
{
Directory.Delete(path, true);
return true;
}
catch (Exception ex)
{
error = ex.Message;
return false;
}
}
public bool CopyRecipeFolder(string baseFolder, string sourceRecipeName, string targetRecipeName, out string error)
{
error = null;
if (string.IsNullOrWhiteSpace(baseFolder) || string.IsNullOrWhiteSpace(sourceRecipeName) || string.IsNullOrWhiteSpace(targetRecipeName))
{
error = "配方名称不能为空";
return false;
}
if (sourceRecipeName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0 ||
targetRecipeName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
{
error = "名称包含非法字符";
return false;
}
var sourcePath = Path.Combine(baseFolder, sourceRecipeName);
var targetPath = Path.Combine(baseFolder, targetRecipeName);
if (!Directory.Exists(sourcePath))
{
error = "源文件夹不存在";
return false;
}
if (Directory.Exists(targetPath))
{
error = "目标文件夹已存在";
return false;
}
try
{
CopyDirectory(sourcePath, targetPath);
return true;
}
catch (Exception ex)
{
error = ex.Message;
try
{
if (Directory.Exists(targetPath))
{
Directory.Delete(targetPath, true);
}
}
catch
{
}
return false;
}
}
public void ClearCarrierRecipe()
{
ClearCarrierRecipeInternal(true);
}
public void ClearSubstrateRecipe()
{
ClearSubstrateRecipeInternal(true);
}
public void ClearWaferRecipe()
{
ClearWaferRecipeInternal(true);
}
public void ClearProcessRecipe()
{
ClearProcessRecipeInternal(true);
}
private void ClearCarrierRecipeInternal(bool notify)
{
CurrentCarrierRecipe = null;
if (notify)
RaiseRecipesChanged();
}
private void ClearSubstrateRecipeInternal(bool notify)
{
CurrentSubstrateRecipe = null;
CurrentWaferRecipe = null;
CurrentProcessRecipe = null;
SaveLastLoadedRecipe(string.Empty);
if (notify)
RaiseRecipesChanged();
}
private void ClearWaferRecipeInternal(bool notify)
{
CurrentWaferRecipe = null;
CurrentProcessRecipe = null;
if (notify)
RaiseRecipesChanged();
}
private void ClearProcessRecipeInternal(bool notify)
{
CurrentProcessRecipe = null;
if (notify)
RaiseRecipesChanged();
}
private static void CopyDirectory(string sourcePath, string targetPath)
{
Directory.CreateDirectory(targetPath);
foreach (var filePath in Directory.GetFiles(sourcePath))
{
var fileName = Path.GetFileName(filePath);
var targetFilePath = Path.Combine(targetPath, fileName);
File.Copy(filePath, targetFilePath, false);
}
foreach (var directoryPath in Directory.GetDirectories(sourcePath))
{
var directoryName = Path.GetFileName(directoryPath);
var targetDirectoryPath = Path.Combine(targetPath, directoryName);
CopyDirectory(directoryPath, targetDirectoryPath);
}
}
public bool RenameFolder(string baseFolder, string oldName, string newName, out string error)
{
error = null;
if (string.IsNullOrWhiteSpace(oldName) || string.IsNullOrWhiteSpace(newName))
{
error = "名称不能为空";
return false;
}
if (oldName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0 ||
newName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
{
error = "名称包含非法字符";
return false;
}
var src = Path.Combine(baseFolder, oldName);
var dst = Path.Combine(baseFolder, newName);
if (!Directory.Exists(src))
{
error = "源文件夹不存在";
return false;
}
if (Directory.Exists(dst))
{
error = "目标文件夹已存在";
return false;
}
try
{
if (string.Equals(oldName, newName, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(oldName, newName, StringComparison.Ordinal))
{
var temp = Path.Combine(baseFolder, oldName + "_tmp_" + Guid.NewGuid().ToString("N"));
Directory.Move(src, temp);
Directory.Move(temp, dst);
}
else
{
Directory.Move(src, dst);
}
return true;
}
catch (Exception ex)
{
error = ex.Message;
return false;
}
}
}
}