Files
tnb.server/visualdev/Tnb.Vengine/Domain/Vmodel.cs

535 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/////////////////////////////////////////////////////////////////////////////////
// 宁波拓通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; } }
/// <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;
}
}