You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
18 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Haoliang.Models.DataCollection;
using Haoliang.Models.Device;
using Haoliang.Models.System;
using Haoliang.Models.User;
using Haoliang.Models.Template;
using Haoliang.Models.Production;
using Haoliang.Data.Repositories;
namespace Haoliang.Core.Services
{
// 完整的仓储接口定义(确保所有服务都能编译)
public interface IAlarmRepository : IRepository<Alarm>
{
Task<IEnumerable<Alarm>> GetByDeviceIdAsync(int deviceId);
Task<IEnumerable<Alarm>> GetByAlarmTypeAsync(AlarmType type);
Task<IEnumerable<Alarm>> GetByStatusAsync(AlarmStatus status);
Task<IEnumerable<Alarm>> GetByDateRangeAsync(DateTime startDate, DateTime endDate);
Task<AlarmStatistics> GetAlarmStatisticsAsync(DateTime date);
Task<IEnumerable<Alarm>> GetBySeverityAsync(AlarmSeverity severity);
Task<IEnumerable<Alarm>> GetByDeviceAndDateRangeAsync(int deviceId, DateTime startDate, DateTime endDate);
}
public interface ISystemConfigRepository : IRepository<SystemConfig>
{
Task<SystemConfig> GetByKeyAsync(string configKey);
Task<bool> DeleteByKeyAsync(string configKey);
Task<bool> KeyExistsAsync(string configKey);
Task<IEnumerable<SystemConfig>> GetByCategoryAsync(string category);
SystemConfig UpsertAsync(SystemConfig config);
}
public interface ILogRepository : IRepository<LogEntry>
{
Task<IEnumerable<LogEntry>> GetLogsAsync(LogLevel? logLevel = null, DateTime? startDate = null, DateTime? endDate = null, string category = null);
Task<int> GetLogCountAsync(LogLevel? logLevel = null, DateTime? startDate = null, DateTime? endDate = null);
Task ArchiveLogsAsync(DateTime cutoffDate);
Task ClearLogsAsync();
}
public interface IScheduledTaskRepository : IRepository<ScheduledTask>
{
Task<IEnumerable<ScheduledTask>> GetActiveTasksAsync();
Task<IEnumerable<ScheduledTask>> GetTasksByStatusAsync(TaskStatus status);
Task<TaskExecutionResult> GetLastExecutionResultAsync(string taskId);
}
public interface IProgramProductionSummaryRepository : IRepository<ProgramProductionSummary>
{
Task<ProgramProductionSummary> GetByDeviceAndDateAsync(int deviceId, DateTime date);
Task<IEnumerable<ProgramProductionSummary>> GetByDateAsync(DateTime date);
Task<IEnumerable<ProgramProductionSummary>> GetByDeviceAsync(int deviceId);
}
public interface IUserRepository : IRepository<User>
{
Task<User> GetByUsernameAsync(string username);
Task<User> GetByEmailAsync(string email);
Task<bool> IsUsernameExistsAsync(string username);
Task<bool> IsEmailExistsAsync(string email);
Task<IEnumerable<User>> GetByRoleAsync(string roleName);
Task<IEnumerable<User>> GetByDepartmentAsync(string department);
}
// 增强的仓储接口
public interface IDeviceRepository : IRepository<CNCDevice>
{
Task<IEnumerable<CNCDevice>> GetOnlineDevicesAsync();
Task<IEnumerable<CNCDevice>> GetOfflineDevicesAsync();
Task<CNCDevice> GetByDeviceCodeAsync(string deviceCode);
Task<bool> IsDeviceOnlineAsync(int deviceId);
Task<IEnumerable<CNCDevice>> GetByTemplateAsync(int templateId);
Task UpdateDeviceStatusAsync(int deviceId, DeviceStatus status);
Task<DeviceStatistics> GetDeviceStatisticsAsync(int deviceId);
}
public interface ITemplateRepository : IRepository<CNCBrandTemplate>
{
Task<IEnumerable<CNCBrandTemplate>> GetByBrandAsync(string brandName);
Task<IEnumerable<CNCBrandTemplate>> GetActiveTemplatesAsync();
Task<bool> IsTemplateInUseAsync(int templateId);
Task<CNCBrandTemplate> GetByNameAsync(string templateName);
}
public interface IProductionRepository : IRepository<ProductionRecord>
{
Task<ProductionRecord> GetByDeviceAndDateAsync(int deviceId, DateTime date);
Task<IEnumerable<ProductionRecord>> GetByDateRangeAsync(int deviceId, DateTime startDate, DateTime endDate);
Task<ProductionStatistics> GetStatisticsAsync(int deviceId, DateTime date);
Task<ProductionSummary> GetSummaryAsync(DateTime date);
Task<bool> HasProductionDataAsync(int deviceId, DateTime date);
Task ArchiveProductionDataAsync(int daysToKeep = 90);
}
public interface ICollectionTaskRepository : IRepository<CollectionTask>
{
Task<IEnumerable<CollectionTask>> GetPendingTasksAsync();
Task<IEnumerable<CollectionTask>> GetFailedTasksAsync();
Task<CollectionTask> GetByDeviceAsync(int deviceId);
Task<bool> MarkTaskCompletedAsync(int taskId, bool isSuccess, string result);
}
public interface ICollectionResultRepository : IRepository<CollectionResult>
{
Task<IEnumerable<CollectionResult>> GetByDeviceAsync(int deviceId);
Task<IEnumerable<CollectionResult>> GetByDateRangeAsync(int deviceId, DateTime startDate, DateTime endDate);
Task<CollectionStatistics> GetStatisticsAsync(DateTime date);
Task<CollectionHealth> GetHealthAsync();
Task ArchiveResultsAsync(int daysToKeep = 30);
}
public interface ICollectionLogRepository : IRepository<CollectionLog>
{
Task<IEnumerable<CollectionLog>> GetByDeviceAsync(int deviceId);
Task<IEnumerable<CollectionLog>> GetByLogLevelAsync(LogLevel logLevel);
Task<int> GetErrorCountAsync(int deviceId);
Task ArchiveLogsAsync(int daysToKeep = 30);
Task ClearLogsAsync();
}
public interface IProductionSummaryRepository : IRepository<ProductionSummary>
{
Task<ProductionSummary> GetByDateAsync(DateTime date);
Task<IEnumerable<ProductionSummary>> GetByDateRangeAsync(DateTime startDate, DateTime endDate);
Task<ProductionSummary> GetByDeviceAndDateAsync(int deviceId, DateTime date);
Task<ProductionSummary> GetTodaySummaryAsync();
}
// 背景任务管理器
public class BackgroundTaskManager : ISchedulerService
{
private readonly IScheduledTaskRepository _taskRepository;
private readonly IProductionService _productionService;
private readonly ILoggingService _loggingService;
private readonly ConcurrentDictionary<string, Task> _runningTasks = new();
private readonly ConcurrentDictionary<string, bool> _taskStatus = new();
private System.Threading.Timer _schedulerTimer;
public BackgroundTaskManager(
IScheduledTaskRepository taskRepository,
IProductionService productionService,
ILoggingService loggingService)
{
_taskRepository = taskRepository;
_productionService = productionService;
_loggingService = loggingService;
}
public async Task StartSchedulerAsync()
{
_schedulerTimer = new System.Threading.Timer(
async _ => await CheckAndExecuteTasksAsync(),
null,
TimeSpan.Zero,
TimeSpan.FromMinutes(1));
await _loggingService.LogInfoAsync("Background task scheduler started");
}
public async Task StopSchedulerAsync()
{
_schedulerTimer?.Dispose();
_schedulerTimer = null;
foreach (var task in _runningTasks.Values)
{
if (!task.IsCompleted)
{
await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(5)));
}
}
await _loggingService.LogInfoAsync("Background task scheduler stopped");
}
public async Task ScheduleTaskAsync(ScheduledTask task)
{
task.TaskStatus = TaskStatus.Pending;
task.CreatedAt = DateTime.Now;
task.LastRunAt = null;
await _taskRepository.AddAsync(task);
await _loggingService.LogInfoAsync($"Task {task.TaskName} scheduled");
}
public async Task<bool> RemoveTaskAsync(string taskId)
{
var task = await _taskRepository.GetByIdAsync(taskId);
if (task == null)
{
return false;
}
// 如果任务正在运行,等待完成
if (_runningTasks.ContainsKey(taskId))
{
var runningTask = _runningTasks[taskId];
await Task.WhenAny(runningTask, Task.Delay(TimeSpan.FromSeconds(5)));
}
return await _taskRepository.DeleteAsync(taskId);
}
public async Task<IEnumerable<ScheduledTask>> GetAllScheduledTasksAsync()
{
return await _taskRepository.GetAllAsync();
}
public async Task<ScheduledTask> GetTaskByIdAsync(string taskId)
{
return await _taskRepository.GetByIdAsync(taskId);
}
public async Task ExecuteTaskAsync(string taskId)
{
if (_runningTasks.ContainsKey(taskId))
{
await _loggingService.LogWarningAsync($"Task {taskId} is already running");
return;
}
var task = await _taskRepository.GetByIdAsync(taskId);
if (task == null)
{
await _loggingService.LogErrorAsync($"Task {taskId} not found");
return;
}
var taskExecution = Task.Run(async () =>
{
try
{
_taskStatus[taskId] = true;
task.TaskStatus = TaskStatus.Running;
task.LastRunAt = DateTime.Now;
await _taskRepository.UpdateAsync(task);
await _loggingService.LogInfoAsync($"Executing task: {task.TaskName}");
// 执行任务逻辑
switch (task.TaskName)
{
case "ProductionCalculation":
await _productionService.CalculateAllProductionAsync();
break;
case "DataCollection":
// 数据采集逻辑
break;
case "LogArchival":
await _loggingService.ArchiveLogsAsync(30);
break;
case "DataCleanup":
// 数据清理逻辑
break;
default:
await _loggingService.LogWarningAsync($"Unknown task type: {task.TaskName}");
break;
}
task.TaskStatus = TaskStatus.Completed;
task.CompletedAt = DateTime.Now;
await _taskRepository.UpdateAsync(task);
await _loggingService.LogInfoAsync($"Task {task.TaskName} completed successfully");
}
catch (Exception ex)
{
task.TaskStatus = TaskStatus.Failed;
task.ErrorMessage = ex.Message;
task.CompletedAt = DateTime.Now;
await _taskRepository.UpdateAsync(task);
await _loggingService.LogErrorAsync($"Task {task.TaskName} failed: {ex.Message}", ex);
}
finally
{
_runningTasks.TryRemove(taskId, out _);
_taskStatus.TryRemove(taskId, out _);
}
});
_runningTasks[taskId] = taskExecution;
}
public async Task<TaskExecutionResult> GetTaskExecutionResultAsync(string taskId)
{
return await _taskRepository.GetLastExecutionResultAsync(taskId);
}
public async Task<bool> IsTaskRunningAsync(string taskId)
{
return _runningTasks.ContainsKey(taskId) && _taskStatus.ContainsKey(taskId) && _taskStatus[taskId];
}
public async Task<string> ScheduleRecurringTaskAsync(string taskName, Action taskAction, TimeSpan interval)
{
var task = new ScheduledTask
{
TaskId = Guid.NewGuid().ToString(),
TaskName = taskName,
CronExpression = $"*/{interval.TotalMinutes} * * * *",
TaskStatus = TaskStatus.Pending,
IsActive = true,
CreatedAt = DateTime.Now,
Description = $"Recurring task: {taskName}"
};
await ScheduleTaskAsync(task);
return task.TaskId;
}
private async Task CheckAndExecuteTasksAsync()
{
var pendingTasks = await _taskRepository.GetActiveTasksAsync();
var now = DateTime.Now;
foreach (var task in pendingTasks)
{
if (await ShouldExecuteTaskAsync(task, now))
{
await ExecuteTaskAsync(task.TaskId);
}
}
}
private async Task<bool> ShouldExecuteTaskAsync(ScheduledTask task, DateTime now)
{
if (task.TaskStatus == TaskStatus.Running || !task.IsActive)
{
return false;
}
// 简单的时间检查实际应该使用CRON表达式解析器
if (task.LastRunAt == null)
{
return true;
}
var timeSinceLastRun = now - task.LastRunAt.Value;
return timeSinceLastRun.TotalMinutes >= 1; // 每分钟执行一次
}
}
// 缓存服务实现
public class CacheManager : ICachingService
{
private readonly ConcurrentDictionary<string, CacheItem> _cache = new();
private readonly System.Threading.Timer _cleanupTimer;
public CacheManager()
{
_cleanupTimer = new System.ThreadingTimer(
_ => CleanupExpiredItems(),
null,
TimeSpan.FromMinutes(5),
TimeSpan.FromMinutes(5));
}
public async Task<T> GetAsync<T>(string key)
{
if (_cache.TryGetValue(key, out var item))
{
if (item.ExpirationTime > DateTime.Now)
{
return (T)item.Value;
}
_cache.TryRemove(key, out _);
}
return default;
}
public async Task SetAsync<T>(string key, T value, TimeSpan? expiration = null)
{
var item = new CacheItem
{
Value = value,
ExpirationTime = DateTime.Now + (expiration ?? TimeSpan.FromMinutes(30))
};
_cache[key] = item;
}
public async Task<bool> RemoveAsync(string key)
{
return _cache.TryRemove(key, out _);
}
public async Task<bool> ExistsAsync(string key)
{
if (_cache.TryGetValue(key, out var item))
{
if (item.ExpirationTime > DateTime.Now)
{
return true;
}
_cache.TryRemove(key, out _);
}
return false;
}
public async Task ClearAsync()
{
_cache.Clear();
}
public async Task<T> GetOrCreateAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiration = null)
{
var value = await GetAsync<T>(key);
if (value == null)
{
value = await factory();
await SetAsync(key, value, expiration);
}
return value;
}
public async Task<IEnumerable<string>> GetAllKeysAsync()
{
return _cache.Keys;
}
public async Task<bool> RefreshAsync<T>(string key)
{
if (_cache.TryGetValue(key, out var item))
{
item.ExpirationTime = DateTime.Now + TimeSpan.FromMinutes(30);
return true;
}
return false;
}
private void CleanupExpiredItems()
{
var now = DateTime.Now;
var expiredKeys = _cache
.Where(kvp => kvp.Value.ExpirationTime <= now)
.Select(kvp => kvp.Key)
.ToList();
foreach (var key in expiredKeys)
{
_cache.TryRemove(key, out _);
}
}
private class CacheItem
{
public object Value { get; set; }
public DateTime ExpirationTime { get; set; }
}
}
// 简化的JWT认证中间件
public class JwtAuthMiddleware : IWebSocketAuthMiddleware
{
private readonly IAuthService _authService;
private readonly ConcurrentDictionary<string, string> _connectionUsers = new();
public JwtAuthMiddleware(IAuthService authService)
{
_authService = authService;
}
public async Task AuthenticateAsync(string connectionId, string token)
{
try
{
var isValid = await _authService.ValidateTokenAsync(token);
if (isValid)
{
var claims = await _authService.GetUserClaimsAsync(int.Parse(token));
_connectionUsers[connectionId] = claims.UserId.ToString();
}
}
catch (Exception ex)
{
// 认证失败
}
}
public async Task<string> GetUserIdAsync(string connectionId)
{
_connectionUsers.TryGetValue(connectionId, out var userId);
return userId;
}
public async Task<string> GetConnectionIdAsync(string userId)
{
foreach (var kvp in _connectionUsers)
{
if (kvp.Value == userId)
{
return kvp.Key;
}
}
return null;
}
public async Task<bool> IsAuthenticatedAsync(string connectionId)
{
return _connectionUsers.ContainsKey(connectionId);
}
public async Task<bool> HasPermissionAsync(string connectionId, string permission)
{
var userId = await GetUserIdAsync(connectionId);
if (string.IsNullOrEmpty(userId))
{
return false;
}
// 这里应该检查用户权限
return true; // 简化实现
}
}
}