923 lines
39 KiB
C#
923 lines
39 KiB
C#
using Abp.Domain.Repositories;
|
||
using Abp.Domain.Uow;
|
||
using Abp.EntityFrameworkCore.Repositories;
|
||
using Abp.Linq.Extensions;
|
||
using Abp.Web.Models;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Linq;
|
||
using System.Net.Http;
|
||
using System.Text;
|
||
using System.Text.Json;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using ToolLibrary.LogHelper;
|
||
using YunDa.SOMS.Application.Core;
|
||
using YunDa.SOMS.Application.Core.Authorization.Accounts;
|
||
using YunDa.SOMS.Application.Core.Session;
|
||
using YunDa.SOMS.Application.Core.SwaggerHelper;
|
||
using YunDa.SOMS.Core.Helper;
|
||
using YunDa.SOMS.DataTransferObject;
|
||
using YunDa.SOMS.DataTransferObject.ExternalEntities.BeijingYounuo;
|
||
using YunDa.SOMS.Entities.ExternalEntities.BeijingYounuo;
|
||
using YunDa.SOMS.Entities.GeneralInformation;
|
||
|
||
namespace YunDa.SOMS.Application.ExternalDataManager.BjYounuo
|
||
{
|
||
/// <summary>
|
||
/// 光纤管理服务
|
||
/// </summary>
|
||
[Description("光纤管理服务")]
|
||
public class OpticalFiberAppService : SOMSAppServiceBase, IOpticalFiberAppService
|
||
{
|
||
private const string AI_API_URL = "http://192.168.81.25:8002/chat/ai";
|
||
|
||
private readonly IRepository<OpticalFiber, Guid> _opticalFiberRepository;
|
||
private readonly IRepository<EquipmentInfo, Guid> _equipmentInfoRepository;
|
||
private readonly HttpClient _httpClient;
|
||
private readonly IConfiguration _configuration;
|
||
private readonly BeijingYounuoApiAppService _beijingYounuoApiAppService;
|
||
|
||
public OpticalFiberAppService(
|
||
ISessionAppService sessionAppService,
|
||
IRepository<OpticalFiber, Guid> opticalFiberRepository,
|
||
IRepository<EquipmentInfo, Guid> equipmentInfoRepository,
|
||
HttpClient httpClient,
|
||
BeijingYounuoApiAppService beijingYounuoApiAppService,
|
||
IConfiguration configuration)
|
||
: base(sessionAppService)
|
||
{
|
||
_opticalFiberRepository = opticalFiberRepository;
|
||
_equipmentInfoRepository = equipmentInfoRepository;
|
||
_httpClient = httpClient;
|
||
_configuration = configuration;
|
||
_beijingYounuoApiAppService = beijingYounuoApiAppService;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建光纤
|
||
/// </summary>
|
||
/// <param name="input">创建输入</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>创建结果</returns>
|
||
[HttpPost]
|
||
public async Task<RequestResult<OpticalFiberDto>> CreateAsync(CreateOpticalFiberInput input, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
// 验证输入
|
||
await ValidateCreateInputAsync(input, cancellationToken).ConfigureAwait(false);
|
||
|
||
var currentUser = GetCurrentUser();
|
||
var entity = ObjectMapper.Map<OpticalFiber>(input);
|
||
|
||
entity.CreationTime = DateTime.Now;
|
||
entity.CreatorUserId = currentUser.Id;
|
||
entity.IsActive = true;
|
||
|
||
var createdEntity = await _opticalFiberRepository.InsertAsync(entity);
|
||
await CurrentUnitOfWork.SaveChangesAsync();
|
||
|
||
var result = ObjectMapper.Map<OpticalFiberDto>(createdEntity);
|
||
|
||
// 获取关联设备信息
|
||
if (createdEntity.EquipmentInfoId.HasValue)
|
||
{
|
||
var equipmentInfo = await _equipmentInfoRepository.GetAsync(createdEntity.EquipmentInfoId.Value);
|
||
result.EquipmentInfoName = equipmentInfo?.Name;
|
||
}
|
||
|
||
return RequestResult<OpticalFiberDto>.CreateSuccess(result, "光纤创建成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"创建光纤失败: {ex.Message}", ex);
|
||
return RequestResult<OpticalFiberDto>.CreateFailed($"创建光纤失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新光纤
|
||
/// </summary>
|
||
/// <param name="input">更新输入</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>更新结果</returns>
|
||
[HttpPost]
|
||
public async Task<RequestResult<OpticalFiberDto>> UpdateAsync(UpdateOpticalFiberInput input, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
// 验证输入
|
||
await ValidateUpdateInputAsync(input, cancellationToken).ConfigureAwait(false);
|
||
|
||
var entity = await _opticalFiberRepository.GetAsync(input.Id);
|
||
if (entity == null)
|
||
{
|
||
return RequestResult<OpticalFiberDto>.CreateFailed("光纤不存在");
|
||
}
|
||
|
||
var currentUser = GetCurrentUser();
|
||
|
||
// 更新实体属性
|
||
ObjectMapper.Map(input, entity);
|
||
entity.LastModificationTime = DateTime.Now;
|
||
entity.LastModifierUserId = currentUser.Id;
|
||
|
||
var updatedEntity = await _opticalFiberRepository.UpdateAsync(entity);
|
||
await CurrentUnitOfWork.SaveChangesAsync();
|
||
|
||
var result = ObjectMapper.Map<OpticalFiberDto>(updatedEntity);
|
||
|
||
// 获取关联设备信息
|
||
if (updatedEntity.EquipmentInfoId.HasValue)
|
||
{
|
||
var equipmentInfo = await _equipmentInfoRepository.GetAsync(updatedEntity.EquipmentInfoId.Value);
|
||
result.EquipmentInfoName = equipmentInfo?.Name;
|
||
}
|
||
|
||
return RequestResult<OpticalFiberDto>.CreateSuccess(result, "光纤更新成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"更新光纤失败: {ex.Message}", ex);
|
||
return RequestResult<OpticalFiberDto>.CreateFailed($"更新光纤失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据ID获取光纤
|
||
/// </summary>
|
||
/// <param name="id">光纤ID</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>光纤信息</returns>
|
||
public async Task<RequestResult<OpticalFiberDto>> GetAsync(Guid id, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
var entity = await _opticalFiberRepository.GetAsync(id);
|
||
if (entity == null)
|
||
{
|
||
return RequestResult<OpticalFiberDto>.CreateFailed("光纤不存在");
|
||
}
|
||
|
||
var result = ObjectMapper.Map<OpticalFiberDto>(entity);
|
||
|
||
// 获取关联设备信息
|
||
if (entity.EquipmentInfoId.HasValue)
|
||
{
|
||
var equipmentInfo = await _equipmentInfoRepository.GetAsync(entity.EquipmentInfoId.Value);
|
||
result.EquipmentInfoName = equipmentInfo?.Name;
|
||
}
|
||
|
||
return RequestResult<OpticalFiberDto>.CreateSuccess(result);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"获取光纤失败: {ex.Message}", ex);
|
||
return RequestResult<OpticalFiberDto>.CreateFailed($"获取光纤失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除光纤
|
||
/// </summary>
|
||
/// <param name="id">光纤ID</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>删除结果</returns>
|
||
public async Task<RequestEasyResult> DeleteAsync(Guid id, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
var entity = await _opticalFiberRepository.GetAsync(id);
|
||
if (entity == null)
|
||
{
|
||
return RequestEasyResult.CreateFailed("光纤不存在");
|
||
}
|
||
|
||
await _opticalFiberRepository.DeleteAsync(entity);
|
||
await CurrentUnitOfWork.SaveChangesAsync();
|
||
|
||
return RequestEasyResult.CreateSuccess("光纤删除成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"删除光纤失败: {ex.Message}", ex);
|
||
return RequestEasyResult.CreateFailed($"删除光纤失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批量删除光纤
|
||
/// </summary>
|
||
/// <param name="ids">光纤ID列表</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>删除结果</returns>
|
||
[HttpPost]
|
||
public async Task<RequestEasyResult> BatchDeleteAsync(List<Guid> ids, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
if (ids == null || !ids.Any())
|
||
{
|
||
return RequestEasyResult.CreateFailed("请选择要删除的光纤");
|
||
}
|
||
|
||
var entities = await _opticalFiberRepository.GetAll()
|
||
.Where(x => ids.Contains(x.Id))
|
||
.ToListAsync(cancellationToken);
|
||
|
||
if (!entities.Any())
|
||
{
|
||
return RequestEasyResult.CreateFailed("未找到要删除的光纤");
|
||
}
|
||
|
||
foreach (var entity in entities)
|
||
{
|
||
await _opticalFiberRepository.DeleteAsync(entity);
|
||
}
|
||
|
||
await CurrentUnitOfWork.SaveChangesAsync();
|
||
|
||
return RequestEasyResult.CreateSuccess($"成功删除 {entities.Count} 条光纤记录");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"批量删除光纤失败: {ex.Message}", ex);
|
||
return RequestEasyResult.CreateFailed($"批量删除光纤失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取光纤列表
|
||
/// </summary>
|
||
/// <param name="input">查询条件</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>光纤列表</returns>
|
||
[HttpPost]
|
||
[AllowAnonymous]
|
||
[ShowApi]
|
||
public async Task<RequestPageResult<OpticalFiberDto>> GetListAsync(GetOpticalFiberInput input, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
var query = _opticalFiberRepository.GetAll()
|
||
.WhereIf(!string.IsNullOrWhiteSpace(input.CiCode), x => x.CiCode.Contains(input.CiCode))
|
||
.WhereIf(!string.IsNullOrWhiteSpace(input.TwinId), x => x.TwinId.Contains(input.TwinId))
|
||
.WhereIf(!string.IsNullOrWhiteSpace(input.P1DeviceNumber), x => x.P1DeviceNumber.Contains(input.P1DeviceNumber))
|
||
.WhereIf(!string.IsNullOrWhiteSpace(input.VirtualPointCode), x => x.VirtualPointCode.Contains(input.VirtualPointCode))
|
||
.WhereIf(input.IsActive.HasValue, x => x.IsActive == input.IsActive.Value);
|
||
|
||
var totalCount = await query.CountAsync(cancellationToken);
|
||
|
||
var entities = await query
|
||
.OrderByDescending(x => x.CreationTime)
|
||
.ToListAsync(cancellationToken);
|
||
|
||
var dtos = ObjectMapper.Map<List<OpticalFiberDto>>(entities);
|
||
|
||
// 获取关联设备信息
|
||
var equipmentIds = entities.Where(x => x.EquipmentInfoId.HasValue)
|
||
.Select(x => x.EquipmentInfoId.Value).Distinct().ToList();
|
||
|
||
if (equipmentIds.Any())
|
||
{
|
||
var equipments = await _equipmentInfoRepository.GetAll()
|
||
.Where(x => equipmentIds.Contains(x.Id))
|
||
.Select(x => new { x.Id, x.Name })
|
||
.ToListAsync(cancellationToken);
|
||
|
||
foreach (var dto in dtos)
|
||
{
|
||
if (dto.EquipmentInfoId.HasValue)
|
||
{
|
||
var equipment = equipments.FirstOrDefault(x => x.Id == dto.EquipmentInfoId.Value);
|
||
dto.EquipmentInfoName = equipment?.Name;
|
||
}
|
||
}
|
||
}
|
||
|
||
return RequestPageResult<OpticalFiberDto>.CreateSuccess(dtos, totalCount, input.PageIndex, input.PageSize);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"获取光纤列表失败: {ex.Message}", ex);
|
||
return RequestPageResult<OpticalFiberDto>.CreateFailed($"获取光纤列表失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批量创建光纤
|
||
/// </summary>
|
||
/// <param name="input">批量创建输入</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>批量创建结果</returns>
|
||
public async Task<RequestEasyResult> BatchCreateAsync(BatchCreateOpticalFiberInput input, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
if (input == null || string.IsNullOrWhiteSpace(input.JsonArrayData))
|
||
{
|
||
return RequestEasyResult.CreateFailed("请提供要创建的光纤数据");
|
||
}
|
||
|
||
// 解析JSON数据
|
||
var createInputs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CreateOpticalFiberInput>>(input.JsonArrayData);
|
||
if (createInputs == null || !createInputs.Any())
|
||
{
|
||
return RequestEasyResult.CreateFailed("JSON数据格式不正确或为空");
|
||
}
|
||
|
||
var currentUser = GetCurrentUser();
|
||
var entities = new List<OpticalFiber>();
|
||
|
||
foreach (var createInput in createInputs)
|
||
{
|
||
try
|
||
{
|
||
await ValidateCreateInputAsync(createInput, cancellationToken).ConfigureAwait(false);
|
||
|
||
var entity = ObjectMapper.Map<OpticalFiber>(createInput);
|
||
entity.CreationTime = DateTime.Now;
|
||
entity.CreatorUserId = currentUser.Id;
|
||
entity.IsActive = true;
|
||
|
||
entities.Add(entity);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Warning(GetType(), $"批量创建中单个光纤验证失败,孪生体ID: {createInput.TwinId}", ex);
|
||
// 继续处理其他项目
|
||
}
|
||
}
|
||
|
||
if (!entities.Any())
|
||
{
|
||
return RequestEasyResult.CreateFailed("没有有效的光纤数据可以创建");
|
||
}
|
||
|
||
await _opticalFiberRepository.GetDbContext().AddRangeAsync(entities, cancellationToken);
|
||
await CurrentUnitOfWork.SaveChangesAsync();
|
||
|
||
return RequestEasyResult.CreateSuccess($"成功创建 {entities.Count} 条光纤记录");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"批量创建光纤失败: {ex.Message}", ex);
|
||
return RequestEasyResult.CreateFailed($"批量创建光纤失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
#region 私有方法
|
||
|
||
/// <summary>
|
||
/// 验证创建输入
|
||
/// </summary>
|
||
/// <param name="input">创建输入</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns></returns>
|
||
private async Task ValidateCreateInputAsync(CreateOpticalFiberInput input, CancellationToken cancellationToken)
|
||
{
|
||
if (input == null)
|
||
throw new ArgumentNullException(nameof(input));
|
||
|
||
if (string.IsNullOrWhiteSpace(input.TwinId))
|
||
throw new ArgumentException("孪生体ID不能为空");
|
||
|
||
if (string.IsNullOrWhiteSpace(input.P1DeviceNumber))
|
||
throw new ArgumentException("P1设备编号不能为空");
|
||
|
||
if (string.IsNullOrWhiteSpace(input.P1PortNumber))
|
||
throw new ArgumentException("P1端口编号不能为空");
|
||
|
||
if (string.IsNullOrWhiteSpace(input.P2DeviceNumber))
|
||
throw new ArgumentException("P2设备编号不能为空");
|
||
|
||
if (string.IsNullOrWhiteSpace(input.P2PortNumber))
|
||
throw new ArgumentException("P2端口编号不能为空");
|
||
|
||
// 检查孪生体ID是否已存在
|
||
var existingEntity = await _opticalFiberRepository.FirstOrDefaultAsync(x => x.TwinId == input.TwinId);
|
||
if (existingEntity != null)
|
||
throw new InvalidOperationException($"孪生体ID '{input.TwinId}' 已存在");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证更新输入
|
||
/// </summary>
|
||
/// <param name="input">更新输入</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns></returns>
|
||
private async Task ValidateUpdateInputAsync(UpdateOpticalFiberInput input, CancellationToken cancellationToken)
|
||
{
|
||
if (input == null)
|
||
throw new ArgumentNullException(nameof(input));
|
||
|
||
if (input.Id == Guid.Empty)
|
||
throw new ArgumentException("光纤ID不能为空");
|
||
|
||
// 检查孪生体ID是否与其他记录冲突
|
||
if (!string.IsNullOrWhiteSpace(input.TwinId))
|
||
{
|
||
var existingEntity = await _opticalFiberRepository.FirstOrDefaultAsync(x => x.TwinId == input.TwinId && x.Id != input.Id);
|
||
if (existingEntity != null)
|
||
throw new InvalidOperationException($"孪生体ID '{input.TwinId}' 已被其他记录使用");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 激活/停用光纤
|
||
/// </summary>
|
||
/// <param name="id">光纤ID</param>
|
||
/// <param name="isActive">是否激活</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>操作结果</returns>
|
||
public async Task<RequestEasyResult> SetActiveAsync(Guid id, bool isActive, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
var entity = await _opticalFiberRepository.GetAsync(id);
|
||
if (entity == null)
|
||
{
|
||
return RequestEasyResult.CreateFailed("光纤记录不存在");
|
||
}
|
||
|
||
entity.IsActive = isActive;
|
||
await _opticalFiberRepository.UpdateAsync(entity);
|
||
await CurrentUnitOfWork.SaveChangesAsync();
|
||
|
||
var statusText = isActive ? "激活" : "停用";
|
||
return RequestEasyResult.CreateSuccess($"光纤{statusText}成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"设置光纤状态失败: {ex.Message}", ex);
|
||
return RequestEasyResult.CreateFailed($"设置光纤状态失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 模拟断线功能 - 根据孪生体ID生成处置意见和影响范围
|
||
/// </summary>
|
||
[AllowAnonymous]
|
||
[ShowApi]
|
||
[HttpGet]
|
||
public async Task<RequestResult<DisconnectionSimulationResult>> SimulateDisconnectionAsync(string twinId, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrWhiteSpace(twinId))
|
||
{
|
||
return RequestResult<DisconnectionSimulationResult>.CreateFailed("孪生体ID不能为空");
|
||
}
|
||
|
||
// 查找光纤配置
|
||
var opticalFiber = await _opticalFiberRepository.GetAll()
|
||
.FirstOrDefaultAsync(x => x.TwinId == twinId, cancellationToken);
|
||
|
||
if (opticalFiber == null)
|
||
{
|
||
return RequestResult<DisconnectionSimulationResult>.CreateFailed($"未找到孪生体ID为 {twinId} 的光纤配置");
|
||
}
|
||
|
||
// 生成处置意见
|
||
var disposalAdvice = GenerateOpticalFiberDisposalAdvice(opticalFiber);
|
||
|
||
// 生成影响范围
|
||
var (impactScopeField, impactScopeDescription) = GenerateOpticalFiberImpactScope(opticalFiber);
|
||
|
||
var result = new DisconnectionSimulationResult
|
||
{
|
||
TwinId = twinId,
|
||
DisposalAdvice = disposalAdvice,
|
||
ImpactScopeField = impactScopeField,
|
||
ImpactScopeDescription = impactScopeDescription,
|
||
ConnectionType = "光纤",
|
||
P1EndInfo = new ConnectionEndInfo
|
||
{
|
||
CabinetName = opticalFiber.P1CabinetName,
|
||
DeviceName = opticalFiber.P1DeviceName,
|
||
DeviceNumber = opticalFiber.P1DeviceNumber,
|
||
PortNumber = opticalFiber.P1PortNumber,
|
||
InputPort = opticalFiber.P1InputPort
|
||
},
|
||
P2EndInfo = new ConnectionEndInfo
|
||
{
|
||
CabinetName = opticalFiber.P2CabinetName,
|
||
DeviceName = opticalFiber.P2DeviceName,
|
||
DeviceNumber = opticalFiber.P2DeviceNumber,
|
||
PortNumber = opticalFiber.P2PortNumber,
|
||
InputPort = opticalFiber.P2InputPort
|
||
}
|
||
};
|
||
|
||
return RequestResult<DisconnectionSimulationResult>.CreateSuccess(result);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"模拟光纤断线失败: {ex.Message}", ex);
|
||
return RequestResult<DisconnectionSimulationResult>.CreateFailed($"模拟光纤断线失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取光纤断线模拟响应 - 返回简单格式的JSON响应
|
||
/// </summary>
|
||
[AllowAnonymous]
|
||
[ShowApi]
|
||
[HttpPost]
|
||
[DontWrapResult]
|
||
public async Task<SimpleDisconnectionResponse> GetSimulatedDisconnectionResponseAsync(object obj, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
JObject jsonObject = JObject.Parse(obj.ToString());
|
||
string twinId = jsonObject["孪生体ID"]?.ToString();
|
||
if (string.IsNullOrWhiteSpace(twinId))
|
||
{
|
||
return new SimpleDisconnectionResponse
|
||
{
|
||
Code = 400,
|
||
Success = false,
|
||
Data = "孪生体ID不能为空"
|
||
};
|
||
}
|
||
|
||
// 查找光纤配置
|
||
var opticalFiber = await _opticalFiberRepository.GetAll()
|
||
.FirstOrDefaultAsync(x => x.TwinId == twinId, cancellationToken);
|
||
|
||
if (opticalFiber == null)
|
||
{
|
||
return new SimpleDisconnectionResponse
|
||
{
|
||
Code = 404,
|
||
Success = false,
|
||
Data = $"未找到孪生体ID为 {twinId} 的光纤配置"
|
||
};
|
||
}
|
||
|
||
string responseData;
|
||
|
||
// 尝试使用AI生成智能响应
|
||
try
|
||
{
|
||
var prompt = BuildOpticalFiberDisconnectionPrompt(opticalFiber);
|
||
var aiResponse = await CallAiApiAsync(prompt, cancellationToken).ConfigureAwait(false);
|
||
var aiContent = ParseAiStreamingResponse(aiResponse);
|
||
|
||
if (!string.IsNullOrWhiteSpace(aiContent))
|
||
{
|
||
responseData = aiContent;
|
||
Log4Helper.Info(GetType(), $"成功使用AI生成光纤断线响应,孪生体ID: {twinId}");
|
||
}
|
||
else
|
||
{
|
||
// AI返回空内容,使用静态生成方法
|
||
Log4Helper.Warning(GetType(), $"AI返回空内容,使用静态生成方法,孪生体ID: {twinId}");
|
||
var (impactScopeField, impactScopeDescription) = GenerateOpticalFiberImpactScope(opticalFiber);
|
||
var disposalAdvice = GenerateOpticalFiberDisposalAdvice(opticalFiber);
|
||
responseData = $"影响范围:\n{impactScopeDescription}\n{disposalAdvice}";
|
||
}
|
||
}
|
||
catch (Exception aiEx)
|
||
{
|
||
// AI调用失败,使用静态生成方法作为后备
|
||
Log4Helper.Warning(GetType(), $"AI API调用失败,使用静态生成方法,孪生体ID: {twinId}", aiEx);
|
||
var (impactScopeField, impactScopeDescription) = GenerateOpticalFiberImpactScope(opticalFiber);
|
||
var disposalAdvice = GenerateOpticalFiberDisposalAdvice(opticalFiber);
|
||
responseData = $"影响范围:\n{impactScopeDescription}\n{disposalAdvice}";
|
||
}
|
||
|
||
// 推送告警
|
||
YounuoAlert alert = new YounuoAlert
|
||
{
|
||
LastOccurrence = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||
Severity = 5,
|
||
SourceAlertKey = "模拟光纤断线",
|
||
Status = 1,
|
||
SourceIdentifier = opticalFiber.P1DeviceNumber,
|
||
Summary = "模拟光纤断线",
|
||
TwinID = twinId,
|
||
};
|
||
await _beijingYounuoApiAppService.PushYounuoAlertAsync(alert);
|
||
|
||
return new SimpleDisconnectionResponse
|
||
{
|
||
Code = 200,
|
||
Success = true,
|
||
Data = responseData
|
||
};
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(this.GetType(), $"获取光纤断线模拟响应失败: {ex.Message}", ex);
|
||
return new SimpleDisconnectionResponse
|
||
{
|
||
Code = 500,
|
||
Success = false,
|
||
Data = $"系统异常: {ex.Message}"
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成光纤处置意见
|
||
/// </summary>
|
||
private string GenerateOpticalFiberDisposalAdvice(OpticalFiber opticalFiber)
|
||
{
|
||
var advice = "处置意见:\n";
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.P1DeviceName) && !string.IsNullOrEmpty(opticalFiber.P1PortNumber))
|
||
{
|
||
advice += $"1.检查{opticalFiber.P1DeviceName}设备的{opticalFiber.P1PortNumber}光纤接收端口\n";
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.P1CabinetName))
|
||
{
|
||
advice += $"2.检查{opticalFiber.P1CabinetName}对应的光纤连接状态\n";
|
||
}
|
||
|
||
advice += "3.确认光纤跳线和接头是否松动或损坏\n";
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.VirtualPointCode))
|
||
{
|
||
advice += $"4.检查虚点编码{opticalFiber.VirtualPointCode}的配置状态\n";
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.P2DeviceName) && !string.IsNullOrEmpty(opticalFiber.P2PortNumber))
|
||
{
|
||
advice += $"5.检查{opticalFiber.P2DeviceName}设备的{opticalFiber.P2PortNumber}光纤接收端口\n";
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.P2CabinetName))
|
||
{
|
||
advice += $"6.检查{opticalFiber.P2CabinetName}对应的光纤连接状态";
|
||
}
|
||
|
||
return advice;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成光纤影响范围
|
||
/// </summary>
|
||
private (string impactScopeField, string impactScopeDescription) GenerateOpticalFiberImpactScope(OpticalFiber opticalFiber)
|
||
{
|
||
var impactScopeField = "";
|
||
var impactScopeDescription = "光纤连接异常,具体包括:\n";
|
||
|
||
// 解析影响范围字段,提取设备名称和地址
|
||
if (!string.IsNullOrEmpty(opticalFiber.ImpactScope))
|
||
{
|
||
impactScopeField = opticalFiber.ImpactScope;
|
||
|
||
// 解析影响范围中的设备和地址信息
|
||
var regex = new Regex(@"\{([^}]+)\}");
|
||
var matches = regex.Matches(opticalFiber.ImpactScope);
|
||
|
||
int index = 1;
|
||
foreach (Match match in matches)
|
||
{
|
||
var content = match.Groups[1].Value;
|
||
if (int.TryParse(content, out _))
|
||
{
|
||
// 数字地址
|
||
impactScopeDescription += $"{index}. 地址 {content} 相关数据异常\n";
|
||
}
|
||
else
|
||
{
|
||
// 设备名称
|
||
impactScopeDescription += $"{index}. {content}相关数据异常\n";
|
||
}
|
||
index++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 如果没有配置影响范围,基于P1和P2端信息生成
|
||
if (!string.IsNullOrEmpty(opticalFiber.P1DeviceName))
|
||
{
|
||
impactScopeField += $"{{{opticalFiber.P1DeviceName}}}";
|
||
impactScopeDescription += $"1. {opticalFiber.P1DeviceName}相关数据异常\n";
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.P2DeviceName))
|
||
{
|
||
impactScopeField += $"{{{opticalFiber.P2DeviceName}}}";
|
||
impactScopeDescription += $"2. {opticalFiber.P2DeviceName}相关数据异常\n";
|
||
}
|
||
}
|
||
|
||
return (impactScopeField, impactScopeDescription.TrimEnd('\n'));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过孪生体代码获取设备信息ID
|
||
/// </summary>
|
||
/// <param name="code">孪生体代码</param>
|
||
/// <param name="cancellationToken">取消令牌</param>
|
||
/// <returns>设备信息ID</returns>
|
||
[HttpGet]
|
||
[AllowAnonymous]
|
||
[ShowApi]
|
||
public async Task<RequestResult<Guid>> GetTwIdAsync(string code, CancellationToken cancellationToken = default)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrWhiteSpace(code))
|
||
{
|
||
return RequestResult<Guid>.CreateFailed("孪生体代码不能为空");
|
||
}
|
||
|
||
// 从配置中获取API基础URL
|
||
var baseUrl = _configuration.GetSection("SysBaseConfig:IsmsGateWayIp").Value;
|
||
if (string.IsNullOrWhiteSpace(baseUrl))
|
||
{
|
||
Log4Helper.Warning(GetType(), "未配置IsmsGateWayIp,使用默认值");
|
||
baseUrl = "http://127.0.0.1:38094";
|
||
}
|
||
|
||
// 构建完整的API URL
|
||
var fullUrl = $"{baseUrl.TrimEnd('/')}/api/services/SOMS/RackEquipment/GetTwId?code={Uri.EscapeDataString(code)}";
|
||
|
||
Log4Helper.Info(GetType(), $"调用GetTwId API: {fullUrl}");
|
||
|
||
// 发送HTTP GET请求
|
||
var response = await _httpClient.GetAsync(fullUrl, cancellationToken).ConfigureAwait(false);
|
||
|
||
if (response.IsSuccessStatusCode)
|
||
{
|
||
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||
Log4Helper.Debug(GetType(), $"GetTwId API响应: {responseContent}");
|
||
|
||
// 反序列化响应
|
||
var result = JsonConvert.DeserializeObject<RequestResult<Guid>>(responseContent);
|
||
|
||
if (result != null)
|
||
{
|
||
Log4Helper.Info(GetType(), $"成功获取TwId,代码: {code}, 设备信息ID: {result.ResultData}");
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
Log4Helper.Warning(GetType(), $"GetTwId API返回空结果,代码: {code}");
|
||
return RequestResult<Guid>.CreateFailed("API返回空结果");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var errorContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||
Log4Helper.Error(GetType(), $"GetTwId API调用失败,状态码: {response.StatusCode}, 错误内容: {errorContent}");
|
||
return RequestResult<Guid>.CreateFailed($"API调用失败: {response.StatusCode}");
|
||
}
|
||
}
|
||
catch (HttpRequestException ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"调用GetTwId API时发生HTTP请求异常,代码: {code}", ex);
|
||
return RequestResult<Guid>.CreateFailed($"网络请求异常: {ex.Message}");
|
||
}
|
||
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
|
||
{
|
||
Log4Helper.Error(GetType(), $"调用GetTwId API超时,代码: {code}", ex);
|
||
return RequestResult<Guid>.CreateFailed("API调用超时");
|
||
}
|
||
catch (TaskCanceledException ex) when (cancellationToken.IsCancellationRequested)
|
||
{
|
||
Log4Helper.Warning(GetType(), $"GetTwId API调用被取消,代码: {code}");
|
||
return RequestResult<Guid>.CreateFailed("请求已取消");
|
||
}
|
||
catch (JsonException ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"调用GetTwId API时发生JSON反序列化错误,代码: {code}", ex);
|
||
return RequestResult<Guid>.CreateFailed($"响应解析失败: {ex.Message}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log4Helper.Error(GetType(), $"调用GetTwId API时发生未知错误,代码: {code}", ex);
|
||
return RequestResult<Guid>.CreateFailed($"未知错误: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
#region AI Integration Helper Methods
|
||
|
||
/// <summary>
|
||
/// 构建光纤断线场景的AI提示词
|
||
/// </summary>
|
||
private string BuildOpticalFiberDisconnectionPrompt(OpticalFiber opticalFiber)
|
||
{
|
||
var prompt = new StringBuilder();
|
||
prompt.AppendLine("请作为一名专业的电力系统运维专家,分析以下光纤断线场景并提供详细的影响范围分析和处置建议。");
|
||
prompt.AppendLine();
|
||
prompt.AppendLine("【断线信息】");
|
||
prompt.AppendLine($"- 连接类型:光纤");
|
||
prompt.AppendLine($"- 孪生体ID:{opticalFiber.TwinId}");
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.P1CabinetName))
|
||
prompt.AppendLine($"- P1端屏柜:{opticalFiber.P1CabinetName}");
|
||
if (!string.IsNullOrEmpty(opticalFiber.P1DeviceNumber))
|
||
prompt.AppendLine($"- P1端设备编号:{opticalFiber.P1DeviceNumber}");
|
||
if (!string.IsNullOrEmpty(opticalFiber.P1PortNumber))
|
||
prompt.AppendLine($"- P1端端口:{opticalFiber.P1PortNumber}");
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.P2CabinetName))
|
||
prompt.AppendLine($"- P2端屏柜:{opticalFiber.P2CabinetName}");
|
||
if (!string.IsNullOrEmpty(opticalFiber.P2DeviceNumber))
|
||
prompt.AppendLine($"- P2端设备编号:{opticalFiber.P2DeviceNumber}");
|
||
if (!string.IsNullOrEmpty(opticalFiber.P2PortNumber))
|
||
prompt.AppendLine($"- P2端端口:{opticalFiber.P2PortNumber}");
|
||
|
||
if (!string.IsNullOrEmpty(opticalFiber.VirtualPointCode))
|
||
prompt.AppendLine($"- 虚拟点位代码:{opticalFiber.VirtualPointCode}");
|
||
if (!string.IsNullOrEmpty(opticalFiber.WiringDirection))
|
||
prompt.AppendLine($"- 配线走向:{opticalFiber.WiringDirection}");
|
||
|
||
prompt.AppendLine();
|
||
prompt.AppendLine("【要求】");
|
||
prompt.AppendLine("请按照以下格式提供分析结果:");
|
||
prompt.AppendLine();
|
||
prompt.AppendLine("影响范围:");
|
||
prompt.AppendLine("(请详细列出该光纤断线可能影响的设备、系统和功能,每项单独一行)");
|
||
prompt.AppendLine();
|
||
prompt.AppendLine("处置意见:");
|
||
prompt.AppendLine("(请提供具体的排查步骤和处置建议,按优先级排序,每项单独一行)");
|
||
|
||
return prompt.ToString();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调用AI API获取分析结果
|
||
/// </summary>
|
||
private async Task<string> CallAiApiAsync(string userMessage, CancellationToken cancellationToken)
|
||
{
|
||
var requestData = new
|
||
{
|
||
user_message = userMessage,
|
||
history = new List<object>()
|
||
};
|
||
|
||
var jsonContent = JsonConvert.SerializeObject(requestData);
|
||
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
||
|
||
Log4Helper.Info(GetType(), $"调用AI API: {AI_API_URL}");
|
||
|
||
var response = await _httpClient.PostAsync(AI_API_URL, content, cancellationToken).ConfigureAwait(false);
|
||
response.EnsureSuccessStatusCode();
|
||
|
||
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||
|
||
Log4Helper.Debug(GetType(), $"AI API原始响应长度: {responseText.Length} 字符");
|
||
|
||
return responseText;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析AI流式响应,提取content内容
|
||
/// </summary>
|
||
private string ParseAiStreamingResponse(string rawResponse)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(rawResponse))
|
||
return string.Empty;
|
||
|
||
var result = new StringBuilder();
|
||
|
||
foreach (string line in rawResponse.Split('\n'))
|
||
{
|
||
var trimmed = line.Trim();
|
||
if (string.IsNullOrWhiteSpace(trimmed))
|
||
continue;
|
||
|
||
try
|
||
{
|
||
using var doc = JsonDocument.Parse(trimmed);
|
||
var root = doc.RootElement;
|
||
|
||
if (root.TryGetProperty("type", out var typeProp) &&
|
||
typeProp.GetString() == "content" &&
|
||
root.TryGetProperty("content", out var contentProp))
|
||
{
|
||
result.Append(contentProp.GetString());
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// 跳过非JSON行或解析失败的行
|
||
continue;
|
||
}
|
||
}
|
||
|
||
return result.ToString();
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|