添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,460 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user