From f519405c63a00c5974989b2ce856884ad01773f3 Mon Sep 17 00:00:00 2001
From: xiaolipro <2357729423@qq.com>
Date: Tue, 17 Mar 2026 18:01:04 +0800
Subject: [PATCH] feat: add FlexibleStringJsonConverter and update
NotifyUserDto to use string UserId
Added a new JSON converter to handle flexible string conversions. Updated NotifyUserDto to change UserId from int to string and removed the [IdRequired] attribute. This aligns with the new converter's functionality to handle different ID formats.
I need to condense this. The core
---
.../GetPageCompleteWarningDetailsInput.cs | 2 +-
.../Dtos/Warning/NotifyUserDto.cs | 8 ++--
.../GetPageReturnWarningDetailsInput.cs | 2 +-
.../FlexibleStringJsonConverter.cs | 44 +++++++++++++++++++
.../GetPageTransportWarningDetailsInput.cs | 2 +-
.../Hangfire/WarningNotifyAggregator.cs | 9 ++--
.../Hangfire/WarningNotifyBuilder.cs | 9 ++--
.../Hangfire/WarningNotifyParam.cs | 2 +-
.../GetPageCompleteWarningDetailsInputVO.cs | 2 +-
.../GetPageReturnWarningDetailsInputVO.cs | 2 +-
.../GetPageTransportWarningDetailsInputVO.cs | 2 +-
.../WarningDetailsEsRepository.cs | 12 ++---
12 files changed, 73 insertions(+), 23 deletions(-)
create mode 100644 src/TrackCenter.Application/Dtos/Warning/Serialization/FlexibleStringJsonConverter.cs
diff --git a/src/TrackCenter.Application/Dtos/Warning/Complete/GetPageCompleteWarningDetailsInput.cs b/src/TrackCenter.Application/Dtos/Warning/Complete/GetPageCompleteWarningDetailsInput.cs
index 3c397682..d5320c60 100644
--- a/src/TrackCenter.Application/Dtos/Warning/Complete/GetPageCompleteWarningDetailsInput.cs
+++ b/src/TrackCenter.Application/Dtos/Warning/Complete/GetPageCompleteWarningDetailsInput.cs
@@ -42,7 +42,7 @@ public class GetPageCompleteWarningDetailsInput : PageInfoInput
///
/// 通知对象id
///
- public int? NotifyUserId { get; set; }
+ public string? NotifyUserId { get; set; }
///
/// 预警创建时间开始
diff --git a/src/TrackCenter.Application/Dtos/Warning/NotifyUserDto.cs b/src/TrackCenter.Application/Dtos/Warning/NotifyUserDto.cs
index aee75155..ba884f31 100644
--- a/src/TrackCenter.Application/Dtos/Warning/NotifyUserDto.cs
+++ b/src/TrackCenter.Application/Dtos/Warning/NotifyUserDto.cs
@@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations;
-using TrackCenter.Application.Dtos.Warning.DataAnnotations;
+using TrackCenter.Application.Dtos.Warning.Serialization;
+using System.Text.Json.Serialization;
namespace TrackCenter.Application.Dtos.Warning;
@@ -8,8 +9,9 @@ public sealed class NotifyUserDto
///
/// 用户id
///
- [IdRequired]
- public int UserId { get; set; }
+ [Required]
+ [JsonConverter(typeof(FlexibleStringJsonConverter))]
+ public string UserId { get; set; } = string.Empty;
///
/// 用户名
diff --git a/src/TrackCenter.Application/Dtos/Warning/Return/GetPageReturnWarningDetailsInput.cs b/src/TrackCenter.Application/Dtos/Warning/Return/GetPageReturnWarningDetailsInput.cs
index e7609916..0076b234 100644
--- a/src/TrackCenter.Application/Dtos/Warning/Return/GetPageReturnWarningDetailsInput.cs
+++ b/src/TrackCenter.Application/Dtos/Warning/Return/GetPageReturnWarningDetailsInput.cs
@@ -52,7 +52,7 @@ public class GetPageReturnWarningDetailsInput : PageInfoInput
///
/// 通知对象用户id
///
- public int? NotifyUserId { get; set; }
+ public string? NotifyUserId { get; set; }
///
/// 轨迹发生时间开始
diff --git a/src/TrackCenter.Application/Dtos/Warning/Serialization/FlexibleStringJsonConverter.cs b/src/TrackCenter.Application/Dtos/Warning/Serialization/FlexibleStringJsonConverter.cs
new file mode 100644
index 00000000..62177bab
--- /dev/null
+++ b/src/TrackCenter.Application/Dtos/Warning/Serialization/FlexibleStringJsonConverter.cs
@@ -0,0 +1,44 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using System.Globalization;
+
+namespace TrackCenter.Application.Dtos.Warning.Serialization;
+
+///
+/// 兼容 string/number 两种 token 读取为 string,避免历史数据反序列化失败。
+///
+public sealed class FlexibleStringJsonConverter : JsonConverter
+{
+ public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return reader.TokenType switch
+ {
+ JsonTokenType.String => reader.GetString() ?? string.Empty,
+ JsonTokenType.Number => ReadNumberAsString(ref reader),
+ JsonTokenType.True => bool.TrueString,
+ JsonTokenType.False => bool.FalseString,
+ JsonTokenType.Null => string.Empty,
+ _ => throw new JsonException("Only string/number/bool/null can be converted to string.")
+ };
+ }
+
+ public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value);
+ }
+
+ private static string ReadNumberAsString(ref Utf8JsonReader reader)
+ {
+ if (reader.TryGetInt64(out var longVal))
+ {
+ return longVal.ToString(CultureInfo.InvariantCulture);
+ }
+
+ if (reader.TryGetDecimal(out var decimalVal))
+ {
+ return decimalVal.ToString(CultureInfo.InvariantCulture);
+ }
+
+ return reader.GetDouble().ToString(CultureInfo.InvariantCulture);
+ }
+}
diff --git a/src/TrackCenter.Application/Dtos/Warning/Transport/GetPageTransportWarningDetailsInput.cs b/src/TrackCenter.Application/Dtos/Warning/Transport/GetPageTransportWarningDetailsInput.cs
index 553c6866..3e1e4629 100644
--- a/src/TrackCenter.Application/Dtos/Warning/Transport/GetPageTransportWarningDetailsInput.cs
+++ b/src/TrackCenter.Application/Dtos/Warning/Transport/GetPageTransportWarningDetailsInput.cs
@@ -41,7 +41,7 @@ public class GetPageTransportWarningDetailsInput : PageInfoInput
///
/// 通知对象用户Id
///
- public int? NotifyUserId { get; set; }
+ public string? NotifyUserId { get; set; }
///
/// 创建时间开始
diff --git a/src/TrackCenter.Application/Hangfire/WarningNotifyAggregator.cs b/src/TrackCenter.Application/Hangfire/WarningNotifyAggregator.cs
index da71b1bf..55afb6d8 100644
--- a/src/TrackCenter.Application/Hangfire/WarningNotifyAggregator.cs
+++ b/src/TrackCenter.Application/Hangfire/WarningNotifyAggregator.cs
@@ -264,11 +264,14 @@ public sealed class WarningNotifyAggregator : ITransientDependency
// 1.以人的维度对不同类别的预警通知分组聚合
// key: userId value: {key:type,value:notify }
- var userIdNotifyTaskDict = new Dictionary>>();
+ var userIdNotifyTaskDict = new Dictionary>>();
foreach (var task in needNotifyTasks)
{
var notifyUsers = TextJsonHelper.Deserialize>(task.NotifyUsers)!;
- var notifyUserIds = notifyUsers.Select(x => x.UserId).ToHashSet();
+ var notifyUserIds = notifyUsers
+ .Select(x => x.UserId.Trim())
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .ToHashSet();
foreach (var userId in notifyUserIds)
{
@@ -303,7 +306,7 @@ public sealed class WarningNotifyAggregator : ITransientDependency
return result;
}
- private WarningNotifyParam BuildNotifyParam(int userId, Dictionary> typeNotifyTaskDict)
+ private WarningNotifyParam BuildNotifyParam(string userId, Dictionary> typeNotifyTaskDict)
{
var options = _optionsMonitor.CurrentValue;
var hours = options.ScanWarningNotifyTaskHourInterval;
diff --git a/src/TrackCenter.Application/Hangfire/WarningNotifyBuilder.cs b/src/TrackCenter.Application/Hangfire/WarningNotifyBuilder.cs
index 42913291..3a354e32 100644
--- a/src/TrackCenter.Application/Hangfire/WarningNotifyBuilder.cs
+++ b/src/TrackCenter.Application/Hangfire/WarningNotifyBuilder.cs
@@ -77,13 +77,14 @@ public static class WarningNotifyBuilder
public const string ReturnPath = "/trajectoryCenter/trajectoryWarningOrder/ReturnWarning";
public const string CompletePath = "/trajectoryCenter/trajectoryWarningOrder/CompleteWarning";
- public static string BuildUrl(string baseUrl, WarningRuleType warningRuleType, int userId)
+ public static string BuildUrl(string baseUrl, WarningRuleType warningRuleType, string userId)
{
+ var encodedUserId = Uri.EscapeDataString(userId);
return warningRuleType switch
{
- WarningRuleType.运输时效预警 => $"{baseUrl}{TransportPath}?userid={userId}",
- WarningRuleType.回传时效预警 => $"{baseUrl}{ReturnPath}?userid={userId}",
- WarningRuleType.完整预警 => $"{baseUrl}{CompletePath}?userid={userId}",
+ WarningRuleType.运输时效预警 => $"{baseUrl}{TransportPath}?userid={encodedUserId}",
+ WarningRuleType.回传时效预警 => $"{baseUrl}{ReturnPath}?userid={encodedUserId}",
+ WarningRuleType.完整预警 => $"{baseUrl}{CompletePath}?userid={encodedUserId}",
_ => throw new ArgumentOutOfRangeException()
};
}
diff --git a/src/TrackCenter.Application/Hangfire/WarningNotifyParam.cs b/src/TrackCenter.Application/Hangfire/WarningNotifyParam.cs
index 433ce045..732946b7 100644
--- a/src/TrackCenter.Application/Hangfire/WarningNotifyParam.cs
+++ b/src/TrackCenter.Application/Hangfire/WarningNotifyParam.cs
@@ -5,7 +5,7 @@ namespace TrackCenter.Application.Hangfire;
///
public class WarningNotifyParam
{
- public int UserId { get; set; }
+ public string UserId { get; set; } = string.Empty;
public int Hours { get; set; }
diff --git a/src/TrackCenter.Domain/Dtos/Warning/GetPageCompleteWarningDetailsInputVO.cs b/src/TrackCenter.Domain/Dtos/Warning/GetPageCompleteWarningDetailsInputVO.cs
index fad24a15..1757fe88 100644
--- a/src/TrackCenter.Domain/Dtos/Warning/GetPageCompleteWarningDetailsInputVO.cs
+++ b/src/TrackCenter.Domain/Dtos/Warning/GetPageCompleteWarningDetailsInputVO.cs
@@ -36,7 +36,7 @@ public class GetPageCompleteWarningDetailsInputVO : PageInfoInput
///
/// 通知对象id
///
- public int? NotifyUserId { get; set; }
+ public string? NotifyUserId { get; set; }
///
/// 预警创建时间开始
diff --git a/src/TrackCenter.Domain/Dtos/Warning/GetPageReturnWarningDetailsInputVO.cs b/src/TrackCenter.Domain/Dtos/Warning/GetPageReturnWarningDetailsInputVO.cs
index b1c0201f..e04f857d 100644
--- a/src/TrackCenter.Domain/Dtos/Warning/GetPageReturnWarningDetailsInputVO.cs
+++ b/src/TrackCenter.Domain/Dtos/Warning/GetPageReturnWarningDetailsInputVO.cs
@@ -49,7 +49,7 @@ public class GetPageReturnWarningDetailsInputVO : PageInfoInput
///
/// 通知对象用户id
///
- public int? NotifyUserId { get; set; }
+ public string? NotifyUserId { get; set; }
///
/// 轨迹发生时间开始
diff --git a/src/TrackCenter.Domain/Dtos/Warning/GetPageTransportWarningDetailsInputVO.cs b/src/TrackCenter.Domain/Dtos/Warning/GetPageTransportWarningDetailsInputVO.cs
index a4aa202a..92ccd428 100644
--- a/src/TrackCenter.Domain/Dtos/Warning/GetPageTransportWarningDetailsInputVO.cs
+++ b/src/TrackCenter.Domain/Dtos/Warning/GetPageTransportWarningDetailsInputVO.cs
@@ -38,7 +38,7 @@ public class GetPageTransportWarningDetailsInputVO : PageInfoInput
///
/// 通知对象用户Id
///
- public int? NotifyUserId { get; set; }
+ public string? NotifyUserId { get; set; }
///
/// 创建时间开始
diff --git a/src/TrackCenter.Repository/Repositories/WarningDetailsEsRepository.cs b/src/TrackCenter.Repository/Repositories/WarningDetailsEsRepository.cs
index 10c7028a..fcb6b327 100644
--- a/src/TrackCenter.Repository/Repositories/WarningDetailsEsRepository.cs
+++ b/src/TrackCenter.Repository/Repositories/WarningDetailsEsRepository.cs
@@ -46,8 +46,8 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
c => c.DateRange(r => r.Field(f => f.CreateTime).LessThanOrEquals(input.CreateTimeEnd)));
// 模糊匹配userId
- musts.AddIf(x => x.NotifyUserId.HasValue,
- c => c.Match(f => f.Field(d => d.NotifyUsers).Query(input.NotifyUserId.ToString())));
+ musts.AddIf(x => !string.IsNullOrWhiteSpace(x.NotifyUserId),
+ c => c.Match(f => f.Field(d => d.NotifyUsers).Query(input.NotifyUserId)));
var r = await _client.SearchAsync(x => x
.Index(GlobalConst.TransportWarningDetailsIndex)
@@ -381,8 +381,8 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
c => c.DateRange(r => r.Field(f => f.CreateTime).LessThanOrEquals(input.WarningCreateTimeEnd)));
// 模糊匹配userId(json字符串包含userId)
- musts.AddIf(x => x.NotifyUserId.HasValue,
- c => c.Match(f => f.Field(d => d.NotifyUsers).Query(input.NotifyUserId.ToString())));
+ musts.AddIf(x => !string.IsNullOrWhiteSpace(x.NotifyUserId),
+ c => c.Match(f => f.Field(d => d.NotifyUsers).Query(input.NotifyUserId)));
musts.AddIf(x => !string.IsNullOrWhiteSpace(x.Customer),
c => c.Match(f => f.Field(d => d.Customer).Query(input.Customer)));
@@ -753,8 +753,8 @@ public class WarningDetailsEsRepository : IWarningDetailsEsRepository, ITransien
c => c.DateRange(r => r.Field(f => f.ProcessedTime).LessThanOrEquals(input.WarningHandleTimeEnd)));
// 模糊匹配userId
- musts.AddIf(x => x.NotifyUserId.HasValue,
- c => c.Match(f => f.Field(d => d.NotifyUsers).Query(input.NotifyUserId.ToString())));
+ musts.AddIf(x => !string.IsNullOrWhiteSpace(x.NotifyUserId),
+ c => c.Match(f => f.Field(d => d.NotifyUsers).Query(input.NotifyUserId)));
musts.AddIf(x => !string.IsNullOrWhiteSpace(x.Customer),
c => c.Match(f => f.Field(d => d.Customer).Query(input.Customer)));