kcode-pi 0.1.0

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.
Files changed (219) hide show
  1. package/README.md +358 -0
  2. package/dist/cli/kcode.d.ts +15 -0
  3. package/dist/cli/kcode.js +153 -0
  4. package/dist/cli/main.d.ts +2 -0
  5. package/dist/cli/main.js +7 -0
  6. package/docs/KCODE_DISTRIBUTION.md +91 -0
  7. package/extensions/kingdee-harness.ts +180 -0
  8. package/extensions/kingdee-header.ts +122 -0
  9. package/extensions/kingdee-tools.ts +379 -0
  10. package/knowledge/.backup/v1.0.0/version.json +10 -0
  11. package/knowledge/cangqiong/product-notes.md +15 -0
  12. package/knowledge/common/business-flows.md +115 -0
  13. package/knowledge/common/config-guides.md +110 -0
  14. package/knowledge/common/error-patterns.md +170 -0
  15. package/knowledge/common/implementation.md +144 -0
  16. package/knowledge/cosmic/hard-constraints.md +38 -0
  17. package/knowledge/cosmic/ksql-datafix.md +34 -0
  18. package/knowledge/cosmic/platform-baseline.md +32 -0
  19. package/knowledge/cosmic/plugin-decision-matrix.md +40 -0
  20. package/knowledge/cosmic/review-checklist.md +40 -0
  21. package/knowledge/cosmic/unittest.md +35 -0
  22. package/knowledge/enterprise/api-reference.md +186 -0
  23. package/knowledge/enterprise/code-patterns.md +217 -0
  24. package/knowledge/enterprise/plugin-lifecycle.md +188 -0
  25. package/knowledge/enterprise/tables.json +159 -0
  26. package/knowledge/flagship/api-reference.md +237 -0
  27. package/knowledge/flagship/code-patterns.md +246 -0
  28. package/knowledge/flagship/cosmic-platform-note.md +15 -0
  29. package/knowledge/flagship/plugin-lifecycle.md +248 -0
  30. package/knowledge/flagship/tables.json +159 -0
  31. package/knowledge/version.json +10 -0
  32. package/knowledge/xinghan/product-notes.md +15 -0
  33. package/package.json +71 -0
  34. package/prompts/kd-discuss.md +11 -0
  35. package/prompts/kd-execute.md +12 -0
  36. package/prompts/kd-plan.md +12 -0
  37. package/prompts/kd-ship.md +12 -0
  38. package/prompts/kd-spec.md +12 -0
  39. package/prompts/kd-verify.md +12 -0
  40. package/skills/kd-check/SKILL.md +26 -0
  41. package/skills/kd-cosmic-dev/SKILL.md +82 -0
  42. package/skills/kd-cosmic-review/SKILL.md +90 -0
  43. package/skills/kd-cosmic-unittest/SKILL.md +92 -0
  44. package/skills/kd-debug/SKILL.md +30 -0
  45. package/skills/kd-discuss/SKILL.md +24 -0
  46. package/skills/kd-execute/SKILL.md +22 -0
  47. package/skills/kd-gen/SKILL.md +34 -0
  48. package/skills/kd-ksql/SKILL.md +86 -0
  49. package/skills/kd-plan/SKILL.md +24 -0
  50. package/skills/kd-ship/SKILL.md +22 -0
  51. package/skills/kd-spec/SKILL.md +24 -0
  52. package/skills/kd-verify/SKILL.md +22 -0
  53. package/themes/kcode-dark.json +81 -0
  54. package/vendor/kingdee-skills/cosmic-unittest/SKILL.md +788 -0
  55. package/vendor/kingdee-skills/cosmic-unittest/author-cache.json +5 -0
  56. package/vendor/kingdee-skills/cosmic-unittest/cosmic-unittest-skill-overview.html +746 -0
  57. package/vendor/kingdee-skills/cosmic-unittest/examples/business-test.md +205 -0
  58. package/vendor/kingdee-skills/cosmic-unittest/examples/common-test.md +257 -0
  59. package/vendor/kingdee-skills/cosmic-unittest/examples/formplugin-test.md +560 -0
  60. package/vendor/kingdee-skills/cosmic-unittest/examples/op-plugin-test.md +231 -0
  61. package/vendor/kingdee-skills/cosmic-unittest/examples/validator-test.md +232 -0
  62. package/vendor/kingdee-skills/cosmic-unittest/patterns/business-helper.md +184 -0
  63. package/vendor/kingdee-skills/cosmic-unittest/patterns/common-module.md +355 -0
  64. package/vendor/kingdee-skills/cosmic-unittest/patterns/convert-plugin.md +130 -0
  65. package/vendor/kingdee-skills/cosmic-unittest/patterns/formplugin.md +235 -0
  66. package/vendor/kingdee-skills/cosmic-unittest/patterns/op-plugin.md +226 -0
  67. package/vendor/kingdee-skills/cosmic-unittest/patterns/validator.md +206 -0
  68. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/SKILL.md +674 -0
  69. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/advanced-scenario-checklist.md +307 -0
  70. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/algox-performance-checklist.md +129 -0
  71. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/coding-standard-checklist.md +491 -0
  72. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/cosmic-api-checklist.md +285 -0
  73. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/data-access-checklist.md +261 -0
  74. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/data-transaction-checklist.md +390 -0
  75. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/domain-logic-checklist.md +295 -0
  76. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/form-plugin-checklist.md +508 -0
  77. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/infra-checklist.md +254 -0
  78. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/ksql-checklist.md +305 -0
  79. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/lifecycle-checklist.md +298 -0
  80. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/operation-plugin-checklist.md +442 -0
  81. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/test-mock-checklist.md +120 -0
  82. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/ui-performance-checklist.md +320 -0
  83. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/pattern-matcher.py +336 -0
  84. package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/review-score-calculator.py +121 -0
  85. package/vendor/kingdee-skills/ok-cosmic/CHANGELOG.md +295 -0
  86. package/vendor/kingdee-skills/ok-cosmic/README.md +460 -0
  87. package/vendor/kingdee-skills/ok-cosmic/SKILL.md +287 -0
  88. package/vendor/kingdee-skills/ok-cosmic/agents/openai.yaml +17 -0
  89. package/vendor/kingdee-skills/ok-cosmic/assets/BatchImportPluginTemplate.java +93 -0
  90. package/vendor/kingdee-skills/ok-cosmic/assets/BillPlugInTemplate.java +156 -0
  91. package/vendor/kingdee-skills/ok-cosmic/assets/ConvertPlugInTemplate.java +255 -0
  92. package/vendor/kingdee-skills/ok-cosmic/assets/FormPluginTemplate.java +597 -0
  93. package/vendor/kingdee-skills/ok-cosmic/assets/IWorkflowPluginTemplate.java +91 -0
  94. package/vendor/kingdee-skills/ok-cosmic/assets/ListPluginTemplate.java +194 -0
  95. package/vendor/kingdee-skills/ok-cosmic/assets/OpPluginTemplate.java +201 -0
  96. package/vendor/kingdee-skills/ok-cosmic/assets/OpenApiControllerTemplate.java +103 -0
  97. package/vendor/kingdee-skills/ok-cosmic/assets/PrintPluginTemplate.java +95 -0
  98. package/vendor/kingdee-skills/ok-cosmic/assets/ReportFormPluginTemplate.java +257 -0
  99. package/vendor/kingdee-skills/ok-cosmic/assets/ReportListDataPluginTemplate.java +70 -0
  100. package/vendor/kingdee-skills/ok-cosmic/assets/StandardTreeListPluginTemplate.java +130 -0
  101. package/vendor/kingdee-skills/ok-cosmic/assets/TaskTemplate.java +80 -0
  102. package/vendor/kingdee-skills/ok-cosmic/assets/TreeListPluginTemplate.java +152 -0
  103. package/vendor/kingdee-skills/ok-cosmic/assets/WriteBackPlugInTemplate.java +286 -0
  104. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/attachment/AttachmentUploadBindSample.java +93 -0
  105. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/botp/BotpTracePushSample.java +168 -0
  106. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/botp/SampleConvertPlugin.java +223 -0
  107. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/cache/SampleCacheUsage.java +218 -0
  108. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/concurrent/SampleThreadPoolBatch.java +156 -0
  109. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/data/DynamicObjectCrudSample.java +205 -0
  110. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/data/DynamicObjectOpsSample.java +100 -0
  111. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/BeforeOperationConfirmSample.java +217 -0
  112. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ConfirmDialogSample.java +131 -0
  113. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/EntryRowCalculateSample.java +116 -0
  114. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/F7FilterSample.java +134 -0
  115. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/GetAndSetValueSample.java +176 -0
  116. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/HyperlinkJumpSample.java +124 -0
  117. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/OpenBillModalSample.java +253 -0
  118. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ReturnParentDataSample.java +295 -0
  119. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/TreeControlSample.java +140 -0
  120. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ViewControlOpsSample.java +132 -0
  121. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/list/ListPluginBasicSample.java +170 -0
  122. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/list/ListPreOpenFilterSample.java +68 -0
  123. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/message/MessageNotifySample.java +95 -0
  124. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/mq/SampleMQConsumer.java +198 -0
  125. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/mq/sample_mq.xml +15 -0
  126. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/operation/OpAddValidatorsSample.java +137 -0
  127. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/operation/OperationOptionBridgeSample.java +228 -0
  128. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/package-info.java +19 -0
  129. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/BaseDataQuerySample.java +194 -0
  130. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/BatchQuerySample.java +368 -0
  131. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/DataSetQueryStatSample.java +131 -0
  132. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/report/SampleReportFormPlugin.java +179 -0
  133. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/report/SampleReportListDataPlugin.java +616 -0
  134. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/snippets-guide.md +64 -0
  135. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/task/ScheduleTaskSample.java +160 -0
  136. package/vendor/kingdee-skills/ok-cosmic/assets/snippets/workflow/SampleWorkflowPlugin.java +302 -0
  137. package/vendor/kingdee-skills/ok-cosmic/manifest.json +78 -0
  138. package/vendor/kingdee-skills/ok-cosmic/ok-cosmic-intro.html +903 -0
  139. package/vendor/kingdee-skills/ok-cosmic/references/adv/attachment-api.md +114 -0
  140. package/vendor/kingdee-skills/ok-cosmic/references/adv/botp-convert.md +98 -0
  141. package/vendor/kingdee-skills/ok-cosmic/references/adv/dynamic-object.md +113 -0
  142. package/vendor/kingdee-skills/ok-cosmic/references/adv/entity-metadata.md +123 -0
  143. package/vendor/kingdee-skills/ok-cosmic/references/adv/event-lifecycle.md +184 -0
  144. package/vendor/kingdee-skills/ok-cosmic/references/adv/flex-prop.md +114 -0
  145. package/vendor/kingdee-skills/ok-cosmic/references/adv/form-utils.md +133 -0
  146. package/vendor/kingdee-skills/ok-cosmic/references/adv/operate-chain.md +159 -0
  147. package/vendor/kingdee-skills/ok-cosmic/references/adv/plugin-base.md +218 -0
  148. package/vendor/kingdee-skills/ok-cosmic/references/adv/query-dataset.md +149 -0
  149. package/vendor/kingdee-skills/ok-cosmic/references/adv/request-context.md +88 -0
  150. package/vendor/kingdee-skills/ok-cosmic/references/adv/view-handler.md +157 -0
  151. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-bill.md +76 -0
  152. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-botp.md +70 -0
  153. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-form.md +165 -0
  154. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-import.md +69 -0
  155. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-list.md +227 -0
  156. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-openapi.md +112 -0
  157. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-operation.md +135 -0
  158. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-print.md +65 -0
  159. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-report-data.md +64 -0
  160. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-report-form.md +90 -0
  161. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-task.md +62 -0
  162. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-tree-list.md +71 -0
  163. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-workflow.md +82 -0
  164. package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-writeback.md +71 -0
  165. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-algo.md +67 -0
  166. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-cache.md +63 -0
  167. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-dynamic-model-svc.md +82 -0
  168. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-dynamic-object.md +70 -0
  169. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-entity-model.md +61 -0
  170. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-exception.md +64 -0
  171. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-file.md +63 -0
  172. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-id.md +47 -0
  173. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-lock.md +61 -0
  174. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-log.md +63 -0
  175. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-network-control.md +70 -0
  176. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-orm-access.md +78 -0
  177. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-request-context.md +62 -0
  178. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-threadpool.md +63 -0
  179. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-tx.md +64 -0
  180. package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-utils.md +67 -0
  181. package/vendor/kingdee-skills/ok-cosmic/requirements.txt +2 -0
  182. package/vendor/kingdee-skills/ok-cosmic/rules/a-layer-rules.json +24 -0
  183. package/vendor/kingdee-skills/ok-cosmic/rules/anti-patterns.md +48 -0
  184. package/vendor/kingdee-skills/ok-cosmic/rules/cheat-sheet.md +256 -0
  185. package/vendor/kingdee-skills/ok-cosmic/rules/coding-preferences.md +140 -0
  186. package/vendor/kingdee-skills/ok-cosmic/rules/constraints.md +61 -0
  187. package/vendor/kingdee-skills/ok-cosmic/rules/decision-matrix.md +222 -0
  188. package/vendor/kingdee-skills/ok-cosmic/rules/intent-routing.md +94 -0
  189. package/vendor/kingdee-skills/ok-cosmic/rules/platform-baseline.md +69 -0
  190. package/vendor/kingdee-skills/ok-cosmic/rules/post-check.md +109 -0
  191. package/vendor/kingdee-skills/ok-cosmic/scripts/config_loader.py +204 -0
  192. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-api-knowledge.py +910 -0
  193. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-basedata-query.py +359 -0
  194. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-config-check.py +181 -0
  195. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-extpoints-query.py +389 -0
  196. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-form-metadata.py +856 -0
  197. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-check.py +262 -0
  198. package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-lint.py +293 -0
  199. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/__init__.py +2 -0
  200. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/base.py +393 -0
  201. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/resource_check.py +176 -0
  202. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/scene_check.py +375 -0
  203. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/style_check.py +434 -0
  204. package/vendor/kingdee-skills/ok-cosmic/scripts/lint/verify_check.py +36 -0
  205. package/vendor/kingdee-skills/ok-cosmic/scripts/route_client.py +186 -0
  206. package/vendor/kingdee-skills/ok-cosmic/scripts/script_utils.py +40 -0
  207. package/vendor/kingdee-skills/ok-cosmic/scripts/sqlite_cache.py +142 -0
  208. package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-commons.jar +0 -0
  209. package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-features.jar +0 -0
  210. package/vendor/kingdee-skills/ok-cosmic/setup/ok-cosmic-docs.db +0 -0
  211. package/vendor/kingdee-skills/ok-cosmic/setup/ok-cosmic.json +13 -0
  212. package/vendor/kingdee-skills/ok-cosmic/setup/setup-mac.sh +18 -0
  213. package/vendor/kingdee-skills/ok-cosmic/setup/setup-windows.bat +53 -0
  214. package/vendor/kingdee-skills/ok-cosmic/setup/setup.jar +0 -0
  215. package/vendor/kingdee-skills/ok-ksql/SKILL.md +81 -0
  216. package/vendor/kingdee-skills/ok-ksql/agents/openai.yaml +7 -0
  217. package/vendor/kingdee-skills/ok-ksql/manifest.json +14 -0
  218. package/vendor/kingdee-skills/ok-ksql/references/ksql-datafix.md +452 -0
  219. package/vendor/kingdee-skills/ok-ksql/scripts/ksql_lint.py +363 -0
@@ -0,0 +1,114 @@
1
+ # 弹性域自动解析工具 (FlexPropUtils)
2
+
3
+ ## TL;DR
4
+ - 适用:把弹性域 ID 批量解析成结构化键值,而不是直接读 `flex_field*`。
5
+ - 先抓:先确认 `FlexType`,再用 `FlexPropUtils` 做批量解析和结果映射。
6
+ - 跳转:普通字段/基础资料引用不要停在本页,分别去元数据或基础资料查询路径。
7
+ - 继续读全文:当你要处理多行分录弹性域、批量解析或配置加载方式时。
8
+
9
+ ## 概述
10
+ 弹性域是苍穹平台提供的高度扩展字段机制。物理上它们以扁平字段(如 `flex_field1`)存储。`FlexPropUtils` (位于 `kd.cd.common.util`) 封装了复杂的映射关系,支持将弹性域 ID 批量解析为结构化的 `Map` 键值对,大幅减少代码量并提高可读性。
11
+
12
+ > **适用边界**
13
+ > ✅ 适用:弹性域 ID 解析为结构化键值对。
14
+ > ❌ 不适用:普通实体字段读取请用 `entity-metadata.md`;基础资料引用请用 `BaseDataServiceHelper`。
15
+
16
+ ## 核心类
17
+ - **`kd.cd.common.util.FlexPropUtils`**: **弹性域处理核心工具类**。
18
+ - **`kd.cd.common.util.FlexType`**: 弹性域类型枚举。
19
+
20
+ ## FlexType 枚举
21
+ 弹性域类型决定了字段映射关系的来源:
22
+ - **`ACT`**: 核算维度
23
+ - **`AUX`**: 辅助属性
24
+
25
+ ## 常用 API 方法
26
+
27
+ ### 1. 弹性域自动解析
28
+ - `parseSingle(DynamicObject flexEntity, FlexType flexType)`: 解析单个弹性域实体,返回值映射。
29
+ - `parse(Collection<DynamicObject> flexEntities, FlexType flexType)`: 批量解析对象集合,返回按主键分组的值映射。
30
+ - `parseByFlexIds(Collection<Object> flexIds, FlexType flexType)`: 直接根据弹性域的主键 ID 进行批量解析,返回按主键分组的值映射。
31
+
32
+ ### 2. 查询方法
33
+ - `queryJsonByFlexIds(Collection<Object> flexIds, FlexType flexType)`: 批量查询并返回弹性域主键映射其 JSON 字符串。
34
+
35
+ ### 3. 配置加载
36
+ - `loadFieldRelationAsMap(FlexType flexType)`: 加载弹性域标识与物理字段名的映射关系。
37
+
38
+ ## 示例代码
39
+
40
+ ### 解析单据中的辅助属性弹性域
41
+ ```java
42
+ package kd.cd.common.demo;
43
+
44
+ import kd.cd.common.util.FlexPropUtils;
45
+ import kd.cd.common.util.FlexType;
46
+ import kd.bos.dataentity.entity.DynamicObject;
47
+ import java.util.Map;
48
+ import java.util.Collection;
49
+
50
+ public class FlexDemo {
51
+ public void demo(DynamicObject bill) {
52
+ // 1. 获取弹性域实体
53
+ DynamicObject flexEntity = bill.getDynamicObject("flex_field");
54
+
55
+ // 2. 解析辅助属性 (AUX) 类型的弹性域
56
+ Map<String, Object> values = FlexPropUtils.parseSingle(flexEntity, FlexType.AUX);
57
+
58
+ // 3. 根据字段 Key 获取解析后的业务值
59
+ Object color = values.get("flex_color");
60
+ Object size = values.get("flex_size");
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### 批量解析弹性域
66
+ ```java
67
+ public void batchDemo(Collection<Object> flexIds) {
68
+ // 根据弹性域主键批量解析
69
+ Map<Object, Map<String, Object>> result = FlexPropUtils.parseByFlexIds(flexIds, FlexType.AUX);
70
+
71
+ // 遍历结果
72
+ for (Map.Entry<Object, Map<String, Object>> entry : result.entrySet()) {
73
+ Object flexId = entry.getKey();
74
+ Map<String, Object> fieldValues = entry.getValue();
75
+
76
+ // 获取具体字段值
77
+ Object color = fieldValues.get("flex_color");
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### 从分录中提取弹性域值
83
+ ```java
84
+ public void extractFromEntry(DynamicObject bill) {
85
+ DynamicObjectCollection entries = bill.getDynamicObjectCollection("entry");
86
+
87
+ // 收集所有弹性域ID
88
+ Set<Object> flexIds = DynamicObjectUtils.setOf(entries, "flex_field.id");
89
+
90
+ // 批量解析
91
+ Map<Object, Map<String, Object>> flexValues = FlexPropUtils.parseByFlexIds(flexIds, FlexType.AUX);
92
+
93
+ // 匹配分录数据
94
+ for (DynamicObject entry : entries) {
95
+ Object flexId = entry.get("flex_field.id");
96
+ Map<String, Object> values = flexValues.get(flexId);
97
+ if (values != null) {
98
+ // 使用解析后的值
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## 实践建议
105
+ 1. **优先使用解析工具**: 严禁直接通过 `get("flex_field1")` 这种方式硬编码逻辑。使用 `FlexPropUtils` 后代码具有更好的业务可读性。
106
+ 2. **区分 FlexType**: 当前 commons 中内置的类型为 `ACT`(核算维度)与 `AUX`(辅助属性),调用前必须确认所属类型。
107
+ 3. **批量处理性能**: 在分录处理逻辑中,建议收集所有弹性域 ID 后统一调用 `parseByFlexIds` 一次性完成转换。
108
+ 4. **空值判断**: 如果弹性域 ID 为空,解析结果通常会返回一个空的 Map。
109
+
110
+ ## 常见坑位
111
+ 1. **缓存更新延迟**: 如果在设计器中新发布了弹性域,后台工具类可能需要 10 分钟缓存 TTL 刷新后才能读取到新字段,生产环境可能需要刷新元数据缓存。
112
+ 2. **空值判断**: 如果弹性域 ID 为空,解析结果通常会返回一个空的 Map,需要进行空判断。
113
+ 3. **字段重复**: 不同类型的弹性域可能包含相同标识的字段,调用时必须确认 `FlexType`。
114
+ 4. **返回类型变化**: `parseSingle` 方法实际是从 `parse` 返回的 Map 中提取对应主键的值,注意返回类型是 `Map<String, Object>`。
@@ -0,0 +1,133 @@
1
+ # 界面视图增强工具 (FormUtils)
2
+
3
+ ## TL;DR
4
+ - 适用:表单/UI 控件启停、可见性、筛选、消息提示和视图信息读取。
5
+ - 先抓:`FormUtils` 只服务有 UI 上下文的场景,优先解决控件和视图层问题。
6
+ - 跳转:后台打开页面改读 `view-handler.md`;服务端事务逻辑改读操作插件文档。
7
+ - 继续读全文:当你要确认控件定位、元数据读取或消息处理 API 时。
8
+
9
+ ## 概述
10
+ 界面交互逻辑是插件开发最耗时的地方。`FormUtils` (位于 `kd.cd.common.form`) 提供了一系列针对 `IFormView` 的快捷操作,能够极大简化控件控制、视图判定、消息处理等代码。
11
+
12
+ > **适用边界**
13
+ > ✅ 适用:表单控件启用/禁用/隐藏、UI 消息、视图判定。
14
+ > ❌ 不适用:后台操作(无 UI 上下文)请用操作插件;后台打开表单/列表请用 `view-handler.md`。
15
+
16
+ ## 核心类
17
+ - **`kd.cd.common.form.FormUtils`**: **界面工具核心类**。
18
+
19
+ ## API 方法全览
20
+
21
+ ### 1. 视图状态与属性
22
+ - `getBillFormId(IFormView view)`: 获取当前表单标识(原标识,非实体标识)。
23
+ - `getBillStatus(IFormView view)`: 获取单据审核状态。
24
+ - `getParentViewNoPlugin(IFormView view)`: 获取无插件的父页面视图。
25
+ - `getViewByPageId(String pageId)`: 通过 PageId 获取视图对象。
26
+ - `getPluginInstance(String pageId, Class<T> clazz)`: 获取某个视图对象的某个插件实例。
27
+ - `getAllPluginInstance(String pageId)`: 获取视图所有插件实例(调试用)。
28
+
29
+ ### 2. 列表控件
30
+ - `getBillList(IFormView view)`: 获取列表控件(BillList)。
31
+ - `getReportList(IFormView view)`: 获取报表列表控件(ReportList)。
32
+ - `getListGrid(IFormView view, Class<T> clazz)`: 获取列表网格控件(泛型)。
33
+ - `getListButtonKeys(String formId, boolean includeDropDown)`: 获取列表所有按钮标识与其对应操作映射。
34
+
35
+ ### 3. 控件筛选与检索
36
+ - `getAllControls(IFormView view)`: 获取当前界面所有控件 Map。
37
+ - `getAllControls(String formId)`: 获取表单中所有控件对象。
38
+ - `getSubControls(Container container, boolean includeContainer)`: 获取容器内的子控件。
39
+ - `selectControls(IFormView view, Predicate<Control> filter)`: 筛选表单控件。
40
+ - `selectSubControls(Container container, Predicate<Control> filter)`: 筛选容器子控件。
41
+
42
+ ### 4. 表单标识获取
43
+ - `getF7ListFormId(String billFormId)`: 获取列表F7标识。
44
+ - `getListFormId(String billFormId)`: 获取列表标识。
45
+ - `getMasterFormId(String extFormId)`: 根据拓展表单标识获取原表单标识。
46
+
47
+ ### 5. 元数据读取(数据库访问)
48
+ - `readListMetadata(String billFormId)`: 查询列表元数据。
49
+ - `readEntityMeta(String formId)`: 查询实体元数据。
50
+ - `readEntityMetaAsMap(String formId, String... fieldKeys)`: 查询实体元数据字段映射。
51
+ - `readFormMeta(String formId)`: 查询表单元数据。
52
+ - `readFormMetaAsMap(String formId, String... fieldKeys)`: 查询表单元数据字段映射。
53
+
54
+ ### 6. UI 消息处理
55
+ - `peekUIMsg(IFormView view)`: 预览视图前端提示信息(调试用)。
56
+ - `getFlatUIMessages(IFormView view, boolean ignoreSuccessMsg)`: 提取视图前端提示信息。
57
+
58
+ ## 示例代码
59
+
60
+ ### 获取视图信息
61
+ ```java
62
+ public void analyzeView(IFormView view) {
63
+ // 获取表单标识
64
+ String formId = FormUtils.getBillFormId(view);
65
+
66
+ // 获取单据状态
67
+ String status = FormUtils.getBillStatus(view);
68
+
69
+ // 获取父页面视图
70
+ IFormView parentView = FormUtils.getParentViewNoPlugin(view);
71
+ }
72
+ ```
73
+
74
+ ### 控件筛选
75
+ ```java
76
+ public void filterControls(IFormView view) {
77
+ String formId = FormUtils.getBillFormId(view);
78
+
79
+ // 获取所有控件
80
+ Map<String, Control> allControls = FormUtils.getAllControls(view);
81
+
82
+ // 筛选特定类型控件
83
+ Map<String, Control> entryGrids = FormUtils.selectControls(view, EntryGrid.class::isInstance);
84
+
85
+ // 获取列表按钮映射
86
+ Map<String, String> buttonOps = FormUtils.getListButtonKeys(formId, true);
87
+ }
88
+ ```
89
+
90
+ ### 列表操作
91
+ ```java
92
+ public void listOperation(IFormView listView) {
93
+ String pageId = listView.getPageId();
94
+
95
+ // 获取列表控件
96
+ BillList billList = FormUtils.getBillList(listView);
97
+
98
+ // 通过PageId获取视图
99
+ IFormView targetView = FormUtils.getViewByPageId(pageId);
100
+
101
+ // 获取插件实例
102
+ MyPlugin plugin = FormUtils.getPluginInstance(pageId, MyPlugin.class);
103
+ }
104
+ ```
105
+
106
+ ### UI 消息提取
107
+ ```java
108
+ public void checkMessages(IFormView view) {
109
+ // 获取所有非成功消息
110
+ List<String> messages = FormUtils.getFlatUIMessages(view, true);
111
+
112
+ // 预览所有UI消息(调试用)
113
+ Map<String, ?> uiMsg = FormUtils.peekUIMsg(view);
114
+ }
115
+ ```
116
+
117
+ ## 实践建议
118
+ 1. **控件筛选**: 使用 `selectControls` 配合方法引用可以快速筛选特定类型控件,如 `EntryGrid.class::isInstance`。
119
+ 2. **父视图获取**: 在弹出界面中需要访问父页面时,使用 `getParentViewNoPlugin` 获取。
120
+ 3. **按钮映射**: `getListButtonKeys` 可用于动态判断按钮对应的操作,便于条件控制。
121
+ 4. **元数据读取**: `readXxxMeta` 系列方法会访问数据库,应避免高频调用。
122
+
123
+ ## 常见坑位
124
+ 1. **视图类型判断**: `getBillStatus` 仅适用于 `IBillView` 类型视图,对动态表单会抛异常。
125
+ 2. **PageId 时效**: `getViewByPageId` 获取的视图对象仅在当前会话有效。
126
+ 3. **控件 Key 区分**: 控件的 Key 与字段标识可能不同,需通过设计器确认。
127
+ 4. **元数据缓存**: `readXxxMeta` 方法每次访问数据库,建议缓存结果。
128
+
129
+ ## 相关工具类
130
+ - **`kd.cd.core.util.SystemPropertyUtils`**: 系统配置工具
131
+ - `isProdEnv()`: 判定是否为生产环境
132
+ - `get(String key, String def)`: 获取配置项
133
+ - `getBoolean(String key, boolean def)`: 获取布尔配置项
@@ -0,0 +1,159 @@
1
+ # 业务操作与链式事务 (OpUtils & OperateChain)
2
+
3
+ ## TL;DR
4
+ - 适用:保存、提交、审核、删除等单据操作,尤其是多步链式执行。
5
+ - 先抓:单次操作优先 `OpUtils`,多步流程再上 `OperateChain`。
6
+ - 跳转:下推/选单改读 `botp-convert.md`;纯插件事件时再读 `base/plugin/plugin-operation.md`。
7
+ - 继续读全文:当你要确认事务边界、结果处理、回滚删除或字段准备写法时。
8
+
9
+ ## 概述
10
+ 业务单据的操作(保存、审核、下推等)是苍穹逻辑流转的基石。`OpUtils` (位于 `kd.cd.common.operate`) 提供了一键执行操作并反馈异常的原子 API;`OperateChain` 提供了流式 API 以执行复杂的操作组。本规范旨在确保单据操作的一致性与健壮性。
11
+
12
+ > **适用边界**
13
+ > ✅ 适用:需要连续执行多个操作(如保存→提交→审核)的链式场景。
14
+ > ❌ 不适用:单次操作(仅 save / submit / audit)优先用 `OpUtils.executeOperateOrThrow`,更简洁。
15
+
16
+ ## OpUtils vs OperationServiceHelper 选择指南
17
+
18
+ | 维度 | `OpUtils.executeOperateOrThrow` | `OperationServiceHelper.executeOperate` |
19
+ |------|------|------|
20
+ | **失败行为** | 自动抛出异常,回滚事务 | 返回 `OperationResult`,需自行检查 |
21
+ | **适合场景** | 大多数业务场景:操作插件、表单插件、服务层 | MQ 消费、后台任务、失败后需回填错误信息 |
22
+ | **代码风格** | 一行调用,fail-fast | 需 if/else 分支处理成功/失败 |
23
+ | **典型用法** | `OpUtils.executeOperateOrThrow("audit", entityId, pks)` | `OperationResult r = OperationServiceHelper.executeOperate("audit", entityId, pks, null); if (!r.isSuccess()) { String errMsg = OpUtils.getCompleteFailMsg(r); }` |
24
+
25
+ > **简单原则**:“失败就应该回滚”用 `OpUtils`;“失败不回滚,我要自己处理”用 `OperationServiceHelper`,用 `OpUtils.getCompleteFailMsg(result)` 提取完整错误信息。
26
+
27
+ ## 核心基类/工具类
28
+ - **`kd.cd.common.operate.OpUtils`**: **核心操作工具类**。
29
+ - **`kd.cd.common.operate.chain.OperateChain`**: 链式操作器。
30
+ - **`kd.cd.common.operate.chain.ChainStorage`**: 操作链数据存储。
31
+ - **`kd.bos.entity.operate.result.OperationResult`**: 单据操作结果。
32
+
33
+ ## OpUtils API 方法
34
+
35
+ ### 1. 核心操作执行
36
+ - `executeOperateOrThrow(String opKey, String entityId, DynamicObject[] dataEntities)`: **最常用**。执行操作,失败则抛出异常回滚事务。
37
+ - `executeOperateOrThrow(String opKey, String entityId, Object[] pks)`: 根据主键执行操作。
38
+ - `executeOperateOrThrow(String opKey, String entityId, DynamicObject[] dataEntities, OperateOption option)`: 带操作参数执行。
39
+ - `executeOperateOrThrow(String opKey, String entityId, Object[] pks, OperateOption option)`: 带操作参数根据主键执行。
40
+ - `throwIfFail(OperationResult result)`: 针对手动执行的操作结果进行校验并回滚。
41
+
42
+ ### 2. 回滚删除
43
+ - `rollbackAndDelete(String entityId, Object pkValue)`: 如果后续逻辑失败,自动反审核并删除本单据。
44
+ - `rollbackAndDelete(IFormView view)`: 基于视图的回滚删除。
45
+ - `rollbackAndDelete(String entityId, Object pkValue, boolean requireNewTXForEachStage)`: 可控制事务隔离级别。
46
+
47
+ ### 3. 字段准备(操作插件用)
48
+ - `prepareEntryFields(MainEntityType mainType, String... entryKeys)`: 一键生成包含分录所有子字段的列表(推荐)。
49
+ - `prepareAllFields(MainEntityType mainType)`: 准备所有加载字段(仅推荐公共插件中使用)。
50
+
51
+ ### 4. 错误消息处理
52
+ - `addErrorMessage(AbstractOperationServicePlugIn plugin, DynamicObject dataEntity, String message)`: 在操作插件中手动回填校验错误消息。
53
+ - `addErrorMessage(AbstractOperationServicePlugIn plugin, DynamicObject dataEntity, String title, String message)`: 带标题的错误消息。
54
+ - `addErrorMessage(AbstractOperationServicePlugIn plugin, DynamicObject dataEntity, String title, String errCode, String message)`: 完整错误消息。
55
+ - `addValidatorErrorMsg(AbstractValidator validator, ExtendedDataEntity extDataEntity, String errCode, String message)`: 校验器错误消息。
56
+ - `getCompleteFailMsg(OperationResult result)`: 提取全量分录中的所有错误消息。
57
+ - `getChsName(String entityId, String opKey)`: 获取操作中文名。
58
+
59
+ ## OperateChain API 方法
60
+
61
+ ### 1. 工厂方法
62
+ - `OperateChain.of(String entityId, Object pkValue)`: 根据实体标识和主键创建。
63
+ - `OperateChain.of(DynamicObject dataEntity)`: 根据数据包创建。
64
+ - `OperateChain.of(IFormView view)`: 根据视图创建。
65
+
66
+ ### 2. 链式操作方法
67
+ - `save()`: 保存。
68
+ - `save(OperateOption option)`: 带参数保存。
69
+ - `submit()`: 提交。
70
+ - `submit(OperateOption option)`: 带参数提交。
71
+ - `submitNoWF()`: 提交(不触发工作流)。
72
+ - `submitNoWF(OperateOption option)`: 带参数提交(不触发工作流)。
73
+ - `audit()`: 审核。
74
+ - `audit(OperateOption option)`: 带参数审核。
75
+ - `unSubmit()`: 撤销提交。
76
+ - `unSubmit(OperateOption option)`: 带参数撤销提交。
77
+ - `unAudit()`: 反审核。
78
+ - `unAudit(OperateOption option)`: 带参数反审核。
79
+ - `delete()`: 删除。
80
+ - `delete(OperateOption option)`: 带参数删除。
81
+ - `operate(String opKey)`: 执行自定义操作。
82
+ - `operate(String opKey, OperateOption option)`: 带参数执行自定义操作。
83
+
84
+ ### 3. 结果处理
85
+ - `isSuccess()`: 判断操作链是否成功。
86
+ - `storage()`: 获取操作链数据存储。
87
+ - `failThenDelete()`: 失败后删除单据。
88
+ - `failThenDeleteAndThrow()`: 失败后删除并抛异常。
89
+ - `failThenDeleteAndThrow(String tip)`: 失败后删除并抛异常(带提示)。
90
+ - `failThenThrow()`: 失败后抛异常。
91
+ - `failThenThrow(String tip)`: 失败后抛异常(带提示)。
92
+
93
+ ### 4. 事务控制
94
+ - `requireNewTXForEachStage(boolean require)`: 是否为每个操作阶段开启独立事务。
95
+ - `getGlobalOptionControl()`: 获取全局操作参数控制器。
96
+
97
+ ## 示例代码
98
+
99
+ ### 静默审核单据模板
100
+ ```java
101
+ package kd.cd.common.demo;
102
+
103
+ import kd.cd.common.operate.OpUtils;
104
+
105
+ public class OpDemo {
106
+ public void auditBill(String formId, Object pkId) {
107
+ // 1. 调用审核操作,失败将自动抛出带完整错误描述的异常
108
+ OpUtils.executeOperateOrThrow("audit", formId, new Object[]{pkId});
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### 链式操作模板
114
+ ```java
115
+ public void chainOperation(DynamicObject dataEntity) {
116
+ // 链式操作:保存 -> 提交 -> 审核 -> 自定义操作
117
+ OperateChain chain = OperateChain.of(dataEntity);
118
+ if (!chain.save().submit().audit().operate("pay").isSuccess()) {
119
+ String errMsg = chain.storage().getErrMsg();
120
+ // 处理失败逻辑
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### 失败后删除
126
+ ```java
127
+ public void operateWithRollback(String entityId, Object pkValue) {
128
+ // 创建单据后,后续操作失败则自动回滚删除
129
+ OperateChain chain = OperateChain.of(entityId, pkValue);
130
+ chain.save().submit().audit();
131
+ chain.failThenDelete(); // 如果前面操作失败,会自动回滚删除
132
+ }
133
+ ```
134
+
135
+ ### 操作插件字段准备
136
+ ```java
137
+ public class MyOperationPlugin extends AbstractOperationServicePlugInExt {
138
+ @Override
139
+ public void onPreparePropertys(PreparePropertysEventArgs e) {
140
+ // 加载分录所有字段(不推荐,只适用公共的操作插件,不要轻易尝试)
141
+ e.setFieldKeys(allFields());
142
+ // 或仅加载特定分录字段
143
+ e.setFieldKeys(entryFields("entry1", "entry2"));
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## 实践建议
149
+ 1. **优先使用 OrThrow**: 失败即回滚的场景,`executeOperateOrThrow` 是保持业务逻辑清晰的最佳方式。
150
+ 2. **需结果分支时用原生 API**: MQ 消费、后台任务等“失败不抛异常”场景,直接用 `OperationServiceHelper.executeOperate` 并检查 `OperationResult`。
151
+ 3. **多语言注意**: 所有的错误消息回填建议使用多语言属性。
152
+ 4. **事务范围**: 在操作插件中使用 `OpUtils` 时,其操作会自动被包在当前的数据库事务中。
153
+ 5. **链式操作**: 使用 `OperateChain` 可以优雅地处理连续操作,支持短路(前一操作失败后不再执行后续操作)。
154
+
155
+ ## 常见坑位
156
+ 1. **ID 数组错误**: `executeOperateOrThrow` 的 ID 数组必须类型一致(长整型或字符串),混合类型会导致单据找不到。
157
+ 2. **状态拦截**: 对已审核单据再次执行 `audit` 操作会返回失败,执行前应检查单据状态。
158
+ 3. **忽略结果检查**: 若直接使用 `OperationServiceHelper` 却不检查 `OperationResult`,会导致逻辑静默失败;应始终检查 `result.isSuccess()` 或使用 `OpUtils.throwIfFail(result)` 托底。
159
+ 4. **独立事务**: 开启 `requireNewTXForEachStage(true)` 后链路将失去"整体原子性",需自行处理补偿逻辑。
@@ -0,0 +1,218 @@
1
+ # 扩展插件基类 (Plugin Base Extensions)
2
+
3
+ ## TL;DR
4
+ - 适用:所有可继承 Ext 基类的表单、单据、列表、操作插件都应先读本页。
5
+ - 先抓:选对 `Abstract*Ext` 基类,再复用已封装的日志、取值、监听注册和列表能力。
6
+ - 跳转:BOTP 转换、反写、工作流、OpenAPI 这类无 Ext 封装场景不要停在本页。
7
+ - 继续读全文:当你要确认 `@Override` 签名、生命周期或扩展方法全集时。
8
+
9
+ ## 概述
10
+ 扩展插件基类(Ext 系列)是基于金蝶苍穹原生插件类的二次封装。通过继承 `kd.cd.common.plugin` 下的基类,开发者可以直接获得统一的 `log` 对象,以及视图/元数据/取值等常用扩展方法。这是 `kd-cd-cosmic-commons` 框架的基础能力之一。
11
+
12
+ > **适用边界**
13
+ > ✅ 适用:所有需要继承 Ext 基类的表单/单据/列表/操作插件。
14
+ > ❌ 不适用:BOTP 转换插件和反写插件没有 Ext 封装,直接用原生基类。
15
+
16
+ ## 核心基类
17
+
18
+ ### 基础插件
19
+ - **`kd.cd.common.plugin.AbstractBasePlugInExt`**: 基础插件扩展。
20
+
21
+ ### 单据插件
22
+ - **`kd.cd.common.plugin.AbstractBillPlugInExt`**: **单据插件首选**。封装了原生 `AbstractBillPlugIn`,内置 `log` 对象,实现 `IBillPluginExtension` 和 `BeforeF7SelectListener`。
23
+
24
+ ### 表单插件
25
+ - **`kd.cd.common.plugin.AbstractFormPluginExt`**: 动态表单插件扩展。
26
+
27
+ ### 列表插件
28
+ - **`kd.cd.common.plugin.AbstractListPluginExt`**: 列表插件扩展,强化了选中行(SelectedRows)的处理。
29
+
30
+ ### 操作插件
31
+ - **`kd.cd.common.plugin.AbstractOperationServicePlugInExt`**: 操作插件扩展,简化了 `onPreparePropertys` 字段准备。
32
+
33
+ ### 校验器
34
+ - **`kd.cd.common.plugin.AbstractValidatorExt`**: 校验器扩展。
35
+
36
+ ## 常用 API 方法
37
+
38
+ ### 通用能力 (所有基类)
39
+ - `log.info(String msg, Object... args)`: 统一的 `kd.bos.logging.Log` 日志对象。
40
+
41
+ ### 操作插件特有 (`AbstractOperationServicePlugInExt`)
42
+ - `allFields()`: 一键生成包含所有字段的列表。
43
+ - `entryFields(String... entryKeys)`: 一键生成包含分录所有子字段的列表。
44
+ - `addErrorMessage(DynamicObject dataEntity, String message)`: 快速回填操作错误。
45
+ - `addErrorMessage(DynamicObject dataEntity, String title, String message)`: 带标题的错误消息。
46
+ - `addErrorMessage(DynamicObject dataEntity, String title, String errCode, String message)`: 完整错误消息。
47
+ - `arrayOfIds(DynamicObject[] array)`: 提取主键数组。
48
+ - `setOfIds(DynamicObject[] array)`: 提取主键集合。
49
+ - `listOf(DynamicObject[] array, String field)`: 提取字段值列表。
50
+ - `setOf(DynamicObject[] array, String field)`: 提取字段值集合。
51
+
52
+ ### IFormPluginExtension 接口方法
53
+ - `getValue(String key)`: 获取字段值。
54
+ - `getValue(String key, int rowIndex)`: 获取分录字段值。
55
+ - `getValue(String key, int rowIndex, int parentRowIndex)`: 获取分录分录字段值。
56
+ - `getFlatValues(String key)`: 扁平获取字段所有值,返回 `List<T>`。
57
+ - `getBaseDataQuoteType(String baseDataField)`: 获取基础资料引用类型。
58
+ - `getEntryPropKeys(String entryKey)`: 获取分录字段标识集。
59
+ - `getEntryProperties(String entryKey)`: 获取分录字段属性映射。
60
+ - `getProperties(Predicate<IDataEntityProperty> predicate)`: 筛选字段属性。
61
+ - `getProperty(String field)`: 获取字段属性。
62
+ - `getEntryType(String entryKey)`: 获取分录类型。
63
+ - `getMainEntityType()`: 获取主实体类型。
64
+ - `view()`: 获取当前视图。
65
+
66
+ ### 监听器注册方法
67
+ - `addEntryRowClickListeners(String... entryKeys)`: 批量注册分录行点击监听。
68
+ - `addTabSelectListeners(String... tabKeys)`: 批量注册页签选择监听。
69
+ - `addHyperClickListeners(String... keys)`: 批量注册超链接点击监听。
70
+ - `addItemClickListeners(String... keys)`: 批量注册菜单项点击监听。
71
+ - `addBeforeF7SelectListeners(String... keys)`: 批量注册 F7 弹出前监听。
72
+
73
+ ### 数据更新方法
74
+ - `updateEntryView(String entryKey, DynamicObjectCollection rowData)`: 更新分录视图数据。
75
+
76
+ ### 列表插件补充方法 (`AbstractListPluginExt`)
77
+ - `getButtonKeys(boolean includeDropDown)`: 获取列表按钮标识与操作映射。
78
+ - `getBillList()`: 获取列表控件。
79
+ - `getSelectedRowPkValues()`: 获取当前选中行主键集合。
80
+ - `clearSelectRows()`: 清空当前列表选中项。
81
+
82
+ ### 调试方法
83
+ - `peek()`: 预览实体结构(调试用)。
84
+
85
+ ## 示例代码
86
+
87
+ ### 标准单据插件模板
88
+ ```java
89
+ package kd.cd.common.demo;
90
+
91
+ import kd.cd.common.plugin.AbstractBillPlugInExt;
92
+ import kd.cd.common.entity.EntityUtils;
93
+ import kd.bos.form.events.AfterDoOperationEventArgs;
94
+
95
+ public class MyBillPlugin extends AbstractBillPlugInExt {
96
+ @Override
97
+ public void afterDoOperation(AfterDoOperationEventArgs e) {
98
+ super.afterDoOperation(e);
99
+ if ("audit".equals(e.getOperationKey())) {
100
+ String billNo = getValue(EntityUtils.getBillNoKey(getBillFormId()));
101
+ log.info("单据 {} 审核成功", billNo);
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### 操作插件模板
108
+ ```java
109
+ public class MyOperationPlugin extends AbstractOperationServicePlugInExt {
110
+ @Override
111
+ public void onPreparePropertys(PreparePropertysEventArgs e) {
112
+ // 加载所有字段
113
+ e.setFieldKeys(allFields());
114
+
115
+ // 或仅加载特定分录字段
116
+ e.setFieldKeys(entryFields("entry1", "entry2"));
117
+ }
118
+
119
+ @Override
120
+ public void beginOperationTransaction(BeginOperationTransactionArgs e) {
121
+ DynamicObject bill = e.getDataEntities()[0];
122
+ if (Boolean.TRUE.equals(bill.getBoolean("forbidflag"))) {
123
+ addErrorMessage(bill, "操作失败,请检查数据");
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ ### 使用扩展方法
130
+ ```java
131
+ public class DemoPlugin extends AbstractBillPlugInExt {
132
+ public void demo() {
133
+ // 获取字段值(支持深路径)
134
+ String orgName = getValue("org.name");
135
+
136
+ // 扁平获取分录所有物料ID
137
+ List<Object> materialIds = getFlatValues("entry.material.id");
138
+
139
+ // 获取分录字段信息
140
+ Set<String> entryFields = getEntryPropKeys("entry");
141
+
142
+ // 获取基础资料引用类型
143
+ String baseType = getBaseDataQuoteType("material");
144
+
145
+ // 调试预览
146
+ Object data = peek();
147
+ }
148
+ }
149
+ ```
150
+
151
+ ## 方法签名快照(生成 @Override 时直接对照)
152
+
153
+ ### AbstractFormPluginExt / AbstractBillPlugInExt 生命周期
154
+ ```java
155
+ public void initialize()
156
+ public void registerListener(EventObject e)
157
+ public void preOpenForm(PreOpenFormEventArgs e)
158
+ public void createNewData(BizDataEventArgs e)
159
+ public void afterCreateNewData(EventObject e)
160
+ public void loadData(LoadDataEventArgs e)
161
+ public void afterLoadData(EventObject e)
162
+ public void beforeBindData(EventObject e)
163
+ public void afterBindData(EventObject e)
164
+ public void afterCopyData(EventObject e)
165
+ public void propertyChanged(PropertyChangedArgs e)
166
+ public void beforeDoOperation(BeforeDoOperationEventArgs args)
167
+ public void afterDoOperation(AfterDoOperationEventArgs args)
168
+ public void beforeItemClick(BeforeItemClickEvent evt)
169
+ public void itemClick(ItemClickEvent evt)
170
+ public void beforeClick(BeforeClickEvent evt)
171
+ public void click(EventObject evt)
172
+ public void beforeF7Select(BeforeF7SelectEvent e)
173
+ public void confirmCallBack(MessageBoxClosedEvent evt)
174
+ public void closedCallBack(ClosedCallBackEvent e)
175
+ public void clientCallBack(ClientCallBackEvent e)
176
+ public void beforeClosed(BeforeClosedEvent e)
177
+ public void customEvent(CustomEventArgs e)
178
+ public void TimerElapsed(TimerElapsedArgs e)
179
+ public void afterAddRow(AfterAddRowEventArgs e)
180
+ public void afterDeleteRow(AfterDeleteRowEventArgs e)
181
+ public void afterDeleteEntry(AfterDeleteEntryEventArgs e)
182
+ public void destory() // 注意:不是 destroy
183
+ ```
184
+
185
+ ### AbstractListPluginExt 特有
186
+ ```java
187
+ public void setFilter(SetFilterEventArgs e)
188
+ public void afterCreateNewData(EventObject e)
189
+ public void beforeDoSelectRow(BeforeDoSelectRowEventArgs e)
190
+ ```
191
+
192
+ ### AbstractOperationServicePlugInExt 生命周期
193
+ ```java
194
+ public void onPreparePropertys(PreparePropertysEventArgs e)
195
+ public void onAddValidators(AddValidatorsEventArgs e)
196
+ public void beforeExecuteOperationTransaction(BeforeOperationArgs e)
197
+ public void beginOperationTransaction(BeginOperationTransactionArgs e)
198
+ public void endOperationTransaction(EndOperationTransactionArgs e)
199
+ public void afterExecuteOperationTransaction(AfterOperationArgs e)
200
+ public void onReturnOperation(ReturnOperationArgs e)
201
+ ```
202
+
203
+ ### AbstractValidatorExt
204
+ ```java
205
+ public void validate(ExtendedDataEntity[] dataEntities, ValidateContext validateContext)
206
+ ```
207
+
208
+ ## 实践建议
209
+ 1. **继承型插件强制使用 super**: 对继承型插件基类(如 `AbstractFormPluginExt`、`AbstractListPlugin`、`AbstractOperationServicePlugIn` 等),重写生命周期方法时务必先调用 `super.xxx()`,确保基类中的上下文初始化逻辑正常运行;接口型插件(如 `IWorkflowPlugin`)不适用此规则。
210
+ 2. **包名校验**: 导入时必须认准 `kd.cd.common.plugin`,避免误导至原生的 `kd.bos` 类。
211
+ 3. **轻量化插件**: 插件层只保留贴近触发点的编排与控制逻辑;复杂计算、可复用业务规则与跨模块数据处理应剥离至服务层(Service)。
212
+ 4. **使用扩展方法**: 优先使用基类提供的扩展方法(如 `getValue`, `getFlatValues` 等),减少重复代码。
213
+
214
+ ## 常见坑位
215
+ 1. **序列化问题**: 插件类会被序列化存储在 Session 中,严禁在插件成员变量中持有不可序列化的对象(如 `DataSet`, `InputStream`)。
216
+ 2. **空指针异常**: 在 `initialize` 阶段 `this.getView()` 可能尚未完全准备好,UI 操作建议推迟到 `registerListener` 之后。
217
+ 3. **多实例冲突**: 同一个表单打开多个页签时,静态变量(static)会共享,严禁在插件中使用非 final 的静态变量存储状态。
218
+ 4. **忘记调用 super**: 重写生命周期方法时忘记调用 `super.xxx()`,可能导致基类的初始化逻辑不执行。