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,160 @@
1
+ /**
2
+ * 后台定时任务示例。
3
+ * <p>
4
+ * 适用插件:后台任务、服务层
5
+ * 优先封装:当前仓库无专门任务封装,简单查询场景可优先考虑 QueryServiceHelper
6
+ * 原生兜底:AbstractTask、QueryServiceHelper、Log
7
+ * 相关 lint 规则:STYLE-009、STYLE-015
8
+ * <p>
9
+ * 使用场景:
10
+ * 1. 定时扫描并处理业务数据;
11
+ * 2. 异常监控预警;
12
+ * 3. 数据汇总统计;
13
+ * 4. 任务参数解析、进度回传、停止检查、dry-run。
14
+ */
15
+ package kd.cd.common.snippets.task;
16
+
17
+ import kd.bos.context.RequestContext;
18
+ import kd.bos.dataentity.entity.DynamicObject;
19
+ import kd.bos.dataentity.entity.DynamicObjectCollection;
20
+ import kd.bos.dataentity.resource.ResManager;
21
+ import kd.bos.dataentity.utils.StringUtils;
22
+ import kd.bos.exception.KDException;
23
+ import kd.bos.logging.Log;
24
+ import kd.bos.logging.LogFactory;
25
+ import kd.bos.orm.query.QCP;
26
+ import kd.bos.orm.query.QFilter;
27
+ import kd.bos.schedule.executor.AbstractTask;
28
+ import kd.bos.servicehelper.QueryServiceHelper;
29
+ import kd.cd.core.util.BigDecimalUtils;
30
+ import kd.cd.core.util.CollectionUtils;
31
+
32
+ import java.math.BigDecimal;
33
+ import java.math.RoundingMode;
34
+ import java.time.LocalDateTime;
35
+ import java.util.Map;
36
+
37
+ public class ScheduleTaskSample extends AbstractTask {
38
+ private static final Log log = LogFactory.getLog(ScheduleTaskSample.class);
39
+ private static final String STAT_FORM_ID = "outapilogdailystats";
40
+ private static final String PARAM_FAIL_RATE_LIMIT = "failRateLimit";
41
+ private static final String PARAM_DRY_RUN = "dryRun";
42
+ private static final BigDecimal DEFAULT_FAIL_RATE_LIMIT = BigDecimalUtils.valueOf(50);
43
+ private static final int DEFAULT_BATCH_SIZE = 50;
44
+ private static final String RES_APP_ID = "kd-cd-common-snippets";
45
+
46
+ @Override
47
+ public void execute(RequestContext requestContext, Map<String, Object> params) throws KDException {
48
+ BigDecimal failRateLimit = resolveFailRateLimit(params);
49
+ boolean dryRun = resolveDryRun(params);
50
+ this.feedbackProgress(0, ResManager.loadKDString("开始扫描接口统计数据", "ScheduleTaskSample_0", RES_APP_ID), null);
51
+
52
+ DynamicObjectCollection stats = queryStats();
53
+ if (CollectionUtils.isEmpty(stats)) {
54
+ this.feedbackProgress(100, ResManager.loadKDString("本次无需处理数据", "ScheduleTaskSample_1", RES_APP_ID), null);
55
+ return;
56
+ }
57
+
58
+ int total = stats.size();
59
+ int processed = 0;
60
+ int alarmCount = 0;
61
+ for (DynamicObject stat : stats) {
62
+ this.checkIsStop();
63
+
64
+ BigDecimal failRate = calculateFailRate(stat);
65
+ if (BigDecimalUtils.largeThan(failRate, failRateLimit)) {
66
+ sendAlarm(stat, failRate, dryRun);
67
+ alarmCount++;
68
+ }
69
+ processed++;
70
+
71
+ if (processed % DEFAULT_BATCH_SIZE == 0 || processed == total) {
72
+ int percent = processed * 100 / total;
73
+ this.feedbackProgress(
74
+ percent,
75
+ String.format(
76
+ ResManager.loadKDString("已处理 %1$d/%2$d 条统计记录,触发 %3$d 条预警", "ScheduleTaskSample_2", RES_APP_ID),
77
+ processed,
78
+ total,
79
+ alarmCount
80
+ ),
81
+ null
82
+ );
83
+ }
84
+ }
85
+ }
86
+
87
+ @Override
88
+ public void stop() throws KDException {
89
+ this.feedbackProgress(95, ResManager.loadKDString("收到停止指令,准备安全退出", "ScheduleTaskSample_3", RES_APP_ID), null);
90
+ }
91
+
92
+ private DynamicObjectCollection queryStats() {
93
+ LocalDateTime nextHour = LocalDateTime.now().plusHours(1).withMinute(0).withSecond(0).withNano(0);
94
+ return QueryServiceHelper.query(
95
+ STAT_FORM_ID,
96
+ "apinum,apiname,successcount,failcount",
97
+ new QFilter("gentime", QCP.equals, nextHour).toArray()
98
+ );
99
+ }
100
+
101
+ private BigDecimal calculateFailRate(DynamicObject stat) {
102
+ int successCount = stat.getInt("successcount");
103
+ int failCount = stat.getInt("failcount");
104
+ int totalCount = successCount + failCount;
105
+ if (totalCount <= 0) {
106
+ return BigDecimal.ZERO;
107
+ }
108
+ return BigDecimalUtils.divide(
109
+ BigDecimalUtils.valueOf((long) failCount * 100),
110
+ BigDecimalUtils.valueOf(totalCount),
111
+ 2,
112
+ RoundingMode.DOWN
113
+ );
114
+ }
115
+
116
+ private void sendAlarm(DynamicObject stat, BigDecimal failRate, boolean dryRun) {
117
+ String message = String.format(
118
+ ResManager.loadKDString("API异常预警:接口编号=%1$s,接口名称=%2$s,成功=%3$d,失败=%4$d,失败率=%5$s%%", "ScheduleTaskSample_4", RES_APP_ID),
119
+ stat.getString("apinum"),
120
+ stat.getString("apiname"),
121
+ stat.getInt("successcount"),
122
+ stat.getInt("failcount"),
123
+ failRate
124
+ );
125
+ if (dryRun) {
126
+ log.info("[dry-run] {}", message);
127
+ } else {
128
+ log.warn(message);
129
+ }
130
+ }
131
+
132
+ private BigDecimal resolveFailRateLimit(Map<String, Object> params) {
133
+ if (CollectionUtils.isEmpty(params)) {
134
+ return DEFAULT_FAIL_RATE_LIMIT;
135
+ }
136
+ Object value = params.get(PARAM_FAIL_RATE_LIMIT);
137
+ if (value instanceof Number) {
138
+ return BigDecimalUtils.valueOf((Number) value);
139
+ }
140
+ if (value instanceof String) {
141
+ String text = ((String) value).trim();
142
+ if (StringUtils.isNumeric(text)) {
143
+ return new BigDecimal(text);
144
+ }
145
+ log.warn("failRateLimit 参数格式非法:{}", value);
146
+ }
147
+ return DEFAULT_FAIL_RATE_LIMIT;
148
+ }
149
+
150
+ private boolean resolveDryRun(Map<String, Object> params) {
151
+ if (params == null) {
152
+ return false;
153
+ }
154
+ Object value = params.get(PARAM_DRY_RUN);
155
+ if (value instanceof Boolean) {
156
+ return (Boolean) value;
157
+ }
158
+ return value instanceof String && Boolean.parseBoolean((String) value);
159
+ }
160
+ }
@@ -0,0 +1,302 @@
1
+ package kd.cd.common.snippets;
2
+
3
+ import kd.bos.dataentity.entity.DynamicObject;
4
+ import kd.bos.dataentity.entity.LocaleString;
5
+ import kd.bos.logging.Log;
6
+ import kd.bos.logging.LogFactory;
7
+ import kd.bos.servicehelper.BusinessDataServiceHelper;
8
+ import kd.bos.servicehelper.botp.BFTrackerServiceHelper;
9
+ import kd.bos.servicehelper.operation.SaveServiceHelper;
10
+ import kd.bos.servicehelper.user.UserServiceHelper;
11
+ import kd.bos.servicehelper.workflow.MessageCenterServiceHelper;
12
+ import kd.bos.servicehelper.workflow.WorkflowServiceHelper;
13
+ import kd.bos.workflow.api.AgentExecution;
14
+ import kd.bos.workflow.api.SuspendInfo;
15
+ import kd.bos.workflow.api.constants.WFTaskResultEnum;
16
+ import kd.bos.workflow.component.approvalrecord.IApprovalRecordGroup;
17
+ import kd.bos.workflow.component.approvalrecord.IApprovalRecordItem;
18
+ import kd.bos.workflow.engine.extitf.IWorkflowPlugin;
19
+ import kd.bos.workflow.engine.msg.info.MessageInfo;
20
+ import kd.cd.common.entity.EntityUtils;
21
+ import kd.cd.common.util.DynamicObjectUtils;
22
+
23
+ import java.time.LocalDateTime;
24
+ import java.time.format.DateTimeFormatter;
25
+ import java.util.ArrayList;
26
+ import java.util.Collections;
27
+ import java.util.HashSet;
28
+ import java.util.List;
29
+ import java.util.Map;
30
+ import java.util.stream.Collectors;
31
+
32
+ /**
33
+ * 工作流插件示例 —— IWorkflowPlugin 全场景 Cookbook。
34
+ * <p>
35
+ * 适用插件:工作流插件
36
+ * 优先封装:(暂无 commons 封装)
37
+ * 原生兜底:IWorkflowPlugin、AgentExecution、WorkflowServiceHelper
38
+ * 相关 lint 规则:(暂无)
39
+ * <p>
40
+ * 使用场景:
41
+ * 1. filterParticipant 过滤审批参与人(排除创建人、取上游源单创建人);
42
+ * 2. notify 审批节点回调(审批意见反写、拒绝通知第三方、写流程变量);
43
+ * 3. afterSuspendProcess 流程挂起通知单据创建人;
44
+ * 4. calcUserIds 动态计算审批参与人;
45
+ * 5. hasTrueCondition 条件分支判断;
46
+ * 6. notifyByWithdraw 流程撤回补偿处理;
47
+ * 7. WorkflowServiceHelper 辅助能力速查(inProcess / getAllApprovalRecord)。
48
+ */
49
+ public class SampleWorkflowPlugin implements IWorkflowPlugin {
50
+ private static final Log log = LogFactory.getLog(SampleWorkflowPlugin.class);
51
+
52
+ // ===================================================================
53
+ // 一、filterParticipant —— 过滤/替换审批参与人
54
+ // ===================================================================
55
+
56
+ /**
57
+ * 场景 1:排除单据创建人,避免自己审批自己。
58
+ * <p>
59
+ * AgentExecution 上下文要点:
60
+ * - getBusinessKey() → 单据主键(字符串)
61
+ * - getEntityNumber() → 单据实体编码
62
+ */
63
+ @Override
64
+ public List<Long> filterParticipant(AgentExecution execution, List<Long> userIds) {
65
+ if (userIds == null || userIds.isEmpty()) {
66
+ return userIds;
67
+ }
68
+ String billId = execution.getBusinessKey();
69
+ String entityNum = execution.getEntityNumber();
70
+ DynamicObject bill = BusinessDataServiceHelper.loadSingle(billId, entityNum);
71
+ DynamicObject creator = bill.getDynamicObject("creator");
72
+ Long creatorId = DynamicObjectUtils.nullSafeGet(creator, "id");
73
+ if (EntityUtils.isNotEmptyPk(creatorId)) {
74
+ userIds.remove(creatorId);
75
+ }
76
+ return userIds;
77
+ }
78
+
79
+ // ===================================================================
80
+ // 二、notify —— 审批节点通知回调
81
+ // ===================================================================
82
+
83
+ /**
84
+ * 场景 1:审批意见反写到单据字段。
85
+ * <p>
86
+ * 工作流传参 [nodeName] → 指定反写字段标识。
87
+ * AgentExecution 上下文要点:
88
+ * - getCurrentTaskResult(WFTaskResultEnum.auditMessage) → 审批意见(JSON,含多语言)
89
+ * - getCurrentTaskResult(WFTaskResultEnum.auditName) → 审批动作名称(同意/驳回)
90
+ * - getCurrentTask().getAssigneeId() → 实际审批人 ID
91
+ * - getCurrentWFPluginParams() → 工作流节点上配置的自定义参数
92
+ */
93
+ @Override
94
+ public void notify(AgentExecution execution) {
95
+ // 获取审批意见
96
+ Object approvalObj = execution.getCurrentTaskResult(WFTaskResultEnum.auditMessage);
97
+ if (approvalObj == null) {
98
+ return;
99
+ }
100
+ // 从工作流节点参数中获取需要反写的字段标识
101
+ String nodeName = execution.getCurrentWFPluginParams().get("nodeName").toString();
102
+ String entityName = execution.getEntityNumber();
103
+ String businessKey = execution.getBusinessKey();
104
+
105
+ DynamicObject bill = BusinessDataServiceHelper.loadSingle(businessKey, entityName);
106
+ // 审批人信息
107
+ List<Map<String, Object>> userInfo = UserServiceHelper.get(
108
+ Collections.singletonList(execution.getCurrentTask().getAssigneeId()));
109
+ String approverName = userInfo.get(0).get("name") + "(" + userInfo.get(0).get("number") + ")";
110
+ String approvalTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
111
+
112
+ // 反写到单据
113
+ bill.set(nodeName, "【审批意见】" + approvalObj + "," + approverName + " " + approvalTime + "\n");
114
+ SaveServiceHelper.update(bill);
115
+ }
116
+
117
+ /**
118
+ * 场景 2(替换 notify):审批拒绝后同步通知第三方系统。
119
+ * <p>
120
+ * 通过 WorkflowServiceHelper.getAllApprovalRecord() 获取完整审批记录,
121
+ * 取最后一条记录组的拒绝原因,推送给外部系统。
122
+ */
123
+ private void notifyRejectToThirdParty(AgentExecution execution) {
124
+ String entityNumber = execution.getEntityNumber();
125
+ String businessKey = execution.getBusinessKey();
126
+ if (businessKey == null) {
127
+ return;
128
+ }
129
+ // 获取审批拒绝原因(从完整审批记录中提取)
130
+ StringBuilder rejectReason = getLastApprovalMessage(businessKey);
131
+ log.info("审批拒绝,单据={}, 原因={}", businessKey, rejectReason);
132
+ }
133
+
134
+ /**
135
+ * 从审批记录中获取最后一个节点的审批意见。
136
+ * <p>
137
+ * WorkflowServiceHelper.getAllApprovalRecord(businessKey) → List&lt;IApprovalRecordGroup&gt;
138
+ * IApprovalRecordGroup.getChildren() → List&lt;IApprovalRecordItem&gt;
139
+ * IApprovalRecordItem:getActivityName() / getMessage() / getResult()
140
+ */
141
+ private StringBuilder getLastApprovalMessage(String businessKey) {
142
+ StringBuilder message = new StringBuilder();
143
+ List<IApprovalRecordGroup> allRecords = WorkflowServiceHelper.getAllApprovalRecord(businessKey);
144
+ if (allRecords == null || allRecords.isEmpty()) {
145
+ return message;
146
+ }
147
+ IApprovalRecordGroup lastGroup = allRecords.get(allRecords.size() - 1);
148
+ for (IApprovalRecordItem item : lastGroup.getChildren()) {
149
+ message.append(item.getActivityName())
150
+ .append(":")
151
+ .append(item.getMessage())
152
+ .append(";");
153
+ }
154
+ return message;
155
+ }
156
+
157
+ // ===================================================================
158
+ // 三、afterSuspendProcess —— 流程挂起通知
159
+ // ===================================================================
160
+
161
+ /**
162
+ * 流程异常挂起时,通知单据创建人。
163
+ * <p>
164
+ * SuspendInfo 上下文:
165
+ * - getBusinessKey() → 单据主键
166
+ * - getEntityNumber() → 单据实体编码
167
+ * - getErrMsg() → 挂起错误原因
168
+ * <p>
169
+ * 通知渠道:MessageCenterServiceHelper.sendMessage() → 消息中心 + 云之家
170
+ */
171
+ @Override
172
+ public void afterSuspendProcess(SuspendInfo suspendInfo) {
173
+ try {
174
+ String pk = suspendInfo.getBusinessKey();
175
+ String entityId = suspendInfo.getEntityNumber();
176
+ DynamicObject bill = BusinessDataServiceHelper.loadSingle(pk, entityId);
177
+
178
+ // 获取单据创建人
179
+ DynamicObject creator = bill.getDynamicObject("creator");
180
+ Long userId = DynamicObjectUtils.nullSafeGet(creator, "id");
181
+ if (EntityUtils.isEmptyPk(userId)) {
182
+ log.info("afterSuspendProcess: creator is empty, pk={}", pk);
183
+ return;
184
+ }
185
+ String billNo = bill.getString("billno");
186
+
187
+ // 构建消息
188
+ MessageInfo messageInfo = new MessageInfo();
189
+ LocaleString title = new LocaleString();
190
+ title.setLocaleValue_zh_CN("流程异常挂起");
191
+ LocaleString content = new LocaleString();
192
+ content.setLocaleValue_zh_CN("您的单据编号为" + billNo + "的流程已挂起,请联系系统管理员。\n"
193
+ + "挂起原因:" + suspendInfo.getErrMsg());
194
+
195
+ messageInfo.setMessageTitle(title);
196
+ messageInfo.setMessageContent(content);
197
+ messageInfo.setUserIds(Collections.singletonList(userId));
198
+ messageInfo.setType(MessageInfo.TYPE_WARNING);
199
+ // notifyType:mcenter=消息中心, yunzhijia=云之家, email=邮件
200
+ messageInfo.setNotifyType("mcenter,yunzhijia");
201
+ MessageCenterServiceHelper.batchSendMessages(Collections.singletonList(messageInfo));
202
+ } catch (Exception e) {
203
+ log.warn("流程挂起通知失败", e);
204
+ }
205
+ }
206
+
207
+ // ===================================================================
208
+ // 四、calcUserIds —— 动态计算审批参与人
209
+ // ===================================================================
210
+
211
+ /**
212
+ * 根据单据字段/流程变量动态返回审批人列表。
213
+ * <p>
214
+ * 典型场景:根据单据金额、部门等信息动态决定审批人。
215
+ */
216
+ @Override
217
+ public List<Long> calcUserIds(AgentExecution execution) {
218
+ List<Long> userIds = new ArrayList<>();
219
+ // 方式 1:从流程变量中获取
220
+ Object startUser = execution.getVariable("startUserId");
221
+ if (startUser instanceof Number) {
222
+ userIds.add(((Number) startUser).longValue());
223
+ }
224
+ // 方式 2:从单据数据中获取
225
+ String billId = execution.getBusinessKey();
226
+ String entityNum = execution.getEntityNumber();
227
+ DynamicObject bill = BusinessDataServiceHelper.loadSingle(billId, entityNum);
228
+ DynamicObject approver = bill.getDynamicObject("kdcd_approver");
229
+ if (approver != null) {
230
+ userIds.add(approver.getLong("id"));
231
+ }
232
+ return userIds;
233
+ }
234
+
235
+ // ===================================================================
236
+ // 五、hasTrueCondition —— 条件分支判断
237
+ // ===================================================================
238
+
239
+ /**
240
+ * 根据流程变量或单据字段决定是否命中当前分支。
241
+ * <p>
242
+ * 返回 true → 流程走当前分支;false → 跳过。
243
+ */
244
+ @Override
245
+ public boolean hasTrueCondition(AgentExecution execution) {
246
+ Object amount = execution.getVariable("amount");
247
+ return amount instanceof Number && ((Number) amount).doubleValue() > 100000D;
248
+ }
249
+
250
+ // ===================================================================
251
+ // 六、notifyByWithdraw —— 流程撤回补偿
252
+ // ===================================================================
253
+
254
+ /**
255
+ * 流程撤回时的补偿处理。
256
+ * <p>
257
+ * 注意:notify 和 notifyByWithdraw 应成对设计,保证状态可恢复。
258
+ */
259
+ @Override
260
+ public void notifyByWithdraw(AgentExecution execution) {
261
+ execution.setVariable("lastNodeName", "withdraw");
262
+ // TODO 恢复单据状态或清理之前 notify 写入的数据
263
+ }
264
+
265
+ // ===================================================================
266
+ // 七、formatFlowRecord —— 审批记录格式化
267
+ // ===================================================================
268
+
269
+ /**
270
+ * 定制审批记录的显示文本。
271
+ * <p>
272
+ * IApprovalRecordItem:getActivityName() / getMessage() / getResult() / setMessage(...)
273
+ */
274
+ @Override
275
+ public IApprovalRecordItem formatFlowRecord(IApprovalRecordItem item) {
276
+ // 示例:在审批记录中追加自定义说明
277
+ // item.setMessage(item.getMessage() + " [已同步]");
278
+ return item;
279
+ }
280
+
281
+ // ===================================================================
282
+ // 八、WorkflowServiceHelper 辅助能力速查
283
+ // ===================================================================
284
+
285
+ /**
286
+ * WorkflowServiceHelper 常用静态方法速查。
287
+ * <p>
288
+ * 这些方法不属于 IWorkflowPlugin 接口事件,但在操作插件、表单插件中经常配合使用。
289
+ */
290
+ private void workflowServiceHelperCheatSheet() {
291
+ String billId = "123456";
292
+
293
+ // 1. 判断单据是否在审批流程中(常用于下推前校验)
294
+ boolean inProcess = WorkflowServiceHelper.inProcess(billId);
295
+
296
+ // 2. 获取完整审批记录(常用于拒绝通知、审批意见展示)
297
+ List<IApprovalRecordGroup> records = WorkflowServiceHelper.getAllApprovalRecord(billId);
298
+
299
+ // 3. 激活挂起的流程实例(常用于异常流程巡检任务)
300
+ // WorkflowServiceHelper.revokeSuspendProcessInstancesByProcessInstanceId(processInstanceId);
301
+ }
302
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "ok-cosmic",
3
+ "version": "1.3.0",
4
+ "description": "苍穹开发主 skill,默认优先复用 kd-cd-cosmic-commons 封装,集成离线知识图谱、元数据、基础资料和业务拓展点查询工具。",
5
+ "author": "Cosmic",
6
+ "tools": [
7
+ {
8
+ "name": "cosmic_search_classes",
9
+ "description": "搜索苍穹类名。用法: --config <json> search <keyword...> [--class-prefix <prefix>] [--kind <kind>]",
10
+ "source": "scripts/cosmic-api-knowledge.py"
11
+ },
12
+ {
13
+ "name": "cosmic_search_methods",
14
+ "description": "全局搜索苍穹方法名。用法: --config <json> search-method <keyword...> [--class-prefix <prefix>] [--kind <kind>]",
15
+ "source": "scripts/cosmic-api-knowledge.py"
16
+ },
17
+ {
18
+ "name": "cosmic_get_class_detail",
19
+ "description": "获取类详情并校验方法签名。用法: --config <json> detail <full.class.Name> [--method <keyword>] [--compact] [--declared-only]",
20
+ "source": "scripts/cosmic-api-knowledge.py"
21
+ },
22
+ {
23
+ "name": "cosmic_get_meta_fields",
24
+ "description": "查询表单元数据字段。用法: --config <json> get <formIdOrName> [逗号分隔批量] [--fuzzy <words...>] [--show-detail] [--refresh] [--tree]",
25
+ "source": "scripts/cosmic-form-metadata.py"
26
+ },
27
+ {
28
+ "name": "cosmic_query_basedata",
29
+ "description": "查询基础资料。用法: --config <json> get --entity-id <id> [--number-or-name <kw>] [--full] [--refresh] [--json]。entityId 必须已确认来源,不确定时先用元数据脚本查 refType",
30
+ "source": "scripts/cosmic-basedata-query.py"
31
+ },
32
+ {
33
+ "name": "cosmic_query_extpoints",
34
+ "description": "查询业务拓展点候选。用法: --config <json> get --keyword <kw> [--limit <n>] [--json] [--full]。命中接口类名后继续用 cosmic-api-knowledge.py detail 确认签名",
35
+ "source": "scripts/cosmic-extpoints-query.py"
36
+ },
37
+ {
38
+ "name": "cosmic_post_check",
39
+ "description": "代码生成后统一检查入口。用法: <file_or_dir> [--fix-hint] [--json] [--strict]。Gradle 项目优先编译检查,非 Gradle 回退静态校验(A/B/C 三层)",
40
+ "source": "scripts/cosmic-post-check.py"
41
+ },
42
+ {
43
+ "name": "cosmic_config_check",
44
+ "description": "Step 0 环境与配置预检。用法: [--config <json>] [--strict] [--json]。检查 Python 依赖(自动安装)、Java 环境、ok-cosmic.json 配置完整性",
45
+ "source": "scripts/cosmic-config-check.py"
46
+ }
47
+ ],
48
+ "assets": [
49
+ "assets/BillPlugInTemplate.java",
50
+ "assets/ConvertPlugInTemplate.java",
51
+ "assets/PrintPluginTemplate.java",
52
+ "assets/ReportFormPluginTemplate.java",
53
+ "assets/ReportListDataPluginTemplate.java",
54
+ "assets/TaskTemplate.java",
55
+ "assets/TreeListPluginTemplate.java",
56
+ "assets/WriteBackPlugInTemplate.java",
57
+ "assets/BatchImportPluginTemplate.java",
58
+ "assets/FormPluginTemplate.java",
59
+ "assets/IWorkflowPluginTemplate.java",
60
+ "assets/ListPluginTemplate.java",
61
+ "assets/OpenApiControllerTemplate.java",
62
+ "assets/OpPluginTemplate.java",
63
+ "assets/StandardTreeListPluginTemplate.java",
64
+ "assets/snippets/"
65
+ ],
66
+ "references": [
67
+ "references/adv/",
68
+ "references/base/",
69
+ "rules/"
70
+ ],
71
+ "ignore": [
72
+ ".DS_Store",
73
+ "__pycache__/",
74
+ "*.pyc",
75
+ "setup/**",
76
+ "README.md"
77
+ ]
78
+ }