二开案例.动态表单插件.动态创建显示列

栏目:云星空知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

二开案例.动态表单插件.动态创建显示列

需求

显示某个产线下的所有序列号,并能够看出序列号加工到哪个作业,作业的列数不固定,需要动态显示

实现逻辑

OnSetBusinessInfo事件与OnSetLayoutInfo事件一起使用,通过捕获OnSetBusinessInfo事件,修改单据的逻辑元模型(BusinessInfo),动态添加字段,通过捕获OnSetLayoutInfo事件修改单据的布局元模型(LayoutInfo),设置动态添加字段的位置。

元数据

 

最终效果

 

示例代码

/// <summary>
/// 当前业务信息
/// </summary>
private BusinessInfo currBusinessInfo;
/// <summary>
/// 当前布局信息
/// </summary>
private LayoutInfo currLayoutInfo;
/// <summary>
/// 工作中心Id
/// </summary>
private long workCenterId;
/// <summary>
/// 生产订单单据类型(启用工序跟踪、柔性生产)
/// </summary>
private List<string> lstMoBillTypeFiltered = new List<string>();
/// <summary>
/// 工序信息,用于确定每个工序计划的工序及顺序
/// </summary>
private DynamicObjectCollection optInfos;
/// <summary>
/// 最大工序数,用于确定有多少列
/// </summary>
private int maxOptNumber;
/// <summary>
/// 序列号信息,用于展示最终数据
/// </summary>
private DynamicObjectCollection snInfos;
 
public override void AfterBindData(EventArgs e)
{
    base.AfterBindData(e);
 
    FillData();
}
 
/// <summary>
/// 填充数据
/// </summary>
private void FillData()
{
    //序列号条件
    string snCondition = Convert.ToString(this.Model.GetValue("FSnCondition"));
 
    IEnumerable<DynamicObject> snInfosByCondition;
    if (snCondition.IsNullOrEmptyOrWhiteSpace())
    {
        snInfosByCondition = snInfos;
    }
    else
    {
        snInfosByCondition = snInfos.Where(o => Convert.ToString(o["FSNNumber"]).Contains(snCondition));
    }
 
    List<IGrouping<object, DynamicObject>> snInfoGroupBySerialId = snInfosByCondition.GroupBy(o => o["FSerialId"]).ToList();
 
    //清除数据
    this.Model.DeleteEntryData("FEntity");
    //行
    for (int i = 0; i < snInfoGroupBySerialId.Count(); i++)
    {
 
        //添加一行
        this.Model.CreateNewEntryRow("FEntity");
 
        //当前行序列号信息
        IGrouping<object, DynamicObject> curRowSnInfo = snInfoGroupBySerialId[i];
        long optPlanId = Convert.ToInt64(curRowSnInfo.FirstOrDefault()["FOptPlanId"]);
        Dictionary<long, IGrouping<long, DynamicObject>> dicOptInfo = optInfos.GroupBy(o => Convert.ToInt64(o["FOptPlanId"])).ToDictionary(o => o.Key);
        //当前行工序信息
        List<DynamicObject> curRowOptInfo = dicOptInfo[optPlanId].OrderBy(o => Convert.ToInt64(o["FOperNumber"])).ToList();
 
        string snNumber = Convert.ToString(curRowSnInfo.FirstOrDefault()["FSNNumber"]);
        //序列号
        this.View.Model.SetValue("FSnNumber", snNumber, i);
 
        //列
        for (int j = 0; j < curRowOptInfo.Count; j++)
        {
            //当前列的序列号信息,存在返修序的时候满足条件的不止一个,取审核时间最近的一个(sql取数的时候已经排序)
            DynamicObject curColumnSnInfo = curRowSnInfo.Where(o => Convert.ToInt64(o["FOperNumber"]) == Convert.ToInt64(curRowOptInfo[j]["FOperNumber"])
                && Convert.ToInt64(o["FProcessId"]) == Convert.ToInt64(curRowOptInfo[j]["FProcessId"])).FirstOrDefault();
            if (curColumnSnInfo != null)
            {
                string key = "FProcess" + (j + 1).ToString();
                string value = string.Format("{0}-{1}-{2}-1", curColumnSnInfo["FOperNumber"], curColumnSnInfo["FProcessName"], curColumnSnInfo["FQtyType"]);
                this.View.Model.SetValue(key, value, i);
            }
        }
    }
    //刷新
    this.View.UpdateView("FEntity");
}
 
/// <summary>
/// 调整单据的逻辑元数据包,动态添加列
/// </summary>
/// <param name="e"></param>
public override void OnSetBusinessInfo(SetBusinessInfoArgs e)
{
    workCenterId = Convert.ToInt64(this.View.OpenParameter.GetCustomParameter("WorkCenterId"));
 
    //生产订单单据类型
    Dictionary<string, DynamicObject> dicMoBillType = SFCCommonServiceHelper.GetAllMoBillType(this.Context);
    foreach (var moBillType in dicMoBillType)
    {
        //工序跟踪
        bool isProcessTrack = moBillType.Value.GetDynamicObjectItemValue<bool>("IsProcessTrack");
        //柔性生产
        bool isFlexibleProduce = moBillType.Value.GetDynamicObjectItemValue<bool>("FlexibleProduce");
        //工序跟踪 and 柔性生产
        if (isProcessTrack && isFlexibleProduce)
        {
            lstMoBillTypeFiltered.Add(moBillType.Key);
        }
    }
 
    optInfos = GetOptInfos(workCenterId, lstMoBillTypeFiltered.ToArray());
 
    //optInfos.GroupBy(o => o["FOptPlanId"]).ToDictionary(o => o.Key, o => o.Count()).Max(o => o.Value);
    maxOptNumber = optInfos.GroupBy(o => o["FOptPlanId"]).Max(o => o.Count());
 
    snInfos = GetSnInfos(workCenterId, lstMoBillTypeFiltered.ToArray());
 
    // 创建当前单据元数据副本,避免直接修改原始元数据,并发时有问题
    FormMetadata currmetadata = (FormMetadata)ObjectUtils.CreateCopy(
                                this.View.OpenParameter.FormMetaData);
    currBusinessInfo = currmetadata.BusinessInfo;
    currLayoutInfo = currmetadata.GetLayoutInfo();
 
    // 取单据体的元数据模型
    string currEntityKey = "FEntity";
    Entity currEntity = currBusinessInfo.GetEntity(currEntityKey);
 
    // 取原始的字段。动态添加的字段,是基于原始字段的一个分身
    Field oriField = currBusinessInfo.GetField("FSnNumber");
    FieldAppearance oriFieldApp = currLayoutInfo.GetFieldAppearance("FSnNumber");
 
    AddNewFieldsToBusinessInfo(currEntityKey, currEntity, oriField);
 
    // 强制要求重新构建单据的ORM模型
    currBusinessInfo.GetDynamicObjectType(true);
 
    // 输出动态调整后的单据逻辑元数据模型(BusinessInfo)
    e.BusinessInfo = currBusinessInfo;
    e.BillBusinessInfo = currBusinessInfo;
}
 
/// <summary>
/// 调整单据的布局元数据,为动态添加列,产生外观布局对象
/// </summary>
/// <param name="e"></param>
public override void OnSetLayoutInfo(SetLayoutInfoArgs e)
{
    // 取原始字段的外观布局对象,尺码需仿照原始字段外观
    FieldAppearance oriFldApp = currLayoutInfo.GetFieldAppearance("FSnNumber");
 
    // 取明细表格外观布局对象
    EntityAppearance entryApp = currLayoutInfo.GetEntityAppearance(oriFldApp.EntityKey);
 
    // 设置字段的录入顺序
    int tabIndex = oriFldApp.Tabindex;
 
    tabIndex = AddNewFieldsToLayoutInfo(oriFldApp, tabIndex);
 
    // 对表格中的字段,重新按照TabIndex进行排序
    entryApp.Layoutinfo.Sort();
 
    // 输出动态调整后的单据布局
    e.LayoutInfo = currLayoutInfo;
 
    // 要求明细表格,重新构建各列,以便把新加入的字段,也加入到表格控件中
    EntryGrid grid = this.View.GetControl<EntryGrid>("FEntity");
    grid.SetCustomPropertyValue("AllowLayoutSetting", false);
    grid.CreateDyanmicList(currLayoutInfo.GetEntityAppearance("FEntity"));
    this.View.SendDynamicFormAction(this.View);
}
 
/// <summary>
/// 增加新字段到业务信息
/// </summary>
/// <param name="currEntityKey"></param>
/// <param name="currEntity"></param>
/// <param name="oriField"></param>
private void AddNewFieldsToBusinessInfo(string currEntityKey, Entity currEntity, Field oriField)
{
    for (int i = 0; i < maxOptNumber; i++)
    {
        // 基于原始字段,复制出新字段,并设置必须改动的属性
        Field newField = (Field)ObjectUtils.CreateCopy(oriField);
        newField.DynamicProperty = null;
        newField.ChildrenFields.Clear();
        newField.EntityKey = currEntityKey;
        newField.Entity = currEntity;
        if (newField.UpdateActions != null)
        {
            newField.UpdateActions.Clear();
        }
        // 必改属性,涉及到数据的加载
        string name = "FProcess" + (i + 1).ToString();
        newField.Key = name;
        newField.FieldName = name;
        newField.PropertyName = name;
        string chineseNumber = NumToChinese((i + 1).ToString());
        newField.Name = new LocaleValue(Kingdee.BOS.Resource.ResManager.LoadKDString("作业", "0151515153565030034703", Kingdee.BOS.Resource.SubSystemType.MFG) + chineseNumber);
 
        // 把新字段,添加到单据的逻辑元数据模型(BusinessInfo)中
        currBusinessInfo.Add(newField);
    }
}
 
/// <summary>
/// 增加新字段到布局信息
/// </summary>
/// <param name="oriFldApp"></param>
/// <param name="tabIndex"></param>
/// <returns></returns>
private int AddNewFieldsToLayoutInfo(FieldAppearance oriFldApp, int tabIndex)
{
    for (int i = 0; i < maxOptNumber; i++)
    {
        // 基于原始字段的外观,产生出新字段的外观
        FieldAppearance newFieldApp = (FieldAppearance)ObjectUtils.CreateCopy(oriFldApp);
        string name = "FProcess" + (i + 1).ToString();
        string chineseNumber = NumToChinese((i + 1).ToString());
 
        newFieldApp.Key = name;
        newFieldApp.Caption = new LocaleValue(Kingdee.BOS.Resource.ResManager.LoadKDString("作业", "0151515153565030034703", Kingdee.BOS.Resource.SubSystemType.MFG) + chineseNumber);
        newFieldApp.Field = currBusinessInfo.GetField(name);
        newFieldApp.Tabindex = ++tabIndex;
 
        // 把新字段的外观,加入到单据布局对象中
        currLayoutInfo.Add(newFieldApp);
    }
    return tabIndex;
}


二开案例.动态表单插件.动态创建显示列

需求显示某个产线下的所有序列号,并能够看出序列号加工到哪个作业,作业的列数不固定,需要动态显示实现逻辑OnSetBusinessInfo事件与OnSet...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息