using Caliburn.Micro; using DocumentFormat.OpenXml.EMMA; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.OperationCenter; using MECF.Framework.UI.Client.CenterViews.Configs.Roles; using MECF.Framework.UI.Client.CenterViews.Editors.Sequence; using MECF.Framework.UI.Client.ClientBase; using MECF.Framework.UI.Client.RecipeEditorLib.DGExtension.CustomColumn; using MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel; using MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel.Params; using OpenSEMI.ClientBase; using OpenSEMI.ClientBase.Command; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe { public class RecipeComparViewModel : UiViewModelBase { private readonly RoleManager _roleManager = new(); private readonly RecipeType _fileTypes; private readonly bool _isFolderOnly; private readonly bool _isShowRootNode; private FileNode _currentFileNode; private EditMode _editMode; private readonly RecipeProvider _recipeProvider; public ObservableCollection Chambers { get; set; } private RecipeData _currentRecipe; public RecipeData CurrentRecipe { get => _currentRecipe; set { _currentRecipe = value; NotifyOfPropertyChange(); } } private RecipeData _currentRecipe2; public RecipeData CurrentRecipe2 { get => _currentRecipe2; set { _currentRecipe2 = value; NotifyOfPropertyChange(); } } private double[] _scrollviewerPositionOffset; public double[] ScrollviewerPositionOffset2 { get => _scrollviewerPositionOffset; set { _scrollviewerPositionOffset = value; NotifyOfPropertyChange(); } } public int ProcessTypeIndexSelection { get; set; } public RecipeType CurrentProcessType => ProcessTypeFileList[ProcessTypeIndexSelection].ProcessType; public int ChamberTypeIndexSelection { get; set; } public ObservableCollection ChamberType { get; set; } public string CurrentChamberType => ChamberType[ChamberTypeIndexSelection]; public string SelectedChamber { get; set; } public ObservableCollection SelectRecipeNameList { get; set; } = new ObservableCollection(); public FileNode DGSelectRecipeName { get; set; } public List ProcessTypeFileList { get; set; } public RecipeComparViewModel() { _fileTypes = RecipeType.Process | RecipeType.Routine; _isFolderOnly = false; _isShowRootNode = false; _recipeProvider = new RecipeProvider(); var chamberType = QueryDataClient.Instance.Service.GetConfig("System.Recipe.SupportedChamberType"); if (chamberType == null) { ChamberType = new ObservableCollection() { "Default" }; } else { ChamberType = new ObservableCollection(((string)(chamberType)).Split(',')); } //_loadRecipeHelp = new LoadRecipeHelp("PM1"); } protected override void OnInitialize() { base.OnInitialize(); _roleManager.Initialize(); BuildFileTree(_isShowRootNode, _isFolderOnly, _fileTypes); } protected override void OnActivate() { UpdateRecipeFormat(); // 根据角色权限设置判断是否显示按钮。 //IsShowCellAccessPermEditButton = GetCapeModeButtonPerm(); //NotifyOfPropertyChange(nameof(IsShowCellAccessPermEditButton)); //UpdateView(); base.OnActivate(); } private void BuildFileTree(bool isShowRootNode, bool isFolderOnly, RecipeType fileType) { var recipeProvider = new RecipeProvider(); var scProcessType = QueryDataClient.Instance.Service.GetConfig("System.Recipe.SupportedProcessType").ToString(); var supportedRecipeType = new List(new[] { RecipeType.Process, RecipeType.Routine }); if (!string.IsNullOrEmpty(scProcessType)) { supportedRecipeType.Clear(); if (fileType.HasFlag(RecipeType.Process) && scProcessType.Contains(RecipeType.Process.ToString())) supportedRecipeType.Add(RecipeType.Process); if (fileType.HasFlag(RecipeType.Routine) && scProcessType.Contains(RecipeType.Routine.ToString())) supportedRecipeType.Add(RecipeType.Routine); } var processTypeFileList = new List(); for (var i = 0; i < supportedRecipeType.Count; i++) { var type = new ProcessTypeFileItem { ProcessType = supportedRecipeType[i] }; var prefix = $"Sic\\{supportedRecipeType[i]}"; var recipes = recipeProvider.GetXmlRecipeList(prefix); type.FileListByProcessType = RecipeSequenceTreeBuilder.BuildFileNode(prefix, "", false, recipes, isFolderOnly, isShowRootNode)[0].Files; processTypeFileList.Add(type); } this.ProcessTypeFileList = processTypeFileList; } public async void TreeSelectChanged(FileNode node) { //if (IsChanged) //{ // var selection = DialogBox.ShowDialog(DialogButton.Yes | DialogButton.No, // DialogType.CONFIRM, // $"Recipe {CurrentRecipe.Name} is changed, do you want to save it?"); // if (selection == DialogButton.Yes) // { // CurrentRecipe.Revisor = BaseApp.Instance.UserContext.LoginName; // CurrentRecipe.ReviseTime = DateTime.Now; // Save(CurrentRecipe, false); // } //} //CurrentFileNode = node; //if (node != null && node.IsFile) //{ // await LoadRecipe(node.PrefixPath, node.FullPath); //} //else //{ // ClearData(); // //_editMode = EditMode.None; //} } private void ClearData() { //_editMode = EditMode.None; ClearData(); } private async Task LoadRecipe(string prefixPath, string recipeName) { //IsLoading = true; CurrentRecipe.Clear(); CurrentRecipe.Steps.Save(); // 重置为已保存状态 CurrentRecipe2.Clear(); CurrentRecipe2.Steps.Save(); // 重置为已保存状态 //ErrorsCount = 0; //SelectRecipeNameList string recipeName1 = SelectRecipeNameList[0].Name; string recipeName2 = SelectRecipeNameList[1].Name; var recipeContent1 = _recipeProvider.ReadRecipeFile(prefixPath, recipeName1); var recipeContent2 = _recipeProvider.ReadRecipeFile(prefixPath, recipeName2); if (string.IsNullOrEmpty(recipeContent1)) { MessageBox.Show($"{prefixPath}\\{recipeName} is empty, please confirm the file is valid.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } await CurrentRecipe.LoadFile(prefixPath, recipeName1, recipeContent1, SelectedChamber, GetLoadingDispatcher()); await CurrentRecipe2.LoadFile(prefixPath, recipeName2, recipeContent2, SelectedChamber, GetLoadingDispatcher()); //_editMode = EditMode.Normal; //IsLoading = false; } //private async Task LoadRecipe(string prefixPath, string recipeName) //{ // //IsLoading = true; // CurrentRecipe.Clear(); // CurrentRecipe.Steps.Save(); // 重置为已保存状态 // CurrentRecipe2.Clear(); // CurrentRecipe2.Steps.Save(); // 重置为已保存状态 // //ErrorsCount = 0; // //SelectRecipeNameList // var recipeContent = _recipeProvider.ReadRecipeFile(prefixPath, recipeName); // if (string.IsNullOrEmpty(recipeContent)) // { // MessageBox.Show($"{prefixPath}\\{recipeName} is empty, please confirm the file is valid.", // "Error", // MessageBoxButton.OK, MessageBoxImage.Error); // return; // } // await CurrentRecipe.LoadFile(prefixPath, recipeName, recipeContent, SelectedChamber, // GetLoadingDispatcher()); // await CurrentRecipe2.LoadFile(prefixPath, recipeName, recipeContent, SelectedChamber, // GetLoadingDispatcher()); // //_editMode = EditMode.Normal; // //IsLoading = false; //} private static Dispatcher GetLoadingDispatcher() { // 判断Step呈现方式 var isCascadeLoading = (bool)QueryDataClient.Instance.Service.GetConfig("System.RecipeCascadeLoading"); var dispatcher = isCascadeLoading ? Dispatcher.CurrentDispatcher : null; return dispatcher; } public void UpdateRecipeFormat() { var chamber = QueryDataClient.Instance.Service.GetConfig("System.Recipe.ChamberModules"); if (chamber == null) { chamber = "PM1"; } Chambers = new ObservableCollection(((string)chamber).Split(',')); if (Chambers.Count > 1) { for (var i = 0; i < Chambers.Count; i++) { var isPmInstall = (bool)QueryDataClient.Instance.Service.GetConfig( $"System.SetUp.Is{Chambers[i].ToString()}Installed"); { if (!isPmInstall) { Chambers.RemoveAt(i); } } } } if (Chambers.Count == 0) { Chambers = new ObservableCollection(new string[] { "PM1" }); } SelectedChamber = Chambers[0]; #region Create RecipeData var recipeData = new RecipeData(CurrentProcessType); recipeData.BuildFormat($"{CurrentChamberType}\\{CurrentProcessType}", SelectedChamber, BaseApp.Instance.UserContext.RoleName); //得到当前登录的RoleItem var role = _roleManager.GetRoleByName(BaseApp.Instance.UserContext.RoleName); recipeData.ReloadRolePermission(role); var recipeData2 = new RecipeData(CurrentProcessType); recipeData2.BuildFormat($"{CurrentChamberType}\\{CurrentProcessType}", SelectedChamber, BaseApp.Instance.UserContext.RoleName); //得到当前登录的RoleItem var role2 = _roleManager.GetRoleByName(BaseApp.Instance.UserContext.RoleName); recipeData2.ReloadRolePermission(role); CurrentRecipe = recipeData; CurrentRecipe2 = recipeData2; #endregion } //public void TreeSelectChanged(FileNode file) //{ // _currentFileNode = file; //} //public void TreeMouseDoubleClick(FileNode file) //{ // DGAdd(file); //} //public void AddRecipeToCompar() //{ // DGAdd(_currentFileNode); //} private void DGAdd(FileNode file) { if (SelectRecipeNameList == null) SelectRecipeNameList = new ObservableCollection(); SelectRecipeNameList.Add(file); } //public void RemoveSelectRecipe() //{ // var v = DGSelectRecipeName; // SelectRecipeNameList.Remove(DGSelectRecipeName); //} //public void ClearSelectRecipe() //{ // SelectRecipeNameList.Clear(); //} public async void ComperSelectRecipe() { SelectRecipeNameList.Clear(); foreach (var ProcessTypeFile in ProcessTypeFileList) { foreach (var item in ProcessTypeFile.FileListByProcessType) { if (item.IsSelected) SelectRecipeNameList.Add(item); } } await LoadRecipe(SelectRecipeNameList[0].PrefixPath, SelectRecipeNameList[0].Name); Start(CurrentRecipe, CurrentRecipe2); } public void Start(RecipeData recipeData1, RecipeData recipeData2) { RecipeStep v = CurrentRecipe.Steps[3]; int stepsCount = recipeData1.Steps.Count <= recipeData2.Steps.Count ? recipeData1.Steps.Count : recipeData2.Steps.Count; for (int i = 0; i < stepsCount; i++) { RecipeStep step1 = recipeData1.Steps[i]; RecipeStep step2 = recipeData2.Steps[i]; for (int j = 0; j < step1.Count; j++) { object obj1= GetValue(step1[j]); object obj2 = GetValue(step2[j]); if ( !(Comparer.Default.Compare(obj1, obj2) == 0) ) { step1[j].Highlight(); step2[j].Highlight(); } } } } private object GetValue(Param param) { object Value = null; if (param is IValueParam vp) Value = vp.GetValue(); return Value; } } }