Browse Source

add ProcessJobInfo
add processData与 PJ_data信息关联

git-svn-id: http://10.4.3.168:50001/svn/Furnace@50 dbcde07d-dcf5-c148-8a84-ac3097b7778e

Jiangjinyuan 2 months ago
parent
commit
2c4db59606
23 changed files with 1254 additions and 83 deletions
  1. 1 0
      FrameworkLocal/Common/DBCore/DatabaseTable.cs
  2. 8 0
      FrameworkLocal/Common/DBCore/ProcessDataRecorder.cs
  3. 6 6
      FrameworkLocal/RTEquipmentLibrary/LogicUnits/PMs/PM.cs
  4. 348 0
      FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessDetailV2View.xaml
  5. 28 0
      FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessDetailV2View.xaml.cs
  6. 475 0
      FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessDetailV2ViewModel.cs
  7. 17 30
      FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessHistoryTwoView.xaml
  8. 29 7
      FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessHistoryTwoViewModel.cs
  9. 89 0
      FrameworkLocal/UIClient/CenterViews/Editors/Recipe/RecipeDataBase.cs
  10. 8 0
      FrameworkLocal/UIClient/UIClient.csproj
  11. 15 0
      FrameworkLocal/UICore/Control/BoatElevatorMap.xaml
  12. 157 0
      FrameworkLocal/UICore/Control/BoatElevatorMap.xaml.cs
  13. 7 0
      FrameworkLocal/UICore/UICore.csproj
  14. 1 0
      Furnace/FurnaceRT/Config/DBModel.sql
  15. 3 3
      Furnace/FurnaceRT/Config/System.sccfg
  16. 5 1
      Furnace/FurnaceRT/Equipments/Jobs/AutoTransfer.cs
  17. 6 1
      Furnace/FurnaceRT/Equipments/PMs/PMModule.cs
  18. 4 1
      Furnace/FurnaceRT/Equipments/PMs/RecipeDBCallback.cs
  19. 32 27
      Furnace/FurnaceRT/Equipments/PMs/RecipeExecutions/Process.cs
  20. 6 2
      Furnace/FurnaceRT/Equipments/Schedulers/SchedulerDBCallback.cs
  21. 4 0
      Furnace/FurnaceRT/Equipments/Systems/EquipmentManager_FA.cs
  22. 2 2
      Furnace/FurnaceUI/Views/Recipes/RecipeLayoutEditView.xaml
  23. 3 3
      Furnace/FurnaceUI/Views/Recipes/RecipeLayoutEditViewModel.cs

+ 1 - 0
FrameworkLocal/Common/DBCore/DatabaseTable.cs

@@ -116,6 +116,7 @@ namespace MECF.Framework.Common.DBCore
             DB.CreateTableColumn("process_data", new Dictionary<string, Type>()
             {
                 {"recipe_setting_time", typeof(float) },
+                {"pj_id", typeof(string) },
             });
             DB.CreateTableColumn("stats_data", new Dictionary<string, Type>()
             {

+ 8 - 0
FrameworkLocal/Common/DBCore/ProcessDataRecorder.cs

@@ -36,7 +36,15 @@ namespace MECF.Framework.Common.DBCore
 
             DB.Insert(sql);
         }
+        public static void UpdatePjId(string guid, string pjId)
+        {
+            string sql = string.Format(
+                "UPDATE \"process_data\" SET \"pj_id\"='{0}' WHERE \"guid\"='{1}';",
+                pjId,
+                guid);
 
+            DB.Insert(sql);
+        }
         public static void UpdateStatus(string guid, string status)
         {
             string sql = string.Format(

+ 6 - 6
FrameworkLocal/RTEquipmentLibrary/LogicUnits/PMs/PM.cs

@@ -21,7 +21,7 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs
     {
         //如果true,robot采用extend, retract指令
         //如果false,robot采用pick,place指令
-        public  bool IsActiveHandoff { get; set; }
+        public bool IsActiveHandoff { get; set; }
 
         //如果true,robot调用收尾PostTransfer
         public bool IsNeedPostTransfer { get; set; }
@@ -32,7 +32,7 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs
         public virtual bool IsProcessing { get; }
 
         public virtual bool IsInstalled { get; set; }
-        public virtual double ForelinePressure { get; set; } 
+        public virtual double ForelinePressure { get; set; }
 
         protected readonly string _statNameWaferProcessed;
         protected readonly string _statNameWaferProcessedSincePreviousClean;
@@ -102,7 +102,7 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs
             return false;
         }
 
-        public virtual bool CheckEnablePump(out  string reason)
+        public virtual bool CheckEnablePump(out string reason)
         {
             reason = "Undefined";
             return false;
@@ -143,7 +143,7 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs
         {
 
         }
- 
+
         public virtual void StartProcess(string recipeName, string recipeContent, bool isClean)
         {
 
@@ -156,7 +156,7 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs
 
         public virtual void OnProcessStart(string guid, string recipeName, bool isClean)
         {
-            ProcessDataRecorder.Start(guid, recipeName, 
+            ProcessDataRecorder.Start(guid, recipeName,
                 WaferManager.Instance.GetWafer(ModuleHelper.Converter(Module), 0).InnerId.ToString(), Module);
 
             if (!isClean)
@@ -206,7 +206,7 @@ namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.PMs
 
             LOG.Write($"{Module} end run recipe {recipeName}, guid {guid}, clean: {isClean}, result {isSucceed}");
 
-            ProcessDataRecorder.End(guid, "Abort" );
+            ProcessDataRecorder.End(guid, "Abort");
 
         }
         public virtual bool SetThrottleValvePosition(int slowPumpPosition, out string reason)

+ 348 - 0
FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessDetailV2View.xaml

@@ -0,0 +1,348 @@
+<UserControl x:Class="MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory.ProcessDetailV2View"
+
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:parts="clr-namespace:Aitex.Core.UI.Control;assembly=MECF.Framework.UI.Core" 
+             mc:Ignorable="d" 
+              Height="768" Width="1024" Background="#E5E5E5">
+    <UserControl.Resources>
+        <Style TargetType="Path" x:Key="TriangleStyle">
+            <Setter Property="Fill" Value="#ccc"/>
+            <Setter Property="Data" Value="M 0,0 L 10,0 L 5,-8 Z"/>
+            <Setter Property="HorizontalAlignment" Value="Right"/>
+        </Style>
+        <SolidColorBrush x:Key="BaseColor_White" Color="White"/>
+        <SolidColorBrush x:Key="BaseColor_White_Gray_1" Color="#E5E5E5"/>
+        <SolidColorBrush x:Key="BaseColor_BorderBrush" Color="#ccc"/>
+        <SolidColorBrush x:Key="BaseColor_Green" Color="Green"/>
+        <SolidColorBrush x:Key="BaseColor_Red" Color="Red"/>
+        <SolidColorBrush x:Key="BaseColor_Yellow" Color="Yellow"/>
+    </UserControl.Resources>
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="70"></RowDefinition>
+            <RowDefinition Height="auto"></RowDefinition>
+            <RowDefinition Height="*"></RowDefinition>
+        </Grid.RowDefinitions>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="auto"></ColumnDefinition>
+            <ColumnDefinition ></ColumnDefinition>
+        </Grid.ColumnDefinitions>
+
+        <Border Margin="5,0,0,0"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1" HorizontalAlignment="Center"  Width="200"  Height="60" >
+            <StackPanel Orientation="Vertical">
+                <TextBlock  Style="{StaticResource TextBlock_Title}" Text="No./Total" TextAlignment="Center"></TextBlock>
+                <TextBlock  Background="White" Height="50" TextAlignment="Center" FontSize="16"  Padding="5">
+                    <Run Text="{Binding SelectItemIndex}"/> <Run Text="/"/> <Run Text="{Binding TableCount}"/>
+                </TextBlock>
+            </StackPanel>
+        </Border>
+        <Border Margin="5,0,0,0"  Grid.Row="1" BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1">
+            <Button  Margin="10,25,10,5" Height="40" Content="File Info"></Button>
+        </Border>
+        <Border Margin="5,0,0,0"   Grid.Row="2" BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1">
+
+            <Canvas>
+                <parts:BoatElevatorMap BoatWafers="{Binding BoatMapWafers}" Margin="30,-35,0,0"  Height="500" Width="158">
+                </parts:BoatElevatorMap>
+                <Border BorderBrush="LightGray" BorderThickness="2,2,0,0" Canvas.Left="14" Canvas.Top="90" SnapsToDevicePixels="True"  Visibility="{Binding IstBoatMapLogicalVisibility}">
+                    <Border BorderBrush="LightGray" BorderThickness="0,0,2,2" Background="Gray" SnapsToDevicePixels="True" >
+                        <Grid Width="92" Height="500" Margin="4">
+                            <Grid.RowDefinitions>
+                                <RowDefinition/>
+                                <RowDefinition/>
+                                <RowDefinition Height="3"/>
+                                <RowDefinition/>
+                                <RowDefinition/>
+                                <RowDefinition Height="3"/>
+                                <RowDefinition/>
+                                <RowDefinition/>
+                                <RowDefinition Height="3"/>
+                                <RowDefinition/>
+                                <RowDefinition/>
+                                <RowDefinition Height="3"/>
+                                <RowDefinition/>
+                                <RowDefinition/>
+                            </Grid.RowDefinitions>
+                            <TextBlock Text="SD"/>
+                            <WrapPanel Grid.Row="1">
+                                <TextBlock   Foreground="{StaticResource BaseColor_White}"  FontSize="18" TextAlignment="Center"  Width="60" Text="{Binding UpperSDNum}"></TextBlock>
+                                <TextBlock Text="Num"/>
+                            </WrapPanel>
+                            <Line Grid.Row="2" X1="-4" Y1="0" X2="96" Y2="0" Margin="0,0,-4,0" StrokeThickness="2" Stroke="LightGray"/>
+
+                            <TextBlock Grid.Row="3" Text="Product"/>
+                            <WrapPanel Grid.Row="4">
+                                <TextBlock Foreground="{StaticResource BaseColor_White}"  FontSize="18" TextAlignment="Center" Width="60" Text="{Binding ProductNum}"></TextBlock>
+                                <TextBlock Text="Num"/>
+                            </WrapPanel>
+                            <Line Grid.Row="5" X1="-4" Y1="0" X2="96" Y2="0" Margin="0,0,-4,0" StrokeThickness="2" Stroke="LightGray"/>
+
+                            <TextBlock Grid.Row="6" Text="Monitor1"/>
+                            <WrapPanel Grid.Row="7">
+                                <TextBlock  Foreground="{StaticResource BaseColor_White}"  FontSize="18" TextAlignment="Center"  Width="60" Text="{Binding MonitorNum1}"></TextBlock>
+
+                                <TextBlock Text="Num"/>
+                            </WrapPanel>
+
+                            <Line Grid.Row="8" X1="-4" Y1="0" X2="96" Y2="0" Margin="0,0,-4,0" StrokeThickness="2" Stroke="LightGray"/>
+
+                            <TextBlock Grid.Row="9" Text="Monitor2"/>
+                            <WrapPanel Grid.Row="10">
+                                <TextBlock  Foreground="{StaticResource BaseColor_White}"  FontSize="18" TextAlignment="Center"  Width="60" Text="{Binding MonitorNum2}"></TextBlock>
+                                <TextBlock Text="Num"/>
+                            </WrapPanel>
+
+                            <Line Grid.Row="11" X1="-4" Y1="0" X2="96" Y2="0" Margin="0,0,-4,0" StrokeThickness="2" Stroke="LightGray"/>
+
+                            <TextBlock Grid.Row="12" Text="ED"/>
+                            <WrapPanel Grid.Row="13">
+                                <TextBlock  Foreground="{StaticResource BaseColor_White}"  FontSize="18" TextAlignment="Center"  Width="60" Text="{Binding LowerSDNum}"></TextBlock>
+                                <TextBlock Text="Num"/>
+                            </WrapPanel>
+                        </Grid>
+                    </Border>
+                </Border>
+
+            </Canvas>
+
+        </Border>
+
+        <Border Width="810" Grid.Column="1"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1" HorizontalAlignment="Center"   Height="60" >
+            <StackPanel Orientation="Horizontal">
+                <Border Width="200" HorizontalAlignment="Left">
+                    <StackPanel Orientation="Vertical">
+                        <TextBlock  Style="{StaticResource TextBlock_Title}" Text="Process Start Time" TextAlignment="Left"></TextBlock>
+                        <TextBlock  Background="{StaticResource BaseColor_White}" Height="50" TextAlignment="Center" FontSize="16" Text="{Binding ViewData.ProcessStartTime}" Padding="5"></TextBlock>
+                    </StackPanel>
+                </Border>
+                <Border Width="200" HorizontalAlignment="Left"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1,0,0,1">
+                    <StackPanel Orientation="Vertical">
+                        <TextBlock  Style="{StaticResource TextBlock_Title}" Text="Process End Time" TextAlignment="Left"></TextBlock>
+                        <TextBlock  Background="{StaticResource BaseColor_White}" Height="50" TextAlignment="Center" FontSize="16" Text="{Binding ViewData.ProcessEndTime}" Padding="5"></TextBlock>
+                    </StackPanel>
+                </Border>
+                <Border Width="200" HorizontalAlignment="Left"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1,0,0,1">
+                    <StackPanel Orientation="Vertical">
+                        <TextBlock  Style="{StaticResource TextBlock_Title}" Text="Process End Result" TextAlignment="Left"></TextBlock>
+                        <TextBlock  Height="50" TextAlignment="Center" FontSize="16"  Text="{Binding ViewData.ProcessEndResult}" Padding="5">
+
+                            <TextBlock.Style>
+                                <Style TargetType="TextBlock">
+                                    <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                    <Style.Triggers>
+                                        <DataTrigger Binding="{Binding ViewData.ProcessEndResult}" Value="Recipe Abort">
+                                            <Setter Property="Background" Value="{StaticResource BaseColor_Yellow}"/>
+                                        </DataTrigger>
+                                        <DataTrigger Binding="{Binding ViewData.ProcessEndResult}" Value="NONE">
+                                            <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                        </DataTrigger>
+                                        <DataTrigger Binding="{Binding ViewData.ProcessEndResult}" Value="NORMAL END">
+                                            <Setter Property="Background" Value="{StaticResource BaseColor_Green}"/>
+                                        </DataTrigger>
+                                    </Style.Triggers>
+                                </Style>
+                            </TextBlock.Style>
+                        </TextBlock>
+                    </StackPanel>
+                </Border>
+                <Border Width="200" HorizontalAlignment="Left"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1,0,0,1">
+                    <StackPanel Orientation="Vertical">
+                        <TextBlock  Style="{StaticResource TextBlock_Title}" Text="Process Recipe" TextAlignment="Left"></TextBlock>
+                        <TextBlock  Background="White" Height="50" TextAlignment="Center" FontSize="16" Text="{Binding PJInfo.RecipeName}" Padding="5"></TextBlock>
+                    </StackPanel>
+                </Border>
+            </StackPanel>
+
+        </Border>
+
+        <Border Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="1"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1" >
+            <Border Width="810" HorizontalAlignment="Left">
+                <StackPanel Orientation="Vertical" >
+                    <TextBlock  Style="{StaticResource TextBlock_Title}" Text="CJobID" TextAlignment="Left"></TextBlock>
+                    <TextBlock  Background="White" Height="50" TextAlignment="Center"  FontSize="16" Text="{Binding PJInfo.LayoutName}" Padding="15"></TextBlock>
+                </StackPanel>
+            </Border>
+
+        </Border>
+        <Border Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="2"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1" >
+            <Grid>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition></RowDefinition>
+                </Grid.RowDefinitions>
+                <StackPanel Orientation="Horizontal">
+                    <Border Width="220" HorizontalAlignment="Left">
+                        <StackPanel Orientation="Vertical">
+                            <TextBlock  Style="{StaticResource TextBlock_Title}" Text="PJob Start Time" TextAlignment="Left"></TextBlock>
+                            <TextBlock  Background="White" Height="50" TextAlignment="Center" FontSize="16" Text="{Binding ViewData.PJobStartTime}" Padding="15"></TextBlock>
+                        </StackPanel>
+                    </Border>
+                    <Border Width="365" HorizontalAlignment="Left"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1,0,0,1">
+
+                    </Border>
+
+                    <Border Width="220" HorizontalAlignment="Left"  BorderBrush="{StaticResource BaseColor_BorderBrush}" BorderThickness="1,0,0,1">
+                        <StackPanel Orientation="Vertical">
+                            <TextBlock  Style="{StaticResource TextBlock_Title}" Text="PJob End Time" TextAlignment="Left"></TextBlock>
+                            <TextBlock  Background="White" Height="50" TextAlignment="Center" FontSize="16" Text="{Binding ViewData.PJobEndTime}" Padding="15"></TextBlock>
+                        </StackPanel>
+                    </Border>
+                </StackPanel>
+                <Border  Grid.Row="1"    BorderThickness="1">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition></ColumnDefinition>
+                            <ColumnDefinition ></ColumnDefinition>
+                        </Grid.ColumnDefinitions>
+                        <Border Background="#ccc" Grid.ColumnSpan="2" Margin="0,0,97,0" >
+                            <StackPanel  Height="30" Orientation="Horizontal"  HorizontalAlignment="Center">
+                                <TextBlock Padding="8" TextAlignment="Center" Width="140" Text="SETTING UP">
+                                    <TextBlock.Style>
+                                        <Style TargetType="TextBlock">
+                                            <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                            <Style.Triggers>
+                                                <DataTrigger Binding="{Binding ViewData.IsSettingUp}" Value="True">
+                                                    <Setter Property="Background" Value="{StaticResource BaseColor_Green}"/>
+                                                </DataTrigger>
+                                                <DataTrigger Binding="{Binding ViewData.IsSettingUp}" Value="False">
+                                                    <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                                </DataTrigger>
+                                            </Style.Triggers>
+                                        </Style>
+                                    </TextBlock.Style>
+
+                                </TextBlock>
+                                <TextBlock Padding="8" TextAlignment="Center" Width="140" Margin="10,0,10,0"  Text="PROCESSING">
+                                    <TextBlock.Style>
+                                        <Style TargetType="TextBlock">
+                                            <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                            <Style.Triggers>
+                                                <DataTrigger Binding="{Binding ViewData.IsProcessing}" Value="True">
+                                                    <Setter Property="Background" Value="{StaticResource BaseColor_Green}"/>
+                                                </DataTrigger>
+                                                <DataTrigger Binding="{Binding ViewData.IsProcessing}" Value="False">
+                                                    <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                                </DataTrigger>
+                                            </Style.Triggers>
+                                        </Style>
+                                    </TextBlock.Style>
+                                </TextBlock>
+                                <TextBlock  Padding="8"  TextAlignment="Center" Width="140"  Text="PROCESS COMPLETE">
+                                    <TextBlock.Style>
+                                        <Style TargetType="TextBlock">
+                                            <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                            <Style.Triggers>
+                                                <DataTrigger Binding="{Binding ViewData.IsProcessComplete}" Value="True">
+                                                    <Setter Property="Background" Value="{StaticResource BaseColor_Green}"/>
+                                                </DataTrigger>
+                                                <DataTrigger Binding="{Binding ViewData.IsProcessComplete}" Value="False">
+                                                    <Setter Property="Background" Value="{StaticResource BaseColor_White_Gray_1}"/>
+                                                </DataTrigger>
+                                            </Style.Triggers>
+                                        </Style>
+                                    </TextBlock.Style>
+                                </TextBlock>
+                            </StackPanel>
+                        </Border>
+                        <Path Grid.Column="1" Style="{StaticResource TriangleStyle}" Stretch="Fill"  Width="98"   Height="100" Margin="0,2,-101,-2">
+                            <Path.RenderTransform>
+                                <TransformGroup>
+                                    <ScaleTransform/>
+                                    <SkewTransform/>
+                                    <RotateTransform Angle="90"/>
+                                    <TranslateTransform/>
+                                </TransformGroup>
+                            </Path.RenderTransform>
+                        </Path>
+                    </Grid>
+
+                </Border>
+                <Border Grid.Row="2"  BorderThickness="1"  >
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition></ColumnDefinition>
+                            <ColumnDefinition></ColumnDefinition>
+                        </Grid.ColumnDefinitions>
+                        <Grid.RowDefinitions>
+                            <RowDefinition></RowDefinition>
+                            <RowDefinition Height="auto"></RowDefinition>
+                        </Grid.RowDefinitions>
+                        <Button
+                            Background="{StaticResource BaseColor_White_Gray_1}"
+            Grid.RowSpan="2"
+            HorizontalContentAlignment="Stretch"
+            VerticalContentAlignment="Stretch"
+            >
+                            <ContentControl>
+                                <Grid>
+                                    <Grid.RowDefinitions>
+                                        <RowDefinition Height="auto"/>
+                                        <RowDefinition Height="auto"/>
+                                        <RowDefinition/>
+                                    </Grid.RowDefinitions>
+                                    <TextBlock Style="{StaticResource TextBlock_Title}" Text="Process Info"></TextBlock>
+                                    <StackPanel Grid.Row="1" HorizontalAlignment="Right">
+                                        <TextBlock Style="{StaticResource TextBlock_Title}" Text="Added film Thinckess"></TextBlock>
+                                        <StackPanel Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal">
+                                            <TextBlock Background="White" Height="30" Width="150" FontSize="17" Padding="5"   Style="{StaticResource TextBlock_Title}" Text="--"></TextBlock>
+                                            <TextBlock Height="30" FontSize="17" Padding="5"   Style="{StaticResource TextBlock_Title}" Text="(Å)"></TextBlock>
+                                        </StackPanel>
+                                    </StackPanel>
+                                </Grid>
+                            </ContentControl>
+                        </Button>
+                        <Button Background="{StaticResource BaseColor_White_Gray_1}" Grid.Column="1" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
+                            <ContentControl>
+                                <Grid>
+                                    <Grid.RowDefinitions>
+                                        <RowDefinition Height="auto"/>
+                                        <RowDefinition Height="auto"/>
+                                        <RowDefinition/>
+                                    </Grid.RowDefinitions>
+                                    <TextBlock Style="{StaticResource TextBlock_Title}" Text="PJob Info" Height="30"></TextBlock>
+                                    <StackPanel Grid.Row="1" HorizontalAlignment="Left">
+                                        <TextBlock Style="{StaticResource TextBlock_Title}" Text="CarrierId"></TextBlock>
+
+                                        <ListBox  Grid.Row="1" ItemsSource="{Binding PDataList}" Margin="10">
+                                            <ListBox.ItemTemplate>
+                                                <DataTemplate>
+                                                    <StackPanel Orientation="Vertical">
+                                                        <TextBlock Text="{Binding No}" TextAlignment="Center" Height="25"></TextBlock>
+                                                        <TextBox Text="{Binding Name}" Width="100" Height="30" VerticalContentAlignment="Center" HorizontalContentAlignment="Center">
+                                                        </TextBox>
+                                                    </StackPanel>
+                                                </DataTemplate>
+                                            </ListBox.ItemTemplate>
+                                        </ListBox>
+                                    </StackPanel>
+                                </Grid>
+                            </ContentControl>
+                        </Button>
+                        <Border Grid.Column="1" Grid.Row="1">
+                            <StackPanel Orientation="Horizontal">
+                                <StackPanel Orientation="Vertical">
+                                    <Button Content="VP" Width="200" Height="80"></Button>
+                                    <Button Content="PMC Trace Logging"   Width="200" Height="80"></Button>
+                                </StackPanel>
+                                <StackPanel Orientation="Vertical">
+                                    <Button Content="Event Logging"    Width="200" Height="80"></Button>
+                                    <Button Content="Alarm Information" Width="200" Height="80"></Button>
+                                </StackPanel>
+                            </StackPanel>
+                        </Border>
+                    </Grid>
+
+                </Border>
+            </Grid>
+
+
+
+        </Border>
+
+
+    </Grid>
+</UserControl>

+ 28 - 0
FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessDetailV2View.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
+{
+    /// <summary>
+    /// ProcessDetailV2View.xaml 的交互逻辑
+    /// </summary>
+    public partial class ProcessDetailV2View : UserControl
+    {
+        public ProcessDetailV2View()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 475 - 0
FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessDetailV2ViewModel.cs

@@ -0,0 +1,475 @@
+using Aitex.Core.UI.Control;
+using Aitex.Core.Util;
+using Caliburn.Micro.Core;
+using DocumentFormat.OpenXml.Drawing;
+using DocumentFormat.OpenXml.Drawing.Diagrams;
+using MECF.Framework.Common.DataCenter;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.Utilities;
+using MECF.Framework.UI.Client.CenterViews.Editors.Recipe;
+using MECF.Framework.UI.Client.ClientBase;
+using SciChart.Core.Extensions;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics.Eventing.Reader;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
+{
+    public class ProcessDetailV2ViewModel : ModuleUiViewModelBase
+    {
+        #region 
+        [Subscription("Rt.Status")]
+        public string RtStatus { get; set; }
+        [Subscription("PM1.Status")]
+        public string PM1Status { get; set; }
+
+        private int _upperSDNum = 0;
+
+        public int UpperSDNum
+        {
+            get => _upperSDNum;
+            set
+            {
+                _upperSDNum = value;
+                NotifyOfPropertyChange(nameof(UpperSDNum));
+            }
+        }
+
+        private int _productNum = 0;
+
+        public int ProductNum
+        {
+            get => _productNum;
+            set
+            {
+                _productNum = value;
+                NotifyOfPropertyChange(nameof(ProductNum));
+            }
+        }
+
+        private int _monitorNum1 = 0;
+
+        public int MonitorNum1
+        {
+            get => _monitorNum1;
+            set
+            {
+                _monitorNum1 = value;
+                NotifyOfPropertyChange(nameof(MonitorNum1));
+            }
+        }
+
+        private int _monitorNum2 = 0;
+
+        public int MonitorNum2
+        {
+            get => _monitorNum2;
+            set
+            {
+                _monitorNum2 = value;
+                NotifyOfPropertyChange(nameof(MonitorNum2));
+            }
+        }
+
+        private int _lowerSDNum = 0;
+
+        public int LowerSDNum
+        {
+            get => _lowerSDNum;
+            set
+            {
+                _lowerSDNum = value;
+                NotifyOfPropertyChange(nameof(LowerSDNum));
+            }
+        }
+        private int _selectItemIndex = 0;
+
+        public int SelectItemIndex
+        {
+            get => _selectItemIndex;
+            set
+            {
+                _selectItemIndex = value;
+                NotifyOfPropertyChange(nameof(SelectItemIndex));
+            }
+        }
+        private int _tableCount = 0;
+
+        public int TableCount
+        {
+            get => _tableCount;
+            set
+            {
+                _tableCount = value;
+                NotifyOfPropertyChange(nameof(TableCount));
+            }
+        }
+        private List<string> _boatMapWafers = new List<string>();
+        public List<string> BoatMapWafers
+        {
+            get => _boatMapWafers;
+            set
+            {
+                _boatMapWafers = value;
+                NotifyOfPropertyChange(nameof(BoatMapWafers));
+            }
+        }
+
+        private ProcessDetailV2ViewData _viewData;
+        public ProcessDetailV2ViewData ViewData
+        {
+            get => _viewData;
+            set
+            {
+                _viewData = value;
+                NotifyOfPropertyChange(nameof(ViewData));
+            }
+        }
+
+        private RecipeDataBase _layoutRecipe = new RecipeDataBase();
+
+        public RecipeDataBase LayoutRecipe
+        {
+            get { return _layoutRecipe; }
+            set { _layoutRecipe = value; this.NotifyOfPropertyChange(nameof(LayoutRecipe)); }
+        }
+        private RecipeDataBase _processRecipe = new RecipeDataBase();
+
+        public RecipeDataBase ProcessRecipe
+        {
+            get { return _processRecipe; }
+            set { _processRecipe = value; this.NotifyOfPropertyChange(nameof(ProcessRecipe)); }
+        }
+        private ProcessHistoryLot _pJInfo = new ProcessHistoryLot();
+
+        public ProcessHistoryLot PJInfo
+        {
+            get { return _pJInfo; }
+            set { _pJInfo = value; this.NotifyOfPropertyChange(nameof(PJInfo)); }
+        }
+        private readonly RecipeProvider _recipeProvider = new RecipeProvider();
+        private RecipeFormatBuilder _columnBuilder = new RecipeFormatBuilder();
+        private string _processPrefix = "Furnace\\Process";
+        private string _layoutPrefix = "Furnace\\Layout";
+        #endregion
+        public ProcessDetailV2ViewModel()
+        {
+        }
+        protected override void OnViewLoaded(object _view)
+        {
+            base.OnViewLoaded(_view);
+
+
+            ViewData = new ProcessDetailV2ViewData();
+
+
+            LoadLayoutInfo(PJInfo.LayoutName);
+            LoadProcessData();
+
+
+
+            if (string.IsNullOrEmpty(PJInfo.LayoutName))
+            {
+                ViewData.ProcessStartTime = ViewData.PJobStartTime;
+                ViewData.ProcessEndTime = ViewData.PJobEndTime;
+            }
+        }
+
+        private void LoadProcessData()
+        {
+            var pjStartNoEnd = PJInfo.StartTime != DateTime.MinValue && PJInfo.EndTime == DateTime.MinValue;
+            var pjStartAndEnd = PJInfo.StartTime != DateTime.MinValue && PJInfo.EndTime != DateTime.MinValue;
+            var hasLayoutRecipe = !string.IsNullOrEmpty(PJInfo.LayoutName);
+
+            string sql = $"SELECT * FROM process_data where (pj_id ='{PJInfo.PjId}')";
+            if (string.IsNullOrEmpty(PJInfo.PjId))
+            {
+                sql = $"SELECT * FROM process_data where (recipe_name ='{PJInfo.RecipeName}' and process_begin_time >= '{PJInfo.StartTime:yyyy/MM/dd HH:mm:ss.fff}' and process_end_time <= '{PJInfo.EndTime:yyyy/MM/dd HH:mm:ss.fff}') order by process_begin_time DESC;";
+            }
+            DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
+            string processDataStatus = "";
+            if (dbData != null && dbData.Rows.Count > 0)
+            {
+                ViewData.ProcessStartTime = dbData.Rows[0]["process_begin_time"].ToString();
+                ViewData.ProcessEndTime = dbData.Rows[0]["process_end_time"].ToString();
+                processDataStatus = dbData.Rows[0]["process_status"].ToString();
+            }
+            if (pjStartNoEnd)
+            {
+                ViewData.IsSettingUp = true;
+                ViewData.IsProcessComplete = false;
+                ViewData.IsProcessing = false;
+            }
+            if (!string.IsNullOrEmpty(ViewData.ProcessStartTime) && string.IsNullOrEmpty(ViewData.ProcessEndTime))
+            {
+                ViewData.IsSettingUp = false;
+                ViewData.IsProcessComplete = false;
+                ViewData.IsProcessing = true;
+            }
+            if (pjStartAndEnd)
+            {
+                ViewData.IsSettingUp = false;
+                ViewData.IsProcessComplete = true;
+                ViewData.IsProcessing = false;
+            }
+            if (PJInfo.Form == ProcessEndResultEnum.Abort.ToDescription())
+            {
+                ViewData.ProcessEndResult = ProcessEndResultEnum.Abort.ToDescription();
+                return;
+            }
+            if (PJInfo.Form == ProcessEndResultEnum.Normal.ToDescription() && !string.IsNullOrEmpty(processDataStatus) && processDataStatus == ProcessEndResultEnum.Succeed.ToDescription())
+            {
+                ViewData.ProcessEndResult = ProcessEndResultEnum.NORMALEND.ToDescription();
+                return;
+            }
+            if (pjStartNoEnd || (PJInfo.Form == ProcessEndResultEnum.Normal.ToDescription() && string.IsNullOrEmpty(processDataStatus)))
+            {
+                ViewData.ProcessEndResult = ProcessEndResultEnum.NONE.ToDescription();
+                return;
+            }
+
+
+        }
+        protected override void InvokeAfterUpdateProperty(Dictionary<string, object> data)
+        {
+            // RefreshCassetteDataTask();
+        }
+        private void RefreshCassetteDataTask()
+        {
+            var wafers = ModuleManager.ModuleInfos[ModuleName.PM1.ToString()].WaferManager.Wafers;
+
+        }
+
+        private void LoadLayoutInfo(string layoutName)
+        {
+            ViewData.PJobStartTime = PJInfo.StartTime.ToString("yyyy/MM/dd HH:mm:ss.fff");
+            ViewData.PJobEndTime = PJInfo.EndTime.ToString("yyyy/MM/dd HH:mm:ss.fff");
+
+            if (string.IsNullOrEmpty(layoutName))
+            {
+
+
+                return;
+            }
+            _columnBuilder.Build("Layout");
+            LayoutRecipe.PrefixPath = _layoutPrefix;
+            var recipeContent = _recipeProvider.LoadRecipe(LayoutRecipe.PrefixPath, layoutName);
+            //if (string.IsNullOrEmpty(recipeContent))
+            //{
+            //    System.Windows.MessageBox.Show($"{layoutName} is empty, please confirm the file is valid.");
+            //    return;
+            //}
+            // LayoutRecipe.InitData(LayoutRecipe.PrefixPath, layoutName, recipeContent, _columnBuilder.Configs, "PM1");
+
+            var waferNumberAll = (int)QueryDataClient.Instance.Service.GetConfig("Boat.SlotCount");
+            var cassetteSlotCount = (int)QueryDataClient.Instance.Service.GetConfig("System.CassetteSlotCount");
+            List<string> listWafers = QueryDataClient.Instance.Service.GetLayoutRecipeContent(recipeContent, waferNumberAll.ToString(), cassetteSlotCount.ToString());
+            BoatMapWafers = listWafers;
+            if (null != BoatMapWafers && BoatMapWafers.Count > 0)
+            {
+                var data = ComputSD(BoatMapWafers);
+                ComputWafer(listWafers);
+            }
+        }
+        private void ComputWafer(List<string> listWafers)
+        {
+            UpperSDNum = listWafers.Where(x => x == "SD").Count();
+            LowerSDNum = listWafers.Where(x => x == "FD").Count();
+
+            ProductNum = listWafers.Where(x => x.StartsWith("P")).Count();
+            MonitorNum1 = listWafers.Where(x => x == "M1").Count();
+            MonitorNum2 = listWafers.Where(x => x == "M2").Count();
+        }
+        private Tuple<int, int> ComputSD(List<string> dataSource)
+        {
+            List<string> otherSlot = dataSource.Where(a => a != "SD" && !string.IsNullOrEmpty(a)).ToList().Distinct().ToList();
+            if (dataSource == null || dataSource.Count == 0)
+            {
+                return new Tuple<int, int>(0, 0);
+            }
+            List<int> minList = new List<int>();
+            for (int i = 0; i < dataSource.Count; i++)
+            {
+                var item = dataSource[i];
+                if (otherSlot.Contains(item) && !string.IsNullOrEmpty(item))
+                {
+                    break;
+                }
+                if (string.IsNullOrEmpty(item))
+                {
+                    continue;
+                }
+                minList.Add(i);
+            }
+
+
+            dataSource.Reverse();
+            List<int> maxList = new List<int>();
+            for (int i = 0; i < dataSource.Count; i++)
+            {
+
+                var item = dataSource[i];
+                if (otherSlot.Contains(item) && !string.IsNullOrEmpty(item))
+                {
+                    break;
+                }
+                if (string.IsNullOrEmpty(item))
+                {
+                    continue;
+                }
+                maxList.Add(i);
+            }
+            return new Tuple<int, int>(minList.Count(), maxList.Count());
+
+        }
+
+        public enum ProcessEndResultEnum
+        {
+            [Description("NORMAL END")]
+            NORMALEND,
+            [Description("ABNORMAL END")]
+            ABNORMALEND,
+            [Description("NONE")]
+            NONE,
+            [Description("Recipe Abort")]
+            Abort,
+            [Description("Normal")]
+            Normal, [Description("Succeed")]
+            Succeed,
+        }
+        public class ProcessDetailV2ViewData : PropertyChangedBase
+        {
+
+            private string _processEndResult;
+            public string ProcessEndResult
+            {
+                get => _processEndResult;
+                set
+                {
+                    _processEndResult = value;
+                    NotifyOfPropertyChange(nameof(ProcessEndResult));
+                }
+            }
+
+            private string _pJobStartTime = "";
+            public string PJobStartTime
+            {
+                get => _pJobStartTime;
+                set
+                {
+                    _pJobStartTime = value;
+                    NotifyOfPropertyChange(nameof(PJobStartTime));
+                }
+            }
+
+
+
+            public string PJobEndTime
+            {
+                get => _pJobEndTime;
+                set
+                {
+                    _pJobEndTime = value;
+                    NotifyOfPropertyChange(nameof(PJobEndTime));
+                }
+            }
+            private string _pJobEndTime = "";
+
+            public string ExecREcipeThinckess
+            {
+                get => _execREcipeThinckess;
+                set
+                {
+                    _execREcipeThinckess = value;
+                    NotifyOfPropertyChange(nameof(ExecREcipeThinckess));
+                }
+            }
+            private string _execREcipeThinckess = "";
+            public string ProcessStartTime
+            {
+                get => _processStartTime;
+                set
+                {
+                    _processStartTime = value;
+                    NotifyOfPropertyChange(nameof(ProcessStartTime));
+                }
+            }
+            private string _processStartTime = "";
+
+
+
+            public string ProcessEndTime
+            {
+                get => _processEndTime;
+                set
+                {
+                    _processEndTime = value;
+                    NotifyOfPropertyChange(nameof(ProcessEndTime));
+                }
+            }
+            private string _processEndTime = "";
+
+            public string CJobId
+            {
+                get => _cJobId;
+                set
+                {
+                    _cJobId = value;
+                    NotifyOfPropertyChange(nameof(CJobId));
+                }
+            }
+            private string _cJobId = "";
+
+            private List<string> _pCarrierIdList = new List<string>();
+
+            public List<string> PCarrierIdList
+            {
+                get => _pCarrierIdList;
+                set
+                {
+                    _pCarrierIdList = value;
+                    NotifyOfPropertyChange(nameof(PCarrierIdList));
+                }
+            }
+            private bool _isSettingUp = false;
+
+            public bool IsSettingUp
+            {
+                get => _isSettingUp;
+                set
+                {
+                    _isSettingUp = value;
+                    NotifyOfPropertyChange(nameof(IsSettingUp));
+                }
+            }
+            private bool _isProcessing = false;
+
+            public bool IsProcessing
+            {
+                get => _isProcessing;
+                set
+                {
+                    _isProcessing = value;
+                    NotifyOfPropertyChange(nameof(IsProcessing));
+                }
+            }
+
+            private bool _isProcessComplete = false;
+
+            public bool IsProcessComplete
+            {
+                get => _isProcessComplete;
+                set
+                {
+                    _isProcessComplete = value;
+                    NotifyOfPropertyChange(nameof(IsProcessComplete));
+                }
+            }
+        }
+    }
+}

+ 17 - 30
FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessHistoryTwoView.xaml

@@ -299,53 +299,40 @@
 
         <StackPanel
             Grid.Row="2"
-            Grid.RowSpan="4"
-            Grid.Column="4"
-            Orientation="Horizontal">
+         
+            Grid.Column="1"
+            Grid.ColumnSpan="8"
+            Orientation="Horizontal" HorizontalAlignment="Right">
             <Button
                 Width="140"
                 Height="40"
-                Margin="4,2,4,2"
                 Command="{Binding BatchDetailCommand}"
                 Content="Batch Detail"/>
-        </StackPanel>
-
-        <StackPanel
-            Grid.Row="2"
-            Grid.RowSpan="4"
-            Grid.Column="5"
-            Orientation="Horizontal">
             <Button
-                Width="140"
-                Height="40"
-                Margin="4,2,4,2"
-                Command="{Binding ProcessDetailCommand}"
-                Content="Process Detail"/>
-        </StackPanel>
+      Width="140"
+      Height="40"
+      Command="{Binding ProcessDetailCommand}"
+      Content="Process Detail"/>
+
 
-        <StackPanel
-            Grid.Row="2"
-            Grid.RowSpan="4"
-            Grid.Column="6"
-            Orientation="Horizontal">
             <Button
                 Width="140"
                 Height="40"
-                Margin="4,2,4,2"
                 Command="{Binding ProcessExportCommand}"
                 Content="Process Export"/>
-        </StackPanel>
-        <StackPanel
-            Grid.Row="2"
-            Grid.RowSpan="4"
-            Grid.Column="3"
-            Orientation="Horizontal">
+
             <Button
                 Width="140"
                 Height="40"
-                Margin="4,2,4,2"
                 Command="{Binding ExportProcessTableCommand}"
                 Content="Process Table"/>
+
+
+            <Button
+                Width="140"
+                Height="40"
+                Command="{Binding ProcessJobInfoCommand}"
+                Content="Process Job"/>
         </StackPanel>
         <!--<StackPanel Grid.Row="2" Grid.Column="5" Grid.RowSpan="4" Orientation="Horizontal">
                 <Button Content="Display Graph" Width="140" Height="40" Margin="4,2,4,2" Command="{Binding DisplayGraphCommand}"/>

+ 29 - 7
FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessHistoryTwoViewModel.cs

@@ -9,6 +9,7 @@ using MECF.Framework.UI.Client.CenterViews.DataLogs.Event;
 using MECF.Framework.UI.Client.ClientBase;
 using OpenSEMI.ClientBase;
 using OpenSEMI.ClientBase.Command;
+using SciChart.Charting.Common.Extensions;
 using SciChart.Core.Extensions;
 using System;
 using System.Collections.Generic;
@@ -31,6 +32,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
             ProcessDetailCommand = new BaseCommand<object>(ProcessDetail);
             ProcessExportCommand = new BaseCommand<object>(ProcessExport);
             ExportProcessTableCommand = new BaseCommand<object>(ExportProcessTable);
+            ProcessJobInfoCommand = new BaseCommand<object>(ProcessJobInfo);
             //  DisplayGraphCommand = new BaseCommand<object>(DisplayGraph);
 
             InitTime();
@@ -89,6 +91,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
         public ICommand ProcessDetailCommand { get; set; }
         public ICommand ProcessExportCommand { get; set; }
         public ICommand ExportProcessTableCommand { get; set; }
+        public ICommand ProcessJobInfoCommand { get; set; }
         //    public ICommand DisplayGraphCommand { get; set; }
 
         protected override void OnViewLoaded(object _view)
@@ -99,6 +102,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
             this.view.wfTimeTo.Content = this.SearchEndTime;
 
             QueryLots(new object());
+            ProcessHistoryLots.FirstOrDefault().IsChecked = true;
         }
 
         void InitTime()
@@ -164,7 +168,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
                 if (result == true)
                 {
                     this.view.wfTimeTo.Content = selectdateViewModel.SearchDate;
-                }  
+                }
             }
         }
         void ProcessDetail(object o)
@@ -173,15 +177,23 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
             //{
             var windowManager = IoC.Get<IWindowManager>();
             var param = ProcessHistoryLots.Where(x => x.IsChecked).ToList();
-            //if(param == null || param.Count() < 1)
-            //{
-            //    DialogBox.ShowError("Please select recipe first!");
-            //    return;
-            //}
+
             object processDetailViewModel = new ProcessDetailViewModel<double>(param);
+
             (windowManager as Caliburn.Micro.WindowManager)?.ShowDialogWithTitle(processDetailViewModel, null, "Process Detail");
             //}
         }
+        void ProcessJobInfo(object o)
+        {
+            var windowManager = IoC.Get<IWindowManager>();
+            var param = ProcessHistoryLots.Where(x => x.IsChecked).FirstOrDefault();
+
+            ProcessDetailV2ViewModel processDetailViewModel = new ProcessDetailV2ViewModel();
+            processDetailViewModel.PJInfo = param;
+            processDetailViewModel.TableCount = ProcessHistoryLots.Count;
+            processDetailViewModel.SelectItemIndex = ProcessHistoryLots.IndexOf(param) + 1;
+            (windowManager as Caliburn.Micro.WindowManager)?.ShowDialogWithTitle(processDetailViewModel, null, "ProcessJob Info");
+        }
         void ExportProcessTable(object o)
         {
 
@@ -285,6 +297,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
                 {
                     ProcessHistoryLot item = new ProcessHistoryLot();
 
+                    item.PjId = dbData.Rows[i]["guid"].ToString();
                     item.BatchID = dbData.Rows[i]["batch_id"].ToString();
                     item.JobName = dbData.Rows[i]["job_name"].ToString();
                     item.RecipeName = dbData.Rows[i]["recipe_name"].ToString();
@@ -325,7 +338,16 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
                 InvokePropertyChanged(nameof(IsChecked));
             }
         }
-
+        private string _pjId;
+        public string PjId
+        {
+            get => _pjId;
+            set
+            {
+                _pjId = value;
+                InvokePropertyChanged(nameof(PjId));
+            }
+        }
         private string _batchID;
         public string BatchID
         {

+ 89 - 0
FrameworkLocal/UIClient/CenterViews/Editors/Recipe/RecipeDataBase.cs

@@ -3051,6 +3051,95 @@ namespace MECF.Framework.UI.Client.CenterViews.Editors.Recipe
             recipeHistory.Recipe_Content = GetXmlString();
             return recipeHistory;
         }
+        private void LoadConfigs(ObservableCollection<Param> configDefine, XmlNode configNode)
+        {
+            ConfigItems.Clear();
+
+            foreach (var param in configDefine)
+            {
+                if (param is DoubleParam param1)
+                {
+                    var config = new DoubleParam()
+                    {
+                        Name = param.Name,
+                        Value = param1.Value,
+                        DisplayName = param.DisplayName,
+                        Minimun = param1.Minimun,
+                        Maximun = param1.Maximun,
+                        Resolution = param1.Resolution
+                    };
+
+                    if (configNode != null && configNode.Attributes[param1.Name] != null)
+                        config.Value = configNode.Attributes[param1.Name].Value;
+
+                    ConfigItems.Add(config);
+                }
+                if (param is NumParam paramInt)
+                {
+                    var config = new NumParam()
+                    {
+                        Name = paramInt.Name,
+                        Value = paramInt.Value,
+                        DisplayName = paramInt.DisplayName,
+                    };
+
+                    if (configNode != null && configNode.Attributes[paramInt.Name] != null)
+                    {
+                        int.TryParse(configNode.Attributes[paramInt.Name].Value, out int intValue);
+                        config.Value = intValue;
+                    }
+                    ConfigItems.Add(config);
+                }
+                if (param is StringParam paramString)
+                {
+                    var config = new StringParam()
+                    {
+                        Name = param.Name,
+                        Value = paramString.Value,
+                        DisplayName = param.DisplayName,
+                    };
+
+                    if (configNode != null && configNode.Attributes[paramString.Name] != null)
+                        config.Value = configNode.Attributes[paramString.Name].Value;
+
+                    ConfigItems.Add(config);
+                }
+
+            }
+        }
+        public void InitData(string prefixPath, string recipeName, string recipeContent, ObservableCollection<Param> configDefine, string module)
+        {
+            IsCompatibleWithCurrentFormat = false;
+            _module = module;
+            Name = recipeName;
+            PrefixPath = prefixPath;
+            try
+            {
+                _doc = new XmlDocument();
+                _doc.LoadXml(recipeContent);
+
+                if (!LoadHeader(_doc.SelectSingleNode("Aitex/TableRecipeData")))
+                    return;
+
+                XmlNodeList nodeSteps = _doc.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{module}']/Step");
+                if (nodeSteps == null)
+                    nodeSteps = _doc.SelectNodes($"Aitex/TableRecipeData/Step");
+                LoadSteps(nodeSteps);
+
+                XmlNode nodeConfig =
+                    _doc.SelectSingleNode($"Aitex/TableRecipeData/Module[@Name='{module}']/Config");
+                if (nodeSteps == null)
+                    nodeConfig = _doc.SelectSingleNode($"Aitex/TableRecipeData/Config");
+
+                LoadConfigs(configDefine, nodeConfig);
+
+                IsCompatibleWithCurrentFormat = true;
+            }
+            catch (Exception ex)
+            {
+                LOG.Write(ex);
+            }
+        }
 
     }
 

+ 8 - 0
FrameworkLocal/UIClient/UIClient.csproj

@@ -229,6 +229,10 @@
       <DependentUpon>CassetteDetailView.xaml</DependentUpon>
     </Compile>
     <Compile Include="CenterViews\DataLogs\ProcessHistory\CassetteDetailViewModel.cs" />
+    <Compile Include="CenterViews\DataLogs\ProcessHistory\ProcessDetailV2View.xaml.cs">
+      <DependentUpon>ProcessDetailV2View.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="CenterViews\DataLogs\ProcessHistory\ProcessDetailV2ViewModel.cs" />
     <Compile Include="CenterViews\DataLogs\ProcessHistory\ProcessDetailView.xaml.cs">
       <DependentUpon>ProcessDetailView.xaml</DependentUpon>
     </Compile>
@@ -1046,6 +1050,10 @@
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </Page>
+    <Page Include="CenterViews\DataLogs\ProcessHistory\ProcessDetailV2View.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="CenterViews\DataLogs\ProcessHistory\ProcessDetailView.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>

+ 15 - 0
FrameworkLocal/UICore/Control/BoatElevatorMap.xaml

@@ -0,0 +1,15 @@
+<UserControl x:Class="Aitex.Core.UI.Control.BoatElevatorMap"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             mc:Ignorable="d" 
+             d:DesignHeight="240" d:DesignWidth="170">
+    <Viewbox Stretch="Uniform">
+        <Canvas Width="240" Height="821">
+            <!--<Image Canvas.Left="3" Source="/FurnaceUI;component/Resources/Images/Controls3/Boat.png" Height="2091" Width="259" Panel.ZIndex="3" Canvas.Top="-450"/>-->
+            <Canvas Width="240" Height="821" x:Name="rootCanvas" Canvas.ZIndex="1">
+            </Canvas>
+        </Canvas>
+    </Viewbox>
+</UserControl>

+ 157 - 0
FrameworkLocal/UICore/Control/BoatElevatorMap.xaml.cs

@@ -0,0 +1,157 @@
+
+using Aitex.Core.Common;
+using Aitex.Core.UI.MVVM;
+using MECF.Framework.Common.Equipment;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+
+namespace Aitex.Core.UI.Control
+{
+    /// <summary>
+    /// ATMDualArmRobot.xaml 的交互逻辑
+    /// </summary>
+    public partial class BoatElevatorMap : UserControl, INotifyPropertyChanged
+    {
+        protected readonly int MoveTime = 300;
+        private const int AnimationTimeout = 3000; // seconds
+
+        private SolidColorBrush SDBrush = new SolidColorBrush(Color.FromArgb(255, 251, 147, 85));
+        private SolidColorBrush FDBrush = new SolidColorBrush(Color.FromArgb(255, 170, 147, 255));
+        private SolidColorBrush PDBrush = new SolidColorBrush(Color.FromArgb(255, 2, 255, 255));
+        private SolidColorBrush M1Brush = new SolidColorBrush(Color.FromArgb(255, 3, 149, 255));
+        private SolidColorBrush M2Brush = new SolidColorBrush(Color.FromArgb(255, 255, 111, 171));
+        private SolidColorBrush NoneBrush = new SolidColorBrush(Color.FromArgb(255, 213, 210, 200));
+
+        public WaferInfo[] RobotWafers
+        {
+            get { return (WaferInfo[])GetValue(RobotWafersProperty); }
+            set { SetValue(RobotWafersProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for RobotWafers.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty RobotWafersProperty =
+            DependencyProperty.Register("RobotWafers", typeof(WaferInfo[]), typeof(BoatElevatorMap), new PropertyMetadata(null, PropertyChangedCallback));
+
+        public List<string> BoatWafers
+        {
+            get { return (List<string>)GetValue(BoatWafersProperty); }
+            set { SetValue(BoatWafersProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for RobotWafers.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty BoatWafersProperty =
+            DependencyProperty.Register("BoatWafers", typeof(List<string>), typeof(BoatElevatorMap), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, BoatWafersPropertyChangedCallback));
+
+
+
+
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+
+            var self = (BoatElevatorMap)d;
+
+        }
+
+        static void BoatWafersPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var self = (BoatElevatorMap)d;
+
+        }
+        public BoatElevatorMap()
+        {
+#if DEBUG
+            System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level = System.Diagnostics.SourceLevels.Critical;
+#endif
+            InitializeComponent();
+            rootCanvas.DataContext = this;
+            bgImage = new System.Windows.Media.Imaging.BitmapImage(new Uri(@"pack://application:,,,/FurnaceUI;component/Resources/Images/Controls3/Boat.png"));
+        }
+
+        private System.Windows.Media.Imaging.BitmapImage bgImage;
+
+        protected override void OnRender(DrawingContext drawingContext)
+        {
+
+            if (DesignerProperties.GetIsInDesignMode(this)|| BoatWafers==null)
+            {
+                return;
+            }
+            int indexWafer = 0;
+            if (bgImage != null)
+            {
+                drawingContext.DrawImage(bgImage, new Rect(13, 50, 150, 600));
+            }
+            int fristY = 610;
+
+            foreach (var item in BoatWafers)
+            {
+                if (item == "----" || string.IsNullOrEmpty(item))
+                {
+                    // drawingContext.DrawEllipse(NoneBrush, new Pen(NoneBrush, 1), new Point(85, fristY - indexWafer * 3), 60, 30);
+                }
+                else
+                {
+                    switch (item)
+                    {
+                        case "PD":
+                            drawingContext.DrawEllipse(PDBrush, new Pen(NoneBrush, 1), new Point(85, fristY - indexWafer * 3), 60, 30);
+                            break;
+                        case "SD":
+                            drawingContext.DrawEllipse(SDBrush, new Pen(NoneBrush, 1), new Point(85, fristY - indexWafer * 3), 60, 30);
+                            break;
+                        case "FD":
+                            drawingContext.DrawEllipse(FDBrush, new Pen(NoneBrush, 1), new Point(85, fristY - indexWafer * 3), 60, 30);
+                            break;
+                        case "M1":
+                            drawingContext.DrawEllipse(M1Brush, new Pen(NoneBrush, 1), new Point(85, fristY - indexWafer * 3), 60, 30);
+                            break;
+                        case "M2":
+                            drawingContext.DrawEllipse(M2Brush, new Pen(NoneBrush, 1), new Point(85, fristY - indexWafer * 3), 60, 30);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                indexWafer += 1;
+            }
+            base.OnRender(drawingContext);
+        }
+
+
+
+        private int oldCurrentValue = 0;
+        int oldX = 0;
+
+
+        private void Invoke(Action action)
+        {
+            Dispatcher.Invoke(action);
+        }
+
+        private void LogMsg(string msg)
+        {
+            var source = "ATMRobot";
+            Console.WriteLine("{0} {1}", source, msg);
+        }
+    }
+
+
+}

+ 7 - 0
FrameworkLocal/UICore/UICore.csproj

@@ -172,6 +172,9 @@
     <Compile Include="Control\Annular.xaml.cs">
       <DependentUpon>Annular.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Control\BoatElevatorMap.xaml.cs">
+      <DependentUpon>BoatElevatorMap.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Control\BoatView.xaml.cs">
       <DependentUpon>BoatView.xaml</DependentUpon>
     </Compile>
@@ -599,6 +602,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Control\BoatElevatorMap.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Control\BoatView.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 1 - 0
Furnace/FurnaceRT/Config/DBModel.sql

@@ -167,6 +167,7 @@ begin
 					  "process_status" text,
 					   "wafer_data_guid" text,
 					   "process_in" text,
+					   "pj_id" text,
 					  CONSTRAINT "process_data_pkey" PRIMARY KEY ("guid" )
 					)
 					WITH (

+ 3 - 3
Furnace/FurnaceRT/Config/System.sccfg

@@ -50,7 +50,7 @@
     </configs>
     
     <configs name="SetUp" display="" >
-      <config default="NTP" name="ToolType"  description="Tool Type" max="" min="" paramter="NTP;ELK;SiBCN;TiN" tag="ReadOnlySelection" unit="" type="String" />
+      <config default="ELK" name="ToolType"  description="Tool Type" max="" min="" paramter="NTP;ELK;SiBCN;TiN" tag="ReadOnlySelection" unit="" type="String" />
       <config default="true" name="IsLP1Installed"  description="Is LP1 Installed" max="0" min="0" paramter="" tag="" unit="" type="Bool" />
       <config default="true" name="IsLP2Installed"  description="Is LP2 Installed" max="0" min="0" paramter="" tag="" unit="" type="Bool" />
       <config default="true" name="IsLP3Installed"  description="Is LP3 Installed" max="0" min="0" paramter="" tag="" unit="" type="Bool" />
@@ -393,7 +393,7 @@
     <config default="10" name="PickTimeout" description="Pick Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
     <config default="10" name="HomeTimeout" description="Home Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
     <config default="10" name="MotionTimeout" description="Motion Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
-    <config default="127.0.0.1:1102" name="Address" description="Robot ip,default 192.168.250.35:13000" max="" min="" paramter="" tag="" unit="" type="String" />
+    <config default="127.0.0.1:10001" name="Address" description="Robot ip,default 192.168.250.35:13000" max="" min="" paramter="" tag="" unit="" type="String" />
     <config default="10" name="PlaceTimeout" description="Place Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
     <config default="10" name="ExtendTimeout" description="Extend Time Out" max="60" min="1" paramter="" tag="" unit="s" type="Integer"  visible="false"/>
     <config default="10" name="RetractTimeout" description="Retract Time Out" max="60" min="1" paramter="" tag="" unit="s" type="Integer"  visible="false"/>
@@ -418,7 +418,7 @@
     <config default="10" name="PickTimeout" description="Pick Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
     <config default="10" name="HomeTimeout" description="Home Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
     <config default="10" name="MotionTimeout" description="Motion Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
-    <config default="127.0.0.1:1102" name="Address" description="Robot ip,default 192.168.250.32:13000" max="" min="" paramter="" tag="" unit="" type="String" />
+    <config default="127.0.0.1:10002" name="Address" description="Robot ip,default 192.168.250.32:13000" max="" min="" paramter="" tag="" unit="" type="String" />
     <config default="10" name="PlaceTimeout" description="Place Time Out" max="360" min="1" paramter="" tag="" unit="s" type="Integer" />
     <config default="10" name="ExtendTimeout" description="Extend Time Out" max="60" min="1" paramter="" tag="" unit="s" type="Integer"  visible="false"/>
     <config default="10" name="RetractTimeout" description="Retract Time Out" max="60" min="1" paramter="" tag="" unit="s" type="Integer"  visible="false"/>

+ 5 - 1
Furnace/FurnaceRT/Equipments/Jobs/AutoTransfer.cs

@@ -6523,7 +6523,11 @@ namespace FurnaceRT.Equipments.Jobs
         {
             _isCoolingSkip = true;
         }
-
+        public string GetFirstPJId()
+        {
+            return _dbCallback.GetFirstPJId();
+         
+        }
         public string GetFirstPJStatus()
         {
             if (_lstProcessJobs == null || _lstProcessJobs.Count == 0)

+ 6 - 1
Furnace/FurnaceRT/Equipments/PMs/PMModule.cs

@@ -1058,7 +1058,12 @@ namespace FurnaceRT.Equipments.PMs
         {
             _processRoutine.ExitProcess();
             if (!IsJobProcess && !_processRoutine.IsExecuteAbort)//非jobprocess需要recipe结束也需要更新数据库
+            {
+                var firstPjId = Singleton<EquipmentManager>.Instance.GetFirstPJId();
+
                 Singleton<EquipmentManager>.Instance.EndPj();
+                _processRoutine.UpdateProcessDataPJid(firstPjId);
+            }
 
 
             //_statWaferCount.Increase();
@@ -1494,7 +1499,7 @@ namespace FurnaceRT.Equipments.PMs
         }
         private double GetWaitTime()
         {
-            if (StringFsmStatus=="Idle")
+            if (StringFsmStatus == "Idle")
             {
                 _waitTimer.Reset();
             }

+ 4 - 1
Furnace/FurnaceRT/Equipments/PMs/RecipeDBCallback.cs

@@ -20,7 +20,10 @@ namespace FurnaceRT.Equipments.PMs
 
             ProcessDataRecorder.Start(guid, recipeName, waferId, module.ToString());
         }
-
+        public void RecipeUpdatePjId(string guid, string pjId)
+        {
+            ProcessDataRecorder.UpdatePjId(guid, pjId);
+        }
         public void RecipeUpdateStatus(string guid, string status)
         {
             ProcessDataRecorder.UpdateStatus(guid, status);

+ 32 - 27
Furnace/FurnaceRT/Equipments/PMs/RecipeExecutions/Process.cs

@@ -194,7 +194,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
         private string _infoAUXWaitCondition = "";
         private string _infoHeaterWaitCondition = "";
         private string _infoMFCWaitCondition = "";
-        private Dictionary<int, Tuple<bool,int>> _callSubSteps = new Dictionary<int, Tuple<bool, int>>();
+        private Dictionary<int, Tuple<bool, int>> _callSubSteps = new Dictionary<int, Tuple<bool, int>>();
         private bool _isJumpStep = false;
 
         public Process(ModuleName module, PMModule pm) : base(module, pm)
@@ -330,7 +330,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                 curSteps = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps;
 
                 if (!_callSubSteps.ContainsKey(_currentStepNumber))
-                    _callSubSteps.Add(_currentStepNumber, Tuple.Create(false,0));
+                    _callSubSteps.Add(_currentStepNumber, Tuple.Create(false, 0));
                 if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].IsCallSubStep)
                     _callSubSteps[_currentStepNumber] = Tuple.Create(true, PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeLoopCount);
 
@@ -384,7 +384,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                                         _currentSubRecipeStepNumber = curSteps[_currentSubRecipeStepNumber].JumpStepNo;
                                     }
 
-                                    RecipeExec("Sub recipe", curSteps, _currentSubRecipeStepNumber, _curStepElpasedTimeBeforePaused, _currentSubRecipeStepNumber+1);
+                                    RecipeExec("Sub recipe", curSteps, _currentSubRecipeStepNumber, _curStepElpasedTimeBeforePaused, _currentSubRecipeStepNumber + 1);
                                 }
                                 else
                                 {
@@ -539,10 +539,10 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                                 if (_stepTimer.IsTimeout())
                                 {
 
-                                    if(PMModule.IsBoatMoveToLoadPosition)
+                                    if (PMModule.IsBoatMoveToLoadPosition)
                                     {
                                         _trigBoatMoveToLoadPositionTimeout.CLK = !boatWaitCondition;
-                                        if(_trigBoatMoveToLoadPositionTimeout.Q)
+                                        if (_trigBoatMoveToLoadPositionTimeout.Q)
                                             PMModule.BoatMoveToLoadPositionTimeoutWarning.Set();
                                     }
                                     //_trigInputSignalTimeOutAlarm.CLK = !PMModule.CheckExternalSensorCondition();
@@ -619,14 +619,14 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                                 {
                                     stepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].StepName;
                                     float.TryParse(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[_currentSubRecipeStepNumber].FilmThickFormula, out thickness);
-                                   
+
                                     //放在前面,stepnumber后面会被更新
                                     if (!_isJumpStep)
                                     {
                                         _faCallback.RecipeStepEnd(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName, _currentSubRecipeStepNumber + 1);
                                         _dbCallback.RecipeStepEnd(PMModule.RecipeRunningInfo.InnerId.ToString(), _currentSubRecipeStepNumber + 1, _fdc.DataList, SC.GetStringValue("PM1.TempCorrection"), SC.GetStringValue("PM1.Heater.PID"));
                                     }
-                                        
+
                                     _fdc.Stop();
 
                                     _totalElpasedTime += curSteps[_currentSubRecipeStepNumber].StepTime;
@@ -685,7 +685,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                                         _faCallback.RecipeStepEnd(PMModule.Module, PMModule.RecipeRunningInfo.RecipeName, _currentStepNumber);
                                         _dbCallback.RecipeStepEnd(PMModule.RecipeRunningInfo.InnerId.ToString(), _currentStepNumber, _fdc.DataList, SC.GetStringValue("PM1.TempCorrection"), SC.GetStringValue("PM1.Heater.PID"));
                                     }
-                                        
+
                                     _fdc.Stop();
 
                                     if (_currentStepNumber >= 0 && !IsSubReciep)
@@ -712,7 +712,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                                         RecipeLoopEndCheck(PMModule.RecipeRunningInfo.RecipeStepList);
                                     }
 
-                                    if(_currentStepNumber >= PMModule.RecipeRunningInfo.RecipeStepList.Count - 1)
+                                    if (_currentStepNumber >= PMModule.RecipeRunningInfo.RecipeStepList.Count - 1)
                                     {
                                         for (int i = 0; i < SC.GetValue<int>($"Boat.SlotCount"); i++)
                                         {
@@ -741,7 +741,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                                     }
                                 }
 
-                                if(!_isJumpStep)
+                                if (!_isJumpStep)
                                 {
                                     PMModule.UpdateRecipeStepThicknessAndTime(stepName, thickness, stepTime);
                                     var wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Module));
@@ -819,7 +819,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
 
             if (IsSubReciep)
             {
-                if(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps != null)
+                if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps != null)
                 {
                     if (_stepTimer.IsIdle())
                     {
@@ -868,13 +868,13 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                             PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[step].LoopStartStep].StepName : "";
                     else
                     {
-                        if(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps.Count > step + 1)
+                        if (PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps.Count > step + 1)
                         {
                             PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[step + 1].StepName;
                         }
                         else
                         {
-                            if(PMModule.RecipeRunningInfo.SubRecipeCurrentLoopCount < PMModule.RecipeRunningInfo.SubRecipeLoopCount)
+                            if (PMModule.RecipeRunningInfo.SubRecipeCurrentLoopCount < PMModule.RecipeRunningInfo.SubRecipeLoopCount)
                             {
                                 //sub 下一个循环
                                 PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps[0].StepName;
@@ -899,7 +899,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                         PMModule.StringProcessFlowState = PMModule.ProcessFlowState.Run.ToString();
                     }
                 }
-                
+
                 return;
             }
 
@@ -932,7 +932,8 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
             PMModule.RecipeRunningInfo.StepTime = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].StepTime;
             PMModule.RecipeRunningInfo.RecipeName = PMModule.RecipeRunningInfo.MainRecipeName;
             PMModule.RecipeRunningInfo.ExecRecipeType = PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].RecipeType;
-            if (_state == RecipeRunningState.RecipeCompleted) { 
+            if (_state == RecipeRunningState.RecipeCompleted)
+            {
                 PMModule.RecipeRunningInfo.HoldTime = 0;
             }
 
@@ -954,7 +955,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                 PMModule.RecipeRunningInfo.StepNumber = step + 1; //CurStepNum start from 0
             }
             PMModule.RecipeRunningInfo.StepName = PMModule.RecipeRunningInfo.RecipeStepList[_showStepNo].StepName;
-            if(PMModule.RecipeRunningInfo.RecipeStepList[step].IsLoopEndStep)
+            if (PMModule.RecipeRunningInfo.RecipeStepList[step].IsLoopEndStep)
                 PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList.Count > PMModule.RecipeRunningInfo.RecipeStepList[step].LoopStartStep ? PMModule.RecipeRunningInfo.RecipeStepList[PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].LoopStartStep].StepName : "";
             else
                 PMModule.RecipeRunningInfo.NextStepName = PMModule.RecipeRunningInfo.RecipeStepList.Count > step + 1 ? PMModule.RecipeRunningInfo.RecipeStepList[step + 1].StepName : "";
@@ -981,8 +982,8 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
             if (_alarmNames.Count == 0)
                 return;
 
-            int group = -1,temp = 0;
-            string iAlarmConditionTable="1:";
+            int group = -1, temp = 0;
+            string iAlarmConditionTable = "1:";
             if (IsSubReciep)
             {
                 for (int i = 0; i < _alarmNames.Count; i++)
@@ -1099,7 +1100,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                 _holdTimeElpasedTime += _holdTimer.GetElapseTime();
                 _holdTimer.Stop();
             }
-            
+
             CurrentLoopCount = 0;
             CurrentAbortRecipeLoopCount = 0;
             CurrentSubRecipeLoopCount = 0;
@@ -1125,6 +1126,10 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
             _state = RecipeRunningState.ExecStep;
         }
 
+        public void UpdateProcessDataPJid(string pjId)
+        {
+            _dbCallback.RecipeUpdatePjId(PMModule.RecipeRunningInfo.InnerId.ToString(), pjId);
+        }
         public void ExitProcess()
         {
             if (_state == RecipeRunningState.RecipeCompleted)
@@ -1180,7 +1185,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                     _holdTimer.Stop();
                 }
             }
-            if(IsSubReciep)
+            if (IsSubReciep)
             {
                 ResetLoop(PMModule.RecipeRunningInfo.RecipeStepList[_currentStepNumber].SubRecipeSteps, _currentSubRecipeStepNumber);
             }
@@ -1234,7 +1239,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
         {
             PMModule.AbortLeakCheck();
             LOG.Write($"Jump to step stepNumber={stepNumber} stepName={stepName}, currentStepNumber={_currentStepNumber}");
-            if (_state == RecipeRunningState.ConditionWait || _state == RecipeRunningState.TimeWait || 
+            if (_state == RecipeRunningState.ConditionWait || _state == RecipeRunningState.TimeWait ||
                 _state == RecipeRunningState.Paused || _state == RecipeRunningState.ExecStep)
             {
                 _loopEnd = true;
@@ -1259,11 +1264,11 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                     ResetLoop(PMModule.RecipeRunningInfo.RecipeStepList, _currentStepNumber);
                 }
 
-                if(_callSubSteps != null)
+                if (_callSubSteps != null)
                 {
-                    foreach(var key in _callSubSteps.Keys)
+                    foreach (var key in _callSubSteps.Keys)
                     {
-                        if(PMModule.RecipeRunningInfo.RecipeStepList.Count > key)
+                        if (PMModule.RecipeRunningInfo.RecipeStepList.Count > key)
                         {
                             PMModule.RecipeRunningInfo.RecipeStepList[key].IsCallSubStep = _callSubSteps[key].Item1;
                             PMModule.RecipeRunningInfo.RecipeStepList[key].SubRecipeLoopCount = _callSubSteps[key].Item2;
@@ -1277,7 +1282,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                 _currentStepNumber = stepNumber - 1;
                 if (_currentStepNumber < 0)
                     _currentStepNumber = 0;
-                    
+
                 _totalElpasedTime = RefreshElpasedTime();
                 _state = RecipeRunningState.StepCompleted;
                 PMModule.IsPaused = false;
@@ -1317,7 +1322,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
                         }
                         else
                         {
-                            if (PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps != null && 
+                            if (PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps != null &&
                                 PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeSteps.Count > _currentSubRecipeStepNumber)
                             {
                                 total += SubRecipeCalTotalTime(i) * PMModule.RecipeRunningInfo.RecipeStepList[i].SubRecipeLoopCount;
@@ -1700,7 +1705,7 @@ namespace FurnaceRT.Equipments.PMs.RecipeExecutions
             _infoMFCWaitCondition = "";
         }
 
-        private void RecipeExec(string type, List<RecipeStep> curSteps, int currentStepNumber, double curStepElpasedTimeBeforePaused, int otherRecipeStartStepNumber=0)
+        private void RecipeExec(string type, List<RecipeStep> curSteps, int currentStepNumber, double curStepElpasedTimeBeforePaused, int otherRecipeStartStepNumber = 0)
         {
             var reason = "";
             _stepTimer.Start(curSteps[currentStepNumber].StepTime * 1000 - curStepElpasedTimeBeforePaused);

+ 6 - 2
Furnace/FurnaceRT/Equipments/Schedulers/SchedulerDBCallback.cs

@@ -184,10 +184,14 @@ namespace FurnaceRT.Equipments.Schedulers
             }
             string layoutData = String.Join(",", layoutDatas);
             string waferData = String.Join(",", waferDatas);
-            if(_processJobInfo != null)
+            if (_processJobInfo != null)
                 JobDataRecorder.UpdatePJ(_processJobInfo.InnerId.ToString(), layoutData, waferData, waferCount);
         }
-
+        public string GetFirstPJId()
+        {
+            if (_processJobInfo != null) return _processJobInfo.InnerId.ToString();
+            return "";
+        }
         public void PjFinished(string endStatus = "Normal")
         {
             if (_processJobInfo != null)

+ 4 - 0
Furnace/FurnaceRT/Equipments/Systems/EquipmentManager_FA.cs

@@ -27,6 +27,10 @@ namespace FurnaceRT.Equipments.Systems
         {
             _auto.EndPj(endStatus);
         }
+        public string GetFirstPJId()
+        {
+            return _auto.GetFirstPJId();
+        }
     }
 
     public partial class EquipmentManager : IJobControlCallBack

+ 2 - 2
Furnace/FurnaceUI/Views/Recipes/RecipeLayoutEditView.xaml

@@ -257,7 +257,7 @@
                                     <RowDefinition/>
                                     <RowDefinition/>
                                 </Grid.RowDefinitions>
-                                <TextBlock Text="Upper SD"/>
+                                <TextBlock Text="SD"/>
                                 <WrapPanel Grid.Row="1">
                                     <controls1:TextBoxEx Width="60" Text="{Binding UpperSDNum}" Tag="Number"/>
                                     <TextBlock Text="Num"/>
@@ -286,7 +286,7 @@
 
                                 <Line Grid.Row="11" X1="-4" Y1="0" X2="96" Y2="0" Margin="0,0,-4,0" StrokeThickness="2" Stroke="LightGray"/>
 
-                                <TextBlock Grid.Row="12" Text="Lower SD"/>
+                                <TextBlock Grid.Row="12" Text="ED"/>
                                 <WrapPanel Grid.Row="13">
                                     <controls1:TextBoxEx Width="60" Text="{Binding LowerSDNum}" Tag="Number"/>
                                     <TextBlock Text="Num"/>

+ 3 - 3
Furnace/FurnaceUI/Views/Recipes/RecipeLayoutEditViewModel.cs

@@ -616,10 +616,10 @@ namespace FurnaceUI.Views.Recipes
             if (null != BoatMapWafers && BoatMapWafers.Count > 0)
             {
                 var data = ComputSD(BoatMapWafers);
-                LowerSDNum = data.Item1;
-                UpperSDNum = data.Item2;
+                 UpperSDNum = listWafers.Where(x => x == "SD").Count();
+                LowerSDNum = listWafers.Where(x => x == "FD").Count();
 
-                ProductNum = listWafers.Where(x => x == "PD").Count();
+                ProductNum = listWafers.Where(x => x.StartsWith("P")).Count();
                 MonitorNum1 = listWafers.Where(x => x == "M1").Count();
                 MonitorNum2 = listWafers.Where(x => x == "M2").Count();
             }