外观
后端代码示例
约 2750 字大约 9 分钟
2025-02-17
[通用]批量创建/更新/删除业务对象
可用位置:✔表单 / ✔列表 / ✔定时器 / ✔自定义接口
提示
下面这个示例只演示批量创建,若是批量更新改成bo.Update(commit);
,批量删除改成bo.Remove(commit);
。
H3.IEngine engine = this.Engine;
H3.DataModel.BizObjectSchema schema = engine.BizObjectManager.GetPublishedSchema("表单编码");//获取表单实例
H3.DataModel.BulkCommit commit = new H3.DataModel.BulkCommit();
for(int i = 0;i < 500; i++)
{
H3.DataModel.BizObject bo = new H3.DataModel.BizObject(engine, schema, H3.Organization.User.SystemUserId);
bo.CreatedBy = H3.Organization.User.SystemUserId;
bo.OwnerId = H3.Organization.User.SystemUserId;
bo.Status = H3.DataModel.BizObjectStatus.Effective;
bo["F000001"] = 1;
bo["F000002"] = "xxx";
//注意:这里不能直接用 bo.Create(),而是将批量提交实例传入
bo.Create(commit);
}
//注意:虽然是批量提交,但是建议一次Commit最多500条数据,否则还是很容易造成超时
string errorMsg = null;
commit.Commit(engine.BizObjectManager, out errorMsg);
if(!string.IsNullOrEmpty(errorMsg))
{
throw new Exception("批量操作失败:" + errorMsg);
}
[通用]正则
可用位置:✔表单 / ✔列表 / ✔定时器 / ✔自定义接口
string input = "1851 1999 1958 1905 2003";
string pattern = @"(?<=19)\d{2}\b";
// 遍历所有匹配到的结果,并对每个匹配项进行处理
foreach(System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(input, pattern))
{
string a = match.Value.ToString();
}
[通用]目标已有附件保留,追加新增的附件
可用位置:✔表单 / ✔列表 / ✔定时器 / ✔自定义接口
当目标表的附件控件是由多个源表复制过去的,此时只用 CopyFiles 接口的覆盖模式,会把其他源表附件覆盖。
换成 CopyFiles 接口的追加模式,本条源数据上次追加的附件又不会被清理,就无法显示更新的效果。
所以,本示例先将 本条源数据上次追加的附件 删除,后追加上 本条源数据 的所有附件,就完美解决了以上两个问题。
public void AddFileToBo(H3.IEngine engine, H3.DataModel.BizObject sourBo, string sourFieldCode, string toBoSchemaCode, string toBoId, string toFieldCode)
{
//第一步:删除 目标 中由本条数据带过去的附件
System.Data.DataTable dt = engine.Query.QueryTable(
"SELECT objectid FROM H_BizObjectFile WHERE fileflag = 0 AND schemacode = @toBoSchemaCode AND propertyname = @toFieldCode AND bizobjectid = @toBoId AND sourcebizobjectid = @sourBoId AND sourcepropertyname = @sourFieldCode", new H3.Data.Database.Parameter[]{
new H3.Data.Database.Parameter("@toBoSchemaCode", System.Data.DbType.String, toBoSchemaCode),
new H3.Data.Database.Parameter("@toFieldCode", System.Data.DbType.String, toFieldCode),
new H3.Data.Database.Parameter("@toBoId", System.Data.DbType.String, toBoId),
new H3.Data.Database.Parameter("@sourBoId", System.Data.DbType.String, sourBo.ObjectId),
new H3.Data.Database.Parameter("@sourFieldCode", System.Data.DbType.String, sourFieldCode)
});
if(dt != null && dt.Rows.Count > 0)
{
foreach(System.Data.DataRow row in dt.Rows)
{
string fId = row["objectid"] + string.Empty;
if(!string.IsNullOrWhiteSpace(fId))
{
engine.BizObjectManager.RemoveFile(fId, true);
}
}
}
//第二步:将本条数据的附件以追加的方式赋值到 目标
engine.BizObjectManager.CopyFiles(
sourBo.Schema.SchemaCode, "", sourFieldCode, sourBo.ObjectId,
toBoSchemaCode, "", toFieldCode, toBoId, false, false
);
}
[通用]CopyFiles图片到目标数据,图片在移动端列表中显示
可用位置:✔表单 / ✔列表 / ✔定时器 / ✔自定义接口
H3.DataModel.BizObject sourceBo = (省略);//源数据业务对象
H3.DataModel.BizObject toBo = (省略);//目标数据业务对象
//将源数据中某图片控件下的图片,复制到目标数据的某图片控件中,并得到复制后的图片信息数组
H3.DataModel.BizObjectFileHeader[] files = this.Engine.BizObjectManager.CopyFiles(sourceBo.Schema.SchemaCode, "", "源数据图片控件编码", sourceBo.ObjectId, toBo.Schema.SchemaCode, "", "目标数据图片控件编码", toBo.ObjectId, true, true);
//将控件中第一张图片设置为移动端列表上的数据图片
toBo.IconId = files[0].FileId;
//更新目标业务对象,提交以上设置
toBo.Update();
[通用]获取控件的H3.DataModel.PropertySchema实例
可用位置:✔表单 / ✔列表 / ✔定时器 / ✔自定义接口
H3.DataModel.PropertySchema
的具体说明请查看:H3.DataModel.PropertySchema
//总控实例
H3.IEngine engine = this.Engine;
//表单结构实例
H3.DataModel.BizObjectSchema schema = engine.BizObjectManager.GetPublishedSchema("表单编码");
//获取 F0000004 控件实例
H3.DataModel.PropertySchema property = schema.GetProperty("F0000004");
//获取 F0000004 控件的标题名
string fieldLabelName = property.DisplayName;
[表单]提交时汇总子表金额
可用位置:✔表单 / ✘列表 / ✘定时器 / ✘自定义接口
表单设计如下:
protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
//判断本次请求来源为 用户点击 提交/同意 按钮
if(actionName == "Submit")
{
//取出当前表单业务对象
H3.DataModel.BizObject thisBo = this.Request.BizObject;
//定义一个 总金额 变量
decimal sumAmount = 0m;
//取出 当前表单业务对象 里的 子表业务对象 集合
H3.DataModel.BizObject[] childTableBoArray = (H3.DataModel.BizObject[]) thisBo["D154601Fefba31462e2945208286b4b34b943bad"];
//判断子表有数据
if(childTableBoArray != null && childTableBoArray.Length > 0)
{
//循环子表每一行的业务对象
foreach(H3.DataModel.BizObject childTableBo in childTableBoArray)
{
decimal amount = 0m;
//取出子表行的金额字段值
string amount_Str = childTableBo["F0000016"] + string.Empty;
//判断该字段有填写金额
if(!string.IsNullOrWhiteSpace(amount_Str))
{
amount = decimal.Parse(amount_Str);
}
//将当前行的金额字段汇总到 总金额 变量
sumAmount = sumAmount + amount;
}
}
//将总金额赋值到主表字段(由于本次为提交操作,只需赋值,数据会在base.OnSubmit方法中自动保存到数据库,无需另外做Update操作)
thisBo["F0000017"] = sumAmount;
}
base.OnSubmit(actionName, postValue, response);
}
[表单]OnLoad事件中获取控件名和设置控件不可见不可写
可用位置:✔表单 / ✘列表 / ✘定时器 / ✘自定义接口
protected override void OnLoad(H3.SmartForm.LoadSmartFormResponse response)
{
//base.OnLoad 中将 this.Request.BizObject 转换处理为 response.ReturnData
base.OnLoad(response);
//对 response.ReturnData 进行处理前,先判断字段是否存在
if(response.ReturnData != null && response.ReturnData.ContainsKey("F0000004"))
{
//获取 F0000004 控件对应的响应数据实例
H3.SmartForm.SmartFormResponseDataItem item = response.ReturnData["F0000004"];
//获取 F0000004 控件的标题名
string fieldLabelName = item.DisplayName;
//设置 F0000004 控件的标题名
item.DisplayName = "这是F0000004控件";
//设置 F0000004 控件不可编辑
item.Editable = false;
//设置 F0000004 控件不可见
item.Visible = false;
}
}
[表单]提交时获取系统生成的流水号控件值
可用位置:✔表单 / ✘列表 / ✘定时器 / ✘自定义接口
protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
//由于 this.Request.BizObject 在经过 base.OnSubmit 方法后,Status 会发生改变,所以这里先暂存备用
H3.DataModel.BizObjectStatus beforeStatus = this.Request.BizObject.Status;
//base.OnSubmit 方法会将本次提交数据保存到数据库,并生成 流水号,所以在提交后立马获取流水号,需要写在 base.OnSubmit 方法之后
base.OnSubmit(actionName, postValue, response);
//由于表单头部按钮以及按钮控件都会进入OnSubmit事件,所以写在OnSubmit事件中的代码,都需要判断执行时机,以防误执行
//判断当前是否是 表单发起提交
if(
(actionName == "Submit" && this.Request.IsCreateMode) ||
(actionName == "Submit" && beforeStatus == H3.DataModel.BizObjectStatus.Draft) ||
(actionName == "Submit" && this.Request.ActivityCode == "Activity2")
)
{
//将当前业务对象数据重新加载一次,更新业务对象中的 SeqNo 字段值
this.Request.BizObject.Load();
//获取系统生成出的流水号控件值
string seqNo = this.Request.BizObject["SeqNo"] + string.Empty;
}
}
[表单]用户提交之后,不关闭表单页面
可用位置:✔表单 / ✘列表 / ✘定时器 / ✘自定义接口
注意
由于产品底层设计原因,表单页面头部上的按钮无法隐藏,用户可以继续点击,所以并不推荐使用本功能。
protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
base.OnSubmit(actionName, postValue, response);
// 判断用户点击的是 提交 按钮
if(actionName == "Submit")
{
response.Message = "提交成功!";// 弹出提示信息
response.ClosePage = false;// 不允许关闭表单
}
}
[表单]一张表单提交的手写签名给另一张表单手写签名赋值
可用位置:✔表单 / ✘列表 / ✘定时器 / ✘自定义接口
其他附件复制方法请参考此文档:附件图片复制
protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
//base.OnSubmit 方法会将本次提交数据保存到数据库,并生成 手写签名,所以在提交后立马获取手写签名,需要写在 base.OnSubmit 方法之后
base.OnSubmit(actionName, postValue, response);
if(actionName == "Submit")
{
//主表内手写签名控件 复制到 主表内手写签名控件 上
this.Request.Engine.BizObjectManager.CopyFiles("原-主表编码", "", "原-主表内手写签名控件编码", "原-主表数据ObjectId", "新-主表编码","", "新-主表内手写签名控件编码", "新-主表数据ObjectId", true, true);
}
}
[表单]提交时校验当天是否已提交
可用位置:✔表单 / ✘列表 / ✘定时器 / ✘自定义接口
protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue, H3.SmartForm.SubmitSmartFormResponse response)
{
try
{
//点提交按钮,有三种情况会发起流程,所以三种情况都需判断
//三种情况分别是:新增提交、先暂存后提交,流程回到发起节点重新提交
//一般在做销售出库冻结库存时,经常会在流程发起时冻结库存,所以会用到此示例
if(
(actionName == "Submit" && this.Request.IsCreateMode) ||
(actionName == "Submit" && this.Request.BizObject.Status == H3.DataModel.BizObjectStatus.Draft) ||
(actionName == "Submit" && this.Request.ActivityCode == "Activity2")
)
{
H3.IEngine engine = this.Engine;
H3.DataModel.BizObject thisBo = this.Request.BizObject;
DateTime todayTime = DateTime.Now;//获取今天日期
DateTime startTime = todayTime.Date;//获取今天 0点0分0秒
DateTime endTime = DateTime.Parse(todayTime.ToString("yyyy-MM-dd 23:59:59"));//获取今天 23点59分59秒
//通过SQL查询今天是否有提交数据
System.Data.DataTable dt = engine.Query.QueryTable("SELECT ObjectId, Name, Status, CreatedTime FROM i_当前表单编码 WHERE Status IN (1, 2) AND CreatedTime >= @startTime AND CreatedTime <= @endTime AND ObjectId != @thisId", new H3.Data.Database.Parameter[]{
new H3.Data.Database.Parameter("@startTime", System.Data.DbType.DateTime, startTime),
new H3.Data.Database.Parameter("@endTime", System.Data.DbType.DateTime, endTime),
new H3.Data.Database.Parameter("@thisId", System.Data.DbType.String, thisBo.ObjectId)//加上当前提交的数据Id,是为了避免先暂存后提交的情况导致也提示不允许提交
});
//若有查出数据,则代表今天已提交数据
if(dt != null && dt.Rows.Count > 0)
{
throw new Exception("今天已提交数据,请勿再次提交!");//抛出异常,此异常信息将被catch块捕获并响应给前端进行弹窗展示
}
}
} catch(Exception ex)
{
response.Errors.Add(ex.Message);//将异常信息响应到前端,弹窗提示
base.OnSubmit(actionName, postValue, response);//此句代码有系统的默认处理动作,所以有异常时也不可少
return;
}
base.OnSubmit(actionName, postValue, response);//此句代码有系统的默认处理动作,所以通过上面的校验时,也要执行此句代码
}
[列表]增加筛选条件
可用位置:✘表单 / ✔列表 / ✘定时器 / ✘自定义接口
注意
这里的代码是写在【列表设计】页面的后端代码中。
protected override void OnInit(H3.SmartForm.LoadListViewResponse response)
{
H3.SmartForm.ListViewRequest request = this.Request;
//判断当前模式为列表页面加载模式,且当前登录人不是管理员
if(request.ListScene == H3.SmartForm.ListScene.NormalList && !request.UserContext.IsAdministrator)
{
//判断当前模式为列表页面加载模式
string isFormControl = request["isFormControl"] == null ? "" : request["isFormControl"].ToString();
if(isFormControl != "1" && isFormControl != "true")
{
H3.IEngine engine = request.Engine;
H3.Data.Filter.And andMatcher = new H3.Data.Filter.And();
//如果列表没有过滤条件,则request.Filter为null,所以这里需要初始化
if(request.Filter == null)
{
request.Filter = new H3.Data.Filter.Filter();
}
//如果列表有其他过滤条件,则把已有过滤条件加入本次筛选对象
if(request.Filter.Matcher != null)
{
andMatcher = (H3.Data.Filter.And) request.Filter.Matcher;
}
//添加筛选条件,让用户只能查看草稿数据
andMatcher.Add(new H3.Data.Filter.ItemMatcher("Status", H3.Data.ComparisonOperatorType.Equal, H3.DataModel.BizObjectStatus.Draft));
//改变当前列表请求筛选条件
request.Filter.Matcher = andMatcher;
}
}
base.OnInit(response);
}
[列表]删除时获得用户选择的数据
可用位置:✘表单 / ✔列表 / ✘定时器 / ✘自定义接口
注意
这里的代码是写在【列表设计】页面的后端代码中。
protected override void OnSubmit(string actionName, H3.SmartForm.ListViewPostValue postValue, H3.SmartForm.SubmitListViewResponse response)
{
try
{
// 判断用户点击的是删除按钮
if(actionName == "Remove")
{
// 获取用户选择数据的 ObjectId 数组
string[] selectedIds = (string[]) postValue.Data["ObjectIds"];
if(selectedIds != null && selectedIds.Length > 0)
{
int maxCount = 100;
if(selectedIds.Length > maxCount)
{
throw new Exception("单次最多处理" + maxCount + "条数据!");
}
H3.IEngine engine = this.Engine;
H3.DataModel.BizObjectSchema schema = this.Request.Schema;
H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter();
H3.Data.Filter.And andMatcher = new H3.Data.Filter.And();
andMatcher.Add(new H3.Data.Filter.ItemMatcher("ObjectId", H3.Data.ComparisonOperatorType.In, selectedIds));
filter.Matcher = andMatcher;
filter.FromRowNum = 0;
filter.ToRowNum = 1000;
H3.DataModel.BizObject[] boArray = H3.DataModel.BizObject.GetList(engine, H3.Organization.User.SystemUserId,
schema, H3.DataModel.GetListScopeType.GlobalAll, filter);
if(boArray != null && boArray.Length > 0)
{
if(boArray.Length != selectedIds.Length)
{
throw new Exception(schema.DisplayName + "数据查询失败!");
}
foreach(H3.DataModel.BizObject bo in boArray)
{
//对选中数据循环处理
}
}
}
}
} catch(Exception ex)
{
response.Errors.Add(ex.Message);
base.OnSubmit(actionName, postValue, response);
return;
}
base.OnSubmit(actionName, postValue, response);
}