538 lines
19 KiB
C#
538 lines
19 KiB
C#
/////////////////////////////////////////////////////////////////////////////////
|
||
// 宁波拓通e智造平台 ToTong Next Builder //
|
||
// https://git.tuotong-tech.com/tnb/tnb.server //
|
||
/////////////////////////////////////////////////////////////////////////////////
|
||
|
||
using System.ComponentModel;
|
||
using System.ComponentModel.DataAnnotations;
|
||
using System.ComponentModel.DataAnnotations.Schema;
|
||
using System.Reflection;
|
||
using JNPF.Common.Core.Manager;
|
||
using JNPF.Common.Extension;
|
||
using Mapster;
|
||
using Newtonsoft.Json.Linq;
|
||
using SqlSugar;
|
||
using Tnb.Core;
|
||
using Yitter.IdGenerator;
|
||
|
||
namespace Tnb.Vengine.Domain;
|
||
|
||
/// <summary>
|
||
/// 视图模型
|
||
/// </summary>
|
||
[SugarTable("sys_vmodel")]
|
||
public partial class Vmodel : Entity
|
||
{
|
||
public const string MAIN_ALIES = "m";
|
||
|
||
#region Properties
|
||
|
||
/// <summary>
|
||
/// 主键标识
|
||
/// </summary>
|
||
[SugarColumn(IsPrimaryKey = true)]
|
||
public string id { get; set; } = YitIdHelper.NextId().ToString();
|
||
|
||
/// <summary>
|
||
/// 模块代码
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "area_code", Length = DbConsts.LengthS)]
|
||
public string areaCode { get; set; } = "edp";
|
||
|
||
/// <summary>
|
||
/// 视图代码
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "vm_code", IsNullable = false, Length = DbConsts.LengthM)]
|
||
public string vmCode { get; set; } = string.Empty;
|
||
|
||
/// <summary>
|
||
/// 视图名称
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "vm_name", IsNullable = false, Length = DbConsts.LengthM)]
|
||
public string vmName { get; set; } = string.Empty;
|
||
|
||
/// <summary>
|
||
/// 数据库连接
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "db_code", Length = DbConsts.LengthS)]
|
||
public string? dbCode { get; set; }
|
||
|
||
/// <summary>
|
||
/// 主表名称
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "table_name", IsNullable = false, Length = DbConsts.LengthS)]
|
||
public string tableName { get; set; } = string.Empty;
|
||
|
||
/// <summary>
|
||
/// 表字段属性
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "db_props", IsNullable = false, IsJson = true)]
|
||
public List<VmDbProp> dbProps { get; set; } = new List<VmDbProp>();
|
||
|
||
/// <summary>
|
||
/// 导航属性
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "nav_props", IsNullable = true, IsJson = true)]
|
||
public List<VmNavProp> navProps { get; set; } = new List<VmNavProp>();
|
||
|
||
/// <summary>
|
||
/// 计算属性
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "cal_props", IsNullable = true, IsJson = true)]
|
||
public List<VmCalProp> calProps { get; set; } = new List<VmCalProp>();
|
||
|
||
/// <summary>
|
||
/// 排序
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "ordinal", IsNullable = false)]
|
||
public int ordinal { get; set; }
|
||
|
||
/// <summary>
|
||
/// 软删除
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "soft_delete", IsNullable = false)]
|
||
public short softDelete { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否激活
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "enabled", IsNullable = false)]
|
||
public short enabled { get; set; } = 1;
|
||
|
||
/// <summary>
|
||
/// 是否删除
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "deleted", IsNullable = false)]
|
||
public short deleted { get; set; }
|
||
|
||
/// <summary>
|
||
/// 描述
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "descrip", Length = DbConsts.LengthL)]
|
||
public string? descrip { get; set; }
|
||
|
||
/// <summary>
|
||
/// 创建时间
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "create_time", IsNullable = false)]
|
||
public DateTime createTime { get; set; } = DateTime.Now;
|
||
|
||
/// <summary>
|
||
/// 创建人
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "create_id", Length = DbConsts.LengthS)]
|
||
public string? createId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 修改时间
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "modify_time", Length = DbConsts.LengthS)]
|
||
public DateTime? modifyTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 修改人
|
||
/// </summary>
|
||
[SugarColumn(ColumnName = "modify_id", Length = DbConsts.LengthS)]
|
||
public string? modifyId { get; set; }
|
||
|
||
[SugarColumn(IsIgnore = true)]
|
||
public string fullCode
|
||
{ get { return areaCode + "/" + vmCode; } }
|
||
|
||
[SugarColumn(IsIgnore = true)]
|
||
public Vmodel? parent { get; set; }
|
||
|
||
/// <summary>
|
||
/// 主键
|
||
/// </summary>
|
||
public override object[] GetKeys()
|
||
{
|
||
return new object[] { id };
|
||
}
|
||
|
||
#endregion Properties
|
||
//private Dictionary<string, string>? _mapField2Prop = null;
|
||
//private Dictionary<string, string>? _mapProp2Field = null;
|
||
/// <summary>
|
||
/// 通过实体创建模型
|
||
/// </summary>
|
||
/// <param name="tpEntity"></param>
|
||
/// <param name="dbCode"></param>
|
||
/// <returns></returns>
|
||
public static Vmodel CreateByEntity(Type tpEntity, string? dbCode = null)
|
||
{
|
||
Vmodel model = new() { dbCode = dbCode, vmCode = tpEntity.Name };
|
||
var sugarTableAttr = tpEntity.GetCustomAttribute<SugarTable>();
|
||
if (sugarTableAttr != null)
|
||
{
|
||
model.tableName = sugarTableAttr.TableName;
|
||
model.vmName = sugarTableAttr.TableDescription;
|
||
}
|
||
if (string.IsNullOrEmpty(model.tableName))
|
||
{
|
||
model.tableName = tpEntity.GetCustomAttribute<TableAttribute>()?.Name ?? tpEntity.Name;
|
||
}
|
||
if (string.IsNullOrEmpty(model.vmName))
|
||
{
|
||
model.vmName = tpEntity.GetCustomAttribute<DisplayAttribute>()?.Name ?? tpEntity.GetCustomAttribute<DescriptionAttribute>()?.Description ?? model.vmCode;
|
||
}
|
||
var props = tpEntity.GetProperties(BindingFlags.Public);
|
||
int n = 1;
|
||
foreach (var p in props)
|
||
{
|
||
VmDbProp prop = new();
|
||
var sugarColumn = p.GetCustomAttribute<SugarColumn>();
|
||
if (sugarColumn != null)
|
||
{
|
||
prop = sugarColumn.Adapt<VmDbProp>();
|
||
}
|
||
prop.code = p.Name;
|
||
prop.ordinal = n++;
|
||
model.dbProps.Add(prop);
|
||
}
|
||
return model;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取模型的主键字段属性
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public VmDbProp GetPrimary()
|
||
{
|
||
return dbProps.First(a => a.pkey);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据属性名获取字段名
|
||
/// </summary>
|
||
/// <param name="propCode"></param>
|
||
/// <returns></returns>
|
||
public string? PropCodeToFieldCode(string propCode)
|
||
{
|
||
return dbProps.Where(a => a.code == propCode).Select(a => a.field).FirstOrDefault();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据字段名获取属性名
|
||
/// </summary>
|
||
/// <param name="fieldCode"></param>
|
||
/// <returns></returns>
|
||
public string? FieldCodeToPropCode(string fieldCode)
|
||
{
|
||
return dbProps.Where(a => a.field == fieldCode).Select(a => a.code).FirstOrDefault();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 属性代码转换为字段代码
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <param name="ignoreNotMapped"></param>
|
||
/// <returns></returns>
|
||
public DObject PropToField(DObject input, bool ignoreNotMapped = true)
|
||
{
|
||
DObject ret = new();
|
||
foreach (var item in input)
|
||
{
|
||
var fcode = PropCodeToFieldCode(item.Key);
|
||
if (!string.IsNullOrEmpty(fcode))
|
||
{
|
||
ret.Add(fcode, item.Value);
|
||
}
|
||
else if (!ignoreNotMapped)
|
||
{
|
||
ret.Add(item.Key, item.Value);
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 字段代码转换为属性代码
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <param name="ignoreNotMapped"></param>
|
||
/// <returns></returns>
|
||
public DObject FieldToProp(DObject input, bool ignoreNotMapped = true)
|
||
{
|
||
DObject ret = new();
|
||
foreach (var item in input)
|
||
{
|
||
var pcode = FieldCodeToPropCode(item.Key);
|
||
if (!string.IsNullOrEmpty(pcode))
|
||
{
|
||
ret.Add(pcode, item.Value);
|
||
}
|
||
else if (!ignoreNotMapped)
|
||
{
|
||
ret.Add(item.Key, item.Value);
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取查询字段的属性信息
|
||
/// </summary>
|
||
/// <param name="outputProps"></param>
|
||
/// <returns></returns>
|
||
public List<VmSelectProp> GetVmSelectProps(string? outputProps)
|
||
{
|
||
if (string.IsNullOrEmpty(outputProps) || outputProps == "*")
|
||
{
|
||
return dbProps.Select(a => new VmSelectProp { code = a.code, field = a.field }).ToList();
|
||
}
|
||
List<VmSelectProp> selProps = new();
|
||
var outputs = outputProps.Split(',').Distinct().ToList();
|
||
foreach (var propCode in outputs)
|
||
{
|
||
if (!propCode.Contains("."))
|
||
{
|
||
var fieldCode = PropCodeToFieldCode(propCode);
|
||
if (!string.IsNullOrEmpty(fieldCode))
|
||
{
|
||
selProps.Add(new VmSelectProp { code = propCode, field = fieldCode });
|
||
}
|
||
continue;
|
||
}
|
||
var codes = propCode.Split('.');
|
||
if (codes.Length != 2) continue;
|
||
if (codes[0] == VmSelectProp.MAIN_ALIES)
|
||
{
|
||
var fieldCode = PropCodeToFieldCode(propCode);
|
||
if (!string.IsNullOrEmpty(fieldCode))
|
||
{
|
||
selProps.Add(new VmSelectProp { code = propCode, field = fieldCode });
|
||
}
|
||
continue;
|
||
}
|
||
var navProp = navProps.FirstOrDefault(a => a.code == codes[0]);
|
||
if (navProp?.naviModel != null)
|
||
{
|
||
var fieldCode = navProp.naviModel.PropCodeToFieldCode(codes[1]);
|
||
if (!string.IsNullOrEmpty(fieldCode))
|
||
{
|
||
selProps.Add(new VmSelectProp { code = codes[1], field = fieldCode, navCode = codes[0], propType = ePropType.Navigate, navType = navProp.navType });
|
||
}
|
||
}
|
||
}
|
||
return selProps;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取联表配置信息
|
||
/// </summary>
|
||
/// <param name="selProps"></param>
|
||
/// <returns></returns>
|
||
public List<JoinInfoParameter> GetJoinInfos(List<VmSelectProp> selProps)
|
||
{
|
||
var navigates = selProps.Where(a => a.propType == ePropType.Navigate).Select(a => a.navCode).Distinct().ToList();
|
||
List<JoinInfoParameter> joins = new();
|
||
foreach (var navCode in navigates)
|
||
{
|
||
if (navCode == VmSelectProp.MAIN_ALIES) continue;
|
||
var navProp = navProps.First(a => a.code == navCode);
|
||
if (navProp.naviModel == null || navProp.navType != eNavigateType.OneToOne) continue;
|
||
JoinInfoParameter join = new JoinInfoParameter { TableName = navProp.naviModel.tableName, ShortName = navCode, Type = JoinType.Inner };
|
||
var fkField = navProp.naviModel.PropCodeToFieldCode(navProp.fkField);
|
||
var refField = navProp.refField;
|
||
if (navProp.refCode != VmSelectProp.MAIN_ALIES)
|
||
{
|
||
var refProp = navProps.First(a => a.code == navProp.refCode);
|
||
refField = refProp.naviModel!.PropCodeToFieldCode(navProp.refField);
|
||
}
|
||
join.Models = ObjectFuncModel.Create("Equals", $"{navCode}.{fkField}", $"{navProp.refCode}.{refField}");
|
||
joins.Add(join);
|
||
}
|
||
return joins;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换为查询过滤条件
|
||
/// </summary>
|
||
/// <param name="filter"></param>
|
||
/// <returns></returns>
|
||
public List<IConditionalModel> GetConditionalModels(DObject? filter)
|
||
{
|
||
List<IConditionalModel> wheres = new List<IConditionalModel>();
|
||
if (filter == null) return wheres;
|
||
foreach (var item in filter)
|
||
{
|
||
VmDbProp? prop = null;
|
||
// TODO 按子表条件查询
|
||
if (item.Key.Contains("."))
|
||
{
|
||
var codes = item.Key.Split('.');
|
||
if (codes.Length >= 2)
|
||
{
|
||
var navProp = navProps.FirstOrDefault(a => a.code == codes[0]);
|
||
if (navProp != null && navProp.naviModel != null)
|
||
{
|
||
var dbProp = navProp.naviModel.dbProps.FirstOrDefault(a => a.code == codes[1]);
|
||
if (dbProp != null)
|
||
{
|
||
prop = new VmDbProp();
|
||
prop.field = codes[0] + "." + dbProp.field;
|
||
prop.csType = dbProp.csType;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
prop = dbProps.FirstOrDefault(a => a.code == item.Key);
|
||
}
|
||
if (prop == null) continue;
|
||
if (item.Value is JArray val)
|
||
{
|
||
var op = val[0].ToString();
|
||
switch (op)
|
||
{
|
||
case "><":
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[1].ToString(), ConditionalType = ConditionalType.GreaterThan, CSharpTypeName = prop.csType });
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[2].ToString(), ConditionalType = ConditionalType.LessThan, CSharpTypeName = prop.csType });
|
||
break;
|
||
|
||
case ">=<":
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[1].ToString(), ConditionalType = ConditionalType.GreaterThanOrEqual, CSharpTypeName = prop.csType });
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[2].ToString(), ConditionalType = ConditionalType.LessThan, CSharpTypeName = prop.csType });
|
||
break;
|
||
|
||
case "><=":
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[1].ToString(), ConditionalType = ConditionalType.GreaterThan, CSharpTypeName = prop.csType });
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[2].ToString(), ConditionalType = ConditionalType.LessThanOrEqual, CSharpTypeName = prop.csType });
|
||
break;
|
||
|
||
case ">=<=":
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[1].ToString(), ConditionalType = ConditionalType.GreaterThanOrEqual, CSharpTypeName = prop.csType });
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val[2].ToString(), ConditionalType = ConditionalType.LessThanOrEqual, CSharpTypeName = prop.csType });
|
||
break;
|
||
|
||
case "in":
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = val.Skip(1).ToString(), ConditionalType = ConditionalType.In, CSharpTypeName = prop.csType });
|
||
break;
|
||
|
||
default: op = string.Empty; break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//if (item.Value == null) continue;
|
||
var conditionalType = ConditionalType.Equal;
|
||
string? value = item.Value?.ToString();
|
||
if (string.IsNullOrEmpty(value)) continue;
|
||
if (value.Length >= 2)
|
||
{
|
||
var op = value.Substring(0, 2);
|
||
switch (op)
|
||
{
|
||
case "%%": conditionalType = ConditionalType.Like; break;
|
||
case ">>": conditionalType = ConditionalType.GreaterThan; break;
|
||
case "<<": conditionalType = ConditionalType.LessThan; break;
|
||
case ">=": conditionalType = ConditionalType.GreaterThanOrEqual; break;
|
||
case "<=": conditionalType = ConditionalType.LessThanOrEqual; break;
|
||
case "==": conditionalType = ConditionalType.Equal; break;
|
||
default: op = string.Empty; break;
|
||
}
|
||
if (!string.IsNullOrEmpty(op))
|
||
{
|
||
value = value.RemovePreFix(op);
|
||
if (value.ToLower() == "null")
|
||
{
|
||
value = null;
|
||
}
|
||
}
|
||
}
|
||
wheres.Add(new ConditionalModel { FieldName = prop.field, FieldValue = value, ConditionalType = conditionalType, CSharpTypeName = prop.csType });
|
||
}
|
||
}
|
||
return wheres;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换为查询字段列表
|
||
/// </summary>
|
||
/// <param name="selProps"></param>
|
||
/// <returns></returns>
|
||
public List<SelectModel> GetSelectModels(List<VmSelectProp> selProps)
|
||
{
|
||
return selProps.Where(a => a.navType != eNavigateType.OneToMany && a.navType != eNavigateType.ManyToMany).Select(a => new SelectModel
|
||
{
|
||
FiledName = a.navCode + "." + a.field,
|
||
AsName = (a.navCode == VmSelectProp.MAIN_ALIES ? "" : a.navCode + "_") + a.code
|
||
}).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取默认对象
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public DObject GetDefaultDObject()
|
||
{
|
||
DObject obj = new();
|
||
foreach (var p in dbProps)
|
||
{
|
||
obj.Add(p.code, p.GetDefaultValue()!);
|
||
}
|
||
return obj;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换为待新增的实体对象
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public DObject ToCreateEntity(DObject input, IUserManager user)
|
||
{
|
||
DObject obj = new();
|
||
foreach (var p in dbProps)
|
||
{
|
||
if (input.ContainsKey(p.code))
|
||
{
|
||
obj.Add(p.field, input[p.code]);
|
||
}
|
||
//当提交的数据与内置规则有重复时,采用内置规则,如果要优先采用提交的数据,这里要使用else if
|
||
if ((p.pkey && p.code == "id") || p.defValue == "@snowid")
|
||
{
|
||
obj[p.field] = YitIdHelper.NextId().ToString();
|
||
}
|
||
else if (p.csType == "DateTime" && (p.code == "createTime" || p.defValue == "@createTime"))
|
||
{
|
||
obj[p.field] = DateTime.Now;
|
||
}
|
||
else if (p.csType == "string" && (p.code == "createId" || p.defValue == "@createId"))
|
||
{
|
||
obj[p.field] = user.UserId;
|
||
}
|
||
else if (obj.GetOrDefault(p.field) == null && (p.required || !string.IsNullOrEmpty(p.defValue)))
|
||
{
|
||
obj[p.field] = p.GetDefaultValue()!;
|
||
}
|
||
}
|
||
return obj;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换为待修改的实体对象
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public DObject ToUpdateEntity(DObject input, IUserManager user)
|
||
{
|
||
DObject obj = new();
|
||
foreach (var p in dbProps)
|
||
{
|
||
if (input.ContainsKey(p.code))
|
||
{
|
||
obj.Add(p.field, input[p.code]);
|
||
}
|
||
//当提交的数据与内置规则有重复时,采用内置规则,如果要优先采用提交的数据,这里要使用else if
|
||
if (p.csType == "DateTime" && (p.code == "updateTime" || p.code == "modifyTime" || p.defValue == "@updateTime"))
|
||
{
|
||
obj[p.field] = DateTime.Now;
|
||
}
|
||
else if (p.csType == "string" && (p.code == "updateId" || p.code == "modifyId" || p.defValue == "@updateId"))
|
||
{
|
||
obj[p.field] = user.UserId;
|
||
}
|
||
}
|
||
return obj;
|
||
}
|
||
} |