using Microsoft.Win32; using NEIntelligentControl2.Models; using NEIntelligentControl2.Models.BoostStation; using NEIntelligentControl2.Models.Datas; using NEIntelligentControl2.Models.Messages; using NEIntelligentControl2.Service.User; using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace NEIntelligentControl2.Pages.BoostStation { /// /// 升压站页面 /// public partial class PageStation : Page { public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(int), typeof(PageStation)); public static readonly DependencyProperty DataTagProperty = DependencyProperty.Register("DataTag", typeof(string), typeof(PageStation)); public static readonly DependencyProperty CoordinateProperty = DependencyProperty.Register("Coordinate", typeof(Point), typeof(PageStation)); public static readonly DependencyProperty IsEditModelProperty = DependencyProperty.Register("IsEditModel", typeof(bool), typeof(PageStation)); public static readonly DependencyProperty IsNegateProperty = DependencyProperty.Register("IsNegate", typeof(bool), typeof(PageStation)); /// /// 控件方向 /// public int Angle { get => (int)GetValue(AngleProperty); set => SetValue(AngleProperty, value); } /// /// 数据标签 /// public string DataTag { get => GetValue(DataTagProperty) as string; set => SetValue(DataTagProperty, value); } /// /// 控件坐标 /// public Point Coordinate { get => (Point)GetValue(CoordinateProperty); set => SetValue(CoordinateProperty, value); } /// /// 是否取反 /// public bool IsNegate { get => (bool)GetValue(IsNegateProperty); set => SetValue(IsNegateProperty, value); } private Control _CurrentControl; private Control _TempleteControl; private bool _IsSelectAction; public BoostStationInfo StationInfo { get; set; } /// /// 保存动作 /// public Action SaveAction { get; set; } /// /// 是否被编辑 /// private bool IsEdited; /// /// 是否继续刷新数据 /// private bool _IsRefreshData; /// /// 所有数据点 /// private List _BoostStationPoints; /// /// 数据地址 /// private string _Url = ""; /// /// 是否是编辑模式 /// public bool IsEditModel { get => (bool)GetValue(IsEditModelProperty); set => SetValue(IsEditModelProperty, value); } /// /// 服务地址 /// private string _InfoUrl = ""; /// /// 单击时间 /// private DateTime _ClickTime; private string _BackgroundOld; private static readonly object locker = new object(); private UserManager _UserManager; private WEBHelper _WEBHelper; public PageStation(UserManager um, WEBHelper web) { InitializeComponent(); _UserManager = um; _WEBHelper = web; try { #if (DEBUG) _InfoUrl = ConfigurationManager.AppSettings["ServicePathDebug"]; #else _InfoUrl = ConfigurationManager.AppSettings["ServicePath"]; #endif } catch (Exception ex) { Console.WriteLine("读取配置文件[ServicePath]出错!", ex); } } private void Init() { _BoostStationPoints = new List(); try { if (!string.IsNullOrWhiteSpace(StationInfo.Background)) { BitmapImage image = GetBackgroundImage(StationInfo.Background); _Canvas.Background = new ImageBrush(image) { Stretch = Stretch.Uniform }; } } catch { } _Canvas.Children.Clear(); foreach (var v in StationInfo.BoostStationPointInfos) { try { var obj = Activator.CreateInstance(Type.GetType($"NEIntelligentControl2.Views.BoostStation.{v.Type}")) as IBoostStationPoint; if (obj == null) { continue; } _BoostStationPoints.Add(obj); obj.DataTag = v.DataTag; obj.Proportion = v.Proportion; obj.Info = v.Info; obj.IsNegate = v.IsNegate; var ct = obj as Control; Canvas.SetLeft(ct, v.Coordinate.X); Canvas.SetTop(ct, v.Coordinate.Y); ct.RenderTransform = GetTransform(v); _Canvas.Children.Add(ct); } catch { } } var keys = string.Join(",", _BoostStationPoints.Where(b => !string.IsNullOrWhiteSpace(b.DataTag)).Select(b => b.DataTag).ToArray()); try { #if (DEBUG) var ul = ConfigurationManager.AppSettings["DataServicePathDebug"]; #else var ul = ConfigurationManager.AppSettings["DataServicePath"]; #endif _Url = $"{ul}/ts/latest?keys={keys}"; } catch (Exception ex) { Console.WriteLine("读取配置文件[DataServicePath]出错!", ex); } } private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { _CurrentControl?.ReleaseMouseCapture(); if (e.OriginalSource != sender) return; ClosePopup(); } private void ClosePopup(bool isSelect = false) { if (!isSelect) { AllNotSelect(); } if (!_Popup.IsOpen) { return; } _Popup.IsOpen = false; var sp = _CurrentControl as IBoostStationPoint; if (sp == null) return; sp.DataTag = this.DataTag; sp.IsNegate = this.IsNegate; Canvas.SetLeft(_CurrentControl, Coordinate.X); Canvas.SetTop(_CurrentControl, Coordinate.Y); _CurrentControl = null; IsEdited = true; } private void AllNotSelect() { var vvs = GetSelectedItems(); foreach (var v in vvs) { var issp = v as IBoostStationPoint; if (issp != null) { issp.IsSelected = false; } } } private Transform GetTransform() { RotateTransform rt = new RotateTransform(); if (_TempleteControl != null) { RotateTransform ort = _TempleteControl.RenderTransform as RotateTransform; rt.Angle = ort.Angle; rt.CenterX = ort.CenterX; rt.CenterY = ort.CenterY; } return rt; } private Transform GetTransform(Control obj) { RotateTransform rt = new RotateTransform(); rt.Angle = this.Angle; rt.CenterX = obj.ActualWidth / 2; rt.CenterY = obj.ActualHeight / 2; return rt; } private Transform GetTransform(BoostStationPointInfo v) { RotateTransform rt = new RotateTransform(); rt.Angle = v.Angle; rt.CenterX = v.CenterCoordinate.X; rt.CenterY = v.CenterCoordinate.Y; return rt; } /// /// 小控件被单击 /// private void PointClicked(Control c) { if ((c as IBoostStationPoint).IsTemplete) { TempleteClicked(); } else { SelectClicked(c); } } private void SelectClicked(Control c) { _ClickTime = DateTime.Now; if (_Popup.IsOpen) { ClosePopup(true); } _CurrentControl = c; _CurrentControl.CaptureMouse(); Coordinate = new Point(Canvas.GetLeft(c), Canvas.GetTop(c)); DataTag = (c as IBoostStationPoint).DataTag; IsNegate = (c as IBoostStationPoint).IsNegate; _Popup.IsOpen = true; _LBISelect.Focus(); } private void TempleteClicked() { var obj = Activator.CreateInstance(_TempleteControl.GetType()) as Control; if (obj == null) return; (obj as IBoostStationPoint).Clicked = PointClicked; (obj as IBoostStationPoint).IsEditModel = true; (obj as IBoostStationPoint).Proportion = (_TempleteControl as IBoostStationPoint).Proportion; Canvas.SetLeft(obj, Canvas.GetLeft(_TempleteControl)); Canvas.SetTop(obj, Canvas.GetTop(_TempleteControl)); obj.RenderTransform = GetTransform(); _Canvas.Children.Add(obj); IsEdited = true; } private void Canvas_MouseMove(object sender, MouseEventArgs e) { if (_IsSelectAction) { if (e.LeftButton != MouseButtonState.Pressed || e.OriginalSource == _Canvas || (DateTime.Now - _ClickTime).TotalMilliseconds < 300) return; MovePoint(_CurrentControl, e); _Popup.IsOpen = false; } else if (_TempleteControl != null) { MovePoint(_TempleteControl, e); } } private void _Canvas_MouseLeave(object sender, MouseEventArgs e) { if (_TempleteControl == null) return; _TempleteControl.Visibility = Visibility.Collapsed; if (_Popup.IsOpen) { _Popup.IsOpen = false; } } private void _Canvas_MouseEnter(object sender, MouseEventArgs e) { if (_TempleteControl == null) return; _TempleteControl.Visibility = Visibility.Visible; } private void ListBoxItem_Selected(object sender, RoutedEventArgs e) { string action = ((Control)sender).Tag as string; _IsSelectAction = action == "Select"; if (_TempleteControl != null) { _Canvas.Children.Remove(_TempleteControl); } if (_IsSelectAction) { _CurrentControl = null; _TempleteControl?.ReleaseMouseCapture(); _TempleteControl = null; } else { _TempleteControl?.CaptureMouse(); } var ct = Type.GetType($"NEIntelligentControl2.Views.BoostStation.{action}"); if (ct == null) return; var obj = Activator.CreateInstance(ct); if (!(obj is IBoostStationPoint)) return; (obj as IBoostStationPoint).IsTemplete = true; (obj as IBoostStationPoint).IsEditModel = true; (obj as IBoostStationPoint).Clicked = PointClicked; _TempleteControl = obj as Control; _TempleteControl.Loaded += PointLoaded; _Canvas.Children.Add(obj as Control); } private void PointLoaded(object sender, RoutedEventArgs e) { Control c = sender as Control; if (c == null) return; c.RenderTransform = GetTransform(c); } private void MovePoint(FrameworkElement c, MouseEventArgs e) { if (c == null) return; Point p = e.GetPosition(_Canvas); Canvas.SetTop(c, p.Y - c.ActualHeight / 2); Canvas.SetLeft(c, p.X - c.ActualWidth / 2); } private void Button_Click(object sender, RoutedEventArgs e) { switch (((Control)sender).Tag) { case "angle":// 角度 AngleChange(); break; case "background":// 选择背景图片 ChoseBackground(); break; case "delete":// 删除 DeletePoint(); break; case "save":// 保存 Save(); break; case "close":// 放弃保存 Close(); break; case "narrow":// 缩小控件 Narrow(); break; case "enlarge":// 放大控件 Enlarge(); break; default: return; } } /// /// 放大控件 /// private void Enlarge() { if (_CurrentControl != null) { (_CurrentControl as IBoostStationPoint).Zoom(1); } if (_TempleteControl != null) { (_TempleteControl as IBoostStationPoint).Zoom(1); } } /// /// 缩小控件 /// private void Narrow() { if (_CurrentControl != null) { (_CurrentControl as IBoostStationPoint).Zoom(-1); } if (_TempleteControl != null) { (_TempleteControl as IBoostStationPoint).Zoom(-1); } } private void Close() { var v = MessageBox.Show("放弃保存?", "提示", MessageBoxButton.YesNo); if (v != MessageBoxResult.Yes) return; if (StationInfo.Background != _BackgroundOld) { StationInfo.Background = _BackgroundOld; BitmapImage image = GetBackgroundImage(StationInfo.Background); _Canvas.Background = new ImageBrush(image) { Stretch = Stretch.Uniform }; } ToNormalModel(); } /// /// 回到正常模式 /// private void ToNormalModel() { _ToolPane.Visibility = Visibility.Collapsed; IsEdited = false; IsEditModel = false; _Popup.IsOpen = false; lock (locker) { Init(); } } /// /// 保存 /// private void Save() { try { if (!IsEdited) { ToNormalModel(); return; } if (_TempleteControl == null) { _Canvas.Children.Remove(_TempleteControl); _TempleteControl = null; } StationInfo.BoostStationPointInfos = GetBoostStationPointInfo(); StationInfo.UpdatedDate = DateTime.Now.Ticks; SaveAction?.Invoke(StationInfo); ToNormalModel(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } /// /// 获取所有控件信息 /// /// private List GetBoostStationPointInfo() { List bspis = new List(); foreach (var v in _Canvas.Children) { if (!(v is IBoostStationPoint)) { continue; } var point = v as IBoostStationPoint; var ct = v as Control; BoostStationPointInfo bspi = new BoostStationPointInfo(); bspi.Type = v.GetType().Name; bspi.DataTag = point.DataTag; bspi.Proportion = point.Proportion; bspi.Info = point.Info; bspi.IsNegate = point.IsNegate; RotateTransform rotate = ct.RenderTransform as RotateTransform; if (rotate != null) { bspi.CenterCoordinate = new Point(rotate.CenterX, rotate.CenterY); bspi.Angle = (int)rotate.Angle; } Point pt = new Point(Canvas.GetLeft(ct), Canvas.GetTop(ct)); bspi.Coordinate = pt; bspis.Add(bspi); } return bspis; } /// /// 更改角度 /// private void AngleChange() { Angle = Angle >= 270 ? 0 : Angle + 90; if (_CurrentControl != null) { _CurrentControl.RenderTransform = GetTransform(_CurrentControl); } if (_TempleteControl != null) { var tr = _TempleteControl.RenderTransform as RotateTransform; tr.Angle = this.Angle; _TempleteControl.RenderTransform = tr; } var vs = GetSelectedItems(); foreach (var v in vs) { v.RenderTransform = GetTransform(v); } IsEdited = true; } /// /// 删除标签点 /// private void DeletePoint() { List list = GetSelectedItems(); if (list.Count <= 0) return; foreach (var v in list) { _Canvas.Children.Remove(v); } IsEdited = true; } private List GetSelectedItems() { List ls = new List(); foreach (var v in _Canvas.Children) { var c = v as IBoostStationPoint; if (c == null || !c.IsSelected) continue; ls.Add(c as Control); } return ls; } private void ChoseBackground() { var dl = new OpenFileDialog(); dl.Filter = "图片(.png)|*.png"; dl.Title = "选择背景图片"; var b = dl.ShowDialog(); if (b == null || b == false) return; try { _BackgroundOld = StationInfo.Background; StationInfo.Background = GetBackgroundByFile(dl.FileName); BitmapImage image = GetBackgroundImage(StationInfo.Background); _Canvas.Background = new ImageBrush(image) { Stretch = Stretch.Uniform }; IsEdited = true; } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 从文件中获取背景图片文字 /// /// private string GetBackgroundByFile(string url) { var bs = File.ReadAllBytes(url); return Convert.ToBase64String(bs); } private BitmapImage GetBackgroundImage(string v) { if (string.IsNullOrWhiteSpace(v)) return null; BitmapImage bt = new BitmapImage(); bt.BeginInit(); bt.CacheOption = BitmapCacheOption.OnLoad; var bs = Convert.FromBase64String(v); using (Stream stream = new MemoryStream(bs)) { bt.StreamSource = stream; bt.EndInit(); bt.Freeze(); } return bt; } private void MenuItem_Click(object sender, RoutedEventArgs e) { switch (((Control)sender).Tag) { case "edit":// 编辑 EditModel(); break; } } /// /// 开启编辑模式 /// private void EditModel() { if (!_UserManager.IsLogined || _UserManager.User.Level != Models.User.UserLevel.Administrator) { MessageBox.Show("请登录管理员账号进入编辑模式!", "提示:", MessageBoxButton.OK, MessageBoxImage.Warning); return; } _BackgroundOld = StationInfo.Background; IsEditModel = true; _ToolPane.Visibility = Visibility.Visible; foreach (var v in _Canvas.Children) { var bsp = v as IBoostStationPoint; if (bsp == null) continue; bsp.Clicked = PointClicked; bsp.IsEditModel = true; } } private void Page_Loaded(object sender, RoutedEventArgs e) { Init(); this._IsRefreshData = true; Task.Factory.StartNew(RefreshData, TaskCreationOptions.LongRunning); Task.Factory.StartNew(CheckUpdate, TaskCreationOptions.LongRunning); } /// /// 检查更新 /// private async void CheckUpdate() { while (_IsRefreshData) { try { var dtstr = _WEBHelper.HttpGetString($"{_InfoUrl}/api/station/boost_station/update_time/{StationInfo.Id}"); long.TryParse(dtstr, out long dt); if (dt > 0 && dt != StationInfo.UpdatedDate) { var info = _WEBHelper.HttpGetJSON($"{_InfoUrl}/api/station/boost_station/{StationInfo.Id}"); Dispatcher.Invoke(() => { lock (locker) { StationInfo = info; Init(); } }); } } catch { } await Task.Delay(10000); } } private async void RefreshData() { while (_IsRefreshData) { try { var vs = _WEBHelper.HttpGetJSON>(_Url); if (vs != null && vs.Count > 0) { Dispatcher?.Invoke(() => { lock (locker) { foreach (var v in _BoostStationPoints) { if (string.IsNullOrWhiteSpace(v.DataTag)) { continue; } if (vs.ContainsKey(v.DataTag)) { v.Value = vs[v.DataTag].Value; } } } }); } Console.WriteLine($"刷新:{StationInfo.Id}"); } catch { } await Task.Delay(2000); } } private void Page_Unloaded(object sender, RoutedEventArgs e) { this._IsRefreshData = false; if (IsEdited) { var v = MessageBox.Show("有未保存的改动,是否保存?", "提示:", MessageBoxButton.YesNo); if (v == MessageBoxResult.Yes) { Save(); } } if (IsEditModel) { ToNormalModel(); } } private void _Canvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e) { if (_Popup.IsOpen) { ClosePopup(); } _LBTools.SelectedIndex = 0; } private void Direction_Click(object sender, RoutedEventArgs e) { if (_CurrentControl == null) return; int dtop = 0; int dleft = 0; switch (((Control)sender).Tag) { case "left": dleft = -1; break; case "right": dleft = 1; break; case "up": dtop = -1; break; case "down": dtop = 1; break; default: return; } double top = Canvas.GetTop(_CurrentControl) + dtop; double left = Canvas.GetLeft(_CurrentControl) + dleft; Coordinate = new Point(left, top); Canvas.SetTop(_CurrentControl, top); Canvas.SetLeft(_CurrentControl, left); } } }