|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Net.Http;
|
|
|
using System.Text;
|
|
|
using System.Web.Http;
|
|
|
using CncModels.Dto;
|
|
|
using CncModels.Dto.Dashboard;
|
|
|
using CncService.Interface;
|
|
|
using CncWebApi.Infrastructure;
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
namespace CncWebApi.Controllers
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 仪表盘控制器
|
|
|
/// </summary>
|
|
|
[RoutePrefix("api/admin/dashboard")]
|
|
|
[JwtAuthFilter]
|
|
|
public class DashboardController : ApiController
|
|
|
{
|
|
|
private readonly IDashboardService _dashboardService;
|
|
|
private static readonly HttpClient _httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
|
|
|
|
|
|
/// <summary>
|
|
|
/// 构造函数
|
|
|
/// </summary>
|
|
|
public DashboardController(IDashboardService dashboardService)
|
|
|
{
|
|
|
_dashboardService = dashboardService;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 8个统计卡片数据
|
|
|
/// GET /api/admin/dashboard/summary
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("summary")]
|
|
|
public IHttpActionResult GetSummary()
|
|
|
{
|
|
|
var result = _dashboardService.GetSummary();
|
|
|
return Ok(ApiResponse<DashboardSummaryResponse>.Success(result));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 车间平均单机产量
|
|
|
/// GET /api/admin/dashboard/workshop-production
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("workshop-production")]
|
|
|
public IHttpActionResult GetWorkshopProduction(DateTime? startDate = null, DateTime? endDate = null)
|
|
|
{
|
|
|
var result = _dashboardService.GetWorkshopProduction(startDate, endDate);
|
|
|
return Ok(ApiResponse<object>.Success(new { items = result }));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 机床产量排行
|
|
|
/// GET /api/admin/dashboard/machine-rank
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("machine-rank")]
|
|
|
public IHttpActionResult GetMachineRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10, string sortOrder = "desc")
|
|
|
{
|
|
|
var result = _dashboardService.GetMachineRank(startDate, endDate, top, sortOrder);
|
|
|
return Ok(ApiResponse<object>.Success(new { items = result }));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 工人产量排行
|
|
|
/// GET /api/admin/dashboard/worker-rank
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("worker-rank")]
|
|
|
public IHttpActionResult GetWorkerRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10, string sortOrder = "desc")
|
|
|
{
|
|
|
var result = _dashboardService.GetWorkerRank(startDate, endDate, top, sortOrder);
|
|
|
return Ok(ApiResponse<object>.Success(new { items = result }));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 产量趋势(近7天)
|
|
|
/// GET /api/admin/dashboard/trend
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("trend")]
|
|
|
public IHttpActionResult GetProductionTrend(int days = 7)
|
|
|
{
|
|
|
var result = _dashboardService.GetProductionTrend();
|
|
|
return Ok(ApiResponse<object>.Success(new { items = result }));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 机床状态分布
|
|
|
/// GET /api/admin/dashboard/machine-status-distribution
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("machine-status-distribution")]
|
|
|
public IHttpActionResult GetMachineStatusDistribution()
|
|
|
{
|
|
|
var result = _dashboardService.GetMachineStatusDistribution();
|
|
|
return Ok(ApiResponse<object>.Success(result));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 最新5条告警
|
|
|
/// GET /api/admin/dashboard/recent-alerts
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("recent-alerts")]
|
|
|
public IHttpActionResult GetRecentAlerts(int count = 5)
|
|
|
{
|
|
|
var result = _dashboardService.GetRecentAlerts(count);
|
|
|
return Ok(ApiResponse<object>.Success(new { items = result }));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 采集服务状态
|
|
|
/// GET /api/admin/collector/status
|
|
|
/// </summary>
|
|
|
[HttpGet]
|
|
|
[Route("~/api/admin/collector/status")]
|
|
|
public IHttpActionResult GetCollectorStatus()
|
|
|
{
|
|
|
var result = _dashboardService.GetCollectorStatus();
|
|
|
return Ok(ApiResponse<object>.Success(result));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 启动采集服务(转发到CncCollector的5800端口)
|
|
|
/// POST /api/admin/collector/start
|
|
|
/// </summary>
|
|
|
[HttpPost]
|
|
|
[Route("~/api/admin/collector/start")]
|
|
|
public IHttpActionResult StartCollector()
|
|
|
{
|
|
|
// 先查询服务状态,决定下一步动作
|
|
|
try
|
|
|
{
|
|
|
dynamic statusObj = _dashboardService.GetCollectorStatus();
|
|
|
string serviceStatus = statusObj?.serviceStatus as string;
|
|
|
if (!string.IsNullOrEmpty(serviceStatus) && string.Equals(serviceStatus, "NotInstalled", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
return Ok(ApiResponse<object>.Fail(40001, "采集服务未安装,请先在服务器上运行 install.ps1 安装服务"));
|
|
|
}
|
|
|
if (!string.IsNullOrEmpty(serviceStatus) && string.Equals(serviceStatus, "Running", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
return Ok(ApiResponse<object>.Fail(40002, "采集服务已在运行中,无需再次启动"));
|
|
|
}
|
|
|
}
|
|
|
catch { /* ignore status fetch errors and fallback to forwarding */ }
|
|
|
|
|
|
return ForwardToCollector("/api/collector/start");
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 停止采集服务
|
|
|
/// POST /api/admin/collector/stop
|
|
|
/// </summary>
|
|
|
[HttpPost]
|
|
|
[Route("~/api/admin/collector/stop")]
|
|
|
public IHttpActionResult StopCollector()
|
|
|
{
|
|
|
return ForwardToCollector("/api/collector/stop");
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 刷新采集服务配置
|
|
|
/// POST /api/admin/collector/refresh
|
|
|
/// </summary>
|
|
|
[HttpPost]
|
|
|
[Route("~/api/admin/collector/refresh")]
|
|
|
public IHttpActionResult RefreshCollectorConfig()
|
|
|
{
|
|
|
return ForwardToCollector("/api/collector/refresh");
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 手动触发日终汇总
|
|
|
/// POST /api/admin/collector/daily-summary
|
|
|
/// </summary>
|
|
|
[HttpPost]
|
|
|
[Route("~/api/admin/collector/daily-summary")]
|
|
|
public IHttpActionResult RunDailySummary()
|
|
|
{
|
|
|
return ForwardToCollector("/api/collector/daily-summary");
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 转发请求到采集服务
|
|
|
/// </summary>
|
|
|
private IHttpActionResult ForwardToCollector(string path)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
var request = new HttpRequestMessage(HttpMethod.Post, $"http://localhost:5800{path}");
|
|
|
request.Headers.Add("X-Api-Key", "collector_api_key_2026");
|
|
|
var response = _httpClient.SendAsync(request).Result;
|
|
|
var body = response.Content.ReadAsStringAsync().Result;
|
|
|
return Ok(ApiResponse<object>.Success(new { forwarded = true, collectorResponse = JsonConvert.DeserializeObject(body) }));
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
// 采集服务不可达时返回失败,避免前端误认为操作成功
|
|
|
return Ok(ApiResponse<object>.Fail(50001, $"采集服务连接失败: {ex.Message}"));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|