更新库文件(Commit 704daa8),用户登录时首先发起登录请求,请求已登录客户端确认的功能。

This commit is contained in:
SL 2023-09-07 23:32:35 +08:00
parent 63e03d78e8
commit ad1f13c3e0
16 changed files with 494 additions and 356 deletions

View File

@ -1,145 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net "/>
</configSections>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
<connectionStrings>
<add name="PostgreSQL" connectionString="Server=localhost;Port=5432;User Id=postgres;Password=123456;Database=postgres;Enlist=true;Preload Reader = true;"/>
</connectionStrings>
<appSettings>
<add key="IsSimulationMode" value="false"/>
<add key="RobotAddress" value="127.0.0.1:10110"/>
<add key="AlignerAddress" value="127.0.0.1:10111"/>
<add key="WIDReaderAddress" value="127.0.0.1:23"/>
<add key="Su" value="21232f297a57a5a743894a0e4a801fc3"/>
<add key="ClientSettingsProvider.ServiceUri" value=""/>
</appSettings>
<log4net>
<appender name="txtFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Logs\log" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Date" />
<param name="StaticLogFileName" value="false" />
<datePattern value="yyyyMMdd'.log'" />
<encoding value="utf-8" />
<maxSizeRollBackups value="120" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%m%n" />
<param name="Header" value="&#13;&#10;&lt;=====Sic Begin=====&gt;&#13;&#10;" />
<param name="Footer" value="&#13;&#10;&lt;=====Sic End=====&gt;&#13;&#10;" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="txtFileAppender"/>
</root>
</log4net>
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information,ActivityTracing" propagateActivity="true">
<listeners>
<add name="xml"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="C:\logs\TracingAndLogging-service.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="xml"/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
<!--<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="messages"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\logs\mitrt.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>-->
<system.serviceModel>
<!--<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="false" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false" maxMessagesToLog="3000" maxSizeOfMessageToLog="2000" />
</diagnostics>-->
<bindings>
<netTcpBinding>
<binding name="Aitex_netTcpBinding" maxReceivedMessageSize="102400000" receiveTimeout="infinite">
<readerQuotas maxDepth="32" maxStringContentLength="1048576" maxArrayLength="163840000" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="None">
<transport clientCredentialType="None"/>
<message clientCredentialType="None"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<services>
<service behaviorConfiguration="BasicBehavior" name="Aitex.Core.Account.AccountService">
<endpoint address="net.tcp://localhost:8775/AccountService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="Aitex.Core.Account.IAccountService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="MECF.Framework.Common.OperationCenter.InvokeService">
<endpoint address="net.tcp://localhost:8751/InvokeService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="MECF.Framework.Common.OperationCenter.IInvokeService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="Aitex.Core.WCF.EventService">
<endpoint address="net.tcp://localhost:8752/EventService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="Aitex.Core.WCF.Interface.IEventService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="MECF.Framework.Common.DataCenter.QueryDataService">
<endpoint address="net.tcp://localhost:8771/QueryDataService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="MECF.Framework.Common.DataCenter.IQueryDataService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="MECF.Framework.Common.RecipeCenter.RecipeService">
<endpoint address="net.tcp://localhost:8773/RecipeService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="MECF.Framework.Common.RecipeCenter.IRecipeService"/>
</service>
</services>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net "/>
</configSections>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
<connectionStrings>
<add name="PostgreSQL" connectionString="Server=localhost;Port=5432;User Id=postgres;Password=123456;Database=postgres;Enlist=true;Preload Reader = true;"/>
</connectionStrings>
<appSettings>
<add key="IsSimulationMode" value="false"/>
<client>
<endpoint address="net.tcp://localhost:6701/SimulatorAdsPlcService"
behaviorConfiguration="EndpointBehavior"
binding="netTcpBinding"
bindingConfiguration="Aitex_netTcpBinding"
contract="MECF.Framework.Common.PLC.IWcfPlcService"
name="Client_IWcfPlcService"/>
</client>
<behaviors>
<serviceBehaviors>
<behavior name="BasicBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="false"/>
</behavior>
<behavior name="SingleModeBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri=""/>
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400"/>
</providers>
</roleManager>
</system.web>
<add key="RobotAddress" value="127.0.0.1:10110"/>
<add key="AlignerAddress" value="127.0.0.1:10111"/>
<add key="WIDReaderAddress" value="127.0.0.1:23"/>
<add key="Su" value="21232f297a57a5a743894a0e4a801fc3"/>
<add key="ClientSettingsProvider.ServiceUri" value=""/>
</appSettings>
<log4net>
<appender name="txtFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Logs\log" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Date" />
<param name="StaticLogFileName" value="false" />
<datePattern value="yyyyMMdd'.log'" />
<encoding value="utf-8" />
<maxSizeRollBackups value="120" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%m%n" />
<param name="Header" value="&#13;&#10;&lt;=====Sic Begin=====&gt;&#13;&#10;" />
<param name="Footer" value="&#13;&#10;&lt;=====Sic End=====&gt;&#13;&#10;" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="txtFileAppender"/>
</root>
</log4net>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true" >
<listeners>
<add name="xml"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml"/>
</listeners>
</source>
<source name="myUserTraceSource"
switchValue="Information, ActivityTracing">
<listeners>
<add name="xml"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="Error.svclog" />
</sharedListeners>
</system.diagnostics>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="Aitex_netTcpBinding" maxReceivedMessageSize="102400000" receiveTimeout="infinite">
<readerQuotas maxDepth="32" maxStringContentLength="1048576" maxArrayLength="163840000" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="None">
<transport clientCredentialType="None"/>
<message clientCredentialType="None"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<services>
<service behaviorConfiguration="BasicBehavior" name="Aitex.Core.Account.AccountService">
<endpoint address="net.tcp://localhost:8775/AccountService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="Aitex.Core.Account.IAccountService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="MECF.Framework.Common.OperationCenter.InvokeService">
<endpoint address="net.tcp://localhost:8751/InvokeService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="MECF.Framework.Common.OperationCenter.IInvokeService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="Aitex.Core.WCF.EventService">
<endpoint address="net.tcp://localhost:8752/EventService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="Aitex.Core.WCF.Interface.IEventService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="MECF.Framework.Common.DataCenter.QueryDataService">
<endpoint address="net.tcp://localhost:8771/QueryDataService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="MECF.Framework.Common.DataCenter.IQueryDataService"/>
</service>
<service behaviorConfiguration="BasicBehavior" name="MECF.Framework.Common.RecipeCenter.RecipeService">
<endpoint address="net.tcp://localhost:8773/RecipeService" binding="netTcpBinding" bindingConfiguration="Aitex_netTcpBinding" contract="MECF.Framework.Common.RecipeCenter.IRecipeService"/>
</service>
</services>
<client>
<endpoint address="net.tcp://localhost:6701/SimulatorAdsPlcService"
behaviorConfiguration="EndpointBehavior"
binding="netTcpBinding"
bindingConfiguration="Aitex_netTcpBinding"
contract="MECF.Framework.Common.PLC.IWcfPlcService"
name="Client_IWcfPlcService"/>
</client>
<behaviors>
<serviceBehaviors>
<behavior name="BasicBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="false"/>
</behavior>
<behavior name="SingleModeBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri=""/>
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400"/>
</providers>
</roleManager>
</system.web>
</configuration>

View File

@ -2,7 +2,7 @@
<root>
<roles>
<!--2:read and write-->
<roleItem id="0" name="Manager" autologout="1" logouttime="20">
<roleItem id="0" name="Manager" autologout="1" logouttime="20" buildin="true">
Header,3;Overview,3;Coating,3;TM,3;Device,3;ioPlatform,3;LeakCheck,3;Sequence,3;Recipe,3;EventLog,3;ProcessHistory,3;RealTimeCharting,3;DataHistory,3;JobList,3;
Charting,3;Config,3;Account,3;Role,3;Runtime,3;Alarm,3;mainPM1,3;processPM1,3;ioPM1,3;motionPM1,3;heaterPM1,3;alarmPM1,3;MFCFlowPM1,3;mainPM2,3;
processPM2,3;ioPM2,3;motionPM2,3;heaterPM2,3;alarmPM2,3;MFCFlowPM2,3;Uid,3;Step,3;Name,3;Time,3;Growth Rate,3;1. Ar/H2 Switch,3;2. SH Total Flow,3;
@ -28,7 +28,7 @@
Step27,3;Step28,3;Step29,3;Step30,3;Step31,3;Step32,3;Step33,3;Step34,3;Step35,3;Step36,3;Step37,3;Step38,3;Step39,3;Step40,3;Step41,3;Step42,3;Step43,3;
Step44,3;Step45,3;Step46,3;Step47,3;Step48,3;Step49,3;Step50,3;
</roleItem>
<roleItem id="1" name="Engineer" autologout="1" logouttime="20">
<roleItem id="1" name="Engineer" autologout="1" logouttime="20" buildin="true">
Header,3;Overview,3;Coating,3;TM,3;Device,3;ioPlatform,3;LeakCheck,3;Sequence,3;Recipe,3;EventLog,3;ProcessHistory,3;RealTimeCharting,3;DataHistory,3;JobList,3;
Charting,3;Config,3;Account,3;Role,3;Runtime,3;Alarm,3;mainPM1,3;processPM1,3;ioPM1,3;motionPM1,3;heaterPM1,3;alarmPM1,3;MFCFlowPM1,3;mainPM2,3;
processPM2,3;ioPM2,3;motionPM2,3;heaterPM2,3;alarmPM2,3;MFCFlowPM2,3;Uid,3;Step,3;Name,3;Time,3;Growth Rate,3;1. Ar/H2 Switch,3;2. SH Total Flow,3;
@ -54,7 +54,7 @@
Step27,3;Step28,3;Step29,3;Step30,3;Step31,3;Step32,3;Step33,3;Step34,3;Step35,3;Step36,3;Step37,3;Step38,3;Step39,3;Step40,3;Step41,3;Step42,3;Step43,3;
Step44,3;Step45,3;Step46,3;Step47,3;Step48,3;Step49,3;Step50,3;
</roleItem>
<roleItem id="2" name="Technician" autologout="1" logouttime="20">
<roleItem id="2" name="Technician" autologout="1" logouttime="20" buildin="true">
Header,3;Overview,3;Coating,3;TM,3;Device,3;ioPlatform,3;LeakCheck,3;Sequence,3;Recipe,3;EventLog,3;ProcessHistory,3;RealTimeCharting,3;DataHistory,3;JobList,3;
Charting,3;Config,3;Account,3;Role,3;Runtime,3;Alarm,3;mainPM1,3;processPM1,3;ioPM1,3;motionPM1,3;heaterPM1,3;alarmPM1,3;MFCFlowPM1,3;mainPM2,3;
processPM2,3;ioPM2,3;motionPM2,3;heaterPM2,3;alarmPM2,3;MFCFlowPM2,3;Uid,3;Step,3;Name,3;Time,3;Growth Rate,3;1. Ar/H2 Switch,3;2. SH Total Flow,3;
@ -80,7 +80,7 @@
Step27,3;Step28,3;Step29,3;Step30,3;Step31,3;Step32,3;Step33,3;Step34,3;Step35,3;Step36,3;Step37,3;Step38,3;Step39,3;Step40,3;Step41,3;Step42,3;Step43,3;
Step44,3;Step45,3;Step46,3;Step47,3;Step48,3;Step49,3;Step50,3;
</roleItem>
<roleItem id="3" name="Operator" autologout="1" logouttime="20">
<roleItem id="3" name="Operator" autologout="1" logouttime="20" buildin="true">
Header,3;Overview,3;Coating,3;TM,3;Device,3;ioPlatform,3;LeakCheck,3;Sequence,3;Recipe,3;EventLog,3;ProcessHistory,3;RealTimeCharting,3;DataHistory,3;JobList,3;
Charting,3;Config,3;Account,3;Role,3;Runtime,3;Alarm,3;mainPM1,3;processPM1,3;ioPM1,3;motionPM1,3;heaterPM1,3;alarmPM1,3;MFCFlowPM1,3;mainPM2,3;
processPM2,3;ioPM2,3;motionPM2,3;heaterPM2,3;alarmPM2,3;MFCFlowPM2,3;Uid,3;Step,3;Name,3;Time,3;Growth Rate,3;1. Ar/H2 Switch,3;2. SH Total Flow,3;

View File

@ -231,6 +231,12 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="Config\Menu.xml">
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>

View File

@ -12,7 +12,7 @@
<ResourceDictionary>
<converters:DummyConverter x:Key="dummyConverter" />
<cv:ReserveBoolSensorConverter x:Key="BoolReverseConverter" />
<cv:BoolReverseConverter x:Key="BoolReverseConverter" />
<cv:BoolVisibilityConverter x:Key="BoolVisibilityConverter" />
<cv:BoolCollapsedConverter x:Key="BoolCollapsedConverter" />

View File

@ -0,0 +1,37 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace SicUI.Converter
{
internal class IsReadOnlyModeToUserInfoNameBgConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var defaultColor = Color.FromRgb(0xC8, 0xE8, 0xFF); //FFC8E8FF
if (value is bool isReadOnlyMode)
{
if (isReadOnlyMode)
return new SolidColorBrush(Colors.Orange);
else
{
var res = Application.Current.TryFindResource("TopFrame_UserInfoBG");
if (res is SolidColorBrush brush)
return brush;
else
return new SolidColorBrush(defaultColor);
}
}
return new SolidColorBrush(defaultColor);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -6,24 +6,31 @@
xmlns:client="clr-namespace:SicUI.Client"
xmlns:converter="clr-namespace:MECF.Framework.UI.Client.Ctrlib.Converter;assembly=MECF.Framework.UI.Client"
xmlns:deviceControl="clr-namespace:Aitex.Core.UI.DeviceControl;assembly=MECF.Framework.UI.Core"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:wnd="http://OpenSEMI.Ctrlib.com/presentation"
xmlns:converters="clr-namespace:MECF.Framework.UI.Core.Converters;assembly=MECF.Framework.UI.Core"
xmlns:converter1="clr-namespace:SicUI.Converter"
xmlns:userControls="clr-namespace:Sicentury.Core.UserControls;assembly=Sicentury.Core"
Title="Sic Manual Edition"
Width="1900"
Height="980"
WindowStartupLocation="CenterScreen"
WindowState="Maximized">
WindowState="Maximized"
mc:Ignorable="d"
d:DesignHeight="980" d:DesignWidth="1900"
d:DataContext="{d:DesignInstance Type=client:MainViewModel, IsDesignTimeCreatable=False}">
<Window.Resources>
<client:CollectionLastIndexConverter x:Key="collectionLastIndexConverter" />
<converter:UnitOnlineBorderColorConverter x:Key="UnitOnlineBorderColorConverter" />
<converters:EngModeToBdThicknessConverter x:Key="BdThicknessConverter"/>
<converters:EngModeToBdColorConverter x:Key="BdColorConverter"/>
<converters:EngModeToBgWatermarkVisibilityConverter x:Key="WatermarkVisibilityConverter"/>
<converter1:IsReadOnlyModeToUserInfoNameBgConverter x:Key="IsReadOnlyModeToUserInfoNameBgConverter"/>
</Window.Resources>
<Grid Background="{DynamicResource MainArea_BG}">
<Grid x:Name="LoginPart" Background="{StaticResource Login_BG}">
<Grid Panel.ZIndex="999" x:Name="LoginPart" Background="{StaticResource Login_BG}">
<Ellipse
MaxWidth="1000"
MaxHeight="800"
@ -41,6 +48,24 @@
BorderThickness="1"
CornerRadius="3">
<Grid>
<userControls:BusyIndicator
Panel.ZIndex="99"
Width="Auto"
Height="Auto"
Padding="20,10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{StaticResource Tab_BG}"
BorderBrush="Gray"
BorderThickness="3"
Message="{Binding RequestLoginIndicatorText}"
Visibility="{Binding IsShowRequestLoginIndicator, Converter={StaticResource BoolVisibilityConverter}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Canceled">
<cal:ActionMessage MethodName="CancelRequestLogin" />
</i:EventTrigger>
</i:Interaction.Triggers>
</userControls:BusyIndicator>
<Path
Width="590"
Height="252.338"
@ -303,7 +328,7 @@
Style="{StaticResource Login_Button}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="Login">
<cal:ActionMessage MethodName="RequestLogin">
<cal:Parameter Value="{Binding ElementName=tbLoginName, Path=Text}" />
<cal:Parameter Value="{Binding ElementName=pdbPassword}" />
<cal:Parameter Value="{Binding ElementName=cbRole, Path=SelectedValue}" />
@ -395,6 +420,7 @@
Text="{Binding SoftwareVersion}" />
</StackPanel>
<Grid
IsHitTestVisible="{Binding IsReadOnlyMode, Converter={StaticResource BoolReverseConverter}}"
Grid.Column="1"
Margin="-25,8,0,8"
ColumnSpan="2">
@ -1029,19 +1055,6 @@
</Grid>
</Grid>
<Grid
Grid.Column="2"
Margin="28,10"
IsEnabled="{Binding IsPermission}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
<Label
Grid.Column="3"
Width="50"
@ -1064,7 +1077,7 @@
</Grid.RowDefinitions>
<Border
Margin="2,4"
Background="{DynamicResource TopFrame_UserInfoBG}"
Background="{Binding IsReadOnlyMode, Converter={StaticResource IsReadOnlyModeToUserInfoNameBgConverter}}"
BorderBrush="{DynamicResource TopFrame_UserInfoBD}"
BorderThickness="1"
CornerRadius="5"
@ -1093,7 +1106,7 @@
</Grid>
</Border>
</Grid>
<Grid Grid.Row="1" Background="{DynamicResource MainArea_BG}">
<Grid Grid.Row="1" Background="{DynamicResource MainArea_BG}" IsHitTestVisible="{Binding IsReadOnlyMode, Converter={StaticResource BoolReverseConverter}}">
<Border Visibility="{Binding IsEngMode, Converter={StaticResource WatermarkVisibilityConverter}}">
<Border.Background>
<ImageBrush ImageSource="/Resources/Images/interlock_bypass_watermark.png"

View File

@ -12,10 +12,6 @@ using MECF.Framework.UI.Core.Accounts;
using OpenSEMI.ClientBase;
using OpenSEMI.ClientBase.Command;
using OpenSEMI.ClientBase.Utility;
using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Visuals;
using SciChart.Charting.Visuals.Annotations;
using SciChart.Charting.Visuals.Axes;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@ -28,92 +24,102 @@ using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;
using Sicentury.Core.Collections;
using Cali = Caliburn.Micro.Core;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
using Aitex.Core.WCF.Interface;
using Caliburn.Micro.Core;
using AuthorizeResult = MECF.Framework.UI.Client.ClientBase.AuthorizeResult;
using Newtonsoft.Json.Linq;
namespace SicUI.Client
{
public class MainViewModel : TimeredMainViewModel
{
#region Variables
private AppMenu _currentMenuItem;
private List<AppMenu> _menuItems;
private List<AppMenu> _subMenuItems;
private ObservableCollection<AppMenu> _historyItems;
private string _context;
private MainView _view;
private Dictionary<Type, BaseModel> _models;
#endregion
#region Menus
public string NowDateTime { get; set; }
private bool _IsLogin = false;
private bool _isLogin = false;
public bool IsLogin
{
get => _IsLogin;
set { _IsLogin = value; NotifyOfPropertyChange(); }
get => _isLogin;
set { _isLogin = value; NotifyOfPropertyChange(); }
}
private List<Role> roles;
private List<Role> _roles;
public List<Role> Roles
{
get => roles;
set { roles = value; RaisePropertyChangedEventImmediately("Roles"); }
get => _roles;
set { _roles = value; RaisePropertyChangedEventImmediately("Roles"); }
}
private ICommand menuItemClickCommand;
private ICommand _menuItemClickCommand;
public ICommand MenuItemClickCommand
{
get
{
if (menuItemClickCommand == null)
menuItemClickCommand = new BaseCommand<AppMenu>((AppMenu menuViewItem) => SwitchMenuItem(menuViewItem));
return menuItemClickCommand;
if (_menuItemClickCommand == null)
_menuItemClickCommand = new BaseCommand<AppMenu>(SwitchMenuItem);
return _menuItemClickCommand;
}
}
private ICommand mainmenuItemClickCommand;
private ICommand _mainMenuItemClickCommand;
public ICommand MainMenuItemClickCommand
{
get
{
if (mainmenuItemClickCommand == null)
mainmenuItemClickCommand = new BaseCommand<AppMenu>((AppMenu menuViewItem) => MainSwitchMenuItem(menuViewItem));
return mainmenuItemClickCommand;
if (_mainMenuItemClickCommand == null)
_mainMenuItemClickCommand = new BaseCommand<AppMenu>(MainSwitchMenuItem);
return _mainMenuItemClickCommand;
}
}
public List<AppMenu> MenuItems
{
get => menuItems;
set { menuItems = value; NotifyOfPropertyChange(); }
get => _menuItems;
set { _menuItems = value; NotifyOfPropertyChange(); }
}
public List<AppMenu> SubMenuItems
{
get => subMenuItems;
set { subMenuItems = value; NotifyOfPropertyChange(); }
get => _subMenuItems;
set { _subMenuItems = value; NotifyOfPropertyChange(); }
}
public ObservableCollection<AppMenu> HistoryMenus
{
get => historyItems;
set { historyItems = value; NotifyOfPropertyChange(); }
get => _historyItems;
set { _historyItems = value; NotifyOfPropertyChange(); }
}
public string Context
{
get => context;
set { context = value; NotifyOfPropertyChange(); }
get => _context;
set { _context = value; NotifyOfPropertyChange(); }
}
public BaseModel CurrentViewModel { get; private set; }
public UserContext User => BaseApp.Instance.UserContext;
private AppMenu _currentMenuItem;
private List<AppMenu> menuItems;
private List<AppMenu> subMenuItems;
private ObservableCollection<AppMenu> historyItems;
private string context;
private MainView _view;
private Dictionary<Type, BaseModel> _models;
#endregion
public BaseModel CurrentViewModel { get; private set; }
public bool IsPM1Installed { get; set; }
public bool IsPM2Installed { get; set; }
@ -128,6 +134,18 @@ namespace SicUI.Client
public int LogoutTime { get; set; }
private bool _isReadOnlyMode;
public bool IsReadOnlyMode
{
get => _isReadOnlyMode;
set
{
_isReadOnlyMode = value;
NotifyOfPropertyChange();
}
}
//public ObservableCollection<EventItem> WarnEventLogList { get; set; }
private DelayedPresentRollingObservableCollection<EventItem> EventLogList { get; }
@ -179,32 +197,6 @@ namespace SicUI.Client
public string RtStatus { get; set; }
public string RtStatusBackground => ModuleStatusBackground.GetStatusBackground(RtStatus);
[Subscription("System.ControlStatus")]
public string ControlStatus { get; set; }
[Subscription("System.CommunicationStatus")]
public string HostStatus { get; set; }
public string HostStatusBackground
{
get
{
switch (HostStatus)
{
case "Disabled":
return "Yellow";
case "Enabled":
case "EnabledNotCommunicating":
case "WaitCRA":
case "WaitDelay":
case "WaitCRFromHost":
return "Transparent";
case "EnabledCommunicating":
return "LawnGreen";
default:
return "Yellow";
}
}
}
[Subscription("PM1.Status")]
public string _PM1Status { get; set; }
@ -388,16 +380,16 @@ namespace SicUI.Client
{
AllEventsVisibility = Visibility.Hidden;
WarnEventsVisibility = Visibility.Visible;
NotifyOfPropertyChange("AllEventsVisibility");
NotifyOfPropertyChange("WarnEventsVisibility");
NotifyOfPropertyChange(nameof(AllEventsVisibility));
NotifyOfPropertyChange(nameof(WarnEventsVisibility));
}
public void ShowAllEvents()
{
AllEventsVisibility = Visibility.Visible;
WarnEventsVisibility = Visibility.Hidden;
NotifyOfPropertyChange("AllEventsVisibility");
NotifyOfPropertyChange("WarnEventsVisibility");
NotifyOfPropertyChange(nameof(AllEventsVisibility));
NotifyOfPropertyChange(nameof(WarnEventsVisibility));
}
private void Instance_OnEvent(EventItem evt)
@ -413,7 +405,7 @@ namespace SicUI.Client
case EventType.KickOut_Notify:
if (evt.Description == "ShutDown")
{
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.LoginName, BaseApp.Instance.UserContext.SessionId);
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.Token);
ShutdownThread = ShutdownExecute;
ShutdownThread.BeginInvoke(ShutdownCallBack, ShutdownThread);
}
@ -423,10 +415,25 @@ namespace SicUI.Client
if (evt.Tag is Credential cred)
{
if (cred.LoginName == BaseApp.Instance.UserContext.LoginName
|| cred.Token == BaseApp.Instance.UserContext.SessionId)
|| cred.Token == BaseApp.Instance.UserContext.Token)
{
//TODO 权限降级,仅查看模式
Execute.OnUIThread(Logout);
Execute.OnUIThread(()=>
{
var ret = DialogBox.ShowDialog(
DialogButton.Yes | DialogButton.No,
DialogType.INFO,
"Some users is logging into the system, you will be forced to switch to read-only mode, do you agree?");
if (ret == DialogButton.Yes)
{
Logoff();
User.LoginName = "Read-Only";
// 降级为仅查看模式
IsReadOnlyMode = true;
}
});
}
}
break;
@ -455,6 +462,118 @@ namespace SicUI.Client
Login(loginName, password, role);
}
private bool _isShowRequestLoginIndicator;
public bool IsShowRequestLoginIndicator
{
get=>_isShowRequestLoginIndicator;
set
{
_isShowRequestLoginIndicator = value;
NotifyOfPropertyChange();
}
}
private string _requestLoginIndicatorText;
public string RequestLoginIndicatorText
{
get => _requestLoginIndicatorText;
set
{
_requestLoginIndicatorText = value;
NotifyOfPropertyChange();
}
}
private Task<LoginRequestResults> _loginTask;
private CancellationTokenSource _ctsWaitingTask;
public void CancelRequestLogin()
{
AccountClient.Instance.Service.CancelLoginRequest();
}
public Task ShowRequestLoginIndicator()
{
return Task.Run(() =>
{
try
{
_ctsWaitingTask = new CancellationTokenSource();
var token = _ctsWaitingTask.Token;
var endTime = DateTime.Now.AddSeconds(30);
// 如果超过一定时间没有从RT返回确认信息则显示登录中的提示
Thread.Sleep(500);
if (token.IsCancellationRequested)
return;
Execute.OnUIThread(() => IsShowRequestLoginIndicator = true);
while (true)
{
var remained = (endTime - DateTime.Now).TotalSeconds;
if (remained <= 0)
break;
Execute.OnUIThread(() =>
RequestLoginIndicatorText =
$"Waiting for RT to confirm login request, {remained:0.0}s remained");
Thread.Sleep(100);
if (token.IsCancellationRequested)
break;
}
}
finally
{
Execute.OnUIThread(() =>
{
RequestLoginIndicatorText = "Waiting for RT to confirm login request, 0s remained";
IsShowRequestLoginIndicator = false;
});
}
});
}
public async void RequestLogin(string loginName, PasswordBox password, Role role)
{
if (_loginTask is { Status: TaskStatus.Running })
return;
Task taskWaiting = default;
// 向RT请求登录
try
{
taskWaiting =ShowRequestLoginIndicator();
_loginTask = AccountClient.Instance.Service.RequestLogin();
await Task.WhenAny(_loginTask, taskWaiting);
_ctsWaitingTask.Cancel();
if (taskWaiting.Status == TaskStatus.RanToCompletion)
{
DialogBox.ShowError("Login failed, timeout of waiting login request confirmation.");
}
else if (_loginTask.Status == TaskStatus.RanToCompletion)
{
if (_loginTask.Result == LoginRequestResults.Rejected)
DialogBox.ShowError("Login failed, rejected by RT.");
else
Login(loginName, password, role);
}
}
catch (InvalidOperationException ex)
{
}
}
public void Login(string loginName, PasswordBox password, Role role)
{
try
@ -470,13 +589,13 @@ namespace SicUI.Client
BaseApp.Instance.UserContext.LoginName = loginName;
BaseApp.Instance.UserContext.Role = role;
BaseApp.Instance.UserContext.LoginTime = result.LoginTime;
BaseApp.Instance.UserContext.SessionId = result.SessionId;
BaseApp.Instance.UserContext.Token = result.Token;
BaseApp.Instance.UserContext.LastAccessTime = DateTime.Now;
BaseApp.Instance.UserContext.IsLogin = true;
//Load menu by role
//filer menu if necessary...
BaseApp.Instance.MenuManager.LoadMenu(RoleAccountProvider.Instance.GetMenusByRole(role.RoleId, BaseApp.Instance.MenuLoader.MenuList));
BaseApp.Instance.MenuManager.LoadMenu(RoleAccountProvider.Instance.GetMenusByRole(role.RoleId));
IsAutoLogout = role.IsAutoLogout;
LogoutTime = role.LogoutTime;
@ -486,9 +605,9 @@ namespace SicUI.Client
InitMenu(); //bind menu to main view
IsLogin = true; //control the display logic of main view
IsReadOnlyMode = false;
LOG.Info(string.Format("{0} login as {1}", loginName, role.RoleName));
LOG.Info($"{loginName} login as {role.RoleName}");
}
else
{
@ -550,39 +669,50 @@ namespace SicUI.Client
public void OnLogoutCommand()
{
WindowManager windowmanager = new WindowManager();
var logoffViewmodel = new LogoffViewModel();
windowmanager.ShowDialog(logoffViewmodel);
BaseApp.Instance.UserMode = logoffViewmodel.DialogResult;
switch (logoffViewmodel.DialogResult)
if (!IsReadOnlyMode)
{
case UserMode.Logoff:
Logoff();
break;
case UserMode.Exit:
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.LoginName, BaseApp.Instance.UserContext.SessionId);
var windowManager = new WindowManager();
var logoffViewmodel = new LogoffViewModel();
windowManager.ShowDialog(logoffViewmodel);
BaseApp.Instance.UserMode = UserMode.Exit;
LOG.Info(
$"{BaseApp.Instance.UserContext.LoginName} exit as {BaseApp.Instance.UserContext.Role.RoleName}");
BaseApp.Instance.UserMode = logoffViewmodel.DialogResult;
TryClose();
break;
case UserMode.Shutdown:
//配置立即生效。
string roleID2 = BaseApp.Instance.UserContext.Role.RoleId;
bool canShutDown = RoleAccountProvider.Instance.GetMenuPermission(roleID2, "Operation.Behaviour.ShutDown") == 3;
if (canShutDown)
InvokeClient.Instance.Service.DoOperation("System.ShutDown");
else
{
DialogBox.ShowError("No Permission for ShutDown");
}
break;
switch (logoffViewmodel.DialogResult)
{
case UserMode.Logoff:
Logoff();
break;
case UserMode.Exit:
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.Token);
BaseApp.Instance.UserMode = UserMode.Exit;
LOG.Info(
$"{BaseApp.Instance.UserContext.LoginName} exit as {BaseApp.Instance.UserContext.Role.RoleName}");
TryClose();
break;
case UserMode.Shutdown:
//配置立即生效。
var roleID2 = BaseApp.Instance.UserContext.Role.RoleId;
var canShutDown =
RoleAccountProvider.Instance.GetMenuPermission(roleID2, "Operation.Behaviour.ShutDown") ==
3;
if (canShutDown)
InvokeClient.Instance.Service.DoOperation("System.ShutDown");
else
{
DialogBox.ShowError("No Permission for ShutDown");
}
break;
}
_eventAggregator.PublishOnUIThread(logoffViewmodel.DialogResult);
}
else
{
Logoff();
}
_eventAggregator.PublishOnUIThread(logoffViewmodel.DialogResult);
}
public void Logoff()
@ -592,9 +722,9 @@ namespace SicUI.Client
{
try
{
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.LoginName, BaseApp.Instance.UserContext.SessionId);
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.Token);
BaseApp.Instance.UserContext.IsLogin = false;
BaseApp.Instance.UserContext.Clear();
LOG.Info(
$"{BaseApp.Instance.UserContext.LoginName} logoff as {BaseApp.Instance.UserContext.Role.RoleName}");
}
@ -642,12 +772,9 @@ namespace SicUI.Client
base.OnInitialize();
StartTimer();
DrawSciChart();
if (Debugger.IsAttached)
{
Login("admin", new PasswordBox() { Password = "admin" }, new Role("0", "Manager", false, 1000, ""));
Login("admin", new PasswordBox() { Password = "admin" }, new Role("0", "Manager", false, 1000, null));
}
}
@ -659,30 +786,6 @@ namespace SicUI.Client
}
void DrawSciChart()
{
// Create the chart surface
var sciChartSurface = new SciChartSurface();
// Create the X and Y Axis
var xAxis = new NumericAxis() { AxisTitle = "Number of Samples (per series)" };
var yAxis = new NumericAxis() { AxisTitle = "Value" };
sciChartSurface.XAxis = xAxis;
sciChartSurface.YAxis = yAxis;
// Specify Interactivity Modifiers
sciChartSurface.ChartModifier = new ModifierGroup(new RubberBandXyZoomModifier(), new ZoomExtentsModifier());
// Add annotation hints to the user
var textAnnotation = new TextAnnotation()
{
Text = "Hello World!",
X1 = 5.0,
Y1 = 5.0
};
sciChartSurface.Annotations.Add(textAnnotation);
}
protected override void OnViewLoaded(object view)
{
base.OnViewLoaded(view);
@ -754,49 +857,45 @@ namespace SicUI.Client
public void MainSwitchMenuItem(AppMenu menuViewItem)
{
if (menuViewItem.MenuItems.Count > 0)
{
if (menuViewItem.LastSelectedSubMenu != null)
SwitchMenuItem(menuViewItem.LastSelectedSubMenu);
else
SwitchMenuItem(menuViewItem.MenuItems[0]);
}
if (menuViewItem.MenuItems.Count <= 0)
return;
SwitchMenuItem(menuViewItem.LastSelectedSubMenu ?? menuViewItem.MenuItems[0]);
}
public void SwitchMenuItem(AppMenu menuViewItem)
{
if (menuViewItem.ViewModel != null && menuViewItem.ViewModel != string.Empty)
if (string.IsNullOrEmpty(menuViewItem.ViewModel))
return;
if (menuViewItem.Model == null)
{
if (menuViewItem.Model == null)
{
menuViewItem.Model = (BaseModel)AssemblyUtil.CreateInstance(AssemblyUtil.GetType(menuViewItem.ViewModel));
((BaseModel)menuViewItem.Model).Permission = menuViewItem.Permission;
((BaseModel)menuViewItem.Model).Token = BaseApp.Instance.UserContext.Token;
menuViewItem.Model = (BaseModel)AssemblyUtil.CreateInstance(AssemblyUtil.GetType(menuViewItem.ViewModel));
((BaseModel)menuViewItem.Model).Permission = menuViewItem.Permission;
// ((BaseModel)menuViewItem.Model).Token = BaseApp.Instance.UserContext.Token;
if (menuViewItem.Model is ISupportMultipleSystem)
(menuViewItem.Model as ISupportMultipleSystem).SystemName = menuViewItem.System;
}
ActivateItem(((BaseModel)menuViewItem.Model));
CurrentViewModel = ((BaseModel)menuViewItem.Model);
//if (((BaseModel)menuViewItem.Model).Page != PageID.MAX_PAGE)
// BaseApp.Instance.SetCurrentPage(((BaseModel)menuViewItem.Model).Page);
HandleSubAndHistoryMenu(menuViewItem);
if (_currentMenuItem != null)
{
_currentMenuItem.Selected = false;
_currentMenuItem.Parent.Selected = false;
}
menuViewItem.Selected = true;
menuViewItem.Parent.Selected = true;
menuViewItem.Parent.LastSelectedSubMenu = menuViewItem;
_currentMenuItem = menuViewItem;
if (menuViewItem.Model is ISupportMultipleSystem smsViewModel)
smsViewModel.SystemName = menuViewItem.System;
}
ActivateItem(((BaseModel)menuViewItem.Model));
CurrentViewModel = ((BaseModel)menuViewItem.Model);
//if (((BaseModel)menuViewItem.Model).Page != PageID.MAX_PAGE)
// BaseApp.Instance.SetCurrentPage(((BaseModel)menuViewItem.Model).Page);
HandleSubAndHistoryMenu(menuViewItem);
if (_currentMenuItem != null)
{
_currentMenuItem.Selected = false;
_currentMenuItem.Parent.Selected = false;
}
menuViewItem.Selected = true;
menuViewItem.Parent.Selected = true;
menuViewItem.Parent.LastSelectedSubMenu = menuViewItem;
_currentMenuItem = menuViewItem;
}
private void HandleSubAndHistoryMenu(AppMenu menuitem)
@ -816,15 +915,15 @@ namespace SicUI.Client
}
}
public bool SwitchPage(string firstLevelMenuID, string secondLevelMenuID)
public bool SwitchPage(string firstLevelMenuId, string secondLevelMenuId)
{
foreach (AppMenu menuitem in BaseApp.Instance.MenuManager.MenuItems)
foreach (var menuitem in BaseApp.Instance.MenuManager.MenuItems)
{
if (menuitem.MenuID == firstLevelMenuID)
if (menuitem.MenuID == firstLevelMenuId)
{
foreach (AppMenu menu in menuitem.MenuItems)
foreach (var menu in menuitem.MenuItems)
{
if (menu.MenuID == secondLevelMenuID)
if (menu.MenuID == secondLevelMenuId)
{
SwitchMenuItem(menu);
return true;
@ -875,14 +974,14 @@ namespace SicUI.Client
DispatcherTimer myDispatcherTimer =
new DispatcherTimer();
myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
myDispatcherTimer.Tick += new EventHandler(Each_Tick);
myDispatcherTimer.Tick += Each_Tick;
myDispatcherTimer.Start();
}
public void Each_Tick(object o, EventArgs sender)
{
NowDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
NotifyOfPropertyChange("NowDateTime");
NotifyOfPropertyChange(nameof(NowDateTime));
}
#endregion
#endregion

View File

@ -14,6 +14,7 @@ using System.Data;
using Aitex.Core.RT.Event;
using System.Dynamic;
using Caliburn.Micro.Core;
using MECF.Framework.Common.Account;
namespace SicUI.Models.Operations.Overviews
{

View File

@ -129,9 +129,6 @@
<Reference Include="WPFToolkit">
<HintPath>..\ThirdParty\MECF.Framework\WPFToolkit.dll</HintPath>
</Reference>
<Reference Include="Xceed.Wpf.Toolkit">
<HintPath>..\ThirdParty\MECF.Framework\Xceed.Wpf.Toolkit.dll</HintPath>
</Reference>
<Reference Include="Xceed.Wpf.Toolkit, Version=3.6.0.0, Culture=neutral, PublicKeyToken=3e4669d2f30244f4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\dlls\Xceed.Wpf.Toolkit.dll</HintPath>
@ -216,6 +213,7 @@
<Compile Include="Controls\WaferAssociationUnitLite.xaml.cs">
<DependentUpon>WaferAssociationUnitLite.xaml</DependentUpon>
</Compile>
<Compile Include="Converter\IsReadOnlyModeToUserInfoNameBgConverter.cs" />
<Compile Include="GlobalUsings.cs" />
<Compile Include="Models\Maintenances\RuntimeView.xaml.cs">
<DependentUpon>RuntimeView.xaml</DependentUpon>
@ -645,12 +643,6 @@
<ItemGroup>
<Resource Include="Themes\Images\parts\atmrobot\image02.png" />
</ItemGroup>
<ItemGroup>
<None Include="Config\Menu.xml">
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Resource Include="Themes\Images\parts\image15.png" />
</ItemGroup>
@ -847,12 +839,6 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Modules\SicModules\SicModules.csproj">
<Project>{424e9610-fa50-49cd-b5be-baf256dbf327}</Project>
<Name>SicModules</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Images\interlock_bypass_watermark.png" />
</ItemGroup>