天涯何

博客园 首页 新随笔 联系 管理

常见问题处理(后)

如何构建过滤器Filter?

依据控件值进行筛选与排序
(一)依据一个控件值进行筛选:
H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter(); // 构建过滤器
H3.Data.Filter.And andMatcher = new H3.Data.Filter.And();   // 构造And匹配器
andMatcher.Add(new H3.Data.Filter.ItemMatcher("控件编码", H3.Data.ComparisonOperatorType.Equal, "筛选依据值")); // 添加筛选条件
filter.Matcher = andMatcher;
(二)依据多个控件值进行筛选:
1. 使用 “AND” 连接条件:
H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter(); // 构建过滤器
H3.Data.Filter.And andMatcher = new H3.Data.Filter.And();   // 构造And匹配器
andMatcher.Add(new H3.Data.Filter.ItemMatcher("控件编码1", H3.Data.ComparisonOperatorType.Equal, "筛选依据值1")); // 添加条件
andMatcher.Add(new H3.Data.Filter.ItemMatcher("控件编码2", H3.Data.ComparisonOperatorType.Equal, "筛选依据值2")); // 添加条件
filter.Matcher = andMatcher;
2. 使用 “OR” 连接条件:
H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter(); // 构建过滤器
H3.Data.Filter.Or orMatcher = new H3.Data.Filter.Or();      // 构造Or匹配器
orMatcher.Add(new H3.Data.Filter.ItemMatcher("控件编码1", H3.Data.ComparisonOperatorType.Equal, "筛选依据值1")); // 添加条件
orMatcher.Add(new H3.Data.Filter.ItemMatcher("控件编码2", H3.Data.ComparisonOperatorType.Equal, "筛选依据值2")); // 添加条件
filter.Matcher = orMatcher;
(三)依据字段进行排序:
1. 正序排序:
H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter(); // 构建过滤器
filter.AddSortBy("控件编码1", H3.Data.Filter.SortDirection.Ascending); // 添加排序依据
2. 倒序排序:
H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter(); // 构建过滤器
filter.AddSortBy("控件编码1", H3.Data.Filter.SortDirection.Descending); // 添加排序依据

✅ 必要说明:
(一)匹配器对象:
  • H3.Data.Filter.And​ 相当于 SQL 中的 AND 关键字。
  • H3.Data.Filter.Or​ 相当于 SQL 中的 OR 关键字。
(二)筛选条件:
  • H3.Data.ComparisonOperatorType.Equal​ 相当于 SQL 中的 =
  • H3.Data.ComparisonOperatorType.NotEqual​ 相当于 SQL 中的 !=
  • H3.Data.ComparisonOperatorType.Above​ 相当于 SQL 中的 >
  • H3.Data.ComparisonOperatorType.NotBelow​ 相当于 SQL 中的 >=
  • H3.Data.ComparisonOperatorType.Below​ 相当于 SQL 中的 <
  • H3.Data.ComparisonOperatorType.NotAbove​ 相当于 SQL 中的 <=

表单按钮编码分别是什么?

答:参考下面表格所示。

按钮名称 ActionName编码 按钮名称 ActionName编码 按钮名称 ActionName编码
暂存 Save 提交 Submit 删除 Remove
撤回 RetrieveInstance 同意 Submit 不同意 Reject
作废 CancelInstance 打印 Print 二维码 ViewQrCode
全屏 FullScreen 关闭 Close 编辑 Edit
转交 Forward 已阅 Read

如何批量操作(创建/更新)对象?

答:创建/更新大批量数据的时候,用commit可以提高效率。

H3.DataModel.BulkCommit commit = new H3.DataModel.BulkCommit();  // 创建一个BulkCommit对象,批量提交对象
H3.DataModel.BizObjectSchema schema = this.Request.Engine.BizObjectManager.GetPublishedSchema("D0001001");  // 获取指定Schema的定义

for(int i = 0; i < 1000; i++) {
    // 创建一个新的BizObject对象
    H3.DataModel.BizObject obj = new H3.DataModel.BizObject(this.Request.Engine, schema, this.Request.UserContext.UserId);
    
    obj["F000001"] = 1;  // 为该对象赋值
    obj.Create(commit);  // 将该对象添加到批量提交队列,如果对象已存在则可以使用obj.Update(commit);
}

string errorMsg = null;
commit.Commit(this.Request.Engine.BizObjectManager, out errorMsg);  // 提交所有对象,出错时返回错误信息

如何获取/修改子表数据?

答:对象子表以子对象数组形式存在,如果需要创建包含子表的对象或修改子表的值,需要构造或获取到子表对象数组,然后将子表对象数组赋值给主表的子表属性。

以下示例代码用于修改订单子表的某一列的值

protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
    // 获取子表属性并强制转换为对象数组
    H3.DataModel.BizObject[] details = (H3.DataModel.BizObject[]) this.Request.BizObject["D00002SalesOrderDetail"];

    // 判断子表是否有数据
    if(details != null && details.Length > 0)
    {
        // 创建一个List,用于存储修改后的子表对象
        List<H3.DataModel.BizObject> lstObject = new List<H3.DataModel.BizObject>();

        // 遍历每一条子表记录并进行修改
        foreach(H3.DataModel.BizObject detail in details)
        {
            // 修改子表列的属性
            detail["WaitStockOutQuantity"] = detail["Quantity"];
            lstObject.Add(detail);  // 将修改后的对象添加到List中
        }

        // 将List转换成对象数组,并重新赋值给主表的子表属性
        this.Request.BizObject["D00002SalesOrderDetail"] = lstObject.ToArray();
    }
}

后端通过主表业务对象给子表增加数据?

// 获取引擎管理对象
H3.IEngine engine = this.Engine;

// 表单编码
string masterSchemaCode = "D00021testtable";

// 表单数据Id
string masterBoId = "bbc60153-19b8-4a57-b074-0c5b77367f8d";

// 子表控件编码
string childSchemaCode = "D00021F7287906e76734bef8819176bc15a8763";

// Load出要修改数据的主表业务对象
H3.DataModel.BizObject masterBo = H3.DataModel.BizObject.Load(H3.Organization.User.SystemUserId, engine, masterSchemaCode, masterBoId, false);

// 获取子表结构体对象
H3.DataModel.BizObjectSchema childSchema = masterBo.Schema.GetChildSchema(childSchemaCode);

// 定义新的子表数据集合
List<H3.DataModel.BizObject> newChildBoList = new List<H3.DataModel.BizObject>();

// 获取子表内已有数据
H3.DataModel.BizObject[] childBoArray = (H3.DataModel.BizObject[]) masterBo[childSchemaCode];

if(childBoArray != null && childBoArray.Length > 0)
{
    foreach(H3.DataModel.BizObject itemBo in childBoArray)
    {
        // 将子表内已有数据循环添加到新的子表数据集合里
        newChildBoList.Add(itemBo);
    }
}

// 新增子表业务对象并添加到子表数据第一行
H3.DataModel.BizObject childBo1 = new H3.DataModel.BizObject(engine, childSchema, H3.Organization.User.SystemUserId);
childBo1["F0000002"] = "xxxxx";  // 设置新行的值
newChildBoList.Insert(0, childBo1);  // 插入到第一行

// 新增子表业务对象并添加到子表数据最后一行
H3.DataModel.BizObject childBo2 = new H3.DataModel.BizObject(engine, childSchema, H3.Organization.User.SystemUserId);
childBo2["F0000002"] = "yyyyyy";  // 设置新行的值
newChildBoList.Add(childBo2);  // 添加到最后一行

// 将新的子表数据集合赋值到子表控件
masterBo[childSchemaCode] = newChildBoList.ToArray();

// 修改主表业务对象,系统会自动识别出上面子表数据被修改了,执行完Update方法,新的子表数据就会被保存到数据库
masterBo.Update();

后端通过主表业务对象给子表删除数据?

// 获取引擎管理对象
H3.IEngine engine = this.Engine;

// 表单编码
string masterSchemaCode = "D00021testtable";

// 表单数据Id
string masterBoId = "bbc60153-19b8-4a57-b074-0c5b77367f8d";

// 子表控件编码
string childSchemaCode = "D00021F7287906e76734bef8819176bc15a8763";

// Load出要修改数据的主表业务对象
H3.DataModel.BizObject masterBo = H3.DataModel.BizObject.Load(H3.Organization.User.SystemUserId, engine, masterSchemaCode, masterBoId, false);

// 获取子表结构体对象
H3.DataModel.BizObjectSchema childSchema = masterBo.Schema.GetChildSchema(childSchemaCode);

// 定义新的子表数据集合
List<H3.DataModel.BizObject> newChildBoList = new List<H3.DataModel.BizObject>();

// 获取子表内已有数据
H3.DataModel.BizObject[] childBoArray = (H3.DataModel.BizObject[]) masterBo[childSchemaCode];

if(childBoArray != null && childBoArray.Length > 0)
{
    foreach(H3.DataModel.BizObject itemBo in childBoArray)
    {
        // 取出子表内F0000002控件的值
        string F0000002 = itemBo["F0000002"] + string.Empty;

        // 判断F0000002控件的值是否为空,不为空时,才将当前子表行数据添加到新的子表数据集合中
        if(!string.IsNullOrEmpty(F0000002))
        {
            // 将符合条件的子表行数据添加到新的子表数据集合中
            newChildBoList.Add(itemBo);
        }
    }
}

// 将新的子表数据集合赋值到子表控件
masterBo[childSchemaCode] = newChildBoList.ToArray();

// 修改主表业务对象,系统会自动识别出上面子表数据被修改了,执行完Update方法,新的子表数据就会被保存到数据库
masterBo.Update();

如何查询可序列化的虚业务对象?

答:可序列化的虚业务对象可以直接返回到前台,由前台代码直接接收。以下示例代码用于在后台查询业务对象数组并添加到Response.ReturnData。由前台代码接收Response.ReturnData数据。

if(actionName == "BtnCheck")
{
    // 获取传入的账号名称
    string accountName = postValue.Data["AccountName"] + string.Empty;

    // 创建过滤器对象
    H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter();

    // 创建And匹配器
    H3.Data.Filter.And andMatcher = new H3.Data.Filter.And();

    // 添加匹配条件:AccountName字段包含accountName
    andMatcher.Add(new H3.Data.Filter.ItemMatcher("AccountName", H3.Data.ComparisonOperatorType.Contains, accountName));

    // 设置过滤器的匹配器
    filter.Matcher = andMatcher;

    int count = 0;
    Dictionary<string, H3.DataModel.BizObjectHeader> headers = null;
    Dictionary<string, string> userNames = null;

    // 查询虚对象列表
    H3.Data.Serialization.VirtualObject[] objects = this.Request.Engine.BizObjectManager.GetList(
        H3.Organization.User.SystemUserId,
        "D00002Account", // 表单编码
        H3.DataModel.GetListScopeType.GlobalAll, // 全局范围
        filter, // 过滤条件
        out count, // 查询结果计数
        true, // 是否包含数据
        out headers, // 输出的业务对象头部信息
        out userNames // 输出的用户名字典
    );

    // 返回数据
    response.ReturnData = new Dictionary<string, object>();
    response.ReturnData.Add("Objects", objects); // 将查询到的虚对象返回到前台
}

如何一键清除表单的所有数据?

答:氚云提供对表单所有数据的一键清除功能,该操作不受数据之间引用限制

string schemaCode   ="D00002Lead";

this.Request.Engine.BizObjectManager.Clear(schemaCode); //清除表单D00002Lead的所有数据。数据清除后不可恢复,请谨慎操作。

如何创建带流程表单,同时发起流程?

答:如果是带流程的表单,在创建业务对象时需要发起流程,需要调用Engine.WorkflowInstanceManager.OriginateInstance接口发起流程。

// 获取发布的BizObjectSchema
H3.DataModel.BizObjectSchema schema = this.Request.Engine.BizObjectManager.GetPublishedSchema("D000001InspectIssue");

// 创建一个新的BizObject
H3.DataModel.BizObject iReport = new H3.DataModel.BizObject(this.Request.Engine, schema, this.Request.UserContext.UserId, this.Request.UserContext.User.ParentId);

// 设置相关字段
iReport["IssueReportName"] = "关于****的整改报告";

// 生成唯一的实例ID
string instanceId = System.Guid.NewGuid().ToString();

// 如果WorkflowInstanceId为空,设置为新生成的实例ID
if (string.IsNullOrEmpty(iReport.WorkflowInstanceId))
    iReport.WorkflowInstanceId = instanceId;

// 创建BizObject
iReport.Create();

// 获取工作流实例
H3.Workflow.Instance.WorkflowInstance wfInstance = this.Request.Engine.WorkflowInstanceManager.GetWorkflowInstance(iReport.WorkflowInstanceId);

if (wfInstance == null)
{
    // 启动工作流

    string workItemID = string.Empty;
    string errorMsg = string.Empty;

    // 获取默认工作流模板
    H3.Workflow.Template.WorkflowTemplate wfTemp = this.Request.Engine.WorkflowTemplateManager.GetDefaultWorkflow(iReport.Schema.SchemaCode);
	//如果是定时器一类的任务发起要将 this.Request.UserContext.UserId 替换成 H3.Organization.User.SystemUserId
    // 发起工作流实例
  this.Request.Engine.WorkflowInstanceManager.OriginateInstance(this.Request.UserContext.UserId, iReport.Schema.SchemaCode, wfTemp.WorkflowVersion, iReport.ObjectId, iReport.WorkflowInstanceId, H3.Workflow.WorkItem.AccessMethod.Web, true, string.Empty, true, out workItemID, out errorMsg);

}

如何添加角色及权限?

// 创建一个新的组织角色
H3.Organization.OrgRole role = new H3.Organization.OrgRole();

// 设置角色的相关属性
role.Code = "manager";       // 角色编码
role.Name = "经理";          // 角色名称
role.CompanyId = Engine.Organization.Company.CompanyId; // 设置公司ID

// 添加角色到公司
Engine.Organization.AddUnit(role); // 创建角色

// 创建权限控制对象
H3.Acl.FunctionAcl acl = new H3.Acl.FunctionAcl(role.Code, "客户管理", "createdby");

// 给角色添加权限
Engine.FunctionAclManager.AddAcl(acl); // 给角色添加权限

如何获取前台post到后台数据的值?

string customer   = this.Request[“Customer”]+string.Empty;

如何获取response到前台数据的值?

object value=response.ReturnData["dataField"];

如何根据当前登录用户所在角色设置字段的可见权限?

// 获取当前登录用户的所有角色
H3.Organization.OrgRole[] _userRoles = this.Request.Engine.Organization.GetUserRoles(this.Request.UserContext.UserId, false);

// 标志位,判断是否为“系统管理员”
bool _flag = false;

if (_userRoles != null)
{
    // 遍历用户角色
    foreach (H3.Organization.OrgRole _userRole in _userRoles)
    {
        // 判断当前角色是否为“系统管理员”
        if (_userRole.Name == "系统管理员")
        {
            _flag = true;
            break;
        }
    }
}

// 如果是“系统管理员”,设置字段不可见和不可编辑
if (_flag)
{
    response.ReturnData["F0000001"].Visible = false;  // 设置字段F0000001不可见
    response.ReturnData["F0000002"].Editable = false; // 设置字段F0000002不可编辑
}

如何获取附件ID?

// 获取附件控件中所有的文件信息
H3.DataModel.BizObjectFileHeader[] files = (H3.DataModel.BizObjectFileHeader[]) this.Request.BizObject["F0000020"]; // 附件控件

// 遍历所有文件信息
foreach (H3.DataModel.BizObjectFileHeader f in files)
{
    // 获取每个附件文件的FileId
    string FileId = f.FileId + string.Empty;
}

如何批量获取附件ID?

// 定义一个空字符串来存储文件信息
string fileInfo = "";

// 创建一个包含表单ObjectId的数组,这个ObjectId代表了需要获取附件的表单数据
string[] ObjectDataId = { child.ObjectId }; // 表单的objectid数组

// 使用BizObjectManager获取与表单相关的文件头信息
H3.DataModel.BizObjectFileHeader[] fileobject = this.Request.Engine.BizObjectManager.GetBizObjectFileHeaders(ObjectDataId);

// 判断是否成功获取到文件头信息
if (fileobject != null && fileobject.Length > 0)
{
    // 遍历每个文件头
    foreach (H3.DataModel.BizObjectFileHeader item in fileobject)
    {
        // 将文件ID添加到fileInfo字符串中,并以分号分隔
        fileInfo += item.FileId + ";";
    }
}

// 注意:新增的时候获取不了ID

如何判断当前用户是不是管理员?

// 获取当前用户的ID,并将其转换为字符串
string userId = this.Request.UserContext.UserId + string.Empty;

// 根据用户ID,获取该用户的所有角色
H3.Organization.OrgRole[] userRoles = this.Engine.Organization.GetUserRoles(userId, true);

// 遍历所有角色,判断是否包含"系统管理员"角色
for (int i = 0; i < userRoles.Length; i++)
{
    // 如果当前角色名称为"系统管理员",则设置返回消息为"true"
    if (userRoles[i].Name == "系统管理员")
    {
        response.Message = "true";
    }
}

如何获取角色中的所有人员?

// 初始化一个空的角色ID字符串
string Dianzhang = "";

// 获取所有角色
H3.Organization.OrgRole[] allRoles = this.Engine.Organization.GetAllRoles();

// 遍历所有角色
foreach(H3.Organization.OrgRole allRole in allRoles)
{
    // 判断当前角色名称是否为"公海提醒"
    if(allRole.Name == "公海提醒")
    {
        // 如果是,则将该角色的ObjectId赋值给Dianzhang
        Dianzhang = allRole.ObjectId;
    }
}

// 获取"公海提醒"角色下的所有成员ID
string[] Renyuans = this.Engine.Organization.GetChildren(Dianzhang, H3.Organization.UnitType.User, true, H3.Organization.State.Active);

如何隐藏子表某列?

// 获取子表数据
Dictionary<string, object> TaskObjects1 = (Dictionary<string, object>)response.ReturnData["D00021cChildTable"].Value;

// 获取子表具体的数据项(这里的“子表”是通过键 "T" 访问的)
Dictionary<string, H3.SmartForm.SmartFormResponseDataItem> taskobject1 = (Dictionary<string, H3.SmartForm.SmartFormResponseDataItem>)TaskObjects1["T"];

// 遍历子表数据的所有键
foreach (string key in taskobject1.Keys)
{
    // 判断是否是特定字段 "D00021cChildTable.ChildNumber"
    if (key == "D00021cChildTable.ChildNumber")
    {
        // 如果是,设置该列为不可见
        taskobject1[key].Visible = false;
    }
}

如何对附件、图片进行复制?

答:调用CopyFiles()。

CopyFiles​ 方法参数说明
  1. 源表和目标表编码

    • "原-主表编码"​、"原-子表编码"​:源表的编码。
    • "新-主表编码"​、"新-子表编码"​:目标表的编码。
  2. 源附件控件和目标附件控件编码

    • "原-主表内附件控件编码"​、"原-子表内附件控件编码"​:源附件控件的编码。
    • "新-主表内附件控件编码"​、"新-子表内附件控件编码"​:目标附件控件的编码。
  3. 源表数据的 ObjectId 和目标表数据的 ObjectId

    • "原-主表数据ObjectId"​、"原-子表数据ObjectId"​:源表的 ObjectId。
    • "新-主表数据ObjectId"​、"新-子表数据ObjectId"​:目标表的 ObjectId。
  4. 最后两个参数

    • 第一个 true​:表示是否覆盖目标附件(true​ 为覆盖,false​ 为添加)。
    • 第二个 true​:表示如果是覆盖模式,是否删除原始附件的物理文件(true​ 为删除,false​ 为只删除记录)。
从主表内附件控件复制到主表内附件控件
this.Request.Engine.BizObjectManager.CopyFiles("原-主表编码", "", "原-主表内附件控件编码", "原-主表数据ObjectId", "新-主表编码", "", "新-主表内附件控件编码", "新-主表数据ObjectId", true, true);
从主表内附件控件复制到子表内附件控件
this.Request.Engine.BizObjectManager.CopyFiles("原-主表编码", "", "原-主表内附件控件编码", "原-主表数据ObjectId", "新-主表编码", "新-子表编码", "新-子表内附件控件编码", "新-子表数据ObjectId", true, true);
从子表内附件控件复制到主表内附件控件
this.Request.Engine.BizObjectManager.CopyFiles("原-主表编码", "原-子表编码", "原-子表内附件控件编码", "原-子表数据ObjectId", "新-主表编码", "", "新-主表内附件控件编码", "新-主表数据ObjectId", true, true);
从子表内附件控件复制到子表内附件控件
this.Request.Engine.BizObjectManager.CopyFiles("原-主表编码", "原-子表编码", "原-子表内附件控件编码", "原-子表数据ObjectId", "新-主表编码", "新-子表编码", "新-子表内附件控件编码", "新-子表数据ObjectId", true, true);

如何获取图片链接?

// 获取图片缩略图url,FileId:附件Id
string fileurl = this.Request.UserContext.GetThumbnailUrl(string FileId);

// 该接口即将下线,如果上述接口报错提示缺少参数,请使用新接口
string thumbnailUrl = this.Request.UserContext.GetThumbnailUrl(string FileId, string ThumbnailKey);

// 示例代码:
string ObjectDataId = this.Request.BizObjectId; // 表单的objectid数组

// 支持多个数据ObjectId参数查询
H3.DataModel.BizObjectFileHeader[] fileobject = this.Request.Engine.BizObjectManager.GetBizObjectFileHeaders(new string[] { ObjectDataId });

if (fileobject != null && fileobject.Length > 0)
{
    foreach (H3.DataModel.BizObjectFileHeader item in fileobject)
    {
        // 获取图片缩略图
        string thumbnailUrl = this.Request.UserContext.GetThumbnailUrl(item.ObjectId, item.ThumbnailKey);
    }
}

// 获取原图url,FileId:附件Id
string url = "https://www.h3yun.com/Form/DoPreview/?attachmentId=" + FileId;

如何构建虚业务对象返回给前端?

答:前端PostForm请求后端,后端返回前端的数据组,需要构建虚业务对象。

前端代码
var parent = this;

$.SmartForm.PostForm("QueryStudentInfo", {
    StudentId: "123" // 学生ID
}, function(data) {
    if (data.Errors && data.Errors.length) {
        $.IShowError("错误", JSON.stringify(data.Errors));
    } else {
        debugger;
        var result = data.ReturnData;

        if (result["StudentName"]) {
            // 获取后端返回的学生姓名
            var StudentName = result["StudentName"];
            // 给当前表单的F0000010控件设置值
            parent.F0000010.SetValue(StudentName);
        }

        if (result["ClassInfo"]) {
            // 获取后端返回的学生所在班级信息
            var ClassName = result["ClassInfo"]["ValueTable"];
        }

        if (result["LikeList"]) {
            // 获取后端返回的学生喜好
            var LikeList = result["LikeList"];
        }

        if (result["FamilyInfo"]) {
            // 获取后端返回的学生家庭信息
            var FamilyInfo = result["FamilyInfo"];
        }
    }
}, function(error) {
    $.IShowError("错误", JSON.stringify(error));
}, false);
后端代码
protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
    if (actionName == "QueryStudentInfo")
    {
        response.ReturnData = new Dictionary<string, object>();

        // 从请求对象中获取学生ID
        string StudentId = this.Request["StudentId"] + string.Empty;

        if (StudentId == "123")
        {
            // 将学生姓名添加到响应对象中
            response.ReturnData.Add("StudentName", "张三");

            // 将学生所在班级信息添加到响应对象中
            H3.Data.Serialization.VirtualObject ClassInfo = new H3.Data.Serialization.VirtualObject();
            ClassInfo.ValueTable["ClassName"] = "大一";
            response.ReturnData.Add("ClassInfo", ClassInfo);

            // 将学生喜好添加到响应对象中
            string[] LikeList = new string[3];
            LikeList[0] = "Rap";
            LikeList[1] = "跳舞";
            LikeList[2] = "打篮球";
            response.ReturnData.Add("LikeList", LikeList);

            // 将学生家庭信息添加到响应对象中
            List<H3.Data.Serialization.VirtualObject> FamilyInfo = new List<H3.Data.Serialization.VirtualObject>();

            // 将父亲信息添加到响应对象中
            H3.Data.Serialization.VirtualObject FatherInfo = new H3.Data.Serialization.VirtualObject();
            FatherInfo.ValueTable["Name"] = "李四";
            FatherInfo.ValueTable["Age"] = 41;
            FamilyInfo.Add(FatherInfo);

            // 将母亲信息添加到响应对象中
            H3.Data.Serialization.VirtualObject MotherInfo = new H3.Data.Serialization.VirtualObject();
            MotherInfo.ValueTable["Name"] = "王五";
            MotherInfo.ValueTable["Age"] = 41;
            FamilyInfo.Add(MotherInfo);

            response.ReturnData.Add("FamilyInfo", FamilyInfo);
        }
        else
        {
            // 响应给前端一个异常信息
            response.Errors.Add("未找到StudentId为“" + StudentId + "”的学生信息!");
        }
    }

    base.OnSubmit(actionName, postValue, response);
}

如何更新子表业务对象?

答:与主表业务对象更新类似。需要注意:子表的数据标题,如果配有主表字段控件则不可使用这样的更新写法。

string schemaCode = "";  // 子表控件编码
string detail = "";      // 子表ObjectId

// Load对象
H3.DataModel.BizObject accountBo = H3.DataModel.BizObject.Load(this.Request.UserContext.UserId, this.Request.Engine, schemaCode, detail, false);

// 修改对象属性值
accountBo["CustomerName"] = "深圳氚云网络科技有限公司";  // 设置客户名称
accountBo["CustomerLevel"] = "已成交";                    // 设置客户等级

// 将对象状态设为生效
accountBo.Status = H3.DataModel.BizObjectStatus.Effective;

// 更新对象
accountBo.Update();

如何重构列表数据?

答:重写response.ReturnData数据集。

protected override void OnLoad(H3.SmartForm.LoadListViewResponse response)
{
    base.OnLoad(response);

    string isFormControl = this.Request["isFormControl"] == null ? "" : this.Request["isFormControl"].ToString();

    // 判断是否是在load列表数据时
    if (isFormControl != "1" && isFormControl != "true")
    {
        H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter();
        H3.Data.Filter.And andMatcher = new H3.Data.Filter.And();

        // 将系统自带的filter添加进来,否则系统自带的筛选将失效
        andMatcher.Add(this.Request.Filter.Matcher);
        filter.Matcher = andMatcher;

        // 获取当前表单业务对象模式
        H3.DataModel.BizObjectSchema allTaskSchema = this.Request.Schema;

        // 获取列表过滤后的业务对象
        H3.DataModel.BizObject[] tasks = H3.DataModel.BizObject.GetList(this.Request.Engine, this.Request.UserContext.UserId, allTaskSchema, H3.DataModel.GetListScopeType.GlobalAll, filter);

        // 初始化一个集合,用来存储经过筛选后响应给前端的数据
        List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();

        if (tasks != null && tasks.Length > 0)
        {
            // 筛选需要显示的列表数据,例如筛选出状态为正常的数据
            foreach (H3.DataModel.BizObject biz in tasks)
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();

                string obj = biz["ObjectId"] + string.Empty; // 获取表单ID
                string state = biz["F0000002"] + string.Empty; // 获取状态

                if (state == "正常" && obj != "")
                {
                    // 构造当前表单业务对象
                    H3.DataModel.BizObject Client = new H3.DataModel.BizObject(this.Engine, this.Request.Schema, this.Request.UserContext.UserId);
                    Client.ObjectId = obj; // 给对象ID赋值
                    Client.Load(); // 根据ID加载业务对象

                    Dictionary<string, Dictionary<string, string>> dicdate = null;

                    foreach (H3.DataModel.PropertySchema pro in this.Request.Schema.Properties) // 给dic赋值
                    {
                        // 附件、图片不会显示在列表上,需要排除掉
                        if (pro.DataType == H3.Data.BizDataType.File || pro.DataType == H3.Data.BizDataType.Image || pro.DataType == H3.Data.BizDataType.BizObjectArray)
                        {
                            continue;
                        }

                        // F0000008控件为日期控件,在这个转成标准的日期表达字符串,用于改变列表对此列异常的显示
                        if (pro.Name == "F0000008")
                        {
                            dic.Add(pro.Name, Client[pro.Name] + string.Empty);
                        }
                        else
                        {
                            dic.Add(pro.Name, Client[pro.Name]);
                        }
                    }

                    /*----Start 以下代码为构造手机端摘要信息----*/
                    string mobilesummary = null; // 移动端摘要构造器所需
                    string pcsummary = null; // 移动端摘要构造器所需
                    string telephone = null; // 移动端摘要构造器所需

                    Client.GetSummary(out dicdate, out mobilesummary, out pcsummary, out telephone); // 返回摘要信息

                    dic.Add("__MobileSummary", mobilesummary);
                    dic.Add("__MobileDicData", dicdate);
                    /*----End 以上代码为构造手机端摘要信息----*/

                    // 将经过筛选后的数据对象 添加进集合中
                    list.Add(dic);
                }
            }

            // 赋值筛选后的列表数据
            response.ReturnData = new List<Dictionary<string, object>>();
            response.ReturnData = list;

            // 由于我们改变了ReturnData集合,所以这里需要改变响应数据的条数
            response.DataCount = list.Count;
        }
    }
}

如何序列化/反序列化JSON?

答:提供C#的Newtonsoft.Json组件进行解析。

string value = this.Serialize(object value);//将对象序列化成json格式的字符串

T value = this.Deserialize<T>(string value);//将json格式的字符串反序列化成T类型的对象

如何获取子表中的字段值?

答:例如获取子表中F0000001字段的值。先获取子表控制值,将其转化为对象数组,在循环遍历取值。

// 获取子表属性并强制转换为对象数组
H3.DataModel.BizObject[] details = (H3.DataModel.BizObject[])this.Request.BizObject["D00002SalesOrderDetail"]; 

// 判断子表是否有数据
if (details != null && details.Length > 0)
{
    // 遍历每一个子表数据对象
    foreach (H3.DataModel.BizObject detail in details)
    {
        // 获取子表中F0000001字段的值
        string zz = detail["F0000001"] + string.Empty; // 获取字段值,并确保不为空
    }
}

表单后端获取审批时填入的审批意见?

protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
    // 如果是提交操作,且当前活动节点是 Activity3
    if(actionName == "Submit" && this.Request.ActivityCode == "Activity3")
    {
        // 获取审批意见
        string comment = postValue.Comment.Text;
        // 你可以在此对comment进行进一步处理,例如存储或日志记录
    }

    // 如果是拒绝操作,且当前活动节点是 Activity3
    if(actionName == "Reject" && this.Request.ActivityCode == "Activity3")
    {
        // 获取审批意见
        string comment = postValue.Comment.Text;
        // 你可以在此对comment进行进一步处理,例如存储或日志记录
    }

    // 调用基类的OnSubmit方法,确保其他处理逻辑得以执行
    base.OnSubmit(actionName, postValue, response);
}

根据流程Id获取流程当前所处节点?

H3.Workflow.Instance.IToken tok = this.Request.Engine.WorkflowInstanceManager.GetWorkflowInstance("流程id").GetLastToken();
IToken​ 属性
  • tok.Activity​:

    • 流程节点编码,类型是 string​,用于标识当前流程节点。
  • tok.Approval​:

    • 流程审批状态,类型是 H3.Data.BoolValue​,有三个可能的值:

      • H3.Data.BoolValue.True​:表示审批通过(同意)。
      • H3.Data.BoolValue.False​:表示审批拒绝(不同意)。
      • H3.Data.BoolValue.Unspecified​:表示未处理,或者流程节点被取消。
  • tok.TokenId​:

    • 流程步骤的唯一标识符,类型是 string​,对应数据库中 H_Token​ 表的 ObjectId​ 字段。
  • tok.Participants​:

    • 流程节点的审批人,类型是 string[]​,每个元素都是一个审批人的用户ID,表示该节点的审批人列表。
  • tok.CreatedTime​:

    • 流程节点的创建时间,类型是 DateTime​,表示该流程节点开始的时间。
  • tok.FinishedTime​:

    • 流程节点的结束时间,类型是 DateTime​,表示该流程节点结束的时间。
  • tok.UsedTime​:

    • 当前节点从开始到结束的耗时,类型是 TimeSpan​,用于表示节点的执行时长。

根据流程实例id查询指定状态工作项的显示名称和参与者

System.Data.DataTable b = this.Engine.Query.QueryWorkItemDisplayAndParticipant(string[] InstanceIds, H3.Workflow.WorkItem.WorkItemState state);
WorkItemState​ 枚举的状态值
  • Waiting​:处于等待的状态,表示工作项等待某个操作或审批。
  • Working​:处于正在工作中的状态,表示工作项正在处理或执行中。
  • Finished​:处于完成状态,表示工作项已完成并结束。
  • Canceled​:已被取消,表示工作项已被取消,不能再进行操作。
  • Unfinished​:并不属于工作项本身的状态,实际上等同于 Waiting​ 或 Working​ 状态,通常用于查询未完成的工作项。
  • NotCanceled​:并不属于工作项本身的状态,实际上指 Waiting​、Working​ 或 Finished​,即未被取消的工作项状态。
  • Unspecified​:未指定的状态,用于方便查询,表示不特定的工作项状态。

数据提交时字段明明有值,但是提交到后台后没有赋值上

答:这种情况一般是你字段为不可写,然后通过代码SetValue的值,这种情况,你只需要在OnSubmit通过

this.Request.BizObject["字段"]\=postValue.Data["字段"];

怎么判断数据为提交还是编辑

答:如果是提交的数据,在OnSubmit里面判断(因为编辑的时候他的数据的状态是生效的状态)

if(this.Request.BizObject.Status==H3.DataModel.BizObjectStatus.Draft){
//这里是新增提交的时候写的代码
}
if(this.Request.BizObject.Status==H3.DataModel.BizObjectStatus.Effective){
//这里是编辑的时候写的代码
}

提交后获取流水号

//得到一个IEngine对象
H3.IEngine engine = this.Request.Engine;
//获取系统虚拟用户的人员Id(表单设计后端类、列表设计后端类、定时器类、自定义接口类中都可以获取)
string systemUserId = H3.Organization.User.SystemUserId;
//获取当前登录人的人员Id(只能在表单设计后端类、列表设计后端类中获取)
string currentUserId = this.Request.UserContext.UserId;
H3.DataModel.BizObject biz = H3.DataModel.BizObject.Load(currentUserId, engine, "D00021fbc02cce483842e6b65b3fb10dd64536", this.Request.BizObjectId + string.Empty, false);
//获取流水号并赋值
biz["F0000001"] = biz["SeqNo"] + string.Empty;
//流水号要在提交后获取

关联多选控件/人员多选控件前端传到后端

前端代码:

var parent = this;
this.F0000005.BindChange("key", function(){
    $.SmartForm.PostForm("GetDays", { F0000005: parent.F0000005.GetValue().join(',') },
        function(res){
            parent.F0000004.SetValue(res.ReturnData.Data1);
        },
        function(){
        },
        false
    );
});

后端代码:

if(actionName == "GetDays"){
    string str = this.Request["F0000005"] + string.Empty;
    string[] str1 = str.Split(',');
    foreach(string str2 in str1){
        H3.DataModel.BizObject biz = H3.DataModel.BizObject.Load(this.Request.UserContext.UserId, this.Engine, "D0002175521e4e872547d4b24098bd4ae17e3b", str2, false); //通过前端传回来的关联表单objectid,加载出业务对象
    }
}

列表自定义按钮(单条数据复制)

前端代码:

if (actionCode == "DataCopy") {
    //点击复制按钮时检查是否选中数据
    var objects = $.ListView.GetSelected();
    if (objects == null || objects == undefined || objects == "") {
        $.IShowWarn("您还未勾选数据,请勾选!");
        return;
    } else if (objects.length > 1) {
        $.IShowWarn("不好意思,只能勾选一个采购单");
        return;
    } else {
        $.ListView.Post("DataCopy", { objectId: objects[0].ObjectId, str1: "123" },
            function (data) {
                if (data.ReturnData == null || !data.ReturnData.Message) {
                    //刷新列表
                    $.ListView.RefreshView();
                    $.IShowSuccess("复制完成!");
                } else if (data.ReturnData != null && data.ReturnData.Message) {
                    $.IShowError(data.ReturnData.Message);
                } else {
                    $.IShowError("复制失败!");
                }
            },
            function (data) {
                $.IShowError(data.Errors[0]);
            },
            false
        );
    }
}

后端代码:

if (actionName == "DataCopy") {
    response.ReturnData = new Dictionary<string, object>();
    string objectId = this.Request["objectId"];
    string str1 = this.Request["str1"];
    if (!string.IsNullOrEmpty(objectId)) {
        H3.DataModel.BizObject accountBo = H3.DataModel.BizObject.Load(this.Request.UserContext.UserId, this.Engine, "D000213ef50cc75c5e4bac958ec64182d62d9d", objectId, false);
        if (accountBo != null) {
            H3.DataModel.BizObjectSchema schema = this.Request.Engine.BizObjectManager.GetPublishedSchema("D000213ef50cc75c5e4bac958ec64182d62d9d");
            H3.DataModel.BizObject obj = new H3.DataModel.BizObject(this.Request.Engine, schema, this.Request.UserContext.UserId); //主表对象
            obj["F0000001"] = DateTime.Now; //需求日期
            ...
            //附件
            this.Request.Engine.BizObjectManager.CopyFiles("D000213ef50cc75c5e4bac958ec64182d62d9d", "", "F0000012", accountBo.ObjectId, "D000213ef50cc75c5e4bac958ec64182d62d9d", "", "F0000012", obj.ObjectId, true, true);
            //子表数据不为空
            if (accountBo["D00021Fe17972588372432381107d8bc67e9d50"] != null) {
                //得到子表数据
                H3.DataModel.BizObject[] zibiao = (H3.DataModel.BizObject[])accountBo["D00021Fe17972588372432381107d8bc67e9d50"];
                //创建存新子表数据集合
                List<H3.DataModel.BizObject> zibiaoList = new List<H3.DataModel.BizObject>();
                //循环复制数据
                foreach (H3.DataModel.BizObject zb in zibiao) {
                    H3.DataModel.BizObjectSchema newSch = this.Request.Engine.BizObjectManager.GetPublishedSchema("D00021Fe17972588372432381107d8bc67e9d50");
                    H3.DataModel.BizObject newzb = new H3.DataModel.BizObject(this.Request.Engine, newSch, this.Request.UserContext.UserId);
                    newzb["F0000006"] = zb["F0000006"];
                    ...
                    zibiaoList.Add(newzb);
                }
                obj["D00021Fe17972588372432381107d8bc67e9d50"] = zibiaoList.ToArray();
            }
            obj.Status = accountBo.Status;
            if (string.IsNullOrEmpty(obj.WorkflowInstanceId))
                obj.WorkflowInstanceId = System.Guid.NewGuid().ToString();
            //创建对象
            H3.ErrorCode createResult = obj.Create();
            //判断是否成功创建数据对象
            if (createResult != H3.ErrorCode.Success) {
                response.ReturnData.Add("Message", createResult.ToString());
            } else {
                if (accountBo.Status == H3.DataModel.BizObjectStatus.Running) {
                    obj.Status = H3.DataModel.BizObjectStatus.Draft;
                    H3.Workflow.Instance.WorkflowInstance wfInstance = this.Request.Engine.WorkflowInstanceManager.GetWorkflowInstance(obj.WorkflowInstanceId);
                    if (wfInstance == null) {
                        //启动流程
                        string workItemID = string.Empty;
                        string errorMsg = string.Empty;
                        H3.Workflow.Template.WorkflowTemplate wfTemp = this.Request.Engine.WorkflowTemplateManager.GetDefaultWorkflow(obj.Schema.SchemaCode);
                        this.Request.Engine.Interactor.OriginateInstance(this.Request.UserContext.UserId, obj.Schema.SchemaCode, wfTemp.WorkflowVersion, obj.ObjectId, obj.WorkflowInstanceId, H3.Workflow.WorkItem.AccessMethod.Web, true, string.Empty, true, out workItemID, out errorMsg);
                    }
                }
            }
        } else {
            response.ReturnData.Add("Message", "数据对象未获取到!");
        }
    } else {
        response.ReturnData.Add("Message", "无数据对象ID!");
    }
}

如何根据某一个角色名获取角色中所有的人

1.获取公司所有角色H3.Organization.OrgRole[] allRoles = this.Request.Engine.Organization.GetAllRoles();

2.循环这个数组,找到你要的角色

3.获取所有用户 string[] userIds = this.Request.Engine.Organization.GetChildren(角色id, H3.Organization.UnitType.Role, true, H3.Organization.State.Active);

如何在导入excel的时候执行代码操作?

首先导入Excel会触发前端的填充,计算规则,不会触发OnSubmit事件,但是流程表单会触发流程结束事件,所以您需要在流程结束的回调时间中编写您的代码

protected override void OnWorkflowInstanceStateChanged(H3.Workflow.Instance.WorkflowInstanceState oldState, H3.Workflow.Instance.WorkflowInstanceState newState) {
    //流程审批结束事件(先执行业务规则,在执行该方法)。
    if (oldState == H3.Workflow.Instance.WorkflowInstanceState.Running && newState == H3.Workflow.Instance.WorkflowInstanceState.Finished) {
        //执行业务代码逻辑
    }
    base.OnWorkflowInstanceStateChanged(oldState, newState);
}

需要注意,如果流程设置的是开始节点直接到结束节点,中间没有审批节点,或者审批节点全部符合自动审批通过逻辑,需要使用如下代码

protected override void OnWorkflowInstanceStateChanged(H3.Workflow.Instance.WorkflowInstanceState oldState, H3.Workflow.Instance.WorkflowInstanceState newState) {
    //流程审批结束事件(先执行业务规则,在执行该方法)。
    if ((oldState == H3.Workflow.Instance.WorkflowInstanceState.Running || oldState == H3.Workflow.Instance.WorkflowInstanceState.Initiated) 
        && newState == H3.Workflow.Instance.WorkflowInstanceState.Finished) {
        //执行业务代码逻辑
    }
    base.OnWorkflowInstanceStateChanged(oldState, newState);
}

新加入的员工没进组织机构

排查以下内容

  1. 是否开启了氚云全员可见,如果没有,请先开启全员可见,然后点击手动同步,然后再设置回来
  2. 人员是否过多,如果组织机构超过1万人,会有几率出现这种情况,超过1万人使用的建议使用云枢进行交付

报表统计数据比真实翻倍了

这种情况一般是由于关联了子表,主表left join子表的时候,如果子表是两行,那么join出来的结果会有两行,这样就会出现统计结果翻倍的情况,建议使用sql进行编写

sql报表如何进行权限控制

只要在查询结果中暴露出OwnerId和OwnerDepartId就行,并一定要要求OwnerId对应的字段是拥有者,如果select man as OwnerId from table (这里的man是一个人员单选).这样也能达到控制权限的目的

复选框出现超过200字符限制的错误

image.png

复选框本质就是一个单行文本,他的字数限制是200个字,如果复选框所选择的字加起来超过了总字数就会报错

出现错误《根据 SchemaCode 获取 BizObjectSchema 失败》

{'Successful': False, 'ErrorMessage': '根据 SchemaCode 获取 BizObjectSchema 失败', 'Logined': False, 'ReturnData': {}, 'DataType': 0}

这种错误只可能有两种情况

1.EngineCode和EngineScrect填错了

2.SchemaCode填错了

注意:记得把EngineCode和EngineScrect写在Header里面

导入excel的时候关联表单有数据,但是导入时提示查询不到

这种情况,一般是由于您的数据是通过业务规则插入的,而且没插数据标题,您虽然看到了数据标题,那是平台帮忙显示的,本质上数据标题(数据库Name值)是空的。这样情况您需要编辑提交一下数据就可以了。最一劳永逸的办法是您再插入业务规则的时候把数据标题也赋值一下

自定义代码调用自动化

执行自动化

Engine.AutomationManager.ExecuteAutomation

请求参数

参数 类型 描述
schemaCode string 业务表单编码
automationCode string 自动化编码
bizObjectIds string[] 业务数据对象ID
customParameterValueMap Dictionary<string, object> 自定义参数值

响应格式:无

posted on 2025-05-23 14:50  天涯何  阅读(114)  评论(0)    收藏  举报