From 03aaeb11c2e05502a372e1392f7d3bd757375325 Mon Sep 17 00:00:00 2001
From: haoliang <821644@qq.com>
Date: Tue, 28 Apr 2026 19:23:44 +0800
Subject: [PATCH] =?UTF-8?q?feat(webapi):=20CncWebApi=E5=AE=8C=E6=95=B4?=
=?UTF-8?q?=E5=AE=9E=E7=8E=B0=20-=2013=E6=8E=A7=E5=88=B6=E5=99=A8+DI+JWT?=
=?UTF-8?q?=E8=AE=A4=E8=AF=81=EF=BC=8C=E7=BC=96=E8=AF=91=E9=80=9A=E8=BF=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Controllers: 13个API控制器(Auth/Dashboard/Machine/Brand/CollectAddress/Worker/Production/Alert/Settings/Log/ScreenConfig/Screen/Option)
- Infrastructure: ServiceResolver(手动DI)+JwtAuthFilter(HMACSHA256签名验证)
- 路由: 属性路由覆盖,管理后台/api/admin/**+大屏/api/screen/**
- 认证: JwtAuthFilter标记admin接口,ScreenController免认证
- DI: WebApiConfig注册ServiceResolver,手动解析Repository+Service依赖链
- WorkshopRepository: 从CncRepository.Impl移入CncRepository/Impl统一管理
---
src/CncRepository/Impl/WorkshopRepository.cs | 111 +++++++++++
src/CncWebApi/App_Start/WebApiConfig.cs | 9 +-
src/CncWebApi/Controllers/AlertController.cs | 78 ++++++++
src/CncWebApi/Controllers/AuthController.cs | 36 ++++
src/CncWebApi/Controllers/BrandController.cs | 123 ++++++++++++
.../Controllers/CollectAddressController.cs | 99 ++++++++++
.../Controllers/DashboardController.cs | 124 ++++++++++++
src/CncWebApi/Controllers/LogController.cs | 55 ++++++
.../Controllers/MachineController.cs | 99 ++++++++++
src/CncWebApi/Controllers/OptionController.cs | 109 +++++++++++
.../Controllers/ProductionController.cs | 64 ++++++
.../Controllers/ScreenConfigController.cs | 141 ++++++++++++++
src/CncWebApi/Controllers/ScreenController.cs | 150 ++++++++++++++
.../Controllers/SettingsController.cs | 151 ++++++++++++++
src/CncWebApi/Controllers/WorkerController.cs | 132 +++++++++++++
src/CncWebApi/Infrastructure/JwtAuthFilter.cs | 112 +++++++++++
.../Infrastructure/ServiceResolver.cs | 184 ++++++++++++++++++
17 files changed, 1774 insertions(+), 3 deletions(-)
create mode 100644 src/CncRepository/Impl/WorkshopRepository.cs
create mode 100644 src/CncWebApi/Controllers/AlertController.cs
create mode 100644 src/CncWebApi/Controllers/AuthController.cs
create mode 100644 src/CncWebApi/Controllers/BrandController.cs
create mode 100644 src/CncWebApi/Controllers/CollectAddressController.cs
create mode 100644 src/CncWebApi/Controllers/DashboardController.cs
create mode 100644 src/CncWebApi/Controllers/LogController.cs
create mode 100644 src/CncWebApi/Controllers/MachineController.cs
create mode 100644 src/CncWebApi/Controllers/OptionController.cs
create mode 100644 src/CncWebApi/Controllers/ProductionController.cs
create mode 100644 src/CncWebApi/Controllers/ScreenConfigController.cs
create mode 100644 src/CncWebApi/Controllers/ScreenController.cs
create mode 100644 src/CncWebApi/Controllers/SettingsController.cs
create mode 100644 src/CncWebApi/Controllers/WorkerController.cs
create mode 100644 src/CncWebApi/Infrastructure/JwtAuthFilter.cs
create mode 100644 src/CncWebApi/Infrastructure/ServiceResolver.cs
diff --git a/src/CncRepository/Impl/WorkshopRepository.cs b/src/CncRepository/Impl/WorkshopRepository.cs
new file mode 100644
index 0000000..3c7f126
--- /dev/null
+++ b/src/CncRepository/Impl/WorkshopRepository.cs
@@ -0,0 +1,111 @@
+using System.Collections.Generic;
+using System.Linq;
+using Dapper;
+using CncModels.Entity;
+using CncRepository.Base;
+using CncRepository.Interface;
+using System.Data;
+using CncModels.Dto;
+
+namespace CncRepository.Impl
+{
+ ///
+ /// 车间仓储实现
+ ///
+ public class WorkshopRepository : BusinessRepository, IWorkshopRepository
+ {
+ public WorkshopRepository(string connectionString) : base(connectionString) { }
+
+ public Workshop GetById(int id)
+ {
+ using (var conn = CreateConnection())
+ {
+ var sql = @"SELECT Id as Id, Name as Name, SortOrder as SortOrder, IsEnabled as IsEnabled, CreatedAt as CreatedAt, UpdatedAt as UpdatedAt FROM cnc_workshop WHERE Id = @Id";
+ return conn.QuerySingleOrDefault(sql, new { Id = id });
+ }
+ }
+
+ public List GetAll()
+ {
+ using (var conn = CreateConnection())
+ {
+ var sql = @"SELECT Id as Id, Name as Name, SortOrder as SortOrder, IsEnabled as IsEnabled, CreatedAt as CreatedAt, UpdatedAt as UpdatedAt FROM cnc_workshop ORDER BY SortOrder ASC";
+ return conn.Query(sql).ToList();
+ }
+ }
+
+ public PagedResult GetList(string keyword)
+ {
+ using (var conn = CreateConnection())
+ {
+ var where = string.Empty;
+ var param = new DynamicParameters();
+ if (!string.IsNullOrWhiteSpace(keyword))
+ {
+ where = " WHERE Name LIKE @Keyword";
+ param.Add("Keyword", $"%{keyword}%");
+ }
+ var limit = 20;
+ var sql = $@"SELECT Id as Id, Name as Name, SortOrder as SortOrder, IsEnabled as IsEnabled, CreatedAt as CreatedAt, UpdatedAt as UpdatedAt
+ FROM cnc_workshop {where} ORDER BY SortOrder ASC LIMIT {limit} OFFSET 0";
+ var totalSql = $@"SELECT COUNT(*) FROM cnc_workshop {where}";
+ var items = conn.Query(sql, param).ToList();
+ var total = conn.ExecuteScalar(totalSql, param);
+ return new PagedResult
+ {
+ Items = items,
+ Total = total,
+ Page = 1,
+ PageSize = limit
+ };
+ }
+ }
+
+ public int Create(Workshop entity)
+ {
+ using (var conn = CreateConnection())
+ {
+ var sql = @"INSERT INTO cnc_workshop (Name, SortOrder, IsEnabled, CreatedAt, UpdatedAt)
+ VALUES (@Name, @SortOrder, @IsEnabled, @CreatedAt, @UpdatedAt);
+ SELECT LAST_INSERT_ID();";
+ return conn.QuerySingle(sql, entity);
+ }
+ }
+
+ public bool Update(Workshop entity)
+ {
+ using (var conn = CreateConnection())
+ {
+ var sql = @"UPDATE cnc_workshop SET Name = @Name, SortOrder = @SortOrder, IsEnabled = @IsEnabled, UpdatedAt = @UpdatedAt WHERE Id = @Id";
+ return conn.Execute(sql, entity) > 0;
+ }
+ }
+
+ public bool Delete(int id)
+ {
+ using (var conn = CreateConnection())
+ {
+ var sql = @"DELETE FROM cnc_workshop WHERE Id = @Id";
+ return conn.Execute(sql, new { Id = id }) > 0;
+ }
+ }
+
+ public bool ToggleEnabled(int id)
+ {
+ using (var conn = CreateConnection())
+ {
+ var sql = @"UPDATE cnc_workshop SET IsEnabled = CASE WHEN IsEnabled = 1 THEN 0 ELSE 1 END, UpdatedAt = NOW() WHERE Id = @Id";
+ return conn.Execute(sql, new { Id = id }) > 0;
+ }
+ }
+
+ public int GetMachineCount(int workshopId)
+ {
+ using (var conn = CreateConnection())
+ {
+ var sql = @"SELECT COUNT(*) FROM cnc_machine WHERE WorkshopId = @WorkshopId";
+ return conn.ExecuteScalar(sql, new { WorkshopId = workshopId });
+ }
+ }
+ }
+}
diff --git a/src/CncWebApi/App_Start/WebApiConfig.cs b/src/CncWebApi/App_Start/WebApiConfig.cs
index ebeb7dd..2672acc 100644
--- a/src/CncWebApi/App_Start/WebApiConfig.cs
+++ b/src/CncWebApi/App_Start/WebApiConfig.cs
@@ -1,5 +1,7 @@
using System.Web.Http;
using System.Web.Http.Cors;
+using CncWebApi.Filters;
+using CncWebApi.Infrastructure;
namespace CncWebApi.App_Start
{
@@ -15,16 +17,17 @@ namespace CncWebApi.App_Start
/// HTTP配置对象
public static void Register(HttpConfiguration config)
{
+ // 依赖注入解析器
+ config.DependencyResolver = new ServiceResolver();
+
// 跨域配置(局域网场景,允许所有来源)
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
// 路由注册
- // 默认路由模板:api/{controller}/{id}
- // 各Controller使用 [RoutePrefix] + [Route] 属性路由覆盖此默认
config.MapHttpAttributeRoutes();
// 全局异常过滤器
- config.Filters.Add(new Filters.GlobalExceptionFilter());
+ config.Filters.Add(new GlobalExceptionFilter());
// 统一JSON序列化设置
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling =
diff --git a/src/CncWebApi/Controllers/AlertController.cs b/src/CncWebApi/Controllers/AlertController.cs
new file mode 100644
index 0000000..f5d0a67
--- /dev/null
+++ b/src/CncWebApi/Controllers/AlertController.cs
@@ -0,0 +1,78 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Web.Http;
+using CncModels.Dto;
+using CncModels.Dto.Alert;
+using CncService.Interface;
+using CncWebApi.Infrastructure;
+
+namespace CncWebApi.Controllers
+{
+ ///
+ /// 告警中心控制器
+ ///
+ [RoutePrefix("api/admin/alert")]
+ [JwtAuthFilter]
+ public class AlertController : ApiController
+ {
+ private readonly IAlertService _alertService;
+
+ ///
+ /// 构造函数
+ ///
+ public AlertController(IAlertService alertService)
+ {
+ _alertService = alertService;
+ }
+
+ ///
+ /// 告警列表(分页)
+ /// GET /api/admin/alert
+ ///
+ [HttpGet]
+ [Route("")]
+ public IHttpActionResult GetList([FromUri] AlertQuery query)
+ {
+ if (query == null) query = new AlertQuery();
+ var result = _alertService.GetList(query);
+ return Ok(ApiResponse>.Success(result));
+ }
+
+ ///
+ /// 告警统计
+ /// GET /api/admin/alert/statistics
+ ///
+ [HttpGet]
+ [Route("statistics")]
+ public IHttpActionResult GetStatistics()
+ {
+ var result = _alertService.GetStatistics();
+ return Ok(ApiResponse.Success(result));
+ }
+
+ ///
+ /// 处理单条告警
+ /// PUT /api/admin/alert/{id}/resolve
+ ///
+ [HttpPut]
+ [Route("{id:long}/resolve")]
+ public IHttpActionResult Resolve(long id)
+ {
+ var result = _alertService.Resolve(id);
+ return Ok(ApiResponse