解决冲突

This commit is contained in:
2026-08-28 10:41:47 +08:00
98 changed files with 1389 additions and 20 deletions
@@ -15,6 +15,7 @@ namespace IOT_API.Controllers.Asset
/// </summary>
[Route("api/Equipment")] //资产管理模块下的设备管理接口
[ApiController]
[Route("api/asset/equipment")]
public class EquipmentController : ControllerBase
{
private readonly IEquipmentService _equipmentService;
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 二维码
/// </summary>
[ApiController]
[Route("api/asset/qrcode")]
public class QrCodeController : ControllerBase
{
// TODO: 实现 二维码 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 证书管理
/// </summary>
[ApiController]
[Route("api/config/certificate")]
public class CertificateController : ControllerBase
{
// TODO: 实现 证书管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 采集点位配置
/// </summary>
[ApiController]
[Route("api/config/collection-point")]
public class CollectionPointController : ControllerBase
{
// TODO: 实现 采集点位配置 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 采集策略管理
/// </summary>
[ApiController]
[Route("api/config/collection-strategy")]
public class CollectionStrategyController : ControllerBase
{
// TODO: 实现 采集策略管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 数据清洗与转换
/// </summary>
[ApiController]
[Route("api/config/data-cleaning")]
public class DataCleaningController : ControllerBase
{
// TODO: 实现 数据清洗与转换 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 设备网关
/// </summary>
[ApiController]
[Route("api/config/device-gateway")]
public class DeviceGatewayController : ControllerBase
{
// TODO: 实现 设备网关 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 网关管理
/// </summary>
[ApiController]
[Route("api/config/gateway")]
public class GatewayController : ControllerBase
{
// TODO: 实现 网关管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// IOT设备管理
/// </summary>
[ApiController]
[Route("api/config/device")]
public class IotDeviceController : ControllerBase
{
// TODO: 实现 IOT设备管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 网络组件与协议注册
/// </summary>
[ApiController]
[Route("api/config/network-component")]
public class NetworkComponentController : ControllerBase
{
// TODO: 实现 网络组件与协议注册 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 产品管理
/// </summary>
[ApiController]
[Route("api/config/product")]
public class ProductController : ControllerBase
{
// TODO: 实现 产品管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 协议管理
/// </summary>
[ApiController]
[Route("api/config/protocol")]
public class ProtocolController : ControllerBase
{
// TODO: 实现 协议管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 协议模板库
/// </summary>
[ApiController]
[Route("api/config/protocol-template")]
public class ProtocolTemplateController : ControllerBase
{
// TODO: 实现 协议模板库 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 时序数据存储
/// </summary>
[ApiController]
[Route("api/config/time-series")]
public class TimeSeriesStorageController : ControllerBase
{
// TODO: 实现 时序数据存储 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 消息告警
/// </summary>
[ApiController]
[Route("api/inspection/alert-message")]
public class AlertMessageController : ControllerBase
{
// TODO: 实现 消息告警 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 告警规则
/// </summary>
[ApiController]
[Route("api/inspection/alert-rule")]
public class AlertRuleController : ControllerBase
{
// TODO: 实现 告警规则 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 数据大屏
/// </summary>
[ApiController]
[Route("api/inspection/bigscreen")]
public class BigScreenController : ControllerBase
{
// TODO: 实现 数据大屏 相关接口
}
}
@@ -0,0 +1,41 @@
using Microsoft.AspNetCore.Mvc;
using Service.Interface;
namespace WebAPI.Controllers
{
/// <summary>
/// 设备看板(温湿度)
/// </summary>
[ApiController]
[Route("api/inspection/dashboard")]
public class DeviceDashboardController : ControllerBase
{
private readonly IDeviceDashboardService _dashboardService;
public DeviceDashboardController(IDeviceDashboardService dashboardService)
{
_dashboardService = dashboardService;
}
/// <summary>
/// 获取所有环境箱的最新温湿度数据(看板卡片,前端轮询调用)
/// </summary>
[HttpGet("realtime")]
public async Task<IActionResult> GetRealtime()
{
return Ok(await _dashboardService.GetRealtimeAsync());
}
/// <summary>
/// 获取指定环境箱最近 N 分钟的温湿度曲线数据
/// </summary>
/// <param name="deviceCode">设备标识,如 BOX-001</param>
/// <param name="minutes">最近多少分钟,默认 5,最大 60</param>
[HttpGet("curve")]
public async Task<IActionResult> GetCurve([FromQuery] string deviceCode, [FromQuery] int minutes = 5)
{
minutes = Math.Clamp(minutes, 1, 60);
return Ok(await _dashboardService.GetCurveAsync(deviceCode, minutes));
}
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 设备效率分析
/// </summary>
[ApiController]
[Route("api/inspection/efficiency")]
public class EfficiencyController : ControllerBase
{
// TODO: 实现 设备效率分析 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 巡检管理
/// </summary>
[ApiController]
[Route("api/inspection/patrol")]
public class PatrolController : ControllerBase
{
// TODO: 实现 巡检管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 统计报表
/// </summary>
[ApiController]
[Route("api/inspection/report")]
public class StatisticsReportController : ControllerBase
{
// TODO: 实现 统计报表 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 访问日志
/// </summary>
[ApiController]
[Route("api/system/access-log")]
public class AccessLogController : ControllerBase
{
// TODO: 实现 访问日志 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 操作审计日志
/// </summary>
[ApiController]
[Route("api/system/audit")]
public class AuditController : ControllerBase
{
// TODO: 实现 操作审计日志 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 数据字典管理
/// </summary>
[ApiController]
[Route("api/system/dict")]
public class DictController : ControllerBase
{
// TODO: 实现 数据字典管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 文件存储管理
/// </summary>
[ApiController]
[Route("api/system/file-storage")]
public class FileStorageController : ControllerBase
{
// TODO: 实现 文件存储管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 组织架构管理
/// </summary>
[ApiController]
[Route("api/system/organization")]
public class OrganizationController : ControllerBase
{
// TODO: 实现 组织架构管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 角色权限管理
/// </summary>
[ApiController]
[Route("api/system/role")]
public class RoleController : ControllerBase
{
// TODO: 实现 角色权限管理 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 系统日志
/// </summary>
[ApiController]
[Route("api/system/system-log")]
public class SystemLogController : ControllerBase
{
// TODO: 实现 系统日志 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 系统参数配置
/// </summary>
[ApiController]
[Route("api/system/param")]
public class SystemParamController : ControllerBase
{
// TODO: 实现 系统参数配置 相关接口
}
}
@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPI.Controllers
{
/// <summary>
/// 用户管理
/// </summary>
[ApiController]
[Route("api/system/user")]
public class UserController : ControllerBase
{
// TODO: 实现 用户管理 相关接口
}
}
+48
View File
@@ -0,0 +1,48 @@
using Service.Implement;
using System.Reflection;
namespace WebAPI
{
/// <summary>
/// 业务服务依赖注入扩展
/// 约定:Service.Interface 中的 IXxxService 对应 Service.Implement 中的 XxxService
/// </summary>
public static class DependencyInjection
{
/// <summary>
/// 自动注册所有业务服务(按命名约定:接口去掉前缀 I 即为实现类名)
/// 以后在 Service 项目里新增「接口 + 实现」时,无需改动这里,会自动注册
/// </summary>
public static IServiceCollection AddBusinessServices(this IServiceCollection services)
{
// Service 项目程序集(接口与实现都在同一个程序集里)
Assembly assembly = typeof(BaseService<>).Assembly;
// 所有具体实现类(非抽象、非泛型定义)
var implTypes = assembly.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericTypeDefinition)
.ToList();
// 所有接口
var ifaceTypes = assembly.GetTypes()
.Where(t => t.IsInterface && !t.IsGenericTypeDefinition)
.ToList();
foreach (var iface in ifaceTypes)
{
// 接口名去掉前缀 I,得到期望的实现类名
string implName = iface.Name.StartsWith("I") ? iface.Name.Substring(1) : iface.Name;
var impl = implTypes.FirstOrDefault(t => t.Name == implName);
if (impl != null && iface.IsAssignableFrom(impl))
{
services.AddScoped(iface, impl);
}
}
// 泛型基础服务(IBaseService<> -> BaseService<>)单独注册
services.AddScoped(typeof(Service.Interface.IBaseService<>), typeof(Service.Implement.BaseService<>));
return services;
}
}
}
+26 -12
View File
@@ -1,6 +1,7 @@
using Common;
using ORM;
using System.Text.Json;
using WebAPI.Services;
namespace WebAPI
{
@@ -8,30 +9,42 @@ namespace WebAPI
{
public static void Main(string[] args)
{
// ======= תδ쳣ʱԶ MiniDump =======
//dump文件崩溃记录(不用或者使用后记得去编译路径删除,.dump文件体积很大)
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
//¼dumpļ
Exception ex = e.ExceptionObject as Exception;
MiniDump.TryDump($"dumps\\Error_{DateTime.Now:yyyy-MM-dd HH-mm-ss-ms}.dmp", MiniDump.Option.WithFullMemory, ex);
string exeDir = AppContext.BaseDirectory;
string dumpDir = Path.Combine(exeDir, "Dump");
if (!Directory.Exists(dumpDir))
{
Directory.CreateDirectory(dumpDir);
}
string dumpFileName = $"Error_{DateTime.Now:yyyy-MM-dd HH-mm-ss-fff}.dmp";
string dumpFullPath = Path.Combine(dumpDir, dumpFileName);
MiniDump.TryDump(dumpFullPath, MiniDump.Option.WithFullMemory, ex);
};
// ======= ת =======
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// ======= ÿʼ =======
//注册postgre数据库
var db = builder.Configuration.GetSection("Database");
DatabaseConfig.InitPostgreSQL(db["Server"]!, int.Parse(db["Port"] ?? "5432"), db["Database"]!, db["User"]!, db["Password"]!);
if (int.TryParse(db["TenantId"], out var tenantId))
DatabaseConfig.SetTenant(tenantId);
DatabaseConfig.CreateDatabaseAndCheckConnection(createDatabase: true, checkConnection: true);
SqlSugarContext.InitDatabase();
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString;
// 3. ԱԭǿתΪշ壩
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
// ======= ý =======
// 自动注册业务服务(Service.Interface -> Service.Implement
builder.Services.AddBusinessServices();
// 温度箱模拟数据:每秒生成 100 条温湿度入库(真实设备接入后删除)
builder.Services.AddHostedService<TemperatureBoxSimulator>();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
@@ -65,8 +78,9 @@ namespace WebAPI
app.UseSwaggerUI();
}
// עλֻ֧ http ֳʱҪʵע͵ Https ض
app.UseHttpsRedirection();
// 关闭 Https 重定向:开启时会把 http 请求 307 到 https 端口,
// 导致前端 vite 代理被 CORS 拦截(Network Error);上位机/现场部署通常也只用 http
// app.UseHttpsRedirection();
app.UseAuthorization();
@@ -0,0 +1,82 @@
using Model.Entity;
using ORM;
namespace WebAPI.Services
{
/// <summary>
/// 温度箱数据模拟器(临时用)
/// 每秒为 100 台环境箱生成一条模拟温湿度数据并批量写入数据库,
/// 真实设备接入后删除此类及 Program.cs 中的注册即可
/// </summary>
public class TemperatureBoxSimulator : BackgroundService
{
private const int DeviceCount = 100;
private const double AlarmTemp = 80.0; // 高温报警阈值
private static readonly Random Rnd = new();
// 每台设备维护一份模拟状态(随机游走需要基于上一次的值)
private class BoxState
{
public double Temperature = Rnd.Next(20, 60);
public double Humidity = Rnd.Next(30, 70);
}
private readonly Dictionary<string, BoxState> _states = new();
public TemperatureBoxSimulator()
{
for (int i = 1; i <= DeviceCount; i++)
{
_states[$"BOX-{i:D3}"] = new BoxState();
}
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
var now = DateTime.Now;
var batch = new List<TemperatureBoxDataEntity>(DeviceCount);
foreach (var kv in _states)
{
var s = kv.Value;
// 随机游走,让曲线平滑连续
s.Temperature = Math.Clamp(s.Temperature + (Rnd.NextDouble() - 0.48) * 2, 15, 95);
s.Humidity = Math.Clamp(s.Humidity + (Rnd.NextDouble() - 0.5) * 3, 20, 90);
bool alarm = s.Temperature >= AlarmTemp;
batch.Add(new TemperatureBoxDataEntity
{
DeviceCode = kv.Key,
DeviceType = "TemperatureBox",
DeviceTemperature = Math.Round(s.Temperature, 1),
DeviceHumidity = Math.Round(s.Humidity, 1),
Status = alarm ? "报警" : "运行",
AlarmInfo = alarm ? "温度超限报警" : "",
CreateTime = now
});
}
// 批量插入
await SqlSugarContext.DbContext.Insertable(batch).ExecuteCommandAsync();
}
catch (Exception ex)
{
Console.WriteLine($"[温度箱模拟器] 写入失败: {ex.Message}");
}
try
{
await Task.Delay(1000, stoppingToken);
}
catch (TaskCanceledException)
{
break;
}
}
}
}
}
+6 -4
View File
@@ -7,10 +7,12 @@
},
"AllowedHosts": "*",
"Database": {
"Server": "localhost",
"Type": "PostgreSQL",
"Server": "127.0.0.1",
"Port": 5432,
"Database": "iot",
"Uid": "postgres",
"Pwd": "postgres"
"Database": "IOT_WEB",
"User": "postgres",
"Password": "kylt123",
"TenantId": 10001
}
}