增强可扩展字段的功能,支持把单个字段的Json/Xml映射到目标类,呈现到表单页并支持编辑保存
This commit is contained in:
parent
ec70e12618
commit
d1c9e5aaae
|
@ -240,15 +240,16 @@ public partial class EntityController<TEntity, TModel> : ReadOnlyEntityControlle
|
|||
// 遍历表单字段,部分字段可能有扩展
|
||||
foreach (var item in EditFormFields)
|
||||
{
|
||||
if (item is FormField ef && ef.GetExpand != null)
|
||||
var field = (item as FormField)?.Expand;
|
||||
if (field?.Decode != null && !(entity as IEntity).Dirtys[item.Name])
|
||||
{
|
||||
// 获取参数对象,展开参数,从表单字段接收参数
|
||||
var p = ef.GetExpand(entity);
|
||||
if (p != null && p is not String && !(entity as IEntity).Dirtys[ef.Name])
|
||||
var p = field.Decode(entity);
|
||||
if (p != null && p is not String)
|
||||
{
|
||||
// 保存参数对象
|
||||
if (FieldCollection.ReadForm(p, Request.Form, ef.Name + "_"))
|
||||
entity.SetItem(ef.Name, p.ToJson(true));
|
||||
if (field.ReadForm(p, Request.Form))
|
||||
entity.SetItem(item.Name, field.Encode?.Invoke(p) ?? p.ToJson(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -481,19 +481,25 @@ public partial class ReadOnlyEntityController<TEntity>
|
|||
fields = fields.Clone();
|
||||
|
||||
// 表单嵌入配置字段
|
||||
if (kind == ViewKinds.EditForm && model is TEntity entity)
|
||||
if ((kind == ViewKinds.EditForm || kind == ViewKinds.Detail) && model is TEntity entity)
|
||||
{
|
||||
// 获取参数对象,展开参数,作为表单字段
|
||||
foreach (var item in fields.ToArray())
|
||||
{
|
||||
if (item is FormField ef && ef.GetExpand != null)
|
||||
var field = (item as FormField)?.Expand;
|
||||
var p = field?.Decode?.Invoke(entity);
|
||||
if (p != null && p is not String)
|
||||
{
|
||||
var p = ef.GetExpand(entity);
|
||||
if (p != null && p is not String)
|
||||
{
|
||||
if (!ef.RetainExpand) fields.Remove(ef);
|
||||
if (field.Name.IsNullOrEmpty()) field.Name = item.Name;
|
||||
if (field.Category.IsNullOrEmpty()) field.Category = item.Category;
|
||||
if (field.Prefix.IsNullOrEmpty()) field.Prefix = item.Name + "_";
|
||||
|
||||
fields.Expand(entity, p, ef.Name + "_");
|
||||
var fs = OnExpandFields(field, entity, p);
|
||||
if (fs != null && fs.Count > 0)
|
||||
{
|
||||
fields.AddRange(fs);
|
||||
|
||||
if (!field.Retain) fields.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -501,5 +507,8 @@ public partial class ReadOnlyEntityController<TEntity>
|
|||
|
||||
return fields;
|
||||
}
|
||||
|
||||
/// <summary>展开字段</summary>
|
||||
protected virtual FieldCollection OnExpandFields(ExpandField field, TEntity entity, Object parameter) => field.Expand(entity, parameter);
|
||||
#endregion
|
||||
}
|
|
@ -82,6 +82,7 @@
|
|||
<Compile Include="..\NewLife.CubeNC\Session\SessionProvider.cs" Link="Session\SessionProvider.cs" />
|
||||
<Compile Include="..\NewLife.CubeNC\ViewModels\DataField.cs" Link="ViewModels\DataField.cs" />
|
||||
<Compile Include="..\NewLife.CubeNC\ViewModels\ErrorModel.cs" Link="ViewModels\ErrorModel.cs" />
|
||||
<Compile Include="..\NewLife.CubeNC\ViewModels\ExpandField.cs" Link="ViewModels\ExpandField.cs" />
|
||||
<Compile Include="..\NewLife.CubeNC\ViewModels\FieldCollection.cs" Link="ViewModels\FieldCollection.cs" />
|
||||
<Compile Include="..\NewLife.CubeNC\ViewModels\FormField.cs" Link="ViewModels\FormField.cs" />
|
||||
<Compile Include="..\NewLife.CubeNC\ViewModels\ILinkExtend.cs" Link="ViewModels\ILinkExtend.cs" />
|
||||
|
|
|
@ -46,8 +46,13 @@ public class CronJobController : EntityController<CronJob, CronJobModel>
|
|||
// 扩展Argument字段
|
||||
{
|
||||
var ef = EditFormFields.GetField("Argument") as FormField;
|
||||
ef.GetExpand = e => (e as CronJob)?.GetArgument();
|
||||
ef.RetainExpand = false;
|
||||
//ef.GetExpand = e => (e as CronJob)?.GetArgument();
|
||||
//ef.RetainExpand = false;
|
||||
ef.Expand = new ExpandField
|
||||
{
|
||||
Decode = e => (e as CronJob)?.GetArgument(),
|
||||
Retain = false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,6 @@
|
|||
using System.Security.Cryptography;
|
||||
|
||||
/// <summary>RSA工具类</summary>
|
||||
public static class RSTool
|
||||
{
|
||||
/// <summary>生成 PEM 格式的 RSA 密钥对</summary>
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using NewLife.Reflection;
|
||||
using NewLife.Serialization;
|
||||
using XCode;
|
||||
|
||||
namespace NewLife.Cube.ViewModels;
|
||||
|
||||
/// <summary>扩展字段。在表单页中,把一个Json/Xml字段扩展为多个字段进行展示和编辑</summary>
|
||||
public class ExpandField
|
||||
{
|
||||
#region 属性
|
||||
/// <summary>名称</summary>
|
||||
public String Name { get; set; }
|
||||
|
||||
/// <summary>获取扩展字段委托。当前字段所表示的对象,各属性作为表单字段展开</summary>
|
||||
public Func<Object, Object> Decode { get; set; }
|
||||
|
||||
/// <summary>编码扩展字段。一般是ToJson/ToXml</summary>
|
||||
public Func<Object, Object> Encode { get; set; }
|
||||
|
||||
/// <summary>保留扩展字段。默认false,字段被扩展以后,表单上就不再出现原字段</summary>
|
||||
public Boolean Retain { get; set; }
|
||||
|
||||
/// <summary>前缀</summary>
|
||||
public String Prefix { get; set; }
|
||||
|
||||
/// <summary>分类</summary>
|
||||
public String Category { get; set; }
|
||||
#endregion
|
||||
|
||||
#region 扩展参数
|
||||
/// <summary>当前字段集合加入目标对象作为扩展字段,用于动态表单</summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="parameter"></param>
|
||||
public FieldCollection Expand(IEntity entity, Object parameter)
|
||||
{
|
||||
var fields = new FieldCollection(ViewKinds.EditForm);
|
||||
|
||||
foreach (var pi in parameter.GetType().GetProperties(true))
|
||||
{
|
||||
// 添加字段,加个前缀,避免与实体字段冲突
|
||||
var ff = fields.Add(pi);
|
||||
ff.Name = Prefix + ff.Name;
|
||||
ff.Category = Category;
|
||||
if (ff.Category.IsNullOrEmpty()) ff.Category = pi.GetCustomAttribute<CategoryAttribute>()?.Category;
|
||||
if (ff.Category.IsNullOrEmpty()) ff.Category = "参数";
|
||||
|
||||
// 数组转为字符串
|
||||
var v = pi.GetValue(parameter);
|
||||
if (v is IList list)
|
||||
{
|
||||
v = list.Join(",");
|
||||
ff.Type = v.GetType();
|
||||
}
|
||||
|
||||
// 把参数值设置到实体对象的扩展属性里面
|
||||
entity.SetItem(ff.Name, v);
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
/// <summary>从表单读取数据到扩展字段的目标对象,稍候序列化并写入扩展字段</summary>
|
||||
/// <param name="parameter"></param>
|
||||
/// <param name="form"></param>
|
||||
/// <returns></returns>
|
||||
public Boolean ReadForm(Object parameter, IFormCollection form)
|
||||
{
|
||||
var flag = false;
|
||||
foreach (var pi in parameter.GetType().GetProperties(true))
|
||||
{
|
||||
// 从Request里面获取参数值
|
||||
var name = Prefix + pi.Name;
|
||||
if (!form.ContainsKey(name)) continue;
|
||||
|
||||
var value = form[name].FirstOrDefault();
|
||||
flag = true;
|
||||
|
||||
Object v = null;
|
||||
if (pi.PropertyType.As<IList>())
|
||||
{
|
||||
var elmType = pi.PropertyType.GetElementTypeEx();
|
||||
var ss = value.Split(",");
|
||||
var arr = Array.CreateInstance(elmType, ss.Length);
|
||||
for (var i = 0; i < arr.Length; i++)
|
||||
{
|
||||
arr.SetValue(ss[i].ChangeType(elmType), i);
|
||||
}
|
||||
|
||||
v = arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = value.ChangeType(pi.PropertyType);
|
||||
}
|
||||
|
||||
// 设置到参数对象里面
|
||||
parameter.SetValue(pi, v);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
#endregion
|
||||
}
|
|
@ -10,7 +10,6 @@ using NewLife.Reflection;
|
|||
using XCode;
|
||||
using XCode.Code;
|
||||
using XCode.Configuration;
|
||||
using XCode.DataAccessLayer;
|
||||
|
||||
namespace NewLife.Cube;
|
||||
|
||||
|
@ -389,79 +388,6 @@ public class FieldCollection : List<DataField>
|
|||
public DataField GetField(String name) => this.FirstOrDefault(e => name.EqualIgnoreCase(e.Name, e.MapField));
|
||||
#endregion
|
||||
|
||||
#region 扩展参数
|
||||
/// <summary>当前字段集合加入目标对象作为扩展字段,用于动态表单</summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="parameter"></param>
|
||||
/// <param name="prefix"></param>
|
||||
public void Expand(IEntity entity, Object parameter, String prefix)
|
||||
{
|
||||
var fields = this;
|
||||
//fields.RemoveField("Argument");
|
||||
|
||||
foreach (var pi in parameter.GetType().GetProperties(true))
|
||||
{
|
||||
// 添加字段,加个前缀,避免与实体字段冲突
|
||||
var ff = fields.Add(pi);
|
||||
ff.Name = prefix + ff.Name;
|
||||
ff.Category = pi.GetCustomAttribute<CategoryAttribute>()?.Category ?? "参数";
|
||||
|
||||
// 数组转为字符串
|
||||
var v = pi.GetValue(parameter);
|
||||
if (v is IList list)
|
||||
{
|
||||
v = list.Join(",");
|
||||
ff.Type = v.GetType();
|
||||
}
|
||||
|
||||
// 把参数值设置到实体对象的扩展属性里面
|
||||
entity.SetItem(ff.Name, v);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>从表单读取数据到扩展字段的目标对象,稍候序列化并写入扩展字段</summary>
|
||||
/// <param name="parameter"></param>
|
||||
/// <param name="form"></param>
|
||||
/// <param name="prefix"></param>
|
||||
/// <returns></returns>
|
||||
public static Boolean ReadForm(Object parameter, IFormCollection form, String prefix)
|
||||
{
|
||||
var flag = false;
|
||||
foreach (var pi in parameter.GetType().GetProperties(true))
|
||||
{
|
||||
// 从Request里面获取参数值
|
||||
var name = prefix + pi.Name;
|
||||
if (!form.ContainsKey(name)) continue;
|
||||
|
||||
var value = form[name].FirstOrDefault();
|
||||
flag = true;
|
||||
|
||||
Object v = null;
|
||||
if (pi.PropertyType.As<IList>())
|
||||
{
|
||||
var elmType = pi.PropertyType.GetElementTypeEx();
|
||||
var ss = value.Split(",");
|
||||
var arr = Array.CreateInstance(elmType, ss.Length);
|
||||
for (var i = 0; i < arr.Length; i++)
|
||||
{
|
||||
arr.SetValue(ss[i].ChangeType(elmType), i);
|
||||
}
|
||||
|
||||
v = arr;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = value.ChangeType(pi.PropertyType);
|
||||
}
|
||||
|
||||
// 设置到参数对象里面
|
||||
parameter.SetValue(pi, v);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 分组
|
||||
/// <summary>按类别分组获取字段列表</summary>
|
||||
/// <param name="entity">实体对象</param>
|
||||
|
|
|
@ -17,8 +17,37 @@ public class FormField : DataField
|
|||
#endif
|
||||
|
||||
/// <summary>获取扩展字段委托。当前字段所表示的对象,各属性作为表单字段展开</summary>
|
||||
public GetExpandDelegate GetExpand { get; set; }
|
||||
[Obsolete("=>Expand")]
|
||||
public GetExpandDelegate GetExpand
|
||||
{
|
||||
get => Expand?.Decode == null ? null : e => Expand.Decode?.Invoke(e);
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
if (Expand != null)
|
||||
Expand.Decode = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var exp = Expand ??= new ExpandField();
|
||||
exp.Decode = e => value(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>保留扩展字段。默认false,字段被扩展以后,表单上就不再出现原字段</summary>
|
||||
public Boolean RetainExpand { get; set; }
|
||||
[Obsolete("=>Expand")]
|
||||
public Boolean RetainExpand
|
||||
{
|
||||
get => Expand?.Retain ?? false;
|
||||
set
|
||||
{
|
||||
if (Expand != null)
|
||||
Expand.Retain = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>扩展字段</summary>
|
||||
public ExpandField Expand { get; set; }
|
||||
}
|
Loading…
Reference in New Issue