@shundoo-ai/dsh-cosmic 1.0.21 → 1.0.22
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/package.json +1 -1
- package/skills/cosmic-build/LOCAL-PATCHES.md +43 -14
- package/skills/cosmic-build/SKILL.md +24 -9
- package/skills/cosmic-build/examples/java-rules/CosmicReportAggregation.java +26 -17
- package/skills/cosmic-build/examples/java-rules/CosmicReportFilters.java +96 -2
- package/skills/cosmic-build/knowledge/cosmic/arch/security/security_standard.md +4 -4
- package/skills/cosmic-build/knowledge/cosmic/platform/allimport.md +2 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/core/dynamic-object-collection.md +6 -4
- package/skills/cosmic-build/knowledge/cosmic/platform/core/model.md +9 -9
- package/skills/cosmic-build/knowledge/cosmic/platform/core/view.md +5 -5
- package/skills/cosmic-build/knowledge/cosmic/platform/form-plugin.md +8 -4
- package/skills/cosmic-build/knowledge/cosmic/platform/list-plugin.md +5 -3
- package/skills/cosmic-build/knowledge/cosmic/platform/print-plugin-guide.md +1 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/report-plugin.md +269 -57
- package/skills/cosmic-build/knowledge/cosmic/platform/reportlistdata-plugin.md +130 -23
- package/skills/cosmic-build/knowledge/cosmic/platform/reporttreedata-plugin.md +48 -28
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/_index.md +12 -3
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/common/attachment-name-process.md +17 -13
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/common/dynamic-update-field.md +4 -4
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/filter-grid/filter-grid-set-value.md +1 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-basedatafield.md +2 -3
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-container-init.md +0 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-popup.md +0 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-value-parse.md +5 -6
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/list-show-form.md +1 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/query-field-dynamic.md +0 -7
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/business-data/delete-service.md +24 -29
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/ksql/db-batch.md +4 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/ksql/db-direct-access.md +4 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/qfilter/entity-object-access.md +8 -3
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/qfilter/qfilter-compose.md +6 -5
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/after-bind-data-set-visible.md +5 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/click-return-data.md +2 -2
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/closed-call-back-set-value.md +2 -2
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/register-listener.md +1 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/set-filter-tab-org.md +3 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/dispatch-service/microservice-dev.md +18 -11
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/dist-lock/dist-lock-basic.md +3 -6
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/mq/mq-subscribe.md +5 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/thread-pool/async-operation.md +10 -6
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/thread-pool/big-task-async.md +4 -2
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/thread-pool/schedule-task.md +9 -7
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/operation-interactive.md +33 -34
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/operation-plugin-events.md +30 -22
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-async-query.md +133 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-batch-query.md +26 -22
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-chart.md +112 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-dataset-assembly.md +200 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-head-filter.md +177 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-hyperlink-drill.md +216 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-list-data-query.md +12 -12
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-merge-column.md +44 -6
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-print-data.md +163 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-row-data-toolbar.md +188 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-subtotal-total.md +139 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-tree-data-query.md +108 -12
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-tree-list.md +181 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/system-service/report-plugin-interface.md +3 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-basedata-cascade-confirm.md +14 -11
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-before-item-validate.md +1 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-build-filter.md +1 -1
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-multi-level-filter.md +11 -11
- package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-refresh-node.md +22 -15
- package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-algo.md +2 -2
- package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-entity-model.md +3 -4
- package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-exception.md +9 -5
- package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-orm-access.md +4 -0
- package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-request-context.md +7 -3
- package/skills/cosmic-build/knowledge/cosmic/platform/standards.md +28 -3
- package/skills/cosmic-build/references/compile-guide.md +36 -1
- package/skills/cosmic-build/references/dcs-code-rules.md +180 -0
- package/skills/cosmic-build/references/delivery.md +16 -2
- package/skills/cosmic-build/references/execution-contract.md +15 -3
- package/skills/cosmic-build/references/java-plugin-delivery.md +21 -11
- package/skills/cosmic-build/references/plugin-handoff-input.md +82 -24
- package/skills/cosmic-build/references/plugin-runtime-routing.md +23 -6
- package/skills/cosmic-build/references/report-filter-contract.md +53 -15
- package/skills/cosmic-build/references/sdk-inspection.md +4 -1
- package/skills/cosmic-build/references/type-registry.json +26 -17
- package/skills/cosmic-build/schemas/data-model-authoring.schema.json +1 -1
- package/skills/cosmic-build/scripts/_http_client.py +3 -0
- package/skills/cosmic-build/scripts/compile_plugin_source.py +251 -42
- package/skills/cosmic-build/scripts/configure_list.py +112 -0
- package/skills/cosmic-build/scripts/dcs-rule-catalog.json +799 -0
- package/skills/cosmic-build/scripts/dcs_code_gate.py +1976 -0
- package/skills/cosmic-build/scripts/execution_binding.py +25 -0
- package/skills/cosmic-build/scripts/platform_api_contract.py +352 -7
- package/skills/cosmic-build/scripts/plugin_source_gate.py +9 -1
- package/skills/cosmic-build/scripts/plugin_target_sdk.py +12 -8
- package/skills/cosmic-build/scripts/prepare_plugin_handoff.py +488 -88
- package/skills/cosmic-build/scripts/query_plugin_handoff.py +207 -20
- package/skills/cosmic-build/scripts/register_plugins.py +27 -10
- package/skills/cosmic-build/scripts/render_output_cards.py +57 -20
- package/skills/cosmic-build/scripts/resolve_output_path.py +60 -26
- package/skills/cosmic-build/scripts/run_java_tests.py +162 -0
- package/skills/cosmic-build/scripts/sync_generated_locale_assets.py +28 -0
- package/skills/cosmic-build/scripts/test/fixtures/ReportSdkCheck.java +1 -22
- package/skills/cosmic-build/scripts/test/fixtures/list_column_property_declarations.json +887 -0
- package/skills/cosmic-build/scripts/test/fixtures/operation-entry-field-prepare.java +78 -0
- package/skills/cosmic-build/scripts/test/test_add_field_required_contract.py +12 -0
- package/skills/cosmic-build/scripts/test/test_batch5_drift_governance.py +23 -2
- package/skills/cosmic-build/scripts/test/test_compile_plugin_source.py +287 -4
- package/skills/cosmic-build/scripts/test/test_configure_list_delivery.py +132 -0
- package/skills/cosmic-build/scripts/test/test_cosmic_sdk_examples.py +58 -1
- package/skills/cosmic-build/scripts/test/test_data_model_contract.py +19 -0
- package/skills/cosmic-build/scripts/test/test_dcs_code_gate.py +901 -0
- package/skills/cosmic-build/scripts/test/test_delivery_stage_boundary.py +1 -1
- package/skills/cosmic-build/scripts/test/test_direct_cli_architecture.py +2 -0
- package/skills/cosmic-build/scripts/test/test_http_client.py +6 -0
- package/skills/cosmic-build/scripts/test/test_java_toolchain_feedback.py +206 -0
- package/skills/cosmic-build/scripts/test/test_kd_api.py +21 -0
- package/skills/cosmic-build/scripts/test/test_list_configuration_closure.py +184 -0
- package/skills/cosmic-build/scripts/test/test_mcp_cli.py +139 -2
- package/skills/cosmic-build/scripts/test/test_menu_creation_closure.py +16 -0
- package/skills/cosmic-build/scripts/test/test_modeling_input_recovery.py +55 -1
- package/skills/cosmic-build/scripts/test/test_open_world_cli_catalog.py +1 -1
- package/skills/cosmic-build/scripts/test/test_operation_field_preparation.py +84 -0
- package/skills/cosmic-build/scripts/test/test_platform_api_contract.py +322 -1
- package/skills/cosmic-build/scripts/test/test_plugin_handoff.py +951 -4
- package/skills/cosmic-build/scripts/test/test_plugin_source_gate.py +30 -2
- package/skills/cosmic-build/scripts/test/test_plugin_target_sdk.py +21 -0
- package/skills/cosmic-build/scripts/test/test_property_reroute.py +165 -0
- package/skills/cosmic-build/scripts/test/test_property_schema_first.py +35 -0
- package/skills/cosmic-build/scripts/test/test_query_plugin_handoff.py +221 -0
- package/skills/cosmic-build/scripts/test/test_register_plugins.py +76 -4
- package/skills/cosmic-build/scripts/test/test_render_output_cards.py +75 -3
- package/skills/cosmic-build/scripts/test/test_report_business_contract.py +27 -5
- package/skills/cosmic-build/scripts/test/test_report_doc_contract_sync.py +103 -11
- package/skills/cosmic-build/scripts/test/test_report_plugin_source_gate.py +46 -16
- package/skills/cosmic-build/scripts/test/test_report_properties.py +74 -15
- package/skills/cosmic-build/scripts/test/test_report_query_data_source.py +3 -1
- package/skills/cosmic-build/scripts/test/test_report_sdk_optimization.py +1 -2
- package/skills/cosmic-build/scripts/test/test_test_environment.py +76 -1
- package/skills/cosmic-build/scripts/test_environment.py +67 -1
- package/skills/cosmic-build/skills/cosmic-coding-impl/SKILL.md +52 -10
- package/skills/cosmic-build/skills/cosmic-meta-api/apis/ai_meta.md +16 -3
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/report-write-contracts.json +59 -26
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/rule-domain.json +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/report-write.schema.json +75 -18
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/scripts/pdm_auto.py +39 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/scripts/pdm_client.py +97 -10
- package/skills/cosmic-build/skills/cosmic-meta-api/modules/verify/SKILL.md +10 -12
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_apps.py +3 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_formactions.py +38 -29
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_listui.py +400 -233
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_metaops.py +87 -45
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_properties.py +42 -15
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_rules.py +135 -5
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/config.py +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/execution_errors.py +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/formatters.py +17 -11
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/property_reroute.py +15 -5
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/report_ops.py +1429 -238
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/validators.py +56 -28
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/cosmic_api.py +380 -134
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/field_decorator.py +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/meta_export.py +12 -11
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/meta_verifier.py +42 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_add_field_placement_closure.py +8 -8
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_build_configuration_readback.py +94 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_build_receipt_resume.py +47 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_metadata_unchanged_fail_closed.py +87 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_dym_evidence.py +23 -23
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_entity_integrity.py +279 -4
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_field_guard.py +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_plugin_contract.py +509 -32
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_readback_derivation.py +178 -1
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_recreate_plan.py +125 -10
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_serve_contract.py +208 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_typed_filters.py +259 -50
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_rule_inventory_perf.py +29 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_rule_write_closure.py +20 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_post_build_recovery.py +18 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_verification_evidence.py +35 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_identity_guard.py +25 -0
- package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_time_range_rule.py +98 -0
- package/skills/cosmic-build/skills/cosmic-meta-knowledge/domain-model/report-model.md +20 -9
- package/skills/cosmic-build/skills/cosmic-meta-knowledge/generation/report-modeling-guide.md +55 -25
- package/skills/cosmic-build/skills/cosmic-meta-knowledge/property-guides/report-column-properties.md +15 -39
- package/skills/cosmic-build/skills/cosmic-meta-modeling/SKILL.md +19 -17
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/SKILL.md +82 -38
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/examples/golden-example-report-batch.md +64 -19
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/examples/golden-example-report-plugin.md +32 -20
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/examples/golden-example-report-tree.md +78 -31
- package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/report-artifact-schema.json +2 -1
- package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-companion-fields.md +3 -0
- package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-list-configuration.md +2 -0
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_contract.py +3 -1
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_emit.py +27 -4
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/report_validator.py +99 -44
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/test_report_examples.py +31 -4
- package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/test_report_validator.py +129 -29
- package/skills/cosmic-build/skills/cosmic-meta-modifier/SKILL.md +6 -2
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/validation.md +2 -0
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/SKILL.md +1 -1
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/report-op/SKILL.md +104 -25
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/SKILL.md +9 -0
- package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/verify/usage-guide.md +2 -2
- package/skills/cosmic-build/skills/cosmic-meta-modifier/references/list-filter-modification.md +39 -12
- package/skills/cosmic-build/skills/mcp-server/SKILL.md +39 -24
- package/skills/cosmic-build/skills/mcp-server/scripts/mcp_cli.py +20 -6
- package/skills/cosmic-dev-best-practices/SKILL.md +1 -1
- package/skills/cosmic-dev-best-practices/references/README.md +2 -2
- package/skills/cosmic-dev-best-practices/references/basedata-dev-convention.md +2 -2
- package/skills/cosmic-dev-best-practices/references/bill-dev-convention.md +4 -4
- package/skills/cosmic-dev-best-practices/references/design-document-convention.md +2 -2
- package/skills/cosmic-dev-best-practices/references/design-examples/basedata-design-example.md +4 -4
- package/skills/cosmic-dev-best-practices/references/design-examples/bill-design-example.md +13 -13
- package/skills/cosmic-dev-best-practices/references/elements/CustomerField.md +1 -1
- package/skills/cosmic-dev-best-practices/references/elements/README.md +1 -1
- package/skills/cosmic-dev-best-practices/references/elements/SupplierField.md +1 -1
- package/skills/cosmic-dev-best-practices/references/elements/common-field-property-conventions.md +109 -13
- package/skills/cosmic-dev-best-practices/references/layout-control-convention.md +1 -1
- package/skills/erp-analysis/references/delivery-contract.md +2 -1
- package/skills/erp-analysis/templates/AGENTS.template.md +3 -1
- package/skills/cosmic-build/assets/platform-report-filters/TypedReportFilterFields.java +0 -169
- package/skills/cosmic-build/assets/platform-report-filters/platform.patch +0 -98
- package/skills/cosmic-build/scripts/apply_report_filter_extension.py +0 -39
package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-multi-level-filter.md
CHANGED
|
@@ -7,7 +7,7 @@ status: "approved"
|
|
|
7
7
|
scene_name: "多级树节点过滤条件构建"
|
|
8
8
|
trigger_event: "buildTreeListFilter"
|
|
9
9
|
scene_keywords: ["buildTreeListFilter", "多级过滤", "云-应用-表单", "节点类型判断", "前缀区分", "QFilter", "setCancel", "addQFilter", "多级树"]
|
|
10
|
-
related_apis: ["BuildTreeListFilterEvent.getNodeId", "BuildTreeListFilterEvent.addQFilter", "BuildTreeListFilterEvent.setCancel", "QFilter", "QCP.in", "QCP.equals", "
|
|
10
|
+
related_apis: ["BuildTreeListFilterEvent.getNodeId", "BuildTreeListFilterEvent.addQFilter", "BuildTreeListFilterEvent.setCancel", "QFilter", "QCP.in", "QCP.equals", "QueryServiceHelper.exists", "QueryServiceHelper.query", "StringUtils.substringAfter"]
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# 场景:多级树节点过滤条件构建
|
|
@@ -23,7 +23,7 @@ related_apis: ["BuildTreeListFilterEvent.getNodeId", "BuildTreeListFilterEvent.a
|
|
|
23
23
|
| BuildTreeListFilterEvent | 过滤条件构建事件 | platform/scenes/event/tree-list-build-filter.md |
|
|
24
24
|
| QFilter | 过滤条件对象 | platform/scenes/data-access/qfilter/ |
|
|
25
25
|
| QCP | 比较操作符常量 | platform/scenes/data-access/qfilter/ |
|
|
26
|
-
|
|
|
26
|
+
| QueryServiceHelper | 数据查询,判断节点类型 | platform/scenes/data-access/qfilter/ |
|
|
27
27
|
|
|
28
28
|
## 方法签名
|
|
29
29
|
```java
|
|
@@ -104,7 +104,7 @@ public class XxxTreeListPlugin extends StandardTreeListPlugin {
|
|
|
104
104
|
}
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
### 示例2
|
|
107
|
+
### 示例2:通过查询判断节点是否为云节点
|
|
108
108
|
```java
|
|
109
109
|
import com.alibaba.fastjson.JSONArray;
|
|
110
110
|
|
|
@@ -112,13 +112,14 @@ import kd.bos.dataentity.entity.DynamicObject;
|
|
|
112
112
|
import kd.bos.dataentity.entity.DynamicObjectCollection;
|
|
113
113
|
import kd.bos.list.events.BuildTreeListFilterEvent;
|
|
114
114
|
import kd.bos.list.plugin.StandardTreeListPlugin;
|
|
115
|
-
import kd.bos.orm.ORM;
|
|
116
115
|
import kd.bos.orm.query.QCP;
|
|
117
116
|
import kd.bos.orm.query.QFilter;
|
|
118
117
|
import kd.bos.servicehelper.QueryServiceHelper;
|
|
119
118
|
|
|
120
119
|
public class XxxTreeListPlugin extends StandardTreeListPlugin {
|
|
121
120
|
|
|
121
|
+
private static final String BIZ_APP_ID = "bizappid";
|
|
122
|
+
|
|
122
123
|
@Override
|
|
123
124
|
public void buildTreeListFilter(BuildTreeListFilterEvent e) {
|
|
124
125
|
super.buildTreeListFilter(e);
|
|
@@ -127,14 +128,13 @@ public class XxxTreeListPlugin extends StandardTreeListPlugin {
|
|
|
127
128
|
// 根节点:显示全部
|
|
128
129
|
if ("-1".equals(nodeId)) {
|
|
129
130
|
e.addQFilter(
|
|
130
|
-
new QFilter(
|
|
131
|
+
new QFilter(BIZ_APP_ID, QCP.is_notnull, ""));
|
|
131
132
|
e.setCancel(true);
|
|
132
133
|
return;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
boolean isCloud = orm.exists("bos_devportal_bizcloud", nodeId);
|
|
136
|
+
// 通过查询判断云产品节点,DCS 禁止 ORM/DB 访问。
|
|
137
|
+
boolean isCloud = QueryServiceHelper.exists("bos_devportal_bizcloud", nodeId);
|
|
138
138
|
|
|
139
139
|
if (isCloud) {
|
|
140
140
|
// 云节点:查询云下所有应用 ID
|
|
@@ -146,11 +146,11 @@ public class XxxTreeListPlugin extends StandardTreeListPlugin {
|
|
|
146
146
|
for (DynamicObject app : apps) {
|
|
147
147
|
appIds.add(app.getString("id"));
|
|
148
148
|
}
|
|
149
|
-
e.addQFilter(new QFilter(
|
|
149
|
+
e.addQFilter(new QFilter(BIZ_APP_ID, QCP.in, appIds));
|
|
150
150
|
} else {
|
|
151
151
|
// 应用节点:直接按应用 ID 过滤
|
|
152
152
|
e.addQFilter(
|
|
153
|
-
new QFilter(
|
|
153
|
+
new QFilter(BIZ_APP_ID, QCP.equals, nodeId));
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
e.setCancel(true);
|
|
@@ -218,7 +218,7 @@ public class XxxTreeListPlugin extends StandardTreeListPlugin {
|
|
|
218
218
|
## 注意事项
|
|
219
219
|
- 多级树的过滤条件构建必须覆盖所有层级类型,避免遗漏导致列表数据异常
|
|
220
220
|
- `e.setCancel(true)` 跳过系统内置的分组过滤逻辑,仅使用自定义条件
|
|
221
|
-
- 节点类型判断有三种方式:前缀区分(`cloud_`/`app_
|
|
221
|
+
- 节点类型判断有三种方式:前缀区分(`cloud_`/`app_`)、`QueryServiceHelper` 查询、节点 Data 属性
|
|
222
222
|
- 推荐使用节点 Data 属性(`TreeNode.setData`/`getData`),在 `initializeTree` 中设置
|
|
223
223
|
- 根节点通常不添加过滤条件或添加 `is_notnull` 条件,显示全部数据
|
|
224
224
|
- 云节点过滤时需查询云下所有应用 ID,使用 `QCP.in` 构建 IN 条件
|
|
@@ -7,7 +7,7 @@ status: "approved"
|
|
|
7
7
|
scene_name: "树节点刷新与自定义构建"
|
|
8
8
|
trigger_event: "refreshNode"
|
|
9
9
|
scene_keywords: ["refreshNode", "树节点", "TreeNode", "子节点加载", "懒加载", "刷新节点"]
|
|
10
|
-
related_apis: ["RefreshNodeEvent.getNodeId", "RefreshNodeEvent.setChildNodes", "ITreeModel.getRoot", "TreeNode.getTreeNode", "TreeNode.getChildren", "TreeNode.addChild"]
|
|
10
|
+
related_apis: ["RefreshNodeEvent.getNodeId", "RefreshNodeEvent.setChildNodes", "ITreeModel.getRoot", "TreeNode.getTreeNode", "TreeNode.getChildren", "TreeNode.addChild", "QueryServiceHelper.queryDataSet"]
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# 场景:树节点刷新与自定义构建
|
|
@@ -23,7 +23,7 @@ related_apis: ["RefreshNodeEvent.getNodeId", "RefreshNodeEvent.setChildNodes", "
|
|
|
23
23
|
| RefreshNodeEvent | 刷新节点事件,获取当前节点、设置子节点 | platform/treelist-plugin.md |
|
|
24
24
|
| TreeNode | 树节点对象,构建父子关系 | platform/treelist-plugin.md |
|
|
25
25
|
| ITreeModel | 树模型,获取根节点缓存 | platform/treelist-plugin.md |
|
|
26
|
-
|
|
|
26
|
+
| QueryServiceHelper | 数据查询,读取节点数据 | platform/scenes/data-access/qfilter/ |
|
|
27
27
|
|
|
28
28
|
## 方法签名
|
|
29
29
|
```java
|
|
@@ -46,7 +46,9 @@ import kd.bos.dataentity.utils.StringUtils;
|
|
|
46
46
|
import kd.bos.entity.tree.TreeNode;
|
|
47
47
|
import kd.bos.form.control.events.RefreshNodeEvent;
|
|
48
48
|
import kd.bos.list.plugin.AbstractTreeListPlugin;
|
|
49
|
-
import kd.bos.orm.
|
|
49
|
+
import kd.bos.orm.query.QCP;
|
|
50
|
+
import kd.bos.orm.query.QFilter;
|
|
51
|
+
import kd.bos.servicehelper.QueryServiceHelper;
|
|
50
52
|
|
|
51
53
|
public class XxxTreeListPlugin extends AbstractTreeListPlugin {
|
|
52
54
|
|
|
@@ -78,10 +80,11 @@ public class XxxTreeListPlugin extends AbstractTreeListPlugin {
|
|
|
78
80
|
|
|
79
81
|
private List<TreeNode> loadTopLevelNodes() {
|
|
80
82
|
List<TreeNode> nodes = new ArrayList<>();
|
|
81
|
-
ORM orm = ORM.create();
|
|
82
83
|
String fields = "id, number, name";
|
|
84
|
+
QFilter[] filters = {new QFilter("enable", QCP.equals, "1")};
|
|
83
85
|
// 查询分组数据,构建树节点
|
|
84
|
-
try (DataSet ds =
|
|
86
|
+
try (DataSet ds = QueryServiceHelper.queryDataSet("entityName", "entityName",
|
|
87
|
+
fields, filters, "number")) {
|
|
85
88
|
Iterator<Row> rows = ds.iterator();
|
|
86
89
|
while (rows.hasNext()) {
|
|
87
90
|
Row row = rows.next();
|
|
@@ -110,10 +113,14 @@ import kd.bos.algo.Row;
|
|
|
110
113
|
import kd.bos.entity.tree.TreeNode;
|
|
111
114
|
import kd.bos.form.control.events.RefreshNodeEvent;
|
|
112
115
|
import kd.bos.list.plugin.AbstractTreeListPlugin;
|
|
113
|
-
import kd.bos.orm.
|
|
116
|
+
import kd.bos.orm.query.QCP;
|
|
117
|
+
import kd.bos.orm.query.QFilter;
|
|
118
|
+
import kd.bos.servicehelper.QueryServiceHelper;
|
|
114
119
|
|
|
115
120
|
public class XxxTreeListPlugin extends AbstractTreeListPlugin {
|
|
116
121
|
|
|
122
|
+
private static final String PARENT_PREFIX = "parent/";
|
|
123
|
+
|
|
117
124
|
@Override
|
|
118
125
|
public void refreshNode(RefreshNodeEvent e) {
|
|
119
126
|
super.refreshNode(e);
|
|
@@ -156,14 +163,14 @@ public class XxxTreeListPlugin extends AbstractTreeListPlugin {
|
|
|
156
163
|
private List<TreeNode> loadParentNodes() {
|
|
157
164
|
// 查询一级分组数据,构建树节点
|
|
158
165
|
List<TreeNode> nodes = new ArrayList<>();
|
|
159
|
-
|
|
160
|
-
try (DataSet ds =
|
|
161
|
-
"id, number, name",
|
|
166
|
+
QFilter[] filters = {new QFilter("enable", QCP.equals, "1")};
|
|
167
|
+
try (DataSet ds = QueryServiceHelper.queryDataSet("parentEntity", "parentEntity",
|
|
168
|
+
"id, number, name", filters, "number")) {
|
|
162
169
|
Iterator<Row> rows = ds.iterator();
|
|
163
170
|
while (rows.hasNext()) {
|
|
164
171
|
Row row = rows.next();
|
|
165
172
|
TreeNode node = new TreeNode();
|
|
166
|
-
node.setId(
|
|
173
|
+
node.setId(PARENT_PREFIX + row.getString("number"));
|
|
167
174
|
node.setText(row.getString("name"));
|
|
168
175
|
node.setParentid("0");
|
|
169
176
|
nodes.add(node);
|
|
@@ -175,15 +182,15 @@ public class XxxTreeListPlugin extends AbstractTreeListPlugin {
|
|
|
175
182
|
private List<TreeNode> loadChildNodes() {
|
|
176
183
|
// 查询二级分组数据,构建树节点
|
|
177
184
|
List<TreeNode> nodes = new ArrayList<>();
|
|
178
|
-
|
|
179
|
-
try (DataSet ds =
|
|
180
|
-
"id, number, name, parent.number",
|
|
185
|
+
QFilter[] filters = {new QFilter("enable", QCP.equals, "1")};
|
|
186
|
+
try (DataSet ds = QueryServiceHelper.queryDataSet("childEntity", "childEntity",
|
|
187
|
+
"id, number, name, parent.number", filters, "parent.number")) {
|
|
181
188
|
Iterator<Row> rows = ds.iterator();
|
|
182
189
|
while (rows.hasNext()) {
|
|
183
190
|
Row row = rows.next();
|
|
184
191
|
TreeNode node = new TreeNode();
|
|
185
192
|
node.setId(row.getString("id"));
|
|
186
|
-
node.setParentid(
|
|
193
|
+
node.setParentid(PARENT_PREFIX + row.getString("parent.number"));
|
|
187
194
|
node.setText(row.getString("name"));
|
|
188
195
|
nodes.add(node);
|
|
189
196
|
}
|
|
@@ -197,5 +204,5 @@ public class XxxTreeListPlugin extends AbstractTreeListPlugin {
|
|
|
197
204
|
- 展开节点和列表刷新时均会触发 `refreshNode`,需判断子节点缓存避免重复加载
|
|
198
205
|
- `TreeNode.getTreeNode(nodeId, depth)` 的第二个参数为搜索深度,需根据树层级设置合理值
|
|
199
206
|
- `e.setChildNodes(null)` 表示当前节点无子节点
|
|
200
|
-
- 使用 `
|
|
207
|
+
- 使用 `QueryServiceHelper.queryDataSet` 并传入有效过滤条件(DCS 禁止 ORM/DB 及空过滤);使用 try-with-resources 确保 DataSet 关闭
|
|
201
208
|
- 节点 ID 必须全局唯一,多级节点建议使用前缀区分(如 `"cloud/" + number`)
|
|
@@ -50,8 +50,8 @@ DataSet bounds = orders.groupBy(new String[]{"supplier"})
|
|
|
50
50
|
.countDistinct(new String[]{"id"}, "bill_count").finish();
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
examples/java-rules/CosmicReportAggregation.java
|
|
54
|
-
|
|
53
|
+
examples/java-rules/CosmicReportAggregation.java 经过编译和运行核验,演示三次同范围表单根
|
|
54
|
+
`QueryServiceHelper` 查询、分录预聚合和空分录处理。提供准确字段别名、权限和业务条件,不以 import Algo 作为性能证明。
|
|
55
55
|
Row 立即取值;框架接管的返回 DataSet 不主动关闭。
|
|
56
56
|
|
|
57
57
|
该引擎未提供 SQL COALESCE,使用示例中经过运行测试的 CASE WHEN 空值表达式。
|
|
@@ -27,11 +27,10 @@
|
|
|
27
27
|
### 1. 遍历实体字段元数据
|
|
28
28
|
```java
|
|
29
29
|
MainEntityType entityType = MetadataServiceHelper.getDataEntityType("my_entity_id");
|
|
30
|
-
//
|
|
30
|
+
// 收集每个字段的显示名,不通过 DCS 禁止的 System.out 打印
|
|
31
|
+
Map<String, String> captions = new LinkedHashMap<>(entityType.getProperties().size());
|
|
31
32
|
for (IDataEntityProperty prop : entityType.getProperties()) {
|
|
32
|
-
|
|
33
|
-
String key = prop.getName();
|
|
34
|
-
System.out.println(key + " : " + displayName);
|
|
33
|
+
captions.put(prop.getName(), prop.getDisplayName().getLocaleValue());
|
|
35
34
|
}
|
|
36
35
|
```
|
|
37
36
|
|
|
@@ -17,13 +17,17 @@
|
|
|
17
17
|
## 示例代码
|
|
18
18
|
### 1. 定义错误码类
|
|
19
19
|
```java
|
|
20
|
-
public class MyModuleErrorCode {
|
|
20
|
+
public final class MyModuleErrorCode {
|
|
21
|
+
private MyModuleErrorCode() {
|
|
22
|
+
// 错误码工具类不应被实例化。
|
|
23
|
+
}
|
|
24
|
+
|
|
21
25
|
private static ErrorCode create(String code, String message) {
|
|
22
26
|
return new ErrorCode("my.module." + code, message);
|
|
23
27
|
}
|
|
24
28
|
// 使用 %s 作为动态参数占位符
|
|
25
|
-
public final
|
|
26
|
-
public final
|
|
29
|
+
public static final ErrorCode ORDER_NOT_FOUND = create("orderNotFound", "订单【%s】不存在或已删除。");
|
|
30
|
+
public static final ErrorCode DATA_PROCESS_ERROR = create("dataProcessError", "数据处理失败:%s");
|
|
27
31
|
}
|
|
28
32
|
```
|
|
29
33
|
|
|
@@ -32,7 +36,7 @@ public class MyModuleErrorCode {
|
|
|
32
36
|
public void processOrder(String billNo) {
|
|
33
37
|
if (StringUtils.isBlank(billNo)) {
|
|
34
38
|
// 直接抛出业务异常
|
|
35
|
-
throw new KDBizException(MyModuleErrorCode.
|
|
39
|
+
throw new KDBizException(MyModuleErrorCode.ORDER_NOT_FOUND, billNo);
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
try {
|
|
@@ -42,7 +46,7 @@ public void processOrder(String billNo) {
|
|
|
42
46
|
throw e;
|
|
43
47
|
} catch (Exception e) {
|
|
44
48
|
// 系统级异常(如网络、IO),封装为业务异常再抛出,并可在此记录日志
|
|
45
|
-
throw new KDException(e, MyModuleErrorCode.
|
|
49
|
+
throw new KDException(e, MyModuleErrorCode.DATA_PROCESS_ERROR, e.getMessage());
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
```
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# ORM 与查询 (QFilter / KSQL)
|
|
2
2
|
|
|
3
|
+
> **DCS 部署:** `kd.bos.orm.ORM`、`kd.bos.db.DB` 分别违反 `CVE-KD-2026-0508`、`CVE-KD-0413`。
|
|
4
|
+
> 本页仅用于理解平台内部实现。DCS 插件使用 `QueryServiceHelper.queryDataSet/query/queryOne/exists`
|
|
5
|
+
> 和 `BusinessDataServiceHelper.load*`,见 [dcs-code-rules.md](../../../../references/dcs-code-rules.md)。
|
|
6
|
+
|
|
3
7
|
金蝶云苍穹提供了强大的 ORM 引擎和基于 KSQL 的查询能力。
|
|
4
8
|
|
|
5
9
|
**注意:** 仅展示核心查询模式与最佳实践。如需查询 `ORM`、`QFilter` 或 `DBServiceHelper` 的完整方法列表、准确参数签名,**请务必使用 `cosmic_get_class_detail(classname="<类名>")` 工具查询。**
|
|
@@ -28,12 +28,16 @@ public void bizMethod() {
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
### 2.
|
|
31
|
+
### 2. 跨线程手动传递(不推荐,优先用 `executeOnceIncludeRequestContext`)
|
|
32
32
|
```java
|
|
33
|
+
import kd.bos.context.RequestContext;
|
|
34
|
+
import kd.bos.threads.ThreadPools;
|
|
35
|
+
|
|
33
36
|
// 复制当前上下文
|
|
34
37
|
RequestContext copiedCtx = RequestContext.copy(RequestContext.get());
|
|
35
38
|
|
|
36
|
-
new Thread(
|
|
39
|
+
// 使用平台线程池;new Thread(...) 违反 DCS CVE-KD-0055-1。
|
|
40
|
+
ThreadPools.executeOnce("xxx-context-task", () -> {
|
|
37
41
|
try {
|
|
38
42
|
// 在新线程中绑定上下文
|
|
39
43
|
RequestContext.set(copiedCtx);
|
|
@@ -42,7 +46,7 @@ new Thread(() -> {
|
|
|
42
46
|
// 务必清理,防止干扰后续任务
|
|
43
47
|
RequestContext.remove();
|
|
44
48
|
}
|
|
45
|
-
})
|
|
49
|
+
});
|
|
46
50
|
```
|
|
47
51
|
|
|
48
52
|
## 实践建议
|
|
@@ -19,9 +19,15 @@
|
|
|
19
19
|
- **禁止在 `propertyChanged` 中无条件调用 `setValue`**
|
|
20
20
|
- 写入任何字段都会重新进入 `propertyChanged`。必须用 `e.getProperty().getName()` 做判断,且新值与当前值相等时跳过写入。方法体内有写入却从未读取 `e.getProperty()` 或 `e.getChangeSet()` 的,以 `PLUGIN_SOURCE_LIFECYCLE_MISUSE` 拒绝
|
|
21
21
|
- **禁止用 `static` 字段保存可变状态**
|
|
22
|
-
- 平台会跨请求、跨会话、跨租户复用同一个插件实例,因此非 final 的 `static` 字段会把一个用户的数据泄漏到另一个用户的页面,并在并发下不可预测地损坏。每次请求的状态放局部变量,需要跨事件保留时放 `getPageCache()`。`static final`
|
|
22
|
+
- 平台会跨请求、跨会话、跨租户复用同一个插件实例,因此非 final 的 `static` 字段会把一个用户的数据泄漏到另一个用户的页面,并在并发下不可预测地损坏。每次请求的状态放局部变量,需要跨事件保留时放 `getPageCache()`。`static final` 字符串、数值、日志对象和 `Pattern` 可共享
|
|
23
|
+
- DCS 禁止静态集合字段,**即使声明 `final`、仅保存固定映射也不允许**(`CVE-KD-0056-*`)。
|
|
24
|
+
使用局部/实例集合;固定映射可用 `static final` 数组、`switch` 或枚举
|
|
23
25
|
- **禁止修改 `EntityMetadataCache` 返回的对象**
|
|
24
26
|
- 返回的实例跨会话共享,改动它会污染此后所有调用方。只读取它,需要变更时自行构造对象
|
|
27
|
+
- **禁止覆写报表表单回调却不把插件注册为其监听**
|
|
28
|
+
- 在 `AbstractReportFormPlugin` 上,`hyperLinkClick`、`itemClick` / `beforeItemClick` 和 `cellClick` / `cellDoubleClick` 只有在 `registerListener` 调用了 `addHyperClickListener`、`addItemClickListeners` 或 `addCellClickListener` 后才会触发:8.0 报表框架里没有任何地方替插件注册。以 `PLUGIN_SOURCE_LISTENER_UNREGISTERED` 拒绝
|
|
29
|
+
- **禁止分批报表的查询忽略当前批**
|
|
30
|
+
- `queryBatchBy` 一旦返回分批依据行,`query` 就会每批执行一次;既不读 `selectedObj` 也不读 `byBatchInfo().getCurrentBatchRows()` 的 `query` 会每批都返回全部行。以 `PLUGIN_SOURCE_BATCH_NOT_NARROWED` 拒绝
|
|
25
31
|
|
|
26
32
|
### 不存在的成员
|
|
27
33
|
|
|
@@ -67,10 +73,15 @@ for (DynamicProperty property : treeEntryProperties) {
|
|
|
67
73
|
this.getView().updateView("entryKey"); // 循环外统一刷新
|
|
68
74
|
```
|
|
69
75
|
|
|
70
|
-
-
|
|
76
|
+
- **禁止循环内微服务调用、保存/操作/删除、缓存访问和日志**(`CVE-KD-0201`、`CVE-KD-0051-*`、`CVE-KD-0058-1`)
|
|
77
|
+
- **无论循环内外,都不使用 `kd.bos.db.DB` 或 `kd.bos.orm.ORM`**(`CVE-KD-0413`、`CVE-KD-2026-0508`)。
|
|
78
|
+
使用 `QueryServiceHelper.queryDataSet(algoKey, entity, fields, filters, orderBys)` 等已验证服务 API
|
|
71
79
|
|
|
72
80
|
### 数据访问
|
|
73
81
|
- **禁止无过滤条件查询大数据量**(默认查询范围要缩小:当月/当天/当前组织)
|
|
82
|
+
- 查询/加载传入 `null` 或空过滤数组违反 DCS `CVE-KD-0303`
|
|
83
|
+
- **删除必须走操作服务**,如 `OperationServiceHelper.executeOperate("delete", ...)`,
|
|
84
|
+
不直接调用 `DeleteServiceHelper.delete`(`CVE-KD-0717-*`)
|
|
74
85
|
- **所有脚本必须使用 KSQL 语法**,禁止方言 SQL
|
|
75
86
|
- **查询参数禁止拼接 SQL 字符串**,使用参数化查询
|
|
76
87
|
- **查询字段层级不超过 4 层**(过深产生笛卡尔积,性能骤降)
|
|
@@ -105,6 +116,8 @@ String msg = String.format(
|
|
|
105
116
|
|
|
106
117
|
### 多线程
|
|
107
118
|
- **禁止使用 JDK 原生线程/线程池**,必须使用苍穹平台线程池 `kd.bos.threads.ThreadPools`
|
|
119
|
+
- DCS 禁止 `new Thread`、`Timer`、`Executors`、`ExecutorService`、`CompletableFuture`、
|
|
120
|
+
`Future` 等执行器(`CVE-KD-0055-*`)
|
|
108
121
|
|
|
109
122
|
```java
|
|
110
123
|
// 正例:苍穹线程池
|
|
@@ -124,6 +137,7 @@ ThreadPools.executeOnce(() -> { /* 异步逻辑 */ });
|
|
|
124
137
|
|
|
125
138
|
### 日志
|
|
126
139
|
- **必须使用 `kd.bos.logging.Log` 接口**,禁止用 `System.out.println`
|
|
140
|
+
- **禁止循环内写日志**(`CVE-KD-0058-1`),循环内收集信息,结束后记录一次汇总
|
|
127
141
|
- **禁止用 JSON 序列化打印页面对象**(`SerializationUtils.toJsonString` 极耗 CPU)
|
|
128
142
|
|
|
129
143
|
```java
|
|
@@ -253,8 +267,19 @@ prop.setValueFast(dataEntity, customerObj);
|
|
|
253
267
|
- 使用第三方 jar 包前检查安全漏洞(https://nvd.nist.gov/vuln/search)
|
|
254
268
|
|
|
255
269
|
### 异常处理
|
|
256
|
-
- 统一使用 `KDException
|
|
270
|
+
- 统一使用 `KDException`(可自定义子异常),面向用户的业务错误使用 `KDBizException`。
|
|
271
|
+
DCS 禁止直接抛出 `RuntimeException` / `Exception`(`java:S112`),避免捕获 `Throwable` / `Error`(`java:S1181`)
|
|
257
272
|
- 有原始异常时必须作为 cause 传入:`throw new KDException(e, new ErrorCode("xxx",e.getMessage()));`
|
|
258
273
|
- 禁止直接调用 `Throwable.printStackTrace()`
|
|
259
274
|
- 三种处理方式:①UI 层捕获并显示**业务语义**提示(让用户知道下一步怎么处理);②包装为新异常抛出(必须将原异常作为 cause);③直接再次抛出
|
|
260
275
|
- **禁止直接隐藏异常**(空 catch 块);有特殊理由必须输出日志并在注释中说明原因
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## DCS 部署门禁
|
|
280
|
+
|
|
281
|
+
编译不能发现所有部署问题。客户自行打包的模块会被 DCS 检查:静态集合、循环内日志或保存、
|
|
282
|
+
`ORM` / `DB`、无过滤查询、重复字面量、未使用导入、空方法等都可能导致整包被拒绝。
|
|
283
|
+
[dcs-code-rules.md](../../../references/dcs-code-rules.md) 列出对应规则与替代方案。
|
|
284
|
+
`compile_plugin_source.py` 以 `PLUGIN_SOURCE_DCS_RULE_VIOLATION` 阻断明确违规,
|
|
285
|
+
其余建议以 `PLUGIN_SOURCE_DCS_RULE_ADVISORY` 返回。
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
不要从其他项目推断接口,也不要搜索无关 jar 或缓存。不使用强转、改插件类型、删除业务行为或
|
|
52
52
|
伪造值绕过检查。模块/构建问题按准确诊断处理,不手工拼 Gradle 命令;目标模块附近代码可辅助定位源码错误。
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
集中修复共同诊断。每个源码结果最多抽样五条,优先保留不同文件的诊断,只有不足以定位时才读 `logPath`。
|
|
55
55
|
同任务其他源码报错可能是共同原因,不能直接归为无关缺陷。做出相关修复后再重试,不原样重复。
|
|
56
56
|
|
|
57
57
|
只有成功的原生结果能建立源码就绪状态,不手工写归档或门禁。
|
|
@@ -59,7 +59,42 @@
|
|
|
59
59
|
|
|
60
60
|
独立源码问题在 `errorCodes` 中一并返回,集中修复后再调用编译。
|
|
61
61
|
|
|
62
|
+
`PLUGIN_SOURCE_OPERATION_ARGUMENT_ORDER` 在首参已有目标表单或 `loadSingle` 调用的实体证据时,
|
|
63
|
+
阻断操作/实体参数颠倒。缺少该证据时,`PLUGIN_SOURCE_OPERATION_ARGUMENT_ORDER_UNVERIFIED`
|
|
64
|
+
仅作提示,不自动交换自定义操作或动态值。`PLUGIN_SOURCE_OPERATION_OVERLOAD_UNVERIFIED`
|
|
65
|
+
表示参数数量不匹配任何已收录重载,不代表目标 SDK 中不存在该重载。启用编译时交给绑定编译器
|
|
66
|
+
验证;`compile=false` 时不能据此推进到 `source_ready`。改用已收录签名,或绑定目标 SDK 并启用
|
|
67
|
+
编译后解决该缺口。注册前会重验这两项门禁,不沿用历史成功归档回执绕过检查。
|
|
68
|
+
|
|
69
|
+
`PLUGIN_SOURCE_DCS_RULE_VIOLATION` 表示检测到 DCS 部署门禁违规,每项携带 `ruleCodes`、行号和 `fix`。
|
|
70
|
+
按 [dcs-code-rules.md](dcs-code-rules.md) 修复;禁止添加 `// NOSONAR` 或 `@SuppressWarnings` 跳过检查,
|
|
71
|
+
它们本身也违反 DCS 规则。`sourceWarnings` 中的 `PLUGIN_SOURCE_DCS_RULE_ADVISORY` 是源码预检
|
|
72
|
+
不能完全确定的问题:修复,或在结果中说明经核实为何不适用。
|
|
73
|
+
|
|
62
74
|
编译回执的 `loadingVerification.runtimeVerified` 仍为 false。默认 Gradle class 产物可观察时,
|
|
63
75
|
`compiledArtifact` 绑定其 FQCN 和哈希;跳过编译或自定义输出未观察时为 null。报表运行测试
|
|
64
76
|
按 [report-filter-contract.md](report-filter-contract.md) 使用只读加载 CLI 后再验收业务。
|
|
65
77
|
复制 class 或重启 JVM 不等于加载证据。
|
|
78
|
+
|
|
79
|
+
准备结果含 `compileCommand` 时直接复用。原生编译保留无关归档条目;无需手工合并归档或为这一步阅读实现脚本。
|
|
80
|
+
|
|
81
|
+
## 目标 Java 工程测试
|
|
82
|
+
|
|
83
|
+
需要工程验证时使用准备结果的 `testCommand`,或执行:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
{python} "{ROOT_DIR}/scripts/run_java_tests.py" --project-root "{projectRoot}" [--tests "<已有测试类或方法>"] [--rerun-tests]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
脚本复用已绑定的 wrapper、JDK 和模块,确认目标模块真实的 Gradle `Test` 任务,
|
|
90
|
+
返回实际执行数量、失败方法及断言和完整日志。`--tests` 可重复;`--rerun-tests`
|
|
91
|
+
只重跑所选测试任务,编译保持增量。保留原有测试源码与断言。普通辅助类和服务类
|
|
92
|
+
随工程编译,无需按插件准备或注册。
|
|
93
|
+
|
|
94
|
+
只有 `outcome=passed` 证明实际执行的测试通过。零测试、跳过、未重跑、任务缺失、
|
|
95
|
+
构建失败和超时必须明确报告;进程退出为 0 不代表执行过断言。测试不会注册或激活插件。
|
|
96
|
+
按反馈定向修复后运行受影响的已有测试,测试实际生产代码,不削弱断言或另写一份业务逻辑。
|
|
97
|
+
|
|
98
|
+
准备或编译返回 `buildEnvironment` 时,一次处理其中完整的 `missing`、`invalid`
|
|
99
|
+
和准确配置命令。缺少编译决策仍需保留决策边界;关闭编译不代表测试环境就绪。
|
|
100
|
+
配置检查不会保存设置。
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# DCS 部署代码规则
|
|
2
|
+
|
|
3
|
+
客户自行打包插件模块并通过 DCS 部署。DCS 会结合金蝶 `CVE-KD-*`、Sonar(`java:S*`)、
|
|
4
|
+
SpotBugs 和 Fortify 等规则检查代码。插件能编译、能注册、能运行,不代表符合部署门禁。
|
|
5
|
+
应从第一版源码就遵循这些规则,减少重新打包和部署的返工。
|
|
6
|
+
|
|
7
|
+
`scripts/dcs_code_gate.py` 提前检查可从源码识别的规则。它已接入
|
|
8
|
+
`compile_plugin_source.py`,即使配置 `compile=false` 也会执行;也可在打包前扫描整个模块。
|
|
9
|
+
每条发现均附带 DCS 规则编号、行号和修复建议,便于与平台报告对应。
|
|
10
|
+
|
|
11
|
+
| 级别 | 含义 | 返回位置 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `block` | 源码预检识别出明确违规 | `issues` 中的 `PLUGIN_SOURCE_DCS_RULE_VIOLATION`;编译流程停止,CLI 退出码为 2 |
|
|
14
|
+
| `advise` | 依赖类型、数据流或复杂度等信息,源码预检不能完全确定;DCS 仍可能拒绝 | `sourceWarnings` 中的 `PLUGIN_SOURCE_DCS_RULE_ADVISORY`;CLI 仅在 `--strict` 时因此失败 |
|
|
15
|
+
|
|
16
|
+
修复所有 `block`。对 `advise` 修复,或说明经核实为何不适用。
|
|
17
|
+
禁止使用 `// NOSONAR` 或 `@SuppressWarnings("java:S…")` 跳过检查,它们本身也违反
|
|
18
|
+
`CVE-KD-0401` / `CVE-KD-0402`。
|
|
19
|
+
|
|
20
|
+
## 规则来源与并集口径
|
|
21
|
+
|
|
22
|
+
`scripts/dcs-rule-catalog.json` 按真实规则编号登记两表并集:
|
|
23
|
+
|
|
24
|
+
| 来源 | 选择口径 | 规则数 |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `金蝶AI套件公有云门禁20261026.xlsx` | 全部规则,保留原有中危、低危规则 | 1467 |
|
|
27
|
+
| `扫描规则_1026144356.xlsx` | 高危 253 条、严重 175 条;排除新表其他等级 | 428 |
|
|
28
|
+
|
|
29
|
+
两表重叠 313 个编号,新增 115 个编号,最终并集为 **1582** 条真实规则。
|
|
30
|
+
同一编号只登记一次,风险等级取两表中的较高等级(严重 > 高危 > 中危 > 低危)。
|
|
31
|
+
目录保留来源、原始等级、扫描引擎以及文件/编号集合指纹,随技能一起交付;运行时无需
|
|
32
|
+
Excel 依赖,也不读取客户电脑上的原始工作簿。
|
|
33
|
+
|
|
34
|
+
目录登记不等于完整自动检测。下列检查仅覆盖可识别的 Java、SQL 和源码模块模式。
|
|
35
|
+
原有 Fortify 兼容名称仍可出现在 `ruleCodes` 中;`relatedRuleCodes` 关联工作簿中同名 Fortify
|
|
36
|
+
规则的真实编号。这些关联是候选关系,不表示已证实某个语言或调用链变体。
|
|
37
|
+
完整目录还包含 TypeScript、KSC、元数据和冲突引擎规则,需要对应引擎及构建/部署上下文。
|
|
38
|
+
|
|
39
|
+
## 受限 API 与替代方案
|
|
40
|
+
|
|
41
|
+
| 不要使用 | 规则 | 推荐写法 |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `kd.bos.orm.ORM` | `CVE-KD-2026-0508` | `QueryServiceHelper.queryDataSet(algoKey, entity, fields, filters, orderBys)`;`QueryServiceHelper.query/queryOne/exists`;`BusinessDataServiceHelper.load*` |
|
|
44
|
+
| `kd.bos.db.DB` | `CVE-KD-0413` | 使用上述服务辅助类,不通过 `DB` 执行 KSQL |
|
|
45
|
+
| `DeleteServiceHelper.delete`、`BusinessDataWriter.delete`、`ORM.delete`,或没有 `where` 的 `delete from` | `CVE-KD-0717-2/3/4`、`CVE-KD-0302-01` | `OperationServiceHelper.executeOperate("delete", entityNumber, ids, OperateOption.create())`,执行删除校验和插件 |
|
|
46
|
+
| `new Thread`、`extends Thread`、`java.util.Timer`、`Executors`、`ExecutorService`、`ThreadPoolExecutor`、`CompletableFuture`、`Future`、`FutureTask`、`ForkJoinPool` | `CVE-KD-0055-1…9` | `kd.bos.threads.ThreadPools.executeOnce("taskName", runnable)`;周期任务使用平台调度 |
|
|
47
|
+
| `kd.bos.mq.MessageConsumer`,RabbitMQ / RocketMQ / Kafka 客户端 | `CVE-KD-20260901-4`、`CVE-KD-0023/24/25` | 根据已验证平台契约使用注册的调度任务或事件订阅 |
|
|
48
|
+
| `JedisClient`、`redis.clients.*`、`ZKFactory`、`kd.bos.zk.*`、`org.apache.zookeeper.*`、`org.apache.curator.*` | `CVE-KD-0019-1/0020/0021/0022`、`CVE-KD-20260901-1…3` | 平台缓存 `CacheFactory` 和平台服务 |
|
|
49
|
+
| `System.getenv/getProperty/getProperties/setProperty`、`System.exit`、`System.gc` | `CVE-KD-0008/0009/0010/0017`、`DM_EXIT`、`DM_GC` | 平台参数;业务错误抛出 `KDBizException`,不退出 JVM |
|
|
50
|
+
| `Class.forName`、`java.lang.reflect.*`、`getDeclared*`、`setAccessible`、`URLClassLoader`、字节码库 | `CVE-KD-0011-*`、`CVE-KD-0012-*`、`java:S3011` | 直接调用公开 API |
|
|
51
|
+
| `RequestContext.setAccountId/setTenantId`、`SessionInfo` setter、`Lang.setHolder`、`RequestContextInfo`、`AccountUtils`、`MCDBUtil`、`DBConfig`、`DataSourceFactory`、`MetadataDao` | `CVE-KD-0014-*`、`CVE-KD-0015-1`、`CVE-KD-0400`、`CVE-KD-0018`、`CVE-KD-0001…0007`、`CVE-KD-0059-1/2/3` | `RequestContext.get()` 的 getter;`EntityMetadataCache.getDataEntityType(entity)` |
|
|
52
|
+
| `java.net.Socket` 等原始 socket | `CVE-KD-0029` | 已验证的平台集成或 HTTP 能力 |
|
|
53
|
+
| `sun.*`、`com.sun.*`、`javax.xml.bind.*` 等 JDK 内部或已移除 API | `CVE-KD-0501` | 公开 JDK 17 API,如 `java.util.Base64`、`java.time` |
|
|
54
|
+
| `System.out/err.print*`、`e.printStackTrace()` | `CVE-KD-0209-1/2`、`java:S106` | `private static final Log LOG = LogFactory.getLog(X.class);`,再调用 `LOG.error("业务说明", e)` |
|
|
55
|
+
| `kd.*.impl.*` / `kd.*.internal.*` 导入,或插件自身使用 `kd.*` 包名 | `CVE-KD-0414-2`、`class_fully_qualified_name_conflict_stp`(建议项) | 公开 SDK 和已准备的应用 ISV 包名 |
|
|
56
|
+
| 内部文件服务 URL(`attachmentServer.url`、`file/upload.do` 等)、临时文件设置(`tempfile.redis` 等) | `CVE-KD-0026-*`、`CVE-KD-0028-*` | `AttachmentServiceHelper` 和已文档化的附件 API |
|
|
57
|
+
|
|
58
|
+
## 静态状态
|
|
59
|
+
|
|
60
|
+
DCS 禁止静态集合字段:`Map`、`HashMap`、`List`、`Set`、`Properties`、
|
|
61
|
+
`ConcurrentHashMap` 等,**即使声明 `static final`、仅作为固定映射表也不允许**
|
|
62
|
+
(`CVE-KD-0056-01…23`)。集合放在局部变量或实例字段;固定映射可使用 `static final` 数组、
|
|
63
|
+
`switch` 或枚举。字符串、数值、`Log` 和 `Pattern` 常量可以使用。
|
|
64
|
+
`public static` 字段必须同时为 `final`(`java:S1444`)。
|
|
65
|
+
|
|
66
|
+
## 循环
|
|
67
|
+
|
|
68
|
+
以下操作不应放在 `for`、`while`、`do` 或 `forEach` 循环体中。先收集 ID,在循环外批量调用,
|
|
69
|
+
在内存处理返回结果,循环结束后统一保存或刷新。
|
|
70
|
+
|
|
71
|
+
| 循环内操作 | 规则 |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `SaveServiceHelper`、`OperationServiceHelper`、`DeleteServiceHelper`、`BusinessDataReader/Writer` | `CVE-KD-0051-07…11` |
|
|
74
|
+
| 嵌套循环中的数据访问(`BusinessDataServiceHelper`、`QueryServiceHelper`、`ORM`、`DB` 等);单层循环作为建议项 | `CVE-KD-1215-1/2` |
|
|
75
|
+
| 规则配置中 `DB`、`ORM`、`DataManager`、`LogORM`、`BusinessDataServiceHelper`、`QueryServiceHelper` 的指定方法(含 `loadHead`、`loadSingle`、`queryDataSet`) | 目录中的 `CVE-KD-0051-14…67` 条目;保留原有 `CVE-KD-TS-0051-46` 兼容检查 |
|
|
76
|
+
| 分布式缓存、页面缓存 `getPageCache()` | `CVE-KD-0051-03/04`、`CVE-KD-0054-1/2` |
|
|
77
|
+
| `getView().updateView(...)` | `CVE-KD-0052` |
|
|
78
|
+
| 日志(`LOG.info` 等);改为循环外记录汇总日志 | `CVE-KD-0058-1` |
|
|
79
|
+
| `DispatchServiceHelper.invoke*` 等微服务调用 | `CVE-KD-0201` |
|
|
80
|
+
| `Pattern.compile`;改为预先编译的 `static final Pattern` | `IIL_PATTERN_COMPILE_IN_LOOP` |
|
|
81
|
+
| 字符串 `str += …`;改为 `StringBuilder` | `java:S1643` |
|
|
82
|
+
|
|
83
|
+
## 数据访问
|
|
84
|
+
|
|
85
|
+
- 按条件查询或加载时传入有效业务过滤条件;按主键重载则传入明确的 ID。
|
|
86
|
+
预检根据参数个数和已知类型识别 SDK 重载,不根据 `top` 参数的字面写法猜测;
|
|
87
|
+
无法确定重载且可能存在空过滤时返回 `advise`。过滤参数为 `null`、`(QFilter[]) null`、
|
|
88
|
+
`new QFilter[0]` 或空数组会触发 `CVE-KD-0303`。适用于 `query`、`queryOne`、`queryDataSet`、
|
|
89
|
+
`exists`、`load`、`loadFromCache`、`loadSingle`、`loadSingleFromCache`。
|
|
90
|
+
使用真实 ID 范围、单据编码、组织或日期范围,不用形式上的恒真条件绕过门禁。
|
|
91
|
+
- 禁止 `select *`(`CVE-KD-0053-01`);不拼接参数值构造 SQL(`java:S2077`,建议项)。
|
|
92
|
+
插件代码禁止 `drop/truncate/rename table`、`create view/procedure/function/trigger`
|
|
93
|
+
等 DDL(`CVE-KD-0013-*`、`CVE-KD-0720-1/2`、`CVE-KD-0721…0723-*`)。Java SQL 字面量禁止
|
|
94
|
+
`/*dialect*/`(`CVE-KD-0060-1`)。不要调用规则指定的 `MetadataDao.getFormDeployFile` /
|
|
95
|
+
`refreshMainEntityLName`(`CVE-KD-0059-2/3`)。
|
|
96
|
+
- `propertyChanged` 不得无条件调用 `updateView()`(`CVE-KD-2026-0618`)。
|
|
97
|
+
先判断 `e.getProperty().getName()` 是否为本插件处理的字段,再局部刷新对应控件。
|
|
98
|
+
- 模块随附 SQL 脚本可创建表(表名不超过 24 字符),不得进行增删改、删除/改名表或创建
|
|
99
|
+
视图、过程、函数、触发器(`CVE-KD-SQL-*`);保存为 UTF-8。源码模块中不要夹带第三方 `.jar`、
|
|
100
|
+
预编译 `.class` 或原生库依赖(`CVE-KD-SCAN-jar`、`CVE-KD-SCAN-libFile`)。源码扫描会标记构建/输出
|
|
101
|
+
目录之外的这些文件,不用于检查最终生成的插件 JAR。
|
|
102
|
+
SQL 扫描区分注释、字符串和引号标识符,并保留发现的行号;字符串中的文本不视为可执行语句。
|
|
103
|
+
- `INSERT` 必须列出目标列(`CVE-KD-SQL-0017`),同时仍执行原有的禁止插入规则
|
|
104
|
+
`CVE-KD-SQL-0005`。识别 KSQL `p_AlterColumn(..., 'NULL')` 删除字段和 `p_modifyobjectname`
|
|
105
|
+
改名;非 UTF-8 SQL 的合并风险等级为严重(`CVE-KD-SQL-0015`)。SQL 脚本中的
|
|
106
|
+
`/*dialect*/` 为建议项(`CVE-KD-SQL-0016`),需核实是否适用 ISV 产品限制。索引变更及
|
|
107
|
+
增加/修改字段作为建议项(`CVE-KD-SQL-0011/12/13`),因为源码无法确定表大小及部署影响。
|
|
108
|
+
- 模块扫描阻断所检查目录内重复的顶层类完全限定名(`class_fully_qualified_name_conflict_internal`);
|
|
109
|
+
最终 JAR 与外部依赖、标准产品的类名冲突仍不属于此源码检查范围。
|
|
110
|
+
|
|
111
|
+
## 代码形态(Sonar / SpotBugs)
|
|
112
|
+
|
|
113
|
+
| 规则 | 推荐写法 |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `java:S1192` | 长度至少 5 字符且使用至少 3 次的字符串(常见为字段键)提取为 `private static final String` 常量 |
|
|
116
|
+
| `java:S1128`、`java:S1481`、`java:S1068`/`UUF_UNUSED_FIELD`、`java:S1144`、`java:S1172` | 清理未使用或重复的导入、局部变量、私有字段/方法及私有方法参数;`try-with-resources` 中的所有资源声明均由自动关闭隐式使用 |
|
|
117
|
+
| `java:S1186`、`java:S108` | 不保留空方法/空块;删除不需要的 override,必需的空实现说明原因 |
|
|
118
|
+
| `java:S1155` | 使用 `list.isEmpty()`,不写 `size() == 0` |
|
|
119
|
+
| `ITA_INEFFICIENT_TO_ARRAY` | `list.toArray(new QFilter[list.size()])`,不使用 `new QFilter[0]` |
|
|
120
|
+
| `java:S112` | 使用 `KDBizException` 或具体异常类型,不直接抛出 `RuntimeException` / `Exception` |
|
|
121
|
+
| `java:S1181` | 捕获 `Exception`,不捕获 `Throwable` / `Error`;为回滚后重新抛出的捕获作为建议项处理 |
|
|
122
|
+
| `java:S2139`、`java:S2142` | 不同时记录并重新抛出同一异常;捕获 `InterruptedException` 后调用 `Thread.currentThread().interrupt()` |
|
|
123
|
+
| `java:S2129`、`DM_*_CTOR`、`java:S2111` | 使用 `Integer.valueOf(…)`、`BigDecimal.valueOf(…)` / `BigDecimal.ZERO`、`new BigDecimal("1.10")`,不使用包装类构造器或 `new BigDecimal(double)`;可表示为 `long` 的十进制字面量用 `BigInteger.valueOf`,字节数组、进制解析及更大数值保留必要构造器 |
|
|
124
|
+
| `java:S4973`、`EC_NULL_ARG` | 字符串用 `"x".equals(v)` 比较;null 用 `== null` |
|
|
125
|
+
| `java:S1157`、`DM_CONVERT_CASE` | 使用 `equalsIgnoreCase`;转换大小写时传入 `Locale.ROOT` |
|
|
126
|
+
| `java:S131`、`java:S128` | `switch` 必须有 `default`;非空 case 不贯穿到下一个 case |
|
|
127
|
+
| `java:S1066`、`java:S1126`、`java:S1125`、`java:S3358` | 合并可合并的嵌套 if;直接返回条件;不写 `== true` 或嵌套三元表达式 |
|
|
128
|
+
| `java:S100`、`java:S101`、`java:S115`、`java:S116`、`java:S117`、`CVE-KD-0403` | 方法/字段/变量/参数为 lowerCamelCase,类为 UpperCamelCase,常量为 `UPPER_SNAKE_CASE`,标识符为英文 |
|
|
129
|
+
| `java:S1124`、`java:S1197` | 修饰符依 `public protected private abstract static final …` 排列;使用 `String[] names` |
|
|
130
|
+
| `java:S1220`、`java:S1598` | 声明已准备的包名,包名与源码目录一致 |
|
|
131
|
+
| `java:S1149`、`java:S1171`、`java:S1604` | 用 `ArrayList` / `HashMap` / `StringBuilder`,不用旧集合/字符串缓冲类;不双括号初始化;单方法匿名类可用 lambda |
|
|
132
|
+
| `java:S5361`、`java:S2864`、`java:S1153` | 普通字面量用 `replace`;需要 value 时遍历 `entrySet()`;不写 `+ String.valueOf(x)` |
|
|
133
|
+
| `java:S125`(建议项)、`java:S3776`(建议项) | 删除注释掉的代码,拆分认知复杂度超过 15 的方法 |
|
|
134
|
+
| `java:S2447` | 返回 `Boolean` 的方法不返回 `null` |
|
|
135
|
+
| `java:S1113`、`java:S2151`、`java:S3014` | 不使用终结器、`runFinalizersOnExit` 或 `ThreadGroup`;显式管理资源,使用平台任务 |
|
|
136
|
+
| `java:S2236`、`java:S2695` | 不用 `Thread` 实例作为 wait/notify 锁;JDBC 参数/列索引从 1 开始,不把 fetch size、上限或超时误当索引 |
|
|
137
|
+
| `java:S1143`、`java:S1163` | 不通过 return/break/continue 或向外抛异常退出 `finally`;其中嵌套函数或内部循环的跳转不视为退出 |
|
|
138
|
+
| `java:S2093`、`java:S2095`(建议项) | 使用 `try-with-resources`,资源所有权或关闭情况不明确时需核实 |
|
|
139
|
+
| `java:S2692`(建议项) | 判断包含时使用 `indexOf(...) >= 0`,否则说明为何排除起始位置匹配 |
|
|
140
|
+
|
|
141
|
+
## 安全
|
|
142
|
+
|
|
143
|
+
- 不在源码保存账号密码、密钥或 token;敏感参数从加密平台配置读取,不写日志。
|
|
144
|
+
含 `password`、`passwd`、`pwd`、`passphrase` 的变量名赋非空字面量会被当前预检识别为
|
|
145
|
+
`java:S2068`;字段键常量应采用明确的业务命名,不能靠改名隐藏真实凭据。
|
|
146
|
+
- 使用 `SecureRandom`,不用 `Random` / `Math.random`(`java:S2245`);使用 SHA-256 或更强摘要,
|
|
147
|
+
不用 MD5/SHA-1(`java:S4790`);使用带随机 IV 的 `AES/GCM/NoPadding` 和带 OAEP 的 RSA
|
|
148
|
+
(`RSA/ECB/OAEPWithSHA-256AndMGF1Padding` 不属于对称 ECB)。密钥长度依算法区分:
|
|
149
|
+
RSA/DSA/DH 至少 2048 位、EC 至少 224 位、AES 至少 128 位;只检查对应生成器的调用。
|
|
150
|
+
TLS 1.2+(`java:S5547`、`java:S5542`、`java:S4426`、`java:S4423` 及 Fortify 规则)。
|
|
151
|
+
- 每个 XML 工厂均须在创建解析器或使用前设置有效防护(`java:S2755`):
|
|
152
|
+
DOM/SAX 设置 `disallow-doctype-decl=true`;StAX 禁用 DTD 和外部实体;转换器/Schema 工厂
|
|
153
|
+
禁止访问外部 DTD 及样式表/Schema。关键词或其他工厂的设置不能替代本实例防护;
|
|
154
|
+
条件分支或运行时设置需要核实(`advise`)。不使用 `ObjectInputStream`、`XMLDecoder` 或 autotype
|
|
155
|
+
反序列化;不在 `finally` 内 return。
|
|
156
|
+
- 不用可预测数字、零值/常量数组或时钟手动初始化 `SecureRandom`(`java:S4347`)。
|
|
157
|
+
不安装恒真主机名验证器(`java:S5527`),不提供无校验的 `X509TrustManager`(`java:S4830`),
|
|
158
|
+
说明性注释不能替代证书与主机名校验。
|
|
159
|
+
- 外部进程/脚本执行、动态 URL/文件路径、重定向和 Header 需要输入来源核实(真实 Fortify 编号,
|
|
160
|
+
建议项);Jackson default typing 也需核实(`java:S4544`)。危险入口不代表已证实注入;
|
|
161
|
+
应校验输入并使用可信白名单,不能把没有阻断项当作数据流已验证。
|
|
162
|
+
|
|
163
|
+
## 打包前扫描模块
|
|
164
|
+
|
|
165
|
+
`compile_plugin_source.py` 会检查它编译的每个类。客户打包前仍需扫描整个源码目录,覆盖旧类、
|
|
166
|
+
SQL 脚本及误放的 jar:
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
{python} "{ROOT_DIR}/scripts/dcs_code_gate.py" --source "{projectRoot}" [--strict]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`status=true` 且 `findingCount=0` 表示在已检查输入中未发现阻断项,不表示全部 DCS 规则通过。
|
|
173
|
+
缺失路径(`missing`)、读取失败(`scanErrors`)或没有支持的源码及二进制发现的输入(`emptySources`)
|
|
174
|
+
均以退出码 2 失败,不能把空扫描报告为通过。
|
|
175
|
+
|
|
176
|
+
`ruleSource` 标识两表并集,`ruleSources` 保留来源选择和指纹,`catalogueMerge` 返回重叠/新增统计。
|
|
177
|
+
`coverage.cataloguedRuleCount=1582` 表示合并后的真实编号数,不计兼容别名,也不等于完整实现的
|
|
178
|
+
DCS 检查数。`coverage.complete=false` 和 `notCovered` 保留覆盖边界:最终 JAR/外部类名冲突、
|
|
179
|
+
元数据、KSC、TypeScript、空值流和全构建数据流/资源所有权等仍需对应 DCS 引擎;文本预检也可能
|
|
180
|
+
漏掉源码违规。本地预检降低返工风险,不能保证部署成功或替代 DCS 的最终检查。
|