add: 久坐提醒项目文件
This commit is contained in:
182
ActivityMonitor.cs
Normal file
182
ActivityMonitor.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TimerApp
|
||||
{
|
||||
public enum MonitorState
|
||||
{
|
||||
Idle,
|
||||
Working,
|
||||
Resting
|
||||
}
|
||||
|
||||
public class ActivityMonitor
|
||||
{
|
||||
private System.Windows.Forms.Timer _timer;
|
||||
private DateTime _lastWorkStartTime;
|
||||
private TimeSpan _accumulatedWorkTime;
|
||||
private DateTime _restStartTime;
|
||||
|
||||
// 配置 (默认值)
|
||||
public TimeSpan WorkDuration { get; set; } = TimeSpan.FromMinutes(20);
|
||||
public TimeSpan RestDuration { get; set; } = TimeSpan.FromMinutes(1);
|
||||
public TimeSpan IdleThreshold { get; set; } = TimeSpan.FromSeconds(30);
|
||||
|
||||
public MonitorState CurrentState { get; private set; } = MonitorState.Idle;
|
||||
|
||||
// 事件
|
||||
public event EventHandler<TimeSpan> WorkProgressChanged; // 剩余工作时间
|
||||
public event EventHandler<TimeSpan> RestProgressChanged; // 剩余休息时间
|
||||
public event EventHandler RestStarted;
|
||||
public event EventHandler RestEnded;
|
||||
public event EventHandler StateChanged;
|
||||
|
||||
public ActivityMonitor()
|
||||
{
|
||||
_timer = new System.Windows.Forms.Timer();
|
||||
_timer.Interval = 1000; // 1秒检查一次
|
||||
_timer.Tick += Timer_Tick;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_timer.Start();
|
||||
ResetWork();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
|
||||
private void ResetWork()
|
||||
{
|
||||
_accumulatedWorkTime = TimeSpan.Zero;
|
||||
_lastWorkStartTime = DateTime.Now;
|
||||
ChangeState(MonitorState.Idle);
|
||||
}
|
||||
|
||||
private void ChangeState(MonitorState newState)
|
||||
{
|
||||
if (CurrentState != newState)
|
||||
{
|
||||
CurrentState = newState;
|
||||
StateChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void Timer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
long idleMs = NativeMethods.GetIdleTime();
|
||||
TimeSpan idleTime = TimeSpan.FromMilliseconds(idleMs);
|
||||
|
||||
if (CurrentState == MonitorState.Resting)
|
||||
{
|
||||
// 休息模式逻辑
|
||||
TimeSpan timeInRest = DateTime.Now - _restStartTime;
|
||||
TimeSpan remainingRest = RestDuration - timeInRest;
|
||||
|
||||
if (remainingRest <= TimeSpan.Zero)
|
||||
{
|
||||
// 休息结束
|
||||
RestEnded?.Invoke(this, EventArgs.Empty);
|
||||
ResetWork(); // 重新开始工作周期
|
||||
}
|
||||
else
|
||||
{
|
||||
RestProgressChanged?.Invoke(this, remainingRest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 工作/空闲模式逻辑
|
||||
if (idleTime > IdleThreshold)
|
||||
{
|
||||
// 用户离开了
|
||||
if (CurrentState == MonitorState.Working)
|
||||
{
|
||||
// 如果正在工作,但离开了,暂停工作计时?
|
||||
// 简单起见,如果离开时间过长,可以视为一种“休息”,或者只是暂停累积
|
||||
// 这里我们简单处理:如果空闲时间超过阈值,状态变为空闲
|
||||
ChangeState(MonitorState.Idle);
|
||||
}
|
||||
|
||||
// 如果在 Idle 状态,且空闲时间非常长(比如超过了休息时间),
|
||||
// 是否应该重置工作计时器?
|
||||
// 假设用户去开会了1小时,回来应该重新计算20分钟。
|
||||
if (idleTime > RestDuration)
|
||||
{
|
||||
_accumulatedWorkTime = TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 用户在活动
|
||||
if (CurrentState == MonitorState.Idle)
|
||||
{
|
||||
// 从空闲变为工作
|
||||
ChangeState(MonitorState.Working);
|
||||
_lastWorkStartTime = DateTime.Now;
|
||||
}
|
||||
|
||||
// 累加工作时间
|
||||
// 简单的累加逻辑:这一秒是工作的
|
||||
_accumulatedWorkTime += TimeSpan.FromSeconds(1);
|
||||
|
||||
// 检查是否达到工作时长
|
||||
TimeSpan remainingWork = WorkDuration - _accumulatedWorkTime;
|
||||
|
||||
if (remainingWork <= TimeSpan.Zero)
|
||||
{
|
||||
// 触发休息
|
||||
_restStartTime = DateTime.Now;
|
||||
ChangeState(MonitorState.Resting);
|
||||
RestStarted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorkProgressChanged?.Invoke(this, remainingWork);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 用于强制重置或测试
|
||||
public void ForceRest()
|
||||
{
|
||||
_restStartTime = DateTime.Now;
|
||||
ChangeState(MonitorState.Resting);
|
||||
RestStarted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void RefreshStatus()
|
||||
{
|
||||
if (CurrentState == MonitorState.Working)
|
||||
{
|
||||
TimeSpan remaining = WorkDuration - _accumulatedWorkTime;
|
||||
WorkProgressChanged?.Invoke(this, remaining);
|
||||
}
|
||||
else if (CurrentState == MonitorState.Resting)
|
||||
{
|
||||
TimeSpan timeInRest = DateTime.Now - _restStartTime;
|
||||
TimeSpan remaining = RestDuration - timeInRest;
|
||||
RestProgressChanged?.Invoke(this, remaining);
|
||||
}
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
_accumulatedWorkTime = TimeSpan.Zero;
|
||||
_lastWorkStartTime = DateTime.Now;
|
||||
|
||||
// Ensure timer is running
|
||||
if (!_timer.Enabled) _timer.Start();
|
||||
|
||||
// Force state to Working since user manually restarted
|
||||
ChangeState(MonitorState.Working);
|
||||
|
||||
// Immediately refresh UI to show full duration
|
||||
RefreshStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user