385 lines
14 KiB
C#
385 lines
14 KiB
C#
using AiSportsMicrospaceDB.DBContext;
|
||
using AiSportsMicrospaceDB.Entities;
|
||
using Common;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Net.NetworkInformation;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Input;
|
||
using System.Windows.Threading;
|
||
using Views.JumpLong;
|
||
using Views.JumpRope;
|
||
using Views.SquatFu;
|
||
using Wpf_AiSportsMicrospace.Common;
|
||
using Wpf_AiSportsMicrospace.Enum;
|
||
using Wpf_AiSportsMicrospace.MyUserControl;
|
||
using Wpf_AiSportsMicrospace.Views;
|
||
using Wpf_AiSportsMicrospace.Views.JumpRope;
|
||
using Yztob.AiSports.Inferences.Things;
|
||
namespace Wpf_AiSportsMicrospace
|
||
{
|
||
/// <summary>
|
||
/// Home.xaml 的交互逻辑
|
||
/// </summary>
|
||
public partial class Home : UserControl
|
||
{
|
||
public static Uri loadingImage = new Uri("pack://application:,,,/Resources/Img/Album/1.gif");
|
||
public static Uri countDownGif = new Uri("pack://application:,,,/Resources/Img/gif/time_3.gif");
|
||
private int _adminClickCount = 0;
|
||
private readonly DispatcherTimer _resetTimer;
|
||
private Main _mainWin => Application.Current.MainWindow as Main;
|
||
|
||
public Home()
|
||
{
|
||
InitializeComponent();
|
||
// 初始化隐藏按钮点击计数重置定时器(3 秒无操作则重置计数)
|
||
_resetTimer = new DispatcherTimer
|
||
{
|
||
Interval = TimeSpan.FromSeconds(3)
|
||
};
|
||
_resetTimer.Tick += (s, e) =>
|
||
{
|
||
_adminClickCount = 0;
|
||
_resetTimer.Stop();
|
||
};
|
||
// --------------------- CoverFlow 加载 ---------------------
|
||
coverFlow.Images.Add(new CoverFlowItem
|
||
{
|
||
ImageUri = GetResourceUri("test_img/test_rope.png"),
|
||
ProgressColor1 = "#215bc7",
|
||
ProgressColor2 = "#fc640e"
|
||
});
|
||
coverFlow.Images.Add(new CoverFlowItem
|
||
{
|
||
ImageUri = GetResourceUri("play_img/play_music.png"),
|
||
ProgressColor1 = "#e73d42",
|
||
ProgressColor2 = "#fd8212"
|
||
});
|
||
coverFlow.Images.Add(new CoverFlowItem
|
||
{
|
||
ImageUri = GetResourceUri("Album/home_history.png"),
|
||
ProgressColor1 = "#e73d42",
|
||
ProgressColor2 = "#215bc7"
|
||
});
|
||
|
||
// 默认选中第3张
|
||
coverFlow.SelectedIndex = 0;
|
||
Loaded += Window_Loaded;
|
||
Unloaded += Home_Unloaded;
|
||
Load_Base();
|
||
Utils.PlayBackgroundMusic("homeprojectselected.mp3", true);
|
||
|
||
}
|
||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||
|
||
if (_mainWin.WebcamClient == null)
|
||
{
|
||
//HandyControl.Controls.MessageBox.Show("摄像头网络异常,请重新连接!");
|
||
return;
|
||
}
|
||
|
||
_mainWin.WebcamClient.StartExtract();
|
||
Utils.PreloadGifs();
|
||
}
|
||
private void Home_Unloaded(object sender, RoutedEventArgs e)
|
||
{
|
||
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||
}
|
||
private bool IsGestureActive = true; // 标记手势识别是否有效
|
||
private void OnHumanFrameUpdated(object sender, List<Human> humans)
|
||
{
|
||
if (!IsGestureActive) return; // 手势识别已停止,直接返回
|
||
|
||
var human = humans.FirstOrDefault();
|
||
if (human == null) return;
|
||
|
||
// 检测挥手动作
|
||
var wavingaction = _mainWin.SportOperate.VerifyRightWavingAction(humans);
|
||
|
||
switch (wavingaction)
|
||
{
|
||
case (int)WavingAction.LeftWave: // 左手挥动
|
||
Application.Current.Dispatcher.BeginInvoke(() => coverFlow.SlideRight());
|
||
break;
|
||
|
||
case (int)WavingAction.RightWave: // 右手挥动
|
||
Application.Current.Dispatcher.BeginInvoke(() => coverFlow.SlideLeft());
|
||
break;
|
||
|
||
case (int)WavingAction.FirstHand: // 举手开始
|
||
Application.Current.Dispatcher.BeginInvoke(() => coverFlow.StartSelectedProgress());
|
||
break;
|
||
|
||
case (int)WavingAction.Raising: // 举手中,实时更新进度
|
||
break;
|
||
|
||
case (int)WavingAction.RaiseHand: // 举手完成
|
||
coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted;
|
||
|
||
// 设置标记,停止后续手势识别
|
||
IsGestureActive = false;
|
||
break;
|
||
|
||
default: // 没有动作 → 取消进度
|
||
Application.Current.Dispatcher.BeginInvoke(() => coverFlow.CancelSelectedProgress());
|
||
break;
|
||
}
|
||
}
|
||
|
||
private void CoverFlow_ProgressCompleted(CoverFlowItem item)
|
||
{
|
||
// 停止抽帧线程/释放资源
|
||
try
|
||
{
|
||
//_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||
//_mainWin.WebcamClient.StopExtract();
|
||
RouterGoNew();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"停止抽帧异常: {ex.Message}");
|
||
}
|
||
}
|
||
//测试点击
|
||
private void GoNew(object sender, MouseButtonEventArgs e)
|
||
{
|
||
RouterGoNew();
|
||
}
|
||
|
||
//跳转二级页面
|
||
private void RouterGoNew()
|
||
{
|
||
// 跳转逻辑(如导航到新页面并传递参数)
|
||
// 例如:RaiseEvent、调用外部委托、或使用导航框架
|
||
var mainWin = Application.Current.MainWindow as Main;
|
||
|
||
if (coverFlow.SelectedIndex == 0)
|
||
{
|
||
var newPage = new GroupJumpRope();
|
||
//mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||
|
||
//var newPage = new BambooDragonfly();
|
||
//var newPage = new WhackAMole();
|
||
mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||
}
|
||
else if (coverFlow.SelectedIndex == 1)
|
||
{
|
||
var newPage = new MusicJumpRope();
|
||
mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||
}
|
||
else
|
||
{
|
||
//var newPage = new TrainingRecords();
|
||
//var newPage = new WhackAMole();
|
||
var newPage = new StandingLeap();
|
||
mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||
}
|
||
}
|
||
|
||
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
|
||
{
|
||
var mainWin = Application.Current.MainWindow as Main;
|
||
mainWin!.ShowCountDownAnimation();
|
||
}
|
||
|
||
// 隐藏按钮点击处理:连续点击五次显示内嵌密码弹窗
|
||
private void HiddenAdminButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
_adminClickCount++;
|
||
// 每次点击重启计时器
|
||
_resetTimer.Stop();
|
||
_resetTimer.Start();
|
||
|
||
if (_adminClickCount >= 5)
|
||
{
|
||
_resetTimer.Stop();
|
||
_adminClickCount = 0;
|
||
|
||
// 显示内嵌密码弹窗
|
||
AdminPasswordBox.Password = string.Empty;
|
||
AdminDialogGrid.Visibility = Visibility.Visible;
|
||
AdminPasswordBox.Focus();
|
||
}
|
||
}
|
||
|
||
// 密码弹窗:确定按钮
|
||
private void AdminOkButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
var entered = AdminPasswordBox.Password ?? string.Empty;
|
||
if (entered == "8888")
|
||
{
|
||
AdminDialogGrid.Visibility = Visibility.Collapsed;
|
||
// 密码正确,打开管理员页面(已有 AdminWindow 或按需改为导航)
|
||
try
|
||
{
|
||
SetDialogGrid.Visibility = Visibility.Visible;
|
||
//var adminWin = new Views.AdminWindow();
|
||
//adminWin.Owner = Window.GetWindow(this);
|
||
//adminWin.Show();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show("密码正确");
|
||
|
||
Debug.WriteLine($"打开管理员页面异常: {ex.Message}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("密码错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
AdminPasswordBox.Password = string.Empty;
|
||
AdminPasswordBox.Focus();
|
||
}
|
||
}
|
||
|
||
// 密码弹窗:取消按钮
|
||
private void AdminCancelButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
AdminDialogGrid.Visibility = Visibility.Collapsed;
|
||
}
|
||
|
||
// 在 PasswordBox 按 Enter 等同于确定,按 Esc 等同于取消
|
||
private void AdminPasswordBox_KeyDown(object sender, KeyEventArgs e)
|
||
{
|
||
if (e.Key == Key.Enter)
|
||
{
|
||
AdminOkButton_Click(sender, e);
|
||
e.Handled = true;
|
||
}
|
||
else if (e.Key == Key.Escape)
|
||
{
|
||
AdminCancelButton_Click(sender, e);
|
||
e.Handled = true;
|
||
}
|
||
}
|
||
|
||
private void SetCancelButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
SetDialogGrid.Visibility = Visibility.Collapsed;
|
||
}
|
||
|
||
//加载配置
|
||
private async void Load_Base()
|
||
{
|
||
var app = (App)Application.Current;
|
||
using var scope = App.AppHost.Services.CreateScope();
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
var baseData = await db.BasicConfig.FirstOrDefaultAsync(x => x.Code == AppSettings.Code);
|
||
if (baseData == null)
|
||
{
|
||
baseData = new BasicConfig { Code = AppSettings.Code, Host = host.Text, UserName = name.Text, Password = password.Text , HomeWidth = int.Parse(homeWidth.Text)};
|
||
db.BasicConfig.Add(baseData);
|
||
db.SaveChanges();
|
||
}
|
||
else
|
||
{
|
||
host.Text = baseData.Host;
|
||
name.Text = baseData.UserName;
|
||
password.Text = baseData.Password;
|
||
homeWidth.Text = baseData.HomeWidth.ToString();
|
||
}
|
||
}
|
||
|
||
//保存基本配置
|
||
private async void SetOkButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
var app = (App)Application.Current;
|
||
using var scope = App.AppHost.Services.CreateScope();
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
var baseData = await db.BasicConfig.FirstOrDefaultAsync(x => x.Code == AppSettings.Code);
|
||
if (baseData == null)
|
||
{
|
||
db.BasicConfig.Add(new BasicConfig
|
||
{
|
||
Code = AppSettings.Code,
|
||
Host = host.Text,
|
||
UserName = name.Text,
|
||
Password = password.Text,
|
||
HomeWidth = int.Parse(homeWidth.Text)
|
||
});
|
||
}
|
||
else
|
||
{
|
||
baseData.Host = host.Text;
|
||
baseData.UserName = name.Text;
|
||
baseData.Password = password.Text;
|
||
baseData.HomeWidth = int.Parse(homeWidth.Text);
|
||
db.BasicConfig.Update(baseData);
|
||
}
|
||
db.SaveChanges();
|
||
|
||
HandyControl.Controls.MessageBox.Show("保存成功!", "提示");
|
||
SetDialogGrid.Visibility = Visibility.Collapsed;
|
||
}
|
||
|
||
//多人跳绳
|
||
private void GoRopeSet(object sender, RoutedEventArgs e)
|
||
{
|
||
//var app = (App)Application.Current;
|
||
//using var scope = App.AppHost.Services.CreateScope();
|
||
//var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
//var mainWindow = new MainWindow(db);
|
||
//mainWindow.Show();
|
||
|
||
var mainWin = Application.Current.MainWindow as Main;
|
||
mainWin.SwitchPageWithMaskAnimation(new MultiJumpRope(), true);
|
||
}
|
||
|
||
//跳远
|
||
private void GoLongSet(object sender, RoutedEventArgs e)
|
||
{
|
||
var mainWin = Application.Current.MainWindow as Main;
|
||
mainWin.SwitchPageWithMaskAnimation(new LongSttting(), true);
|
||
}
|
||
|
||
private void Ping_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
//var config = _context.BasicConfig.FirstOrDefault();
|
||
|
||
//if (config != null)
|
||
//{
|
||
// //var ip = config.Ip;
|
||
//}
|
||
|
||
var host = this.host.Text.Trim();
|
||
if (string.IsNullOrWhiteSpace(host))
|
||
{
|
||
this.ShowError("相机主机地址/IP不能为空。");
|
||
return;
|
||
}
|
||
|
||
var pinger = new Ping();
|
||
var reply = pinger.Send(host, 10);
|
||
if (reply.Status == IPStatus.Success)
|
||
this.ShowInformation("与相机通信正常。");
|
||
else
|
||
this.ShowError($"与相机通信失败,错误:{reply.Status}。");
|
||
}
|
||
|
||
// 辅助方法:获取资源绝对 Uri,兼容 Debug 和 发布
|
||
private static Uri GetResourceUri(string relativePath)
|
||
{
|
||
string baseDir = AppContext.BaseDirectory;
|
||
|
||
// 发布目录下路径
|
||
string fullPath = Path.Combine(baseDir, "Resources", "Img", relativePath.Replace("/", Path.DirectorySeparatorChar.ToString()));
|
||
|
||
if (!File.Exists(fullPath))
|
||
{
|
||
#if DEBUG
|
||
// Debug 下 fallback 到项目根目录
|
||
string projectRoot = Path.Combine(baseDir, @"..\..\..");
|
||
fullPath = Path.Combine(projectRoot, "Resources", "Img", relativePath.Replace("/", Path.DirectorySeparatorChar.ToString()));
|
||
#endif
|
||
}
|
||
|
||
return new Uri(fullPath, UriKind.Absolute);
|
||
}
|
||
}
|
||
}
|