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.
- package/README.md +358 -0
- package/dist/cli/kcode.d.ts +15 -0
- package/dist/cli/kcode.js +153 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +7 -0
- package/docs/KCODE_DISTRIBUTION.md +91 -0
- package/extensions/kingdee-harness.ts +180 -0
- package/extensions/kingdee-header.ts +122 -0
- package/extensions/kingdee-tools.ts +379 -0
- package/knowledge/.backup/v1.0.0/version.json +10 -0
- package/knowledge/cangqiong/product-notes.md +15 -0
- package/knowledge/common/business-flows.md +115 -0
- package/knowledge/common/config-guides.md +110 -0
- package/knowledge/common/error-patterns.md +170 -0
- package/knowledge/common/implementation.md +144 -0
- package/knowledge/cosmic/hard-constraints.md +38 -0
- package/knowledge/cosmic/ksql-datafix.md +34 -0
- package/knowledge/cosmic/platform-baseline.md +32 -0
- package/knowledge/cosmic/plugin-decision-matrix.md +40 -0
- package/knowledge/cosmic/review-checklist.md +40 -0
- package/knowledge/cosmic/unittest.md +35 -0
- package/knowledge/enterprise/api-reference.md +186 -0
- package/knowledge/enterprise/code-patterns.md +217 -0
- package/knowledge/enterprise/plugin-lifecycle.md +188 -0
- package/knowledge/enterprise/tables.json +159 -0
- package/knowledge/flagship/api-reference.md +237 -0
- package/knowledge/flagship/code-patterns.md +246 -0
- package/knowledge/flagship/cosmic-platform-note.md +15 -0
- package/knowledge/flagship/plugin-lifecycle.md +248 -0
- package/knowledge/flagship/tables.json +159 -0
- package/knowledge/version.json +10 -0
- package/knowledge/xinghan/product-notes.md +15 -0
- package/package.json +71 -0
- package/prompts/kd-discuss.md +11 -0
- package/prompts/kd-execute.md +12 -0
- package/prompts/kd-plan.md +12 -0
- package/prompts/kd-ship.md +12 -0
- package/prompts/kd-spec.md +12 -0
- package/prompts/kd-verify.md +12 -0
- package/skills/kd-check/SKILL.md +26 -0
- package/skills/kd-cosmic-dev/SKILL.md +82 -0
- package/skills/kd-cosmic-review/SKILL.md +90 -0
- package/skills/kd-cosmic-unittest/SKILL.md +92 -0
- package/skills/kd-debug/SKILL.md +30 -0
- package/skills/kd-discuss/SKILL.md +24 -0
- package/skills/kd-execute/SKILL.md +22 -0
- package/skills/kd-gen/SKILL.md +34 -0
- package/skills/kd-ksql/SKILL.md +86 -0
- package/skills/kd-plan/SKILL.md +24 -0
- package/skills/kd-ship/SKILL.md +22 -0
- package/skills/kd-spec/SKILL.md +24 -0
- package/skills/kd-verify/SKILL.md +22 -0
- package/themes/kcode-dark.json +81 -0
- package/vendor/kingdee-skills/cosmic-unittest/SKILL.md +788 -0
- package/vendor/kingdee-skills/cosmic-unittest/author-cache.json +5 -0
- package/vendor/kingdee-skills/cosmic-unittest/cosmic-unittest-skill-overview.html +746 -0
- package/vendor/kingdee-skills/cosmic-unittest/examples/business-test.md +205 -0
- package/vendor/kingdee-skills/cosmic-unittest/examples/common-test.md +257 -0
- package/vendor/kingdee-skills/cosmic-unittest/examples/formplugin-test.md +560 -0
- package/vendor/kingdee-skills/cosmic-unittest/examples/op-plugin-test.md +231 -0
- package/vendor/kingdee-skills/cosmic-unittest/examples/validator-test.md +232 -0
- package/vendor/kingdee-skills/cosmic-unittest/patterns/business-helper.md +184 -0
- package/vendor/kingdee-skills/cosmic-unittest/patterns/common-module.md +355 -0
- package/vendor/kingdee-skills/cosmic-unittest/patterns/convert-plugin.md +130 -0
- package/vendor/kingdee-skills/cosmic-unittest/patterns/formplugin.md +235 -0
- package/vendor/kingdee-skills/cosmic-unittest/patterns/op-plugin.md +226 -0
- package/vendor/kingdee-skills/cosmic-unittest/patterns/validator.md +206 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/SKILL.md +674 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/advanced-scenario-checklist.md +307 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/algox-performance-checklist.md +129 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/coding-standard-checklist.md +491 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/cosmic-api-checklist.md +285 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/data-access-checklist.md +261 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/data-transaction-checklist.md +390 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/domain-logic-checklist.md +295 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/form-plugin-checklist.md +508 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/infra-checklist.md +254 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/ksql-checklist.md +305 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/lifecycle-checklist.md +298 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/operation-plugin-checklist.md +442 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/test-mock-checklist.md +120 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/references/ui-performance-checklist.md +320 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/pattern-matcher.py +336 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/review-score-calculator.py +121 -0
- package/vendor/kingdee-skills/ok-cosmic/CHANGELOG.md +295 -0
- package/vendor/kingdee-skills/ok-cosmic/README.md +460 -0
- package/vendor/kingdee-skills/ok-cosmic/SKILL.md +287 -0
- package/vendor/kingdee-skills/ok-cosmic/agents/openai.yaml +17 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/BatchImportPluginTemplate.java +93 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/BillPlugInTemplate.java +156 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/ConvertPlugInTemplate.java +255 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/FormPluginTemplate.java +597 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/IWorkflowPluginTemplate.java +91 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/ListPluginTemplate.java +194 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/OpPluginTemplate.java +201 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/OpenApiControllerTemplate.java +103 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/PrintPluginTemplate.java +95 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/ReportFormPluginTemplate.java +257 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/ReportListDataPluginTemplate.java +70 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/StandardTreeListPluginTemplate.java +130 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/TaskTemplate.java +80 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/TreeListPluginTemplate.java +152 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/WriteBackPlugInTemplate.java +286 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/attachment/AttachmentUploadBindSample.java +93 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/botp/BotpTracePushSample.java +168 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/botp/SampleConvertPlugin.java +223 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/cache/SampleCacheUsage.java +218 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/concurrent/SampleThreadPoolBatch.java +156 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/data/DynamicObjectCrudSample.java +205 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/data/DynamicObjectOpsSample.java +100 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/BeforeOperationConfirmSample.java +217 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ConfirmDialogSample.java +131 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/EntryRowCalculateSample.java +116 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/F7FilterSample.java +134 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/GetAndSetValueSample.java +176 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/HyperlinkJumpSample.java +124 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/OpenBillModalSample.java +253 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ReturnParentDataSample.java +295 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/TreeControlSample.java +140 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/form/ViewControlOpsSample.java +132 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/list/ListPluginBasicSample.java +170 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/list/ListPreOpenFilterSample.java +68 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/message/MessageNotifySample.java +95 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/mq/SampleMQConsumer.java +198 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/mq/sample_mq.xml +15 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/operation/OpAddValidatorsSample.java +137 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/operation/OperationOptionBridgeSample.java +228 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/package-info.java +19 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/BaseDataQuerySample.java +194 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/BatchQuerySample.java +368 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/query/DataSetQueryStatSample.java +131 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/report/SampleReportFormPlugin.java +179 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/report/SampleReportListDataPlugin.java +616 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/snippets-guide.md +64 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/task/ScheduleTaskSample.java +160 -0
- package/vendor/kingdee-skills/ok-cosmic/assets/snippets/workflow/SampleWorkflowPlugin.java +302 -0
- package/vendor/kingdee-skills/ok-cosmic/manifest.json +78 -0
- package/vendor/kingdee-skills/ok-cosmic/ok-cosmic-intro.html +903 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/attachment-api.md +114 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/botp-convert.md +98 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/dynamic-object.md +113 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/entity-metadata.md +123 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/event-lifecycle.md +184 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/flex-prop.md +114 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/form-utils.md +133 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/operate-chain.md +159 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/plugin-base.md +218 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/query-dataset.md +149 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/request-context.md +88 -0
- package/vendor/kingdee-skills/ok-cosmic/references/adv/view-handler.md +157 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-bill.md +76 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-botp.md +70 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-form.md +165 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-import.md +69 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-list.md +227 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-openapi.md +112 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-operation.md +135 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-print.md +65 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-report-data.md +64 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-report-form.md +90 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-task.md +62 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-tree-list.md +71 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-workflow.md +82 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/plugin/plugin-writeback.md +71 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-algo.md +67 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-cache.md +63 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-dynamic-model-svc.md +82 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-dynamic-object.md +70 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-entity-model.md +61 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-exception.md +64 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-file.md +63 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-id.md +47 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-lock.md +61 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-log.md +63 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-network-control.md +70 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-orm-access.md +78 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-request-context.md +62 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-threadpool.md +63 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-tx.md +64 -0
- package/vendor/kingdee-skills/ok-cosmic/references/base/sdk/sdk-utils.md +67 -0
- package/vendor/kingdee-skills/ok-cosmic/requirements.txt +2 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/a-layer-rules.json +24 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/anti-patterns.md +48 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/cheat-sheet.md +256 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/coding-preferences.md +140 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/constraints.md +61 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/decision-matrix.md +222 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/intent-routing.md +94 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/platform-baseline.md +69 -0
- package/vendor/kingdee-skills/ok-cosmic/rules/post-check.md +109 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/config_loader.py +204 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-api-knowledge.py +910 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-basedata-query.py +359 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-config-check.py +181 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-extpoints-query.py +389 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-form-metadata.py +856 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-check.py +262 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-lint.py +293 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/__init__.py +2 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/base.py +393 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/resource_check.py +176 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/scene_check.py +375 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/style_check.py +434 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/verify_check.py +36 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/route_client.py +186 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/script_utils.py +40 -0
- package/vendor/kingdee-skills/ok-cosmic/scripts/sqlite_cache.py +142 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-commons.jar +0 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-features.jar +0 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/ok-cosmic-docs.db +0 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/ok-cosmic.json +13 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/setup-mac.sh +18 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/setup-windows.bat +53 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/setup.jar +0 -0
- package/vendor/kingdee-skills/ok-ksql/SKILL.md +81 -0
- package/vendor/kingdee-skills/ok-ksql/agents/openai.yaml +7 -0
- package/vendor/kingdee-skills/ok-ksql/manifest.json +14 -0
- package/vendor/kingdee-skills/ok-ksql/references/ksql-datafix.md +452 -0
- package/vendor/kingdee-skills/ok-ksql/scripts/ksql_lint.py +363 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 网络控制 (Data Mutex / NetCtrl)
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
- 适用:单据/数据的网控互斥,避免多人同时编辑或冲突操作。
|
|
5
|
+
- 先抓:`DataMutex` + `MutexLockInfo`,先区分功能互斥和数据互斥。
|
|
6
|
+
- 跳转:跨服务通用资源锁不是网控,去 `sdk-lock.md`。
|
|
7
|
+
- 继续读全文:当你要批量申请网控、读取锁信息或处理释放时。
|
|
8
|
+
|
|
9
|
+
## 概述
|
|
10
|
+
网络控制(也称网控或互斥锁)用于解决多用户并发操作同一单据时产生的数据冲突问题。它主要分为**功能互斥**(如审核时禁止编辑)和**数据互斥**(如同一单据禁止两人同时修改)。
|
|
11
|
+
|
|
12
|
+
## 核心类
|
|
13
|
+
- **`kd.bos.mutex.DataMutex`**: 网控核心接口类(支持 AutoCloseable)。
|
|
14
|
+
- **`kd.bos.form.operate.MutexHelper`**: 网控操作帮助类。
|
|
15
|
+
- **`kd.bos.mutex.MutexLockInfo`**: 定义锁的具体信息(实体、主键、操作标识等)。
|
|
16
|
+
|
|
17
|
+
## 常用 API 方法
|
|
18
|
+
### 1. 申请网控
|
|
19
|
+
- `DataMutex.create().require(MutexLockInfo info)`: 申请单条数据的网控锁。
|
|
20
|
+
- `batchrequire(List<Map<String, Object>> data)`: 批量申请网控。
|
|
21
|
+
|
|
22
|
+
### 2. 释放网控
|
|
23
|
+
- `release(String objId, String entityKey, String operationKey)`: 释放单条网控。
|
|
24
|
+
- `batchRelease(List<Map<String, Object>> data)`: 批量释放。
|
|
25
|
+
|
|
26
|
+
### 3. 获取锁信息
|
|
27
|
+
- `getLockInfo(String objId, String groupId, String entityKey)`: 查询当前数据被谁锁定。
|
|
28
|
+
|
|
29
|
+
## 示例代码
|
|
30
|
+
```java
|
|
31
|
+
import kd.bos.mutex.DataMutex;
|
|
32
|
+
import kd.bos.mutex.MutexLockInfo;
|
|
33
|
+
|
|
34
|
+
public void doTaskWithMutex(String billId) {
|
|
35
|
+
// 1. 创建网控对象(使用 try-with-resources 自动管理)
|
|
36
|
+
try (DataMutex mutex = DataMutex.create()) {
|
|
37
|
+
// 2. 定义锁信息
|
|
38
|
+
MutexLockInfo lockInfo = new MutexLockInfo();
|
|
39
|
+
lockInfo.setDataObjId(billId);
|
|
40
|
+
lockInfo.setEntityKey("my_entity_id");
|
|
41
|
+
lockInfo.setOperationKey("submit");
|
|
42
|
+
lockInfo.setGroupId("default_netctrl"); // 默认互斥组
|
|
43
|
+
|
|
44
|
+
// 3. 申请锁
|
|
45
|
+
if (mutex.require(lockInfo)) {
|
|
46
|
+
try {
|
|
47
|
+
// 执行核心业务逻辑
|
|
48
|
+
process();
|
|
49
|
+
} finally {
|
|
50
|
+
// 4. 显式释放(重要)
|
|
51
|
+
mutex.release(billId, "my_entity_id", "submit");
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
throw new KDBizException("单据已被其他用户锁定,请稍后重试");
|
|
55
|
+
}
|
|
56
|
+
} catch (Exception e) {
|
|
57
|
+
logger.error("网控异常", e);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 实践建议
|
|
63
|
+
1. **自动释放**:始终使用 `try-with-resources` 语法创建 `DataMutex` 实例,以确保底层连接被正确关闭。
|
|
64
|
+
2. **细粒度控制**:合理利用 `groupId`。如果希望你的逻辑不与系统标准操作冲突,可以自定义 `groupId`。
|
|
65
|
+
3. **友好提示**:申请锁失败时,建议调用 `getLockInfo` 并将占用者的信息提示给用户。
|
|
66
|
+
|
|
67
|
+
## 常见坑位
|
|
68
|
+
1. **死锁风险**:严禁在持有锁的过程中执行超长时间的同步等待(如调用外系统 API),这会导致单据被长时间锁定无法操作。
|
|
69
|
+
2. **忘记释放**:手动调用的 `require` **必须**有对应的 `release` 调用,否则该单据可能一直处于“锁定中”状态,直到用户 Session 超时。
|
|
70
|
+
3. **同用户重入**:默认情况下,同用户多次申请同一把锁是允许的(可重入),但需注意逻辑闭环。
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# ORM 与查询 (QFilter / KSQL)
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
- 适用:原生 ORM、`QFilter`、KSQL、`DBRoute` 查询写法和底层 DB 路由。
|
|
5
|
+
- 先抓:优先 ORM + `QFilter`,只有表达不了再下沉到 KSQL 或 SQL。
|
|
6
|
+
- 跳转:团队封装查询优先读 `adv/query-dataset.md`;精确签名必须走脚本验证。
|
|
7
|
+
- 继续读全文:当你要写复杂过滤、KSQL 更新或跨库路由逻辑时。
|
|
8
|
+
|
|
9
|
+
金蝶云苍穹提供了强大的 ORM 引擎和基于 KSQL 的查询能力。
|
|
10
|
+
|
|
11
|
+
**注意:** 仅展示核心查询模式与最佳实践。如需查询 `ORM`、`QFilter` 或 `DBServiceHelper` 的完整方法列表、准确参数签名,**请务必使用 `cosmic_get_class_detail(classname="<类名>")` 工具查询。**
|
|
12
|
+
|
|
13
|
+
## 1. ORM 查询基础 (ORM / QFilter)
|
|
14
|
+
|
|
15
|
+
### 核心查询模式
|
|
16
|
+
```java
|
|
17
|
+
import kd.bos.orm.ORM;
|
|
18
|
+
import kd.bos.orm.query.QFilter;
|
|
19
|
+
import kd.bos.orm.query.QCP;
|
|
20
|
+
|
|
21
|
+
ORM orm = ORM.create();
|
|
22
|
+
|
|
23
|
+
// 1. 查询单条记录 (返回 DynamicObject)
|
|
24
|
+
DynamicObject obj = orm.queryOne("entity_name", new QFilter[]{filter});
|
|
25
|
+
|
|
26
|
+
// 2. 查询集合 (返回 DynamicObjectCollection)
|
|
27
|
+
DynamicObjectCollection coll = orm.query("entity_name", fields, new QFilter[]{filter});
|
|
28
|
+
|
|
29
|
+
// 3. 流式查询 (推荐,返回 DataSet)
|
|
30
|
+
DataSet ds = orm.queryDataSet("algo_key", "entity_name", fields, new QFilter[]{filter}, "id desc");
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### QFilter 常用操作符 (QCP)
|
|
34
|
+
- **基本比较**: `equals`, `not_equals`, `large_than`, `less_than`, `large_equals`, `less_equals`
|
|
35
|
+
- **集合/范围**: `in`, `not_in`, `between`
|
|
36
|
+
- **模糊匹配**: `like` (自动补 `%`), `not_like`
|
|
37
|
+
|
|
38
|
+
### 复杂条件组合
|
|
39
|
+
```java
|
|
40
|
+
QFilter f1 = new QFilter("status", QCP.equals, "C");
|
|
41
|
+
QFilter f2 = new QFilter("amt", QCP.large_than, 100);
|
|
42
|
+
|
|
43
|
+
// AND 组合
|
|
44
|
+
QFilter combined = f1.and(f2);
|
|
45
|
+
// OR 组合
|
|
46
|
+
QFilter combinedOr = f1.or(new QFilter("type", QCP.equals, "A"));
|
|
47
|
+
|
|
48
|
+
// 链式调用
|
|
49
|
+
QFilter finalFilter = QFilter.of("status = 'C'").and("amt > 1000");
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 2. KSQL 与原生 SQL (DBServiceHelper)
|
|
53
|
+
|
|
54
|
+
用于执行复杂的、非 ORM 能够表达的 SQL 逻辑。
|
|
55
|
+
|
|
56
|
+
### 核心方法
|
|
57
|
+
- **KSQL 查询**: `DBServiceHelper.executeQuery(algoKey, ksql, params)` -> 返回 `DataSet`
|
|
58
|
+
- **KSQL 更新**: `DBServiceHelper.executeUpdate(ksql, params)` (慎用,优先用 `SaveServiceHelper`)
|
|
59
|
+
|
|
60
|
+
### 底层 DB 路由 (DB / DBRoute)
|
|
61
|
+
用于跨库访问或需要使用数据库方言 (`/*dialect*/`) 的场景。
|
|
62
|
+
```java
|
|
63
|
+
import kd.bos.db.DB;
|
|
64
|
+
import kd.bos.db.DBRoute;
|
|
65
|
+
|
|
66
|
+
DB.execute(DBRoute.of("route_key"), "/*dialect*/update t_table set fstatus='C' where fid=?", params);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 3. 开发建议 (Best Practices)
|
|
70
|
+
|
|
71
|
+
1. **优先使用 QFilter**:避免手写 SQL 字符串拼接,防止 SQL 注入并确保跨数据库兼容性。
|
|
72
|
+
2. **字段按需加载**:严禁在 `query` 中使用 `*` 或加载不必要的字段,以节省内存。
|
|
73
|
+
3. **关联查询技巧**:
|
|
74
|
+
- 访问基础资料属性:`new QFilter("customer.number", QCP.like, "C%")`
|
|
75
|
+
- 访问单据体字段:`new QFilter("entryentity.material", QCP.equals, mid)`
|
|
76
|
+
4. **性能预警**:避免在 `QFilter` 中使用大量的 `OR` 条件或复杂的子查询,这可能导致索引失效。
|
|
77
|
+
5. **资源关闭**:通过 `orm.queryDataSet` 或 `DBServiceHelper.executeQuery` 获取的 `DataSet` **必须**及时关闭。
|
|
78
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 请求上下文 (Request Context)
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
- 适用:查看当前线程里的用户、租户、组织和语言等上下文字段。
|
|
5
|
+
- 先抓:`RequestContext.get()` 只解决“读取上下文”,不解决跨线程传播。
|
|
6
|
+
- 跳转:异步/后台线程恢复上下文优先读 `adv/request-context.md` 或线程池文档。
|
|
7
|
+
- 继续读全文:当你要手动传递上下文、读组织/语种信息或排查线程问题时。
|
|
8
|
+
|
|
9
|
+
## 概述
|
|
10
|
+
`RequestContext` 保存了当前请求线程关联的租户、账套、用户信息及登录环境。它是苍穹平台识别“我是谁”、“我在哪”的核心依据,贯穿了从前端请求到后台服务调用的全生命周期。
|
|
11
|
+
|
|
12
|
+
## 核心类
|
|
13
|
+
- **`kd.bos.context.RequestContext`**: 请求上下文的核心工具类。
|
|
14
|
+
|
|
15
|
+
## 常用 API 方法
|
|
16
|
+
- `RequestContext.get()`: 获取当前线程绑定的上下文对象。
|
|
17
|
+
- `getCurrUserId()` / `getUid()`: 获取当前登录用户的 ID。
|
|
18
|
+
- `getUserName()`: 获取用户姓名。
|
|
19
|
+
- `getTenantId()` / `getAccountId()`: 获取租户 ID 和账套 ID。
|
|
20
|
+
- `getOrgId()`: 获取当前用户登录时选中的组织 ID。
|
|
21
|
+
- `getLocale()` / `getLang()`: 获取当前语种(如 `zh_CN`)。
|
|
22
|
+
|
|
23
|
+
## 示例代码
|
|
24
|
+
### 1. 基础信息获取
|
|
25
|
+
```java
|
|
26
|
+
import kd.bos.context.RequestContext;
|
|
27
|
+
|
|
28
|
+
public void bizMethod() {
|
|
29
|
+
RequestContext ctx = RequestContext.get();
|
|
30
|
+
long userId = ctx.getCurrUserId();
|
|
31
|
+
long orgId = ctx.getOrgId();
|
|
32
|
+
String accountId = ctx.getAccountId();
|
|
33
|
+
// 执行基于当前身份的逻辑...
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. 跨线程手动传递 (不推荐,优先用线程池)
|
|
38
|
+
```java
|
|
39
|
+
// 复制当前上下文
|
|
40
|
+
RequestContext copiedCtx = RequestContext.copy(RequestContext.get());
|
|
41
|
+
|
|
42
|
+
new Thread(() -> {
|
|
43
|
+
try {
|
|
44
|
+
// 在新线程中绑定上下文
|
|
45
|
+
RequestContext.set(copiedCtx);
|
|
46
|
+
// 执行逻辑...
|
|
47
|
+
} finally {
|
|
48
|
+
// 务必清理,防止干扰后续任务
|
|
49
|
+
RequestContext.remove();
|
|
50
|
+
}
|
|
51
|
+
}).start();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 实践建议
|
|
55
|
+
1. **优先使用平台线程池**:手动使用 `RequestContext.copy` 极易出错,推荐使用 `ThreadPools.executeOnceIncludeRequestContext`,平台会自动处理上下文克隆。
|
|
56
|
+
2. **严禁共用实例**:跨线程传递时**必须调用 `copy()`**,严禁直接 `set(originalCtx)`,否则会导致调用链监控数据混乱。
|
|
57
|
+
3. **及时清理**:如果手动调用了 `RequestContext.set()`,务必在 `finally` 块中执行 `remove()`。
|
|
58
|
+
|
|
59
|
+
## 常见坑位
|
|
60
|
+
1. **异步线程失效**:在普通异步线程或 MQ 消费者中,直接调用 `RequestContext.get()` 返回的是空对象或默认对象,导致 `userId` 为 0 或数据库操作无权限。
|
|
61
|
+
2. **内存泄露**:频繁在非平台托管线程中 `set` 而不 `remove`,会导致 `ThreadLocal` 变量不断堆积。
|
|
62
|
+
3. **调用链污染**:若直接复用原线程的 `RequestContext` 实例,多个并发线程会共享同一个 `traceId`,导致日志追踪无法区分。
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 线程池 (Unified Thread Pool)
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
- 适用:平台统一线程池和携带 `RequestContext` 的异步任务执行。
|
|
5
|
+
- 先抓:优先用平台线程池 API,不要直接 new JDK 线程池。
|
|
6
|
+
- 跳转:只是恢复上下文本身看 `adv/request-context.md`;定时作业则看 `plugin-task.md`。
|
|
7
|
+
- 继续读全文:当你要创建线程池、提交任务或处理返回值/上下文传递时。
|
|
8
|
+
|
|
9
|
+
## 概述
|
|
10
|
+
苍穹平台提供了统一的线程池管理机制,用于替代原生的 JDK 线程池。使用平台线程池可以确保线程生命周期的安全管理、自动清理线程变量,并支持将 `RequestContext` (请求上下文) 自动传递到异步线程中。
|
|
11
|
+
|
|
12
|
+
## 核心类
|
|
13
|
+
- **`kd.bos.threads.ThreadPools`**: 获取和创建线程池的工厂类。
|
|
14
|
+
- **`kd.bos.threads.ThreadPool`**: 平台封装的线程池接口。
|
|
15
|
+
|
|
16
|
+
## 常用 API 方法
|
|
17
|
+
### 快速执行
|
|
18
|
+
- `executeOnceIncludeRequestContext(String name, Runnable runnable)`: 携带当前上下文执行一次异步任务。
|
|
19
|
+
|
|
20
|
+
### 创建线程池
|
|
21
|
+
- `newCachedThreadPool(String name, int coreSize, int maxSize)`: 创建可缓存线程池。
|
|
22
|
+
- `newFixedThreadPool(String name, int size)`: 创建固定大小线程池。
|
|
23
|
+
|
|
24
|
+
### 提交任务
|
|
25
|
+
- `execute(Runnable task)`: 提交任务。
|
|
26
|
+
- `executeIncludeRequestContext(Runnable task)`: 提交任务并携带上下文。
|
|
27
|
+
- `submit(Callable<T> task)`: 提交带返回值的任务。
|
|
28
|
+
|
|
29
|
+
## 示例代码
|
|
30
|
+
```java
|
|
31
|
+
import kd.bos.threads.ThreadPool;
|
|
32
|
+
import kd.bos.threads.ThreadPools;
|
|
33
|
+
|
|
34
|
+
public class ThreadDemo {
|
|
35
|
+
// 1. 建议将线程池定义为静态常量(全局共享)
|
|
36
|
+
private static final ThreadPool pool = ThreadPools.newFixedThreadPool("MyBizPool", 5);
|
|
37
|
+
|
|
38
|
+
public void runAsyncTask() {
|
|
39
|
+
// 2. 提交携带上下文的异步任务
|
|
40
|
+
pool.executeIncludeRequestContext(() -> {
|
|
41
|
+
// 在此异步线程中可以正常调用 RequestContext.get()
|
|
42
|
+
doComplexBusiness();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public void runOnce() {
|
|
47
|
+
// 3. 简单场景:单次快速异步
|
|
48
|
+
ThreadPools.executeOnceIncludeRequestContext("SingleTask", () -> {
|
|
49
|
+
log.info("异步执行中...");
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 实践建议
|
|
56
|
+
1. **优先携带上下文**:在业务逻辑中,务必使用 `xxxIncludeRequestContext` 系列方法,否则异步线程中无法获取用户信息、账套信息及进行数据库操作。
|
|
57
|
+
2. **全局化维护**:线程池应作为类的静态成员变量,严禁在方法内部频繁创建和关闭线程池。
|
|
58
|
+
3. **命名规范**:创建线程池时必须指定有业务语义的 `name`,以便在 `monitor` 监控中定位问题。
|
|
59
|
+
|
|
60
|
+
## 常见坑位
|
|
61
|
+
1. **直接 new Thread**:严禁在代码中直接使用 `new Thread().start()`,这会导致上下文丢失且线程不可控。
|
|
62
|
+
2. **拒绝策略**:平台线程池对阻塞队列做了优化,默认不会丢失任务,但在高负载下可能会阻塞提交线程,需注意响应时间。
|
|
63
|
+
3. **内存泄露**:虽然平台会自动清理线程变量,但如果在异步线程中使用 `ThreadLocal` 存储了大对象且未手动移除,仍存在泄露风险。
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 分布式事务 (Distributed Transaction / KDTX)
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
- 适用:分布式事务、最终一致性、TCC 和本地事务控制。
|
|
5
|
+
- 先抓:默认优先最终一致性模式,本地 `TX` 只解决单库事务。
|
|
6
|
+
- 跳转:普通单据操作别过度上升到 KDTX,先判断是否真的跨服务或跨库。
|
|
7
|
+
- 继续读全文:当你要注册一致性任务、写 TCC 或控制本地事务边界时。
|
|
8
|
+
|
|
9
|
+
## 概述
|
|
10
|
+
KDTX (Kingdee Distributed Transaction) 是苍穹平台提供的分布式事务解决方案,主要用于解决跨微服务、跨数据库操作时的数据一致性问题。它支持“最终一致性”和“TCC”两种核心模式。
|
|
11
|
+
|
|
12
|
+
## 核心类
|
|
13
|
+
- **`kd.bos.kdtx.sdk.api.EventualConsistencyService`**: 最终一致性服务基类。
|
|
14
|
+
- **`kd.bos.kdtx.sdk.api.TCCService`**: TCC 模式服务基类。
|
|
15
|
+
- **`kd.bos.db.tx.TX`**: 本地数据库事务控制工具。
|
|
16
|
+
|
|
17
|
+
## 常用 API 方法
|
|
18
|
+
### 1. 最终一致性模式 (推荐)
|
|
19
|
+
- `EventualConsistencyService.register(Class<? extends EventualConsistencyService> clazz)`: 注册异步执行任务。
|
|
20
|
+
- `addProperty(String key, Object value)`: 传递业务参数。
|
|
21
|
+
|
|
22
|
+
### 2. 本地事务控制
|
|
23
|
+
- `TX.required()`: 如果当前没有事务,则开启一个新事务;如果有,则加入。
|
|
24
|
+
- `txHandle.commit()`: 提交事务。
|
|
25
|
+
|
|
26
|
+
## 示例代码
|
|
27
|
+
### 实现最终一致性服务
|
|
28
|
+
```java
|
|
29
|
+
import kd.bos.kdtx.sdk.api.EventualConsistencyService;
|
|
30
|
+
|
|
31
|
+
// 1. 定义任务逻辑
|
|
32
|
+
public class MySyncTask extends EventualConsistencyService {
|
|
33
|
+
@Override
|
|
34
|
+
public void invoke() throws Exception {
|
|
35
|
+
String billNo = (String) this.getProperty("billno");
|
|
36
|
+
// 执行具体的跨系统同步逻辑...
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 2. 在主业务逻辑中注册
|
|
41
|
+
public void auditBill(DynamicObject bill) {
|
|
42
|
+
try (TXHandle tx = TX.required()) {
|
|
43
|
+
// 修改本地状态
|
|
44
|
+
bill.set("status", "C");
|
|
45
|
+
SaveServiceHelper.update(bill);
|
|
46
|
+
|
|
47
|
+
// 注册异步同步任务(本地事务提交后才会真正触发执行)
|
|
48
|
+
EventualConsistencyService.register(MySyncTask.class)
|
|
49
|
+
.addProperty("billno", bill.getString("billno"));
|
|
50
|
+
|
|
51
|
+
tx.commit();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 实践建议
|
|
57
|
+
1. **优先最终一致性**:绝大多数业务场景(如发邮件、同步第三方接口)建议使用最终一致性模式,以保证主流程的响应速度和高可用。
|
|
58
|
+
2. **幂等性要求**:分布式事务任务可能会因网络波动而重试,`invoke()` 方法内部逻辑**必须**实现幂等。
|
|
59
|
+
3. **事务范围最小化**:不要在事务块(`TX.required`)中放置耗时的网络 IO 操作。
|
|
60
|
+
|
|
61
|
+
## 常见坑位
|
|
62
|
+
1. **参数序列化**:通过 `addProperty` 传递的对象必须支持序列化(基础类型或 DynamicObject)。
|
|
63
|
+
2. **事务嵌套风险**:注意 `TX.required` 与外部事务的交互,避免产生意料之外的回滚。
|
|
64
|
+
3. **异常处理**:`invoke()` 方法抛出异常会导致 KDTX 框架自动重试,请确保异常捕获的准确性。
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# 基础工具类 (DataEntity Utils)
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
- 适用:`StringUtils`、`DateUtils`、`CollectionUtils`、`SerializationUtils` 等基础工具。
|
|
5
|
+
- 先抓:优先平台自带空安全工具,少混入第三方同名工具导致风格不一。
|
|
6
|
+
- 跳转:业务对象处理不是本页;`DynamicObject`、查询、元数据分别看专题文档。
|
|
7
|
+
- 继续读全文:当你要查字符串、日期、集合、JSON 的常用方法和示例时。
|
|
8
|
+
|
|
9
|
+
## 概述
|
|
10
|
+
苍穹平台在 `kd.bos.dataentity.utils` 包下提供了一系列高性能、Null 安全的工具类,用于处理字符串、日期、集合及 JSON 序列化。在业务开发中,应优先使用这些工具类而非原生 JDK 或第三方库。
|
|
11
|
+
|
|
12
|
+
## 核心类
|
|
13
|
+
- **`kd.bos.dataentity.utils.StringUtils`**: 字符串处理工具。
|
|
14
|
+
- **`kd.bos.dataentity.utils.DateUtils`**: 日期计算与格式化工具。
|
|
15
|
+
- **`kd.bos.dataentity.utils.CollectionUtils`**: 集合操作工具。
|
|
16
|
+
- **`kd.bos.dataentity.serialization.SerializationUtils`**: JSON 序列化工具。
|
|
17
|
+
|
|
18
|
+
## 常用 API 方法
|
|
19
|
+
### 1. 字符串 (StringUtils)
|
|
20
|
+
- `isBlank(String str)` / `isNotBlank(String str)`: Null 安全的空白检查。
|
|
21
|
+
- `equals(String str1, String str2)`: 避免 NPE 的相等比较。
|
|
22
|
+
- `join(Iterable<?> iterable, String separator)`: 字符串拼接。
|
|
23
|
+
|
|
24
|
+
### 2. 日期 (DateUtils)
|
|
25
|
+
- `format(Date date, String pattern)`: 日期格式化。
|
|
26
|
+
- `parseDate(String str, String pattern)`: 日期解析。
|
|
27
|
+
- `addDays(Date date, int amount)`: 日期加减计算。
|
|
28
|
+
|
|
29
|
+
### 3. 集合 (CollectionUtils)
|
|
30
|
+
- `isEmpty(Collection<?> coll)`: Null 安全的判空。
|
|
31
|
+
- `partition(List<T> list, int size)`: 将大列表拆分为固定大小的子列表(分批处理利器)。
|
|
32
|
+
|
|
33
|
+
### 4. JSON 序列化 (SerializationUtils)
|
|
34
|
+
- `toJsonString(Object obj)`: 对象转 JSON。
|
|
35
|
+
- `fromJsonString(String json, Class<T> clazz)`: JSON 转对象。
|
|
36
|
+
|
|
37
|
+
## 示例代码
|
|
38
|
+
```java
|
|
39
|
+
import kd.bos.dataentity.utils.StringUtils;
|
|
40
|
+
import kd.bos.dataentity.utils.CollectionUtils;
|
|
41
|
+
import java.util.List;
|
|
42
|
+
|
|
43
|
+
public class UtilsDemo {
|
|
44
|
+
public void processData(String input, List<Long> ids) {
|
|
45
|
+
// 1. 字符串检查
|
|
46
|
+
if (StringUtils.isBlank(input)) { return; }
|
|
47
|
+
|
|
48
|
+
// 2. 集合分批处理(每 100 条一批)
|
|
49
|
+
if (CollectionUtils.isNotEmpty(ids)) {
|
|
50
|
+
List<List<Long>> batches = CollectionUtils.partition(ids, 100);
|
|
51
|
+
for (List<Long> batch : batches) {
|
|
52
|
+
doBatchUpdate(batch);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 实践建议
|
|
60
|
+
1. **Null 安全第一**:凡是涉及外部输入(如界面字段、API 入参)的变量,建议一律通过 `StringUtils.isNotBlank` 或 `CollectionUtils.isEmpty` 进行预检。
|
|
61
|
+
2. **格式统一**:日期格式化建议统一使用 `DateUtils.format`,以保证在不同时区环境下的表现一致。
|
|
62
|
+
3. **避免重复造轮子**:在手写复杂的字符串截取或集合合并逻辑前,先查阅上述工具类的 API。
|
|
63
|
+
|
|
64
|
+
## 常见坑位
|
|
65
|
+
1. **混用包名**:注意 `StringUtils` 存在于多个包中(如 Apache Commons, Spring),苍穹开发务必认准 `kd.bos.dataentity.utils`。
|
|
66
|
+
2. **JSON 性能**:`SerializationUtils` 内部基于 FastJson,对于极高性能要求的场景,注意大对象的序列化开销。
|
|
67
|
+
3. **DateUtils 偏移**:日期加减时,注意 `amount` 参数的正负值含义。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "A 层硬约束规则 ID 列表(单一可信源)。cosmic-post-lint.py 和 post-check.md 共同引用此文件。",
|
|
3
|
+
"a_layer_rule_ids": [
|
|
4
|
+
"SCENE-001",
|
|
5
|
+
"SCENE-002",
|
|
6
|
+
"SCENE-006",
|
|
7
|
+
"SCENE-007",
|
|
8
|
+
"SCENE-008",
|
|
9
|
+
"SCENE-009",
|
|
10
|
+
"SCENE-010",
|
|
11
|
+
"SCENE-012",
|
|
12
|
+
"STYLE-009",
|
|
13
|
+
"STYLE-011",
|
|
14
|
+
"STYLE-012",
|
|
15
|
+
"STYLE-014",
|
|
16
|
+
"STYLE-015",
|
|
17
|
+
"STYLE-016",
|
|
18
|
+
"STYLE-018",
|
|
19
|
+
"STYLE-022",
|
|
20
|
+
"STYLE-023",
|
|
21
|
+
"STYLE-024",
|
|
22
|
+
"RESOURCE-004"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 禁忌清单 (Anti-Patterns)
|
|
2
|
+
|
|
3
|
+
> 本文件为禁忌清单;其中 `scene_check.py`(SCENE-\*)对应的场景错配条目会被自动检测。
|
|
4
|
+
> 幻觉方法名/类名黑名单用于事前人工/AI 自检,`hal_check.py` 与 `HAL-*` 事后 lint 规则已废弃。
|
|
5
|
+
> 场景错配条目默认属于 **A 层硬约束**,除非单独标注 `[B层]`。
|
|
6
|
+
> 编码风格(STYLE-\*)和资源管理(RESOURCE-\*)规则见 [coding-preferences.md](coding-preferences.md)。
|
|
7
|
+
|
|
8
|
+
## 幻觉方法名黑名单 `[事前自检]`
|
|
9
|
+
|
|
10
|
+
| 错误写法 | 正确替代 | 说明 |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `setReadOnly(...)` | `getView().setEnable(false, "key")` | 苍穹不存在 setReadOnly 方法 |
|
|
13
|
+
| `afterCreateControl(...)` | `afterBindData` / `registerListener` | 不存在该事件方法 |
|
|
14
|
+
| `IDataModel.setReadOnly(...)` | `getView().setEnable(false, "key")` | 模型层不负责 UI 状态 |
|
|
15
|
+
| `this.getView().refresh()` | `this.getView().updateView(key)` | 不存在 refresh(),使用 updateView |
|
|
16
|
+
| `model.getEntryCount(...)` | `model.getEntryRowCount(entryKey)` | 方法名和参数都不同 |
|
|
17
|
+
| `model.deleteRow(...)` | `model.deleteEntryRow(entryKey, rowIndex)` | 方法名不同 |
|
|
18
|
+
| `model.addRow(...)` | `model.createNewEntryRow(entryKey, rowIndex)` | 方法名不同 |
|
|
19
|
+
| `destroy(...)` | `destory(...)` | 苍穹方法名就是 destory(少 r),不是 destroy |
|
|
20
|
+
| `model.getRowCount(...)` | `model.getEntryRowCount(entryKey)` | 与 JTable 的 getRowCount 混淆 |
|
|
21
|
+
| `model.getEntry(...)` | `dataEntity.getDynamicObjectCollection(entryKey)` 或 `model.getEntryRowEntity(entryKey, rowIndex)` | IDataModel 不存在 getEntry() |
|
|
22
|
+
| `QueryServiceHelper.queryAll(...)` | `QueryServiceHelper.query(entityId, selectFields, filters)` | 不存在 queryAll 方法 |
|
|
23
|
+
|
|
24
|
+
## 幻觉类名黑名单 `[事前自检]`
|
|
25
|
+
|
|
26
|
+
- ❌ 不存在以 `Cosmic` 开头的工具类(Utils/Helper/Service),除非脚本明确查到。
|
|
27
|
+
- ❌ 不存在以 `Cloud` 开头的 Utils/Helper 工具类,除非脚本明确查到。项目自定义的 `Cloud*Service` 不在该规则范围内。
|
|
28
|
+
- ❌ 不存在 `BillHelper`(应为 `BusinessDataServiceHelper`)。
|
|
29
|
+
- ❌ 不存在 `FormHelper`(应为 `FormUtils`,位于 `kd.cd.common.form`)。
|
|
30
|
+
- ❌ 不存在 `ListHelper`(应为 `BaseDataServiceHelper` 或 `QueryServiceHelper`)。
|
|
31
|
+
- ❌ 不存在 `PluginHelper`(应按具体场景使用对应 ServiceHelper)。
|
|
32
|
+
|
|
33
|
+
## 场景错配黑名单 `[A层]`
|
|
34
|
+
|
|
35
|
+
| 错误做法 | 原因 | 正确做法 | 层级 |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| 在操作插件中调用 `this.getView()` | 操作插件无 UI 上下文 | 使用 `log` 或 `addErrorMessage` | `[A层]` `→ SCENE-001` |
|
|
38
|
+
| 在操作插件中 `this.getModel().setValue(...)` | 操作插件不通过 model 操作 | 直接操作 `DynamicObject` 数据包 | `[A层]` `→ SCENE-002` |
|
|
39
|
+
| 在 UI 插件中做重查询/复杂事务 | UI 插件应保持轻量 | 移至操作插件或服务层 | `[B层]` |
|
|
40
|
+
| 在 `initialize()` 中注册监听或写 UI 状态逻辑 | 生命周期不对,可能失效或错时执行 | 在 `registerListener` 注册,在 `afterBindData` 处理界面状态 | `[A层]` `→ SCENE-006` |
|
|
41
|
+
| 在 `registerListener` 中调用 `model.getValue(...)` | 此时数据尚未绑定 | 推迟到 `afterBindData` | `[B层]` |
|
|
42
|
+
| 在 `beforeBindData` / `afterBindData` 中 `setValue` 或改数据包 | 绑定阶段禁止改数据 | 改到 `createNewData`、`propertyChanged`、保存前等正确事件 | `[A层]` `→ SCENE-008` |
|
|
43
|
+
| 在 `afterCreateNewData` 中期望触发 `propertyChanged` | 此时赋值不触发 | 在 `afterBindData` 中处理级联 | `[B层]` |
|
|
44
|
+
| 仅 `implements Listener` 不注册监听 | 监听不会生效 | 在 `registerListener` 中调用 `add*Listener` | `[B层]` |
|
|
45
|
+
| 对继承型插件 `@Override` 不调 `super.xxx()` | 基类初始化逻辑不执行 | 继承型必须先调 `super`;接口型无需 | `[B层]` |
|
|
46
|
+
| 直接修改 `EntityMetadataCache` 返回的元数据对象 | 缓存对象是单例,污染全局 | `clone` 后再修改 | `[A层]` |
|
|
47
|
+
| 用其他实体 `createInstance()` 的对象给引用属性赋值 `→ SCENE-010` | 引用对象类型可能不一致 | 使用属性复杂类型或当前实体元数据创建对象 | `[A层]` |
|
|
48
|
+
| 在 `propertyChanged` 中无条件 `setValue` `→ SCENE-012` | 触发新的 `propertyChanged` 导致死循环(栈溢出) | 先判断 `e.getProperty().getName()` 是否是目标字段,赋值前比对新旧值是否相同 | `[A层]` |
|