1341 lines
47 KiB
C#
1341 lines
47 KiB
C#
using AiSportsMicrospaceDB.DBContext;
|
||
using AiSportsMicrospaceDB.Entities;
|
||
using Common;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using System.IO;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Input;
|
||
using System.Windows.Media;
|
||
using System.Windows.Media.Imaging;
|
||
using System.Windows.Shapes;
|
||
using Yztob.AiSports.Sensors.Abstractions;
|
||
using Yztob.AiSports.Sensors.Things;
|
||
using Line = System.Windows.Shapes.Line;
|
||
using Point = System.Windows.Point;
|
||
|
||
namespace Wpf_AiSportsMicrospace.Views
|
||
{
|
||
/// <summary>
|
||
/// 多人大绳点位配置页面
|
||
/// 功能:
|
||
/// 1. 根据 HomeWidth 动态生成 5-7 个点位
|
||
/// 2. 支持 Y 轴拖动调整
|
||
/// 3. 从数据库加载/保存点位数据
|
||
/// </summary>
|
||
public partial class MultiJumpRope : UserControl
|
||
{
|
||
#region 私有变量
|
||
|
||
private bool _isDragging = false;
|
||
private Ellipse _draggedEllipse;
|
||
private double _dragStartY;
|
||
private double _originalY;
|
||
private double _dragStartX;
|
||
private double _originalX;
|
||
|
||
/// <summary>
|
||
/// 点位数据列表
|
||
/// </summary>
|
||
private List<JumpRopePoint> _points = new List<JumpRopePoint>();
|
||
|
||
/// <summary>
|
||
/// 当前场地宽度
|
||
/// </summary>
|
||
private double _homeWidth = 6.0;
|
||
|
||
/// <summary>
|
||
/// 点位半径(长轴)
|
||
/// </summary>
|
||
private const double PointRadiusY = 35;
|
||
|
||
/// <summary>
|
||
/// 点位短轴(扁平化比例 0.5)
|
||
/// </summary>
|
||
private const double PointRadiusX = 70;
|
||
|
||
private int _lastFrameNumber = -1;
|
||
private WriteableBitmap _videoBitmap;
|
||
|
||
|
||
/// <summary>
|
||
/// 重要点位索引(0 表示不设置)
|
||
/// </summary>
|
||
private int _keyPointIndex = 0;
|
||
|
||
|
||
/// <summary>
|
||
/// 音乐跳绳二号位索引(0 表示不设置)
|
||
/// </summary>
|
||
private int _musicPoint2Index = 0;
|
||
|
||
#endregion
|
||
|
||
#region 构造函数
|
||
|
||
public MultiJumpRope()
|
||
{
|
||
InitializeComponent();
|
||
SetupDragEvents();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 私有方法
|
||
|
||
/// <summary>
|
||
/// 页面加载完成事件
|
||
/// </summary>
|
||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
LoadPointsFromDatabase();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置拖拽事件
|
||
/// </summary>
|
||
private void SetupDragEvents()
|
||
{
|
||
MainCanvas.MouseMove += MainCanvas_MouseMove;
|
||
MainCanvas.MouseLeftButtonUp += MainCanvas_MouseLeftButtonUp;
|
||
MainCanvas.MouseLeave += MainCanvas_MouseLeave;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据 HomeWidth 计算点位数量
|
||
/// HomeWidth <= 5:5 个点位
|
||
/// 5 < HomeWidth < 7:6 个点位
|
||
/// HomeWidth >= 7:7 个点位
|
||
/// </summary>
|
||
private int CalculatePointCount(double homeWidth)
|
||
{
|
||
if (homeWidth <= 5)
|
||
return 5;
|
||
else if (homeWidth > 5 && homeWidth < 7)
|
||
return 6;
|
||
else
|
||
return 7;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从数据库加载点位数据
|
||
/// </summary>
|
||
private async void LoadPointsFromDatabase()
|
||
{
|
||
try
|
||
{
|
||
var app = (App)Application.Current;
|
||
using var scope = App.AppHost.Services.CreateScope();
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
|
||
// 获取场地宽度配置
|
||
var baseConfig = await db.BasicConfig.FirstOrDefaultAsync(x => x.Code == AppSettings.Code);
|
||
if (baseConfig == null)
|
||
{
|
||
UpdateStatus("未找到相机主机配置");
|
||
return;
|
||
}
|
||
|
||
_homeWidth = baseConfig.HomeWidth;
|
||
//int pointCount = CalculatePointCount(_homeWidth);
|
||
int pointCount = (int)(_homeWidth);
|
||
|
||
// 更新 UI 显示
|
||
//HomeWidthText.Text = _homeWidth.ToString("F1");
|
||
PointCountText.Text = $"点位数量: {pointCount} 个";
|
||
|
||
// 清空现有控件
|
||
ClearPoints();
|
||
|
||
// 获取已保存的点位数据
|
||
var pointsData = await db.GroupPoints.FirstOrDefaultAsync(x => x.Code == AppSettings.Code);
|
||
|
||
if (pointsData != null)
|
||
{
|
||
// 从数据库加载保存的点位
|
||
LoadPointsFromDatabaseData(pointsData, pointCount);
|
||
}
|
||
else
|
||
{
|
||
// 生成默认点位位置
|
||
CreateDefaultPoints(pointCount);
|
||
}
|
||
|
||
var BaseData = await db.BasicConfig.FirstOrDefaultAsync(x => x.Code == AppSettings.Code);
|
||
if (BaseData == null)
|
||
{
|
||
this.ShowError("相机主机地址/IP不能为空。");
|
||
return;
|
||
}
|
||
|
||
var _webcamClient = WebcamClient.CreateRTSP(BaseData.Host, BaseData.UserName, BaseData.Password);
|
||
|
||
//处理抽帧回调
|
||
_webcamClient.OnExtractFrame += this.OnFrameExtracted;
|
||
_webcamClient.StartExtract();//开始抽帧
|
||
|
||
UpdateStatus($"点数据加载成功 - 共 {pointCount} 个点位");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
UpdateStatus($"加载点数据失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private async void OnFrameExtracted(VideoFrame frame)
|
||
{
|
||
if (frame == null) return;
|
||
|
||
// 跳帧:每秒只渲染 10~15 帧,降低 CPU 占用
|
||
if (_lastFrameNumber != -1 && frame.Number - _lastFrameNumber < 2) return;
|
||
_lastFrameNumber = (int)frame.Number;
|
||
|
||
//获得帧二进制流,保存图像、人体识别竺
|
||
var buffer = frame.GetImageBuffer(Yztob.AiSports.Sensors.Things.ImageFormat.Jpeg).ToArray();
|
||
//await File.WriteAllBytesAsync($"./temps/{frame.Number}.jpg", buffer);
|
||
|
||
// === 显示到 WPF ===
|
||
BitmapImage bitmap = null;
|
||
await Task.Run(() =>
|
||
{
|
||
using var ms = new MemoryStream(buffer);
|
||
bitmap = new BitmapImage();
|
||
bitmap.BeginInit();
|
||
bitmap.CacheOption = BitmapCacheOption.OnLoad;
|
||
bitmap.StreamSource = ms;
|
||
bitmap.EndInit();
|
||
bitmap.Freeze(); // 跨线程安全
|
||
});
|
||
|
||
// UI 线程显示
|
||
Application.Current.Dispatcher.Invoke(() =>
|
||
{
|
||
if (videoImage == null) return;
|
||
|
||
if (_videoBitmap == null ||
|
||
_videoBitmap.PixelWidth != bitmap.PixelWidth ||
|
||
_videoBitmap.PixelHeight != bitmap.PixelHeight)
|
||
{
|
||
_videoBitmap = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight,
|
||
96, 96, PixelFormats.Bgra32, null);
|
||
videoImage.Source = _videoBitmap;
|
||
}
|
||
|
||
_videoBitmap.Lock();
|
||
bitmap.CopyPixels(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight),
|
||
_videoBitmap.BackBuffer,
|
||
_videoBitmap.BackBufferStride * bitmap.PixelHeight,
|
||
_videoBitmap.BackBufferStride);
|
||
_videoBitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));
|
||
_videoBitmap.Unlock();
|
||
});
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 清空所有点位控件
|
||
/// </summary>
|
||
private void ClearPoints()
|
||
{
|
||
_points.Clear();
|
||
PointsContainer.ItemsSource = null;
|
||
ConnectionLine.Points.Clear();
|
||
|
||
// 清除画布上除了背景和固定控件外的所有元素
|
||
var elementsToRemove = new List<UIElement>();
|
||
foreach (var child in MainCanvas.Children)
|
||
{
|
||
if (child is Ellipse || child is Border || child is Line)
|
||
{
|
||
var element = child as FrameworkElement;
|
||
if (element?.Name != "ConnectionLine" &&
|
||
element?.Name != "PointsContainer" &&
|
||
element?.Name != "CoordinateDisplay")
|
||
{
|
||
elementsToRemove.Add(element);
|
||
}
|
||
}
|
||
}
|
||
|
||
foreach (var element in elementsToRemove)
|
||
{
|
||
MainCanvas.Children.Remove(element);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从数据库数据加载点位
|
||
/// db.GroupPoints 包含 Point1_X, Point1_Y, Point2_X, Point2_Y 等字段
|
||
/// </summary>
|
||
private void LoadPointsFromDatabaseData(GroupPoints data, int pointCount)
|
||
{
|
||
for (int i = 1; i <= pointCount; i++)
|
||
{
|
||
var point = new JumpRopePoint
|
||
{
|
||
Id = i,
|
||
Index = i
|
||
};
|
||
|
||
// 从数据库读取 Point 类型的属性
|
||
var pointProperty = typeof(GroupPoints).GetProperty($"Point{i}");
|
||
|
||
if (pointProperty != null)
|
||
{
|
||
var dbPoint = pointProperty.GetValue(data);
|
||
if (dbPoint != null)
|
||
{
|
||
// 获取 Point 的 X 和 Y 属性
|
||
var xProp = dbPoint.GetType().GetProperty("X");
|
||
var yProp = dbPoint.GetType().GetProperty("Y");
|
||
|
||
if (xProp != null && yProp != null)
|
||
{
|
||
point.X = (double)(xProp.GetValue(dbPoint) ?? 0);
|
||
point.Y = (double)(yProp.GetValue(dbPoint) ?? 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果坐标为 0,则使用默认值
|
||
if (point.X == 0) point.X = GetDefaultX(i, pointCount);
|
||
if (point.Y == 0) point.Y = GetDefaultY();
|
||
|
||
point.BackgroundColor = i % 2 == 0 ? "#F3F4F6" : "#FFFFFF";
|
||
|
||
_points.Add(point);
|
||
CreatePointControl(point);
|
||
}
|
||
// 加载控制点位索引
|
||
var keyPointProperty = typeof(GroupPoints).GetProperty("KeyPointIndex");
|
||
if (keyPointProperty != null)
|
||
{
|
||
_keyPointIndex = (int)(keyPointProperty.GetValue(data) ?? 0);
|
||
}
|
||
else
|
||
{
|
||
_keyPointIndex = 0;
|
||
}
|
||
|
||
// 加载音乐跳绳二号位位置(从 Point10 字段),并与点位列表对比
|
||
var point10Property = typeof(GroupPoints).GetProperty("Point10");
|
||
if (point10Property != null)
|
||
{
|
||
var dbPoint10 = point10Property.GetValue(data);
|
||
if (dbPoint10 != null)
|
||
{
|
||
var xProp = dbPoint10.GetType().GetProperty("X");
|
||
var yProp = dbPoint10.GetType().GetProperty("Y");
|
||
if (xProp != null && yProp != null)
|
||
{
|
||
var point10X = (double)(xProp.GetValue(dbPoint10) ?? 0);
|
||
var point10Y = (double)(yProp.GetValue(dbPoint10) ?? 0);
|
||
|
||
// 与点位列表对比,找出匹配的点位
|
||
double tolerance = 1.0; // 容差值,允许1像素的误差
|
||
foreach (var point in _points)
|
||
{
|
||
if (Math.Abs(point.X - point10X) < tolerance &&
|
||
Math.Abs(point.Y - point10Y) < tolerance)
|
||
{
|
||
_musicPoint2Index = point.Id;
|
||
UpdateStatus($"音乐跳绳二号位已识别为点位 {point.Id}: X:{point10X:F0} Y:{point10Y:F0}");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
RefreshPointsDataList();
|
||
UpdateConnectionLine();
|
||
RefreshKeyPointComboBox();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建默认点位
|
||
/// </summary>
|
||
private void CreateDefaultPoints(int pointCount)
|
||
{
|
||
for (int i = 1; i <= pointCount; i++)
|
||
{
|
||
var point = new JumpRopePoint
|
||
{
|
||
Id = i,
|
||
Index = i,
|
||
X = GetDefaultX(i, pointCount),
|
||
Y = GetDefaultY(),
|
||
BackgroundColor = i % 2 == 0 ? "#F3F4F6" : "#FFFFFF"
|
||
};
|
||
|
||
_points.Add(point);
|
||
CreatePointControl(point);
|
||
}
|
||
|
||
RefreshPointsDataList();
|
||
UpdateConnectionLine();
|
||
RefreshKeyPointComboBox();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取默认 X 坐标(均匀分布)
|
||
/// </summary>
|
||
private double GetDefaultX(int index, int pointCount)
|
||
{
|
||
double canvasWidth = MainCanvas.ActualWidth > 0 ? MainCanvas.ActualWidth : 1920;
|
||
// 小边距,让第一个点和最后一个点靠近边缘
|
||
double margin = 90;
|
||
double availableWidth = canvasWidth - (margin * 2);
|
||
|
||
// 均匀分布在 margin 和 canvasWidth - margin 之间
|
||
if (pointCount > 1)
|
||
{
|
||
double spacing = availableWidth / (pointCount - 1);
|
||
return margin + (spacing * (index - 1));
|
||
}
|
||
|
||
return canvasWidth / 2;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取默认 Y 坐标(画布中间)
|
||
/// </summary>
|
||
private double GetDefaultY()
|
||
{
|
||
double canvasHeight = MainCanvas.ActualHeight > 0 ? MainCanvas.ActualHeight : 800;
|
||
return canvasHeight / 2;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建点位控件
|
||
/// </summary>
|
||
private void CreatePointControl(JumpRopePoint point)
|
||
{
|
||
// 创建外圈光晕
|
||
var glow = new Ellipse
|
||
{
|
||
Width = (PointRadiusX + 10) * 2,
|
||
Height = (PointRadiusY + 10) * 2,
|
||
Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#3434D399")),
|
||
Opacity = 0.5
|
||
};
|
||
Canvas.SetLeft(glow, point.X - glow.Width / 2);
|
||
Canvas.SetTop(glow, point.Y - glow.Height / 2);
|
||
Canvas.SetZIndex(glow, 1);
|
||
|
||
// 创建主椭圆
|
||
var ellipse = new Ellipse
|
||
{
|
||
Name = $"PointEllipse_{point.Id}",
|
||
Width = PointRadiusX * 2,
|
||
Height = PointRadiusY * 2,
|
||
Fill = new LinearGradientBrush
|
||
{
|
||
StartPoint = new Point(0.5, 0),
|
||
EndPoint = new Point(0.5, 1),
|
||
GradientStops = new GradientStopCollection
|
||
{
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#34D399"), 0),
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#059669"), 1)
|
||
}
|
||
},
|
||
Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#059669")),
|
||
StrokeThickness = 2,
|
||
//Cursor = Cursors.SizeNS // 垂直方向光标
|
||
Cursor = Cursors.SizeAll
|
||
};
|
||
|
||
// 绑定数据
|
||
ellipse.DataContext = point;
|
||
ellipse.Tag = point;
|
||
|
||
// 设置位置
|
||
Canvas.SetLeft(ellipse, point.X - PointRadiusX);
|
||
Canvas.SetTop(ellipse, point.Y - PointRadiusY);
|
||
Canvas.SetZIndex(ellipse, 10);
|
||
|
||
// 添加鼠标事件
|
||
ellipse.MouseLeftButtonDown += Point_MouseLeftButtonDown;
|
||
ellipse.MouseMove += Point_MouseMove; // 新增
|
||
ellipse.MouseLeftButtonUp += Point_MouseLeftButtonUp; // 新增
|
||
ellipse.MouseEnter += Point_MouseEnter;
|
||
ellipse.MouseLeave += Point_MouseLeave;
|
||
|
||
// 创建标签
|
||
var label = new TextBlock
|
||
{
|
||
Text = $"P{point.Id}",
|
||
Foreground = Brushes.White,
|
||
FontSize = 16,
|
||
FontWeight = FontWeights.Bold,
|
||
HorizontalAlignment = HorizontalAlignment.Center,
|
||
VerticalAlignment = VerticalAlignment.Center
|
||
};
|
||
|
||
var labelBorder = new Border
|
||
{
|
||
Child = label,
|
||
Name = $"label{point.Id}",
|
||
|
||
Width = PointRadiusX * 2,
|
||
Height = PointRadiusY * 2,
|
||
Background = Brushes.Transparent,
|
||
IsHitTestVisible = false // 让鼠标事件穿透到下层的椭圆
|
||
};
|
||
Canvas.SetLeft(labelBorder, point.X - PointRadiusX);
|
||
Canvas.SetTop(labelBorder, point.Y - PointRadiusY);
|
||
Canvas.SetZIndex(labelBorder, 11);
|
||
|
||
// 创建 X 轴引导线(垂直虚线)
|
||
var xGuideLine = new Line
|
||
{
|
||
Name = $"XGuideLine_{point.Id}",
|
||
X1 = point.X,
|
||
Y1 = 0,
|
||
X2 = point.X,
|
||
Y2 = MainCanvas.ActualHeight > 0 ? MainCanvas.ActualHeight : 800,
|
||
Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#6366F1")),
|
||
StrokeThickness = 1,
|
||
StrokeDashArray = new DoubleCollection { 5, 5 },
|
||
Opacity = 0.4
|
||
};
|
||
Canvas.SetZIndex(xGuideLine, 2);
|
||
|
||
// 创建 Y 轴引导线(水平虚线)
|
||
var yGuideLine = new Line
|
||
{
|
||
Name = $"YGuideLine_{point.Id}",
|
||
X1 = 0,
|
||
Y1 = point.Y,
|
||
X2 = MainCanvas.ActualWidth > 0 ? MainCanvas.ActualWidth : 1920,
|
||
Y2 = point.Y,
|
||
Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#10B981")),
|
||
StrokeThickness = 1,
|
||
StrokeDashArray = new DoubleCollection { 5, 5 },
|
||
Opacity = 0.4
|
||
};
|
||
Canvas.SetZIndex(yGuideLine, 2);
|
||
|
||
// 添加到画布
|
||
MainCanvas.Children.Add(glow);
|
||
MainCanvas.Children.Add(xGuideLine);
|
||
MainCanvas.Children.Add(yGuideLine);
|
||
MainCanvas.Children.Add(ellipse);
|
||
MainCanvas.Children.Add(labelBorder);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新右侧点位数据列表
|
||
/// </summary>
|
||
private void RefreshPointsDataList()
|
||
{
|
||
var items = _points.Select((point, index) => new
|
||
{
|
||
PointLabel = point.Id.ToString(),
|
||
CoordinateText = $"X:{Math.Round(point.X)} Y:{Math.Round(point.Y)}",
|
||
BackgroundColor = point.BackgroundColor
|
||
}).ToList();
|
||
|
||
PointsDataList.ItemsSource = items;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新控制点位下拉框
|
||
/// </summary>
|
||
private void RefreshKeyPointComboBox()
|
||
{
|
||
// 保存当前选择
|
||
int previousSelection = KeyPointComboBox.SelectedIndex;
|
||
int previousSelection2 = MusicPointBox2.SelectedIndex;
|
||
|
||
// 清除并重新填充选项
|
||
KeyPointComboBox.Items.Clear();
|
||
MusicPointBox2.Items.Clear();
|
||
|
||
// 为每个 ComboBox 创建独立的 "不设置" 选项
|
||
var noneItem1 = new ComboBoxItem { Content = "不设置", Tag = 0 };
|
||
var noneItem2 = new ComboBoxItem { Content = "不设置", Tag = 0 };
|
||
var noneItem3 = new ComboBoxItem { Content = "不设置", Tag = 0 };
|
||
|
||
KeyPointComboBox.Items.Add(noneItem1);
|
||
MusicPointBox2.Items.Add(noneItem3);
|
||
|
||
// 添加所有点位选项(为每个 ComboBox 创建独立实例)
|
||
foreach (var point in _points)
|
||
{
|
||
var item1 = new ComboBoxItem { Content = $"点位 {point.Id}", Tag = point.Id };
|
||
var item2 = new ComboBoxItem { Content = $"点位 {point.Id}", Tag = point.Id };
|
||
var item3 = new ComboBoxItem { Content = $"点位 {point.Id}", Tag = point.Id };
|
||
|
||
KeyPointComboBox.Items.Add(item1);
|
||
MusicPointBox2.Items.Add(item3);
|
||
}
|
||
|
||
// 恢复选择或默认选择
|
||
if (previousSelection > 0 && previousSelection <= _points.Count)
|
||
{
|
||
KeyPointComboBox.SelectedIndex = previousSelection;
|
||
}
|
||
else if (_keyPointIndex > 0)
|
||
{
|
||
// 恢复保存的控制点位选择
|
||
int comboIndex = _points.FindIndex(p => p.Id == _keyPointIndex);
|
||
if (comboIndex >= 0)
|
||
{
|
||
KeyPointComboBox.SelectedIndex = comboIndex + 1; // +1 因为第一个是"不设置"
|
||
}
|
||
else
|
||
{
|
||
KeyPointComboBox.SelectedIndex = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
KeyPointComboBox.SelectedIndex = 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
// 恢复音乐跳绳二号位选择
|
||
if (previousSelection2 > 0 && previousSelection2 <= _points.Count)
|
||
{
|
||
MusicPointBox2.SelectedIndex = previousSelection2;
|
||
}
|
||
else if (_musicPoint2Index > 0)
|
||
{
|
||
int comboIndex = _points.FindIndex(p => p.Id == _musicPoint2Index);
|
||
if (comboIndex >= 0)
|
||
{
|
||
MusicPointBox2.SelectedIndex = comboIndex + 1;
|
||
}
|
||
else
|
||
{
|
||
MusicPointBox2.SelectedIndex = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MusicPointBox2.SelectedIndex = 0;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 控制点位选择改变事件
|
||
/// </summary>
|
||
private void KeyPointComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||
{
|
||
if (KeyPointComboBox.SelectedItem is ComboBoxItem selectedItem)
|
||
{
|
||
_keyPointIndex = (int)(selectedItem.Tag ?? 0);
|
||
|
||
if (_keyPointIndex > 0)
|
||
{
|
||
UpdateStatus($"已设置点位 {_keyPointIndex} 为控制点位");
|
||
HighlightKeyPoint(_keyPointIndex);
|
||
}
|
||
else
|
||
{
|
||
UpdateStatus("已取消控制点位设置");
|
||
ResetAllPointsHighlight();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 音乐跳绳二号位选择改变事件
|
||
/// </summary>
|
||
private void MusicPointBox2_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||
{
|
||
if (MusicPointBox2.SelectedItem is ComboBoxItem selectedItem)
|
||
{
|
||
_musicPoint2Index = (int)(selectedItem.Tag ?? 0);
|
||
|
||
if (_musicPoint2Index > 0)
|
||
{
|
||
UpdateStatus($"已设置点位 {_musicPoint2Index} 为音乐跳绳二号位");
|
||
HighlightMusicPoint2(_musicPoint2Index);
|
||
}
|
||
else
|
||
{
|
||
UpdateStatus("已取消音乐跳绳二号位设置");
|
||
ResetAllPointsHighlight();
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 高亮显示控制点位
|
||
/// </summary>
|
||
private void HighlightKeyPoint(int pointId)
|
||
{
|
||
// 重置所有点位样式
|
||
ResetAllPointsHighlight();
|
||
|
||
// 高亮控制点位
|
||
var ellipse = MainCanvas.Children
|
||
.OfType<Ellipse>()
|
||
.FirstOrDefault(e => e.Name == $"PointEllipse_{pointId}");
|
||
|
||
if (ellipse != null)
|
||
{
|
||
ellipse.Fill = new LinearGradientBrush
|
||
{
|
||
StartPoint = new Point(0.5, 0),
|
||
EndPoint = new Point(0.5, 1),
|
||
GradientStops = new GradientStopCollection
|
||
{
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#EF4444"), 0),
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#DC2626"), 1)
|
||
}
|
||
};
|
||
ellipse.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#B91C1C"));
|
||
ellipse.StrokeThickness = 3;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 高亮显示音乐跳绳二号位
|
||
/// </summary>
|
||
private void HighlightMusicPoint2(int pointId)
|
||
{
|
||
// 重置所有点位样式
|
||
ResetAllPointsHighlight();
|
||
|
||
// 高亮音乐跳绳二号位(使用紫色区分)
|
||
var ellipse = MainCanvas.Children
|
||
.OfType<Ellipse>()
|
||
.FirstOrDefault(e => e.Name == $"PointEllipse_{pointId}");
|
||
|
||
if (ellipse != null)
|
||
{
|
||
ellipse.Fill = new LinearGradientBrush
|
||
{
|
||
StartPoint = new Point(0.5, 0),
|
||
EndPoint = new Point(0.5, 1),
|
||
GradientStops = new GradientStopCollection
|
||
{
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#8B5CF6"), 0),
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#7C3AED"), 1)
|
||
}
|
||
};
|
||
ellipse.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#6D28D9"));
|
||
ellipse.StrokeThickness = 3;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置所有点位的高亮样式
|
||
/// </summary>
|
||
private void ResetAllPointsHighlight()
|
||
{
|
||
foreach (var point in _points)
|
||
{
|
||
var ellipse = MainCanvas.Children
|
||
.OfType<Ellipse>()
|
||
.FirstOrDefault(e => e.Name == $"PointEllipse_{point.Id}");
|
||
|
||
if (ellipse != null)
|
||
{
|
||
ellipse.Fill = new LinearGradientBrush
|
||
{
|
||
StartPoint = new Point(0.5, 0),
|
||
EndPoint = new Point(0.5, 1),
|
||
GradientStops = new GradientStopCollection
|
||
{
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#34D399"), 0),
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#059669"), 1)
|
||
}
|
||
};
|
||
ellipse.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#059669"));
|
||
ellipse.StrokeThickness = 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新连接线
|
||
/// </summary>
|
||
private void UpdateConnectionLine()
|
||
{
|
||
var points = new PointCollection();
|
||
foreach (var point in _points.OrderBy(p => p.X))
|
||
{
|
||
points.Add(new Point(point.X, point.Y));
|
||
}
|
||
ConnectionLine.Points = points;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 鼠标事件处理
|
||
|
||
/// <summary>
|
||
/// 点位鼠标按下事件
|
||
/// </summary>
|
||
private void Point_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||
{
|
||
_isDragging = true;
|
||
_draggedEllipse = sender as Ellipse;
|
||
//_dragStartY = e.GetPosition(MainCanvas).Y;
|
||
|
||
//if (_draggedEllipse.Tag is JumpRopePoint point)
|
||
//{
|
||
// _originalY = point.Y;
|
||
//}
|
||
|
||
// 现在:同时捕获X和Y坐标
|
||
var currentPos = e.GetPosition(MainCanvas);
|
||
_dragStartX = currentPos.X;
|
||
_dragStartY = currentPos.Y;
|
||
if (_draggedEllipse.Tag is JumpRopePoint point)
|
||
{
|
||
_originalX = point.X;
|
||
_originalY = point.Y;
|
||
}
|
||
|
||
|
||
_draggedEllipse.CaptureMouse();
|
||
|
||
// 提升 Z 索引
|
||
Canvas.SetZIndex(_draggedEllipse, 100);
|
||
|
||
// 改变颜色表示选中状态
|
||
_draggedEllipse.Fill = new LinearGradientBrush
|
||
{
|
||
StartPoint = new Point(0.5, 0),
|
||
EndPoint = new Point(0.5, 1),
|
||
GradientStops = new GradientStopCollection
|
||
{
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#FBBF24"), 0),
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#D97706"), 1)
|
||
}
|
||
};
|
||
_draggedEllipse.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#D97706"));
|
||
|
||
UpdateStatus($"正在调整 P{(_draggedEllipse.Tag as JumpRopePoint)?.Id} 点的 Y 坐标");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 点位鼠标移动事件(在椭圆上直接处理)
|
||
/// </summary>
|
||
private void Point_MouseMove(object sender, MouseEventArgs e)
|
||
{
|
||
if (_isDragging && _draggedEllipse != null)
|
||
{
|
||
var currentPos = e.GetPosition(MainCanvas);
|
||
var deltaY = currentPos.Y - _dragStartY;
|
||
var deltaX = currentPos.X - _dragStartX;
|
||
if (_draggedEllipse.Tag is JumpRopePoint point)
|
||
{
|
||
// 同时计算X和Y轴移动
|
||
double newY = _originalY + deltaY;
|
||
double newX = _originalX + deltaX;
|
||
|
||
// 限制在画布范围内
|
||
double canvasHeight = MainCanvas.ActualHeight > 0 ? MainCanvas.ActualHeight : 1080;
|
||
newY = Math.Max(PointRadiusY, Math.Min(canvasHeight - PointRadiusY, newY));
|
||
|
||
double canvasWidth = MainCanvas.ActualWidth > 0 ? MainCanvas.ActualWidth : 1920;
|
||
newX = Math.Max(PointRadiusX, Math.Min(canvasWidth - PointRadiusX, newX));
|
||
|
||
// 更新点位数据
|
||
point.Y = newY;
|
||
point.X = newX;
|
||
|
||
// 更新椭圆位置
|
||
Canvas.SetTop(_draggedEllipse, newY - PointRadiusY);
|
||
Canvas.SetLeft(_draggedEllipse, newX - PointRadiusX);
|
||
// 更新光晕位置
|
||
UpdateGlowPosition(point);
|
||
|
||
// 更新标签位置
|
||
UpdateLabelPosition(point);
|
||
|
||
// 更新引导线
|
||
|
||
UpdateGuideLines(point, canvasWidth, canvasHeight);
|
||
|
||
// 更新连接线
|
||
UpdateConnectionLine();
|
||
|
||
// 更新坐标显示
|
||
UpdateCoordinateDisplay(new Point(point.X, newY), $"P{point.Id}");
|
||
|
||
// 更新右侧数据列表
|
||
RefreshPointsDataList();
|
||
|
||
// 重置拖动起始位置
|
||
_dragStartX = currentPos.X;
|
||
_dragStartY = currentPos.Y;
|
||
_originalX = newX;
|
||
_originalY = newY;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 点位鼠标释放事件(在椭圆上直接处理)
|
||
/// </summary>
|
||
private void Point_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||
{
|
||
if (_isDragging)
|
||
{
|
||
_isDragging = false;
|
||
if (_draggedEllipse != null)
|
||
{
|
||
_draggedEllipse.ReleaseMouseCapture();
|
||
Canvas.SetZIndex(_draggedEllipse, 10);
|
||
|
||
// 恢复颜色
|
||
_draggedEllipse.Fill = new LinearGradientBrush
|
||
{
|
||
StartPoint = new Point(0.5, 0),
|
||
EndPoint = new Point(0.5, 1),
|
||
GradientStops = new GradientStopCollection
|
||
{
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#34D399"), 0),
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#059669"), 1)
|
||
}
|
||
};
|
||
_draggedEllipse.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#059669"));
|
||
|
||
if (_draggedEllipse.Tag is JumpRopePoint point)
|
||
{
|
||
UpdateStatus($"P{point.Id} 点位置已调整为 Y = {Math.Round(point.Y)}");
|
||
}
|
||
|
||
_draggedEllipse = null;
|
||
}
|
||
|
||
// 隐藏坐标显示
|
||
CoordinateDisplay.Visibility = Visibility.Collapsed;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新光晕位置
|
||
/// </summary>
|
||
private void UpdateGlowPosition(JumpRopePoint point)
|
||
{
|
||
// 找到对应的椭圆
|
||
var ellipse = MainCanvas.Children
|
||
.OfType<Ellipse>()
|
||
.FirstOrDefault(e => e.Name == $"PointEllipse_{point.Id}");
|
||
|
||
if (ellipse != null)
|
||
{
|
||
// 光晕宽度
|
||
double glowWidth = (PointRadiusX + 10) * 2;
|
||
double glowHeight = (PointRadiusY + 10) * 2;
|
||
double expectedLeft = point.X - glowWidth / 2;
|
||
|
||
// 查找光晕(根据尺寸和位置判断)
|
||
var glow = MainCanvas.Children
|
||
.OfType<Ellipse>()
|
||
.FirstOrDefault(e =>
|
||
{
|
||
var left = Canvas.GetLeft(e);
|
||
var top = Canvas.GetTop(e);
|
||
return e.Width == glowWidth &&
|
||
e.Height == glowHeight &&
|
||
Math.Abs(left - expectedLeft) < 10;
|
||
});
|
||
|
||
if (glow != null)
|
||
{
|
||
Canvas.SetLeft(glow, point.X - glowWidth / 2);
|
||
Canvas.SetTop(glow, point.Y - glowHeight / 2);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新标签位置
|
||
/// </summary>
|
||
private void UpdateLabelPosition(JumpRopePoint point)
|
||
{
|
||
|
||
var labelBorder = MainCanvas.Children.OfType<Border>().FirstOrDefault(e => e.Name == $"label{point.Id}");
|
||
|
||
if (labelBorder != null)
|
||
{
|
||
Canvas.SetLeft(labelBorder, point.X - PointRadiusX);
|
||
Canvas.SetTop(labelBorder, point.Y - PointRadiusY);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新引导线
|
||
/// </summary>
|
||
private void UpdateGuideLines(JumpRopePoint point, double canvasWidth, double canvasHeight)
|
||
{
|
||
// 更新 X 轴引导线(垂直线)
|
||
var xGuideLine = MainCanvas.Children
|
||
.OfType<Line>()
|
||
.FirstOrDefault(l => l.Name == $"XGuideLine_{point.Id}");
|
||
|
||
if (xGuideLine != null)
|
||
{
|
||
xGuideLine.X1 = point.X;
|
||
xGuideLine.X2 = point.X;
|
||
xGuideLine.Y1 = 0;
|
||
xGuideLine.Y2 = canvasHeight;
|
||
}
|
||
|
||
// 更新 Y 轴引导线(水平线)
|
||
var yGuideLine = MainCanvas.Children
|
||
.OfType<Line>()
|
||
.FirstOrDefault(l => l.Name == $"YGuideLine_{point.Id}");
|
||
|
||
if (yGuideLine != null)
|
||
{
|
||
yGuideLine.X1 = 0;
|
||
yGuideLine.X2 = canvasWidth;
|
||
yGuideLine.Y1 = point.Y;
|
||
yGuideLine.Y2 = point.Y;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 画布鼠标移动事件
|
||
/// </summary>
|
||
private void MainCanvas_MouseMove(object sender, MouseEventArgs e)
|
||
{
|
||
if (_isDragging && _draggedEllipse != null)
|
||
{
|
||
var currentY = e.GetPosition(MainCanvas).Y;
|
||
var deltaY = currentY - _dragStartY;
|
||
|
||
if (_draggedEllipse.Tag is JumpRopePoint point)
|
||
{
|
||
// 计算新位置(只允许 Y 轴移动)
|
||
double newY = _originalY + deltaY;
|
||
|
||
// 限制在画布范围内
|
||
double canvasHeight = MainCanvas.ActualHeight > 0 ? MainCanvas.ActualHeight : 800;
|
||
newY = Math.Max(PointRadiusY, Math.Min(canvasHeight - PointRadiusY, newY));
|
||
|
||
// 更新点位数据
|
||
point.Y = newY;
|
||
|
||
// 更新椭圆位置
|
||
Canvas.SetTop(_draggedEllipse, newY - PointRadiusY);
|
||
|
||
// 更新连接线
|
||
UpdateConnectionLine();
|
||
|
||
// 更新坐标显示
|
||
UpdateCoordinateDisplay(new Point(point.X, newY), $"P{point.Id}");
|
||
|
||
// 更新右侧数据列表
|
||
RefreshPointsDataList();
|
||
|
||
// 重置拖动起始位置
|
||
_dragStartY = currentY;
|
||
_originalY = newY;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 画布鼠标释放事件
|
||
/// </summary>
|
||
private void MainCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||
{
|
||
if (_isDragging)
|
||
{
|
||
_isDragging = false;
|
||
if (_draggedEllipse != null)
|
||
{
|
||
_draggedEllipse.ReleaseMouseCapture();
|
||
Canvas.SetZIndex(_draggedEllipse, 10);
|
||
|
||
// 恢复颜色
|
||
_draggedEllipse.Fill = new LinearGradientBrush
|
||
{
|
||
StartPoint = new Point(0.5, 0),
|
||
EndPoint = new Point(0.5, 1),
|
||
GradientStops = new GradientStopCollection
|
||
{
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#34D399"), 0),
|
||
new GradientStop((Color)ColorConverter.ConvertFromString("#059669"), 1)
|
||
}
|
||
};
|
||
_draggedEllipse.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#059669"));
|
||
|
||
if (_draggedEllipse.Tag is JumpRopePoint point)
|
||
{
|
||
UpdateStatus($"P{point.Id} 点位置已调整为 Y = {Math.Round(point.Y)}");
|
||
}
|
||
|
||
_draggedEllipse = null;
|
||
}
|
||
|
||
// 隐藏坐标显示
|
||
CoordinateDisplay.Visibility = Visibility.Collapsed;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 画布鼠标离开事件
|
||
/// </summary>
|
||
private void MainCanvas_MouseLeave(object sender, MouseEventArgs e)
|
||
{
|
||
if (_isDragging)
|
||
{
|
||
MainCanvas_MouseLeftButtonUp(sender, e);
|
||
}
|
||
}
|
||
|
||
private void MainCanvas_MouseLeftButtonUp(object sender, MouseEventArgs e)
|
||
{
|
||
throw new NotImplementedException();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 鼠标进入点位
|
||
/// </summary>
|
||
private void Point_MouseEnter(object sender, MouseEventArgs e)
|
||
{
|
||
var ellipse = sender as Ellipse;
|
||
ellipse.Opacity = 0.9;
|
||
|
||
// 显示坐标提示
|
||
if (ellipse.Tag is JumpRopePoint point)
|
||
{
|
||
var position = new Point(point.X, point.Y);
|
||
UpdateCoordinateDisplay(position, $"P{point.Id}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 鼠标离开点位
|
||
/// </summary>
|
||
private void Point_MouseLeave(object sender, MouseEventArgs e)
|
||
{
|
||
var ellipse = sender as Ellipse;
|
||
ellipse.Opacity = 1.0;
|
||
|
||
if (!_isDragging)
|
||
{
|
||
CoordinateDisplay.Visibility = Visibility.Collapsed;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新坐标显示
|
||
/// </summary>
|
||
private void UpdateCoordinateDisplay(System.Windows.Point position, string pointName)
|
||
{
|
||
CoordinateDisplay.Content = $"{pointName}: ({position.X:F0}, {position.Y:F0})";
|
||
CoordinateDisplay.Margin = new Thickness(position.X + 15, position.Y - 80, 0, 0);
|
||
CoordinateDisplay.Visibility = Visibility.Visible;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 按钮事件处理
|
||
|
||
/// <summary>
|
||
/// 加载点数据按钮点击事件
|
||
/// </summary>
|
||
private void LoadPointsButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
LoadPointsFromDatabase();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存点数据按钮点击事件
|
||
/// </summary>
|
||
private void SavePointsButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
SavePointsToDatabase();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置点数据按钮点击事件
|
||
/// </summary>
|
||
private void ResetPointsButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
var result = MessageBox.Show(
|
||
"确定要将所有点位重置为默认位置吗?",
|
||
"确认重置",
|
||
MessageBoxButton.YesNo,
|
||
MessageBoxImage.Question);
|
||
|
||
if (result == MessageBoxResult.Yes)
|
||
{
|
||
ResetToDefault();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回首页按钮点击事件
|
||
/// </summary>
|
||
private void Label_MouseDown(object sender, RoutedEventArgs e)
|
||
{
|
||
var mainWin = Application.Current.MainWindow as Main;
|
||
var newPage = new Home();
|
||
mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 保存和重置方法
|
||
|
||
/// <summary>
|
||
/// 保存点位数据到数据库
|
||
/// </summary>
|
||
private void SavePointsToDatabase()
|
||
{
|
||
try
|
||
{
|
||
var app = (App)Application.Current;
|
||
using var scope = App.AppHost.Services.CreateScope();
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
|
||
var pointsData = db.GroupPoints.FirstOrDefault(x => x.Code == AppSettings.Code);
|
||
|
||
if (pointsData == null)
|
||
{
|
||
pointsData = new GroupPoints { Code = AppSettings.Code };
|
||
db.GroupPoints.Add(pointsData);
|
||
}
|
||
|
||
// 获取 Point 类型(支持 System.Drawing.Point 或 System.Windows.Point)
|
||
var pointType = Type.GetType("System.Windows.Point, WindowsBase");
|
||
|
||
if (pointType != null)
|
||
{
|
||
foreach (var point in _points)
|
||
{
|
||
var pointProperty = typeof(GroupPoints).GetProperty($"Point{point.Id}");
|
||
|
||
if (pointProperty != null)
|
||
{
|
||
// 创建 Point 实例并保存
|
||
var pointInstance = Activator.CreateInstance(pointType, point.X, point.Y);
|
||
var pointNew = new AiSportsMicrospaceDB.Entities.Point
|
||
{
|
||
X = point.X,
|
||
Y = point.Y
|
||
};
|
||
pointProperty.SetValue(pointsData, pointNew);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 保存重要点位索引
|
||
var keyPointProperty = typeof(GroupPoints).GetProperty("KeyPointIndex");
|
||
var controlPoint = typeof(GroupPoints).GetProperty("ControlPoint");
|
||
var controlPointNew = new AiSportsMicrospaceDB.Entities.Point
|
||
{
|
||
X = _points[_keyPointIndex - 1].X,
|
||
Y = _points[_keyPointIndex - 1].Y
|
||
};
|
||
if (keyPointProperty != null)
|
||
{
|
||
keyPointProperty.SetValue(pointsData, _keyPointIndex);
|
||
controlPoint.SetValue(pointsData, controlPointNew);
|
||
}
|
||
|
||
// 保存音乐跳绳二号位位置到 Point10 字段
|
||
if (_musicPoint2Index > 0 && _musicPoint2Index <= _points.Count)
|
||
{
|
||
var point10Property = typeof(GroupPoints).GetProperty("Point10");
|
||
if (point10Property != null)
|
||
{
|
||
var musicPoint2New = new AiSportsMicrospaceDB.Entities.Point
|
||
{
|
||
X = _points[_musicPoint2Index - 1].X,
|
||
Y = _points[_musicPoint2Index - 1].Y
|
||
};
|
||
point10Property.SetValue(pointsData, musicPoint2New);
|
||
}
|
||
}
|
||
|
||
db.SaveChanges();
|
||
UpdateStatus("点数据保存成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
UpdateStatus($"保存点数据失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置为默认位置
|
||
/// </summary>
|
||
private void ResetToDefault()
|
||
{
|
||
try
|
||
{
|
||
var app = (App)Application.Current;
|
||
using var scope = App.AppHost.Services.CreateScope();
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
|
||
// 删除现有的点位数据
|
||
var existingData = db.GroupPoints.FirstOrDefault(x => x.Code == AppSettings.Code);
|
||
if (existingData != null)
|
||
{
|
||
db.GroupPoints.Remove(existingData);
|
||
db.SaveChanges();
|
||
}
|
||
|
||
// 重新生成默认点位
|
||
int pointCount = CalculatePointCount(_homeWidth);
|
||
CreateDefaultPoints(pointCount);
|
||
|
||
UpdateStatus("已重置为默认点位置");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
UpdateStatus($"重置失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新状态栏文本
|
||
/// </summary>
|
||
private void UpdateStatus(string message)
|
||
{
|
||
StatusText.Text = $"{DateTime.Now:HH:mm:ss} - {message}";
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 跳绳点位数据模型
|
||
/// </summary>
|
||
public class JumpRopePoint
|
||
{
|
||
/// <summary>
|
||
/// 点位编号 (1-7)
|
||
/// </summary>
|
||
public int Id { get; set; }
|
||
|
||
/// <summary>
|
||
/// 索引
|
||
/// </summary>
|
||
public int Index { get; set; }
|
||
|
||
/// <summary>
|
||
/// X 坐标(固定不可移动)
|
||
/// </summary>
|
||
public double X { get; set; }
|
||
|
||
/// <summary>
|
||
/// Y 坐标(可拖动调整)
|
||
/// </summary>
|
||
public double Y { get; set; }
|
||
|
||
/// <summary>
|
||
/// 背景颜色(用于列表显示)
|
||
/// </summary>
|
||
public string BackgroundColor { get; set; }
|
||
}
|
||
}
|