77个文件已修改
40个文件已添加
4个文件已删除
| | |
| | | <ItemGroup> |
| | | <Compile Include="StepSender.cs" /> |
| | | <Compile Include="TcpClientTool.cs" /> |
| | | <Compile Include="TcpClientTool3.cs" /> |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | </ItemGroup> |
| | | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| | |
| | | // 生成号 |
| | | // 修订号 |
| | | // |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.0")] |
| | | [assembly: AssemblyVersion("1.0.0.1")] |
| | | [assembly: AssemblyFileVersion("1.0.0.1")] |
| | |
| | | { |
| | | |
| | | errorMsg = null; |
| | | TcpClientTool client = null; |
| | | TcpClientTool3 client = null; |
| | | try |
| | | { |
| | | client = new TcpClientTool(ip, port); |
| | | client = new TcpClientTool3(ip, port); |
| | | string res = null; |
| | | client.ExecuteMessageChanged += (sender, data) => |
| | | { |
| New file |
| | |
| | | using System; |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | |
| | | namespace CellStepSender |
| | | { |
| | | public class TcpClientTool3 |
| | | { |
| | | private string _ip; |
| | | private int _port; |
| | | private bool _isConnected = false; // 是否连接 |
| | | private Socket _clientSocket; // 套接字 |
| | | |
| | | public event EventHandler<string> ExecuteMessageChanged; |
| | | |
| | | public TcpClientTool3(string ip, int port) |
| | | { |
| | | this._ip = ip; |
| | | this._port = port; |
| | | } |
| | | |
| | | public void Connect() |
| | | { |
| | | try |
| | | { |
| | | _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); |
| | | IPAddress ipaddress = IPAddress.Parse(this._ip); |
| | | IPEndPoint endpoint = new IPEndPoint(ipaddress, _port); |
| | | _clientSocket.Connect(endpoint); |
| | | _isConnected = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _clientSocket.Dispose(); |
| | | _isConnected = false; |
| | | throw ex; |
| | | } |
| | | } |
| | | |
| | | public void Disconnect() |
| | | { |
| | | _clientSocket.Dispose(); |
| | | } |
| | | |
| | | public void Send(string data) |
| | | { |
| | | byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(data); |
| | | lock (this) |
| | | { |
| | | _clientSocket.Send(arrClientSendMsg); |
| | | } |
| | | } |
| | | |
| | | public bool SendStep( |
| | | string ip, int port, |
| | | int ovenIndex, int cellIndex, string step, string value, string limitUp, |
| | | string limitDown, string unit, string result, string updateTime, out string errorMsg) |
| | | { |
| | | |
| | | errorMsg = null; |
| | | try |
| | | { |
| | | if (!_isConnected) |
| | | { |
| | | errorMsg = "Not Connected"; |
| | | return false; |
| | | } |
| | | |
| | | string msg = $"{ovenIndex};{cellIndex};{step},{value},{limitUp},{limitDown},{unit},{result},{updateTime}\n"; |
| | | Send(msg); |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | errorMsg = ex.Message; |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | { |
| | | try |
| | | { |
| | | AlarmTexts = XmlHelper.DeserializeFromXml<ObservableCollection<AlarmText>>(alarmTextPath); |
| | | if (string.IsNullOrEmpty(alarmTextPath) || !File.Exists(alarmTextPath)) |
| | | { |
| | | AlarmTexts = new ObservableCollection<AlarmText>(); |
| | | } |
| | | else |
| | | { |
| | | AlarmTexts = XmlHelper.DeserializeFromXml<ObservableCollection<AlarmText>>(alarmTextPath); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | AlarmTexts = new ObservableCollection<AlarmText>(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private void UserControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | |
| | | Loaded -= UserControl_Loaded; |
| | | } |
| | | |
| | | public override void DoClose(object sender, EventArgs e) |
| | | { |
| | | // AlarmUtil.OnAlarm -= AlarmUtil_OnAlarm; |
| | | } |
| | | |
| | | //private void MonitorTimer_Elapsed_bak(object sender, ElapsedEventArgs e) |
| | | //{ |
| | | // try |
| | |
| | | <Generator>ResXFileCodeGenerator</Generator> |
| | | <LastGenOutput>Resources.Designer.cs</LastGenOutput> |
| | | </EmbeddedResource> |
| | | <None Include="app.config" /> |
| | | <None Include="packages.config" /> |
| | | <None Include="Properties\Settings.settings"> |
| | | <Generator>SettingsSingleFileGenerator</Generator> |
| | |
| | | public string Name { get; set; } |
| | | [ExcelColumn("设置项类型")] |
| | | public string Type { get; set; } |
| | | |
| | | [ExcelColumn("是否为数组")] |
| | | public bool IsArray { get; set; } = false; |
| | | |
| | | [ExcelColumn("数组长度")] |
| | | public int Length { get; set; } = 1; |
| | | |
| | | [ExcelColumn("值")] |
| | | public string Value { get; set; } |
| | | [ExcelColumn("单位")] |
| | |
| | | { |
| | | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | /// "{size},{基准值},{最小值},{最大值}" |
| | | if (parameter == null) return 15; |
| | | |
| | | string[] ps = parameter.ToString().Split(','); |
| | |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using System.Collections.Generic; |
| | | using System.IO; |
| | |
| | | /// </summary> |
| | | public class ProductManager |
| | | { |
| | | public static string GetFolder() |
| | | { |
| | | if (ParamSetting.ShareConfig != null) |
| | | { |
| | | return Path.Combine(ParamSetting.ShareConfig, "Product"); |
| | | } |
| | | return Path.Combine(PathHelper.ConfigFolder, "Product"); |
| | | } |
| | | |
| | | public static string GetDataFilePath() |
| | | { |
| | | return Path.Combine(GetFolder(), "Product.data"); |
| | | } |
| | | |
| | | public static string GetParamFolderByProductName(string productName) |
| | | { |
| | | return Path.Combine(GetFolder(), "Parameter", $"Parameter_{productName}.data"); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取保存的产品 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public static T GetProducts<T>() where T : IList<ProductData> |
| | | { |
| | | string path = PathHelper.ProductDataFile; |
| | | string path = GetDataFilePath(); |
| | | if (!File.Exists(path)) return default(T); |
| | | T datas = XmlHelper.DeserializeFromXml<T>(path); |
| | | return datas; |
| | |
| | | /// <returns></returns> |
| | | public static T GetParametersByProductName<T>(string productName) where T : IList<ParameterData> |
| | | { |
| | | string path = Path.Combine(PathHelper.ProductParameterFolder, $"Parameter_{productName}.data"); |
| | | string path = GetParamFolderByProductName(productName); |
| | | if (!File.Exists(path)) return default(T); |
| | | T datas = XmlHelper.DeserializeFromXml<T>(path); |
| | | return datas; |
| | |
| | | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 |
| | | //通过使用 "*",如下所示: |
| | | // [assembly: AssemblyVersion("1.0.*")] |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.0")] |
| | | [assembly: AssemblyVersion("1.0.0.1")] |
| | | [assembly: AssemblyFileVersion("1.0.0.1")] |
| | |
| | | /// 启用扫码换型 |
| | | /// </summary> |
| | | public static bool EnableAutoModel { get; private set; } = false; |
| | | public static string ShareConfig { get; private set; } = null; |
| | | public static bool ShowBurnInAbort { get; private set; } = true; |
| | | public static string SocketNames { get; private set; } = string.Empty; |
| | | |
| | | static ParamSetting() |
| | | { |
| | |
| | | { |
| | | |
| | | } |
| | | |
| | | try |
| | | { |
| | | ShareConfig = ParameterManager.GetCommonParameterByName<string>("ShareConfig", null); |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | |
| | | try |
| | | { |
| | | ShowBurnInAbort = ParameterManager.GetCommonParameterByName<bool>("ShowBurnInAbort", true); |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | |
| | | try |
| | | { |
| | | SocketNames = ParameterManager.GetCommonParameterByName<string>("SocketNames", string.Empty); |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | namespace HMI.Core.Util |
| | | { |
| | | public class HexUtil |
| | | { |
| | | public static byte[] ToBytesFromHexString(string hexString) |
| | | { |
| | | //以 ' ' 分割字符串,并去掉空字符 |
| | | string[] chars = hexString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); |
| | | byte[] returnBytes; |
| | | returnBytes = BitConverter.GetBytes(Convert.ToInt32(chars[0])); |
| | | return returnBytes; |
| | | } |
| | | } |
| | | //public class HexUtil |
| | | //{ |
| | | // public static byte[] ToBytesFromHexString(string hexString) |
| | | // { |
| | | // //以 ' ' 分割字符串,并去掉空字符 |
| | | // string[] chars = hexString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); |
| | | // byte[] returnBytes; |
| | | // returnBytes = BitConverter.GetBytes(Convert.ToInt32(chars[0])); |
| | | // return returnBytes; |
| | | // } |
| | | //} |
| | | } |
| | |
| | | /// </summary> |
| | | public static string ParameterDataPath { get; private set; } |
| | | |
| | | /// <summary> |
| | | /// 产品数据目录 |
| | | /// </summary> |
| | | public static string ProductDataFolder { get; private set; } |
| | | public static string ProductParameterFolder { get; private set; } |
| | | |
| | | /// <summary> |
| | | /// 产品数据源文件 |
| | | /// </summary> |
| | | public static string ProductDataFile { get; private set; } |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// 测试项数据目录 |
| | |
| | | ParameterFolder = InitFolder(ConfigFolder + "\\Parameter"); |
| | | ParameterDataPath = ParameterFolder + "\\CommonParameter.data"; |
| | | |
| | | ProductDataFolder = InitFolder(ConfigFolder + "\\Product"); |
| | | ProductParameterFolder = InitFolder(ProductDataFolder + "\\Parameter"); |
| | | ProductDataFile = ProductDataFolder + "\\Product.data"; |
| | | //ProductDataFolder = InitFolder(ConfigFolder + "\\Product"); |
| | | //ProductParameterFolder = InitFolder(ProductDataFolder + "\\Parameter"); |
| | | //ProductDataFile = ProductDataFolder + "\\Product.data"; |
| | | |
| | | TestItemDataFolder = InitFolder(ProductDataFolder + "\\TestItem"); |
| | | // TestItemDataFolder = InitFolder(ProductDataFolder + "\\TestItem"); |
| | | TestItemDataFile = TestItemDataFolder + "\\TestItem.data"; |
| | | |
| | | LogViewerDir = InitFolder(ConfigFolder + "\\LogViewer"); |
| | |
| | | } |
| | | } |
| | | |
| | | public long InsertWithId(string Sql) |
| | | { |
| | | try |
| | | { |
| | | if (Sql.EndsWith(";")) |
| | | { |
| | | Sql += "SELECT last_insert_rowid();"; |
| | | } |
| | | else |
| | | { |
| | | Sql += ";SELECT last_insert_rowid();"; |
| | | } |
| | | using (var cmd = new SQLiteCommand(Sql, conn)) |
| | | { |
| | | return (long)cmd.ExecuteScalar(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | string message = "ExecuteSql Error:" + ex.Message; |
| | | throw new Exception(message); |
| | | } |
| | | } |
| | | |
| | | public object SelectOne(string Sql) |
| | | { |
| | | try |
| | | { |
| | | using (var cmd = new SQLiteCommand(Sql, conn)) |
| | | { |
| | | return cmd.ExecuteScalar(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | string message = "ExecuteSql Error:" + ex.Message; |
| | | throw new Exception(message); |
| | | } |
| | | } |
| | | |
| | | public int ExecuteBatch(IEnumerable<string> sqls) |
| | | { |
| | | SQLiteTransaction tr = null; |
| | |
| | | using HMI.Base; |
| | | using HMI.Core.Util; |
| | | using HMI.DataViewer.Entity; |
| | | using HMI.UI.Converter; |
| | | using HMI.UI.Util; |
| | | using NPOI.SS.Formula.Functions; |
| | | using NPOI.SS.UserModel; |
| | |
| | | |
| | | namespace HMI.DataViewer |
| | | { |
| | | public class DefaultValueConverter : IValueConverter |
| | | { |
| | | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | if (value is DateTime date) |
| | | { |
| | | return date.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | } |
| | | return value.ToString(); |
| | | } |
| | | |
| | | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | return value; |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// UserControl1.xaml 的交互逻辑 |
| | |
| | | } |
| | | |
| | | private Dictionary<string, DataBase_Setting> Map = new Dictionary<string, DataBase_Setting>(); |
| | | |
| | | private IValueConverter defaultConverter = new DefaultValueConverter(); |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | | { |
| | |
| | | Header = header, |
| | | Binding = new System.Windows.Data.Binding(bindingPath) |
| | | { |
| | | Converter = defaultConverter |
| | | Converter = DateStrConverter.Instance |
| | | }, |
| | | Width = new DataGridLength(1, DataGridLengthUnitType.Star) |
| | | }; |
| | |
| | | <StackPanel DockPanel.Dock="Right" Style="{StaticResource ButtonGroup}"> |
| | | <Button Style="{StaticResource QueryBtn}" |
| | | x:Name="queryBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource RfhBtn}" |
| | | <Button Style="{StaticResource ResetBtn}" |
| | | x:Name="resetBtn" Click="Button_Click"/> |
| | | <!--<Button x:Name="exportBtn" |
| | | Style="{StaticResource ExportBtn}" Click="Button_Click"/>--> |
| | |
| | | <ComboBoxItem Content="Error"/> |
| | | </ComboBox> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="14" Text="{DynamicResource App.StartTime}"/> |
| | | <pu:DateTimePicker Style="{StaticResource TimePicker}" x:Name="startTimeInput"/> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="14" Text="{DynamicResource App.EndTime}"/> |
| | | <pu:DateTimePicker Style="{StaticResource TimePicker}" x:Name="endTimeInput"/> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="14" Text="{DynamicResource log.source}"/> |
| | | <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="sourceInput" Width="180"/> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="14" Text="{DynamicResource App.StartTime}"/> |
| | | <pu:DateTimePicker Style="{StaticResource TimePicker}" IsEnabled="{Binding AutoRfh,Converter={StaticResource reverseBool}}" |
| | | x:Name="startTimeInput"/> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="14" Text="{DynamicResource App.EndTime}"/> |
| | | <pu:DateTimePicker Style="{StaticResource TimePicker}" IsEnabled="{Binding AutoRfh,Converter={StaticResource reverseBool}}" |
| | | x:Name="endTimeInput"/> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="14" Text="{DynamicResource log.autoRefresh}"/> |
| | | <CheckBox x:Name="autoRfhInput" HorizontalAlignment="Center" VerticalAlignment="Center" |
| | |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock VerticalAlignment="Center" Text="{Binding time}"/> |
| | | <TextBlock VerticalAlignment="Center" Text="{Binding time,Converter={x:Static uic:DateStrConverter.Instance},ConverterParameter='yyyy-MM-dd HH:mm:ss.fff'}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | |
| | | <GridViewColumn Width="1420"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource log.text}"/> |
| | |
| | | </ListView.View> |
| | | </ListView> |
| | | |
| | | <StackPanel Grid.Row="3" HorizontalAlignment="Right"> |
| | | <pu:Pagination Style="{StaticResource DefaultPage}" |
| | | CurrentPage="{Binding CurrentPage}" |
| | | MaxPage="{Binding MaxPage}"/> |
| | | </StackPanel> |
| | | |
| | | <!--<DataGrid Grid.Row="2" x:Name="table" |
| | | CellStyle="{StaticResource sbCell}" |
| | | RowHeight="{StaticResource nanD}" Style="{StaticResource DefaultDataGrid}"> |
| | |
| | | |
| | | private Timer autoRfhTimer; |
| | | |
| | | private int currentPage = 1; |
| | | public int CurrentPage |
| | | private long pageSize = 50; |
| | | |
| | | private long currentPage = 1; |
| | | public long CurrentPage |
| | | { |
| | | get => currentPage; |
| | | set |
| | | { |
| | | Set(ref currentPage, value); |
| | | Filtrate(value, pageSize); |
| | | } |
| | | } |
| | | |
| | | private int maxPage = 0; |
| | | public int MaxPage |
| | | private long maxPage = 1; |
| | | public long MaxPage |
| | | { |
| | | get => maxPage; |
| | | set |
| | | { |
| | | Set(ref currentPage, value); |
| | | Set(ref maxPage, value); |
| | | } |
| | | } |
| | | |
| | |
| | | }; |
| | | autoRfhTimer.Elapsed += AutoRfhTimer_Elapsed; |
| | | InitializeComponent(); |
| | | QueryReset(); |
| | | } |
| | | |
| | | public override void InitFinish() |
| | |
| | | //} |
| | | } |
| | | |
| | | |
| | | private void UserControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | Loaded -= UserControl_Loaded; |
| | |
| | | { |
| | | Refresh100items(); |
| | | } |
| | | |
| | | //private void RefreshTable() { |
| | | // if(CurrentPage == ) |
| | | //} |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | | { |
| | |
| | | break; |
| | | case "resetBtn": |
| | | QueryReset(); |
| | | CurrentPage = 1; |
| | | break; |
| | | case "exportBtn": |
| | | DoExport(); |
| | |
| | | return; |
| | | } |
| | | |
| | | queryBtn.IsEnabled = false; |
| | | autoRfhInput.IsEnabled = false; |
| | | Filtrate(); |
| | | AutoRfh = false; |
| | | //queryBtn.IsEnabled = false; |
| | | //autoRfhInput.IsEnabled = false; |
| | | CurrentPage = 1; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | |
| | | private void QueryReset() |
| | | { |
| | | var today = DateTime.Now; |
| | | var start = DateTime.Parse(today.ToString("yyyy-MM-dd 00:00:00")).AddDays(-7); |
| | | var end = DateTime.Parse(today.ToString("yyyy-MM-dd 00:00:00")).AddDays(1); |
| | | |
| | | levelInput.Text = null; |
| | | startTimeInput.SelectedDateTime = null; |
| | | endTimeInput.SelectedDateTime = null; |
| | | startTimeInput.Text = null; |
| | | table.ItemsSource = null; |
| | | startTimeInput.SelectedDateTime = start; |
| | | endTimeInput.SelectedDateTime = end; |
| | | } |
| | | |
| | | private void Filtrate() |
| | | private void Filtrate(long page, long size) |
| | | { |
| | | string str = LoadSql(); |
| | | DataTable dt = new DataTable(); |
| | | var files = GetOldDbFiles(PathHelper.LogViewerDir, new DateTime?[] { startTimeInput.SelectedDateTime, |
| | | try |
| | | { |
| | | var files = GetOldDbFiles(PathHelper.LogViewerDir, new DateTime?[] { startTimeInput.SelectedDateTime, |
| | | endTimeInput.SelectedDateTime }); |
| | | foreach (string file in files) |
| | | { |
| | | using (SqliteHelper sql = new SqliteHelper(file)) |
| | | if (files.Length <= 0) |
| | | { |
| | | dt.Merge(sql.GetDataTable(str)); |
| | | table.ItemsSource = new DataTable().DefaultView; |
| | | return; |
| | | } |
| | | |
| | | using (Sqlite3Helper helper = new Sqlite3Helper(files[0])) |
| | | { |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'"; |
| | | helper.Execute(attach); |
| | | } |
| | | |
| | | string sql = string.Join(" UNION ALL ", GetSqls(files)); |
| | | |
| | | string sortName = "time", sortDirection = "DESC"; |
| | | |
| | | string baseSql = $"SELECT level,time,source,text FROM ({sql}) as _temp"; |
| | | |
| | | string countSql = $"SELECT COUNT(1) FROM ({sql}) as __temp"; |
| | | |
| | | long total = (long)helper.SelectOne(countSql); |
| | | long pages = (total/pageSize)+ ((total % pageSize) > 0 ? 1 : 0); |
| | | |
| | | sql = $"{baseSql} ORDER BY {sortName} {sortDirection} LIMIT {size} OFFSET {(page - 1) * size} "; |
| | | |
| | | DataTable dt = helper.GetDataTable(sql); |
| | | table.ItemsSource = dt.DefaultView; |
| | | |
| | | MaxPage = pages; |
| | | } |
| | | |
| | | } |
| | | if (dt.Rows.Count > 0) |
| | | catch (Exception ex) |
| | | { |
| | | dt.DefaultView.Sort = "time Desc"; |
| | | log.Error("Select Log Error.", ex); |
| | | MsgBoxHelper2.Error($"查询失败: {ex.Message}"); |
| | | } |
| | | table.ItemsSource = dt.DefaultView; |
| | | } |
| | | |
| | | public static string[] GetOldDbFiles(string folderPath, DateTime?[] range) |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 加载界面判断数据库语句 |
| | | /// |
| | | /// </summary> |
| | | /// <returns> str数据库的语句 </returns> |
| | | private string LoadSql() |
| | | /// <param name="files"></param> |
| | | /// <returns></returns> |
| | | private string[] GetSqls(string[] files) |
| | | { |
| | | string sql = " select level,time,source,text from log"; |
| | | List<string> datas = new List<string>(); |
| | | if (!string.IsNullOrEmpty(levelInput.Text)) |
| | | string[] sqls = new string[files.Length]; |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | datas.Add($"level='{levelInput.Text}'"); |
| | | } |
| | | if (!string.IsNullOrEmpty(startTimeInput.Text)) |
| | | { |
| | | datas.Add($"time>='{startTimeInput.Text}'"); |
| | | } |
| | | if (!string.IsNullOrEmpty(endTimeInput.Text)) |
| | | { |
| | | datas.Add($"time<='{endTimeInput.Text}'"); |
| | | } |
| | | if (!string.IsNullOrEmpty(sourceInput.Text)) |
| | | { |
| | | datas.Add($"source='{sourceInput.Text}'"); |
| | | } |
| | | string sql = $"SELECT level,time,source,text FROM db{i}.log"; |
| | | List<string> datas = new List<string>(); |
| | | if (!string.IsNullOrEmpty(levelInput.Text)) |
| | | { |
| | | datas.Add($"level='{levelInput.Text}'"); |
| | | } |
| | | if (!string.IsNullOrEmpty(startTimeInput.Text)) |
| | | { |
| | | datas.Add($"time>='{startTimeInput.Text}'"); |
| | | } |
| | | if (!string.IsNullOrEmpty(endTimeInput.Text)) |
| | | { |
| | | datas.Add($"time<'{endTimeInput.Text}'"); |
| | | } |
| | | if (!string.IsNullOrEmpty(sourceInput.Text)) |
| | | { |
| | | datas.Add($"source='{sourceInput.Text}'"); |
| | | } |
| | | |
| | | string condition = string.Join(" AND ", datas); |
| | | condition = string.IsNullOrEmpty(condition) ? string.Empty : $" WHERE {condition}"; |
| | | |
| | | sql = $"{sql}{condition} order by time desc"; |
| | | return sql; |
| | | string condition = string.Join(" AND ", datas); |
| | | condition = string.IsNullOrEmpty(condition) ? string.Empty : $" WHERE {condition}"; |
| | | sql = $"{sql}{condition}"; |
| | | sqls[i] = sql; |
| | | } |
| | | return sqls; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | this.Dispatcher.BeginInvoke((Action)delegate () |
| | | { |
| | | table.ItemsSource = dt.DefaultView; |
| | | MaxPage = 1; |
| | | }); |
| | | } |
| | | } |
| | |
| | | /// <param name="datas"></param> |
| | | private void SaveProduct(IList<ProductData> datas) |
| | | { |
| | | XmlHelper.SerializeToXml(PathHelper.ProductDataFile, datas); |
| | | XmlHelper.SerializeToXml(ProductManager.GetDataFilePath(), datas); |
| | | } |
| | | #endregion |
| | | |
| | |
| | | /// <param name="datas"></param> |
| | | private void SaveParameter(IList<ParameterData> datas) |
| | | { |
| | | string fileName = Path.Combine(PathHelper.ProductDataFolder, "Parameter", $"Parameter_{SelectedProduct.Name}.data"); |
| | | string fileName = ProductManager.GetParamFolderByProductName(SelectedProduct.Name); |
| | | XmlHelper.SerializeToXml(fileName, datas); |
| | | } |
| | | |
| | | private void SaveParameter(string product, IList<ParameterData> datas) |
| | | { |
| | | string fileName = Path.Combine(PathHelper.ProductDataFolder, "Parameter", $"Parameter_{product}.data"); |
| | | string fileName = ProductManager.GetParamFolderByProductName(product); |
| | | XmlHelper.SerializeToXml(fileName, datas); |
| | | } |
| | | #endregion |
| | |
| | | using HMI.Base; |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Util; |
| | | using HMI.ParameterManage.Model; |
| | | using HMI.UI.Util; |
| | | using NPOI.POIFS.NIO; |
| | | using NPOI.SS.Formula.Functions; |
| | | using System.Linq; |
| | | using System.Text.RegularExpressions; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Markup; |
| | | |
| | | namespace HMI.ParameterManage |
| | | { |
| | |
| | | ToastHelper.Warning(Window.GetWindow(this), this.lang("Pm.PleaseSelectProduct")); |
| | | return; |
| | | } |
| | | var win = new ParameterModal(Model) |
| | | //var win = new ParameterModal(Model) |
| | | //{ |
| | | // Title = data == null ? this.lang("Pm.Parameter.Add") : this.lang("Pm.Parameter.Edit"), |
| | | // Owner = Window.GetWindow(this), |
| | | //}; |
| | | //if (win.Open(Model.SelectedProduct.Name, data ?? new ParameterData { ProductName = Model.SelectedProduct.Name }, Model.groups) == true) |
| | | //{ |
| | | // Model.LoadParameters(); |
| | | //} |
| | | |
| | | SettingModal modal = new SettingModal() |
| | | { |
| | | Title = data == null ? this.lang("Pm.Parameter.Add") : this.lang("Pm.Parameter.Edit"), |
| | | Owner = Window.GetWindow(this), |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (win.Open(Model.SelectedProduct.Name, data ?? new ParameterData { ProductName = Model.SelectedProduct.Name }, Model.groups) == true) |
| | | var target = data ?? new ParameterData(); |
| | | if (modal.Open(target, Model.Parameters, Model.groups, Model.SelectedProduct.Name) == true) |
| | | { |
| | | //if (index == -1) |
| | | //{ |
| | | // Datasource.Add(modal.Data); |
| | | // ParameterManager.SaveCommonParameter(Datasource); |
| | | //} |
| | | //else |
| | | //{ |
| | | // ParameterManager.SaveCommonParameter(Datasource); |
| | | //} |
| | | Model.SaveOrUpdateParameter(target); |
| | | Model.LoadParameters(); |
| | | } |
| | | } |
| | |
| | | </ComboBox> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgIsArray" Header="IsArray" dp:FormGroupHelper.IsRequired="True" GroupName="MyFormGroup"> |
| | | <CheckBox x:Name="CbIsArray" /> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgValue" Style="{StaticResource RequiredInputFormGroupStyle}" |
| | | Header="{DynamicResource Pm.Parameter.Value}" |
| | | dp:FormGroupHelper.IsRequired="True" GroupName="MyFormGroup"> |
| | |
| | | { |
| | | Data.Name = TbName.Text; |
| | | Data.Type = CbType.Text; |
| | | Data.IsArray = CbIsArray.IsChecked == true; |
| | | Data.Value = GetTargetValue(); |
| | | Data.Unit = TbUnit.Text; |
| | | Data.Description = TbDescription.Text; |
| | |
| | | Data = data; |
| | | TbName.Text = Data.Name; |
| | | CbType.SelectedValue = Data.Type; |
| | | CbIsArray.IsChecked = Data.IsArray; |
| | | CbGroup.ItemsSource = groups; |
| | | UpdateWindow(Data.Type); |
| | | UpdateForm(Data); |
| | |
| | | <Grid Margin="10"> |
| | | <StackPanel x:Name="formPanel"> |
| | | |
| | | <pu:FormGroup x:Name="FgProductName" Visibility="Collapsed" |
| | | Header="{DynamicResource Pm.Product.Name}" |
| | | dp:FormGroupHelper.IsRequired="True" |
| | | GroupName="MyFormGroup"> |
| | | <TextBox x:Name="TbProductName" IsReadOnly="True" Style="{StaticResource EditorTextBoxStyle}" /> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgName" |
| | | dp:FormGroupHelper.ValidateMethod="ValidateName" |
| | | Header="{DynamicResource Pm.Parameter.Name}" |
| | |
| | | <ComboBoxItem>Bool</ComboBoxItem> |
| | | <ComboBoxItem>String</ComboBoxItem> |
| | | </ComboBox> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgIsArray" Header="IsArray" dp:FormGroupHelper.IsRequired="True" GroupName="MyFormGroup"> |
| | | <CheckBox x:Name="CbIsArray" Checked="CbIsArray_Checked" Unchecked="CbIsArray_Checked"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgLength" Visibility="Collapsed" Header="Length" dp:FormGroupHelper.IsRequired="True" GroupName="MyFormGroup"> |
| | | <ui:NumberInput x:Name="NiLength" TextChanged="NiLength_TextChanged" Style="{StaticResource EditorTextBoxStyle}"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgValue" Style="{StaticResource RequiredInputFormGroupStyle}" |
| | |
| | | <TextBox x:Name="TbStringValue" Style="{StaticResource EditorTextBoxStyle}"/> |
| | | <Button Grid.Column="1" Click="Button_Click" Style="{StaticResource SearchButton}"/> |
| | | </Grid> |
| | | <DataGrid Visibility="Collapsed" |
| | | x:Name="arrayInput" MinHeight="100" MaxHeight="200" CanUserAddRows="False" CanUserDeleteRows="False"></DataGrid> |
| | | </Grid> |
| | | </pu:FormGroup> |
| | | |
| | |
| | | using HMI.UI.DpUtil; |
| | | using HMI.UI.Util; |
| | | using Microsoft.Win32; |
| | | using NPOI.SS.Formula.Functions; |
| | | using NPOI.SS.Formula.PTG; |
| | | using Panuon.WPF.UI; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | using System.Linq; |
| | | using System.Text.RegularExpressions; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace HMI.ParameterManage |
| | | { |
| | | public class BoolData |
| | | { |
| | | public int Index { get; } |
| | | public bool Value { get; set; } |
| | | |
| | | public BoolData(int index) |
| | | { |
| | | this.Index = index; |
| | | } |
| | | } |
| | | |
| | | public class IntData |
| | | { |
| | | public int Index { get; } |
| | | public int Value { get; set; } |
| | | |
| | | public IntData(int index) |
| | | { |
| | | this.Index = index; |
| | | } |
| | | } |
| | | |
| | | public class DoubleData |
| | | { |
| | | public int Index { get; } |
| | | public double Value { get; set; } |
| | | |
| | | public DoubleData(int index) |
| | | { |
| | | this.Index = index; |
| | | } |
| | | } |
| | | |
| | | public class StringData |
| | | { |
| | | public int Index { get; } |
| | | public string Value { get; set; } = string.Empty; |
| | | |
| | | public StringData(int index) |
| | | { |
| | | this.Index = index; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ModalWindow.xaml 的交互逻辑 |
| | | /// </summary> |
| | |
| | | { |
| | | Data.Name = TbName.Text; |
| | | Data.Type = CbType.Text; |
| | | Data.IsArray = CbIsArray.IsChecked == true; |
| | | Data.Length = int.Parse(NiLength.Text); |
| | | |
| | | Data.Value = GetTargetValue(); |
| | | Data.Unit = TbUnit.Text; |
| | | Data.Description = TbDescription.Text; |
| | |
| | | return flag; |
| | | } |
| | | |
| | | public bool? Open(ParameterData data, ObservableCollection<ParameterData> datasource, List<string> groups) |
| | | public bool? Open(ParameterData data, ObservableCollection<ParameterData> datasource, List<string> groups,string productName = null) |
| | | { |
| | | if (!string.IsNullOrEmpty(productName)) |
| | | { |
| | | FgProductName.Visibility = System.Windows.Visibility.Visible; |
| | | TbProductName.Text = productName; |
| | | } |
| | | |
| | | Datasource = datasource; |
| | | Data = data; |
| | | TbGroup.ItemsSource = groups; |
| | | |
| | | TbName.Text = Data.Name; |
| | | CbType.SelectedValue = Data.Type; |
| | | CbIsArray.IsChecked = Data.IsArray; |
| | | NiLength.Text = Data.Length.ToString(); |
| | | |
| | | UpdateWindow(Data.Type); |
| | | UpdateForm(Data); |
| | | |
| | |
| | | private string GetTargetValue() |
| | | { |
| | | var type = CbType.Text; |
| | | if (CbIsArray.IsChecked == true) |
| | | { |
| | | var arr = (object[])arrayInput.ItemsSource; |
| | | return string.Join(",", arr.Select(e => e.GetType().GetProperty("Value").GetValue(e).ToString()).ToArray()); |
| | | } |
| | | |
| | | if (type == "Int" || type == "Double") |
| | | { |
| | | return NiNumberValue.Text; |
| | |
| | | |
| | | private void UpdateForm(ParameterData data) |
| | | { |
| | | if (Data.Type == "Int" || Data.Type == "Int") |
| | | if (data.IsArray) |
| | | { |
| | | NiNumberValue.Text = Data.Value; |
| | | } |
| | | else if (Data.Type == "Bool") |
| | | { |
| | | CbBoolValue.SelectedValue = Data.Value; |
| | | string[] arr = data.Value.Split(','); |
| | | arrayInput.ItemsSource = RefreshArray(arr, Data.Type); |
| | | } |
| | | else |
| | | { |
| | | TbStringValue.Text = Data.Value; |
| | | if (Data.Type == "Int" || Data.Type == "Int") |
| | | { |
| | | NiNumberValue.Text = Data.Value; |
| | | } |
| | | else if (Data.Type == "Bool") |
| | | { |
| | | CbBoolValue.SelectedValue = Data.Value; |
| | | } |
| | | else |
| | | { |
| | | TbStringValue.Text = Data.Value; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | val = ((ComboBoxItem)e.AddedItems[0]).Content.ToString(); |
| | | } |
| | | UpdateWindow(val); |
| | | if (CbIsArray.IsChecked == true) |
| | | { |
| | | arrayInput.ItemsSource = RefreshArray(GetLength(), val); |
| | | } |
| | | } |
| | | |
| | | private void Button_Click(object sender, System.Windows.RoutedEventArgs e) |
| | |
| | | TbStringValue.Text = ofd.FileName; |
| | | } |
| | | } |
| | | |
| | | private void CbIsArray_Checked(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | bool isChecked = ((CheckBox)sender).IsChecked == true; |
| | | if (isChecked) |
| | | { |
| | | FgLength.Visibility = System.Windows.Visibility.Visible; |
| | | arrayInput.Visibility = System.Windows.Visibility.Visible; |
| | | arrayInput.ItemsSource = RefreshArray(GetLength(), CbType.Text); |
| | | } |
| | | else |
| | | { |
| | | FgLength.Visibility = System.Windows.Visibility.Collapsed; |
| | | arrayInput.Visibility = System.Windows.Visibility.Collapsed; |
| | | } |
| | | } |
| | | |
| | | private object[] RefreshArray(int length, string type) |
| | | { |
| | | var arr = new object[length]; |
| | | for (int i = 0; i < length; i++) |
| | | { |
| | | if (type == "Int") |
| | | { |
| | | arr[i] = new IntData(i); |
| | | } |
| | | else if (type == "Double") |
| | | { |
| | | arr[i] = new DoubleData(i); |
| | | } |
| | | else if (type == "Bool") |
| | | { |
| | | arr[i] = new BoolData(i); |
| | | } |
| | | else |
| | | { |
| | | arr[i] = new StringData(i); |
| | | } |
| | | } |
| | | return arr; |
| | | } |
| | | |
| | | private object[] RefreshArray(string[] source, string type) |
| | | { |
| | | var arr = new object[source.Length]; |
| | | type = string.IsNullOrEmpty(type) ? "String" : type; |
| | | for (int i = 0; i < arr.Length; i++) |
| | | { |
| | | if (type == "Int") |
| | | { |
| | | arr[i] = new IntData(i) |
| | | { |
| | | Value = int.Parse(source[i]) |
| | | }; |
| | | } |
| | | else if (type == "Double") |
| | | { |
| | | arr[i] = new DoubleData(i) |
| | | { |
| | | Value = double.Parse(source[i]) |
| | | }; |
| | | } |
| | | else if (type == "Bool") |
| | | { |
| | | arr[i] = new BoolData(i) |
| | | { |
| | | Value = bool.Parse(source[i]) |
| | | }; |
| | | } |
| | | else |
| | | { |
| | | arr[i] = new StringData(i) |
| | | { |
| | | Value = source[i] |
| | | }; |
| | | } |
| | | } |
| | | return arr; |
| | | } |
| | | |
| | | private int GetLength() |
| | | { |
| | | try |
| | | { |
| | | string text = NiLength.Text; |
| | | if (text.Contains(".")) |
| | | { |
| | | text = text.Split('.')[0]; |
| | | } |
| | | int length = int.Parse(text); |
| | | return length > 0 ? length : 1; |
| | | } |
| | | catch |
| | | { |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | private void NiLength_TextChanged(object sender, TextChangedEventArgs e) |
| | | { |
| | | if (CbIsArray.IsChecked != true) |
| | | { |
| | | return; |
| | | } |
| | | arrayInput.ItemsSource = RefreshArray(GetLength(), CbType.Text); |
| | | } |
| | | } |
| | | } |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | <Compile Include="StdSettingCheckBox.xaml.cs"> |
| | | <DependentUpon>StdSettingCheckBox.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="StdEnableMes.xaml.cs"> |
| | | <DependentUpon>StdEnableMes.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="StdUIEventArg.cs" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Page Include="StdSettingCheckBox.xaml"> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | <SubType>Designer</SubType> |
| | | </Page> |
| | | <Page Include="StdEnableMes.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| New file |
| | |
| | | <UserControl x:Class="HMI.StdControl.StdSettingCheckBox" |
| | | 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:local="clr-namespace:HMI.StdControl" |
| | | mc:Ignorable="d" |
| | | x:Name="self" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <CheckBox x:Name="CbEnableMes" IsChecked="{Binding IsChecked,ElementName=self,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | VerticalContentAlignment="Center" |
| | | IsEnabled="{Binding CbEnabled,ElementName=self}" |
| | | Content="{Binding Text,ElementName=self}" /> |
| | | </UserControl> |
| New file |
| | |
| | | using HMI.Core.Manager; |
| | | using System; |
| | | using System.ComponentModel; |
| | | using System.Runtime.CompilerServices; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace HMI.StdControl |
| | | { |
| | | /// <summary> |
| | | /// StdEnableMes.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class StdSettingCheckBox : UserControl, INotifyPropertyChanged |
| | | { |
| | | |
| | | #region ... |
| | | public virtual event PropertyChangedEventHandler PropertyChanged; |
| | | |
| | | protected virtual void Set([CallerMemberName] string name = null) |
| | | { |
| | | |
| | | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); |
| | | } |
| | | |
| | | protected void Set<T>(ref T old, T @new, [CallerMemberName] string propertyName = null) |
| | | { |
| | | old = @new; |
| | | if (propertyName != null) |
| | | { |
| | | Set(propertyName); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | private event EventHandler<StdUIEventArg> valueChanged; |
| | | public event EventHandler<StdUIEventArg> ValueChanged |
| | | { |
| | | add |
| | | { |
| | | valueChanged += value; |
| | | } |
| | | remove |
| | | { |
| | | valueChanged -= value; |
| | | } |
| | | } |
| | | |
| | | public static DependencyProperty IsCheckedProperty = DependencyProperty.Register( |
| | | "IsChecked", |
| | | typeof(bool), |
| | | typeof(StdSettingCheckBox), |
| | | new FrameworkPropertyMetadata(false)); |
| | | |
| | | public static DependencyProperty ValueProperty = DependencyProperty.Register( |
| | | "Value", |
| | | typeof(string), |
| | | typeof(StdSettingCheckBox), |
| | | new FrameworkPropertyMetadata(null)); |
| | | |
| | | public static DependencyProperty CbEnabledProperty = DependencyProperty.Register( |
| | | "CbEnabled", |
| | | typeof(bool), |
| | | typeof(StdSettingCheckBox), |
| | | new FrameworkPropertyMetadata(true)); |
| | | |
| | | public static DependencyProperty TextProperty = DependencyProperty.Register( |
| | | "Text", |
| | | typeof(string), |
| | | typeof(StdSettingCheckBox), |
| | | new FrameworkPropertyMetadata(null)); |
| | | |
| | | |
| | | public bool CbEnabled |
| | | { |
| | | get => (bool)GetValue(CbEnabledProperty); |
| | | set |
| | | { |
| | | SetValue(CbEnabledProperty, value); |
| | | } |
| | | } |
| | | |
| | | public string Value |
| | | { |
| | | get => (string)GetValue(ValueProperty); |
| | | set |
| | | { |
| | | SetValue(ValueProperty, value); |
| | | } |
| | | } |
| | | |
| | | public string Text |
| | | { |
| | | get => (string)GetValue(TextProperty); |
| | | set |
| | | { |
| | | SetValue(TextProperty, value); |
| | | } |
| | | } |
| | | |
| | | public bool IsChecked |
| | | { |
| | | get => (bool)GetValue(IsCheckedProperty); |
| | | set |
| | | { |
| | | if (WriteConfig(Value, value)) |
| | | { |
| | | SetValue(IsCheckedProperty, value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public StdSettingCheckBox() |
| | | { |
| | | InitializeComponent(); |
| | | this.Loaded += StdSettingCheckBox_Loaded; |
| | | } |
| | | |
| | | private void StdSettingCheckBox_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | try |
| | | { |
| | | var value = ParameterManager.GetCommonParameterByName(Value); |
| | | if (value == null) |
| | | { |
| | | this.Visibility = System.Windows.Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | IsChecked = bool.Parse(value.Value); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | IsChecked = false; |
| | | } |
| | | } |
| | | |
| | | private bool WriteConfig(string name, bool value) |
| | | { |
| | | try |
| | | { |
| | | valueChanged?.Invoke(this, new StdUIEventArg() |
| | | { |
| | | StringValue = name, |
| | | BoolValue = value |
| | | }); |
| | | return ParameterManager.UpdateCommonParameter(name, value, out string errMsg); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.Globalization; |
| | | using System.Windows.Data; |
| | | |
| | | namespace HMI.UI.Converter |
| | | { |
| | | |
| | | public class DateStrConverter : IValueConverter |
| | | { |
| | | public static DateStrConverter Instance { get; } = new DateStrConverter(); |
| | | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | if (value is DateTime date) |
| | | { |
| | | if (parameter != null) |
| | | { |
| | | return date.ToString(parameter.ToString()); |
| | | } |
| | | return date.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | } |
| | | return value.ToString(); |
| | | } |
| | | |
| | | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | return DateTime.Parse(value.ToString()); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.Windows.Data; |
| | | |
| | | namespace HMI.UI.Converter |
| | | { |
| | | public class RadioEnumConverter : IValueConverter |
| | | { |
| | | public static RadioEnumConverter Instance { get; } = new RadioEnumConverter(); |
| | | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) |
| | | { |
| | | return value?.Equals(parameter); |
| | | } |
| | | |
| | | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) |
| | | { |
| | | return value?.Equals(true) == true ? parameter : Binding.DoNothing; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.Globalization; |
| | | using System.Windows.Data; |
| | | |
| | | namespace HMI.UI.Converter |
| | | { |
| | | public class ResultConverter : IValueConverter |
| | | { |
| | | public static ResultConverter Instance = new ResultConverter(); |
| | | |
| | | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | if (value == null) return value; |
| | | var str = value.ToString(); |
| | | if (str.Equals("ok", StringComparison.OrdinalIgnoreCase) || str.Equals("pass", StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | return "PASS"; |
| | | } |
| | | if (str.Equals("ng", StringComparison.OrdinalIgnoreCase) || str.Equals("fail", StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | return "FAIL"; |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | return value; |
| | | } |
| | | } |
| | | } |
| | |
| | | <Compile Include="Controls\treegrid\TreeItemConverter.cs" /> |
| | | <Compile Include="Controls\treegrid\TreeNodeExtend.cs" /> |
| | | <Compile Include="Controls\VisualHost.cs" /> |
| | | <Compile Include="Converter\DateStrConverter.cs" /> |
| | | <Compile Include="Converter\RadioEnumConverter.cs" /> |
| | | <Compile Include="Converter\ResultConverter.cs" /> |
| | | <Compile Include="Converter\ReverseBoolConverter.cs" /> |
| | | <Compile Include="Converter\IndentConverter.cs" /> |
| | | <Compile Include="Converter\CollectionHasItem.cs" /> |
| | |
| | | <Compile Include="MDI\Workspace.xaml.cs"> |
| | | <DependentUpon>Workspace.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="RequirePasswordByUser.xaml.cs"> |
| | | <DependentUpon>RequirePasswordByUser.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="RequirePasswordWindow.xaml.cs"> |
| | | <DependentUpon>RequirePasswordWindow.xaml</DependentUpon> |
| | | </Compile> |
| | |
| | | <Compile Include="Util\MsgBoxHelper.cs" /> |
| | | <Compile Include="Util\MsgBoxHelper2.cs" /> |
| | | <Compile Include="Util\ToastHelper.cs" /> |
| | | <Page Include="RequirePasswordByUser.xaml"> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | <SubType>Designer</SubType> |
| | | </Page> |
| | | <Page Include="RequirePasswordWindow.xaml"> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | <SubType>Designer</SubType> |
| | |
| | | </Grid.ColumnDefinitions> |
| | | <Border Padding="10,5,0,5" Background="{DynamicResource PrimaryColor}" |
| | | CornerRadius="5,5,0,0"> |
| | | <Label Padding="2" BorderThickness="0" Margin="0" Foreground="#FFF" x:Name="titleLabel" Content="请稍后"/> |
| | | <Label Padding="2" Background="Transparent" BorderThickness="0" Margin="0" Foreground="#FFF" x:Name="titleLabel" Content="请稍后"/> |
| | | </Border> |
| | | <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" |
| | | VerticalAlignment="Center" |
| | |
| | | </EventTrigger> |
| | | </TextBlock.Triggers> |
| | | </TextBlock> |
| | | <TextBlock Grid.Row="1" Margin="20,0,0,0" Grid.Column="1" x:Name="contentLabel" |
| | | <TextBlock Grid.Row="1" Margin="20,0,0,0" Grid.Column="1" Background="Transparent" x:Name="contentLabel" |
| | | VerticalAlignment="Center" TextWrapping="Wrap"/> |
| | | </StackPanel> |
| | | </Grid> |
| New file |
| | |
| | | <pu:WindowX x:Class="HMI.Base.RequirePasswordByUser" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:local="clr-namespace:HMI.Base" |
| | | mc:Ignorable="d" |
| | | Style="{StaticResource ModalWindow}" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil" |
| | | Loaded="WindowX_Loaded" |
| | | FontSize="14" |
| | | WindowStartupLocation="CenterOwner" |
| | | Height="200" |
| | | pu:WindowXModalDialog.OKButtonContent="确定" |
| | | Title="请输入密码" Width="500"> |
| | | <Grid dp:GridHelper.Space="10"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | </Grid.RowDefinitions> |
| | | <pu:FormGroup Header="当前用户" Orientation="Horizontal" Style="{StaticResource InputFormGroupStyle}"> |
| | | <TextBlock Text="{Binding Username}"/> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Grid.Row="1" Header="密码" Orientation="Horizontal" |
| | | Style="{StaticResource RequiredInputFormGroupStyle}"> |
| | | <PasswordBox x:Name="PwdPassword" VerticalContentAlignment="Center" |
| | | Style="{StaticResource SignInPasswordBoxStyle}" |
| | | pu:PasswordBoxHelper.Watermark="{DynamicResource App.Password}"/> |
| | | </pu:FormGroup> |
| | | </Grid> |
| | | </pu:WindowX> |
| New file |
| | |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Util; |
| | | using HMI.UI.Util; |
| | | using Panuon.WPF.UI; |
| | | using System.ComponentModel; |
| | | |
| | | namespace HMI.Base |
| | | { |
| | | /// <summary> |
| | | /// RequirePasswordWindow.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class RequirePasswordByUser : WindowX |
| | | { |
| | | public RequirePasswordByUser(string username) |
| | | { |
| | | this.Username = username; |
| | | this.DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | private string username; |
| | | public string Username |
| | | { |
| | | get => username; |
| | | set |
| | | { |
| | | Set(ref username, value); |
| | | } |
| | | } |
| | | |
| | | protected override void OnClosing(CancelEventArgs e) |
| | | { |
| | | //Press Continue Button |
| | | if (DialogResult == true) |
| | | { |
| | | try |
| | | { |
| | | using (var helper = new Sqlite3Helper(PathHelper.DatabasePath)) |
| | | { |
| | | if (!helper.HasData($"SELECT 1 FROM user WHERE username = '{Username}' AND password = '{PwdPassword.Password}';")) |
| | | { |
| | | ToastHelper.Error(this, "密码错误"); |
| | | e.Cancel = true; |
| | | } |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | ToastHelper.Error(this, $"验证用户信息失败: {ex.Message}"); |
| | | e.Cancel = true; |
| | | } |
| | | } |
| | | base.OnClosing(e); |
| | | } |
| | | |
| | | private void WindowX_Loaded(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | Username = UserInfo.User.Username; |
| | | PwdPassword.Password = string.Empty; |
| | | } |
| | | } |
| | | } |
| | |
| | | Loaded="WindowX_Loaded" |
| | | FontSize="14" |
| | | Height="200" |
| | | WindowStartupLocation="CenterOwner" |
| | | pu:WindowXModalDialog.OKButtonContent="确定" |
| | | Title="请输入密码" Width="500"> |
| | | <Grid dp:GridHelper.Space="10"> |
| | |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:puconfig="clr-namespace:Panuon.WPF.UI.Configurations;assembly=Panuon.WPF.UI"> |
| | | |
| | | <pu:MessageBoxXSettings x:Key="MsgBoxWarn" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSettings.WindowXStyle> |
| | | <pu:MessageBoxXSetting x:Key="MsgBoxWarn" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSetting.WindowXStyle> |
| | | <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}"> |
| | | <Setter Property="pu:WindowXCaption.Background" Value="{DynamicResource WarningColor}" /> |
| | | <Setter Property="pu:WindowXCaption.Foreground" Value="{DynamicResource WarningColorContract}" /> |
| | |
| | | <Setter Property="Height" Value="200" /> |
| | | <Setter Property="SizeToContent" Value="Manual" /> |
| | | </Style> |
| | | </pu:MessageBoxXSettings.WindowXStyle> |
| | | </pu:MessageBoxXSetting.WindowXStyle> |
| | | |
| | | <pu:MessageBoxXSettings.ButtonStyle> |
| | | <pu:MessageBoxXSetting.ButtonStyle> |
| | | <Style TargetType="Button" BasedOn="{StaticResource {x:Static pu:MessageBoxX.ButtonStyleKey}}"> |
| | | |
| | | <Style.Triggers> |
| | |
| | | <Setter Property="ContentTemplate"> |
| | | <Setter.Value> |
| | | <DataTemplate> |
| | | <TextBlock Text="{Binding}" TextDecorations="Underline" /> |
| | | <TextBlock Text="{DynamicResource App.Cancel}" TextDecorations="Underline" /> |
| | | </DataTemplate> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Trigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </pu:MessageBoxXSettings.ButtonStyle> |
| | | </pu:MessageBoxXSettings> |
| | | </pu:MessageBoxXSetting.ButtonStyle> |
| | | </pu:MessageBoxXSetting> |
| | | |
| | | <pu:MessageBoxXSettings x:Key="MsgBoxError" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSettings.WindowXStyle> |
| | | <pu:MessageBoxXSetting x:Key="MsgBoxError" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSetting.WindowXStyle> |
| | | <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}"> |
| | | <Setter Property="pu:WindowXCaption.Background" Value="{DynamicResource DangerColor}" /> |
| | | <Setter Property="pu:WindowXCaption.Foreground" Value="{DynamicResource DangerColorContrast}" /> |
| | |
| | | <Setter Property="Height" Value="200" /> |
| | | <Setter Property="SizeToContent" Value="Manual" /> |
| | | </Style> |
| | | </pu:MessageBoxXSettings.WindowXStyle> |
| | | </pu:MessageBoxXSetting.WindowXStyle> |
| | | |
| | | <pu:MessageBoxXSettings.ButtonStyle> |
| | | <pu:MessageBoxXSetting.ButtonStyle> |
| | | <Style TargetType="Button" BasedOn="{StaticResource {x:Static pu:MessageBoxX.ButtonStyleKey}}"> |
| | | |
| | | <Style.Triggers> |
| | |
| | | <Setter Property="ContentTemplate"> |
| | | <Setter.Value> |
| | | <DataTemplate> |
| | | <TextBlock Text="{Binding}" TextDecorations="Underline" /> |
| | | <TextBlock Text="{DynamicResource App.Cancel}" TextDecorations="Underline" /> |
| | | </DataTemplate> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Trigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </pu:MessageBoxXSettings.ButtonStyle> |
| | | </pu:MessageBoxXSettings> |
| | | </pu:MessageBoxXSetting.ButtonStyle> |
| | | </pu:MessageBoxXSetting> |
| | | |
| | | <pu:MessageBoxXSettings x:Key="MsgBoxInfo" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSettings.WindowXStyle> |
| | | <pu:MessageBoxXSetting x:Key="MsgBoxInfo" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSetting.WindowXStyle> |
| | | <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}"> |
| | | <Setter Property="pu:WindowXCaption.Background" Value="{DynamicResource PrimaryColor}" /> |
| | | <Setter Property="pu:WindowXCaption.Foreground" Value="{DynamicResource PrimaryColorContract}" /> |
| | |
| | | <Setter Property="Height" Value="200" /> |
| | | <Setter Property="SizeToContent" Value="Manual" /> |
| | | </Style> |
| | | </pu:MessageBoxXSettings.WindowXStyle> |
| | | </pu:MessageBoxXSetting.WindowXStyle> |
| | | |
| | | <pu:MessageBoxXSettings.ButtonStyle> |
| | | <pu:MessageBoxXSetting.ButtonStyle> |
| | | <Style TargetType="Button" BasedOn="{StaticResource {x:Static pu:MessageBoxX.ButtonStyleKey}}"> |
| | | |
| | | <Style.Triggers> |
| | |
| | | <Setter Property="ContentTemplate"> |
| | | <Setter.Value> |
| | | <DataTemplate> |
| | | <TextBlock Text="{Binding}" TextDecorations="Underline" /> |
| | | <TextBlock Text="{DynamicResource App.Cancel}" TextDecorations="Underline" /> |
| | | </DataTemplate> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Trigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </pu:MessageBoxXSettings.ButtonStyle> |
| | | </pu:MessageBoxXSettings> |
| | | </pu:MessageBoxXSetting.ButtonStyle> |
| | | </pu:MessageBoxXSetting> |
| | | |
| | | <pu:ToastSetting x:Key="toastSuccess" Spacing="25"> |
| | | <pu:ToastSetting.LabelStyle> |
| | |
| | | <Setter Property="pu:WindowXModalDialog.OKButtonContent" |
| | | Value="{DynamicResource App.Save}"/> |
| | | <Setter Property="pu:WindowXModalDialog.ButtonPanelMargin" Value="0,30,10,10"/> |
| | | <Setter Property="InteropOwnersMask" Value="False"/> |
| | | </Style> |
| | | |
| | | <Style x:Key="DefaultListBox" TargetType="ListBox" BasedOn="{StaticResource {x:Static pu:StyleKeys.ListBoxStyle}}"> |
| | |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Style> |
| | | |
| | | <Style x:Key="DefaultPageItem" TargetType="pu:PaginationItem"> |
| | | <Setter Property="Cursor" Value="Hand" /> |
| | | <Setter Property="MinWidth" Value="30" /> |
| | | <Setter Property="Width" Value="Auto" /> |
| | | <Setter Property="Width" Value="Auto" /> |
| | | </Style> |
| | | |
| | | <Style x:Key="DefaultPage" TargetType="pu:Pagination"> |
| | | <Setter Property="Height" Value="30"/> |
| | | <Setter Property="HorizontalAlignment" Value="Right"/> |
| | | <Setter Property="Foreground" Value="Black" /> |
| | | <Setter Property="ItemsBackground" Value="Transparent"/> |
| | | <Setter Property="ItemsCornerRadius" Value="12"/> |
| | | <Setter Property="ItemsSelectedBackground" Value="{DynamicResource SecondPrimaryColor}"/> |
| | | <Setter Property="ItemContainerStyle" Value="{StaticResource DefaultPageItem}"/> |
| | | </Style> |
| | | |
| | | </ResourceDictionary> |
| | |
| | | <ResourceDictionary Source="/HMI.UI;component/Style/PanuonResource.xaml"/> |
| | | <ResourceDictionary Source="/HMI.UI;component/Style/MsgBoxStyle.xaml"/> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | <Style TargetType="{x:Type pu:FormGroup}" BasedOn="{StaticResource InputFormGroupStyle}"></Style> |
| | | <!--<Style TargetType="{x:Type pu:FormGroup}" BasedOn="{StaticResource InputFormGroupStyle}"></Style>--> |
| | | <uic:PathImageConverter x:Key="path2Image"/> |
| | | <uic:DataGridRowNumberConverter x:Key="rowNumber"/> |
| | | <uic:VisibilityBoolConverter x:Key="vbConverter"/> |
| | |
| | | <None Include="App.config" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\UILib\UILib.csproj"> |
| | | <Project>{27325fe0-3ce2-4cd5-8eb5-7e45cc441479}</Project> |
| | | <Name>UILib</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\ConnectionUtil\ConnectionUtil.csproj"> |
| | | <Project>{d0806fa6-3f6d-4304-81b8-ead9da7cb5b2}</Project> |
| | | <Name>ConnectionUtil</Name> |
| | |
| | | <Project>{202d9a7b-96b3-4ad4-9977-fc4263207a02}</Project> |
| | | <Name>Plugin.TsExecution</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.UICollection\Plugin.UICollection.csproj"> |
| | | <Project>{22dc8d91-50b2-47ca-86a8-29a6da48f388}</Project> |
| | | <Name>Plugin.UICollection</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\SimpleUtil\HMI.Simple.Util\HMI.Simple.Util.csproj"> |
| | | <Project>{cf5bebe9-2803-49c3-b773-73d082e0984a}</Project> |
| | | <Name>HMI.Simple.Util</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Util.ManualDebug\Util.ManualDebug.csproj"> |
| | | <Project>{d0944e62-ee52-4abe-832a-a09d98814db1}</Project> |
| | | <Name>Util.ManualDebug</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Folder Include="Entity\" /> |
| | |
| | | <Grid x:Name="page"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | <RowDefinition /> |
| | | </Grid.RowDefinitions> |
| | | <Button Click="Button_Click">测试</Button> |
| | | <!--<Button Click="Button_Click2" Grid.Row="1">发送</Button> |
| | | <Button Click="Button_Click3" Grid.Row="2">发送TCP</Button> |
| | | <Button Click="Button_Click4" Grid.Row="4">发送Data</Button>--> |
| | | <TextBox x:Name="input" Height="0" Grid.Row="3"></TextBox> |
| | | <!--<TextBox x:Name="input" Height="0" Grid.Row="3"></TextBox> |
| | | <TextBlock Grid.Row="5" Height="0" x:Name="console"></TextBlock> |
| | | <Border Grid.Row="6" x:Name="border"></Border> |
| | | <Border Grid.Row="6" x:Name="border"></Border>--> |
| | | <Border Grid.Row="1" x:Name="border2"></Border> |
| | | </Grid> |
| | | </pu:WindowX> |
| | |
| | | using HMI.Core.Util; |
| | | using HMI.Simple.Util; |
| | | using log4net; |
| | | using ModBusTcp; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.DataBoard; |
| | | using Plugin.TestResult_WPF; |
| | | using Plugin.TsExecution; |
| | | using Plugin.UICollection; |
| | | using System; |
| | | using System.IO; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | using System.Windows; |
| | | using Util.ManualDebug; |
| | | namespace UnitTest |
| | | { |
| | | /// <summary> |
| | |
| | | LangUtil.Load(); |
| | | InitializeComponent(); |
| | | //RebuildDb(); |
| | | border2.Child = new TcpDebugger(); |
| | | |
| | | ModBusTcpController controller = new ModBusTcpController("127.0.0.1", 502); |
| | | if (controller.Start(out msg)) { |
| | | bool res; |
| | | int? target; |
| | | |
| | | controller.WriteBool("1", true, out msg); |
| | | controller.ReadDOBool("1", out res, out msg); |
| | | Console.WriteLine(res); |
| | | controller.ReadDOInt("1", out target, out msg); |
| | | Console.WriteLine(target); |
| | | controller.WriteInt("1", 1, out msg); |
| | | controller.ReadDOInt("1", out target, out msg); |
| | | Console.WriteLine(target); |
| | | Console.WriteLine(target); |
| | | } |
| | | |
| | | |
| | | |
| | | //page.Children.Add(new UserControl1()); |
| | |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | var win = new ManualDebug() |
| | | { |
| | | seqPath = "C:\\Users\\chrry\\Desktop\\手动调试示例.seq" |
| | | }; |
| | | |
| | | win.Show(); |
| | | //Task.Run(() => |
| | | //{ |
| | | // for (int j = 0; j < 1000; j++) |
| | |
| | | //}); |
| | | |
| | | //tsExecution.UpdatePositionStatus(0, "Passed"); |
| | | tsExecution.UpdatePositionStatus(0, "Failed"); |
| | | //tsExecution.UpdatePositionStatus(0, "Failed"); |
| | | //tsExecution.UpdatePositionProcessValue(0, 12); |
| | | //tsExecution.PausePosition(0); |
| | | //tsExecution.SetPositionBarcode(0, "123456789"); |
| | |
| | | Console.WriteLine($"{e.Data}"); |
| | | } |
| | | |
| | | private void Client_OnData(object sender, PipeDataEventArgs e) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | console.Text += e.Data; |
| | | }); |
| | | } |
| | | |
| | | private void Button_Click2(object sender, RoutedEventArgs e) |
| | | { |
| | | var allStart = DateTime.Now; |
| | | for (int i = 0; i < 100; i++) |
| | | { |
| | | var start = DateTime.Now; |
| | | if (client.SendMessage("ping", out string res)) |
| | | { |
| | | var interval = (DateTime.Now - start).TotalMilliseconds; |
| | | Console.WriteLine($"{interval}: {res}"); |
| | | } |
| | | } |
| | | Console.WriteLine($"Total: {(DateTime.Now - allStart).TotalMilliseconds}"); |
| | | } |
| | | |
| | | private void Button_Click3(object sender, RoutedEventArgs e) |
| | | { |
| | | try |
| | | { |
| | | var allStart = DateTime.Now; |
| | | for (int i = 0; i < 500; i++) |
| | | { |
| | | var start = DateTime.Now; |
| | | string data = input.Text; |
| | | string str = $"{{\"command\":5,\"value\":{data},\"id\":\"DITag0\"}}\r\n"; |
| | | string res = tcpClient.SendMessage(str); |
| | | var interval = (DateTime.Now - start).TotalMilliseconds; |
| | | Console.WriteLine($"{interval}: {res}"); |
| | | } |
| | | Console.WriteLine($"Total: {(DateTime.Now - allStart).TotalMilliseconds}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | |
| | | private void Button_Click4(object sender, RoutedEventArgs e) |
| | | { |
| | | try |
| | | { |
| | | var allStart = DateTime.Now; |
| | | for (int i = 0; i < 500; i++) |
| | | { |
| | | var start = DateTime.Now; |
| | | string data = input.Text; |
| | | string str = $"{{\"command\":5,\"value\":{data},\"id\":\"DITag0\"}}"; |
| | | client.SendMessage(str, out string res); |
| | | var interval = (DateTime.Now - start).TotalMilliseconds; |
| | | Console.WriteLine($"{interval}: {res}"); |
| | | } |
| | | Console.WriteLine($"Total: {(DateTime.Now - allStart).TotalMilliseconds}"); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine(ex.StackTrace); |
| | | } |
| | | } |
| | | |
| | | private void HandlePlugin(object obj) |
| | | { |
| | |
| | | |
| | | private void Window_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | var plugin = new TsExecution(); |
| | | HandlePlugin(plugin); |
| | | border.Child = plugin; |
| | | tsExecution = plugin; |
| | | //var plugin = new TsExecution(); |
| | | //HandlePlugin(plugin); |
| | | //border.Child = plugin; |
| | | //tsExecution = plugin; |
| | | this.Loaded -= Window_Loaded; |
| | | } |
| | | } |
| | |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using log4net; |
| | | using S7Driver; |
| | | using System; |
| | | using System.Collections.Generic; |
| | |
| | | |
| | | public event EventHandler<LoadMsg> LoadMessageAppend; |
| | | |
| | | private static ILog log = LogManager.GetLogger("AlarmHelper"); |
| | | |
| | | internal AlarmHelper() |
| | | { |
| | | |
| | | } |
| | | |
| | | public ObservableCollection<AlarmSetting> BlockSettings { get; private set; } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | //log.Error("Read OPCServer Data Error.", ex); |
| | | log.Error("Read PLC Alarm Data Error.", ex); |
| | | } |
| | | finally |
| | | { |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | //log.Error("PcTimer Execute Failed", ex); |
| | | log.Error("Read MSMQ Alarm Data Failed", ex); |
| | | } |
| | | finally |
| | | { |
| | |
| | | using HMI.Core; |
| | | using HMI.Core.Util; |
| | | using NPOI.HSSF.UserModel; |
| | | using NPOI.SS.Formula.Functions; |
| | | using NPOI.SS.UserModel; |
| | | using NPOI.XSSF.UserModel; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Data; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Reflection; |
| | |
| | | } |
| | | } |
| | | |
| | | public static void ExportExcel<T>(string targetPath, DataTable table) |
| | | { |
| | | Type type = typeof(T); |
| | | var properties = PropertyHelper.GetAtterProperty<T, ExcelColumnAttribute>(out var attrs); |
| | | if (properties == null || properties.Count <= 0) |
| | | { |
| | | throw new Exception("No Attribute"); |
| | | } |
| | | IWorkbook workbook = null; |
| | | if (targetPath.EndsWith(".xlsx")) |
| | | { |
| | | workbook = new XSSFWorkbook(); |
| | | } |
| | | else if (targetPath.EndsWith(".xls")) |
| | | { |
| | | workbook = new HSSFWorkbook(); |
| | | } |
| | | workbook.CreateSheet("sheet1");////新建一个工作表 |
| | | ISheet SheetOne = workbook.GetSheet("Sheet1"); |
| | | IRow row1 = SheetOne.CreateRow(0); |
| | | for (int i = 0; i < properties.Count; i++) |
| | | { |
| | | row1.CreateCell(i).SetCellValue(LangUtil.Get((attrs[i]).Name)); |
| | | } |
| | | |
| | | for (int i = 0; i < table.Rows.Count; i++) |
| | | { |
| | | IRow rowTemp = SheetOne.CreateRow(i + 1); |
| | | for (int j = 0; j < properties.Count; j++) |
| | | { |
| | | var attr = attrs[j]; |
| | | object obj = attr.IgnoreExport ? "" : table.Rows[i][properties[j].Name]; |
| | | string value = obj?.ToString(); |
| | | if (obj is DateTime time) |
| | | { |
| | | value = time.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | } |
| | | rowTemp.CreateCell(j).SetCellValue(value); |
| | | } |
| | | } |
| | | |
| | | using (FileStream fs = new FileStream(targetPath, FileMode.OpenOrCreate)) |
| | | { |
| | | workbook.Write(fs); |
| | | } |
| | | } |
| | | |
| | | |
| | | public static List<T> ReadFromExcel<T>(string sourcePath) |
| | | { |
| | |
| | | <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL"> |
| | | <HintPath>..\WPFProject\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL"> |
| | | <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> |
| | | <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.dll</HintPath> |
| | | </Reference> |
| | |
| | | <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXmlFormats.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="System" /> |
| | | <Reference Include="System.Configuration" /> |
| | | <Reference Include="System.Core" /> |
| | | <Reference Include="System.Web" /> |
| | | <Reference Include="System.Xml.Linq" /> |
| | | <Reference Include="System.Data.DataSetExtensions" /> |
| | | <Reference Include="Microsoft.CSharp" /> |
| | |
| | | private static extern uint GetPrivateProfileStringA(string section, string key, |
| | | string def, Byte[] retVal, int size, string filePath); |
| | | |
| | | [DllImport("kernel32")] |
| | | private static extern int GetPrivateProfileSection(string section, byte[] retVal, int size, string filePath); |
| | | |
| | | #endregion |
| | | public static List<string> ReadSections() |
| | | { |
| | |
| | | return true; |
| | | } |
| | | #endregion |
| | | |
| | | public static Dictionary<string, string> GetKeyValuesBySection(string iniFile, string section) |
| | | { |
| | | int size = 65536; |
| | | byte[] buffer = new byte[size]; |
| | | |
| | | Dictionary<string, string> result = new Dictionary<string, string>(); |
| | | int bytesRead = GetPrivateProfileSection(section, buffer, size, iniFile); |
| | | if (bytesRead > 0) |
| | | { |
| | | string sectionData = Encoding.Default.GetString(buffer, 0, bytesRead - 1); |
| | | string[] keyValuePairs = sectionData.Split('\0'); |
| | | |
| | | foreach (string pair in keyValuePairs) |
| | | { |
| | | if (!string.IsNullOrEmpty(pair)) |
| | | { |
| | | int equalSignIndex = pair.IndexOf('='); |
| | | if (equalSignIndex > 0) |
| | | { |
| | | string key = pair.Substring(0, equalSignIndex).Trim(); |
| | | string value = pair.Substring(equalSignIndex + 1).Trim(); |
| | | result[key] = value; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | } |
| | | } |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <packages> |
| | | <package id="log4net" version="3.0.4" targetFramework="net472" /> |
| | | <package id="NPOI" version="2.4.1" targetFramework="net472" /> |
| | | <package id="SharpZipLib" version="1.0.0" targetFramework="net472" /> |
| | | </packages> |
| | |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <None Include="app.config" /> |
| | | <None Include="packages.config" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | |
| | | { |
| | | private BaseConfig config; |
| | | |
| | | private static readonly string[] datas = new string[] { "_CoolerStatus", "_LEDLight", "_Req", "_SetTemp", "_SaveTemp", "_TempDown", "_TempUp", "_AvgTemp" }; |
| | | private static readonly string[] datas = new string[] { "_LEDLight", "_Req", "_SetTemp", "_SaveTemp", "_TempDown", "_TempUp", "_AvgTemp" }; |
| | | |
| | | [ObservableProperty] |
| | | private string header; |
| | |
| | | } |
| | | } |
| | | |
| | | private void TryDeleteData(PLCTagData data) |
| | | { |
| | | if (MsgBoxHelper2.WarnChoose($"确定删除数据: {data.Name} 吗?") == System.Windows.MessageBoxResult.OK) |
| | | { |
| | | Datasource.Remove(data); |
| | | } |
| | | } |
| | | |
| | | private void Button_Click(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | var btn = sender as Button; |
| | |
| | | case "importBtn": |
| | | DoImport(); |
| | | break; |
| | | case "delBtn": |
| | | TryDeleteData((PLCTagData)btn.DataContext); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | |
| | | <Generator>ResXFileCodeGenerator</Generator> |
| | | <LastGenOutput>Resources.Designer.cs</LastGenOutput> |
| | | </EmbeddedResource> |
| | | <None Include="app.config" /> |
| | | <None Include="packages.config" /> |
| | | <None Include="Properties\Settings.settings"> |
| | | <Generator>SettingsSingleFileGenerator</Generator> |
| New file |
| | |
| | | using HMI.Core.Annotation; |
| | | using System.Windows; |
| | | |
| | | [assembly:ThemeInfo( |
| | | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located |
| | | //(used if a resource is not found in the page, |
| | | // or application resource dictionaries) |
| | | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located |
| | | //(used if a resource is not found in the page, |
| | | // app, or any theme specific resource dictionaries) |
| | | )] |
| | | [assembly: PluginClassName("Plugin.DataViewer.DataViewerControl")] |
| New file |
| | |
| | | using System.ComponentModel; |
| | | using System.Globalization; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Data; |
| | | |
| | | namespace Plugin.DataViewer |
| | | { |
| | | public class CustomSortColumnConverter : IValueConverter |
| | | { |
| | | public static CustomSortColumnConverter Instance = new CustomSortColumnConverter(); |
| | | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | if (value as ListSortDirection? == ListSortDirection.Ascending) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | if (value as ListSortDirection? == ListSortDirection.Descending) |
| | | { |
| | | return false; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | return value; |
| | | } |
| | | } |
| | | |
| | | public interface ICustomSortColumn |
| | | { |
| | | public bool? IsAsc { get; set; } |
| | | |
| | | void UpdateOther(bool? value); |
| | | DataGrid GetOwner(); |
| | | } |
| | | |
| | | public class CustomSortTemplateColumn : DataGridTemplateColumn, ICustomSortColumn |
| | | { |
| | | public static DependencyProperty IsAscProperty = DependencyProperty.Register( |
| | | "IsAsc", |
| | | typeof(bool?), |
| | | typeof(DataGridTemplateColumn), |
| | | new FrameworkPropertyMetadata(null)); |
| | | |
| | | public bool? IsAsc |
| | | { |
| | | get => (bool?)GetValue(IsAscProperty); |
| | | set |
| | | { |
| | | SetValue(IsAscProperty, value); |
| | | } |
| | | } |
| | | |
| | | public void UpdateOther(bool? value) |
| | | { |
| | | foreach (var col in DataGridOwner.Columns) |
| | | { |
| | | if (col == this) continue; |
| | | if (col is ICustomSortColumn csc) |
| | | { |
| | | csc.IsAsc = value; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public DataGrid GetOwner() |
| | | { |
| | | return this.DataGridOwner; |
| | | } |
| | | } |
| | | |
| | | public class CustomSortTextColumn : DataGridTextColumn, ICustomSortColumn |
| | | { |
| | | public static DependencyProperty IsAscProperty = DependencyProperty.Register( |
| | | "IsAsc", |
| | | typeof(bool?), |
| | | typeof(DataGridTextColumn), |
| | | new FrameworkPropertyMetadata(null)); |
| | | |
| | | public bool? IsAsc |
| | | { |
| | | get => (bool?)GetValue(IsAscProperty); |
| | | set |
| | | { |
| | | SetValue(IsAscProperty, value); |
| | | } |
| | | } |
| | | public void UpdateOther(bool? value) |
| | | { |
| | | foreach (var col in DataGridOwner.Columns) |
| | | { |
| | | if (col == this) continue; |
| | | if (col is ICustomSortColumn csc) |
| | | { |
| | | csc.IsAsc = value; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public DataGrid GetOwner() |
| | | { |
| | | return this.DataGridOwner; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <hb:SimpleMaskControl x:Class="Plugin.DataViewer.DataViewerControl" |
| | | 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:local="clr-namespace:Plugin.DataViewer" |
| | | mc:Ignorable="d" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:sc="clr-namespace:System.ComponentModel;assembly=System" |
| | | xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <ResourceDictionary> |
| | | <ResourceDictionary.MergedDictionaries> |
| | | <pu:StyleDictionary Includes="Label" /> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | |
| | | <Style x:Key="SB" TargetType="DataGridColumnHeader"> |
| | | <Setter Property="Foreground" Value="{DynamicResource PrimaryColorContract}"/> |
| | | <!--<Setter Property="Background" Value="{DynamicResource PrimaryColor}"/> |
| | | <Setter Property="Foreground" Value="{DynamicResource PrimaryColorContract}"/> |
| | | <Setter Property="BorderBrush" Value="{DynamicResource PrimaryColorContract}"/> |
| | | <Setter Property="BorderThickness" Value="0,0,1,1"/>--> |
| | | <Setter Property="Template"> |
| | | <Setter.Value> |
| | | <ControlTemplate TargetType="DataGridColumnHeader"> |
| | | <Border BorderBrush="#FFF" Background="{DynamicResource PrimaryColor}" |
| | | MouseLeftButtonDown="Grid_MouseLeftButtonUp" |
| | | Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGridColumnHeader}}" |
| | | BorderThickness="0,0,1,1"> |
| | | <Grid Margin="{TemplateBinding Padding}"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition Width="Auto" /> |
| | | <ColumnDefinition Width="*" /> |
| | | <ColumnDefinition Width="Auto" /> |
| | | <ColumnDefinition Width="Auto" /> |
| | | </Grid.ColumnDefinitions> |
| | | <Thumb x:Name="PART_LeftHeaderGripper" Grid.Column="0" HorizontalAlignment="Left" |
| | | Width="1" BorderThickness="0" BorderBrush="Transparent" |
| | | Cursor="SizeWE"/> |
| | | <ContentPresenter Grid.Column="0" |
| | | VerticalAlignment="Center" |
| | | Content="{Binding Column.Header,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGridColumnHeader}}"/> |
| | | <TextBlock VerticalAlignment="Center" Grid.Column="2" Text="" x:Name="sorter"> <!----> |
| | | <TextBlock.Style> |
| | | <Style TargetType="TextBlock"> |
| | | <Setter Property="FontFamily" Value="{StaticResource iconfont}"/> |
| | | <Setter Property="Visibility" Value="Collapsed"/> |
| | | <Style.Triggers> |
| | | |
| | | <!--<DataTrigger Binding="{Binding Column.CustomSort, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGridColumnHeader}}" Value="{x:Null}"> |
| | | <Setter Property="Visibility" Value="Collapsed"/> |
| | | </DataTrigger>--> |
| | | |
| | | <DataTrigger Binding="{Binding Column.IsAsc, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGridColumnHeader}}" Value="false"> |
| | | <Setter Property="Visibility" Value="Visible"/> |
| | | </DataTrigger> |
| | | |
| | | <DataTrigger Binding="{Binding Column.IsAsc, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGridColumnHeader}}" Value="True"> |
| | | <Setter Property="Visibility" Value="Visible"/> |
| | | <Setter Property="LayoutTransform"> |
| | | <Setter.Value> |
| | | <RotateTransform Angle="180"/> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </TextBlock.Style> |
| | | </TextBlock> |
| | | <Thumb x:Name="PART_RightHeaderGripper" Grid.Column="3" HorizontalAlignment="Right" Width="1" BorderThickness="0" |
| | | BorderBrush="Transparent" Cursor="SizeWE"/> |
| | | </Grid> |
| | | </Border> |
| | | </ControlTemplate> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Style> |
| | | |
| | | <Style x:Key="ThisDataGridRow" TargetType="DataGridRow"> |
| | | <Setter Property="Background" Value="White"/> |
| | | <Style.Triggers> |
| | | <Trigger Property="AlternationIndex" Value="1"> |
| | | <Setter Property="Background" Value="#eeeeee"/> |
| | | </Trigger> |
| | | <DataTrigger Binding="{Binding result,Converter={x:Static uic:ResultConverter.Instance}}" Value="FAIL"> |
| | | <Setter Property="Background" Value="{DynamicResource DangerColor}"/> |
| | | <Setter Property="Foreground" Value="{DynamicResource SecondPrimaryColorContract}"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding status,Converter={x:Static uic:ResultConverter.Instance}}" Value="FAIL"> |
| | | <Setter Property="Background" Value="{DynamicResource DangerColor}"/> |
| | | <Setter Property="Foreground" Value="{DynamicResource SecondPrimaryColorContract}"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | |
| | | <Style x:Key="OutLabel" TargetType="Label"> |
| | | <Setter Property="Height" Value="25"/> |
| | | <Setter Property="Padding" Value="0"/> |
| | | <Setter Property="VerticalAlignment" Value="Center"/> |
| | | <Setter Property="HorizontalContentAlignment" Value="Stretch"/> |
| | | <Setter Property="VerticalContentAlignment" Value="Stretch"/> |
| | | <Setter Property="Background" Value="#ffffff"/> |
| | | <Setter Property="BorderThickness" Value="2"/> |
| | | <Setter Property="FontSize" Value="10"/> |
| | | <Setter Property="Foreground" Value="#000000"/> |
| | | </Style> |
| | | |
| | | <Style x:Key="InLabel" TargetType="Label"> |
| | | <Setter Property="VerticalContentAlignment" Value="Center"/> |
| | | <Setter Property="BorderThickness" Value="0"/> |
| | | <Setter Property="pu:LabelHelper.CornerRadius" Value="2,0,0,2"/> |
| | | </Style> |
| | | </ResourceDictionary> |
| | | </UserControl.Resources> |
| | | |
| | | <Border Style="{StaticResource CardBoarder}"> |
| | | <Grid> |
| | | <Grid dp:GridHelper.Space="10" dp:GridHelper.SpaceIgnore="ALL"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition Width="4*"/> |
| | | <ColumnDefinition Width="6*"/> |
| | | </Grid.ColumnDefinitions> |
| | | |
| | | <DockPanel Grid.ColumnSpan="2"> |
| | | <!--<StackPanel DockPanel.Dock="Right" Style="{StaticResource ButtonGroup}"> |
| | | <Button Style="{StaticResource AddBtn}" x:Name="addBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource EditBtn}" x:Name="editBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource RfhBtn}" x:Name="rfhBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource DelBtn}" x:Name="delBtn" Click="Button_Click"/> |
| | | </StackPanel>--> |
| | | <TextBlock Style="{StaticResource TitleBox}" Text="{DynamicResource Dv.Title}"/> |
| | | </DockPanel> |
| | | |
| | | <!--<Grid> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition/> |
| | | </Grid.ColumnDefinitions> |
| | | </Grid>--> |
| | | <StackPanel Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Left" Style="{StaticResource ButtonGroup}"> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" |
| | | Text="SN"/> |
| | | <pu:SearchBox x:Name="snInput" Tag="sn" SearchTextChanged="SearchTextChanged" MinWidth="180" /> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" |
| | | Text="穴位号"/> |
| | | <pu:SearchBox x:Name="positionInput" Tag="position" SearchTextChanged="SearchTextChanged" MinWidth="180" /> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" Text="型号"/> |
| | | <pu:SearchBox x:Name="modelInput" Tag="model" SearchTextChanged="SearchTextChanged" MinWidth="180" /> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" Text="结果"/> |
| | | <pu:SearchBox x:Name="resultInput" Tag="result" SearchTextChanged="SearchTextChanged" MinWidth="180" /> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" |
| | | Text="{DynamicResource App.StartTime}"/> |
| | | <pu:DateTimePicker Style="{StaticResource TimePicker}" |
| | | SelectedDateTime="{x:Null}" x:Name="startTimeInput"/> |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" |
| | | Text="{DynamicResource App.EndTime}"/> |
| | | <pu:DateTimePicker Style="{StaticResource TimePicker}" |
| | | SelectedDateTime="{x:Null}" x:Name="endTimeInput"/> |
| | | |
| | | <Button Style="{StaticResource QueryBtn}" |
| | | x:Name="srhBtn" Click="Button_Click"/> |
| | | |
| | | <Button Style="{StaticResource ResetBtn}" |
| | | x:Name="resetBtn" Click="Button_Click"/> |
| | | </StackPanel> |
| | | |
| | | <Grid Grid.Row="2" Grid.Column="0" dp:GridHelper.Space="5" dp:GridHelper.SpaceIgnore="ALL"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | <RowDefinition Height="Auto"/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <DockPanel> |
| | | <Button DockPanel.Dock="Right" Style="{StaticResource ExportBtn}" |
| | | x:Name="exportBtn" Click="Button_Click"/> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10"> |
| | | |
| | | <Label |
| | | Height="25" |
| | | Padding="0" |
| | | HorizontalContentAlignment="Stretch" |
| | | VerticalContentAlignment="Stretch" |
| | | pu:LabelHelper.CornerRadius="2" |
| | | Background="#ffffff" |
| | | BorderBrush="{DynamicResource PrimaryColor}" |
| | | BorderThickness="2" |
| | | FontSize="10" |
| | | FontWeight="Bold" |
| | | Foreground="#000000"> |
| | | <DockPanel Margin="-1" MinWidth="80"> |
| | | <Label VerticalContentAlignment="Center" BorderThickness="0" Content="ALL" Foreground="{DynamicResource PrimaryColorContract}" |
| | | pu:LabelHelper.CornerRadius="2,0,0,2" DockPanel.Dock="Left" Background="{DynamicResource PrimaryColor}" /> |
| | | <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" Foreground="Black"> |
| | | <Run Text="{Binding TotalCount}"/> |
| | | </TextBlock> |
| | | </DockPanel> |
| | | </Label> |
| | | |
| | | <Label |
| | | Height="25" |
| | | Padding="0" |
| | | HorizontalContentAlignment="Stretch" |
| | | VerticalContentAlignment="Stretch" |
| | | pu:LabelHelper.CornerRadius="2" |
| | | Background="#ffffff" |
| | | BorderBrush="{DynamicResource SuccessColor}" |
| | | BorderThickness="2" |
| | | FontSize="10" |
| | | FontWeight="Bold" |
| | | Foreground="#000000"> |
| | | <DockPanel Margin="-1" MinWidth="80"> |
| | | <Label VerticalContentAlignment="Center" BorderThickness="0" Content="PASS" Foreground="{DynamicResource SuccessColorContrast}" |
| | | pu:LabelHelper.CornerRadius="2,0,0,2" DockPanel.Dock="Left" Background="{DynamicResource SuccessColor}"/> |
| | | <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" Foreground="Black"> |
| | | <Run Text="{Binding PassCount}"/> |
| | | </TextBlock> |
| | | </DockPanel> |
| | | </Label> |
| | | |
| | | <Label |
| | | Height="25" |
| | | Padding="0" |
| | | HorizontalContentAlignment="Stretch" |
| | | VerticalContentAlignment="Stretch" |
| | | pu:LabelHelper.CornerRadius="2" |
| | | Background="#ffffff" |
| | | BorderBrush="{DynamicResource DangerColor}" |
| | | BorderThickness="2" |
| | | FontSize="10" |
| | | FontWeight="Bold" |
| | | Foreground="#000000"> |
| | | <DockPanel Margin="-1" MinWidth="80"> |
| | | <Label VerticalContentAlignment="Center" BorderThickness="0" Content="FAIL" Foreground="{DynamicResource DangerColorContrast}" |
| | | pu:LabelHelper.CornerRadius="2,0,0,2" DockPanel.Dock="Left" Background="{DynamicResource DangerColor}" /> |
| | | <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" Foreground="Black"> |
| | | <Run Text="{Binding FailCount}"/> |
| | | </TextBlock> |
| | | </DockPanel> |
| | | </Label> |
| | | |
| | | </StackPanel> |
| | | |
| | | </DockPanel> |
| | | |
| | | |
| | | |
| | | <DataGrid Grid.Row="1" CanUserSortColumns="False" |
| | | AutoGenerateColumns="False" x:Name="resultTable" |
| | | RowStyle="{StaticResource ThisDataGridRow}" |
| | | Style="{StaticResource DefaultDataGrid}" |
| | | ColumnHeaderStyle="{StaticResource SB}" |
| | | VirtualizingStackPanel.CacheLength="10" |
| | | SelectedItem="{Binding SelectedResult}" |
| | | MouseDoubleClick="resultTable_MouseDoubleClick" |
| | | ColumnHeaderHeight="30"> |
| | | <DataGrid.Columns> |
| | | <DataGridTemplateColumn Header="#" IsReadOnly="True" Width="Auto"> |
| | | <DataGridTemplateColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <TextBlock Text="{Binding Converter={StaticResource rowNumber}, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/> |
| | | </DataTemplate> |
| | | </DataGridTemplateColumn.CellTemplate> |
| | | </DataGridTemplateColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="*" Binding="{Binding sn}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="SN"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="80" Binding="{Binding position}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="穴位号"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="80" Binding="{Binding model}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="型号"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="80" Binding="{Binding result}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="测试结果"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="160" Binding="{Binding time,Converter={x:Static uic:DateStrConverter.Instance}}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="测试时间"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | </DataGrid.Columns> |
| | | </DataGrid> |
| | | |
| | | <pu:Pagination Grid.Row="2" Height="30" Margin="10" HorizontalAlignment="Right" Foreground="Black" |
| | | ItemsBackground="Transparent" |
| | | ItemsCornerRadius="12" |
| | | ItemsSelectedBackground="{DynamicResource SecondPrimaryColor}" |
| | | x:Name="page" CurrentPageChanged="page_CurrentPageChanged" |
| | | CurrentPage="{Binding CurrentPage}" |
| | | MaxPage="{Binding TotalPage}"> |
| | | <pu:Pagination.ItemContainerStyle> |
| | | <Style TargetType="pu:PaginationItem"> |
| | | <Setter Property="MinWidth" Value="30" /> |
| | | <Setter Property="Width" Value="Auto" /> |
| | | <Setter Property="Width" Value="Auto" /> |
| | | </Style> |
| | | </pu:Pagination.ItemContainerStyle> |
| | | </pu:Pagination> |
| | | </Grid> |
| | | |
| | | |
| | | <Grid Grid.Row="2" Grid.Column="1" dp:GridHelper.Space="5" dp:GridHelper.SpaceIgnore="ALL"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | <RowDefinition Height="Auto"/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <DockPanel> |
| | | <Button DockPanel.Dock="Right" Style="{StaticResource ExportBtn}" |
| | | x:Name="exportItemBtn" Click="Button_Click"/> |
| | | <Button DockPanel.Dock="Right" Margin="0,0,10,0" Style="{StaticResource QueryBtn}" |
| | | x:Name="srhItemBtn" Click="Button_Click"/> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10"> |
| | | <Label> |
| | | <DockPanel Margin="-1" MinWidth="80" > |
| | | <Label VerticalContentAlignment="Center" BorderThickness="0" Content="测试结果" Foreground="{DynamicResource SuccessColorContrast}" |
| | | pu:LabelHelper.CornerRadius="2,0,0,2" DockPanel.Dock="Left" Background="Transparent"/> |
| | | <TextBlock VerticalAlignment="Center" Padding="0,0,5,0" |
| | | HorizontalAlignment="Center" FontSize="14" Foreground="{DynamicResource SuccessColorContrast}"> |
| | | <Run Text="{Binding SelectedStatus,Converter={x:Static uic:ResultConverter.Instance}}"/> |
| | | </TextBlock> |
| | | </DockPanel> |
| | | |
| | | <Label.Style> |
| | | <Style TargetType="Label" BasedOn="{StaticResource {x:Static pu:StyleKeys.LabelStyle}}"> |
| | | <Setter Property="pu:LabelHelper.CornerRadius" Value="2"/> |
| | | <Setter Property="Background" Value="{DynamicResource SuccessColor}"/> |
| | | <Setter Property="BorderBrush" Value="{DynamicResource SuccessColor}"/> |
| | | <Setter Property="Height" Value="25"/> |
| | | <Setter Property="Padding" Value="0"/> |
| | | <Setter Property="HorizontalContentAlignment" Value="Center"/> |
| | | <Setter Property="VerticalContentAlignment" Value="Center"/> |
| | | <Setter Property="BorderThickness" Value="2"/> |
| | | <Setter Property="FontSize" Value="10"/> |
| | | <Setter Property="FontWeight" Value="Bold"/> |
| | | <Setter Property="Foreground" Value="Black"/> |
| | | |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding SelectedStatus}" Value="{x:Null}"> |
| | | <Setter Property="Visibility" Value="Collapsed"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding SelectedStatus,Converter={x:Static uic:ResultConverter.Instance}}" Value="FAIL"> |
| | | <Setter Property="Background" Value="{DynamicResource DangerColor}"/> |
| | | <Setter Property="BorderBrush" Value="{DynamicResource DangerColor}"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Label.Style> |
| | | </Label> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" Text="测试项"/> |
| | | <pu:SearchBox x:Name="stepInput" Tag="step" SearchTextChanged="SearchTextChanged" MinWidth="180" /> |
| | | |
| | | <TextBlock Style="{StaticResource TitleBox}" FontSize="{StaticResource ContentFontSize2}" Text="结果"/> |
| | | <pu:SearchBox x:Name="statusInput" Tag="status" SearchTextChanged="SearchTextChanged" MinWidth="180" /> |
| | | |
| | | </StackPanel> |
| | | </DockPanel> |
| | | |
| | | <DataGrid Grid.Row="1" x:Name="testItemTable" ColumnHeaderHeight="30" |
| | | ColumnHeaderStyle="{StaticResource SB}" |
| | | RowStyle="{StaticResource ThisDataGridRow}" |
| | | Style="{StaticResource DefaultDataGrid}"> |
| | | <DataGrid.Columns> |
| | | <DataGridTemplateColumn Header="#" IsReadOnly="True" CanUserResize="False"> |
| | | <DataGridTemplateColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <TextBlock Text="{Binding Converter={StaticResource rowNumber}, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/> |
| | | </DataTemplate> |
| | | </DataGridTemplateColumn.CellTemplate> |
| | | </DataGridTemplateColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="Auto" Binding="{Binding sn}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="SN"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="*" Binding="{Binding step}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="测试项"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="*" Binding="{Binding value}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="测试值"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="80" Binding="{Binding limitDown}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="下限"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="80" Binding="{Binding limitUp}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="上限"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="80" Binding="{Binding unit}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="单位"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="80" Binding="{Binding status}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="结果"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | <local:CustomSortTextColumn IsReadOnly="True" Width="160" Binding="{Binding time,Converter={x:Static uic:DateStrConverter.Instance}}"> |
| | | <local:CustomSortTextColumn.Header> |
| | | <TextBlock Text="测试时间"/> |
| | | </local:CustomSortTextColumn.Header> |
| | | </local:CustomSortTextColumn> |
| | | |
| | | </DataGrid.Columns> |
| | | </DataGrid> |
| | | |
| | | <pu:Pagination Grid.Row="2" Height="30" HorizontalAlignment="Right" Foreground="Black" ItemsBackground="Transparent" |
| | | ItemsCornerRadius="12" |
| | | ItemsSelectedBackground="{DynamicResource SecondPrimaryColor}" |
| | | x:Name="itemPage" CurrentPageChanged="page_CurrentPageChanged" |
| | | CurrentPage="{Binding TestItemPage}" |
| | | MaxPage="{Binding TestItemTotalPage}"> |
| | | <pu:Pagination.ItemContainerStyle> |
| | | <Style TargetType="pu:PaginationItem"> |
| | | <Setter Property="MinWidth" Value="30" /> |
| | | <Setter Property="Cursor" Value="Hand" /> |
| | | <Setter Property="Width" Value="Auto" /> |
| | | </Style> |
| | | </pu:Pagination.ItemContainerStyle> |
| | | </pu:Pagination> |
| | | </Grid> |
| | | <ui:MaskControl Grid.Row="2" Grid.Column="1" x:Name="mask2"/> |
| | | </Grid> |
| | | <ui:MaskControl x:Name="topMask"/> |
| | | </Grid> |
| | | </Border> |
| | | </hb:SimpleMaskControl> |
| New file |
| | |
| | | using CommunityToolkit.Mvvm.ComponentModel; |
| | | using HMI.Base; |
| | | using HMI.Core; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using Microsoft.Win32; |
| | | using Panuon.WPF.UI; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | using System.Data; |
| | | using System.IO; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Controls.Primitives; |
| | | |
| | | namespace Plugin.DataViewer |
| | | { |
| | | public class TestResult |
| | | { |
| | | [ExcelColumn("SN")] |
| | | public string sn { get; set; } |
| | | |
| | | [ExcelColumn("穴位号")] |
| | | public string position { get; set; } |
| | | |
| | | [ExcelColumn("型号")] |
| | | public string model { get; set; } |
| | | |
| | | [ExcelColumn("测试结果")] |
| | | public string result { get; set; } |
| | | |
| | | [ExcelColumn("测试时间")] |
| | | public string time { get; set; } |
| | | } |
| | | |
| | | public class SerialData |
| | | { |
| | | [ExcelColumn("SN")] |
| | | public string sn { get; set; } |
| | | |
| | | [ExcelColumn("穴位号")] |
| | | public string position { get; set; } |
| | | |
| | | [ExcelColumn("型号")] |
| | | public string model { get; set; } |
| | | |
| | | [ExcelColumn("测试项")] |
| | | public string step { get; set; } |
| | | |
| | | [ExcelColumn("测试值")] |
| | | public string value { get; set; } |
| | | |
| | | [ExcelColumn("下限")] |
| | | public string limitDown { get; set; } |
| | | |
| | | [ExcelColumn("上限")] |
| | | public string limitUp { get; set; } |
| | | [ExcelColumn("结果")] |
| | | public string status { get; set; } |
| | | |
| | | [ExcelColumn("单位")] |
| | | public string unit { get; set; } |
| | | |
| | | [ExcelColumn("测试时间")] |
| | | public string time { get; set; } |
| | | } |
| | | |
| | | public class SortParam |
| | | { |
| | | public string name { get; set; } |
| | | public ListSortDirection direction { get; set; } |
| | | public string sort { get; set; } |
| | | } |
| | | |
| | | public class ResultData |
| | | { |
| | | public string sn { get; set; } |
| | | public string position { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// DataViewerControl.xaml 的交互逻辑 |
| | | /// </summary> |
| | | [ObservableObject] |
| | | public partial class DataViewerControl : SimpleMaskControl |
| | | { |
| | | [ObservableProperty] |
| | | private DataView resultView; |
| | | |
| | | [ObservableProperty] |
| | | private ObservableCollection<ResultData> resultData; |
| | | |
| | | [ObservableProperty] |
| | | private long currentPage = 1; |
| | | |
| | | [ObservableProperty] |
| | | private long totalPage = 0; |
| | | |
| | | private int pageSize = 30; |
| | | |
| | | [ObservableProperty] |
| | | private long totalCount; |
| | | |
| | | [ObservableProperty] |
| | | private long passCount; |
| | | |
| | | [ObservableProperty] |
| | | private long failCount; |
| | | |
| | | [ObservableProperty] |
| | | private long testItemPage = 1; |
| | | |
| | | [ObservableProperty] |
| | | private long testItemTotalPage = 0; |
| | | |
| | | [ObservableProperty] |
| | | private object selectedResult; |
| | | |
| | | [ObservableProperty] |
| | | private string selectedStatus; |
| | | |
| | | private SortParam sorter; |
| | | private SortParam itemSorter; |
| | | public DataViewerControl() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | Reset(); |
| | | } |
| | | |
| | | private string[] GetFiles(DateTime? startTime, DateTime? endTime) |
| | | { |
| | | string dir = ParamSetting.DataLogFolder; |
| | | string startName = $"Data_{startTime?.ToString("yyyyMMdd")}"; |
| | | string endName = $"Data_{endTime?.ToString("yyyyMMdd")}"; |
| | | var oldFiles = Directory.GetFiles(dir, "Data_*.db"); |
| | | oldFiles = oldFiles.Where(file => |
| | | { |
| | | var fileName = Path.GetFileNameWithoutExtension(file); |
| | | bool flag = true; |
| | | flag &= (string.Compare(fileName, startName) == 1 || fileName == startName); |
| | | flag &= (string.Compare(endName, fileName) == 1 || fileName == endName); |
| | | return flag; |
| | | }).ToArray(); |
| | | return oldFiles; |
| | | } |
| | | |
| | | private void Reset() |
| | | { |
| | | var today = DateTime.Now; |
| | | var startTime = today.AddDays(-7); |
| | | var end = today.AddDays(1); |
| | | |
| | | snInput.Text = string.Empty; |
| | | positionInput.Text = string.Empty; |
| | | modelInput.Text = string.Empty; |
| | | resultInput.Text = string.Empty; |
| | | |
| | | startTimeInput.SelectedDateTime = DateTime.Parse(startTime.ToString("yyyy-MM-dd 00:00:00")); |
| | | endTimeInput.SelectedDateTime = DateTime.Parse(end.ToString("yyyy-MM-dd 00:00:00")); |
| | | } |
| | | |
| | | private void Button_Click(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | var btn = sender as Button; |
| | | if (btn.Name == "resetBtn") |
| | | { |
| | | Reset(); |
| | | if (CurrentPage == 1) |
| | | { |
| | | SelectPage(1, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | CurrentPage = 1; |
| | | } |
| | | return; |
| | | } |
| | | if (btn.Name == "srhBtn") |
| | | { |
| | | if (CurrentPage == 1) |
| | | { |
| | | SelectPage(1, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | CurrentPage = 1; |
| | | } |
| | | return; |
| | | } |
| | | |
| | | if (btn.Name == "srhItemBtn") |
| | | { |
| | | if (TestItemPage == 1) |
| | | { |
| | | RefreshTestItem(this.selectResultId, 1, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | TestItemPage = 1; |
| | | } |
| | | return; |
| | | } |
| | | |
| | | if (btn.Name == "exportBtn") |
| | | { |
| | | TryExport(); |
| | | } |
| | | |
| | | if (btn.Name == "exportItemBtn") |
| | | { |
| | | TryExportItem(); |
| | | } |
| | | } |
| | | |
| | | private void TryExport() |
| | | { |
| | | SaveFileDialog sfd = new SaveFileDialog |
| | | { |
| | | Filter = "Excel 文件 (*.xls)|*.xls" |
| | | }; |
| | | if (sfd.ShowDialog() != true) |
| | | { |
| | | return; |
| | | } |
| | | string filePath = sfd.FileName; |
| | | |
| | | DateTime? startTime = startTimeInput.SelectedDateTime, endTime = endTimeInput.SelectedDateTime; |
| | | |
| | | topMask.ShowMask(this, () => |
| | | { |
| | | var table = SelectResult(startTime, endTime); |
| | | |
| | | ExcelHelper.ExportExcel<TestResult>(filePath, table); |
| | | |
| | | }, (ex) => |
| | | { |
| | | log.Error("Export Result Failed.", ex); |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | MsgBoxHelper2.Error($"导出失败!{ex.Message}"); |
| | | }); |
| | | }, "导出中,请稍后..."); |
| | | } |
| | | |
| | | private void TryExportItem() |
| | | { |
| | | SaveFileDialog sfd = new SaveFileDialog |
| | | { |
| | | Filter = "Excel 文件 (*.xls)|*.xls" |
| | | }; |
| | | if (sfd.ShowDialog() != true) |
| | | { |
| | | return; |
| | | } |
| | | string filePath = sfd.FileName; |
| | | |
| | | DateTime? startTime = startTimeInput.SelectedDateTime, endTime = endTimeInput.SelectedDateTime; |
| | | |
| | | topMask.ShowMask(this, () => |
| | | { |
| | | var table = SelectItem(startTime, endTime); |
| | | |
| | | ExcelHelper.ExportExcel<SerialData>(filePath, table); |
| | | |
| | | }, (ex) => |
| | | { |
| | | log.Error("Export Result Failed.", ex); |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | MsgBoxHelper2.Error($"导出失败!{ex.Message}"); |
| | | }); |
| | | }, "导出中,请稍后..."); |
| | | } |
| | | |
| | | private DataTable SelectResult(DateTime? startTime, DateTime? endTime) |
| | | { |
| | | var files = GetFiles(startTime, endTime); |
| | | if (files == null || files.Length <= 0) |
| | | { |
| | | return new DataTable(); |
| | | } |
| | | using (var helper = new Sqlite3Helper(files[0])) |
| | | { |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'"; |
| | | helper.Execute(attach); |
| | | } |
| | | |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | if (!helper.HasData($"SELECT 1 FROM pragma_table_info('testResult','db{i}') WHERE name = 'resultId';")) |
| | | { |
| | | helper.Execute($"ALTER TABLE db{i}.testResult ADD resultId TEXT;"); |
| | | } |
| | | } |
| | | |
| | | string sql = string.Join(" UNION ALL ", GetResultSqlsByFiles(files, startTime, endTime)); |
| | | string sortName = "time", sortDirection = "DESC"; |
| | | string baseSql = $"SELECT id,sn,model,station,position,result,time,resultId FROM ({sql}) as _temp"; |
| | | |
| | | |
| | | |
| | | sql = $"{baseSql} ORDER BY {sortName} {sortDirection}"; |
| | | |
| | | return helper.GetDataTable(sql); |
| | | |
| | | //for (int i = 0; i < files.Length; i++) |
| | | //{ |
| | | // helper.Execute($"DETACH DATABASE db{i}"); |
| | | //} |
| | | } |
| | | } |
| | | |
| | | private DataTable SelectItem(DateTime? startTime, DateTime? endTime) |
| | | { |
| | | if (string.IsNullOrEmpty(this.selectResultId)) |
| | | { |
| | | return new DataTable(); |
| | | } |
| | | var files = GetFiles(startTime, endTime); |
| | | if (files == null || files.Length <= 0) |
| | | { |
| | | return new DataTable(); |
| | | } |
| | | using (var helper = new Sqlite3Helper(files[0])) |
| | | { |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'"; |
| | | helper.Execute(attach); |
| | | } |
| | | |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | if (!helper.HasData($"SELECT 1 FROM pragma_table_info('serialData','db{i}') WHERE name = 'resultId';")) |
| | | { |
| | | helper.Execute($"ALTER TABLE db{i}.serialData ADD resultId TEXT;"); |
| | | } |
| | | } |
| | | |
| | | string sql = string.Join(" UNION ALL ", GetTestItemSqlsByFiles(this.selectResultId, files)); |
| | | |
| | | string sortName = "time", sortDirection = "DESC"; |
| | | |
| | | string baseSql = $"SELECT sn, position, model,step, limitDown, limitUp,unit, value,status,time FROM ({sql}) as _temp"; |
| | | |
| | | sql = $"{baseSql} ORDER BY {sortName} {sortDirection}"; |
| | | |
| | | return helper.GetDataTable(sql); |
| | | |
| | | |
| | | //for (int i = 0; i < files.Length; i++) |
| | | //{ |
| | | // helper.Execute($"DETACH DATABASE db{i}"); |
| | | //} |
| | | } |
| | | } |
| | | |
| | | private void SelectPage(long page, long pageSize) |
| | | { |
| | | try |
| | | { |
| | | var files = GetFiles(startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime); |
| | | if (files == null || files.Length <= 0) |
| | | { |
| | | return; |
| | | } |
| | | using (var helper = new Sqlite3Helper(files[0])) |
| | | { |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'"; |
| | | helper.Execute(attach); |
| | | } |
| | | |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | if (!helper.HasData($"SELECT 1 FROM pragma_table_info('testResult','db{i}') WHERE name = 'resultId';")) |
| | | { |
| | | helper.Execute($"ALTER TABLE db{i}.testResult ADD resultId TEXT;"); |
| | | } |
| | | } |
| | | |
| | | string sql = string.Join(" UNION ALL ", GetResultSqlsByFiles(files, startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime)); |
| | | string sortName = "time", sortDirection = "DESC"; |
| | | |
| | | if (sorter != null) |
| | | { |
| | | sortName = sorter.name; |
| | | sortDirection = sorter.sort; |
| | | } |
| | | string countSql = $"SELECT COUNT(1) FROM ({sql}) as _temp"; |
| | | long total = (long)helper.SelectOne(countSql); |
| | | |
| | | string baseSql = $"SELECT id,sn,model,station,position,result,time,resultId FROM ({sql}) as _temp"; |
| | | |
| | | |
| | | |
| | | sql = $"{baseSql} ORDER BY {sortName} {sortDirection} LIMIT {pageSize} OFFSET {(page - 1) * pageSize}"; |
| | | |
| | | var dt = helper.GetDataTable(sql); |
| | | |
| | | TotalPage = total / pageSize + (total % pageSize > 0 ? 1 : 0); |
| | | resultTable.ItemsSource = dt.DefaultView; |
| | | |
| | | sql = $"SELECT result,COUNT(1) as num FROM ({baseSql}) GROUP BY result"; |
| | | var nums = helper.GetDataTable(sql); |
| | | |
| | | long all = 0, pass = 0, fail = 0; |
| | | foreach (DataRow row in nums.Rows) |
| | | { |
| | | if ("ok".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase) |
| | | || "pass".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | pass += (long)row["num"]; |
| | | all += (long)row["num"]; |
| | | } |
| | | if ("ng".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase) |
| | | || "fail".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | fail += (long)row["num"]; |
| | | all += (long)row["num"]; |
| | | } |
| | | } |
| | | |
| | | TotalCount = all; |
| | | PassCount = pass; |
| | | FailCount = fail; |
| | | |
| | | //for (int i = 0; i < files.Length; i++) |
| | | //{ |
| | | // helper.Execute($"DETACH DATABASE db{i}"); |
| | | //} |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Select TestResult Error.", ex); |
| | | |
| | | } |
| | | } |
| | | |
| | | private void RefreshTestItem(string resultId, long page, int pageSize) |
| | | { |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(resultId)) |
| | | { |
| | | testItemTable.ItemsSource = new DataTable().DefaultView; |
| | | return; |
| | | } |
| | | |
| | | var files = GetFiles(startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime); |
| | | if (files == null || files.Length <= 0) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | string sql = string.Join(" UNION ALL ", GetTestItemSqlsByFiles(resultId, files)); |
| | | string sortName = "time", sortDirection = "DESC"; |
| | | if (itemSorter != null) |
| | | { |
| | | sortName = itemSorter.name; |
| | | sortDirection = itemSorter.sort; |
| | | } |
| | | |
| | | mask2.ShowMask(null, () => |
| | | { |
| | | using (var helper = new Sqlite3Helper(files[0])) |
| | | { |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'"; |
| | | helper.Execute(attach); |
| | | } |
| | | |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | if (!helper.HasData($"SELECT 1 FROM pragma_table_info('serialData','db{i}') WHERE name = 'resultId';")) |
| | | { |
| | | helper.Execute($"ALTER TABLE db{i}.serialData ADD resultId TEXT;"); |
| | | } |
| | | } |
| | | |
| | | |
| | | string countSql = $"SELECT COUNT(1) FROM ({sql}) as _temp"; |
| | | long total = (long)helper.SelectOne(countSql); |
| | | |
| | | string baseSql = $"SELECT sn, model,step, limitDown, limitUp,unit, value,status,time FROM ({sql}) as _temp"; |
| | | |
| | | sql = $"{baseSql} ORDER BY {sortName} {sortDirection} LIMIT {pageSize} OFFSET {(page - 1) * pageSize}"; |
| | | |
| | | var dt = helper.GetDataTable(sql); |
| | | |
| | | |
| | | //for (int i = 0; i < files.Length; i++) |
| | | //{ |
| | | // helper.Execute($"DETACH DATABASE db{i}"); |
| | | //} |
| | | |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | TestItemTotalPage = total / pageSize + (total % pageSize > 0 ? 1 : 0); |
| | | testItemTable.ItemsSource = dt.DefaultView; |
| | | }, System.Windows.Threading.DispatcherPriority.Normal); |
| | | } |
| | | }, (ex) => |
| | | { |
| | | log.Error("Select TestItem Error.", ex); |
| | | }, |
| | | "查询中..."); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Try Select TestItem Error.", ex); |
| | | } |
| | | } |
| | | |
| | | public string[] GetResultSqlsByFiles(string[] files, DateTime? startTime, DateTime? endTime) |
| | | { |
| | | string sn = string.Empty, position = string.Empty, model = string.Empty, result = string.Empty; |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | sn = snInput.Text; |
| | | position = positionInput.Text; |
| | | model = modelInput.Text; |
| | | result = resultInput.Text; |
| | | }); |
| | | |
| | | string[] sqls = new string[files.Length]; |
| | | List<string> querys = new List<string>(); |
| | | if (!string.IsNullOrEmpty(sn)) |
| | | { |
| | | querys.Add($"sn = '{sn}'"); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(position)) |
| | | { |
| | | querys.Add($"position = '{position}'"); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(model)) |
| | | { |
| | | querys.Add($"model = '{model}'"); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(result)) |
| | | { |
| | | querys.Add($"result = '{result}'"); |
| | | } |
| | | |
| | | if (startTime != null) |
| | | { |
| | | querys.Add($"time >= '{startTime.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"); |
| | | } |
| | | |
| | | if (endTime != null) |
| | | { |
| | | querys.Add($"time < '{endTime.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"); |
| | | } |
| | | |
| | | string segment = ""; |
| | | if (querys.Count > 0) |
| | | { |
| | | segment = $" WHERE {string.Join(" AND ", querys)}"; |
| | | } |
| | | |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | sqls[i] = $"SELECT id,sn,model,station,position,result,time,resultId FROM db{i}.testResult {segment}"; |
| | | } |
| | | return sqls; |
| | | } |
| | | |
| | | private string[] GetTestItemSqlsByFiles(string resultId, string[] files) |
| | | { |
| | | List<string> querys = new List<string>() { |
| | | $"resultId = '{resultId}'" |
| | | }; |
| | | string step = string.Empty, status = string.Empty; |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | step = stepInput.Text; |
| | | status = statusInput.Text; |
| | | }); |
| | | |
| | | |
| | | if (!string.IsNullOrEmpty(step)) |
| | | { |
| | | querys.Add($"step = '{step}'"); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(status)) |
| | | { |
| | | querys.Add($"status = '{status}'"); |
| | | } |
| | | |
| | | string segment = string.Join(" AND ", querys); ; |
| | | |
| | | string[] sqls = new string[files.Length]; |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | sqls[i] = $"SELECT sn, position, model,step, limitDown, limitUp,unit, value,status,time FROM db{i}.serialData WHERE {segment}"; |
| | | } |
| | | return sqls; |
| | | } |
| | | |
| | | public string[] GetSource(string[] files, string name, string tableName, string value) |
| | | { |
| | | try |
| | | { |
| | | if (files == null || files.Length <= 0) |
| | | { |
| | | return new string[0]; |
| | | } |
| | | string[] GetModelSqls() |
| | | { |
| | | string[] sqls = new string[files.Length]; |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | sqls[i] = $"SELECT DISTINCT {name} FROM db{i}.{tableName} WHERE {name} LIKE '%{value}%'"; |
| | | } |
| | | return sqls; |
| | | } |
| | | |
| | | using (var helper = new Sqlite3Helper(files[0])) |
| | | { |
| | | for (int i = 0; i < files.Length; i++) |
| | | { |
| | | var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'"; |
| | | helper.Execute(attach); |
| | | } |
| | | string sql = string.Join(" UNION ", GetModelSqls()); |
| | | sql = $"SELECT DISTINCT {name} FROM ({sql}) LIMIT 10"; |
| | | |
| | | var dt = helper.GetDataTable(sql); |
| | | return dt.Select().Select(row => row[name].ToString()).ToArray(); |
| | | } |
| | | return new string[0]; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return new string[0]; |
| | | } |
| | | } |
| | | |
| | | |
| | | private void SearchTextChanged(object sender, Panuon.WPF.SearchTextChangedRoutedEventArgs e) |
| | | { |
| | | SearchBox sb = sender as SearchBox; |
| | | string tag = sb.Tag.ToString(), value = sb.Text; |
| | | var files = GetFiles(startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime); |
| | | Task.Run(() => |
| | | { |
| | | string[] items = new string[0]; |
| | | if (tag == "step" || tag == "status") |
| | | { |
| | | items = GetSource(files, tag, "serialData", value); |
| | | } |
| | | else |
| | | { |
| | | items = GetSource(files, tag, "testResult", value); |
| | | } |
| | | Dispatcher.BeginInvoke(new Action(() => |
| | | { |
| | | sb.ItemsSource = items; |
| | | }), System.Windows.Threading.DispatcherPriority.Normal); |
| | | }); |
| | | } |
| | | |
| | | private void Grid_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | var border = sender as Border; |
| | | var header = border.Tag as DataGridColumnHeader; |
| | | var col = header.Column as ICustomSortColumn; |
| | | |
| | | if (col == null) return; |
| | | |
| | | col.UpdateOther(null); |
| | | |
| | | var dataGrid = col.GetOwner(); |
| | | |
| | | if (col.IsAsc == null) |
| | | { |
| | | col.IsAsc = true; |
| | | |
| | | if (dataGrid == resultTable) |
| | | { |
| | | sorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Ascending, sort = "ASC" }; |
| | | } |
| | | else { |
| | | itemSorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Ascending, sort = "ASC" }; |
| | | } |
| | | |
| | | } |
| | | else if (col.IsAsc == true) |
| | | { |
| | | col.IsAsc = false; |
| | | if (dataGrid == resultTable) |
| | | { |
| | | sorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Descending, sort = "DESC" }; |
| | | } |
| | | else |
| | | { |
| | | itemSorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Descending, sort = "DESC" }; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | col.IsAsc = null; |
| | | if (dataGrid == resultTable) |
| | | { |
| | | sorter = null; |
| | | } |
| | | else |
| | | { |
| | | itemSorter = null; |
| | | } |
| | | } |
| | | |
| | | if (dataGrid == resultTable) |
| | | { |
| | | if (CurrentPage == 1) |
| | | { |
| | | SelectPage(1, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | CurrentPage = 1; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (TestItemPage == 1) |
| | | { |
| | | RefreshTestItem(this.selectResultId, 1, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | TestItemPage = 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void page_CurrentPageChanged(object sender, Panuon.WPF.SelectedValueChangedRoutedEventArgs<int> e) |
| | | { |
| | | if (sender == page) |
| | | { |
| | | SelectPage(e.NewValue, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | RefreshTestItem(this.selectResultId, e.NewValue, this.pageSize); |
| | | } |
| | | } |
| | | |
| | | private string selectResultId; |
| | | |
| | | partial void OnSelectedResultChanged(object value) |
| | | { |
| | | if (value != null) |
| | | { |
| | | return; |
| | | } |
| | | var selectedRow = value as DataRowView; |
| | | var resultId = selectedRow?["resultId"]?.ToString(); |
| | | this.SelectedStatus = selectedRow?["result"]?.ToString(); |
| | | this.selectResultId = resultId; |
| | | |
| | | if (TestItemPage == 1) |
| | | { |
| | | RefreshTestItem(resultId, 1, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | TestItemPage = 1; |
| | | } |
| | | } |
| | | |
| | | private void resultTable_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | var selectedRow = this.SelectedResult as DataRowView; |
| | | var resultId = selectedRow?["resultId"]?.ToString(); |
| | | this.SelectedStatus = selectedRow?["result"]?.ToString(); |
| | | this.selectResultId = resultId; |
| | | |
| | | if (TestItemPage == 1) |
| | | { |
| | | RefreshTestItem(resultId, 1, this.pageSize); |
| | | } |
| | | else |
| | | { |
| | | TestItemPage = 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <OutputType>Library</OutputType> |
| | | <TargetFramework>net472</TargetFramework> |
| | | <Nullable>enable</Nullable> |
| | | <LangVersion>10.0</LangVersion> |
| | | <ImplicitUsings>enable</ImplicitUsings> |
| | | <UseWPF>true</UseWPF> |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> |
| | | <PackageReference Include="log4net" Version="3.0.4" /> |
| | | <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" /> |
| | | <PackageReference Include="Panuon.WPF.UI" Version="1.3.0.2" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\HMI.Base\HMI.Base.csproj" /> |
| | | <ProjectReference Include="..\HMI.Core\HMI.Core.csproj" /> |
| | | <ProjectReference Include="..\HMI.UI\HMI.UI.csproj" /> |
| | | <ProjectReference Include="..\HMI.Util\HMI.Util.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| | |
| | | <RowDefinition/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition Width="Auto"/> |
| | | <ColumnDefinition/> |
| | | </Grid.ColumnDefinitions> |
| | | |
| | | |
| | | <TextBlock FontSize="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='20,940'}" |
| | | FontWeight="Bold" |
| | |
| | | <!--<local:Chart Grid.Row="2" x:Name="chart" BorderThickness="0,1,0,1" BorderBrush="Black" |
| | | MouseDoubleClick="chart_MouseDoubleClick"/>--> |
| | | |
| | | <StatusBar FontSize="18" Grid.Row="3"> |
| | | <StatusBar FontSize="14" Grid.Row="3"> |
| | | <StatusBar.ItemsPanel> |
| | | <ItemsPanelTemplate> |
| | | <DockPanel/> |
| | |
| | | </StatusBarItem> |
| | | |
| | | <StatusBarItem > |
| | | <TextBox IsReadOnly="True" Background="Transparent" BorderThickness="0" Text="{Binding statusText}"/> |
| | | <TextBox IsReadOnly="True" FontSize="16" Background="Transparent" BorderThickness="0" Text="{Binding statusText}"/> |
| | | </StatusBarItem> |
| | | </StatusBar> |
| | | |
| | | <Grid Grid.Row="4"> |
| | | <Grid.ColumnDefinitions> |
| | | <UniformGrid Grid.Row="4" Rows="1"> |
| | | <!--<UniformGrid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | <ColumnDefinition/> |
| | | </Grid.ColumnDefinitions> |
| | | </UniformGrid.ColumnDefinitions>--> |
| | | <Button Click="ScanWindow_Click" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Tr.Scan}"/> |
| | | <Button Grid.Column="1" Click="ClearAllSnr_Click" Style="{StaticResource DangerButton}" |
| | | IsEnabled="{Binding IsTesting,Converter={StaticResource reverseBool}}" |
| | | Content="{DynamicResource Tr.ClearAllSNR}"/> |
| | | <!--<Button Grid.Column="2" Click="SetStationGlobal_Click" Style="{StaticResource SuccessButton}" |
| | | Content="{DynamicResource App.Start}"/>--> |
| | | <Button Grid.Column="2" Click="StartSingleClick"> |
| | | Content="{DynamicResource App.Start}"/> Background="#1296db"--> |
| | | |
| | | <Button Grid.Column="2" Click="Abort_Click" x:Name="abortBtn" |
| | | Style="{DynamicResource DangerButton}" Background="#1296db" Content="Abort"/> |
| | | |
| | | <Button Grid.Column="3" Click="StartSingleClick"> |
| | | <Button.Style> |
| | | <Style TargetType="Button" BasedOn="{StaticResource SuccessButton}"> |
| | | <Setter Property="Content" Value="{DynamicResource App.Start}"/> |
| | |
| | | </Style> |
| | | </Button.Style> |
| | | </Button> |
| | | </Grid> |
| | | |
| | | </UniformGrid> |
| | | </Grid> |
| | | </UserControl> |
| | |
| | | using HMI.Core.Setting; |
| | | using HMI.Base; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.LogUtil; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using Plugin.TestResult; |
| | | using Plugin.TestResult.Util; |
| | | using Plugin.TestResult_WPF.Model; |
| | | using Plugin.TsSupport; |
| | | using SuperSocket.SocketBase.Config; |
| | | using SuperSocket.SocketBase.Protocol; |
| | | using System; |
| | |
| | | using System.Timers; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Markup; |
| | | |
| | | namespace Plugin.TestResult_WPF |
| | | { |
| | |
| | | public int index { get; private set; } |
| | | private readonly int cellCount; |
| | | private readonly string chartTitle; |
| | | private readonly TestResultView parent; |
| | | public readonly TestResultView parent; |
| | | |
| | | private BaseConfig config; |
| | | private LiveChart chart; |
| | |
| | | { |
| | | var cellRow = (i / config.PositionColumn) + 1; |
| | | var cellCol = (i % config.PositionColumn) + 1; |
| | | var cellTitle = $"{title}-{cellRow}-{cellCol}"; |
| | | var cellTitle = $"{title}-{cellRow}-{cellCol}"; |
| | | |
| | | var cell = new SingleCell(this, cellTitle, i, config.CellListMaxSize, countIniPath); |
| | | mainGrid.Children.Add(cell); |
| | |
| | | testTimeTimer.AutoReset = true; |
| | | testTimeTimer.Elapsed += TestTimeTimer_Elapsed; |
| | | if (!ParamSetting.ShowCoolerSetting) coolerSetting.Visibility = Visibility.Collapsed; |
| | | if (!ParamSetting.ShowBurnInAbort) abortBtn.Visibility = Visibility.Collapsed; |
| | | } |
| | | |
| | | private void TestTimeTimer_Elapsed(object sender, ElapsedEventArgs e) |
| | |
| | | { |
| | | if (MsgBoxHelper2.WarnChoose(this.lang("Tr.MakeSureStopOvenTest", title)) == MessageBoxResult.OK) |
| | | { |
| | | LogHelper.Info("UI", $"老化炉[{title}]停止按钮按下", out _); |
| | | ViewControl.Logger.Info($"老化炉[{title}]停止按钮按下"); |
| | | parent.SetStartFlag(this.index, false); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | ClearChartData(); |
| | | parent.SetStartFlag(this.index, true); |
| | | /// 检查是否关门 |
| | | if (parent.executionWrapper?.GetStationGlobalValue<bool>($"StationState.DoorClose[{this.index}]", 0) != true) |
| | | { |
| | | /// 没关门不允许启动 |
| | | MsgBoxHelper2.Warn("请先关闭舱门!"); |
| | | return; |
| | | } |
| | | |
| | | /// 检查是否有条码 |
| | | bool flag = false; |
| | | foreach (var cell in cells) |
| | | { |
| | | if (!string.IsNullOrEmpty(cell.sn)) |
| | | { |
| | | flag = true; |
| | | break; |
| | | } |
| | | } |
| | | if (flag) |
| | | { |
| | | LogHelper.Info("UI", $"老化炉[{title}]启动按钮按下", out _); |
| | | ViewControl.Logger.Info($"老化炉[{title}]启动按钮按下"); |
| | | ClearChartData(); |
| | | parent.SetStartFlag(this.index, true); |
| | | } |
| | | else |
| | | { |
| | | MsgBoxHelper2.Warn("请先完成扫码!"); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | private void Scanner_ComplateClick(object sender, RoutedEventArgs e) |
| | | { |
| | | string paramName = $"StationState.Scanner[{index}]"; |
| | | parent.engine.Globals.SetValBoolean(paramName, 1, true); |
| | | //parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | |
| | | parent.executionWrapper.SetStationGlobalValue<bool>(paramName, 1, true); |
| | | //parent.engine.Globals.SetValBoolean(paramName, 1, true); |
| | | } |
| | | |
| | | private void Scanner_Closed(object sender, EventArgs e) |
| | |
| | | |
| | | private void Scanner_FinishBarcode(object sender, BarcodeEventArg e) |
| | | { |
| | | if (parent.SequenceContext == null) return; |
| | | if (parent.executionWrapper == null) return; |
| | | //if (parent.SequenceContext == null) return; |
| | | |
| | | int rows = (config.CellCount / config.PositionColumn) + 1; |
| | | CellInfo cellInfo = ScannerParser.GetCellInfoByCode(CbProduct.SelectedItem?.ToString(), mainGrid.Columns, rows, e.positionCode); |
| | |
| | | throw new Exception(this.lang("Tr.PositionCantClearSNR", oldCellInfo.OriginCode)); |
| | | } |
| | | // 移除条码 |
| | | parent.engine.Globals.SetValString(oldCellInfo.LookUpStr, 1, ""); |
| | | parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | parent.executionWrapper.SetStationGlobalValue<string>(oldCellInfo.LookUpStr, 1, ""); |
| | | parent.executionWrapper.CommitToDisk(false); |
| | | |
| | | //parent.engine.Globals.SetValString(oldCellInfo.LookUpStr, 1, ""); |
| | | //parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | oldCell.SetStatus("waiting"); |
| | | oldCell.ClearSN(); |
| | | return; |
| | |
| | | } |
| | | |
| | | // 写入条码 |
| | | parent.engine.Globals.SetValString(LookupStr, 1, snrCode); |
| | | parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | parent.executionWrapper.SetStationGlobalValue<string>(LookupStr, 1, snrCode); |
| | | parent.executionWrapper.CommitToDisk(false); |
| | | |
| | | //parent.engine.Globals.SetValString(LookupStr, 1, snrCode); |
| | | //parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | |
| | | TestResultView.nameTables[cellInfo.OvenName].GetSingleCell(cellInfo.Index).SetStatus("hadCode"); |
| | | TestResultView.nameTables[cellInfo.OvenName].GetSingleCell(cellInfo.Index).sn = snrCode; |
| | |
| | | string strs = datas_10015[2]; |
| | | string[] values = strs.Split(','); |
| | | |
| | | //string step = datas_10015[2]; |
| | | //string result = datas_10015[3]; |
| | | GetSingleCell(cellIndex).SetInfos(new Info |
| | | { |
| | | step = values[0], |
| | |
| | | |
| | | private void ClearAllSnr_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | var str = $"StationState.DoorClose[{index}]"; |
| | | if (parent.engine.Globals.GetValBoolean(str, 0) == true) |
| | | if (parent.executionWrapper?.GetStationGlobalValue<bool>($"StationState.DoorClose[{this.index}]", 0) == true) |
| | | { |
| | | MsgBoxHelper.Error(Window.GetWindow(this), this.lang("Tr.CantClearSNR")); |
| | | /// 关门了就不允许清条码 |
| | | MsgBoxHelper2.Warn(this.lang("Tr.CantClearSNR")); |
| | | return; |
| | | } |
| | | |
| | |
| | | |
| | | public void TryClearCellSN(int cellIndex) |
| | | { |
| | | var str = $"StationState.DoorClose[{this.index}]"; |
| | | if (parent.engine.Globals.GetValBoolean(str, 0) == true) |
| | | if (parent.executionWrapper?.GetStationGlobalValue<bool>($"StationState.DoorClose[{this.index}]", 0) == true) |
| | | { |
| | | MsgBoxHelper.Error(Window.GetWindow(this), this.lang("Tr.CantClearSNR")); |
| | | return; |
| | |
| | | string LookupStr = $"StationState.SN[{dutNo}]"; |
| | | var lastSN = cell.sn; |
| | | cell.SetStatus("waiting"); |
| | | parent.engine.Globals.SetValString(LookupStr, 1, ""); |
| | | parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | |
| | | parent.executionWrapper.SetStationGlobalValue<string>(LookupStr, 1, ""); |
| | | parent.executionWrapper.CommitToDisk(false); |
| | | |
| | | //parent.engine.Globals.SetValString(LookupStr, 1, ""); |
| | | //parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | if (!string.IsNullOrEmpty(lastSN)) Scanner.RemoveSNR(lastSN); |
| | | cell.ClearSN(); |
| | | } |
| | | |
| | | private void Button_Click_2(object sender, RoutedEventArgs e) |
| | | private void Abort_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | if (MsgBoxHelper.WarnMessage(Window.GetWindow(this), this.lang("Tr.MakeSureStopOvenTest", title)) == MessageBoxResult.OK) |
| | | if (!parent.IsRunning) |
| | | { |
| | | parent.SetStartFlag(this.index, false); |
| | | MsgBoxHelper.WarnMessage(this, this.lang("Tr.StartSeqFirst"), null, MessageBoxButton.OK); |
| | | return; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | string key = $"StationState.Start[{this.index}]"; |
| | | //if (parent.executionWrapper?.GetStationGlobalValue<bool>(key, 0) == true) |
| | | //{ |
| | | // MsgBoxHelper2.Warn("测试启动中,不允许Abort"); |
| | | // return; |
| | | //} |
| | | var win = new RequirePasswordByUser("admin") |
| | | { |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (win.ShowDialog() != true) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | if (MsgBoxHelper2.WarnChoose("请确认老化仓在安全温度,水冷机吹水完成,单击OK按钮仓位回到初始化状态") != MessageBoxResult.OK) |
| | | { |
| | | return; |
| | | } |
| | | LogHelper.Info("UI", "Abort按钮按下", out _); |
| | | ViewControl.Logger.Info("Abort按钮按下"); |
| | | key = $"StationState.Abort[{this.index}]"; |
| | | parent.executionWrapper?.SetStationGlobalValue(key, 0, true); |
| | | } |
| | | } |
| | | } |
| | |
| | | CanUserDeleteRows="False" |
| | | IsReadOnly="True" |
| | | ColumnWidth="*" |
| | | VirtualizingStackPanel.VirtualizationMode="Standard" |
| | | VirtualizingPanel.IsContainerVirtualizable="True" |
| | | VirtualizingPanel.IsVirtualizing="True" |
| | | VirtualizingStackPanel.VirtualizationMode="Recycling" |
| | | FontSize="16"> |
| | | <DataGrid.Resources> |
| | | <Style TargetType="ScrollBar" BasedOn="{StaticResource ScrollStyle_Mobile}"/> |
| New file |
| | |
| | | using HMI.Core.Manager; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace Plugin.TestResult.Lixun |
| | | { |
| | | public class SNValidator |
| | | { |
| | | public static bool ValidateSN(string model, string sn, out string msg) |
| | | { |
| | | msg = string.Empty; |
| | | string validate = string.Empty; |
| | | try |
| | | { |
| | | validate = ProductManager.GetParameterByProductAndName(model, "SNRValidate")?.Value; |
| | | if (string.IsNullOrEmpty(validate)) |
| | | { |
| | | msg = $"当前型号[{model}]未配置SNRValidate参数,无法校验SN合法性"; |
| | | return true; |
| | | } |
| | | string[] arr = validate.Split(';'); |
| | | if (arr.Length == 1) |
| | | { |
| | | if (!sn.Contains(arr[0])) |
| | | { |
| | | msg = $"条码不包含固定码[{arr[0]}]"; |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | if (arr.Length == 2) |
| | | { |
| | | int length = int.Parse(arr[1]); |
| | | if (!sn.Contains(arr[0])) |
| | | { |
| | | msg = $"条码不包含固定码[{arr[0]}]"; |
| | | return false; |
| | | } |
| | | if (sn.Length != length) |
| | | { |
| | | msg = $"条码长度应为[{length}]"; |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | if (arr.Length >= 3) |
| | | { |
| | | int length = int.Parse(arr[1]); |
| | | int startIndex = int.Parse(arr[2]); |
| | | |
| | | if (sn.Length != length) |
| | | { |
| | | msg = $"条码长度应为[{length}]"; |
| | | return false; |
| | | } |
| | | |
| | | if (startIndex >= sn.Length) |
| | | { |
| | | msg = $"条码长读小于起始下标[{validate}]"; |
| | | return false; |
| | | } |
| | | |
| | | if (arr[0].Length > sn.Length) |
| | | { |
| | | msg = $"条码长读小于固定码长度[{validate}]"; |
| | | return false; |
| | | } |
| | | |
| | | if (sn.Substring(startIndex, arr[0].Length) != arr[0]) |
| | | { |
| | | msg = $"固定码检查失败: [{validate}]"; |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | msg = $"当前型号[{model}]配置参数[{validate}]解析失败"; |
| | | return false; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | msg = $"当前型号[{model}]配置参数[{validate}]解析失败"; |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <pu:WindowX x:Class="Plugin.TestResult.ManualDebugWindow" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | mc:Ignorable="d" |
| | | xmlns:sb="clr-namespace:Util.SB;assembly=Util.ManualDebug" |
| | | Title="ManualDebugWindow" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | Style="{StaticResource ModalWindow}" |
| | | Closing="Window_Closing" |
| | | WindowStartupLocation="CenterScreen" |
| | | pu:WindowXModalDialog.Buttons="{x:Null}" |
| | | Height="1000" Width="900"> |
| | | <Grid x:Name="sb"> |
| | | <sb:ManualDebug OvenName="{Binding OvenName,Mode=OneWay}" |
| | | CellName="{Binding CellName,Mode=OneWay}" |
| | | OvenIndex="{Binding OvenIndex,Mode=OneWay}" |
| | | CellIndex="{Binding CellIndex,Mode=OneWay}"/> |
| | | </Grid> |
| | | </pu:WindowX> |
| New file |
| | |
| | | using HMI.Util; |
| | | using Panuon.WPF.UI; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.IO; |
| | | using System.Windows; |
| | | using Util.SB; |
| | | |
| | | namespace Plugin.TestResult |
| | | { |
| | | /// <summary> |
| | | /// ManualDebugWindow.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class ManualDebugWindow : WindowX |
| | | { |
| | | |
| | | private ManualDebug debug; |
| | | |
| | | public ManualDebugWindow(string seqPath, string modelPath) |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | debug = (ManualDebug)sb.Children[0]; |
| | | ReadBtns(); |
| | | //List<BtnConfig> settings = new List<BtnConfig> { new BtnConfig { Title = "上电激活", Name = "Active" } }; |
| | | debug.seqPath = seqPath; |
| | | debug.modelPath = modelPath; |
| | | } |
| | | |
| | | private string ovenName; |
| | | public string OvenName |
| | | { |
| | | get => ovenName; |
| | | set |
| | | { |
| | | Set(ref ovenName, value); |
| | | } |
| | | } |
| | | |
| | | private string cellName; |
| | | public string CellName |
| | | { |
| | | get => cellName; |
| | | set |
| | | { |
| | | Set(ref cellName, value); |
| | | } |
| | | } |
| | | |
| | | private int ovenIndex; |
| | | public int OvenIndex |
| | | { |
| | | get => ovenIndex; |
| | | set |
| | | { |
| | | Set(ref ovenIndex, value); |
| | | } |
| | | } |
| | | |
| | | private int cellIndex; |
| | | public int CellIndex |
| | | { |
| | | get => cellIndex; |
| | | set |
| | | { |
| | | Set(ref cellIndex, value); |
| | | } |
| | | } |
| | | |
| | | private void ReadBtns() |
| | | { |
| | | string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.ini"); |
| | | var map = IniFileHelper.GetKeyValuesBySection(path, "Btns"); |
| | | List<BtnConfig> settings = new List<BtnConfig>(); |
| | | foreach (var kv in map) |
| | | { |
| | | settings.Add(new BtnConfig { Title = kv.Key, Name = kv.Value }); |
| | | } |
| | | debug.RefreshButtons(settings); |
| | | } |
| | | |
| | | private void Window_Closing(object sender, CancelEventArgs e) |
| | | { |
| | | if (MessageBox.Show("确定要关闭吗?", "提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK) |
| | | { |
| | | debug.Stop(); |
| | | } |
| | | else |
| | | { |
| | | e.Cancel = true; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | using ScottPlot.Colormaps; |
| | | using SuperSocket.SocketBase; |
| | | using SuperSocket.SocketBase; |
| | | using SuperSocket.SocketBase.Protocol; |
| | | using System; |
| | | using System.Collections; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | |
| | |
| | | public override StringRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest) |
| | | { |
| | | rest = 0; |
| | | StringBuilder sb = new StringBuilder(); |
| | | int i = offset; |
| | | List<byte> bytes = new List<byte>(); |
| | | while (i < readBuffer.Length) |
| | |
| | | { |
| | | break; |
| | | } |
| | | sb.Append((char)b); |
| | | bytes.Add(b); |
| | | } |
| | | byte[] arr = bytes.ToArray(); |
| | | return new StringRequestInfo(DateTime.Now + "", Encoding.UTF8.GetString(arr), null);//sb.ToString() |
| | | return new StringRequestInfo(DateTime.Now.ToString("yyyyMMddHHmmssfff"), Encoding.UTF8.GetString(arr), null);//sb.ToString() |
| | | } |
| | | } |
| | | |
| | | public class StringParser : IRequestInfoParser<StringRequestInfo> |
| | | { |
| | | |
| | | public StringRequestInfo ParseRequestInfo(string source) |
| | | { |
| | | return new StringRequestInfo(DateTime.Now.ToString("yyyyMMddHHmmssfff"), source, null); |
| | | } |
| | | } |
| | | |
| | | //public class TcpServer : AppServer<TcpSession> |
| | | //{ |
| | | // public TcpServer() : base(new DefaultReceiveFilterFactory<DTReceiveFilter, StringRequestInfo>()) |
| | | // { |
| | | |
| | | // } |
| | | //} |
| | | |
| | | public class TcpServer : AppServer<TcpSession> |
| | | { |
| | | public TcpServer() : base(new DefaultReceiveFilterFactory<DTReceiveFilter, StringRequestInfo>()) |
| | | public TcpServer() : base(new TerminatorReceiveFilterFactory("\n", Encoding.UTF8, new StringParser())) |
| | | { |
| | | |
| | | } |
| | |
| | | <SpecificVersion>False</SpecificVersion> |
| | | <HintPath>..\Libs\NationalInstruments.TestStand.Interop.UI.AxControls.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> |
| | | <HintPath>..\WPFProject\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="OpenTK, Version=3.3.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL"> |
| | | <HintPath>..\WPFProject\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll</HintPath> |
| | | </Reference> |
| | |
| | | <DependentUpon>CoolerStatus.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="CSVPrinter.cs" /> |
| | | <Compile Include="Lixun\SNValidator.cs" /> |
| | | <Compile Include="ManualDebugWindow.xaml.cs"> |
| | | <DependentUpon>ManualDebugWindow.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="Model\BaseConfig.cs" /> |
| | | <Compile Include="Model\CellInfo.cs" /> |
| | | <Compile Include="Model\Info.cs" /> |
| | |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | | <Page Include="InfoWindow.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | | <Page Include="ManualDebugWindow.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | |
| | | <Generator>ResXFileCodeGenerator</Generator> |
| | | <LastGenOutput>Resources.Designer.cs</LastGenOutput> |
| | | </EmbeddedResource> |
| | | <None Include="app.config" /> |
| | | <None Include="Config\log4net.config" /> |
| | | <None Include="Config\log4net.unix.config" /> |
| | | <None Include="packages.config" /> |
| | |
| | | <Project>{3068124e-f12b-473e-99a0-2da5a0385d05}</Project> |
| | | <Name>Plugin.TsSupport</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\SimpleUtil\HMI.LogUtil\HMI.LogUtil.csproj"> |
| | | <Project>{6d0aab08-0f3e-48ce-b755-9d29bc8f1225}</Project> |
| | | <Name>HMI.LogUtil</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Util.ManualDebug\Util.ManualDebug.csproj"> |
| | | <Project>{d0944e62-ee52-4abe-832a-a09d98814db1}</Project> |
| | | <Name>Util.ManualDebug</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Resource Include="Resource\abort.png" /> |
| | |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.TestResult.Lixun; |
| | | using Plugin.TestResult.Model; |
| | | using Plugin.TestResult.Util; |
| | | using Plugin.TestResult_WPF.Model; |
| | |
| | | var EnableMes = ParameterManager.GetCommonParameterByName<bool>("EnableMes", false); |
| | | if (ParamSetting.CustomerCode == "LIXUN" && EnableMes) |
| | | { |
| | | if (PNUtil.GetPN(ParamSetting.MesAddress, snr, out string pn, out string msg)) |
| | | var table = TestResultView.tables[this.ovenIndex]; |
| | | string currentPn = table.CbProduct.Text; |
| | | |
| | | /// 检查格式 |
| | | if (!SNValidator.ValidateSN(currentPn, snr, out string msg)) |
| | | { |
| | | var table = TestResultView.tables[this.ovenIndex]; |
| | | string currentPn = table.CbProduct.Text; |
| | | TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); |
| | | MsgBoxHelper2.Error($"检查产品条码异常:{msg}"); |
| | | snrText.Text = string.Empty; |
| | | snrText.Focus(); |
| | | return; |
| | | } |
| | | |
| | | /// 获取站名 |
| | | string stationName = ProductManager.GetParameterByProductAndName(currentPn, "MES站位")?.Value; |
| | | if (string.IsNullOrEmpty(stationName)) |
| | | { |
| | | TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); |
| | | MsgBoxHelper2.Error($"检查产品条码异常,当前产品[{currentPn}]未设置参数MES站位"); |
| | | snrText.Text = string.Empty; |
| | | snrText.Focus(); |
| | | return; |
| | | } |
| | | |
| | | /// 检查PN |
| | | if (PNUtil.GetPN(ParamSetting.MesAddress, stationName, snr, out string pn, out msg)) |
| | | { |
| | | |
| | | if (pn != currentPn) |
| | | { |
| | | TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); |
| | |
| | | snrText.Focus(); |
| | | return; |
| | | } |
| | | |
| | | /// 检查工序 |
| | | if (PNUtil.CheckIn(ViewControl.Logger, ParamSetting.MesAddress, stationName, snr, out bool needCheckIn, out msg)) |
| | | { |
| | | if (needCheckIn != true) |
| | | { |
| | | TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); |
| | | MsgBoxHelper2.Error($"条码[{snr}]工序不在本站:{msg}"); |
| | | snrText.Text = string.Empty; |
| | | snrText.Focus(); |
| | | return; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | TestResultView.tables[this.ovenIndex].GetSingleCell(targetCellInfo.Index).LightRed(true, out _); |
| | | MsgBoxHelper2.Error($"条码[{snr}]CheckIn失败:{msg}"); |
| | | snrText.Text = string.Empty; |
| | | snrText.Focus(); |
| | | return; |
| | | } |
| | | } |
| | | //var _ = ScannerParser.GetCellInfoByCode(this.model, this.columns, this.rows, snr); |
| | | //ToastHelper.Warning(this, "产品码格式异常"); |
| | |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | x:Name="uc" |
| | | PreviewMouseRightButtonDown="OnPreviewMouseRightButtonDown" |
| | | MouseDoubleClick="UserControl_MouseDoubleClick" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | |
| | | <ToolTip Padding="5" BorderThickness="1" BorderBrush="Black" Background="Yellow" Content="{Binding tooltipContent}"/> |
| | | </UserControl.ToolTip>--> |
| | | |
| | | <UserControl.ContextMenu> |
| | | <!--<UserControl.ContextMenu> |
| | | <ContextMenu> |
| | | <!--<MenuItem IsCheckable="True" IsChecked="{Binding CellIsDisabled,Mode=TwoWay}" Header="禁用"/>--> |
| | | <MenuItem IsCheckable="False" x:Name="clearSNRItem" Click="MenuItem_Click" Header="{DynamicResource Tr.ClearSNR}"/> |
| | | <MenuItem IsCheckable="False" DataContext="{Binding table}" IsEnabled="{Binding IsTesting,Converter={StaticResource reverseBool}}" x:Name="clearSNRItem" Click="MenuItem_Click" Header="{DynamicResource Tr.ClearSNR}"/> |
| | | <MenuItem IsCheckable="False" x:Name="exportCSVItem" Click="MenuItem_Click" Header="{DynamicResource App.ExportCSV}"/> |
| | | <MenuItem IsCheckable="False" x:Name="manualDebugItem" Click="MenuItem_Click" Header="手动调试"> |
| | | <MenuItem.Style> |
| | | <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Static pu:StyleKeys.MenuItemStyle}}"> |
| | | |
| | | </Style> |
| | | </MenuItem.Style> |
| | | </MenuItem> |
| | | </ContextMenu> |
| | | </UserControl.ContextMenu> |
| | | </UserControl.ContextMenu>--> |
| | | |
| | | <UserControl.Style> |
| | | <Style TargetType="UserControl"> |
| | |
| | | </UserControl.Style> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="18"/> |
| | | <RowDefinition /> |
| | | <RowDefinition Height="14"/> |
| | | <RowDefinition Height="14"/> |
| | | </Grid.RowDefinitions> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | </Grid.ColumnDefinitions> |
| | | <StackPanel Orientation="Horizontal" Background="LightGray" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Right"> |
| | | <TextBlock Foreground="Red" Text="{DynamicResource Ts.ProbeAlarm}"> |
| | | <TextBlock.Style> |
| | | <Style TargetType="TextBlock"> |
| | | <Setter Property="Visibility" Value="Collapsed"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding probeAlarm}" Value="True"> |
| | | <Setter Property="Visibility" Value="Visible"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </TextBlock.Style> |
| | | </TextBlock> |
| | | <TextBlock Margin="0"> |
| | | <Run Text="{Binding ProbeCount}"/> |
| | | <Run Text="/"/> |
| | | <Run Text="{Binding ProbeWarn}"/> |
| | | </TextBlock> |
| | | </StackPanel> |
| | | <Label Grid.Row="0" Grid.Column="0" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" Padding="0" Margin="5,5,0,0" |
| | | FontSize="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='8,103'}" |
| | |
| | | </Style> |
| | | </Label.Style> |
| | | </Label> |
| | | <ui:ScrollLabel Grid.Row="1" Grid.Column="0" Margin="3,0,0,5" Padding="0" Value="{Binding sn}"/> |
| | | |
| | | <Image Grid.Row="0" Grid.Column="1" Width="30" HorizontalAlignment="Right" Height="30" Margin="0,5,5,0"> |
| | | <Image Grid.Row="0" Grid.Column="1" Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='10,20'}" HorizontalAlignment="Right" |
| | | Margin="0,5,5,0"> |
| | | <Image.Style> |
| | | <Style TargetType="Image"> |
| | | <Setter Property="HorizontalAlignment" Value="Center"/> |
| | |
| | | </Style> |
| | | </Image.Style> |
| | | </Image> |
| | | |
| | | <ui:ScrollLabel Grid.Row="1" Grid.Column="0" FontSize="10" Grid.ColumnSpan="2" Margin="3,0,0,0" Padding="0" Value="{Binding sn}"/> |
| | | |
| | | <StackPanel Orientation="Horizontal" Background="LightGray" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Top" HorizontalAlignment="Right"> |
| | | <TextBlock Foreground="Red" Text="{DynamicResource Ts.ProbeAlarm}" FontSize="10"> |
| | | <TextBlock.Style> |
| | | <Style TargetType="TextBlock"> |
| | | <Setter Property="Visibility" Value="Collapsed"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding probeAlarm}" Value="True"> |
| | | <Setter Property="Visibility" Value="Visible"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </TextBlock.Style> |
| | | </TextBlock> |
| | | <TextBlock Margin="0" FontSize="10"> |
| | | <Run Text="{Binding ProbeCount}"/> |
| | | <Run Text="/"/> |
| | | <Run Text="{Binding ProbeWarn}"/> |
| | | </TextBlock> |
| | | </StackPanel> |
| | | </Grid> |
| | | </UserControl> |
| | |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using PLCHelper; |
| | | using Plugin.TestResult; |
| | | using Plugin.TestResult.Util; |
| | | using Plugin.TestResult_WPF.Constant; |
| | | using Plugin.TestResult_WPF.Model; |
| | |
| | | private InfoWindow window; |
| | | private int maxSize; |
| | | |
| | | private DataTable table; |
| | | public DataTable table { get; private set; } |
| | | |
| | | public SingleCell(DataTable table, string title, int index, int maxSize, string iniFile) |
| | | { |
| | |
| | | |
| | | public void SetStatus(string status) |
| | | { |
| | | var oldStatus = this.status; |
| | | this.status = status; |
| | | if (oldStatus != "testing" && status == "testing") |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | UpdateProbeCount(ProbeCount + 1); |
| | | var now = DateTime.Now; |
| | | string dateStr = now.ToString("yyyyMMdd"); |
| | | visualTestId = $"{title}_{now.ToString("yyyyMMddHHmmssfff")}"; |
| | | helper = CheckSqlHelper(dateStr); |
| | | } |
| | | var oldStatus = this.status; |
| | | this.status = status; |
| | | if (oldStatus != "testing" && status == "testing") |
| | | { |
| | | UpdateProbeCount(ProbeCount + 1); |
| | | var now = DateTime.Now; |
| | | string dateStr = now.ToString("yyyyMMdd"); |
| | | visualTestId = $"{title}_{now.ToString("yyyyMMddHHmmssfff")}"; |
| | | helper = CheckSqlHelper(dateStr); |
| | | InsertARecourd(); |
| | | } |
| | | |
| | | if (oldStatus != "ok" && status == "ok") |
| | | { |
| | | SaveInfoToDB(); |
| | | } |
| | | if (oldStatus != "ok" && status == "ok") |
| | | { |
| | | SaveInfoToDB(); |
| | | } |
| | | |
| | | if (oldStatus != "ng" && status == "ng") |
| | | if (oldStatus != "ng" && status == "ng") |
| | | { |
| | | SaveInfoToDB(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private void InsertARecourd() |
| | | { |
| | | try |
| | | { |
| | | SaveInfoToDB(); |
| | | string model = table?.CbProduct?.SelectedItem?.ToString(); |
| | | var timestr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | var sql = $"INSERT INTO testResult (sn,model,station,position,result,time,resultId) VALUES ('{sn}','{model}','','{title}','{this.status}','{timestr}','{visualTestId}');"; |
| | | helper.Execute(sql); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ViewControl.Logger.Error($"Cell[{title}] SaveToDB Error.", ex); |
| | | } |
| | | } |
| | | |
| | | public void WriteCSV(Info info) |
| | | { |
| | | try |
| | | { |
| | | if (ParamSetting.CustomerCode != "LIXUN") |
| | | { |
| | | return; |
| | | } |
| | | string fileName = this.sn?.Replace("/", "#")?.Replace("\\", "#") + ".csv"; |
| | | string dir = Path.Combine(ParamSetting.DataLogFolder, "csv", this.title); |
| | | string title = $"{this.lang("Test.Name")},{this.lang("Test.Value")},{this.lang("Test.LimitDown")},{this.lang("Test.LimitUp")},{this.lang("Test.Unit")},{this.lang("Test.Result")},{this.lang("Test.TestTime")}"; |
| | | string line = $"{info.step},{info.value},{info.limitDown},{info.limitUp},{info.unit},{info.result},{info.updateTime}"; |
| | | //try |
| | | //{ |
| | | // if (ParamSetting.CustomerCode != "LIXUN") |
| | | // { |
| | | // return; |
| | | // } |
| | | // string fileName = this.sn?.Replace("/", "#")?.Replace("\\", "#") + ".csv"; |
| | | // string dir = Path.Combine(ParamSetting.DataLogFolder, "csv", this.title); |
| | | // string title = $"{this.lang("Test.Name")},{this.lang("Test.Value")},{this.lang("Test.LimitDown")},{this.lang("Test.LimitUp")},{this.lang("Test.Unit")},{this.lang("Test.Result")},{this.lang("Test.TestTime")}"; |
| | | // string line = $"{info.step},{info.value},{info.limitDown},{info.limitUp},{info.unit},{info.result},{info.updateTime}"; |
| | | |
| | | CSVPrinter.Print(dir, fileName, title, line); |
| | | // ReverseCSV(Path.Combine(dir, fileName)); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | } |
| | | // CSVPrinter.Print(dir, fileName, title, line); |
| | | // // ReverseCSV(Path.Combine(dir, fileName)); |
| | | //} |
| | | //catch (Exception ex) |
| | | //{ |
| | | //} |
| | | } |
| | | |
| | | public void SendToChart(Info info) |
| | |
| | | allInfos.Add(info); |
| | | SendToChart(info); |
| | | WriteCSV(info); |
| | | if (queue.Count >= maxSize) |
| | | |
| | | /// 目前先不限制数量,后续如果数据过多导致性能问题再考虑限制数量 |
| | | //if (queue.Count >= maxSize) |
| | | //{ |
| | | // queue.TryDequeue(out var first); |
| | | // queue.Enqueue(info); |
| | | // this.infos = new ObservableCollection<Info>(queue); |
| | | // if (window != null) window.UpdateSource(this.infos); |
| | | //} |
| | | //else |
| | | //{ |
| | | // queue.Enqueue(info); |
| | | // if (window != null) |
| | | // { |
| | | // window.Dispatcher.Invoke(() => |
| | | // { |
| | | // this.infos.Add(info); |
| | | // }); |
| | | // } |
| | | // else |
| | | // { |
| | | // Dispatcher.Invoke(() => |
| | | // { |
| | | // this.infos.Add(info); |
| | | // }); |
| | | // } |
| | | //} |
| | | |
| | | if (window != null) |
| | | { |
| | | queue.TryDequeue(out var first); |
| | | queue.Enqueue(info); |
| | | this.infos = new ObservableCollection<Info>(queue); |
| | | if (window != null) window.UpdateSource(this.infos); |
| | | window.Dispatcher.Invoke(() => |
| | | { |
| | | this.infos.Add(info); |
| | | }); |
| | | } |
| | | else |
| | | { |
| | | queue.Enqueue(info); |
| | | if (window != null) |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | window.Dispatcher.Invoke(() => |
| | | { |
| | | this.infos.Add(info); |
| | | }); |
| | | } |
| | | else |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | this.infos.Add(info); |
| | | }); |
| | | } |
| | | this.infos.Add(info); |
| | | }); |
| | | } |
| | | |
| | | Dispatcher.Invoke(() => |
| | |
| | | { |
| | | try |
| | | { |
| | | string model = table?.CbProduct?.SelectedItem?.ToString(); |
| | | var timestr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | var sql = $"INSERT INTO testResult (sn,station,position,result,time,resultId) VALUES ('{sn}','','{title}','{this.status}','{timestr}','{visualTestId}');"; |
| | | //var sql = $"INSERT INTO testResult (sn,model,station,position,result,time,resultId) VALUES ('{sn}','{model}','','{title}','{this.status}','{timestr}','{visualTestId}');"; |
| | | var sql = $"UPDATE testResult SET time = '{timestr}', result = '{this.status}' WHERE resultId = '{visualTestId}'"; |
| | | helper.Execute(sql); |
| | | helper.Dispose(); |
| | | helper = null; |
| | |
| | | case "exportCSVItem": |
| | | TryExportCSV(); |
| | | break; |
| | | case "manualDebugItem": |
| | | OpenManualDebugWindow(); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 打开手动调试窗口 |
| | | /// </summary> |
| | | private void OpenManualDebugWindow() |
| | | { |
| | | string manualDebugSeq = ParameterManager.GetCommonParameterByName("ManualDebugSeqPath")?.Value; |
| | | if (string.IsNullOrEmpty(manualDebugSeq)) |
| | | { |
| | | MsgBoxHelper2.Error("请先设置手动调试序列路径[ManualDebugSeqPath]!"); |
| | | return; |
| | | } |
| | | string modelPath = table.parent.testModelFile; |
| | | var win = new ManualDebugWindow(manualDebugSeq, modelPath) |
| | | { |
| | | Title = $"{this.title}手动调试", |
| | | Owner = Window.GetWindow(this), |
| | | OvenIndex = this.table.index, |
| | | OvenName = this.table.title, |
| | | |
| | | CellIndex = this.index, |
| | | CellName = this.title |
| | | }; |
| | | win.ShowDialog(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 尝试导出CSV |
| | | /// </summary> |
| | | private void TryExportCSV() |
| | | { |
| | | System.Windows.Forms.SaveFileDialog sfd = new System.Windows.Forms.SaveFileDialog |
| | |
| | | return S7Context.WriteData(RunTimeVariablePool.DEFAULT_PLC_NAME, |
| | | $"Oven{table.index + 1}_Cell{index + 1}_Light_NG", on, out msg); |
| | | } |
| | | |
| | | private void OnPreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | |
| | | ContextMenu contextMenu = new ContextMenu(); |
| | | contextMenu.Closed += ContextMenu_Closed; |
| | | |
| | | //< /> |
| | | //< |
| | | //< MenuItem IsCheckable = "False" x: Name = "manualDebugItem" Click = "MenuItem_Click" Header = "手动调试" > |
| | | // < MenuItem.Style > |
| | | // < Style TargetType = "MenuItem" BasedOn = "{StaticResource {x:Static pu:StyleKeys.MenuItemStyle}}" > |
| | | |
| | | // </ Style > |
| | | // </ MenuItem.Style > |
| | | //</ MenuItem > |
| | | |
| | | var item = new MenuItem |
| | | { |
| | | IsCheckable = false, |
| | | IsEnabled = !table.IsTesting, |
| | | Name = "clearSNRItem", |
| | | Header = this.lang("Tr.ClearSNR"), |
| | | }; |
| | | item.Click += MenuItem_Click; |
| | | contextMenu.Items.Add(item); |
| | | |
| | | item = new MenuItem |
| | | { |
| | | IsCheckable = false, |
| | | Name = "exportCSVItem", |
| | | Header = this.lang("App.ExportCSV"), |
| | | }; |
| | | item.Click += MenuItem_Click; |
| | | contextMenu.Items.Add(item); |
| | | |
| | | if (table.parent.inManualDebugMode) |
| | | { |
| | | item = new MenuItem |
| | | { |
| | | IsCheckable = false, |
| | | Name = "manualDebugItem", |
| | | Header = this.lang("手动调试"), |
| | | }; |
| | | item.Click += MenuItem_Click; |
| | | contextMenu.Items.Add(item); |
| | | } |
| | | |
| | | this.ContextMenu = contextMenu; |
| | | } |
| | | |
| | | private void ContextMenu_Closed(object sender, RoutedEventArgs e) |
| | | { |
| | | this.ContextMenu = null; |
| | | } |
| | | } |
| | | } |
| | |
| | | using Plugin.TsSupport; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Runtime.InteropServices; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | |
| | | public static Dictionary<string, DataTable> nameTables { get; private set; } = new Dictionary<string, DataTable>(); |
| | | private readonly BaseConfig config; |
| | | |
| | | public AxApplicationMgr testApp; |
| | | |
| | | |
| | | public string testModelFile; |
| | | public string testSeqFile; |
| | | /// <summary> |
| | | /// 测试序列 |
| | | /// </summary> |
| | | private SequenceFile testSeq = null; |
| | | public Engine engine; |
| | | private Execution execution = null; |
| | | /// <summary> |
| | | /// 测试序列操作句柄 |
| | | /// </summary> |
| | | public SequenceContext SequenceContext { get; private set; } = null; |
| | | /// <summary> |
| | | /// 测试模型序列 |
| | | /// </summary> |
| | | private SequenceFile modeSeq; |
| | | public bool inManualDebugMode = false; |
| | | |
| | | #region TS相关 |
| | | //public AxApplicationMgr testApp; |
| | | ///// <summary> |
| | | ///// 测试序列 |
| | | ///// </summary> |
| | | //private SequenceFile testSeq = null; |
| | | //public Engine engine; |
| | | //private Execution execution = null; |
| | | ///// <summary> |
| | | ///// 测试序列操作句柄 |
| | | ///// </summary> |
| | | //public SequenceContext SequenceContext { get; private set; } = null; |
| | | ///// <summary> |
| | | ///// 测试模型序列 |
| | | ///// </summary> |
| | | //private SequenceFile modeSeq; |
| | | |
| | | public ITestExecutionWrapper executionWrapper; |
| | | #endregion |
| | | |
| | | public TestResultView() : this(new BaseConfig { testing = false }) |
| | | { |
| | |
| | | |
| | | public void RefreshCooler() |
| | | { |
| | | |
| | | |
| | | } |
| | | |
| | | private void RefreshNumberConfig(BaseConfig config) |
| | |
| | | |
| | | |
| | | InitializeComponent(); |
| | | testApp = TestAppManager.GetAxApplicationMgr(); |
| | | testApp.ExitApplication += this.axApplicationMgr_ExitApplication; |
| | | testApp.UIMessageEvent += this.axApplicationMgr_UIMessageEvent; |
| | | testApp.ExecutionClosed += this.axApplicationMgr_ExecutionClosed; |
| | | |
| | | executionWrapper = new TsExecutionWrapper(); //new TsExecutionWrapper(); |
| | | if (executionWrapper is TsExecutionWrapper tsWrapper) |
| | | { |
| | | tsWrapper.AxApplicationMgr.ExitApplication += this.axApplicationMgr_ExitApplication; |
| | | tsWrapper.AxApplicationMgr.UIMessageEvent += this.axApplicationMgr_UIMessageEvent; |
| | | tsWrapper.AxApplicationMgr.ExecutionClosed += this.axApplicationMgr_ExecutionClosed; |
| | | ((System.ComponentModel.ISupportInitialize)(tsWrapper.AxApplicationMgr)).BeginInit();//myClient为第三方控件名 |
| | | host.Child = tsWrapper.AxApplicationMgr; |
| | | ((System.ComponentModel.ISupportInitialize)(tsWrapper.AxApplicationMgr)).EndInit(); |
| | | } |
| | | |
| | | |
| | | ((System.ComponentModel.ISupportInitialize)(this.testApp)).BeginInit();//myClient为第三方控件名 |
| | | host.Child = testApp; |
| | | ((System.ComponentModel.ISupportInitialize)(this.testApp)).EndInit(); |
| | | |
| | | //InitTestStandEngine(); |
| | | //StartTestSequence(); |
| | | //testApp = TestAppManager.GetAxApplicationMgr(); |
| | | //testApp.ExitApplication += this.axApplicationMgr_ExitApplication; |
| | | //testApp.UIMessageEvent += this.axApplicationMgr_UIMessageEvent; |
| | | //testApp.ExecutionClosed += this.axApplicationMgr_ExecutionClosed; |
| | | //((System.ComponentModel.ISupportInitialize)(this.testApp)).BeginInit();//myClient为第三方控件名 |
| | | //host.Child = testApp; |
| | | //((System.ComponentModel.ISupportInitialize)(this.testApp)).EndInit(); |
| | | } |
| | | |
| | | private void Refresh() |
| | |
| | | { |
| | | try |
| | | { |
| | | this.engine = this.testApp.GetEngine(); |
| | | this.engine.PersistBreakpoints = false; |
| | | this.testApp.IsEditor = true; |
| | | this.testApp.LoginOnStart = false; |
| | | this.testApp.Start(); |
| | | this.modeSeq = this.engine.GetSequenceFileEx(testModelFile); |
| | | //this.engine = this.testApp.GetEngine(); |
| | | //this.engine.PersistBreakpoints = false; |
| | | //this.testApp.IsEditor = true; |
| | | //this.testApp.LoginOnStart = false; |
| | | //this.testApp.Start(); |
| | | //this.modeSeq = this.engine.GetSequenceFileEx(testModelFile); |
| | | executionWrapper.Init(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(testSeqFile)) return; |
| | | this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq"); |
| | | this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 0, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType); |
| | | this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null); |
| | | this.engine.Globals.SetValBoolean("StationState.StopTest", 0, false); |
| | | executionWrapper?.StartSequence(this.testSeqFile, |
| | | @"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq"); |
| | | |
| | | executionWrapper.SetStationGlobalValue<bool>("StationState.StopTest", 0, false); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | { |
| | | try |
| | | { |
| | | if (this.SequenceContext == null) |
| | | return; |
| | | bool val = this.SequenceContext.StationGlobals.Exists("StationState.StopTest", 0); |
| | | if (val) |
| | | executionWrapper?.SetStationGlobalValue<bool>("StationState.StopTest", 0, true, true); |
| | | |
| | | try |
| | | { |
| | | this.SequenceContext.StationGlobals.SetValBoolean("StationState.StopTest", 0, true); |
| | | bool isStop = this.execution.WaitForEndEx(2000, true, null, null); |
| | | executionWrapper?.WaitForExit(); |
| | | executionWrapper?.ReleaseSeqFile(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ViewControl.Logger.Error("Wait For Exit error.", ex); |
| | | //if (ex is NullReferenceException ne) |
| | | //{ |
| | | |
| | | //} |
| | | //else |
| | | //{ |
| | | // throw ex; |
| | | //} |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | |
| | | |
| | | private void axApplicationMgr_ExitApplication(object sender, EventArgs e) |
| | | { |
| | | Environment.ExitCode = testApp.ExitCode; |
| | | //Environment.ExitCode = testApp.ExitCode; |
| | | //TSHelper.DoSynchronousGCForCOMObjectDestruction(); |
| | | } |
| | | |
| | |
| | | if (MethodCode == 0) |
| | | { |
| | | /// 设置句柄 |
| | | this.SequenceContext = (SequenceContext)e.uiMsg.ActiveXData; |
| | | //this.SequenceContext = (SequenceContext)e.uiMsg.ActiveXData; |
| | | if (executionWrapper is TsExecutionWrapper tsWrapper) |
| | | { |
| | | tsWrapper.context = (SequenceContext)e.uiMsg.ActiveXData; |
| | | } |
| | | return; |
| | | } |
| | | |
| | |
| | | int ovenIndex = int.Parse(datas_10015[0]); |
| | | int cellIndex = int.Parse(datas_10015[1]); |
| | | tables[ovenIndex].GetSingleCell(cellIndex).ClearInfo(); |
| | | //GC.Collect(); |
| | | return; |
| | | } |
| | | if (MethodCode == 12) |
| | |
| | | int index = int.Parse(datas[0]); |
| | | if (MsgBoxHelper2.WarnChoose(datas[1], "提示") == MessageBoxResult.OK) |
| | | { |
| | | SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 1); |
| | | executionWrapper.SetStationGlobalValue<int>($"StationState.Pipe[{index}]", 1, 1); |
| | | //SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 1); |
| | | } |
| | | else |
| | | { |
| | | SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 0); |
| | | executionWrapper.SetStationGlobalValue<int>($"StationState.Pipe[{index}]", 1, 0); |
| | | //SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 0); |
| | | } |
| | | return; |
| | | } |
| | |
| | | |
| | | public void SetStartFlag(int index, bool data) |
| | | { |
| | | if (this.SequenceContext == null) return; |
| | | string name = tables[index].title; |
| | | ViewControl.Logger?.Info($"将老化炉[{name}] 的Start变量设置为 {data};"); |
| | | string key = $"StationState.Start[{index}]"; |
| | | this.engine.Globals.SetValBoolean(key, 1, data); |
| | | //bool val = this.engine.Globals.GetValBoolean(key, 0); |
| | | //this.SequenceContext.StationGlobals.SetValBoolean(key, 0, data); |
| | | //bool val = this.SequenceContext.StationGlobals.GetValBoolean(key, 0); |
| | | |
| | | executionWrapper?.SetStationGlobalValue<bool>(key, 1, data); |
| | | |
| | | if (data == false) |
| | | { |
| | | key = $"StationState.Scanner[{index}]"; |
| | | executionWrapper?.SetStationGlobalValue<bool>(key, 1, false); |
| | | } |
| | | } |
| | | |
| | | public bool? GetStartFlag(int index) |
| | | { |
| | | string key = $"StationState.Start[{index}]"; |
| | | return executionWrapper.GetStationGlobalValue<bool>(key, 0); |
| | | } |
| | | |
| | | public void ReleaseResource() |
| | | { |
| | | testApp.ExitApplication -= this.axApplicationMgr_ExitApplication; |
| | | testApp.UIMessageEvent -= this.axApplicationMgr_UIMessageEvent; |
| | | testApp.ExecutionClosed -= this.axApplicationMgr_ExecutionClosed; |
| | | if (executionWrapper is TsExecutionWrapper tsWrapper) |
| | | { |
| | | tsWrapper.AxApplicationMgr.ExitApplication -= this.axApplicationMgr_ExitApplication; |
| | | tsWrapper.AxApplicationMgr.UIMessageEvent -= this.axApplicationMgr_UIMessageEvent; |
| | | tsWrapper.AxApplicationMgr.ExecutionClosed -= this.axApplicationMgr_ExecutionClosed; |
| | | } |
| | | |
| | | foreach (var table in tables) |
| | | { |
| | | table.RelaseResource(); |
| | |
| | | for (int i = 0; i < tables.Length; i++) |
| | | { |
| | | var table = tables[i]; |
| | | // table.SetCurrentProduct(currentProduct); |
| | | string LookupStr = $"StationState.Model[{i}]"; |
| | | string tableModel = engine?.Globals?.GetValString(LookupStr, 1); |
| | | |
| | | string tableModel = executionWrapper?.GetStationGlobalValue<string>(LookupStr, 1); |
| | | //engine?.Globals?.GetValString(LookupStr, 1); |
| | | table.SetCurrentProduct(tableModel); |
| | | } |
| | | } |
| | |
| | | public void SetOvenProduct(int index, string product) |
| | | { |
| | | string LookupStr = $"StationState.Model[{index}]"; |
| | | engine?.Globals?.SetValString(LookupStr, 1, product); |
| | | engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | executionWrapper?.SetStationGlobalValue<string>(LookupStr, 1, product); |
| | | executionWrapper?.CommitToDisk(false); |
| | | } |
| | | |
| | | public void RefreshProducts() |
| | | { |
| | | } |
| | | } |
| | | } |
| | |
| | | using HMI.Core.Util; |
| | | using log4net; |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json.Linq; |
| | | using Plugin.TestResult_WPF; |
| | | using System; |
| | | using System.Net.Http; |
| | |
| | | |
| | | public class PNUtil |
| | | { |
| | | public static bool GetPN(string mesAddress, string sn, out string pn, out string msg) |
| | | public static bool GetPN(string mesAddress, string stationName, string sn, out string pn, out string msg) |
| | | { |
| | | pn = null; |
| | | msg = string.Empty; |
| | | try |
| | | { |
| | | string json = $"{{\"csn\":\"{sn}\",\"station_name\":\"OP170Burn-In老化\"}}"; |
| | | //OP170Burn-In老化 |
| | | string json = $"{{\"csn\":\"{sn}\",\"station_name\":\"{stationName}\"}}"; |
| | | HttpClient val = new HttpClient(); |
| | | ViewControl.Logger.Debug($"Get PN Send: [{json}]"); |
| | | try |
| | |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | public static bool CheckIn(ILog log, string mesAddress, string stationName, string sn, out bool needCheckIn, out string msg) |
| | | { |
| | | JObject data = new JObject(); |
| | | data.Add("cmd", "QUERY_RECORD"); |
| | | data.Add("p", "UOP"); |
| | | |
| | | data.Add("sn", sn); |
| | | data.Add("station_name", stationName); |
| | | data.Add("op", "A0000001"); |
| | | |
| | | needCheckIn = false; |
| | | msg = string.Empty; |
| | | string sendData = string.Empty; |
| | | string resData = null; |
| | | try |
| | | { |
| | | sendData = data.ToString(Formatting.None); |
| | | using (HttpClient val = new HttpClient()) |
| | | { |
| | | StringContent val2 = new StringContent(sendData, Encoding.UTF8, "application/json"); |
| | | HttpResponseMessage result = val.PostAsync("http://" + mesAddress + "/mes-module-system-2.1.1/lixun/api/checkIn", (HttpContent)(object)val2).Result; |
| | | result.EnsureSuccessStatusCode(); |
| | | resData = result.Content.ReadAsStringAsync().Result; |
| | | JObject httpResult = JObject.Parse(resData); |
| | | |
| | | log.Info("CheckIn Send: " + httpResult.Value<string>("sendStr")); |
| | | log.Info("CheckIn Receive: " + httpResult.Value<string>("receiveStr")); |
| | | log.Info("CheckIn Get: " + resData); |
| | | |
| | | msg = httpResult.Value<string>("msg"); |
| | | if (httpResult.Value<int>("code") == 200) |
| | | { |
| | | needCheckIn = httpResult.Value<bool>("needCheckIn"); |
| | | return true; |
| | | } |
| | | log.Error("CheckIn Error: " + msg); |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | msg = ex.Message + " in " + ex.StackTrace + ".SendStr: " + sendData + ",ResultStr: " + resData; |
| | | log.Error("CheckIn Unknow Error: " + msg); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | <ColumnDefinition Width="*"/> |
| | | </Grid.ColumnDefinitions>--> |
| | | <local:TestResultView x:Name="testResultView" Grid.Row="1" Grid.Column="0" Loaded="testResultView_Loaded" /> |
| | | <DockPanel Margin="10,0" Grid.Row="0" Grid.Column="1" Background="#FFF" VerticalAlignment="Center"> |
| | | <DockPanel Margin="10,0" Grid.Row="0" Grid.Column="1" LastChildFill="False" Background="#FFF" VerticalAlignment="Center"> |
| | | <pu:FormGroup DockPanel.Dock="Right"> |
| | | <StackPanel Orientation="Horizontal" VerticalAlignment="Center" dp:StackPanelHelper.ChildSpace="20"> |
| | | <Button x:Name="btnStart" Click="Start_Click" Style="{StaticResource SuccessButton}" |
| | | Width="100" FontSize="14" Padding="0" Height="30" Content="{DynamicResource App.Start}"/> |
| | | <Button x:Name="btnStart" Click="Start_Click" |
| | | Width="100" FontSize="14" Padding="0" Height="30" Content="{DynamicResource App.Start}"> |
| | | <Button.Style> |
| | | <Style TargetType="Button" BasedOn="{StaticResource SuccessButton}"> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding EnableManualDebug}" Value="True"> |
| | | <Setter Property="IsEnabled" Value="False"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding IsRunning}" Value="True"> |
| | | <Setter Property="IsEnabled" Value="False"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Button.Style> |
| | | </Button> |
| | | |
| | | <Button x:Name="btnStop" Click="Stop_Click" Style="{StaticResource DangerButton}" |
| | | Width="100" FontSize="14" Padding="0" Height="30" |
| | |
| | | ValueChanged="StdEnableMes_ValueChanged"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgEnableManualDebug" Visibility="Collapsed"> |
| | | <CheckBox FontSize="20" |
| | | IsChecked="{Binding EnableManualDebug,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | VerticalContentAlignment="Center" |
| | | Content="手动调试" /> |
| | | </pu:FormGroup> |
| | | |
| | | |
| | | <!--<pu:FormGroup Header="{DynamicResource Tr.Status}" FontSize="16"> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10"> |
| | |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.LogUtil; |
| | | using HMI.StdControl; |
| | | using HMI.UI.Util; |
| | | using log4net; |
| | |
| | | using NationalInstruments.TestStand.Interop.UI.Ax; |
| | | using PLCHelper; |
| | | using Plugin.TestResult.Util; |
| | | using Plugin.TsSupport; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | |
| | | /// </summary> |
| | | public partial class ViewControl : PluginMaskControl, IAlarmHandler |
| | | { |
| | | /// <summary> |
| | | /// 测试序列操作句柄 |
| | | /// </summary> |
| | | private SequenceContext SequenceContext = null; |
| | | |
| | | private System.Timers.Timer timer; |
| | | |
| | |
| | | set => Set(ref _fileName, value); |
| | | } |
| | | |
| | | private bool enableManualDebug; |
| | | public bool EnableManualDebug |
| | | { |
| | | get => enableManualDebug; |
| | | set |
| | | { |
| | | if (IsRunning) |
| | | { |
| | | MsgBoxHelper2.Warn("请先结束自动测试"); |
| | | return; |
| | | } |
| | | testResultView.inManualDebugMode = value; |
| | | Set(ref enableManualDebug, value); |
| | | } |
| | | } |
| | | |
| | | public override void SetLogger(ILog logger) |
| | | { |
| | | base.SetLogger(logger); |
| | |
| | | Set(ref isRunning, value); |
| | | testResultView.IsRunning = value; |
| | | this.modelSelect.IsEnabled = !value; |
| | | this.btnStart.IsEnabled = !value; |
| | | this.btnStop.IsEnabled = value; |
| | | stdEnableMes.CbEnabled = !value; |
| | | } |
| | | } |
| | | |
| | | private bool AutoExecuteSeq = true; |
| | | |
| | | #region TS相关 |
| | | |
| | | /// <summary> |
| | | /// 测试序列操作句柄 |
| | | /// </summary> |
| | | private SequenceContext SequenceContext = null; |
| | | #endregion |
| | | |
| | | public ViewControl() |
| | | { |
| | |
| | | timer.Interval = 1000; |
| | | timer.Elapsed += Timer_Elapsed; |
| | | InitializeComponent(); |
| | | testResultView.testApp.ExitApplication += new EventHandler(this.axApplicationMgr_ExitApplication); |
| | | testResultView.testApp.UIMessageEvent += new _ApplicationMgrEvents_UIMessageEventEventHandler(this.axApplicationMgr_UIMessageEvent); |
| | | testResultView.testApp.ExecutionClosed += new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.axApplicationMgr_ExecutionClosed); |
| | | |
| | | if (testResultView.executionWrapper is TsExecutionWrapper tsWrapper) |
| | | { |
| | | tsWrapper.AxApplicationMgr.ExitApplication += new EventHandler(this.axApplicationMgr_ExitApplication); |
| | | tsWrapper.AxApplicationMgr.UIMessageEvent += new _ApplicationMgrEvents_UIMessageEventEventHandler(this.axApplicationMgr_UIMessageEvent); |
| | | tsWrapper.AxApplicationMgr.ExecutionClosed += new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.axApplicationMgr_ExecutionClosed); |
| | | } |
| | | |
| | | |
| | | //testResultView.testApp.ExitApplication += new EventHandler(this.axApplicationMgr_ExitApplication); |
| | | //testResultView.testApp.UIMessageEvent += new _ApplicationMgrEvents_UIMessageEventEventHandler(this.axApplicationMgr_UIMessageEvent); |
| | | //testResultView.testApp.ExecutionClosed += new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.axApplicationMgr_ExecutionClosed); |
| | | } |
| | | |
| | | private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) |
| | |
| | | testResultView.testSeqFile = string.Empty; |
| | | FileName = string.Empty; |
| | | } |
| | | RefreshUIConfig(); |
| | | } |
| | | |
| | | public override void DoClose(object sender, EventArgs e) |
| | | /// <summary> |
| | | /// 刷新UI配置 |
| | | /// </summary> |
| | | private void RefreshUIConfig() |
| | | { |
| | | try |
| | | { |
| | | timer?.Stop(); |
| | | testResultView.ReleaseResource(); |
| | | /// 运行中就不管 |
| | | if (IsRunning) |
| | | { |
| | | return; |
| | | } |
| | | bool enableManualDebug = ParameterManager.GetCommonParameterByName("EnableManualDebug", false); |
| | | if (enableManualDebug) |
| | | { |
| | | FgEnableManualDebug.Visibility = Visibility.Visible; |
| | | } |
| | | else |
| | | { |
| | | FgEnableManualDebug.Visibility = Visibility.Collapsed; |
| | | EnableManualDebug = false; |
| | | } |
| | | } |
| | | catch |
| | | catch (Exception ex) |
| | | { |
| | | } |
| | | } |
| | | |
| | | public override void OnClose(object sender, CancelEventArgs e) |
| | | { |
| | | if (IsRunning) |
| | | { |
| | | MsgBoxHelper2.Warn("请先停止老化测试!"); |
| | | e.Cancel = true; |
| | | log.Error("RefreshUIConfig Error.", ex); |
| | | } |
| | | } |
| | | |
| | |
| | | productSource.Add(prd.Name); |
| | | } |
| | | testResultView.SetProductSource(productSource); |
| | | testResultView.SetCurrentProduct(null); |
| | | |
| | | string model = testResultView.engine.Globals.GetValString("ProductModel", 1); |
| | | if (!string.IsNullOrEmpty(model)) |
| | | { |
| | | this.modelSelect.SelectedItem = model; |
| | | testResultView.SetCurrentProduct(model); |
| | | } |
| | | else if (products.Count > 0) |
| | | { |
| | | this.modelSelect.SelectedIndex = 0; |
| | | testResultView.SetCurrentProduct(products[0].Name); |
| | | } |
| | | //string model = testResultView.executionWrapper.GetStationGlobalValue<string>("ProductModel", 1); |
| | | ////testResultView.engine.Globals.GetValString("ProductModel", 1); |
| | | //if (!string.IsNullOrEmpty(model)) |
| | | //{ |
| | | // this.modelSelect.SelectedItem = model; |
| | | // testResultView.SetCurrentProduct(model); |
| | | //} |
| | | //else if (products.Count > 0) |
| | | //{ |
| | | // this.modelSelect.SelectedIndex = 0; |
| | | // testResultView.SetCurrentProduct(products[0].Name); |
| | | //} |
| | | } |
| | | |
| | | private void modelSelect_SelectionChanged(object sender, SelectionChangedEventArgs e) |
| | |
| | | { |
| | | string currentModel = this.modelSelect.SelectedItem.ToString(); |
| | | List<ParameterData> parameters = ProductManager.GetParametersByProductName(currentModel); |
| | | testResultView.engine.Globals.SetValString("ProductModel", 0, currentModel); |
| | | testResultView.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | |
| | | testResultView.executionWrapper.SetStationGlobalValue<string>("ProductModel", 0, currentModel); |
| | | testResultView.executionWrapper.CommitToDisk(false); |
| | | |
| | | //testResultView.engine.Globals.SetValString("ProductModel", 0, currentModel); |
| | | //testResultView.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | IsRunning = false; |
| | | return; |
| | | } |
| | | LogHelper.Info("UI", "总启动按钮按下", out _); |
| | | log.Info("总启动按钮按下"); |
| | | ShowMask(() => |
| | | { |
| | | testResultView.StartTestSequence(); |
| | |
| | | { |
| | | try |
| | | { |
| | | bool breakStop = false; |
| | | foreach (var oven in TestResultView.tables) |
| | | { |
| | | if (oven.IsTesting) |
| | | { |
| | | breakStop = true; |
| | | break; |
| | | } |
| | | } |
| | | if (breakStop) |
| | | { |
| | | MsgBoxHelper2.Warn(this.lang("Tr.OvenIsTesting")); |
| | | return; |
| | | } |
| | | |
| | | if (MsgBoxHelper2.WarnChoose(this.lang("Tr.MakeSureStopAllTest")) != MessageBoxResult.OK) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | LogHelper.Info("UI", "总停止按钮按下", out _); |
| | | log.Info("总停止按钮按下"); |
| | | testResultView.StopTest(); |
| | | /// 已经加了WaitForExit,这里可以改为false |
| | | IsRunning = false; |
| | | } |
| | | catch (Exception ex) |
| | |
| | | |
| | | private void StdEnableMes_ValueChanged(object sender, StdUIEventArg e) |
| | | { |
| | | testResultView.SequenceContext?.StationGlobals.SetValBoolean($"SystemSetting.{e.StringValue}", 1, e.BoolValue); |
| | | testResultView.executionWrapper.SetStationGlobalValue<bool>($"SystemSetting.{e.StringValue}", 1, e.BoolValue); |
| | | //testResultView.SequenceContext?.StationGlobals.SetValBoolean($"SystemSetting.{e.StringValue}", 1, e.BoolValue); |
| | | } |
| | | |
| | | public void HandleAlarm(AlarmText alarm) |
| | | { |
| | | if (alarm.Level >= 4 && TestResultView.tables != null) |
| | | { |
| | | log.Info($"4级报警触发: [{alarm.AlarmInfo}],将停止所有炉体测试"); |
| | | foreach (var oven in TestResultView.tables) |
| | | { |
| | | testResultView.SetStartFlag(oven.index, false); |
| | |
| | | if (alarm.Level >= 3) |
| | | { |
| | | /// 3级以上的报警会停止测试 |
| | | log.Info($"3级报警触发: [{alarm.AlarmInfo}],将停止老化炉[{targetOven.title}]测试"); |
| | | testResultView.SetStartFlag(targetOven.index, false); |
| | | } |
| | | } |
| | | |
| | | public override void Active() |
| | | { |
| | | base.Active(); |
| | | LoadProduct(); |
| | | RefreshUIConfig(); |
| | | } |
| | | |
| | | public override void OnClose(object sender, CancelEventArgs e) |
| | | { |
| | | if (IsRunning) |
| | | { |
| | | MsgBoxHelper2.Warn("请先停止老化测试!"); |
| | | e.Cancel = true; |
| | | } |
| | | } |
| | | |
| | | public override void DoClose(object sender, EventArgs e) |
| | | { |
| | | try |
| | | { |
| | | timer?.Stop(); |
| | | testResultView.ReleaseResource(); |
| | | } |
| | | catch |
| | | { |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | <package id="LiveChartsCore.SkiaSharpView.WPF" version="2.0.0-rc5.4" targetFramework="net472" /> |
| | | <package id="log4net" version="3.0.4" targetFramework="net472" /> |
| | | <package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net472" /> |
| | | <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" /> |
| | | <package id="OpenTK" version="3.3.1" targetFramework="net472" /> |
| | | <package id="OpenTK.GLWpfControl" version="3.3.0" targetFramework="net472" /> |
| | | <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" /> |
| | |
| | | <Reference Include="WindowsFormsIntegration" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Page Include="ScreenGrid.xaml"> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | <SubType>Designer</SubType> |
| | | </Page> |
| | | <Page Include="ScreenTouch.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | | <Page Include="ScreenTouchWin.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | | <Page Include="WorkOrderWin.xaml"> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | <SubType>Designer</SubType> |
| | |
| | | <SubType>Designer</SubType> |
| | | </Page> |
| | | <Compile Include="Entity\TestStep.cs" /> |
| | | <Compile Include="ScreenGrid.xaml.cs"> |
| | | <DependentUpon>ScreenGrid.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="ScreenTouch.xaml.cs"> |
| | | <DependentUpon>ScreenTouch.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="ScreenTouchWin.xaml.cs"> |
| | | <DependentUpon>ScreenTouchWin.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="WorkOrderWin.xaml.cs"> |
| | | <DependentUpon>WorkOrderWin.xaml</DependentUpon> |
| | | </Compile> |
| | |
| | | // 生成号 |
| | | // 修订号 |
| | | // |
| | | [assembly: AssemblyVersion("1.0.0.2")] |
| | | [assembly: AssemblyFileVersion("1.0.0.2")] |
| | | [assembly: AssemblyVersion("1.0.0.3")] |
| | | [assembly: AssemblyFileVersion("1.0.0.3")] |
| | | [assembly: PluginClassName("Plugin.TsExecution.TsExecution")] |
| New file |
| | |
| | | <hb:NotifyControl x:Class="Plugin.TsExecution.ScreenGrid" |
| | | 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:local="clr-namespace:Plugin.TsExecution" |
| | | mc:Ignorable="d" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | Background="LightGray" Padding="0" Margin="0" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <Grid x:Name="grid" dp:GridHelper.Space="2" Margin="0"> |
| | | |
| | | </Grid> |
| | | </hb:NotifyControl> |
| New file |
| | |
| | | using HMI.Base; |
| | | using HMI.UI.DpUtil; |
| | | using System.Collections.ObjectModel; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace Plugin.TsExecution |
| | | { |
| | | public class ScreenGridConfig |
| | | { |
| | | public int rows { get; set; } |
| | | public int columns { get; set; } |
| | | public ObservableCollection<bool> values { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ScreenTouch.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class ScreenGrid : NotifyControl |
| | | { |
| | | public ScreenGrid(int rows, int columns) |
| | | { |
| | | InitializeComponent(); |
| | | |
| | | for (int i = 0; i < rows; i++) |
| | | { |
| | | grid.RowDefinitions.Add(new RowDefinition()); |
| | | } |
| | | |
| | | for (int i = 0; i < columns; i++) |
| | | { |
| | | grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto}); |
| | | } |
| | | } |
| | | |
| | | public void AddScreen(ScreenTouch screen, int row, int col) |
| | | { |
| | | grid.Children.Add(screen); |
| | | Grid.SetRow(screen, row); |
| | | Grid.SetColumn(screen, col); |
| | | |
| | | GridHelper.RefreshGridSpace(grid); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <hb:NotifyControl x:Class="Plugin.TsExecution.ScreenTouch" |
| | | 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:local="clr-namespace:Plugin.TsExecution" |
| | | mc:Ignorable="d" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UniformGrid x:Name="uniform" dp:UniformGridHelper.InnerBorder="0.3" Background="LightGray" |
| | | dp:UniformGridHelper.InnerBorderBrush="Transparent"> |
| | | </UniformGrid> |
| | | </hb:NotifyControl> |
| New file |
| | |
| | | using HMI.Base; |
| | | using System; |
| | | using System.Collections.ObjectModel; |
| | | using System.Globalization; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Data; |
| | | using System.Windows.Media; |
| | | |
| | | namespace Plugin.TsExecution |
| | | { |
| | | public class ColorConverter : IMultiValueConverter |
| | | { |
| | | public static ColorConverter Instance = new ColorConverter(); |
| | | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | if (values[0] is ObservableCollection<string> list && values[1] is string tag) |
| | | { |
| | | if (list?.Contains(tag) == true) return Brushes.Green; |
| | | return Brushes.White; |
| | | } |
| | | return values; |
| | | } |
| | | |
| | | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) |
| | | { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ScreenTouch.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class ScreenTouch : NotifyControl |
| | | { |
| | | public static readonly DependencyProperty ValuesProperty = DependencyProperty.Register( |
| | | nameof(Values), |
| | | typeof(ObservableCollection<bool>), |
| | | typeof(ScreenTouch), |
| | | new PropertyMetadata(null, OnValuesChanged)); |
| | | |
| | | private static void OnValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
| | | { |
| | | if (d is ScreenTouch control) |
| | | { |
| | | // 如果有旧的集合,取消订阅 |
| | | if (e.OldValue is ObservableCollection<bool> oldCollection) |
| | | { |
| | | oldCollection.CollectionChanged -= control.Value_CollectionChanged; |
| | | } |
| | | |
| | | // 如果有新的集合,订阅变更事件 |
| | | if (e.NewValue is ObservableCollection<bool> newCollection) |
| | | { |
| | | newCollection.CollectionChanged += control.Value_CollectionChanged; |
| | | } |
| | | |
| | | // 刷新所有单元格 |
| | | control.PaintPoints(); |
| | | } |
| | | } |
| | | |
| | | |
| | | public ScreenTouch(int rows, int columns) |
| | | { |
| | | this.rows = rows; |
| | | this.columns = columns; |
| | | InitializeComponent(); |
| | | Refresh(); |
| | | Values = new ObservableCollection<bool>(new bool[rows * columns]); |
| | | } |
| | | |
| | | public ObservableCollection<bool> Values |
| | | { |
| | | get => (ObservableCollection<bool>)GetValue(ValuesProperty); |
| | | set |
| | | { |
| | | SetValue(ValuesProperty, value); |
| | | } |
| | | } |
| | | |
| | | private void Value_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) |
| | | { |
| | | PaintPoints(); |
| | | } |
| | | |
| | | public int rows { get; private set; } |
| | | public int columns { get; private set; } |
| | | |
| | | private Border[] children; |
| | | |
| | | public void Refresh() |
| | | { |
| | | uniform.Children.Clear(); |
| | | uniform.Rows = rows; |
| | | uniform.Columns = columns; |
| | | |
| | | children = new Border[rows * columns]; |
| | | |
| | | |
| | | for (int i = 0; i < children.Length; i++) |
| | | { |
| | | var border = new Border |
| | | { |
| | | BorderThickness = new Thickness(0), |
| | | Background = Brushes.White |
| | | }; |
| | | children[i] = border; |
| | | uniform.Children.Add(border); |
| | | } |
| | | } |
| | | |
| | | public void Refresh(int rows, int columns) |
| | | { |
| | | this.rows = rows; |
| | | this.columns = columns; |
| | | Refresh(); |
| | | } |
| | | |
| | | public void Clear() |
| | | { |
| | | Values = new ObservableCollection<bool>(new bool[rows * columns]); |
| | | } |
| | | |
| | | public void DrawPoint(int x, int y) |
| | | { |
| | | Values[y * columns + x] = true; |
| | | } |
| | | |
| | | public void DrawPoints(int[][] points) |
| | | { |
| | | var temp = new ObservableCollection<bool>(new bool[rows * columns]); |
| | | foreach (int[] point in points) |
| | | { |
| | | //children[point[0]][point[1]].Background = Brushes.Green; |
| | | temp[point[1] * columns + point[0]] = true; |
| | | } |
| | | Values = temp; |
| | | } |
| | | |
| | | private void PaintPoints() |
| | | { |
| | | for (int i = 0; i < Values.Count; i++) |
| | | { |
| | | if (Values[i]) |
| | | { |
| | | children[i].Background = Brushes.Green; |
| | | } |
| | | else |
| | | { |
| | | children[i].Background = Brushes.White; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <pu:WindowX x:Class="Plugin.TsExecution.ScreenTouchWin" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:local="clr-namespace:Plugin.TsExecution" |
| | | mc:Ignorable="d" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | SizeChanged="Window_SizeChanged" |
| | | Style="{StaticResource ModalWindow}" |
| | | pu:WindowXModalDialog.Buttons="{x:Null}" |
| | | WindowStartupLocation="CenterScreen" |
| | | WindowState="Maximized" |
| | | Background="LightGray" |
| | | Title="Screens" Height="450" Width="800"> |
| | | <Grid x:Name="grid" HorizontalAlignment="Center"> |
| | | |
| | | </Grid> |
| | | </pu:WindowX> |
| New file |
| | |
| | | using Panuon.WPF.UI; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Collections.ObjectModel; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Data; |
| | | using System.Windows.Documents; |
| | | using System.Windows.Input; |
| | | using System.Windows.Media; |
| | | using System.Windows.Media.Imaging; |
| | | using System.Windows.Shapes; |
| | | |
| | | namespace Plugin.TsExecution |
| | | { |
| | | /// <summary> |
| | | /// ScreenTouchWin.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class ScreenTouchWin : WindowX |
| | | { |
| | | private ScreenGrid screenGrid; |
| | | private ScreenTouch[] screens; |
| | | |
| | | public ScreenTouchWin(ScreenTouch[] configs) |
| | | { |
| | | screenGrid = new ScreenGrid(1, configs.Length); |
| | | screens = new ScreenTouch[configs.Length]; |
| | | InitializeComponent(); |
| | | |
| | | int space = 2 * (screens.Length + 1); |
| | | for (int i = 0; i < screens.Length; i++) |
| | | { |
| | | var screen = new ScreenTouch(configs[i].rows, configs[i].columns) |
| | | { |
| | | Width = Math.Max(Math.Floor((this.ActualHeight / 9 * 16 - space) / screens.Length), 0), |
| | | Height = Math.Max(Math.Floor((this.ActualHeight / 9 * 16 - space) / screens.Length / 16 * 9), 0) |
| | | }; |
| | | |
| | | screen.SetBinding(ScreenTouch.ValuesProperty, new Binding(nameof(ScreenTouch.Values)) { Source = configs[i], Mode = BindingMode.OneWay }); |
| | | |
| | | screens[i] = screen; |
| | | screenGrid.AddScreen(screen, 0, i); |
| | | } |
| | | |
| | | grid.Children.Add(screenGrid); |
| | | } |
| | | |
| | | private void Window_SizeChanged(object sender, SizeChangedEventArgs e) |
| | | { |
| | | if (screenGrid == null) |
| | | { |
| | | return; |
| | | } |
| | | int space = 2 * (screens.Length + 1); |
| | | |
| | | for (int i = 0; i < screens.Length; i++) |
| | | { |
| | | var screen = screens[i]; |
| | | screen.Width = Math.Max(Math.Floor((this.ActualHeight / 9 * 16 - space) / screens.Length), 0); |
| | | screen.Height = Math.Max(Math.Floor((this.ActualHeight / 9 * 16 - space) / screens.Length / 16 * 9), 0); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | FontSize="{Binding ActualHeight,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | | Converter={StaticResource hfc}, ConverterParameter='12,816'}" |
| | | x:Name="control" |
| | | SizeChanged="control_SizeChanged" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <ResourceDictionary> |
| | |
| | | <RowDefinition Height="Auto"/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <Grid dp:GridHelper.InnerBorder="1" dp:GridHelper.Space="2" |
| | | <Grid dp:GridHelper.InnerBorder="1" dp:GridHelper.Space="2" x:Name="tableHeader" |
| | | dp:GridHelper.InnerBorderBrush="{DynamicResource CommonBoarder}"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition Width="Auto"/> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition /> |
| | | <ColumnDefinition Width="Auto"/> |
| | | </Grid.ColumnDefinitions> |
| | | <StackPanel Grid.RowSpan="3"> |
| | | <StackPanel.Style> |
| | | <Style TargetType="StackPanel"> |
| | | <Setter Property="Background" Value="DeepSkyBlue"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding Status}" Value="Passed"> |
| | | <Setter Property="Background" Value="{StaticResource passedColor}"/> |
| | |
| | | <Label> |
| | | <Label.Style> |
| | | <Style TargetType="Label"> |
| | | <Setter Property="VerticalAlignment" Value="Center"/> |
| | | <Setter Property="Padding" Value="10,10,10,0"/> |
| | | <Setter Property="Margin" Value="0"/> |
| | | <Setter Property="FontFamily" Value="{StaticResource iconfont}"/> |
| | |
| | | </Label.Style> |
| | | </Label> |
| | | |
| | | <Label Content="{Binding Status}" VerticalContentAlignment="Center" |
| | | <Label Content="{Binding Status}" VerticalAlignment="Center" VerticalContentAlignment="Center" |
| | | Padding="0" |
| | | Margin="0" |
| | | HorizontalContentAlignment="Center" |
| | |
| | | |
| | | <!--<Label HorizontalContentAlignment="Left" Grid.Column="1" Content="{Binding Status}"/>--> |
| | | |
| | | <Label Style="{StaticResource baseLabel}" Background="#FFF" Grid.Row="1" Grid.Column="1"> |
| | | <Label Style="{StaticResource baseLabel}" Background="#FFF" Grid.Row="0" Grid.Column="1"> |
| | | <StackPanel Orientation="Horizontal"> |
| | | <TextBlock Style="{StaticResource baseText}" Text="{DynamicResource Ts.Total}"/> |
| | | <TextBlock Style="{StaticResource baseText}" Margin="2,0,18,0" Text="{Binding TotalNum}"/> |
| | |
| | | </StackPanel> |
| | | </Label> |
| | | |
| | | <Label Style="{StaticResource baseLabel}" Background="#FFF" Grid.Row="2" Grid.Column="1"> |
| | | <Label Style="{StaticResource baseLabel}" Background="#FFF" Grid.Row="1" Grid.Column="1"> |
| | | <StackPanel Orientation="Horizontal"> |
| | | <Label Style="{StaticResource baseLabel}" Content="{DynamicResource Ts.CurrentSnr}"/> |
| | | <Label Style="{StaticResource baseLabel}" Margin="2,0,18,0" Content="{Binding Barcode}"/> |
| | |
| | | <Label Style="{StaticResource baseLabel}" Margin="2,0,18,0" Content="{Binding ElapseTime}"/> |
| | | </StackPanel> |
| | | </Label> |
| | | <Border x:Name="screenContainer" BorderThickness="0" Grid.Column="2" Grid.RowSpan="2" MouseLeftButtonDown="screenContainer_MouseLeftButtonDown"> |
| | | |
| | | </Border> |
| | | </Grid> |
| | | |
| | | <Grid Grid.Row="2" x:Name="simplePanel" dp:GridHelper.Space="2" dp:GridHelper.SpaceIgnore="TOP"> |
| | |
| | | </ListView.View> |
| | | </ListView>--> |
| | | |
| | | <DataGrid Grid.Row="0" Style="{StaticResource DefaultDataGrid}" Margin="2,0,2,2" |
| | | |
| | | |
| | | <Canvas Grid.Row="0" x:Name="canvas" Background="Transparent"> |
| | | <DataGrid Canvas.Left="0" Canvas.Top="0" Height="{Binding ActualHeight,ElementName=canvas}" |
| | | Width="{Binding ActualWidth,ElementName=canvas}" |
| | | Style="{StaticResource DefaultDataGrid}" Margin="2,0,2,2" |
| | | FontSize="{DynamicResource tableFontSize}" |
| | | dp:DataGridHelper.ShowRowNumber="True" |
| | | VirtualizingPanel.IsContainerVirtualizable="True" |
| | |
| | | RowHeight="{StaticResource nanD}" |
| | | ColumnHeaderHeight="{Binding ActualWidth,ElementName=control, |
| | | Converter={StaticResource fc}, ConverterParameter='32,1093,30,45'}" |
| | | HorizontalScrollBarVisibility="Disabled" |
| | | HorizontalScrollBarVisibility="Disabled" |
| | | ItemsSource="{Binding Datasource}" x:Name="table"> |
| | | |
| | | <DataGrid.Columns> |
| | | <DataGridTextColumn Header="#" |
| | | <DataGrid.Columns> |
| | | <DataGridTextColumn Header="#" |
| | | ElementStyle="{StaticResource TableTextBlock}" |
| | | Binding="{Binding Header, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}, Mode=FindAncestor}}" |
| | | Width="0.4*"/> |
| | | <DataGridTextColumn Width="2.5*" Binding="{Binding Name}" |
| | | <DataGridTextColumn Width="2.5*" Binding="{Binding Name}" |
| | | ElementStyle="{StaticResource TableTextBlock}"> |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Name}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="0.8*" Binding="{Binding Unit}" |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Name}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="0.8*" Binding="{Binding Unit}" |
| | | ElementStyle="{StaticResource TableTextBlock}"> |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Unit}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="2*" Binding="{Binding Value}" |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Unit}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="2*" Binding="{Binding Value}" |
| | | ElementStyle="{StaticResource TableTextBlock}"> |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Value}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="1.5*" Binding="{Binding LimitDown}" |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Value}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="1.5*" Binding="{Binding LimitDown}" |
| | | ElementStyle="{StaticResource TableTextBlock}"> |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.LimitDown}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="1.5*" Binding="{Binding LimitUp}" |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.LimitDown}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="1.5*" Binding="{Binding LimitUp}" |
| | | ElementStyle="{StaticResource TableTextBlock}"> |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.LimitUp}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="0.6*" Binding="{Binding ConsumeTime}" |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.LimitUp}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTextColumn Width="0.6*" Binding="{Binding ConsumeTime}" |
| | | ElementStyle="{StaticResource TableTextBlock}"> |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.ConsumeTime}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTemplateColumn Width="1*"> |
| | | <DataGridTemplateColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Result}"/> |
| | | </DataGridTemplateColumn.Header> |
| | | <DataGridTemplateColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Grid x:Name="border" Margin="0"> |
| | | <TextBlock x:Name="text" Margin="-1" Padding="0" VerticalAlignment="Center" Text="{Binding Result}"/> |
| | | </Grid> |
| | | <DataTemplate.Triggers> |
| | | <DataTrigger Binding="{Binding Result}" Value="Passed"> |
| | | <Setter TargetName="border" Property="Background" Value="{StaticResource passedColor}"/> |
| | | <Setter TargetName="text" Property="Foreground" Value="#000"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Result}" Value="Failed"> |
| | | <Setter TargetName="border" Property="Background" Value="{DynamicResource DangerColor}"/> |
| | | <Setter TargetName="text" Property="Foreground" Value="#000"/> |
| | | </DataTrigger> |
| | | </DataTemplate.Triggers> |
| | | </DataTemplate> |
| | | </DataGridTemplateColumn.CellTemplate> |
| | | </DataGridTemplateColumn> |
| | | </DataGrid.Columns> |
| | | </DataGrid> |
| | | <DataGridTextColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.ConsumeTime}"/> |
| | | </DataGridTextColumn.Header> |
| | | </DataGridTextColumn> |
| | | <DataGridTemplateColumn Width="1*"> |
| | | <DataGridTemplateColumn.Header> |
| | | <TextBlock Text="{DynamicResource Test.Result}"/> |
| | | </DataGridTemplateColumn.Header> |
| | | <DataGridTemplateColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Grid x:Name="border" Margin="0"> |
| | | <TextBlock x:Name="text" Margin="-1" Padding="0" VerticalAlignment="Center" Text="{Binding Result}"/> |
| | | </Grid> |
| | | <DataTemplate.Triggers> |
| | | <DataTrigger Binding="{Binding Result}" Value="Passed"> |
| | | <Setter TargetName="border" Property="Background" Value="{StaticResource passedColor}"/> |
| | | <Setter TargetName="text" Property="Foreground" Value="#000"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Result}" Value="Failed"> |
| | | <Setter TargetName="border" Property="Background" Value="{DynamicResource DangerColor}"/> |
| | | <Setter TargetName="text" Property="Foreground" Value="#000"/> |
| | | </DataTrigger> |
| | | </DataTemplate.Triggers> |
| | | </DataTemplate> |
| | | </DataGridTemplateColumn.CellTemplate> |
| | | </DataGridTemplateColumn> |
| | | </DataGrid.Columns> |
| | | </DataGrid> |
| | | </Canvas> |
| | | |
| | | <Grid Grid.Row="1" Height="20" Margin="0"> |
| | | <ProgressBar Grid.Row="3" x:Name="testProcess" Value="{Binding ProcessValue}"/> |
| | |
| | | |
| | | <Grid Background="#f1eded" Grid.Row="2" Height="25"> |
| | | <DockPanel> |
| | | <Label Padding="0" FontSize="12" VerticalContentAlignment="Center" Content="{Binding CurrentStep}"/> |
| | | <Label Margin="10,0,0,0" Padding="0" FontSize="16" VerticalContentAlignment="Center" Content="{Binding SocketName}"/> |
| | | <Label Margin="20,0,0,0" Padding="0" FontSize="14" VerticalContentAlignment="Center" Content="{Binding CurrentStep}"/> |
| | | |
| | | <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" Margin="0,0,5,0"> |
| | | <!--<Button FontSize="12" x:Name="scannerSetting" |
| | |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Util; |
| | | using HMI.Util; |
| | | using NationalInstruments.TestStand.Interop.API; |
| | |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Runtime.CompilerServices; |
| | | using System.Timers; |
| | | using System.Windows; |
| | |
| | | } |
| | | } |
| | | #endregion |
| | | private bool isLoadOK = false; |
| | | private int index; |
| | | private string CountIniPath; |
| | | |
| | | private string status = "Ready"; |
| | | |
| | | private ScreenTouch[] screens; |
| | | private ScreenGrid screenGrid; |
| | | |
| | | public string Status |
| | | { |
| | |
| | | Set("TestInfo"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private string socketName = string.Empty; |
| | | public string SocketName |
| | | { |
| | | get { return socketName; } |
| | | set |
| | | { |
| | | Set(ref socketName, value); |
| | | } |
| | | } |
| | | |
| | |
| | | //Canvas.SetTop(modal, (scannerPanel.ActualHeight - scannerVisualModal.ActualHeight) / 2); |
| | | } |
| | | } |
| | | |
| | | public void RefreshScreen(int[][] configs) |
| | | { |
| | | //foreach (UIElement item in canvas.Children) |
| | | //{ |
| | | // if (item is ScreenTouch) |
| | | // { |
| | | // canvas.Children.Remove(item); |
| | | // } |
| | | //} |
| | | screenContainer.Child = null; |
| | | |
| | | |
| | | screenGrid = new ScreenGrid(1, configs.Length); |
| | | |
| | | screens = new ScreenTouch[configs.Length]; |
| | | |
| | | int space = 2 * (screens.Length + 1); |
| | | for (int i = 0; i < configs.Length; i++) |
| | | { |
| | | var screen = new ScreenTouch(configs[i][0], configs[i][1]) |
| | | { |
| | | Width = Math.Max((tableHeader.ActualHeight / 9 * 16 - space) / screens.Length, 0), |
| | | Height = Math.Max((tableHeader.ActualHeight / 9 * 16 - space) / screens.Length / 16 * 9, 0) |
| | | }; |
| | | screens[i] = screen; |
| | | screenGrid.AddScreen(screen, 0, i); |
| | | } |
| | | screenContainer.Child = screenGrid; |
| | | |
| | | //canvas.Children.Add(screens[0]); |
| | | //Canvas.SetBottom(screens[0], 0); |
| | | //Canvas.SetRight(screens[0], 0); |
| | | //Panel.SetZIndex(screens[0], 999); |
| | | } |
| | | |
| | | public void DrawScreenPoint(int index, int x, int y) |
| | | { |
| | | screens[index].DrawPoint(x, y); |
| | | } |
| | | |
| | | public void DrawScreenPoints(int index, int[][] points) |
| | | { |
| | | screens[index].DrawPoints(points); |
| | | } |
| | | |
| | | public void ClearScreenPoint(int index) |
| | | { |
| | | screens[index].Clear(); |
| | | } |
| | | |
| | | public void RefreshProduct(ProductData product) |
| | | { |
| | | if (product == null) |
| | | { |
| | | screenContainer.Child = null; |
| | | return; |
| | | } |
| | | try |
| | | { |
| | | string screenSize = ProductManager.GetParameterByProductAndName(product.Name, "ScreenTouch")?.Value; |
| | | if (string.IsNullOrEmpty(screenSize)) |
| | | { |
| | | screenContainer.Child = null; |
| | | return; |
| | | } |
| | | string[] arr = screenSize.Split(';'); |
| | | int[][] configs = new int[arr.Length][]; |
| | | |
| | | for (int i = 0; i < arr.Length; i++) |
| | | { |
| | | string[] size = arr[i].Split(','); |
| | | configs[i] = new int[2] { int.Parse(size[0]), int.Parse(size[1]) }; |
| | | } |
| | | RefreshScreen(configs); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | TsExecution.logger.Error("RefreshProduct Failed.", ex); |
| | | screenContainer.Child = null; |
| | | } |
| | | } |
| | | |
| | | private void control_SizeChanged(object sender, SizeChangedEventArgs e) |
| | | { |
| | | if (screenGrid == null) |
| | | { |
| | | return; |
| | | } |
| | | //screenGrid.Height = tableHeader.ActualHeight - 2; |
| | | //screenGrid.Width = tableHeader.ActualHeight / 9 * 16 - 2; |
| | | |
| | | int space = 2 * (screens.Length + 1); |
| | | |
| | | for (int i = 0; i < screens.Length; i++) |
| | | { |
| | | var screen = screens[i]; |
| | | screen.Width = Math.Max(Math.Floor((tableHeader.ActualHeight / 9 * 16 - space) / screens.Length), 0); |
| | | screen.Height = Math.Max(Math.Floor(screen.Width / 16 * 9), 0); |
| | | } |
| | | } |
| | | |
| | | private void screenContainer_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | if (e.ClickCount == 2) |
| | | { |
| | | new ScreenTouchWin(screens) |
| | | { |
| | | Owner = Window.GetWindow(this) |
| | | }.ShowDialog(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | using System.ComponentModel; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Runtime.InteropServices; |
| | | using System.Timers; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | |
| | | private SequenceFile modeSeq = null; |
| | | public AxApplicationMgr AxApplicationMgr; |
| | | private Execution execution = null; |
| | | |
| | | private SequenceContext sequenceContext = null; |
| | | |
| | | private Chart chart; |
| | | #endregion |
| | |
| | | { |
| | | Set(ref selectedProduct, value); |
| | | CurrentProductModel = value?.Name; |
| | | if (tsSockets != null) |
| | | { |
| | | foreach (SingleControl socket in tsSockets) |
| | | { |
| | | socket.RefreshProduct(value); |
| | | } |
| | | } |
| | | SetTestSeqFile(value); |
| | | } |
| | | } |
| | |
| | | SelectedProduct = tempProduct; |
| | | } |
| | | RefershUI(); |
| | | if (tsSockets != null) |
| | | { |
| | | foreach (SingleControl socket in tsSockets) |
| | | { |
| | | socket.RefreshProduct(SelectedProduct); |
| | | } |
| | | } |
| | | SampleStatus = false; |
| | | } |
| | | |
| | |
| | | private void InitTsEngine() |
| | | { |
| | | AxApplicationMgr = TestAppManager.GetAxApplicationMgr(); |
| | | |
| | | |
| | | //AxApplicationMgr. += AxApplicationMgr_EndExecution; |
| | | AxApplicationMgr.EndExecution += AxApplicationMgr_EndExecution; |
| | | AxApplicationMgr.ExitApplication += new EventHandler(this.AxApplicationMgr_ExitApplication); |
| | | AxApplicationMgr.UIMessageEvent += |
| | | new _ApplicationMgrEvents_UIMessageEventEventHandler(this.AxApplicationMgr_UIMessageEvent); |
| | | AxApplicationMgr.ExecutionClosed += |
| | | new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.AxApplicationMgr_ExecutionClosed); |
| | | |
| | | AxApplicationMgr.ExitApplication += this.AxApplicationMgr_ExitApplication; |
| | | AxApplicationMgr.UIMessageEvent += this.AxApplicationMgr_UIMessageEvent; |
| | | AxApplicationMgr.ExecutionClosed += this.AxApplicationMgr_ExecutionClosed; |
| | | |
| | | ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).BeginInit(); |
| | | host.Child = AxApplicationMgr; |
| | | ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).EndInit(); |
| | | } |
| | | |
| | | private volatile bool canSwitchModel = false; |
| | | private volatile Action switchAction = null; |
| | | |
| | | private void AxApplicationMgr_EndExecution(object sender, _ApplicationMgrEvents_EndExecutionEvent e) |
| | | { |
| | | log.Info("AxApplicationMgr_EndExecution"); |
| | | if (ReleaseSequenceFile()) |
| | | { |
| | | IsTesting = false; |
| | | log.Info("Release SeqFile Success!"); |
| | | if (canSwitchModel) switchAction?.Invoke(); |
| | | } |
| | | else |
| | | { |
| | |
| | | private void RefershUI() |
| | | { |
| | | panel.Children.Clear(); |
| | | string[] names = ParamSetting.SocketNames.Split(','); |
| | | |
| | | //重新生成子面板 |
| | | for (int i = 0; i < this.socketNum; i++) |
| | | { |
| | | SingleControl control = new SingleControl(i, CountIniPath, this.probeWarn); |
| | | string name = string.Empty; |
| | | if (i < names.Length) |
| | | { |
| | | name = names[i]; |
| | | } |
| | | |
| | | SingleControl control = new SingleControl(i, CountIniPath, this.probeWarn) |
| | | { |
| | | SocketName = name |
| | | }; |
| | | panel.Children.Add(control); |
| | | tsSockets.Add(control); |
| | | |
| | |
| | | private void StartSequence() |
| | | { |
| | | if (!isLoadOK) return; |
| | | |
| | | engine?.Globals.SetValBoolean("StationState.StopTest", 0, false); |
| | | if (ParamSetting.EnableAutoModel) |
| | | { |
| | | try |
| | |
| | | |
| | | public void StopSequenceClick() |
| | | { |
| | | canSwitchModel = false; |
| | | switchAction = null; |
| | | ShowMask(() => |
| | | { |
| | | bool stoped = StopSequence(); |
| | | if (stoped) |
| | | { |
| | | IsTesting = false; |
| | | } |
| | | }, null, null, LangUtil.Get("App.SequenceIsStopping")); |
| | | //new MaskWindow((WindowX)Window.GetWindow(this), |
| | | // (win) => |
| | | // { |
| | | // try |
| | | // { |
| | | // bool stoped = StopSequence(); |
| | | // if (stoped) |
| | | // { |
| | | // IsTesting = false; |
| | | // } |
| | | // } |
| | | // finally |
| | | // { |
| | | // Dispatcher.Invoke(() => |
| | | // { |
| | | |
| | | // win.Close(); |
| | | // }); |
| | | // } |
| | | // } |
| | | // ).Info(LangUtil.Get("App.SequenceIsStopping")); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | for (int i = 0; i < tsSockets.Count; i++) |
| | | { |
| | | var context = this.tsSockets[i].SequenceFileContext; |
| | | //bool val = context.StationGlobals.Exists("StationState.StopTest", 0); |
| | | //if (val) |
| | | //{ |
| | | // context.StationGlobals.SetValBoolean("StationState.StopTest", 0, true); |
| | | // bool isStop = this.execution.WaitForEndEx(2000, true, null, null); |
| | | //} |
| | | context?.StationGlobals.SetValBoolean("StationState.StopTest", 1, true); |
| | | } |
| | | } |
| | | if (this.execution == null) return true; |
| | | |
| | | bool res = this.execution.WaitForEndEx(2000, true, null, null); |
| | | //bool res = this.execution.WaitForEndEx(-1, true, null, null); |
| | | bool res = this.execution?.WaitForEndEx(-1, true, Type.Missing, null) == true; |
| | | Marshal.ReleaseComObject(this.execution); |
| | | this.execution = null; |
| | | return res; |
| | | } |
| | | catch (Exception ex) |
| | |
| | | |
| | | private void StartClick() |
| | | { |
| | | canSwitchModel = true; |
| | | ShowMask(() => |
| | | { |
| | | StartSequence(); |
| | |
| | | this.tsSockets[index].ElapseTime = strData; |
| | | break; |
| | | case (int)UIMessageCodes.UIMsg_EndExecution://执行结束 |
| | | IsTesting = false; |
| | | //IsTesting = false; |
| | | //this.ReleaseSequenceFile(); |
| | | break; |
| | | case 10030://显示测试进度 |
| | |
| | | case 10034: |
| | | CurrentProductModel = strData; |
| | | break; |
| | | case 10035: |
| | | string[] arr_10035 = strData.Split(';'); |
| | | |
| | | int[][] points = new int[arr_10035.Length - 1][]; |
| | | |
| | | for (int i = 1; i < arr_10035.Length; i++) |
| | | { |
| | | string[] strs = arr_10035[i].Split(','); |
| | | points[i - 1] = new int[2] { int.Parse(strs[0]), int.Parse(strs[1]) }; |
| | | } |
| | | this.tsSockets[index].DrawScreenPoints(int.Parse(arr_10035[0]), points); |
| | | break; |
| | | case 10036: |
| | | this.tsSockets[index].ClearScreenPoint(int.Parse(strData)); |
| | | break; |
| | | case 10099: |
| | | string[] arr = strData.Split(','); |
| | | if (canSwitchModel) SwitchSequenceByModel(index, arr[0], arr[1]); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private void SwitchSequenceByModel(int index, string model, string snr) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | var target = Products.FirstOrDefault(e => e.Name == model); |
| | | |
| | | ShowMask(() => |
| | | { |
| | | bool stoped = StopSequence(); |
| | | //if (stoped) |
| | | //{ |
| | | // IsTesting = false; |
| | | //} |
| | | }, null, null, "换型中,请稍后..."); |
| | | |
| | | if (target == null) |
| | | { |
| | | MsgBoxHelper2.Warn($"请先在产品管理页面配置型号 [{model}] 的产品信息!"); |
| | | return; |
| | | } |
| | | |
| | | switchAction = () => |
| | | { |
| | | switchAction = null; |
| | | log?.Info($"尝试自动换型: {switchAction}"); |
| | | if (canSwitchModel) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | try |
| | | { |
| | | log?.Info("开始自动换型"); |
| | | SelectedProduct = target; |
| | | engine?.Globals.SetValString($"CacheSNR[{index}]", 1, snr); |
| | | engine?.CommitGlobalsToDisk(false); |
| | | StartClick(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log?.Error("自动换型失败", ex); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | }); |
| | | } |
| | | |
| | | private void ShowAlarm(AlarmText alarm) |
| | |
| | | |
| | | try |
| | | { |
| | | log.Info($"Event: {eventCode}, NumericData: {index}, StringData: {strData}"); |
| | | log.Debug($"Event: {eventCode}, NumericData: {index}, StringData: {strData}"); |
| | | } |
| | | catch |
| | | { |
| | |
| | | } |
| | | if (eventCode == 10001) |
| | | { |
| | | sequenceContext = (SequenceContext)e.uiMsg.ActiveXData; |
| | | |
| | | tsSockets[index].SequenceFileContext = (SequenceContext)e.uiMsg.ActiveXData; |
| | | return; |
| | | } |
| | |
| | | { |
| | | lock (this) |
| | | { |
| | | if (this.testSeq == null) |
| | | { |
| | | return true; |
| | | } |
| | | //execution.Abort(); |
| | | int count = 10; |
| | | while (count > 0) |
| | |
| | | if (this.testSeq == null) |
| | | return true; |
| | | |
| | | if (this.engine.ReleaseSequenceFileEx(this.testSeq, 4)) |
| | | if (this.engine?.ReleaseSequenceFileEx(this.testSeq, 4) == true) |
| | | { |
| | | Marshal.ReleaseComObject(this.testSeq); |
| | | this.testSeq = null; |
| | | // GC.Collect(); |
| | | } |
| | | if (this.engine.ReleaseSequenceFileEx(this.modeSeq, 4)) |
| | | if (this.engine?.ReleaseSequenceFileEx(this.modeSeq, 4) == true) |
| | | { |
| | | Marshal.ReleaseComObject(this.modeSeq); |
| | | this.modeSeq = null; |
| | | } |
| | | this.engine.UnloadAllModules(); |
| | | this.engine?.UnloadAllModules(); |
| | | return this.testSeq == null && this.modeSeq == null; |
| | | } |
| | | catch (Exception ex) |
| New file |
| | |
| | | using NationalInstruments.TestStand.Interop.API; |
| | | using System; |
| | | |
| | | namespace Plugin.TsSupport |
| | | { |
| | | public class ExecutionEndEvent |
| | | { |
| | | public object Origin { get; set; } |
| | | public object Data { get; set; } |
| | | } |
| | | |
| | | public class UIMessageEvent |
| | | { |
| | | public object Origin { get; set; } |
| | | public object Data { get; set; } |
| | | public int EventCode { get; set; } |
| | | public double NumberData { get; set; } |
| | | public bool BoolData { get; set; } |
| | | public string StrData { get; set; } |
| | | } |
| | | |
| | | public interface ITestExecutionWrapper |
| | | { |
| | | event EventHandler<UIMessageEvent> UIMessageEvent; |
| | | |
| | | event EventHandler<ExecutionEndEvent> EndExecutionEvent; |
| | | |
| | | object Init(); |
| | | |
| | | object StartSequence(string filePath, string modelPath); |
| | | |
| | | T GetStationGlobalValue<T>(string key, int option); |
| | | |
| | | T GetFileGlobalValue<T>(string key, int option); |
| | | |
| | | void SetStationGlobalValue<T>(string key, int option, T value, bool inContext = false); |
| | | |
| | | void SetFileGlobalValue<T>(string key, int option, T value); |
| | | |
| | | void CommitToDisk(bool option); |
| | | |
| | | bool WaitForExit(); |
| | | |
| | | bool ReleaseSeqFile(); |
| | | void SetContext(object context); |
| | | } |
| | | } |
| | |
| | | <Reference Include="System.Xml" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Compile Include="ITestExecutionWrapper.cs" /> |
| | | <Compile Include="TestAppManager.cs" /> |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | <Compile Include="TeststandWrapper.cs" /> |
| | | <Compile Include="TsExecutionWrapper.cs" /> |
| | | </ItemGroup> |
| | | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| | | </Project> |
| New file |
| | |
| | | using NationalInstruments.TestStand.Interop.API; |
| | | using NationalInstruments.TestStand.Interop.UI.Ax; |
| | | using System; |
| | | using System.Diagnostics; |
| | | |
| | | namespace Plugin.TsSupport |
| | | { |
| | | public class TeststandWrapper : ITestExecutionWrapper |
| | | { |
| | | #region TestStand事件 |
| | | /// <summary> |
| | | /// TS 引擎 |
| | | /// </summary> |
| | | private Engine engine = null; |
| | | |
| | | /// <summary> |
| | | /// 测试序列路径 |
| | | /// </summary> |
| | | private string testSeqFile = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// 测试序列 |
| | | /// </summary> |
| | | private SequenceFile testSeq = null; |
| | | |
| | | /// <summary> |
| | | /// 测试模型序列 |
| | | /// </summary> |
| | | private SequenceFile modeSeq = null; |
| | | |
| | | /// <summary> |
| | | /// 运行实例 |
| | | /// </summary> |
| | | private Execution execution = null; |
| | | |
| | | public SequenceContext context { get; set; } = null; |
| | | |
| | | /// <summary> |
| | | /// 事件管理器 |
| | | /// </summary> |
| | | public AxApplicationMgr AxApplicationMgr { get; private set; } |
| | | #endregion |
| | | |
| | | public event EventHandler<UIMessageEvent> UIMessageEvent; |
| | | public event EventHandler<ExecutionEndEvent> EndExecutionEvent; |
| | | |
| | | public TeststandWrapper() |
| | | { |
| | | AxApplicationMgr = TestAppManager.GetAxApplicationMgr(); |
| | | AxApplicationMgr.EndExecution += AxApplicationMgr_EndExecution; |
| | | AxApplicationMgr.UIMessageEvent += AxApplicationMgr_UIMessageEvent; |
| | | |
| | | //AxApplicationMgr.ExitApplication += new EventHandler(this.AxApplicationMgr_ExitApplication); |
| | | //AxApplicationMgr.ExecutionClosed += |
| | | // new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.AxApplicationMgr_ExecutionClosed); |
| | | } |
| | | |
| | | private void AxApplicationMgr_UIMessageEvent(object sender, _ApplicationMgrEvents_UIMessageEventEvent e) |
| | | { |
| | | UIMessageEvent?.Invoke(this, new UIMessageEvent() |
| | | { |
| | | Origin = e, |
| | | EventCode = Convert.ToInt32(e.uiMsg.Event), |
| | | NumberData = Convert.ToInt16(e.uiMsg.NumericData), |
| | | Data = e.uiMsg.ActiveXData, |
| | | StrData = e.uiMsg.StringData |
| | | }); |
| | | } |
| | | |
| | | private void AxApplicationMgr_EndExecution(object sender, _ApplicationMgrEvents_EndExecutionEvent e) |
| | | { |
| | | EndExecutionEvent?.Invoke(this, new ExecutionEndEvent() { Origin = e }); |
| | | } |
| | | |
| | | public object Init() |
| | | { |
| | | this.engine = this.AxApplicationMgr.GetEngine(); |
| | | this.engine.PersistBreakpoints = false; |
| | | this.AxApplicationMgr.IsEditor = true; |
| | | this.AxApplicationMgr.LoginOnStart = false; |
| | | this.AxApplicationMgr.Start(); |
| | | return this.AxApplicationMgr; |
| | | } |
| | | |
| | | public object StartSequence(string filePath, string modelPath) |
| | | { |
| | | this.testSeqFile = filePath; |
| | | |
| | | this.modeSeq = this.engine.GetSequenceFileEx(modelPath); |
| | | this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType); |
| | | this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null); |
| | | return execution; |
| | | } |
| | | |
| | | public T GetFileGlobalValue<T>(string key, int option) |
| | | { |
| | | if (typeof(T) == typeof(bool)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValBoolean(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(string)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValString(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(int)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(double)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(float)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValNumber(key, option); |
| | | } |
| | | return default(T); |
| | | } |
| | | |
| | | public T GetStationGlobalValue<T>(string key, int option) |
| | | { |
| | | if (typeof(T) == typeof(bool)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValBoolean(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(string)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValString(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(int)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(double)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(float)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValNumber(key, option); |
| | | } |
| | | return default(T); |
| | | } |
| | | |
| | | public void SetFileGlobalValue<T>(string key, int option, T value) |
| | | { |
| | | if (value is bool bVal) |
| | | { |
| | | context?.FileGlobals?.SetValBoolean(key, option, bVal); |
| | | } |
| | | else if (value is string sVal) |
| | | { |
| | | context?.FileGlobals?.SetValString(key, option, sVal); |
| | | } |
| | | else if (value is int iVal) |
| | | { |
| | | context?.FileGlobals?.SetValNumber(key, option, iVal); |
| | | } |
| | | else if (value is double dVal) |
| | | { |
| | | context?.FileGlobals?.SetValNumber(key, option, dVal); |
| | | } |
| | | else if (value is float fVal) |
| | | { |
| | | context?.FileGlobals?.SetValNumber(key, option, fVal); |
| | | } |
| | | } |
| | | |
| | | public void SetStationGlobalValue<T>(string key, int option, T value, bool inContext = false) |
| | | { |
| | | PropertyObject obj = null; |
| | | if (inContext) |
| | | { |
| | | obj = context?.StationGlobals; |
| | | } |
| | | else |
| | | { |
| | | obj = engine?.Globals; |
| | | } |
| | | |
| | | if (value is bool bVal) |
| | | { |
| | | obj?.SetValBoolean(key, option, bVal); |
| | | } |
| | | else if (value is string sVal) |
| | | { |
| | | obj?.SetValString(key, option, sVal); |
| | | } |
| | | else if (value is int iVal) |
| | | { |
| | | obj?.SetValNumber(key, option, iVal); |
| | | } |
| | | else if (value is double dVal) |
| | | { |
| | | obj?.SetValNumber(key, option, dVal); |
| | | } |
| | | else if (value is float fVal) |
| | | { |
| | | obj?.SetValNumber(key, option, fVal); |
| | | } |
| | | //engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | |
| | | public void CommitToDisk(bool option) |
| | | { |
| | | engine?.CommitGlobalsToDisk(option); |
| | | } |
| | | |
| | | public bool WaitForExit() |
| | | { |
| | | return this.execution?.WaitForEndEx(-1, true, Type.Missing, null) == true; |
| | | } |
| | | |
| | | public bool ReleaseSeqFile() |
| | | { |
| | | if (testSeq != null) |
| | | { |
| | | return engine?.ReleaseSequenceFileEx(testSeq, 4) == true; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | public void SetContext(object context) |
| | | { |
| | | this.context = (SequenceContext)context; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using NationalInstruments.TestStand.Interop.API; |
| | | using NationalInstruments.TestStand.Interop.UI.Ax; |
| | | using System; |
| | | |
| | | namespace Plugin.TsSupport |
| | | { |
| | | public class TsExecutionWrapper : ITestExecutionWrapper |
| | | { |
| | | |
| | | #region TestStand事件 |
| | | /// <summary> |
| | | /// TS 引擎 |
| | | /// </summary> |
| | | private Engine engine = null; |
| | | |
| | | /// <summary> |
| | | /// 测试序列路径 |
| | | /// </summary> |
| | | private string testSeqFile = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// 测试序列 |
| | | /// </summary> |
| | | private SequenceFile testSeq = null; |
| | | |
| | | /// <summary> |
| | | /// 测试模型序列 |
| | | /// </summary> |
| | | private SequenceFile modeSeq = null; |
| | | |
| | | /// <summary> |
| | | /// 运行实例 |
| | | /// </summary> |
| | | private Execution execution = null; |
| | | |
| | | public SequenceContext context { get; set; } = null; |
| | | |
| | | /// <summary> |
| | | /// 事件管理器 |
| | | /// </summary> |
| | | public AxApplicationMgr AxApplicationMgr { get; private set; } |
| | | |
| | | public event _ApplicationMgrEvents_EndExecutionEventHandler OnEndExecution; |
| | | |
| | | public event EventHandler<UIMessageEvent> UIMessageEvent; |
| | | public event EventHandler<ExecutionEndEvent> EndExecutionEvent; |
| | | |
| | | public TsExecutionWrapper() |
| | | { |
| | | AxApplicationMgr = TestAppManager.GetAxApplicationMgr(); |
| | | //AxApplicationMgr.EndExecution += AxApplicationMgr_EndExecution; |
| | | //AxApplicationMgr.ExitApplication += new EventHandler(this.AxApplicationMgr_ExitApplication); |
| | | //AxApplicationMgr.UIMessageEvent += |
| | | // new _ApplicationMgrEvents_UIMessageEventEventHandler(this.AxApplicationMgr_UIMessageEvent); |
| | | //AxApplicationMgr.ExecutionClosed += |
| | | // new _ApplicationMgrEvents_ExecutionClosedEventHandler(this.AxApplicationMgr_ExecutionClosed); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | public object Init() |
| | | { |
| | | this.engine = this.AxApplicationMgr.GetEngine(); |
| | | this.engine.PersistBreakpoints = false; |
| | | this.AxApplicationMgr.IsEditor = true; |
| | | this.AxApplicationMgr.LoginOnStart = false; |
| | | this.AxApplicationMgr.Start(); |
| | | return this.AxApplicationMgr; |
| | | } |
| | | |
| | | public object StartSequence(string filePath, string modelPath) |
| | | { |
| | | this.testSeqFile = filePath; |
| | | |
| | | this.modeSeq = this.engine.GetSequenceFileEx(modelPath); |
| | | this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType); |
| | | this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null); |
| | | return execution; |
| | | } |
| | | |
| | | public T GetFileGlobalValue<T>(string key, int option) |
| | | { |
| | | if (typeof(T) == typeof(bool)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValBoolean(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(string)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValString(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(int)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(double)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(float)) |
| | | { |
| | | return (T)(object)context?.FileGlobals?.GetValNumber(key, option); |
| | | } |
| | | return default(T); |
| | | } |
| | | |
| | | public T GetStationGlobalValue<T>(string key, int option) |
| | | { |
| | | if (typeof(T) == typeof(bool)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValBoolean(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(string)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValString(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(int)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(double)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValNumber(key, option); |
| | | } |
| | | else if (typeof(T) == typeof(float)) |
| | | { |
| | | return (T)(object)engine?.Globals?.GetValNumber(key, option); |
| | | } |
| | | return default(T); |
| | | } |
| | | |
| | | public void SetFileGlobalValue<T>(string key, int option, T value) |
| | | { |
| | | if (value is bool bVal) |
| | | { |
| | | context?.FileGlobals?.SetValBoolean(key, option, bVal); |
| | | } |
| | | else if (value is string sVal) |
| | | { |
| | | context?.FileGlobals?.SetValString(key, option, sVal); |
| | | } |
| | | else if (value is int iVal) |
| | | { |
| | | context?.FileGlobals?.SetValNumber(key, option, iVal); |
| | | } |
| | | else if (value is double dVal) |
| | | { |
| | | context?.FileGlobals?.SetValNumber(key, option, dVal); |
| | | } |
| | | else if (value is float fVal) |
| | | { |
| | | context?.FileGlobals?.SetValNumber(key, option, fVal); |
| | | } |
| | | } |
| | | |
| | | public void SetStationGlobalValue<T>(string key, int option, T value, bool inContext = false) |
| | | { |
| | | PropertyObject obj = null; |
| | | if (inContext) |
| | | { |
| | | obj = context?.StationGlobals; |
| | | } |
| | | else |
| | | { |
| | | obj = engine?.Globals; |
| | | } |
| | | |
| | | if (value is bool bVal) |
| | | { |
| | | obj?.SetValBoolean(key, option, bVal); |
| | | } |
| | | else if (value is string sVal) |
| | | { |
| | | obj?.SetValString(key, option, sVal); |
| | | } |
| | | else if (value is int iVal) |
| | | { |
| | | obj?.SetValNumber(key, option, iVal); |
| | | } |
| | | else if (value is double dVal) |
| | | { |
| | | obj?.SetValNumber(key, option, dVal); |
| | | } |
| | | else if (value is float fVal) |
| | | { |
| | | obj?.SetValNumber(key, option, fVal); |
| | | } |
| | | //engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | |
| | | public void CommitToDisk(bool option) |
| | | { |
| | | engine?.CommitGlobalsToDisk(option); |
| | | } |
| | | |
| | | public bool WaitForExit() |
| | | { |
| | | return this.execution?.WaitForEndEx(-1, true, Type.Missing, null) == true; |
| | | } |
| | | |
| | | public bool ReleaseSeqFile() |
| | | { |
| | | if (testSeq != null) |
| | | { |
| | | return engine?.ReleaseSequenceFileEx(testSeq, 4) == true; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | public void SetContext(object context) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System.Windows; |
| | | |
| | | [assembly:ThemeInfo( |
| | | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located |
| | | //(used if a resource is not found in the page, |
| | | // or application resource dictionaries) |
| | | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located |
| | | //(used if a resource is not found in the page, |
| | | // app, or any theme specific resource dictionaries) |
| | | )] |
| New file |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <OutputType>Library</OutputType> |
| | | <TargetFramework>net472</TargetFramework> |
| | | <Nullable>enable</Nullable> |
| | | <LangVersion>10.0</LangVersion> |
| | | <ImplicitUsings>enable</ImplicitUsings> |
| | | <UseWPF>true</UseWPF> |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> |
| | | <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" /> |
| | | <PackageReference Include="Panuon.WPF.UI" Version="1.3.0.2" /> |
| | | <PackageReference Include="TouchSocket" Version="4.2.0" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\UILib\UILib.csproj" /> |
| | | <ProjectReference Include="..\..\UtilLib\UtilLib.csproj" /> |
| | | <ProjectReference Include="..\HMI.UI\HMI.UI.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| New file |
| | |
| | | <UserControl x:Class="Plugin.UICollection.TcpDebugger" |
| | | 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:local="clr-namespace:Plugin.UICollection" |
| | | mc:Ignorable="d" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:UILib.DpUtil;assembly=UILib" |
| | | xmlns:uic="clr-namespace:UILib.Converter;assembly=UILib" |
| | | FontSize="16" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <ResourceDictionary> |
| | | <!--<ResourceDictionary.MergedDictionaries> |
| | | <pu:StyleDictionary Excludes="Button" /> |
| | | </ResourceDictionary.MergedDictionaries>--> |
| | | <Style TargetType="ComboBox"/> |
| | | <Style TargetType="ComboBoxItem"/> |
| | | <Style TargetType="Button"> |
| | | |
| | | </Style> |
| | | <Style TargetType="GroupBox"> |
| | | |
| | | </Style> |
| | | <Style TargetType="TextBox"> |
| | | <Setter Property="VerticalContentAlignment" Value="Center"/> |
| | | <Setter Property="MinWidth" Value="120"/> |
| | | <Setter Property="Height" Value="Auto"/> |
| | | </Style> |
| | | </ResourceDictionary> |
| | | </UserControl.Resources> |
| | | |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition/> |
| | | <RowDefinition Height="Auto"/> |
| | | </Grid.RowDefinitions> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition Width="Auto"/> |
| | | <ColumnDefinition/> |
| | | </Grid.ColumnDefinitions> |
| | | <StackPanel dp:StackPanelHelper.ChildSpace="10" Margin="0,10,0,10"> |
| | | <pu:FormGroup Header="IP" GroupName="client"> |
| | | <TextBox Text="{Binding Ip}"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup Header="Port" GroupName="client"> |
| | | <TextBox Text="{Binding Port}"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup Header="客户端端口" GroupName="client"> |
| | | <TextBox Text="{Binding ClientPort}"/> |
| | | </pu:FormGroup> |
| | | |
| | | <Label> |
| | | <Label.Style> |
| | | <Style TargetType="Label"> |
| | | <Setter Property="Foreground" Value="White"/> |
| | | <Setter Property="Background" Value="Red"/> |
| | | <Setter Property="VerticalContentAlignment" Value="Center"/> |
| | | <Setter Property="HorizontalContentAlignment" Value="Center"/> |
| | | <Setter Property="Content" Value="未连接"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding IsConnected}" Value="True"> |
| | | <Setter Property="Background" Value="Green"/> |
| | | <Setter Property="Content" Value="已连接"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Label.Style> |
| | | </Label> |
| | | |
| | | <Button Tag="Connect" Content="连接" Click="Button_Click"/> |
| | | <GroupBox Header="接收设置"> |
| | | <StackPanel dp:StackPanelHelper.ChildSpace="10" Margin="0,10"> |
| | | <StackPanel Orientation="Horizontal"> |
| | | <RadioButton Content="字符串" IsChecked="{Binding ReceiveDataType,Converter={x:Static uic:RadioEnumConverter.Instance},ConverterParameter={x:Static local:DataType.String}}" GroupName="ReceiveType"/> |
| | | <RadioButton Content="Hex" IsChecked="{Binding ReceiveDataType,Converter={x:Static uic:RadioEnumConverter.Instance},ConverterParameter={x:Static local:DataType.HEX}}" GroupName="ReceiveType"/> |
| | | </StackPanel> |
| | | <pu:FormGroup Header="编码格式"> |
| | | <ComboBox x:Name="receiveEncodeInput" SelectedValue="{Binding ReceiveEncode}"/> |
| | | <pu:FormGroup.Style> |
| | | <Style TargetType="pu:FormGroup"> |
| | | <Setter Property="IsEnabled" Value="False"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding ReceiveDataType}" Value="{x:Static local:DataType.String}"> |
| | | <Setter Property="IsEnabled" Value="True"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </pu:FormGroup.Style> |
| | | </pu:FormGroup> |
| | | </StackPanel> |
| | | </GroupBox> |
| | | </StackPanel> |
| | | |
| | | <StackPanel Grid.Row="1" Grid.Column="0"> |
| | | <GroupBox Header="发送设置"> |
| | | <StackPanel dp:StackPanelHelper.ChildSpace="10" Margin="0,10"> |
| | | <StackPanel Orientation="Horizontal"> |
| | | <RadioButton Content="字符串" IsChecked="{Binding SendDataType,Converter={x:Static uic:RadioEnumConverter.Instance},ConverterParameter={x:Static local:DataType.String}}" GroupName="SendType"/> |
| | | <RadioButton Content="Hex" IsChecked="{Binding SendDataType,Converter={x:Static uic:RadioEnumConverter.Instance},ConverterParameter={x:Static local:DataType.HEX}}" GroupName="SendType"/> |
| | | </StackPanel> |
| | | |
| | | <pu:FormGroup Header="编码格式"> |
| | | <ComboBox x:Name="sendEncodeInput" SelectedValue="{Binding SendEncode}"/> |
| | | <pu:FormGroup.Style> |
| | | <Style TargetType="pu:FormGroup"> |
| | | <Setter Property="IsEnabled" Value="False"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding SendDataType}" Value="{x:Static local:DataType.String}"> |
| | | <Setter Property="IsEnabled" Value="True"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </pu:FormGroup.Style> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup Header="分隔符"> |
| | | <ComboBox ItemsSource="{Binding EndMarkSource}" SelectedValue="{Binding EndMark}" DisplayMemberPath="Name" SelectedValuePath="Type"/> |
| | | <pu:FormGroup.Style> |
| | | <Style TargetType="pu:FormGroup"> |
| | | <Setter Property="IsEnabled" Value="False"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding SendDataType}" Value="{x:Static local:DataType.String}"> |
| | | <Setter Property="IsEnabled" Value="True"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </pu:FormGroup.Style> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Header="自定义分隔符"> |
| | | <TextBox Text="{Binding CustomEndMark}"/> |
| | | <pu:FormGroup.Style> |
| | | <Style TargetType="pu:FormGroup"> |
| | | <Setter Property="IsEnabled" Value="False"/> |
| | | <Style.Triggers> |
| | | <MultiDataTrigger> |
| | | <MultiDataTrigger.Conditions> |
| | | <Condition Binding="{Binding SendDataType}" Value="{x:Static local:DataType.String}"/> |
| | | <Condition Binding="{Binding EndMark}" Value="2"/> |
| | | </MultiDataTrigger.Conditions> |
| | | <Setter Property="IsEnabled" Value="True"/> |
| | | </MultiDataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </pu:FormGroup.Style> |
| | | </pu:FormGroup> |
| | | </StackPanel> |
| | | </GroupBox> |
| | | </StackPanel> |
| | | |
| | | <Grid Grid.Row="1" Grid.Column="1"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | </Grid.ColumnDefinitions> |
| | | <GroupBox Header="数据发送"> |
| | | <TextBox x:Name="sendBox" TextWrapping="Wrap" VerticalContentAlignment="Top" |
| | | PreviewTextInput="TextBox_PreviewTextInput"/> |
| | | </GroupBox> |
| | | <Button Grid.Column="1" Padding="20" Content="发送" Tag="Send" Click="Button_Click"/> |
| | | </Grid> |
| | | |
| | | <Grid Grid.Row="0" Grid.Column="1"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | </Grid.ColumnDefinitions> |
| | | <GroupBox Header="数据接收"> |
| | | <RichTextBox x:Name="console" IsReadOnly="True"/> |
| | | </GroupBox> |
| | | </Grid> |
| | | </Grid> |
| | | </UserControl> |
| New file |
| | |
| | | using CommunityToolkit.Mvvm.ComponentModel; |
| | | using System.Collections.ObjectModel; |
| | | using System.Globalization; |
| | | using System.Text; |
| | | using System.Text.RegularExpressions; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Data; |
| | | using System.Windows.Documents; |
| | | using System.Windows.Media; |
| | | using TouchSocket.Core; |
| | | using TouchSocket.Sockets; |
| | | using UtilLib; |
| | | |
| | | namespace Plugin.UICollection |
| | | { |
| | | public enum DataType |
| | | { |
| | | String = 0, |
| | | HEX = 1 |
| | | } |
| | | |
| | | public enum SupportEncode |
| | | { |
| | | GBK = 0, |
| | | ASCII = 1, |
| | | UTF8 = 2 |
| | | } |
| | | |
| | | public class EndMarkSource |
| | | { |
| | | public string Name { get; set; } |
| | | public int Type { get; set; } |
| | | } |
| | | |
| | | public class ByteStringConverter : IValueConverter |
| | | { |
| | | private TcpDebugger control { get; set; } |
| | | |
| | | public ByteStringConverter(TcpDebugger control) |
| | | { |
| | | this.control = control; |
| | | } |
| | | |
| | | public static string GroupByTwo(string str) |
| | | { |
| | | if (string.IsNullOrEmpty(str)) |
| | | return string.Empty; |
| | | |
| | | StringBuilder result = new StringBuilder(); |
| | | for (int i = 0; i < str.Length; i += 2) |
| | | { |
| | | if (i > 0) |
| | | result.Append(' '); |
| | | |
| | | int length = Math.Min(2, str.Length - i); |
| | | result.Append(str.Substring(i, length)); |
| | | } |
| | | return result.ToString(); |
| | | } |
| | | |
| | | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | DataType sendType = control.SendDataType; |
| | | if (sendType != DataType.HEX) |
| | | { |
| | | return value; |
| | | } |
| | | var str = value.ToString(); |
| | | return GroupByTwo(str); |
| | | } |
| | | |
| | | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | DataType sendType = control.SendDataType; |
| | | if (sendType != DataType.HEX) |
| | | { |
| | | return value; |
| | | } |
| | | return value.ToString().Replace(" ", ""); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// TcpDebugger.xaml 的交互逻辑 |
| | | /// </summary> |
| | | [ObservableObject] |
| | | public partial class TcpDebugger : UserControl |
| | | { |
| | | |
| | | [ObservableProperty] |
| | | private string ip = "127.0.0.1"; |
| | | |
| | | [ObservableProperty] |
| | | private int port; |
| | | |
| | | [ObservableProperty] |
| | | private int clientPort; |
| | | |
| | | [ObservableProperty] |
| | | private DataType receiveDataType = DataType.String; |
| | | |
| | | [ObservableProperty] |
| | | private DataType sendDataType = DataType.String; |
| | | |
| | | [ObservableProperty] |
| | | private bool isConnected = false; |
| | | |
| | | [ObservableProperty] |
| | | private string sendText; |
| | | |
| | | [ObservableProperty] |
| | | private SupportEncode receiveEncode; |
| | | |
| | | [ObservableProperty] |
| | | private SupportEncode sendEncode; |
| | | |
| | | [ObservableProperty] |
| | | private ObservableCollection<EndMarkSource> endMarkSource = new ObservableCollection<EndMarkSource> { |
| | | new EndMarkSource{ Name="无",Type=-1}, |
| | | new EndMarkSource{ Name="\\r",Type=0}, |
| | | new EndMarkSource{ Name="\\r\\n",Type=1}, |
| | | new EndMarkSource{ Name="自定义",Type=2}, |
| | | }; |
| | | |
| | | [ObservableProperty] |
| | | private int endMark; |
| | | |
| | | [ObservableProperty] |
| | | private string customEndMark; |
| | | |
| | | private ByteStringConverter bsConverter; |
| | | |
| | | |
| | | private TcpClient client; |
| | | |
| | | public TcpDebugger() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | sendEncodeInput.ItemsSource = Enum.GetValues(typeof(SupportEncode)).Cast<SupportEncode>(); |
| | | receiveEncodeInput.ItemsSource = Enum.GetValues(typeof(SupportEncode)).Cast<SupportEncode>(); |
| | | DataObject.AddPastingHandler(sendBox, OnPasting); |
| | | bsConverter = new ByteStringConverter(this); |
| | | BindingOperations.SetBinding(sendBox, TextBox.TextProperty, new Binding(nameof(SendText)) |
| | | { |
| | | Source = this, |
| | | Mode = BindingMode.TwoWay, |
| | | UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, |
| | | Converter = bsConverter |
| | | }); |
| | | } |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | var btn = (Button)sender; |
| | | if (btn.Tag.ToString() == "Connect") |
| | | { |
| | | TryConnect(); |
| | | return; |
| | | } |
| | | |
| | | if (btn.Tag.ToString() == "Send") |
| | | { |
| | | TrySend(); |
| | | return; |
| | | } |
| | | |
| | | } |
| | | |
| | | private void TryConnect() |
| | | { |
| | | try |
| | | { |
| | | if (IsConnected) return; |
| | | var config = new TouchSocketConfig().SetRemoteIPHost($"tcp://{Ip}:{Port}"); |
| | | client = new TcpClient(); |
| | | client.Received = TcpReceived; |
| | | client.Connected = (sender, e) => |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | Add("连接", "连接成功", Brushes.Green); |
| | | IsConnected = true; |
| | | }); |
| | | return EasyTask.CompletedTask; |
| | | }; |
| | | client.Closed = (sender, e) => |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | Add("连接", "连接断开", Brushes.Red); |
| | | IsConnected = false; |
| | | }); |
| | | return EasyTask.CompletedTask; |
| | | }; |
| | | client.SetupAsync(config); |
| | | client.ConnectAsync(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | IsConnected = false; |
| | | // throw ex; |
| | | } |
| | | } |
| | | |
| | | private Task TcpReceived(object sender, ReceivedDataEventArgs e) |
| | | { |
| | | try |
| | | { |
| | | var datas = e.Memory.Span.ToArray(); |
| | | string msg = null; |
| | | if (ReceiveDataType == DataType.HEX) |
| | | { |
| | | msg = HexUtil.ByteArrayToHex(datas); |
| | | } |
| | | else |
| | | { |
| | | if (ReceiveEncode == SupportEncode.GBK) |
| | | { |
| | | msg = Encoding.Default.GetString(datas); |
| | | } |
| | | else if (ReceiveEncode == SupportEncode.ASCII) |
| | | { |
| | | msg = Encoding.ASCII.GetString(datas); |
| | | } |
| | | else |
| | | { |
| | | |
| | | msg = Encoding.UTF8.GetString(datas); |
| | | } |
| | | } |
| | | Add("接收", msg, Brushes.Green); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | //log.Error($"TcpReceived Error.", ex); |
| | | } |
| | | return EasyTask.CompletedTask; |
| | | } |
| | | |
| | | private byte[] GetBytes(out string msg) |
| | | { |
| | | msg = null; |
| | | if (string.IsNullOrEmpty(SendText)) |
| | | { |
| | | return null; |
| | | } |
| | | if (SendDataType == DataType.String) |
| | | { |
| | | msg = SendText + GetEndMark(); |
| | | if (SendEncode == SupportEncode.GBK) |
| | | { |
| | | return Encoding.Default.GetBytes(msg); |
| | | } |
| | | if (SendEncode == SupportEncode.ASCII) |
| | | { |
| | | return Encoding.ASCII.GetBytes(msg); |
| | | } |
| | | if (SendEncode == SupportEncode.UTF8) |
| | | { |
| | | return Encoding.UTF8.GetBytes(msg); |
| | | } |
| | | return null; |
| | | } |
| | | msg = SendText; |
| | | if (msg.Length % 2 != 0) |
| | | { |
| | | msg = msg.Insert(msg.Length - 1, "0"); |
| | | } |
| | | msg = ByteStringConverter.GroupByTwo(msg); |
| | | return HexUtil.HexToByteArray(msg); |
| | | } |
| | | |
| | | private string GetEndMark() |
| | | { |
| | | if (EndMark == -1) |
| | | { |
| | | return string.Empty; |
| | | } |
| | | if (EndMark == 0) |
| | | { |
| | | return "\r"; |
| | | } |
| | | if (EndMark == 1) |
| | | { |
| | | return "\r\n"; |
| | | } |
| | | if (EndMark == 2) |
| | | { |
| | | return CustomEndMark; |
| | | } |
| | | return string.Empty; |
| | | } |
| | | |
| | | public void TrySend() |
| | | { |
| | | if (!IsConnected) |
| | | { |
| | | MessageBox.Show("请先连接", "提示"); |
| | | return; |
| | | } |
| | | var datas = GetBytes(out string msg); |
| | | if (datas != null) |
| | | { |
| | | client.SendAsync(datas).Wait(); |
| | | Add("发送", msg, Brushes.Blue); |
| | | // SendText = string.Empty; |
| | | } |
| | | } |
| | | |
| | | public void Add(string type, string text, Brush color) |
| | | { |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | Run run = new Run(); |
| | | run.Text = $"{time} {type}\r\n"; |
| | | run.Foreground = Brushes.Gray; |
| | | |
| | | Paragraph paragraph = new Paragraph(run) |
| | | { |
| | | LineHeight = 1 |
| | | }; |
| | | |
| | | run = new Run(); |
| | | run.Text = $"{text}\r\n"; |
| | | run.Foreground = color; |
| | | paragraph.Inlines.Add(run); |
| | | //也可以插入到最后面 |
| | | console.Document.Blocks.InsertAfter(console.Document.Blocks.LastBlock, paragraph); |
| | | |
| | | //插入到最前面 |
| | | //rtxtLog.Document.Blocks.Add(paragraph); |
| | | |
| | | // 滚动至最后行 |
| | | //rtxtLog.ScrollToEnd(); |
| | | //Console.ScrollToHome(); |
| | | console.ScrollToEnd(); |
| | | // 删除 |
| | | //if (Console.Document.Blocks.Count > 10000) |
| | | //{ |
| | | // for (int i = 1000; i < Console.Document.Blocks.Count; i++) |
| | | // { |
| | | // _ = Console.Document.Blocks.Remove(Console.Document.Blocks.FirstBlock); |
| | | // } |
| | | //} |
| | | |
| | | }, System.Windows.Threading.DispatcherPriority.Normal); |
| | | } |
| | | |
| | | private static readonly Regex HexRegex = new Regex("^[0-9A-Fa-f]+$"); |
| | | |
| | | private void TextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e) |
| | | { |
| | | if (SendDataType != DataType.HEX) |
| | | { |
| | | return; |
| | | } |
| | | var tb = (TextBox)sender; |
| | | string segment = e.Text; |
| | | |
| | | if (!HexRegex.IsMatch(segment)) |
| | | { |
| | | tb.Text = tb.Text.Replace(segment, ""); |
| | | tb.CaretIndex = tb.Text.Length; |
| | | e.Handled = true; |
| | | return; |
| | | } |
| | | // tb.Text = tb.Text.ToUpper(); |
| | | |
| | | base.OnPreviewTextInput(e); |
| | | } |
| | | |
| | | private void OnPasting(object sender, DataObjectPastingEventArgs e) |
| | | { |
| | | if (SendDataType != DataType.HEX) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | if (e.DataObject.GetDataPresent(typeof(string))) |
| | | { |
| | | string text = (string)e.DataObject.GetData(typeof(string)); |
| | | text = text.Replace(" ", ""); |
| | | if (!HexRegex.IsMatch(text)) |
| | | { |
| | | e.CancelCommand(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | public string Id { get; set; } |
| | | public string Name { get; set; } |
| | | public string Type { get; set; } |
| | | public bool IsArray { get; set; } |
| | | public string Value { get; set; } |
| | | public string Unit { get; set; } |
| | | public string Description { get; set; } |
| | |
| | | private static void WriteParameterData(SequenceContext context, ParameterData data) |
| | | { |
| | | string prefix = "SystemSetting"; |
| | | if (data.Type == "Bool") |
| | | |
| | | if (data.IsArray) |
| | | { |
| | | context.StationGlobals.SetValBoolean($"{prefix}.{data.Name}", 1, bool.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Int") |
| | | { |
| | | context.StationGlobals.SetValNumber($"{prefix}.{data.Name}", 1, int.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Double") |
| | | { |
| | | context.StationGlobals.SetValNumber($"{prefix}.{data.Name}", 1, double.Parse(data.Value)); |
| | | PropertyValueTypes type; |
| | | if (data.Type == "Bool") |
| | | { |
| | | type = PropertyValueTypes.PropValType_Boolean; |
| | | } |
| | | else if (data.Type == "Int") |
| | | { |
| | | type = PropertyValueTypes.PropValType_Number; |
| | | } |
| | | else if (data.Type == "Double") |
| | | { |
| | | type = PropertyValueTypes.PropValType_Number; |
| | | } |
| | | else |
| | | { |
| | | type = PropertyValueTypes.PropValType_String; |
| | | } |
| | | string[] arr = data.Value?.Split(',') ?? new string[0]; |
| | | if (arr.Length > 0) |
| | | { |
| | | context.StationGlobals.DeleteSubProperty($"{prefix}.{data.Name}", 2); |
| | | |
| | | context.StationGlobals.NewSubProperty($"{prefix}.{data.Name}", type, true, null, 1); |
| | | context.StationGlobals.GetPropertyObject($"{prefix}.{data.Name}", 0).SetNumElements(arr.Length); |
| | | for (int i = 0; i < arr.Length; i++) |
| | | { |
| | | if (type == PropertyValueTypes.PropValType_String) |
| | | { |
| | | context.StationGlobals.SetValString($"{prefix}.{data.Name}[{i}]", 0, arr[i]); |
| | | } |
| | | if (data.Type == "Int") |
| | | { |
| | | context.StationGlobals.SetValNumber($"{prefix}.{data.Name}[{i}]", 0, int.Parse(arr[i])); |
| | | } |
| | | if (data.Type == "Double") |
| | | { |
| | | context.StationGlobals.SetValNumber($"{prefix}.{data.Name}[{i}]", 0, double.Parse(arr[i])); |
| | | } |
| | | if (data.Type == "Bool") |
| | | { |
| | | context.StationGlobals.SetValBoolean($"{prefix}.{data.Name}[{i}]", 0, bool.Parse(arr[i])); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | context.StationGlobals.SetValString($"{prefix}.{data.Name}", 1, data.Value); |
| | | if (data.Type == "Bool") |
| | | { |
| | | context.StationGlobals.SetValBoolean($"{prefix}.{data.Name}", 1, bool.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Int") |
| | | { |
| | | context.StationGlobals.SetValNumber($"{prefix}.{data.Name}", 1, int.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Double") |
| | | { |
| | | context.StationGlobals.SetValNumber($"{prefix}.{data.Name}", 1, double.Parse(data.Value)); |
| | | } |
| | | else |
| | | { |
| | | context.StationGlobals.SetValString($"{prefix}.{data.Name}", 1, data.Value); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | private static void WriteParameterData(object instance, ParameterData data) |
| | | { |
| | | SequenceContext context = (SequenceContext)instance; |
| | | if (data.Type == "Bool") |
| | | string name = $"DUTSetting.{data.Name}"; |
| | | |
| | | if (data.IsArray) |
| | | { |
| | | context.FileGlobals.SetValBoolean($"DUTSetting.{data.Name}", 1, bool.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Int") |
| | | { |
| | | context.FileGlobals.SetValNumber($"DUTSetting.{data.Name}", 1, int.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Double") |
| | | { |
| | | context.FileGlobals.SetValNumber($"DUTSetting.{data.Name}", 1, double.Parse(data.Value)); |
| | | PropertyValueTypes type; |
| | | if (data.Type == "Bool") |
| | | { |
| | | type = PropertyValueTypes.PropValType_Boolean; |
| | | } |
| | | else if (data.Type == "Int") |
| | | { |
| | | type = PropertyValueTypes.PropValType_Number; |
| | | } |
| | | else if (data.Type == "Double") |
| | | { |
| | | type = PropertyValueTypes.PropValType_Number; |
| | | } |
| | | else |
| | | { |
| | | type = PropertyValueTypes.PropValType_String; |
| | | } |
| | | string[] arr = data.Value?.Split(',') ?? new string[0]; |
| | | if (arr.Length > 0) |
| | | { |
| | | context.FileGlobals.DeleteSubProperty(name, 2); |
| | | |
| | | context.FileGlobals.NewSubProperty(name, type, true, null, 1); |
| | | context.FileGlobals.GetPropertyObject(name, 0).SetNumElements(arr.Length); |
| | | for (int i = 0; i < arr.Length; i++) |
| | | { |
| | | if (type == PropertyValueTypes.PropValType_String) |
| | | { |
| | | context.FileGlobals.SetValString($"{name}[{i}]", 0, arr[i]); |
| | | } |
| | | if (data.Type == "Int") |
| | | { |
| | | context.FileGlobals.SetValNumber($"{name}[{i}]", 0, int.Parse(arr[i])); |
| | | } |
| | | if (data.Type == "Double") |
| | | { |
| | | context.FileGlobals.SetValNumber($"{name}[{i}]", 0, double.Parse(arr[i])); |
| | | } |
| | | if (data.Type == "Bool") |
| | | { |
| | | context.FileGlobals.SetValBoolean($"{name}[{i}]", 0, bool.Parse(arr[i])); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | context.FileGlobals.SetValString($"DUTSetting.{data.Name}", 1, data.Value); |
| | | if (data.Type == "Bool") |
| | | { |
| | | context.FileGlobals.SetValBoolean(name, 1, bool.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Int") |
| | | { |
| | | context.FileGlobals.SetValNumber(name, 1, int.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Double") |
| | | { |
| | | context.FileGlobals.SetValNumber(name, 1, double.Parse(data.Value)); |
| | | } |
| | | else |
| | | { |
| | | context.FileGlobals.SetValString(name, 1, data.Value); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | private static string GetDataFilePath() |
| | | { |
| | | string path = ParameterUtil.GetCommonParameterValue("ShareConfig", out _); |
| | | if (path == null) |
| | | { |
| | | path = Path.Combine(RegUtil.GetLocaltion(), "Config"); |
| | | } |
| | | return path; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | errMsg = string.Empty; |
| | | try |
| | | { |
| | | string dir = RegUtil.GetLocaltion(); |
| | | string path = Path.Combine(dir, "Config", "Product", "Parameter", $"Parameter_{model}.data"); |
| | | string path = Path.Combine(GetDataFilePath(), "Product", "Parameter", $"Parameter_{model}.data"); |
| | | return WriteConfigToContextByPath(path, instance, out errMsg); |
| | | } |
| | | catch (Exception ex) |
| | |
| | | using System.Reflection; |
| | | using System.Runtime.CompilerServices; |
| | | using System.Runtime.InteropServices; |
| | | |
| | | // 有关程序集的一般信息由以下 |
| | |
| | | // 生成号 |
| | | // 修订号 |
| | | // |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.2")] |
| | | [assembly: AssemblyVersion("1.0.0.3")] |
| | | [assembly: AssemblyFileVersion("1.0.0.3")] |
| New file |
| | |
| | | using System.Windows; |
| | | |
| | | [assembly:ThemeInfo( |
| | | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located |
| | | //(used if a resource is not found in the page, |
| | | // or application resource dictionaries) |
| | | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located |
| | | //(used if a resource is not found in the page, |
| | | // app, or any theme specific resource dictionaries) |
| | | )] |
| New file |
| | |
| | | <UserControl x:Class="Util.SB.ManualDebug" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:local="clr-namespace:Util.SB" |
| | | mc:Ignorable="d" |
| | | x:Name="self" |
| | | MinHeight="400" MinWidth="500"> |
| | | |
| | | <UserControl.Resources> |
| | | <ResourceDictionary> |
| | | <ResourceDictionary.MergedDictionaries> |
| | | <ResourceDictionary Source="/Util.ManualDebug;component/ManualDebugStyle.xaml"/> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | </ResourceDictionary> |
| | | </UserControl.Resources> |
| | | |
| | | <Grid> |
| | | <Grid Margin="10"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="5"/> |
| | | <RowDefinition Height="*"/> |
| | | <RowDefinition Height="5"/> |
| | | <RowDefinition Height="*"/> |
| | | </Grid.RowDefinitions> |
| | | <WindowsFormsHost x:Name="host" Visibility="Collapsed"></WindowsFormsHost> |
| | | |
| | | <!-- 按钮和状态区域 --> |
| | | <Border Grid.Row="0" Background="{StaticResource TsPanelBrush}" |
| | | BorderBrush="{StaticResource BorderBrush}" |
| | | BorderThickness="1" CornerRadius="4" Padding="15"> |
| | | <StackPanel> |
| | | <TextBlock Text="手动调试控制" FontSize="14" FontWeight="SemiBold" |
| | | Foreground="{StaticResource PrimaryBrush}" Margin="0,0,0,15"/> |
| | | |
| | | <WrapPanel x:Name="btnPanel"> |
| | | |
| | | </WrapPanel> |
| | | </StackPanel> |
| | | </Border> |
| | | |
| | | <!-- 分隔条1 --> |
| | | <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" |
| | | Background="Transparent" Cursor="SizeNS"/> |
| | | |
| | | <!-- TX/RX 数据区域 --> |
| | | <Border Grid.Row="2" Background="{StaticResource TsPanelBrush}" |
| | | BorderBrush="{StaticResource BorderBrush}" |
| | | BorderThickness="1" CornerRadius="4" Padding="10"> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="*"/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <StackPanel Orientation="Horizontal" Grid.Row="0" Margin="0,0,0,10"> |
| | | <TextBlock Text="测试数据" FontSize="14" FontWeight="SemiBold" |
| | | Foreground="{StaticResource PrimaryBrush}" VerticalAlignment="Center"/> |
| | | <Button Content="清空" Style="{StaticResource ActionButtonStyle}" |
| | | Margin="15,0,0,0" Click="OnClearClick"/> |
| | | </StackPanel> |
| | | |
| | | <DataGrid x:Name="DataGridComm" Grid.Row="1" |
| | | ItemsSource="{Binding TestData,ElementName=self}"> |
| | | <DataGrid.Columns> |
| | | <DataGridTextColumn Header="测试项" Binding="{Binding Name}" Width="120" IsReadOnly="True"/> |
| | | <DataGridTextColumn Header="收" Binding="{Binding Receive}" Width="*" IsReadOnly="True"/> |
| | | <DataGridTextColumn Header="发" Binding="{Binding Send}" Width="*" IsReadOnly="True"/> |
| | | <DataGridTextColumn Header="单位" Binding="{Binding Unit}" Width="60" IsReadOnly="True"/> |
| | | <DataGridTextColumn Header="上限" Binding="{Binding UpperLimit}" Width="80" IsReadOnly="True"/> |
| | | <DataGridTextColumn Header="下限" Binding="{Binding LowerLimit}" Width="80" IsReadOnly="True"/> |
| | | <DataGridTextColumn Header="结果" Binding="{Binding Result}" Width="70" IsReadOnly="True"/> |
| | | <DataGridTextColumn Header="时间" Binding="{Binding Time}" Width="90" IsReadOnly="True"/> |
| | | </DataGrid.Columns> |
| | | <DataGrid.RowStyle> |
| | | <Style TargetType="DataGridRow"> |
| | | <Style.Triggers> |
| | | <DataTrigger Value="True"> |
| | | <DataTrigger.Binding> |
| | | <MultiBinding Converter="{x:Static local:ResultFailedConverter.Instance}"> |
| | | <Binding Path="Result"/> |
| | | </MultiBinding> |
| | | </DataTrigger.Binding> |
| | | <Setter Property="Background" Value="#FFE0E0"/> |
| | | <Setter Property="Foreground" Value="#C53030"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </DataGrid.RowStyle> |
| | | </DataGrid> |
| | | </Grid> |
| | | </Border> |
| | | |
| | | <!-- 分隔条2 --> |
| | | <GridSplitter Grid.Row="3" Height="5" HorizontalAlignment="Stretch" |
| | | Background="Transparent" Cursor="SizeNS"/> |
| | | |
| | | <!-- 日志区域 --> |
| | | <Border Grid.Row="4" Background="{StaticResource TsPanelBrush}" |
| | | BorderBrush="{StaticResource BorderBrush}" |
| | | BorderThickness="1" CornerRadius="4" Padding="10"> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="*"/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <StackPanel Orientation="Horizontal" Grid.Row="0" Margin="0,0,0,8"> |
| | | <TextBlock Text="日志" FontSize="14" FontWeight="SemiBold" |
| | | Foreground="{StaticResource PrimaryBrush}" VerticalAlignment="Center"/> |
| | | <Button Content="清空日志" Style="{StaticResource ActionButtonStyle}" |
| | | Margin="15,0,0,0" Click="OnClearLogClick"/> |
| | | </StackPanel> |
| | | |
| | | <RichTextBox x:Name="LogRichTextBox" Grid.Row="1" |
| | | IsReadOnly="True" |
| | | VerticalScrollBarVisibility="Auto" |
| | | FontFamily="Consolas" |
| | | FontSize="11" |
| | | BorderThickness="1" |
| | | BorderBrush="Black" |
| | | Padding="4"/> |
| | | </Grid> |
| | | </Border> |
| | | </Grid> |
| | | <Border Background="#AAFFFFFF" x:Name="mask"> |
| | | <TextBlock Text="初始化中..." |
| | | FontSize="16" FontWeight="Bold" Foreground="{StaticResource PrimaryBrush}" HorizontalAlignment="Center" VerticalAlignment="Center"/> |
| | | </Border> |
| | | </Grid> |
| | | </UserControl> |
| New file |
| | |
| | | using Plugin.TsSupport; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | using System.Globalization; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Data; |
| | | using System.Windows.Documents; |
| | | using System.Windows.Media; |
| | | |
| | | namespace Util.SB |
| | | { |
| | | public class BtnConfig |
| | | { |
| | | public string Title { get; set; } |
| | | public string Name { get; set; } |
| | | } |
| | | |
| | | // 结果失败判断转换器(支持不区分大小写) |
| | | public class ResultFailedConverter : IMultiValueConverter |
| | | { |
| | | public static readonly ResultFailedConverter Instance = new ResultFailedConverter(); |
| | | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) |
| | | { |
| | | if (values.Length > 0 && values[0] is string) |
| | | { |
| | | string result = (string)values[0]; |
| | | string upper = result.ToUpperInvariant(); |
| | | return upper == "NG" || upper == "FAIL"; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) |
| | | { |
| | | throw new NotImplementedException(); |
| | | } |
| | | } |
| | | |
| | | // 日志级别枚举 |
| | | public enum LogLevel |
| | | { |
| | | Debug = 0, |
| | | Info = 1, |
| | | Warn = 2, |
| | | Error = 3 |
| | | } |
| | | |
| | | public partial class ManualDebug : UserControl |
| | | { |
| | | public static readonly DependencyProperty OvenNameProperty = DependencyProperty.Register( |
| | | "OvenName", |
| | | typeof(string), |
| | | typeof(ManualDebug), |
| | | new PropertyMetadata("")); |
| | | |
| | | public static readonly DependencyProperty CellNameProperty = DependencyProperty.Register( |
| | | "CellName", |
| | | typeof(string), |
| | | typeof(ManualDebug), |
| | | new PropertyMetadata("")); |
| | | |
| | | public static readonly DependencyProperty OvenIndexProperty = DependencyProperty.Register( |
| | | "OvenIndex", |
| | | typeof(int), |
| | | typeof(ManualDebug), |
| | | new PropertyMetadata(0)); |
| | | |
| | | public static readonly DependencyProperty CellIndexProperty = DependencyProperty.Register( |
| | | "CellIndex", |
| | | typeof(int), |
| | | typeof(ManualDebug), |
| | | new PropertyMetadata(0)); |
| | | |
| | | public string OvenName |
| | | { |
| | | get { return (string)GetValue(OvenNameProperty); } |
| | | set |
| | | { |
| | | SetValue(OvenNameProperty, value); |
| | | } |
| | | } |
| | | |
| | | public string CellName |
| | | { |
| | | get { return (string)GetValue(CellNameProperty); } |
| | | set { SetValue(CellNameProperty, value); } |
| | | } |
| | | |
| | | public int OvenIndex |
| | | { |
| | | get { return (int)GetValue(OvenIndexProperty); } |
| | | set { SetValue(OvenIndexProperty, value); } |
| | | } |
| | | |
| | | public int CellIndex |
| | | { |
| | | get { return (int)GetValue(CellIndexProperty); } |
| | | set { SetValue(CellIndexProperty, value); } |
| | | } |
| | | |
| | | public ObservableCollection<TestDataItem> TestData { get; private set; } = new ObservableCollection<TestDataItem>(); |
| | | |
| | | private Dictionary<string, StatusBtn> btnCache = new Dictionary<string, StatusBtn>(); |
| | | |
| | | // 日志级别颜色 |
| | | private readonly SolidColorBrush _debugBrush; |
| | | private readonly SolidColorBrush _infoBrush; |
| | | private readonly SolidColorBrush _warnBrush; |
| | | private readonly SolidColorBrush _errorBrush; |
| | | |
| | | private ITestExecutionWrapper executionWrapper; |
| | | |
| | | public string seqPath { get; set; } |
| | | public string modelPath { get; set; } = "C:\\Program Files\\National Instruments\\TestStand 2020\\Components\\Models\\TestStandModels\\ParallelModel.seq"; |
| | | |
| | | public ManualDebug() |
| | | { |
| | | _debugBrush = new SolidColorBrush(Color.FromRgb(0x71, 0x80, 0x8A)); // 灰色 |
| | | _infoBrush = new SolidColorBrush(Colors.Black); |
| | | _warnBrush = new SolidColorBrush(Color.FromRgb(0xD6, 0x9E, 0x2E)); // 橙黄色 |
| | | _errorBrush = new SolidColorBrush(Color.FromRgb(0xC5, 0x30, 0x30)); // 红色 |
| | | this.Loaded += ManualDebug_Loaded; |
| | | InitializeComponent(); |
| | | RefreshButtons(null); |
| | | } |
| | | |
| | | private void ManualDebug_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | Task.Run(() => |
| | | { |
| | | System.Threading.Thread.Sleep(500); |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | InitWrapper(); |
| | | StartSeq(); |
| | | mask.Visibility = Visibility.Collapsed; |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | public void RefreshButtons(List<BtnConfig> settings) |
| | | { |
| | | if (settings == null) return; |
| | | |
| | | for (int i = 0; i < settings.Count; i++) { |
| | | var setting = settings[i]; |
| | | |
| | | var margin = new Thickness(0, 0, 20, 0); |
| | | if (i == settings.Count - 1) |
| | | { |
| | | margin = new Thickness(0); |
| | | } |
| | | |
| | | var btn = new StatusBtn |
| | | { |
| | | Title = setting.Title, |
| | | Tag = setting, |
| | | Margin = margin |
| | | }; |
| | | btn.BtnClick += Btn_BtnClick; |
| | | btnCache[setting.Name] = btn; |
| | | btnPanel.Children.Add(btn); |
| | | } |
| | | } |
| | | |
| | | public void StartSeq() |
| | | { |
| | | try |
| | | { |
| | | executionWrapper?.StartSequence(seqPath, modelPath); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AppendLog(LogLevel.Error, $"启动测试序列失败 {ex.Message} {ex.StackTrace}"); |
| | | } |
| | | } |
| | | |
| | | private void InitWrapper() |
| | | { |
| | | try |
| | | { |
| | | var wrapper = new TeststandWrapper(); |
| | | var AxApplicationMgr = wrapper.AxApplicationMgr; |
| | | ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).BeginInit(); |
| | | host.Child = AxApplicationMgr; |
| | | ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).EndInit(); |
| | | wrapper.Init(); |
| | | executionWrapper = wrapper; |
| | | |
| | | wrapper.UIMessageEvent += Wrapper_UIMessageEvent; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AppendLog(LogLevel.Error, $"初始化Teststand {ex.Message} {ex.StackTrace}"); |
| | | } |
| | | } |
| | | |
| | | private void Wrapper_UIMessageEvent(object sender, UIMessageEvent e) |
| | | { |
| | | try |
| | | { |
| | | if (e.EventCode == 10000) |
| | | { |
| | | executionWrapper?.SetContext(e.Data); |
| | | return; |
| | | } |
| | | if (e.EventCode == 10001) |
| | | { |
| | | string[] arr = e.StrData.Split(','); |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | AddTestData(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]); |
| | | }); |
| | | return; |
| | | } |
| | | if (e.EventCode == 10002) |
| | | { |
| | | string[] arr = e.StrData.Split(','); |
| | | LogLevel level = (LogLevel)int.Parse(arr[0]); |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | AppendLog(level, arr[1]); |
| | | }); |
| | | return; |
| | | } |
| | | if (e.EventCode == 10003) |
| | | { |
| | | string[] arr = e.StrData.Split(','); |
| | | DebugStatus status = (DebugStatus)int.Parse(arr[1]); |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | SetStatus(arr[0], status); |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AppendLog(LogLevel.Error, $"处理UI信息失败 {ex.Message} {ex.StackTrace}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private void Btn_BtnClick(object sender, RoutedEventArgs e) |
| | | { |
| | | var btn = (StatusBtn)sender; |
| | | BtnConfig config = (BtnConfig)btn.Tag; |
| | | StartSingleTest(config.Name); |
| | | } |
| | | |
| | | private void StartSingleTest(string name) |
| | | { |
| | | try |
| | | { |
| | | string key = $"Running.OvenName"; |
| | | executionWrapper?.SetFileGlobalValue(key, 1, OvenName); |
| | | |
| | | key = $"Running.CellName"; |
| | | executionWrapper?.SetFileGlobalValue(key, 1, CellName); |
| | | |
| | | key = $"Running.OvenIndex"; |
| | | executionWrapper?.SetFileGlobalValue(key, 1, OvenIndex); |
| | | |
| | | key = $"Running.CellIndex"; |
| | | executionWrapper?.SetFileGlobalValue(key, 1, CellIndex); |
| | | |
| | | key = $"Running.ActionName"; |
| | | executionWrapper?.SetFileGlobalValue(key, 1, name); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AppendLog(LogLevel.Error, $"启动功能失败 {ex.Message} {ex.StackTrace}"); |
| | | } |
| | | } |
| | | |
| | | // 设置状态显示 |
| | | private void SetStatus(string labelName, DebugStatus status) |
| | | { |
| | | if (btnCache.ContainsKey(labelName)) |
| | | { |
| | | var btn = btnCache[labelName]; |
| | | btn.Status = status; |
| | | } |
| | | } |
| | | |
| | | // 重置状态显示 |
| | | private void ResetStatus(string labelName) |
| | | { |
| | | SetStatus(labelName, DebugStatus.Idle); |
| | | } |
| | | |
| | | // 设置测试中状态并禁用按钮 |
| | | private void SetTestingStatus(string labelName, Button button) |
| | | { |
| | | SetStatus(labelName, DebugStatus.Testing); |
| | | button.IsEnabled = false; |
| | | } |
| | | |
| | | private void OnClearClick(object sender, RoutedEventArgs e) |
| | | { |
| | | TestData.Clear(); |
| | | } |
| | | |
| | | private void OnClearLogClick(object sender, RoutedEventArgs e) |
| | | { |
| | | LogRichTextBox.Document.Blocks.Clear(); |
| | | } |
| | | |
| | | private void AddTestData(string name, string send, string receive, string unit, string upper, string lower, string result, string time) |
| | | { |
| | | TestData.Add(new TestDataItem |
| | | { |
| | | Name = name, |
| | | Send = send, |
| | | Receive = receive, |
| | | Unit = unit, |
| | | UpperLimit = upper, |
| | | LowerLimit = lower, |
| | | Result = result, |
| | | Time = time |
| | | }); |
| | | |
| | | if (DataGridComm.Items.Count > 0) |
| | | { |
| | | DataGridComm.ScrollIntoView(DataGridComm.Items[DataGridComm.Items.Count - 1]); |
| | | } |
| | | } |
| | | |
| | | // 获取日志级别对应的颜色 |
| | | private Brush GetLogLevelBrush(LogLevel level) |
| | | { |
| | | switch (level) |
| | | { |
| | | case LogLevel.Debug: |
| | | return _debugBrush; |
| | | case LogLevel.Info: |
| | | return _infoBrush; |
| | | case LogLevel.Warn: |
| | | return _warnBrush; |
| | | case LogLevel.Error: |
| | | return _errorBrush; |
| | | default: |
| | | return _infoBrush; |
| | | } |
| | | } |
| | | |
| | | // 添加带级别的日志 |
| | | private void AppendLog(LogLevel level, string message) |
| | | { |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | string timestamp = DateTime.Now.ToString("HH:mm:ss.fff"); |
| | | string levelStr = level.ToString().ToUpper(); |
| | | |
| | | Paragraph? paragraph = LogRichTextBox.Document.Blocks.LastBlock as Paragraph; |
| | | if (paragraph == null) |
| | | { |
| | | paragraph = new Paragraph(); |
| | | LogRichTextBox.Document.Blocks.Add(paragraph); |
| | | } |
| | | |
| | | // 时间戳(灰色) |
| | | Run timestampRun = new Run("[" + timestamp + "] ") { Foreground = _debugBrush }; |
| | | paragraph.Inlines.Add(timestampRun); |
| | | |
| | | // 级别标签 |
| | | Brush levelBrush = GetLogLevelBrush(level); |
| | | Run levelRun = new Run("[" + levelStr + "] ") { Foreground = levelBrush, FontWeight = FontWeights.SemiBold }; |
| | | paragraph.Inlines.Add(levelRun); |
| | | |
| | | // 消息内容 |
| | | Run messageRun = new Run(message + "\n") { Foreground = levelBrush }; |
| | | paragraph.Inlines.Add(messageRun); |
| | | |
| | | LogRichTextBox.ScrollToEnd(); |
| | | }); |
| | | } |
| | | |
| | | // 兼容旧调用方式,默认 Info 级别 |
| | | private void AppendLog(string message) |
| | | { |
| | | AppendLog(LogLevel.Info, message); |
| | | } |
| | | |
| | | public void Stop() |
| | | { |
| | | try |
| | | { |
| | | executionWrapper?.SetFileGlobalValue("Running.StopTest", 1, true); |
| | | executionWrapper?.WaitForExit(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | public class TestDataItem : INotifyPropertyChanged |
| | | { |
| | | private string _name = ""; |
| | | private string _receive = ""; |
| | | private string _send = ""; |
| | | private string _unit = ""; |
| | | private string _upperLimit = ""; |
| | | private string _lowerLimit = ""; |
| | | private string _result = ""; |
| | | private string _time = ""; |
| | | |
| | | public string Name |
| | | { |
| | | get { return _name; } |
| | | set { _name = value; OnPropertyChanged("Name"); } |
| | | } |
| | | |
| | | public string Receive |
| | | { |
| | | get { return _receive; } |
| | | set { _receive = value; OnPropertyChanged("Receive"); } |
| | | } |
| | | |
| | | public string Send |
| | | { |
| | | get { return _send; } |
| | | set { _send = value; OnPropertyChanged("Send"); } |
| | | } |
| | | |
| | | public string Unit |
| | | { |
| | | get { return _unit; } |
| | | set { _unit = value; OnPropertyChanged("Unit"); } |
| | | } |
| | | |
| | | public string UpperLimit |
| | | { |
| | | get { return _upperLimit; } |
| | | set { _upperLimit = value; OnPropertyChanged("UpperLimit"); } |
| | | } |
| | | |
| | | public string LowerLimit |
| | | { |
| | | get { return _lowerLimit; } |
| | | set { _lowerLimit = value; OnPropertyChanged("LowerLimit"); } |
| | | } |
| | | |
| | | public string Result |
| | | { |
| | | get { return _result; } |
| | | set { _result = value; OnPropertyChanged("Result"); } |
| | | } |
| | | |
| | | public string Time |
| | | { |
| | | get { return _time; } |
| | | set { _time = value; OnPropertyChanged("Time"); } |
| | | } |
| | | |
| | | public event PropertyChangedEventHandler PropertyChanged; |
| | | |
| | | protected virtual void OnPropertyChanged(string propertyName) |
| | | { |
| | | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
| | | |
| | | <!-- 颜色定义 --> |
| | | <SolidColorBrush x:Key="TsBgBrush" Color="#F0F2F5"/> |
| | | <SolidColorBrush x:Key="TsPanelBrush" Color="#FFFFFF"/> |
| | | <SolidColorBrush x:Key="BorderBrush" Color="#A0AEC0"/> |
| | | <SolidColorBrush x:Key="PrimaryBrush" Color="#2E5C8A"/> |
| | | |
| | | <!-- 状态颜色画刷 --> |
| | | <SolidColorBrush x:Key="StatusOKBrush" Color="#2D8659"/> |
| | | <SolidColorBrush x:Key="StatusNGBrush" Color="#C53030"/> |
| | | <SolidColorBrush x:Key="StatusTestingBrush" Color="#3182CE"/> |
| | | <SolidColorBrush x:Key="StatusDefaultBrush" Color="#E0E0E0"/> |
| | | <SolidColorBrush x:Key="BorderDarkBrush" Color="#718096"/> |
| | | |
| | | <!-- ActionButtonStyle 按钮样式 --> |
| | | <Style x:Key="ActionButtonStyle" TargetType="Button"> |
| | | <Setter Property="Height" Value="22"/> |
| | | <Setter Property="Padding" Value="8,0"/> |
| | | <Setter Property="Background" Value="White"/> |
| | | <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> |
| | | <Setter Property="BorderThickness" Value="1"/> |
| | | <Setter Property="FontSize" Value="11"/> |
| | | <Setter Property="Cursor" Value="Hand"/> |
| | | <Setter Property="Template"> |
| | | <Setter.Value> |
| | | <ControlTemplate TargetType="Button"> |
| | | <Border Background="{TemplateBinding Background}" |
| | | BorderBrush="{TemplateBinding BorderBrush}" |
| | | BorderThickness="{TemplateBinding BorderThickness}" |
| | | CornerRadius="2" |
| | | Padding="{TemplateBinding Padding}"> |
| | | <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> |
| | | </Border> |
| | | <ControlTemplate.Triggers> |
| | | <Trigger Property="IsMouseOver" Value="True"> |
| | | <Setter Property="Background" Value="#F0F0F0"/> |
| | | </Trigger> |
| | | </ControlTemplate.Triggers> |
| | | </ControlTemplate> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Style> |
| | | |
| | | <!-- ManualDebug 窗口专用按钮样式 --> |
| | | <Style x:Key="DebugButtonStyle" TargetType="Button"> |
| | | <Setter Property="Width" Value="100"/> |
| | | <Setter Property="Height" Value="32"/> |
| | | <Setter Property="Background" Value="White"/> |
| | | <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> |
| | | <Setter Property="BorderThickness" Value="1"/> |
| | | <Setter Property="FontSize" Value="11"/> |
| | | <Setter Property="Cursor" Value="Hand"/> |
| | | <Setter Property="Template"> |
| | | <Setter.Value> |
| | | <ControlTemplate TargetType="Button"> |
| | | <Border Background="{TemplateBinding Background}" |
| | | BorderBrush="{TemplateBinding BorderBrush}" |
| | | BorderThickness="{TemplateBinding BorderThickness}" |
| | | CornerRadius="4" |
| | | Padding="{TemplateBinding Padding}"> |
| | | <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> |
| | | </Border> |
| | | <ControlTemplate.Triggers> |
| | | <Trigger Property="IsMouseOver" Value="True"> |
| | | <Setter Property="Background" Value="#E8E8E8"/> |
| | | </Trigger> |
| | | <Trigger Property="IsPressed" Value="True"> |
| | | <Setter Property="Background" Value="#D0D0D0"/> |
| | | </Trigger> |
| | | <Trigger Property="IsEnabled" Value="False"> |
| | | <Setter Property="Background" Value="LightGray"/> |
| | | </Trigger> |
| | | </ControlTemplate.Triggers> |
| | | </ControlTemplate> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Style> |
| | | |
| | | <!-- DataGrid样式 --> |
| | | <Style TargetType="DataGrid"> |
| | | <Setter Property="AutoGenerateColumns" Value="False"/> |
| | | <Setter Property="CanUserAddRows" Value="False"/> |
| | | <Setter Property="CanUserDeleteRows" Value="False"/> |
| | | <Setter Property="HeadersVisibility" Value="Column"/> |
| | | <Setter Property="GridLinesVisibility" Value="All"/> |
| | | <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource BorderBrush}"/> |
| | | <Setter Property="VerticalGridLinesBrush" Value="{StaticResource BorderBrush}"/> |
| | | <Setter Property="BorderBrush" Value="{StaticResource BorderDarkBrush}"/> |
| | | <Setter Property="BorderThickness" Value="1"/> |
| | | <Setter Property="Background" Value="White"/> |
| | | <Setter Property="RowBackground" Value="White"/> |
| | | <Setter Property="AlternatingRowBackground" Value="#F5F5F5"/> |
| | | <Setter Property="FontSize" Value="11"/> |
| | | </Style> |
| | | |
| | | <Style TargetType="DataGridColumnHeader"> |
| | | <Setter Property="Background" Value="#F5F5F5"/> |
| | | <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> |
| | | <Setter Property="BorderThickness" Value="0,0,1,1"/> |
| | | <Setter Property="Padding" Value="4"/> |
| | | <Setter Property="Height" Value="26"/> |
| | | <Setter Property="FontWeight" Value="Normal"/> |
| | | </Style> |
| | | |
| | | <Style TargetType="DataGridCell"> |
| | | <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> |
| | | <Setter Property="BorderThickness" Value="0"/> |
| | | <Setter Property="Padding" Value="2,4"/> |
| | | <Style.Triggers> |
| | | <Trigger Property="IsSelected" Value="True"> |
| | | <Setter Property="Background" Value="#BBDEFB"/> |
| | | <Setter Property="Foreground" Value="Black"/> |
| | | </Trigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | |
| | | <Style TargetType="DataGridRow"> |
| | | <Style.Triggers> |
| | | <Trigger Property="IsSelected" Value="True"> |
| | | <Setter Property="Background" Value="#BBDEFB"/> |
| | | </Trigger> |
| | | <Trigger Property="IsMouseOver" Value="True"> |
| | | <Setter Property="Background" Value="#E3F2FD"/> |
| | | </Trigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | |
| | | </ResourceDictionary> |
| New file |
| | |
| | | <UserControl x:Class="Util.SB.StatusBtn" |
| | | 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:local="clr-namespace:Util.SB" |
| | | mc:Ignorable="d" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <ResourceDictionary> |
| | | <ResourceDictionary.MergedDictionaries> |
| | | <ResourceDictionary Source="/Util.ManualDebug;component/ManualDebugStyle.xaml"/> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | |
| | | <Style x:Key="StatusTextStyle" TargetType="TextBlock"> |
| | | <Setter Property="HorizontalAlignment" Value="Center"/> |
| | | <Setter Property="VerticalAlignment" Value="Center"/> |
| | | <Setter Property="FontWeight" Value="SemiBold"/> |
| | | <Setter Property="FontSize" Value="12"/> |
| | | <Setter Property="Text" Value="-"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.NG}"> |
| | | <Setter Property="Text" Value="NG"/> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.OK}"> |
| | | <Setter Property="Text" Value="OK"/> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.Testing}"> |
| | | <Setter Property="Text" Value="TESTING"/> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | |
| | | <!-- 状态边框样式 --> |
| | | <Style x:Key="StatusBorderStyle" TargetType="Border"> |
| | | <Setter Property="Background" Value="{StaticResource StatusDefaultBrush}"/> |
| | | <Setter Property="CornerRadius" Value="2"/> |
| | | <Setter Property="HorizontalAlignment" Value="Center"/> |
| | | <Setter Property="Width" Value="100"/> |
| | | <Setter Property="Height" Value="24"/> |
| | | <Setter Property="Margin" Value="0,5,0,0"/> |
| | | |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.NG}"> |
| | | <Setter Property="Background" Value="{StaticResource StatusNGBrush}"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.OK}"> |
| | | <Setter Property="Background" Value="{StaticResource StatusOKBrush}"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.Testing}"> |
| | | <Setter Property="Background" Value="{StaticResource StatusTestingBrush}"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | |
| | | <Style x:Key="btnStyle" TargetType="Button" BasedOn="{StaticResource DebugButtonStyle}"> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.Testing}"> |
| | | <Setter Property="IsEnabled" Value="False"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </ResourceDictionary> |
| | | |
| | | </UserControl.Resources> |
| | | <StackPanel> |
| | | <Button x:Name="btn" Content="{Binding Title}" Style="{StaticResource btnStyle}" Click="Button_Click"/> |
| | | <Border Style="{StaticResource StatusBorderStyle}"> |
| | | <TextBlock Style="{StaticResource StatusTextStyle}"/> |
| | | </Border> |
| | | </StackPanel> |
| | | </UserControl> |
| New file |
| | |
| | | using CommunityToolkit.Mvvm.ComponentModel; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace Util.SB |
| | | { |
| | | // 状态枚举 |
| | | public enum DebugStatus |
| | | { |
| | | Idle = 0, // 空闲 |
| | | Testing = 1, // 测试中 |
| | | OK = 2, // 通过 |
| | | NG = 3 // 失败 |
| | | } |
| | | /// <summary> |
| | | /// StatusBtn.xaml 的交互逻辑 |
| | | /// </summary> |
| | | [ObservableObject] |
| | | public partial class StatusBtn : UserControl |
| | | { |
| | | public event RoutedEventHandler BtnClick; |
| | | |
| | | public StatusBtn() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | [ObservableProperty] |
| | | private string title = string.Empty; |
| | | |
| | | [ObservableProperty] |
| | | private DebugStatus status = DebugStatus.Idle; |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | BtnClick?.Invoke(this, e); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <TargetFramework>net472</TargetFramework> |
| | | <Nullable>enable</Nullable> |
| | | <LangVersion>10.0</LangVersion> |
| | | <ImplicitUsings>enable</ImplicitUsings> |
| | | <UseWPF>true</UseWPF> |
| | | <Platforms>AnyCPU;x64;x86</Platforms> |
| | | <FileVersion>1.0.0.0</FileVersion> |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> |
| | | <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\Plugin.TsSupport\Plugin.TsSupport.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Reference Include="NationalInstruments.TestStand.Interop.API"> |
| | | <HintPath>..\Libs\NationalInstruments.TestStand.Interop.API.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="NationalInstruments.TestStand.Interop.UI.AxControls"> |
| | | <HintPath>..\Libs\NationalInstruments.TestStand.Interop.UI.AxControls.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="System.Windows.Forms" /> |
| | | <Reference Include="WindowsFormsIntegration" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| | |
| | | </startup> |
| | | <runtime> |
| | | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
| | | <probing privatePath="Libs;ThirdParty;Plugin;3rds;Api;" /> |
| | | <probing privatePath="Libs;ThirdParty;Plugin;3rds;Api;OpenTap;" /> |
| | | <dependentAssembly> |
| | | <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> |
| | | <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> |
| | |
| | | { |
| | | var process = GetProcess(); |
| | | |
| | | mutex = new Mutex(true, "TestPlatform_OnlyRun_CRNS"); |
| | | mutex = new Mutex(true, "TestPlatform_OnlyRun_CRNS__"); |
| | | if (mutex.WaitOne(0, false))//&& process == null |
| | | { |
| | | WriteRegister(); |
| | |
| | | <DockPanel Background="Transparent"> |
| | | <Border DockPanel.Dock="Left" BorderThickness="1,1,0,1" Background="Transparent" BorderBrush="{StaticResource PrimaryColor}" Width="50"></Border> |
| | | <ListBox DockPanel.Dock="Left" Grid.Row="0" x:Name="Menu" |
| | | Style="{StaticResource ListBoxItemStyle1}" FontSize="16" |
| | | Style="{StaticResource ListBoxItemStyle1}" FontSize="14" |
| | | BorderBrush="{StaticResource PrimaryColor}" |
| | | BorderThickness="1" |
| | | SelectionChanged="Menu_SelectionChanged" |
| | |
| | | using HMI.Base; |
| | | using HMI.Core.Api; |
| | | using Panuon.WPF.UI; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | |
| | | |
| | | namespace WPFProject.Controls |
| | | { |
| | | public class TabChangedEventArg |
| | | { |
| | | public IPlugin oldValue { get; set; } |
| | | public IPlugin newValue { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// MainTabControl.xaml 的交互逻辑 |
| | | /// </summary> |
| | |
| | | } |
| | | |
| | | // Tab切换事件 |
| | | public static readonly RoutedEvent OnTabChangeEvent = |
| | | EventManager.RegisterRoutedEvent("OnTabChange", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MenuTabControl)); |
| | | |
| | | public event RoutedEventHandler OnTabChange |
| | | { |
| | | add |
| | | { |
| | | AddHandler(OnTabChangeEvent, value); |
| | | } |
| | | |
| | | remove |
| | | { |
| | | RemoveHandler(OnTabChangeEvent, value); |
| | | } |
| | | } |
| | | public event EventHandler<TabChangedEventArg> TabChanged; |
| | | |
| | | private ObservableCollection<PluginInfo> _MenuItems; |
| | | |
| | |
| | | { |
| | | page.Child = (UIElement)content; |
| | | } |
| | | TabChanged?.Invoke(this, new TabChangedEventArg { oldValue = last, newValue = newPlugin }); |
| | | } |
| | | } |
| | | |
| | |
| | | "Tr.CantClearSNR": "Program is running, can't clear snr!", |
| | | "Tr.MakeSureStopOvenTest": "Are you sure you want stop [{0}] test?", |
| | | "Tr.PositionCantClearSNR": "Position [{0}] can't clear snr now!", |
| | | "Tr.MakeSureStopAllTest": "Are you sure you want to stop test?", |
| | | "Tr.OvenIsTesting": "Oven is testing, can't stop test.'", |
| | | "Tr.TestProgram": "Test Program" |
| | | } |
| | |
| | | "App.MenuLoadFailed": "{0} load failed: {1} {2}", |
| | | "App.MenuCount": "There are {0} menus is loading...", |
| | | "App.SelectIcon": "Select icon", |
| | | "App.Welcome": "Welcom! {0}", |
| | | "App.Welcome": "Welcome! {0}", |
| | | "App.MakeSureLogout": "Are you sure you want to logout?", |
| | | "App.MakeSureRestartApp": "Are you sure you want to restart?", |
| | | "App.NoExportData": "No Data To Export", |
| | |
| | | "App.ScannerSetting": "Scanner Setting", |
| | | "App.SequenceIsStarting": "Starting Test,Please Wait...", |
| | | "App.Status": "Status", |
| | | "App.LoadPluginError": "Load plugin error,please check." |
| | | "App.LoadPluginError": "Load plugin error,please check.", |
| | | "App.Version": "Ver.", |
| | | "App.PluginVersion": "Plugin Ver.", |
| | | "App.CPUUsage": "CPU Usage", |
| | | "App.RemUsage": "Rem Usage", |
| | | "App.TotalCPUUsage": "PC CPU Usage", |
| | | "App.TotalRemUsage": "PC Rem Usage" |
| | | } |
| | |
| | | "Tr.CantClearSNR": "程序运行中,不能清空条码", |
| | | "Tr.MakeSureStopOvenTest": "确实停止老化炉[{0}]的测试吗?", |
| | | "Tr.PositionCantClearSNR": "穴位[{0}]当前不允许清除条码!", |
| | | "Tr.MakeSureStopAllTest": "确定要停止所有测试吗?", |
| | | "Tr.OvenIsTesting": "有仓位正在测试中,不能停止测试", |
| | | "Tr.TestProgram": "测试程序" |
| | | } |
| | |
| | | "App.ScannerSetting": "扫码枪设置", |
| | | "App.SequenceIsStarting": "正在启动测试序列,请稍后...", |
| | | "App.Status": "状态", |
| | | "App.LoadPluginError": "加载出错,请确认" |
| | | "App.LoadPluginError": "加载出错,请确认", |
| | | "App.Version": "软件版本:", |
| | | "App.PluginVersion": "插件版本:", |
| | | "App.CPUUsage": "CPU使用", |
| | | "App.RemUsage": "内存使用", |
| | | "App.TotalCPUUsage": "总CPU使用", |
| | | "App.TotalRemUsage": "总内存使用" |
| | | } |
| | |
| | | pu:WindowXCaption.HeaderAlignment="Stretch" |
| | | Title="TestPlatform" |
| | | pu:WindowXCaption.Background="Transparent" |
| | | pu:WindowXCaption.Height="80" |
| | | pu:WindowXCaption.Height="60" |
| | | IsOverlayerVisible="True" |
| | | pu:WindowXCaption.Foreground="#FFF"> |
| | | <Window.Resources> |
| | |
| | | <Setter Property="pu:MenuHelper.TopLevelItemsHoverBackground" Value="{x:Null}"/> |
| | | <Setter Property="pu:MenuHelper.TopLevelDropDownPlacement" Value="BottomLeft"/> |
| | | </Style> |
| | | |
| | | </Window.Resources> |
| | | <Window.Background> |
| | | <ImageBrush Stretch="Uniform" AlignmentX="Left" AlignmentY="Top" |
| | |
| | | |
| | | <pu:WindowXCaption.HeaderTemplate> |
| | | <DataTemplate> |
| | | <DockPanel DataContext="{Binding ElementName=window}" WindowChrome.IsHitTestVisibleInChrome="True" VerticalAlignment="Center" Height="100"> |
| | | <DockPanel DataContext="{Binding ElementName=window}" WindowChrome.IsHitTestVisibleInChrome="True" |
| | | VerticalAlignment="Center" Height="80"> |
| | | <StackPanel Orientation="Horizontal"> |
| | | <Image DockPanel.Dock="Left" Source="{Binding WindowLogo}" Margin="5,0,20,0" Height="60" VerticalAlignment="Center" Stretch="Fill" |
| | | <Image DockPanel.Dock="Left" Source="{Binding WindowLogo}" Margin="5,0,20,0" Height="40" VerticalAlignment="Center" Stretch="Fill" |
| | | RenderOptions.BitmapScalingMode="HighQuality" /> |
| | | <TextBlock FontSize="30" VerticalAlignment="Center" Text="{Binding WindowTitle}"> |
| | | <TextBlock.Effect> |
| | |
| | | </Grid.RowDefinitions> |
| | | <StackPanel Grid.Row="0" VerticalAlignment="Top" Margin="10,10,0,0" Orientation="Horizontal"> |
| | | <Menu Margin="0" Padding="0" VerticalAlignment="Top" |
| | | VerticalContentAlignment="Center" Style="{StaticResource UserMenu}" |
| | | |
| | | Background="Transparent"> |
| | | VerticalContentAlignment="Center" Style="{StaticResource UserMenu}" Background="Transparent"> |
| | | <MenuItem x:Name="userMenu" Header="{Binding WelcomeTitle}" FontSize="16"> |
| | | <MenuItem Icon="" Cursor="Hand" FontSize="14" Header="退出登录" |
| | | x:Name="MiLogout" Click="MenuItem_Click"/> |
| | |
| | | </Button.Style> |
| | | </Button> |
| | | </StackPanel> |
| | | <Button Grid.Row="1" Margin="20,0,0,20" Foreground="#FFF" |
| | | Visibility="{Binding Alarms.Count,Converter={StaticResource cv}}" |
| | | HorizontalContentAlignment="Left" Style="{StaticResource LinkButton}" |
| | | Click="Clear_AllAlarm_Click" |
| | | Content="清除全部报警"/> |
| | | <DockPanel Margin="20,0,0,20" Grid.Row="1" LastChildFill="False"> |
| | | <Button DockPanel.Dock="Left" Foreground="#FFF" |
| | | Visibility="{Binding Alarms.Count,Converter={StaticResource cv}}" |
| | | HorizontalContentAlignment="Left" Style="{StaticResource LinkButton}" |
| | | Click="Clear_AllAlarm_Click" |
| | | Content="清除全部报警"/> |
| | | <!--<local:ResourceUI x:Name="resourceUI" Loaded="resourceUI_Loaded" DockPanel.Dock="Right"/>--> |
| | | </DockPanel> |
| | | </Grid> |
| | | |
| | | <ListBox x:Name="list" |
| | |
| | | <Setter Property="Padding" Value="0"/> |
| | | <Setter Property="VerticalContentAlignment" Value="Center"/> |
| | | <Setter Property="HorizontalContentAlignment" Value="Stretch"/> |
| | | <Setter Property="Height" Value="70"/> |
| | | <Setter Property="Height" Value="50"/> |
| | | <Setter Property="Margin" Value="0,0,0,1"/> |
| | | <Setter Property="BorderThickness" Value="0"/> |
| | | </Style> |
| | |
| | | <RowDefinition Height="Auto"/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <ctl:MainTabControl Grid.Row="0" x:Name="menuTab"> |
| | | <ctl:MainTabControl Grid.Row="0" x:Name="menuTab" TabChanged="menuTab_TabChanged"> |
| | | |
| | | </ctl:MainTabControl> |
| | | |
| | | <!--<ctl:MenuTabControl Grid.Row="1" x:Name="menuTab" OnTabChange="menuTab_OnTabChange"> </ctl:MenuTabControl>--> |
| | | |
| | | |
| | | <!--<StatusBar Grid.Row="1" Background="{StaticResource HoriBar}"></StatusBar>--> |
| | | <DockPanel Grid.Row="1" Height="20" Background="{StaticResource PrimaryColor}" LastChildFill="False"> |
| | | |
| | | <TextBlock Margin="20,0,0,0" FontSize="14" VerticalAlignment="Center" Foreground="#FFF"> |
| | | <Run Text="{DynamicResource App.Version}"/> |
| | | <Run Text="{Binding SoftwareVersion}"/> |
| | | </TextBlock> |
| | | |
| | | <TextBlock Margin="20,0,0,0" FontSize="14" VerticalAlignment="Center" Foreground="#FFF"> |
| | | <Run Text="{DynamicResource App.PluginVersion}"/> |
| | | <Run Text="{Binding PluginVersion}"/> |
| | | </TextBlock> |
| | | |
| | | <local:ResourceUI FontSize="14" Margin="0,1,20,1" DockPanel.Dock="Right" x:Name="resourceUI"/> |
| | | |
| | | </DockPanel> |
| | | </Grid> |
| | | </pu:WindowX> |
| | |
| | | using HMI.Core.Util; |
| | | using HMI.UI.Util; |
| | | using HMI.Util.Alarm; |
| | | using log4net; |
| | | using Panuon.WPF.UI; |
| | | using System; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Threading.Tasks; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Media.Imaging; |
| | |
| | | /// </summary> |
| | | public partial class PanuonWindow : WindowX, IPluginContainer, IAlarmShow |
| | | { |
| | | private ILog log = LogManager.GetLogger("MainWindow"); |
| | | public PanuonWindow() |
| | | { |
| | | this.Loaded += PanuonWindow_Loaded; |
| | | SoftwareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); |
| | | } |
| | | |
| | | private UserInfo currentUser; |
| | |
| | | get => Alarms?.Count ?? 0; |
| | | } |
| | | |
| | | private string softwareVersion; |
| | | public string SoftwareVersion |
| | | { |
| | | get => softwareVersion; |
| | | set |
| | | { |
| | | Set(ref softwareVersion, value); |
| | | } |
| | | } |
| | | |
| | | private string pluginVersion; |
| | | public string PluginVersion |
| | | { |
| | | get => pluginVersion; |
| | | set |
| | | { |
| | | Set(ref pluginVersion, value); |
| | | } |
| | | } |
| | | |
| | | public ListBox sb |
| | | { |
| | | get; set; |
| | |
| | | |
| | | private void PanuonWindow_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | DataContext = this; |
| | | RefrshConfig(); |
| | | InitializeComponent(); |
| | | AlarmShowHelper.Register(this); |
| | | var sb = WindowXCaption.GetHeaderTemplate(this); |
| | | //sb.FindName("list",this.Con); |
| | | try |
| | | { |
| | | DataContext = this; |
| | | RefrshConfig(); |
| | | InitializeComponent(); |
| | | AlarmShowHelper.Register(this); |
| | | |
| | | WelcomeTitle = this.lang("App.Welcome", UserInfo.User.Name); |
| | | ShowMenu = false; |
| | | Application.Current.MainWindow = this; |
| | | SystemSetting.SystemSettingChanged += SystemSetting_SystemSettingChanged; |
| | | WelcomeTitle = this.lang("App.Welcome", UserInfo.User.Name); |
| | | ShowMenu = false; |
| | | Application.Current.MainWindow = this; |
| | | SystemSetting.SystemSettingChanged += SystemSetting_SystemSettingChanged; |
| | | |
| | | Task.Run(() => |
| | | { |
| | | ResourceListener.Instance.RefreshEvent += this.resourceUI.Refresh; |
| | | ResourceListener.Instance.Start(); |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Window Loaded Error.", ex); |
| | | } |
| | | } |
| | | |
| | | private void RefrshConfig() |
| | |
| | | { |
| | | try |
| | | { |
| | | ResourceListener.Instance.Stop(); |
| | | AlarmUtil.Release(); |
| | | PluginLoader.Reset(); |
| | | UserInfo.Logout(); |
| | |
| | | { |
| | | |
| | | } |
| | | Application.Current.Shutdown(); |
| | | Application.Current.Shutdown(0); |
| | | } |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | |
| | | Alarms?.Clear(); |
| | | } |
| | | |
| | | private void menuTab_TabChanged(object sender, Controls.TabChangedEventArg e) |
| | | { |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | if (e.newValue == null) |
| | | { |
| | | PluginVersion = string.Empty; |
| | | } |
| | | else |
| | | { |
| | | PluginVersion = e.newValue.GetType().Assembly.GetName().Version.ToString(); |
| | | } |
| | | }, System.Windows.Threading.DispatcherPriority.Normal); |
| | | } |
| | | |
| | | //private void BaseWindow_Loaded(object sender, RoutedEventArgs e) |
| | | //{ |
| | | // var s = (Style)this.Resources["WindowButton"]; |
| | |
| | | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 |
| | | //通过使用 "*",如下所示: |
| | | // [assembly: AssemblyVersion("1.0.*")] |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyVersion("1.0.0.1")] |
| | | [assembly: AssemblyFileVersion("1.0.0.0")] |
| | | [assembly: XmlConfigurator(ConfigFile = "Config/log4net.config", Watch = true)] |
| New file |
| | |
| | | using HMI.Simple.Util; |
| | | using log4net; |
| | | using System; |
| | | using System.Diagnostics; |
| | | using System.Management; |
| | | using System.Timers; |
| | | using System.Xml.Linq; |
| | | |
| | | namespace WPFProject |
| | | { |
| | | public class RunTimeState |
| | | { |
| | | public float cpuRate { get; set; } |
| | | public double remRate { get; set; } |
| | | |
| | | public float totalCpuRate { get; set; } |
| | | public double totalRemRate { get; set; } |
| | | } |
| | | |
| | | public class ResourceListener |
| | | { |
| | | public event EventHandler<RunTimeState> RefreshEvent; |
| | | private Timer timer; |
| | | private System.Threading.CancellationTokenSource _can; |
| | | |
| | | private static ResourceListener instance; |
| | | public static ResourceListener Instance |
| | | { |
| | | get |
| | | { |
| | | |
| | | if (instance == null) |
| | | { |
| | | instance = new ResourceListener(); |
| | | } |
| | | return instance; |
| | | } |
| | | } |
| | | private ILog log = LogManager.GetLogger("ResourceListener"); |
| | | |
| | | // CPU占用 |
| | | private PerformanceCounter totalCpuCounter; |
| | | |
| | | private PerformanceCounter cpuCounter; |
| | | |
| | | private ResourceListener() |
| | | { |
| | | totalCpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); |
| | | cpuCounter = new PerformanceCounter("Process", "% Processor Time", Process.GetCurrentProcess().ProcessName, true); |
| | | } |
| | | |
| | | public void Start() |
| | | { |
| | | _can = new System.Threading.CancellationTokenSource(); |
| | | Refresh(); |
| | | timer = new Timer(); |
| | | timer.AutoReset = false; |
| | | timer.Interval = 30000; |
| | | timer.Elapsed += Timer_Elapsed; |
| | | timer.Enabled = true; |
| | | } |
| | | |
| | | private void Refresh() |
| | | { |
| | | try |
| | | { |
| | | var _cpuCount = Environment.ProcessorCount; |
| | | ObjectQuery wql = new ObjectQuery("SELECT * FROM Win32_OperatingSystem"); |
| | | ManagementObjectSearcher searcher = new ManagementObjectSearcher(wql); |
| | | |
| | | string prcName = Process.GetCurrentProcess().ProcessName; |
| | | var counter_Exec = new PerformanceCounter("Process", "Working Set - Private", prcName); |
| | | ulong dWsp_Exec = (ulong)(counter_Exec.RawValue / 1024); |
| | | |
| | | var totalCpuRate = totalCpuCounter.NextValue(); |
| | | var cpuRate = cpuCounter.NextValue() / _cpuCount; |
| | | |
| | | foreach (ManagementObject obj in searcher.Get()) |
| | | { |
| | | ulong totalVisibleMemorySize = (ulong)obj["TotalVisibleMemorySize"]; |
| | | ulong freePhysicalMemory = (ulong)obj["FreePhysicalMemory"]; |
| | | |
| | | ulong usedMemory = totalVisibleMemorySize - freePhysicalMemory; |
| | | string info = $"\r\n总内存: {totalVisibleMemorySize / 1024} MB\r\n"; |
| | | |
| | | info += $"已使用内存: {usedMemory / 1024} MB\r\n"; |
| | | double usagePercent = usedMemory * 100d / totalVisibleMemorySize; |
| | | info += $"内存占用率: {usagePercent:F2}%\r\n"; |
| | | |
| | | info += $"应用占用内存: {dWsp_Exec / 1024} MB\r\n"; |
| | | double appPercent = dWsp_Exec * 100d / totalVisibleMemorySize; |
| | | info += $"应用内存占用率: {appPercent:F2}%"; |
| | | RefreshEvent?.Invoke(this, new RunTimeState |
| | | { |
| | | cpuRate = cpuRate, |
| | | remRate = appPercent, |
| | | totalCpuRate = totalCpuRate, |
| | | totalRemRate = usagePercent |
| | | }); |
| | | log.Info(info); |
| | | if (usagePercent > 80) |
| | | { |
| | | // AlarmUtil.CreateAlarm("App", "内存占用过高,超80%", out _); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Refresh Resource Error.", ex); |
| | | } |
| | | } |
| | | |
| | | private void Timer_Elapsed(object sender, ElapsedEventArgs e) |
| | | { |
| | | try |
| | | { |
| | | timer.Enabled = false; |
| | | _can.Token.ThrowIfCancellationRequested(); |
| | | Refresh(); |
| | | timer.Enabled = true; |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | } |
| | | |
| | | public void Stop() |
| | | { |
| | | _can?.Cancel(); |
| | | _can?.Dispose(); |
| | | instance = null; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | [Btns] |
| | | ;名称=ActionName |
| | | 上电激活=Active |
| | | CAN测试=CanTest |
| | | LIN测试=LinTest |
| | | DoIP测试=DOIPTest |
| New file |
| | |
| | | <hb:NotifyControl x:Class="WPFProject.ResourceUI" |
| | | 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:local="clr-namespace:WPFProject.UI" |
| | | mc:Ignorable="d" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <hb:NotifyControl.Resources> |
| | | <ResourceDictionary> |
| | | <ResourceDictionary.MergedDictionaries> |
| | | <pu:StyleDictionary Includes="Label" /> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | <Style x:Key="def" TargetType="Label" BasedOn="{StaticResource {x:Static pu:StyleKeys.LabelStyle}}"> |
| | | <Setter Property="pu:LabelHelper.CornerRadius" Value="3"/> |
| | | <Setter Property="Padding" Value="5,0"/> |
| | | <Setter Property="Margin" Value="0"/> |
| | | <Setter Property="VerticalContentAlignment" Value="Center"/> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </Style> |
| | | </ResourceDictionary> |
| | | </hb:NotifyControl.Resources> |
| | | |
| | | <Grid dp:GridHelper.Space="10" dp:GridHelper.SpaceIgnore="ALL"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition Width="Auto"/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | </Grid.ColumnDefinitions> |
| | | |
| | | <Label Grid.Column="0" Style="{StaticResource def}" x:Name="l1"> |
| | | <TextBlock> |
| | | <Run Text="{DynamicResource App.CPUUsage}"/> |
| | | <Run Text="{Binding CpuRate}"/> |
| | | </TextBlock> |
| | | </Label> |
| | | |
| | | <Label Grid.Column="1" Style="{StaticResource def}" x:Name="l2"> |
| | | <TextBlock> |
| | | <Run Text="{DynamicResource App.RemUsage}"/> |
| | | <Run Text="{Binding RemRate}"/> |
| | | </TextBlock> |
| | | </Label> |
| | | |
| | | <Label Grid.Column="2" Style="{StaticResource def}" x:Name="l3"> |
| | | <TextBlock Grid.Column="2"> |
| | | <Run Text="{DynamicResource App.TotalCPUUsage}"/> |
| | | <Run Text="{Binding TotalCpuRate}"/> |
| | | </TextBlock> |
| | | </Label> |
| | | |
| | | <Label Grid.Column="3" Style="{StaticResource def}" x:Name="l4"> |
| | | <TextBlock Grid.Column="3"> |
| | | <Run Text="{DynamicResource App.TotalRemUsage}"/> |
| | | <Run Text="{Binding TotalRemRate}"/> |
| | | </TextBlock> |
| | | </Label> |
| | | </Grid> |
| | | </hb:NotifyControl> |
| New file |
| | |
| | | using HMI.Base; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Media; |
| | | |
| | | namespace WPFProject |
| | | { |
| | | /// <summary> |
| | | /// ResourceListener.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class ResourceUI : NotifyControl |
| | | { |
| | | private string cpuRate; |
| | | public string CpuRate |
| | | { |
| | | get => cpuRate; |
| | | set |
| | | { |
| | | Set(ref cpuRate, value); |
| | | } |
| | | } |
| | | |
| | | private string remRate; |
| | | public string RemRate |
| | | { |
| | | get => remRate; |
| | | set |
| | | { |
| | | Set(ref remRate, value); |
| | | } |
| | | } |
| | | |
| | | private string totalCpuRate; |
| | | public string TotalCpuRate |
| | | { |
| | | get => totalCpuRate; |
| | | set |
| | | { |
| | | Set(ref totalCpuRate, value); |
| | | } |
| | | } |
| | | |
| | | private string totalRemRate; |
| | | public string TotalRemRate |
| | | { |
| | | get => totalRemRate; |
| | | set |
| | | { |
| | | Set(ref totalRemRate, value); |
| | | } |
| | | } |
| | | |
| | | public ResourceUI() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | public void Refresh(object sender, RunTimeState state) |
| | | { |
| | | Dispatcher.BeginInvoke(() => |
| | | { |
| | | CpuRate = $"{state.cpuRate:F1}%"; |
| | | SetColor(state.cpuRate, l1); |
| | | RemRate = $"{state.remRate:F1}%"; |
| | | SetColor(state.remRate, l2); |
| | | |
| | | TotalCpuRate = $"{state.totalCpuRate:F1}%"; |
| | | SetColor(state.totalCpuRate, l3); |
| | | TotalRemRate = $"{state.totalRemRate:F1}%"; |
| | | SetColor(state.totalRemRate, l4); |
| | | }, System.Windows.Threading.DispatcherPriority.Normal); |
| | | } |
| | | |
| | | private void SetColor(double val, Label label) |
| | | { |
| | | if (val > 80) |
| | | { |
| | | label.Background = Brushes.Red; |
| | | } |
| | | else if (val > 60) |
| | | { |
| | | label.Background = Brushes.Orange; |
| | | } |
| | | else |
| | | { |
| | | label.Background = Application.Current.FindResource("SecondPrimaryColor") as Brush; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | <Compile Include="PanuonWindow.xaml.cs"> |
| | | <DependentUpon>PanuonWindow.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="ResourceListener.cs" /> |
| | | <Compile Include="UI\ResourceUI.xaml.cs"> |
| | | <DependentUpon>ResourceUI.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="UI\TestWindow.xaml.cs"> |
| | | <DependentUpon>TestWindow.xaml</DependentUpon> |
| | | </Compile> |
| | |
| | | <DependentUpon>MenuTabControl.xaml</DependentUpon> |
| | | </Compile> |
| | | <Page Include="PanuonWindow.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | | <Page Include="UI\ResourceUI.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | |
| | | <CopyToOutputDirectory>Always</CopyToOutputDirectory> |
| | | </Content> |
| | | <Content Include="变更记录\2025-12-24.txt" /> |
| | | <None Include="Settings.ini"> |
| | | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
| | | </None> |
| | | <Resource Include="Icon\b1.jpg" /> |
| | | <Resource Include="Icon\b2.jpg" /> |
| | | <Resource Include="Icon\b3.jpg" /> |
| | |
| | | <ProjectReference Include="..\ModBusTcpController\ModBusTcpController.csproj"> |
| | | <Project>{49db0c9b-b239-4608-a91e-f5ed43afaf96}</Project> |
| | | <Name>ModBusTcpController</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.DataViewer\Plugin.DataViewer.csproj"> |
| | | <Project>{dbfe5040-963f-4bbf-93fb-26b3f18fda90}</Project> |
| | | <Name>Plugin.DataViewer</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.SeqEditor\Plugin.SeqEditor.csproj"> |
| | | <Project>{1260f995-1ae9-17b6-feb5-c430c1416bec}</Project> |
| | |
| | | move /y "$(TargeDir)Plugin.ModelManage.dll" $(TargeDir)Plugin\Plugin.ModelManage.dll" |
| | | move /y "$(TargeDir)Plugin.CurrentSensorControl.dll" $(TargeDir)Plugin\Plugin.CurrentSensorControl.dll" |
| | | move /y "$(TargeDir)Plugin.TsSupport.dll" $(TargeDir)Plugin\Plugin.TsSupport.dll" |
| | | move /y "$(TargeDir)Plugin.DataViewer.dll" $(TargeDir)Plugin\Plugin.DataViewer.dll" |
| | | move /y "$(TargeDir)Util.ManualDebug.dll" $(TargeDir)Plugin\Util.ManualDebug.dll" |
| | | |
| | | setlocal enabledelayedexpansion |
| | | |
| | |
| | | ) |
| | | |
| | | for %25%25F in ("%25source_folder%25\*") do ( |
| | | if /I not "%25%25~nxF"=="$(TargetFileName)" if /I not "%25%25~nxF"=="$(TargetFileName).config" if /I not "%25%25~nxF"=="$(TargetName).pdb" if /I not "%25%25~nxF"=="clear.bat" if /I not "%25%25~nxF"=="安装MSMQ.bat" ( |
| | | if /I not "%25%25~nxF"=="$(TargetFileName)" if /I not "%25%25~nxF"=="$(TargetFileName).config" if /I not "%25%25~nxF"=="$(TargetName).pdb" if /I not "%25%25~nxF"=="clear.bat" if /I not "%25%25~nxF"=="安装MSMQ.bat" if /I not "%25%25~nxF"=="Settings.ini" ( |
| | | move /Y "%25%25F" "%25destination_folder%25" |
| | | ) |
| | | ) |
| | |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.SeqEditor", "..\Plugin.SeqEditor\Plugin.SeqEditor.csproj", "{1260F995-1AE9-17B6-FEB5-C430C1416BEC}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.DataViewer", "..\Plugin.DataViewer\Plugin.DataViewer.csproj", "{DBFE5040-963F-4BBF-93FB-26B3F18FDA90}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.UICollection", "..\Plugin.UICollection\Plugin.UICollection.csproj", "{22DC8D91-50B2-47CA-86A8-29A6DA48F388}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtilLib", "..\..\UtilLib\UtilLib.csproj", "{A132F114-A26B-4428-BAEC-4851F38C0E14}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UILib", "..\..\UILib\UILib.csproj", "{27325FE0-3CE2-4CD5-8EB5-7E45CC441479}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Util.ManualDebug", "..\Util.ManualDebug\Util.ManualDebug.csproj", "{D0944E62-EE52-4ABE-832A-A09D98814DB1}" |
| | | EndProject |
| | | Global |
| | | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
| | | Debug|Any CPU = Debug|Any CPU |
| | |
| | | {1260F995-1AE9-17B6-FEB5-C430C1416BEC}.Release|x64.Build.0 = Release|x64 |
| | | {1260F995-1AE9-17B6-FEB5-C430C1416BEC}.Release|x86.ActiveCfg = Release|x86 |
| | | {1260F995-1AE9-17B6-FEB5-C430C1416BEC}.Release|x86.Build.0 = Release|x86 |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Release|x64.Build.0 = Release|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {DBFE5040-963F-4BBF-93FB-26B3F18FDA90}.Release|x86.Build.0 = Release|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Release|x64.Build.0 = Release|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {22DC8D91-50B2-47CA-86A8-29A6DA48F388}.Release|x86.Build.0 = Release|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Release|x64.Build.0 = Release|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {A132F114-A26B-4428-BAEC-4851F38C0E14}.Release|x86.Build.0 = Release|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Release|x64.Build.0 = Release|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {27325FE0-3CE2-4CD5-8EB5-7E45CC441479}.Release|x86.Build.0 = Release|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Debug|x64.Build.0 = Debug|x64 |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Debug|x86.ActiveCfg = Debug|x86 |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Debug|x86.Build.0 = Debug|x86 |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Release|x64.Build.0 = Release|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {D0944E62-EE52-4ABE-832A-A09D98814DB1}.Release|x86.Build.0 = Release|Any CPU |
| | | EndGlobalSection |
| | | GlobalSection(SolutionProperties) = preSolution |
| | | HideSolutionNode = FALSE |