h3factory 0.0.0-stage → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +241 -2
- package/bin/h3factory.js +87 -0
- package/cli.py +951 -0
- package/config.example.json +8 -0
- package/docs/platform_gotchas.md +118 -0
- package/docs/requirement_checklist.md +54 -0
- package/docs/schema_doc.md +216 -0
- package/docs/workflow.md +146 -0
- package/h3design/__init__.py +0 -0
- package/h3design/controls.py +414 -0
- package/h3design/dsl.py +553 -0
- package/h3design/newbuilder.py +852 -0
- package/h3platform/__init__.py +0 -0
- package/h3platform/api.py +214 -0
- package/h3platform/h3console.py +99 -0
- package/h3platform/settings.py +74 -0
- package/h3verify/__init__.py +0 -0
- package/h3verify/verify.py +217 -0
- package/package.json +51 -4
- package/projects/demo/dicts.json +10 -0
- package/projects/demo/generated/product.cs +82 -0
- package/projects/demo/groups.json +3 -0
- package/projects/demo/sheets/product.json +24 -0
- package/scripts/postinstall.js +109 -0
- package/skills/h3factory/SKILL.md +137 -0
- package/skills/h3yun-dev-assistant/BACKEND_GUIDELINES.md +120 -0
- package/skills/h3yun-dev-assistant/DEV_DOC_ROUTING.md +39 -0
- package/skills/h3yun-dev-assistant/FORM_ACTIONS_GUIDELINES.md +116 -0
- package/skills/h3yun-dev-assistant/FRONTEND_GUIDELINES.md +47 -0
- package/skills/h3yun-dev-assistant/OPENAPI_GUIDELINES.md +8 -0
- package/skills/h3yun-dev-assistant/PLATFORM_CONSTRAINTS.md +160 -0
- package/skills/h3yun-dev-assistant/POST_GUIDELINES.md +47 -0
- package/skills/h3yun-dev-assistant/PRACTICE_NOTES.md +626 -0
- package/skills/h3yun-dev-assistant/SKILL.md +70 -0
- package/skills/h3yun-dev-assistant/SQL_GUIDELINES.md +9 -0
- package/skills/h3yun-dev-assistant/TOOL_FUNCTIONS.md +96 -0
- package/templates/controller.cs.tpl +78 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: h3yun-dev-assistant
|
|
3
|
+
description: 氚云、H3Yun、H3、SmartForm、BizObject、OnLoad、OnSubmit、表单或列表前端、控件编码、PostForm、ListView.Post、SQL、高级数据源、OpenAPI、氚云二开报错时使用。生成或排查氚云 C# 后端、ES5 前端和 SQL 代码。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 氚云二次开发助手
|
|
7
|
+
|
|
8
|
+
你是氚云/H3Yun 二次开发助手,生成可直接用于平台的 C# 后端、ES5 前端、SQL 和排错建议。
|
|
9
|
+
|
|
10
|
+
## 工作方式
|
|
11
|
+
|
|
12
|
+
1. 先判断任务类型,只读取下方对应的规则文件;不要为了简单问题加载全部规则。
|
|
13
|
+
2. 读取 `DEV_DOC_ROUTING.md`,根据当前需求决定是否需要读取对应氚专开发文档;不要只凭记忆猜测平台 API 或控件类型。
|
|
14
|
+
3. **先评估,后实现。** 在用户确认前不得生成、修改或应用业务代码,也不得以“先给草稿”为由绕过确认。先输出需求评估,至少包括:目标与范围、拟修改位置、涉及的表单/字段/按钮/事件、需要加载的规则和文档、实现方案、潜在风险、缺失信息和待用户确认事项。
|
|
15
|
+
4. 对评估中的不确定项、平台差异、接口签名、参数含义、数据权限、异常处理和兼容性问题,逐项编号列出,不得自行假设。能通过现有代码、规则文件或官方文档确认的内容先自行确认,只有仍无法确认的内容才交给用户决定。
|
|
16
|
+
5. 评估完成后,使用交互式提问让用户逐项确认待定事项;优先提供明确选项(例如“采用方案 A / 采用方案 B / 暂不实现”),同时允许用户补充自定义答案。用户未明确确认全部阻塞项前,保持评估状态,不开始写代码;用户确认后如需求范围发生变化,重新评估受影响部分。
|
|
17
|
+
6. 用户提供的代码仅用于确认既有业务行为、编码和平台兼容性,不作为新增代码的风格模板。新增需求默认仅修改必要接入位置,不得顺带重命名、格式化、提取方法、去重或修复无关问题;发现无关缺陷仅说明,除非阻塞当前需求。
|
|
18
|
+
7. 缺少关键表单编码、控件编码、按钮编码、触发事件或预期行为时,只询问最少必要信息;不得臆造编码。
|
|
19
|
+
8. 用户完成确认后,给出完整、可粘贴的代码。新增封装方法须有简短中文注释;使用表单或字段编码处,须标注其业务含义。
|
|
20
|
+
9. C# 按 .NET Framework 4.6.2 编写,前端严格使用 ES5。
|
|
21
|
+
10. 每次生成或修改氚云代码后,必须执行“生成后自检”,未完成自检不得交付代码。
|
|
22
|
+
11. 生成代码前检查 `TOOL_FUNCTIONS.md`;存在适用工具方法时优先复用,复制方法实现及其必要依赖后再调用,不得重复造轮子。该文件中的方法不是氚云内置方法,必须按文档说明复制到对应代码块。
|
|
23
|
+
|
|
24
|
+
## 生成后自检
|
|
25
|
+
|
|
26
|
+
生成或修改代码后,逐项检查本次新增或修改的代码:
|
|
27
|
+
|
|
28
|
+
- 凡本次按“按需加载”读取且实际涉及的规范文件,必须逐项复核其中适用于本次变更的全部规则和硬性限制;不得只检查编码注释或只检查部分规则。
|
|
29
|
+
- 每个表单编码都在相邻注释中标注表单名称。
|
|
30
|
+
- 每个字段、子表或按钮编码都在相邻注释中标注“表单名称-字段名称”。
|
|
31
|
+
- 每条新增或修改的 SQL 查询语句前,均有注释说明涉及的表单、表名及字段编码和业务含义。
|
|
32
|
+
- 每个 SQL 外部输入条件均使用参数化查询;不存在 SQL 拼接输入值。
|
|
33
|
+
- 新增 C# 代码符合 .NET Framework 4.6.2,新增前端代码符合 ES5。
|
|
34
|
+
- 新增或修改的自定义类只定义带默认值的字段(对象类型字段可默认为 null),不存在 `{ get; set; }` 自动属性。
|
|
35
|
+
- 新增 `PostForm`、`ListView.Post` 或自定义 Post 的请求名称、前后端 `actionName` 判断和响应结构完全一致。
|
|
36
|
+
- 逐一识别本次使用的所有氚云特有方法、函数、对象、事件、接口和平台属性;对每一处调用分别核对官方文档或已加载规范中的方法签名、参数顺序、参数数量、参数类型、必填性、允许值、返回结构、调用上下文和版本适用性,不得只确认“方法名存在”。
|
|
37
|
+
- 对每个氚云专有调用记录核对结果;若参数无法从规则、官方文档或现有可靠示例确认,必须停止交付并向用户说明不确定点,不得凭经验补全参数。
|
|
38
|
+
- 若复用了 `TOOL_FUNCTIONS.md` 中的方法,检查方法实现、必要依赖是否完整复制,调用参数是否符合该方法的约定,并确认没有与现有代码同名或重复定义。
|
|
39
|
+
- 自检发现任一项不符合时,必须先修正代码并重新执行完整自检,再进行交付说明。
|
|
40
|
+
|
|
41
|
+
## 按需加载
|
|
42
|
+
|
|
43
|
+
- 生成或修改任意后端 C# 代码,包括表单后端、列表后端、`BizObject`、`OnLoad`、`OnSubmit`、流程、组织、消息、自定义接口、WebAPI/WebService、业务校验:读取 `BACKEND_GUIDELINES.md`。
|
|
44
|
+
- 后端读取或设置 `BizObject` 的主表或子表控件值时:查阅 `BACKEND_GUIDELINES.md` 指定的“业务对象控件取值与赋值”开发文档,不得猜测类型。
|
|
45
|
+
- 表单前端、列表前端、按钮校验、控件操作:读取 `FRONTEND_GUIDELINES.md`。
|
|
46
|
+
- 表单 `$.SmartForm.PostForm`、列表 `$.ListView.Post`、自定义 Post、前后端交互、按钮请求后端、`功能名_Post`、`ReturnData`:必须读取 `POST_GUIDELINES.md`;若同时生成后端或前端,也读取对应规则文件。
|
|
47
|
+
- SQL、高级数据源、后端查询:读取 `SQL_GUIDELINES.md`。后端 SQL 查询还必须读取 `BACKEND_GUIDELINES.md`。不确定表单或字段编码时,优先通过氚云 SQL 排查工具读取 `cmax.json` 和 `fields.md`。
|
|
48
|
+
- 异步、后台执行、线程、并发、`Task`、队列、定时器、计划或周期任务、批量、长耗时、导入、大数据量、性能优化、文件、附件、缓存、本地 I/O、自定义接口、OpenAPI、超时、频率、乐观锁、重复执行、失败重试或幂等:必须读取 `PLATFORM_CONSTRAINTS.md`。
|
|
49
|
+
- 外部系统调用氚云 OpenAPI:读取 `OPENAPI_GUIDELINES.md`;接口签名或请求结构不确定时,再查该文件指定的开发文档。
|
|
50
|
+
- 消息、流程、组织、第三方 WebAPI/WebService 等具体平台 API:确认参数或版本差异时查开发文档,不得猜测签名。
|
|
51
|
+
- 需要通用字段转换、数值处理、日期格式化、计算公式触发或子表汇总时:读取 `TOOL_FUNCTIONS.md`,优先复用其中的方法。
|
|
52
|
+
- 需要控件取值类型、完整工具代码、系统表、流程/消息代码骨架、OpenAPI 附件实测、已知坑等历史实测经验时:读取 `PRACTICE_NOTES.md`(本地积累,与规则文件冲突时以规则文件为准)。
|
|
53
|
+
|
|
54
|
+
## 通用底线
|
|
55
|
+
|
|
56
|
+
- 不使用反射、`Task`、线程、普通 .NET 定时器或本地文件 I/O。
|
|
57
|
+
- 不使用 DDL,不用 SQL 直接增删改业务数据,不自行建立数据库连接。
|
|
58
|
+
- 不直接操作 DOM;不使用 ES6+ 语法。
|
|
59
|
+
- 出现平台能力、接口参数或版本差异不确定时,先查文档或明确说明不确定点。
|
|
60
|
+
|
|
61
|
+
## 常用文档
|
|
62
|
+
|
|
63
|
+
- 总索引:https://h3yunpro.github.io/llms.txt
|
|
64
|
+
- 表单事件:https://h3yunpro.github.io/docs/form-events/
|
|
65
|
+
- 列表事件:https://h3yunpro.github.io/docs/list-events/
|
|
66
|
+
- 前后端交互:https://h3yunpro.github.io/docs/interactive-example/
|
|
67
|
+
- 表单 PostForm 示例:https://h3yunpro.github.io/docs/pure-example/#%E8%A1%A8%E5%8D%95-postform
|
|
68
|
+
- 列表 Post 示例:https://h3yunpro.github.io/docs/pure-example/#%E5%88%97%E8%A1%A8-post
|
|
69
|
+
- OpenAPI 索引:https://h3yun-pro-doc-openapi.apifox.cn/llms.txt
|
|
70
|
+
- 工具方法合集(本地复用库):`TOOL_FUNCTIONS.md`;原始文档:https://h3yunpro.github.io/docs/tool-function/
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# SQL 规则
|
|
2
|
+
|
|
3
|
+
- SQL 仅用于查询、报表和高级数据源;禁止用 SQL 直接增删改业务数据或执行 DDL。
|
|
4
|
+
- 所有用户输入条件使用参数化查询。参数使用三参构造:`new H3.Data.Database.Parameter("@参数名", System.Data.DbType.实际类型, value)`;`DbType` 必须与值类型匹配,例如字符串用 `String`、整数用 `Int32`/`Int64`、小数用 `Decimal`、日期用 `DateTime`、布尔值用 `Boolean`。
|
|
5
|
+
- 后端使用 `engine.Query.QueryTable(sql, parameters.ToArray())`;参数集合为空时可传 `null`。
|
|
6
|
+
- 后端执行 SQL 查询时,SQL 语句必须压缩为单行字符串,不使用包含换行的多行字符串,避免因换行导致平台编译器报错。
|
|
7
|
+
- 空值使用 `IS NULL` 或 `IS NOT NULL`,不使用 `= NULL`。
|
|
8
|
+
- 不确定表单编码、控件编码、表名或字段名时,先通过 SQL 排查工具读取项目中的 `cmax.json` 与相关 `fields.md`。
|
|
9
|
+
- 业务主表为 `i_表单编码`,子表为 `i_子表控件编码`,关联表单多选中间表为 `i_表单编码_关联表单多选控件编码` 或 `i_子表控件编码_关联表单多选控件编码`。
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# 氚云常用工具方法库
|
|
2
|
+
|
|
3
|
+
来源:氚专开发者扩展文档《工具方法合集》:https://h3yunpro.github.io/docs/tool-function/
|
|
4
|
+
|
|
5
|
+
## 使用规则
|
|
6
|
+
|
|
7
|
+
- 本文件中的方法不是氚云内置方法,使用前必须将对应方法代码复制到当前氚云类代码块中。
|
|
8
|
+
- 生成代码前先判断是否已有工具方法可以直接复用;能复用时不得重复编写等价方法。
|
|
9
|
+
- 只复制本次实际需要的方法及其依赖,避免无关代码膨胀。
|
|
10
|
+
- 使用前必须确认当前代码位置、C# 版本、方法可见性、依赖命名空间和参数含义。
|
|
11
|
+
- 这些方法均来自外部工具合集,不得把它们当作平台 API;调用时仍需按“生成后自检”逐项核对参数。
|
|
12
|
+
|
|
13
|
+
## 后端字段与数值处理
|
|
14
|
+
|
|
15
|
+
适用位置:表单、列表、定时器、自定义接口。
|
|
16
|
+
|
|
17
|
+
```cs
|
|
18
|
+
public static string gStr(object val) { return val + string.Empty; }
|
|
19
|
+
public static bool gBool(object val) { string valStr = (val + string.Empty).ToLower(); return valStr == "true" || valStr == "1"; }
|
|
20
|
+
public static decimal gDecimalNum(object val) { return gNum(val, 0m); }
|
|
21
|
+
public static double gDoubleNum(object val) { return gNum(val, 0.0); }
|
|
22
|
+
public static int gIntNum(object val) { return gNum(val, 0); }
|
|
23
|
+
public static decimal gDecimalSum(object objArray, string field) { return gSum(objArray, field, 0m); }
|
|
24
|
+
public static double gDoubleSum(object objArray, string field) { return gSum(objArray, field, 0.0); }
|
|
25
|
+
public static int gIntSum(object objArray, string field) { return gSum(objArray, field, 0); }
|
|
26
|
+
public static decimal gNum(object val, decimal defVal) { string s = val + string.Empty; s = string.IsNullOrWhiteSpace(s) ? "0" : s; decimal n = defVal; return decimal.TryParse(s, out n) ? n : defVal; }
|
|
27
|
+
public static double gNum(object val, double defVal) { string s = val + string.Empty; s = string.IsNullOrWhiteSpace(s) ? "0" : s; double n = defVal; return double.TryParse(s, out n) ? n : defVal; }
|
|
28
|
+
public static int gNum(object val, int defVal) { string s = val + string.Empty; s = string.IsNullOrWhiteSpace(s) ? "0" : s; int n = defVal; return int.TryParse(s, out n) ? n : defVal; }
|
|
29
|
+
public static bool tTime(object val, out DateTime time) { return DateTime.TryParse(val + string.Empty, out time); }
|
|
30
|
+
public static DateTime gTime(object val, DateTime defaultTime) { string s = val + string.Empty; if(string.IsNullOrWhiteSpace(s)) return defaultTime; DateTime t = defaultTime; return DateTime.TryParse(s, out t) ? t : defaultTime; }
|
|
31
|
+
public static string g200Str(string str) { return !string.IsNullOrWhiteSpace(str) && str.Length > 200 ? str.Substring(0, 200) : str; }
|
|
32
|
+
public static string g2000Str(string str) { return !string.IsNullOrWhiteSpace(str) && str.Length > 2000 ? str.Substring(0, 2000) : str; }
|
|
33
|
+
public static decimal gRound(decimal num, int digits) { return System.Math.Round(num, digits, System.MidpointRounding.AwayFromZero); }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 子表汇总依赖
|
|
37
|
+
|
|
38
|
+
`gDecimalSum`、`gDoubleSum`、`gIntSum` 依赖以下重载。`objArray` 必须是 `H3.DataModel.BizObject[]`,`field` 必须是子表内控件编码。
|
|
39
|
+
|
|
40
|
+
```cs
|
|
41
|
+
public static decimal gSum(object objArray, string field, decimal defVal) {
|
|
42
|
+
if(objArray == null || string.IsNullOrWhiteSpace(field)) return defVal;
|
|
43
|
+
H3.DataModel.BizObject[] list = (H3.DataModel.BizObject[])objArray;
|
|
44
|
+
if(list == null || list.Length == 0) return defVal;
|
|
45
|
+
decimal sum = defVal;
|
|
46
|
+
foreach(H3.DataModel.BizObject bo in list) sum += gNum(bo[field], defVal);
|
|
47
|
+
return sum;
|
|
48
|
+
}
|
|
49
|
+
public static double gSum(object objArray, string field, double defVal) { return Convert.ToDouble(gSum(objArray, field, 0m)); }
|
|
50
|
+
public static int gSum(object objArray, string field, int defVal) { return Convert.ToInt32(gSum(objArray, field, 0m)); }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 后端计算公式
|
|
54
|
+
|
|
55
|
+
仅在需要触发已有控件计算公式时复用。主表传主表业务对象,子表传当前子表业务对象;子表控件参数只能传子表内控件编码,不能传“子表编码.控件编码”。
|
|
56
|
+
|
|
57
|
+
```cs
|
|
58
|
+
public static void CalcPropertyComputationRule(H3.DataModel.BizObject bo, string propertyCode)
|
|
59
|
+
{
|
|
60
|
+
if(bo == null || !bo.Schema.PropertyExist(propertyCode)) return;
|
|
61
|
+
H3.DataModel.PropertySchema schema = bo.Schema.GetProperty(propertyCode);
|
|
62
|
+
if(string.IsNullOrWhiteSpace(schema.ComputationRule)) return;
|
|
63
|
+
string rule = schema.ComputationRule.Replace(bo.Schema.SchemaCode + ".", "");
|
|
64
|
+
bo[propertyCode] = bo.CalcExpression(rule);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 前端值与日期处理
|
|
69
|
+
|
|
70
|
+
以下代码为 ES5,可放在表单默认代码之前;日期控件赋值只能使用 `yyyy-MM-dd` 或 `yyyy-MM-dd HH:mm:ss` 格式。
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
function convertToNumber(v) {
|
|
74
|
+
if(typeof v === "string" && v.length) { try { return parseFloat(v); } catch(e) { return 0; } }
|
|
75
|
+
if(typeof v === "number") return v;
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
function convertToString(v) {
|
|
79
|
+
if(typeof v === "string") return v;
|
|
80
|
+
if(typeof v === "number") return v + "";
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
function MyDateFormat(d, fmt) {
|
|
84
|
+
var o = { "M+": d.getMonth() + 1, "d+": d.getDate(), "H+": d.getHours(), "m+": d.getMinutes(), "s+": d.getSeconds(), "q+": Math.floor((d.getMonth() + 3) / 3), "S": d.getMilliseconds() };
|
|
85
|
+
if(/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (d.getFullYear() + "").substr(4 - RegExp.$1.length));
|
|
86
|
+
for(var k in o) if(new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
|
|
87
|
+
return fmt;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 复用检查清单
|
|
92
|
+
|
|
93
|
+
- 是否存在可直接复用的工具方法及其依赖。
|
|
94
|
+
- 是否只复制必要方法,避免重复定义同名方法。
|
|
95
|
+
- 每个方法的参数、返回值、适用位置和平台上下文是否已确认。
|
|
96
|
+
- 工具方法内部使用的氚云类型或平台成员是否逐项完成签名与参数自检。
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// =====================================================================
|
|
2
|
+
// ${TITLE} —— ${SHEET_KEY} 提交时 OnSubmit 服务端代码(h3factory cli gen 骨架)
|
|
3
|
+
// 【粘贴位置】表单设计器 → 业务规则/后端事件 → 提交时
|
|
4
|
+
// 【类名】必须等于当前表单 SchemaCode(本文件已填:${SCHEMA_CODE})
|
|
5
|
+
//
|
|
6
|
+
// 通用模式参考(奥驰样例已编译通过的实现,可直接照抄结构):
|
|
7
|
+
// 料号生成_料号申请表.cs —— 5-key 计数 upsert(NextCounter)、跨表查重、
|
|
8
|
+
// 表单存名称→字典查代码、规格描述按模板单遍替换
|
|
9
|
+
// D:\AI\自动编号\料号生成_料号申请表.cs
|
|
10
|
+
// =====================================================================
|
|
11
|
+
using System;
|
|
12
|
+
using System.Collections.Generic;
|
|
13
|
+
using System.Data;
|
|
14
|
+
using System.Text;
|
|
15
|
+
using System.Text.RegularExpressions;
|
|
16
|
+
using H3;
|
|
17
|
+
|
|
18
|
+
public class ${SCHEMA_CODE} : H3.SmartForm.SmartFormController
|
|
19
|
+
{
|
|
20
|
+
// ---------------- SchemaCode(与本工程 projects registry.json 一致) ----------------
|
|
21
|
+
private const string SELF_SCHEMA = "${SCHEMA_CODE}"; // ${TITLE}(本表)
|
|
22
|
+
${SCHEMA_CONSTS}
|
|
23
|
+
${FIELD_CONSTS}
|
|
24
|
+
// ================= 工具 =================
|
|
25
|
+
private static string SqlStr(string v) { return (v + string.Empty).Replace("'", "''"); }
|
|
26
|
+
private static string S(object v) { return (v + string.Empty).Trim(); } // BizObject 字段值为 object
|
|
27
|
+
private bool Flag(object v)
|
|
28
|
+
{
|
|
29
|
+
if (v == null) return false;
|
|
30
|
+
string s = (v + string.Empty).ToLower();
|
|
31
|
+
return s == "true" || s == "1" || s == "是";
|
|
32
|
+
}
|
|
33
|
+
private long AsLong(object v)
|
|
34
|
+
{
|
|
35
|
+
long n;
|
|
36
|
+
if (v == null || !long.TryParse(v + string.Empty, out n)) return 0;
|
|
37
|
+
return n;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public ${SCHEMA_CODE}(H3.SmartForm.SmartFormRequest request) : base(request) { }
|
|
41
|
+
|
|
42
|
+
protected override void OnLoad(H3.SmartForm.LoadSmartFormResponse response)
|
|
43
|
+
{
|
|
44
|
+
base.OnLoad(response);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ================= 提交时入口 =================
|
|
48
|
+
protected override void OnSubmit(string actionName, H3.SmartForm.SmartFormPostValue postValue,
|
|
49
|
+
H3.SmartForm.SubmitSmartFormResponse response)
|
|
50
|
+
{
|
|
51
|
+
try
|
|
52
|
+
{
|
|
53
|
+
H3.DataModel.BizObject form = this.Request.BizObject;
|
|
54
|
+
|
|
55
|
+
// 仅"草稿 → 首次提交"触发生成;编辑重提/流转保存直接跳过。
|
|
56
|
+
bool firstSubmit = actionName == "Submit" &&
|
|
57
|
+
this.Request.BizObject.Status == H3.DataModel.BizObjectStatus.Draft;
|
|
58
|
+
if (!firstSubmit) return;
|
|
59
|
+
|
|
60
|
+
// ============================================================
|
|
61
|
+
// TODO 业务规则写在这里:
|
|
62
|
+
// 1. 读本表单字段 string v = S(form[F_XXX]);
|
|
63
|
+
// 2. 读关联表记录 BizObject rule = BizObject.Load(this.Request.UserContext.UserId,
|
|
64
|
+
// this.Engine, REF_SCHEMA, refId, false);
|
|
65
|
+
// 3. 计数/查重等跨表逻辑参考 料号生成_料号申请表.cs
|
|
66
|
+
// (Engine.Query.QueryTable / COALESCE / BizObject.Create+Update)
|
|
67
|
+
// 4. 错误拦截 response.Errors.Add("提示信息"); return;
|
|
68
|
+
// 5. 生成字段写回 form[F_XXX] = "结果"; (本表字段直接改 form 即保存)
|
|
69
|
+
// 6. 子表行集合 BizObject[] rows = form[GRID_XXX] as BizObject[]; // 数组!
|
|
70
|
+
// 遍历读列值 row["列key"];子表行字段写回 row["列key"] = v;
|
|
71
|
+
// ============================================================
|
|
72
|
+
}
|
|
73
|
+
catch (Exception ex)
|
|
74
|
+
{
|
|
75
|
+
response.Errors.Add("生成失败: " + ex.Message);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|