This commit is contained in:
ArtoriasWu
2026-06-24 16:22:24 +08:00
parent 60b3afb954
commit 4b7ce6790f
24 changed files with 3421 additions and 0 deletions
@@ -0,0 +1,21 @@
using System.Globalization;
namespace MiGu.Server.SimpleFields;
public static class SimpleFieldDateTime
{
public const string StorageFormat = "yyyy-MM-dd HH:mm:ss";
public static DateTimeOffset Now => DateTimeOffset.Now;
public static string ToStorage(DateTimeOffset value) =>
value.LocalDateTime.ToString(StorageFormat, CultureInfo.InvariantCulture);
public static DateTimeOffset FromStorage(string value)
{
if (DateTime.TryParseExact(value, StorageFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var local))
return new DateTimeOffset(local);
return DateTimeOffset.Parse(value, CultureInfo.InvariantCulture);
}
}
@@ -0,0 +1,84 @@
using System.ComponentModel.DataAnnotations;
namespace MiGu.Server.SimpleFields;
public sealed class SimpleField
{
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>车型唯一标识:assemblyName.shortName,如 StandardScene.QrLidar.Forklift。</summary>
[MaxLength(64)]
public string CarType { get; set; } = "";
/// <summary>
/// 字段类型唯一标识:assemblyName.shortName,如 StandardScene.QrLidar.Forklift。
/// </summary>
[MaxLength(64)]
public string FieldType { get; set; } = "";
/// <summary>
/// 字段唯一标识:key,如 Forklift.PositionX。
/// </summary>
[MaxLength(128)]
public string Key { get; set; } = "";
/// <summary>
/// 字段值,如 10.0。
/// </summary>
public string Value { get; set; } = "";
/// <summary>
/// 数据类型,如 System.String。
/// </summary>
[MaxLength(128)]
public string DataType { get; set; } = "";
/// <summary>
/// 中文名称,如 位置 X。
/// </summary>
[MaxLength(256)]
public string? Chinese { get; set; }
/// <summary>
/// 英文名称,如 Position X。
/// </summary>
[MaxLength(256)]
public string? English { get; set; }
/// <summary>
/// 其他语言名称,如 位置 X。
/// </summary>
[MaxLength(512)]
public string Other { get; set; } = "";
/// <summary>
/// 是否内置默认字段,如 true。
/// </summary>
public bool IsDefault { get; set; }
/// <summary>
/// 创建时间,如 2021-01-01 12:00:00。
/// </summary>
public DateTimeOffset CreateTime { get; set; }
/// <summary>
/// 更新时间,如 2021-01-01 12:00:00。
/// </summary>
public DateTimeOffset UpdateTime { get; set; }
}
public sealed record SimpleFieldRequest(
Guid? Id,
string CarType,
string FieldType,
string Key,
string? Value,
string? DataType,
string? Chinese,
string? English,
string? Other,
bool IsDefault);
public sealed record SimpleFieldBatchRequest(
bool ReplaceAll,
List<SimpleFieldRequest> Items);
@@ -0,0 +1,132 @@
using Microsoft.EntityFrameworkCore;
using MiGu.Server.Persistence;
namespace MiGu.Server.SimpleFields;
public sealed class SimpleFieldService
{
private readonly PlatformDbContext _db;
public SimpleFieldService(PlatformDbContext db) => _db = db;
public async Task<List<SimpleField>> ListAsync(string? fieldType = null, string? carType = null, string? q = null)
{
var query = _db.SimpleFields.AsNoTracking()
.OrderBy(x => x.CarType).ThenBy(x => x.FieldType).ThenBy(x => x.Key)
.AsQueryable();
if (!string.IsNullOrWhiteSpace(fieldType))
query = query.Where(x => x.FieldType == fieldType);
if (!string.IsNullOrWhiteSpace(carType))
query = query.Where(x => x.CarType == carType);
if (!string.IsNullOrWhiteSpace(q))
{
var kw = q.Trim();
query = query.Where(x =>
x.Key.Contains(kw) ||
x.CarType.Contains(kw) ||
(x.Chinese != null && x.Chinese.Contains(kw)) ||
(x.English != null && x.English.Contains(kw)) ||
x.Other.Contains(kw) ||
x.Value.Contains(kw));
}
return await query.ToListAsync();
}
public async Task<SimpleField> SaveAsync(SimpleFieldRequest req)
{
if (string.IsNullOrWhiteSpace(req.CarType)) throw new SimpleFieldException("car_type 不能为空");
if (string.IsNullOrWhiteSpace(req.FieldType)) throw new SimpleFieldException("field_type 不能为空");
if (string.IsNullOrWhiteSpace(req.Key)) throw new SimpleFieldException("key 不能为空");
var carType = req.CarType.Trim();
var now = SimpleFieldDateTime.Now;
SimpleField entity;
if (req.Id is { } id && id != Guid.Empty)
{
entity = await _db.SimpleFields.FirstOrDefaultAsync(x => x.Id == id)
?? throw new SimpleFieldException("记录不存在");
}
else
{
var dup = await _db.SimpleFields.AnyAsync(x =>
x.CarType == carType &&
x.FieldType == req.FieldType.Trim() &&
x.Key == req.Key.Trim());
if (dup) throw new SimpleFieldException("同车型与字段类型下 key 已存在");
entity = new SimpleField { Id = Guid.NewGuid(), CreateTime = now };
_db.SimpleFields.Add(entity);
}
entity.CarType = carType;
entity.FieldType = req.FieldType.Trim();
entity.Key = req.Key.Trim();
entity.Value = req.Value?.Trim() ?? "";
entity.DataType = req.DataType?.Trim() ?? "";
entity.Chinese = req.Chinese is null ? null : req.Chinese.Trim();
entity.English = req.English is null ? null : req.English.Trim();
entity.Other = req.Other?.Trim() ?? "";
entity.IsDefault = req.IsDefault;
entity.UpdateTime = now;
if (entity.CreateTime == default) entity.CreateTime = now;
await _db.SaveChangesAsync();
return entity;
}
public async Task DeleteAsync(Guid id)
{
var entity = await _db.SimpleFields.FirstOrDefaultAsync(x => x.Id == id)
?? throw new SimpleFieldException("记录不存在");
_db.SimpleFields.Remove(entity);
await _db.SaveChangesAsync();
}
/// <summary>批量保存全部字段;ReplaceAll=true 时清空表后写入。</summary>
public async Task<int> SaveBatchAsync(SimpleFieldBatchRequest req)
{
var items = req.Items ?? new List<SimpleFieldRequest>();
if (items.Count == 0) throw new SimpleFieldException("没有可保存的字段");
if (req.ReplaceAll)
{
var all = await _db.SimpleFields.ToListAsync();
_db.SimpleFields.RemoveRange(all);
}
var now = SimpleFieldDateTime.Now;
var added = 0;
foreach (var item in items)
{
if (string.IsNullOrWhiteSpace(item.CarType) ||
string.IsNullOrWhiteSpace(item.FieldType) ||
string.IsNullOrWhiteSpace(item.Key))
continue;
_db.SimpleFields.Add(new SimpleField
{
Id = Guid.NewGuid(),
CarType = item.CarType.Trim(),
FieldType = item.FieldType.Trim(),
Key = item.Key.Trim(),
Value = item.Value?.Trim() ?? "",
DataType = item.DataType?.Trim() ?? "",
Chinese = item.Chinese is null ? null : item.Chinese.Trim(),
English = item.English is null ? null : item.English.Trim(),
Other = item.Other?.Trim() ?? "",
IsDefault = item.IsDefault,
CreateTime = now,
UpdateTime = now
});
added++;
}
await _db.SaveChangesAsync();
return added;
}
}
public sealed class SimpleFieldException : Exception
{
public SimpleFieldException(string message) : base(message) { }
}