merge
This commit is contained in:
@@ -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) { }
|
||||
}
|
||||
Reference in New Issue
Block a user