@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.
Files changed (218) hide show
  1. package/package.json +1 -1
  2. package/skills/cosmic-build/LOCAL-PATCHES.md +43 -14
  3. package/skills/cosmic-build/SKILL.md +24 -9
  4. package/skills/cosmic-build/examples/java-rules/CosmicReportAggregation.java +26 -17
  5. package/skills/cosmic-build/examples/java-rules/CosmicReportFilters.java +96 -2
  6. package/skills/cosmic-build/knowledge/cosmic/arch/security/security_standard.md +4 -4
  7. package/skills/cosmic-build/knowledge/cosmic/platform/allimport.md +2 -1
  8. package/skills/cosmic-build/knowledge/cosmic/platform/core/dynamic-object-collection.md +6 -4
  9. package/skills/cosmic-build/knowledge/cosmic/platform/core/model.md +9 -9
  10. package/skills/cosmic-build/knowledge/cosmic/platform/core/view.md +5 -5
  11. package/skills/cosmic-build/knowledge/cosmic/platform/form-plugin.md +8 -4
  12. package/skills/cosmic-build/knowledge/cosmic/platform/list-plugin.md +5 -3
  13. package/skills/cosmic-build/knowledge/cosmic/platform/print-plugin-guide.md +1 -0
  14. package/skills/cosmic-build/knowledge/cosmic/platform/report-plugin.md +269 -57
  15. package/skills/cosmic-build/knowledge/cosmic/platform/reportlistdata-plugin.md +130 -23
  16. package/skills/cosmic-build/knowledge/cosmic/platform/reporttreedata-plugin.md +48 -28
  17. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/_index.md +12 -3
  18. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/common/attachment-name-process.md +17 -13
  19. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/common/dynamic-update-field.md +4 -4
  20. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/filter-grid/filter-grid-set-value.md +1 -1
  21. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-basedatafield.md +2 -3
  22. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-container-init.md +0 -1
  23. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-popup.md +0 -1
  24. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/filter-value-parse.md +5 -6
  25. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/list-show-form.md +1 -1
  26. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/control/list/query-field-dynamic.md +0 -7
  27. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/business-data/delete-service.md +24 -29
  28. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/ksql/db-batch.md +4 -0
  29. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/ksql/db-direct-access.md +4 -0
  30. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/qfilter/entity-object-access.md +8 -3
  31. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/data-access/qfilter/qfilter-compose.md +6 -5
  32. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/after-bind-data-set-visible.md +5 -1
  33. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/click-return-data.md +2 -2
  34. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/closed-call-back-set-value.md +2 -2
  35. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/register-listener.md +1 -1
  36. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/event/set-filter-tab-org.md +3 -0
  37. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/dispatch-service/microservice-dev.md +18 -11
  38. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/dist-lock/dist-lock-basic.md +3 -6
  39. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/mq/mq-subscribe.md +5 -1
  40. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/thread-pool/async-operation.md +10 -6
  41. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/thread-pool/big-task-async.md +4 -2
  42. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/infra/thread-pool/schedule-task.md +9 -7
  43. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/operation-interactive.md +33 -34
  44. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/operation/operation-plugin-events.md +30 -22
  45. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-async-query.md +133 -0
  46. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-batch-query.md +26 -22
  47. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-chart.md +112 -0
  48. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-dataset-assembly.md +200 -0
  49. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-head-filter.md +177 -0
  50. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-hyperlink-drill.md +216 -0
  51. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-list-data-query.md +12 -12
  52. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-merge-column.md +44 -6
  53. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-print-data.md +163 -0
  54. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-row-data-toolbar.md +188 -0
  55. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-subtotal-total.md +139 -0
  56. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-tree-data-query.md +108 -12
  57. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/report/report-tree-list.md +181 -0
  58. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/system-service/report-plugin-interface.md +3 -0
  59. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-basedata-cascade-confirm.md +14 -11
  60. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-before-item-validate.md +1 -1
  61. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-build-filter.md +1 -1
  62. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-multi-level-filter.md +11 -11
  63. package/skills/cosmic-build/knowledge/cosmic/platform/scenes/tree/tree-list-refresh-node.md +22 -15
  64. package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-algo.md +2 -2
  65. package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-entity-model.md +3 -4
  66. package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-exception.md +9 -5
  67. package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-orm-access.md +4 -0
  68. package/skills/cosmic-build/knowledge/cosmic/platform/sdk/sdk-request-context.md +7 -3
  69. package/skills/cosmic-build/knowledge/cosmic/platform/standards.md +28 -3
  70. package/skills/cosmic-build/references/compile-guide.md +36 -1
  71. package/skills/cosmic-build/references/dcs-code-rules.md +180 -0
  72. package/skills/cosmic-build/references/delivery.md +16 -2
  73. package/skills/cosmic-build/references/execution-contract.md +15 -3
  74. package/skills/cosmic-build/references/java-plugin-delivery.md +21 -11
  75. package/skills/cosmic-build/references/plugin-handoff-input.md +82 -24
  76. package/skills/cosmic-build/references/plugin-runtime-routing.md +23 -6
  77. package/skills/cosmic-build/references/report-filter-contract.md +53 -15
  78. package/skills/cosmic-build/references/sdk-inspection.md +4 -1
  79. package/skills/cosmic-build/references/type-registry.json +26 -17
  80. package/skills/cosmic-build/schemas/data-model-authoring.schema.json +1 -1
  81. package/skills/cosmic-build/scripts/_http_client.py +3 -0
  82. package/skills/cosmic-build/scripts/compile_plugin_source.py +251 -42
  83. package/skills/cosmic-build/scripts/configure_list.py +112 -0
  84. package/skills/cosmic-build/scripts/dcs-rule-catalog.json +799 -0
  85. package/skills/cosmic-build/scripts/dcs_code_gate.py +1976 -0
  86. package/skills/cosmic-build/scripts/execution_binding.py +25 -0
  87. package/skills/cosmic-build/scripts/platform_api_contract.py +352 -7
  88. package/skills/cosmic-build/scripts/plugin_source_gate.py +9 -1
  89. package/skills/cosmic-build/scripts/plugin_target_sdk.py +12 -8
  90. package/skills/cosmic-build/scripts/prepare_plugin_handoff.py +488 -88
  91. package/skills/cosmic-build/scripts/query_plugin_handoff.py +207 -20
  92. package/skills/cosmic-build/scripts/register_plugins.py +27 -10
  93. package/skills/cosmic-build/scripts/render_output_cards.py +57 -20
  94. package/skills/cosmic-build/scripts/resolve_output_path.py +60 -26
  95. package/skills/cosmic-build/scripts/run_java_tests.py +162 -0
  96. package/skills/cosmic-build/scripts/sync_generated_locale_assets.py +28 -0
  97. package/skills/cosmic-build/scripts/test/fixtures/ReportSdkCheck.java +1 -22
  98. package/skills/cosmic-build/scripts/test/fixtures/list_column_property_declarations.json +887 -0
  99. package/skills/cosmic-build/scripts/test/fixtures/operation-entry-field-prepare.java +78 -0
  100. package/skills/cosmic-build/scripts/test/test_add_field_required_contract.py +12 -0
  101. package/skills/cosmic-build/scripts/test/test_batch5_drift_governance.py +23 -2
  102. package/skills/cosmic-build/scripts/test/test_compile_plugin_source.py +287 -4
  103. package/skills/cosmic-build/scripts/test/test_configure_list_delivery.py +132 -0
  104. package/skills/cosmic-build/scripts/test/test_cosmic_sdk_examples.py +58 -1
  105. package/skills/cosmic-build/scripts/test/test_data_model_contract.py +19 -0
  106. package/skills/cosmic-build/scripts/test/test_dcs_code_gate.py +901 -0
  107. package/skills/cosmic-build/scripts/test/test_delivery_stage_boundary.py +1 -1
  108. package/skills/cosmic-build/scripts/test/test_direct_cli_architecture.py +2 -0
  109. package/skills/cosmic-build/scripts/test/test_http_client.py +6 -0
  110. package/skills/cosmic-build/scripts/test/test_java_toolchain_feedback.py +206 -0
  111. package/skills/cosmic-build/scripts/test/test_kd_api.py +21 -0
  112. package/skills/cosmic-build/scripts/test/test_list_configuration_closure.py +184 -0
  113. package/skills/cosmic-build/scripts/test/test_mcp_cli.py +139 -2
  114. package/skills/cosmic-build/scripts/test/test_menu_creation_closure.py +16 -0
  115. package/skills/cosmic-build/scripts/test/test_modeling_input_recovery.py +55 -1
  116. package/skills/cosmic-build/scripts/test/test_open_world_cli_catalog.py +1 -1
  117. package/skills/cosmic-build/scripts/test/test_operation_field_preparation.py +84 -0
  118. package/skills/cosmic-build/scripts/test/test_platform_api_contract.py +322 -1
  119. package/skills/cosmic-build/scripts/test/test_plugin_handoff.py +951 -4
  120. package/skills/cosmic-build/scripts/test/test_plugin_source_gate.py +30 -2
  121. package/skills/cosmic-build/scripts/test/test_plugin_target_sdk.py +21 -0
  122. package/skills/cosmic-build/scripts/test/test_property_reroute.py +165 -0
  123. package/skills/cosmic-build/scripts/test/test_property_schema_first.py +35 -0
  124. package/skills/cosmic-build/scripts/test/test_query_plugin_handoff.py +221 -0
  125. package/skills/cosmic-build/scripts/test/test_register_plugins.py +76 -4
  126. package/skills/cosmic-build/scripts/test/test_render_output_cards.py +75 -3
  127. package/skills/cosmic-build/scripts/test/test_report_business_contract.py +27 -5
  128. package/skills/cosmic-build/scripts/test/test_report_doc_contract_sync.py +103 -11
  129. package/skills/cosmic-build/scripts/test/test_report_plugin_source_gate.py +46 -16
  130. package/skills/cosmic-build/scripts/test/test_report_properties.py +74 -15
  131. package/skills/cosmic-build/scripts/test/test_report_query_data_source.py +3 -1
  132. package/skills/cosmic-build/scripts/test/test_report_sdk_optimization.py +1 -2
  133. package/skills/cosmic-build/scripts/test/test_test_environment.py +76 -1
  134. package/skills/cosmic-build/scripts/test_environment.py +67 -1
  135. package/skills/cosmic-build/skills/cosmic-coding-impl/SKILL.md +52 -10
  136. package/skills/cosmic-build/skills/cosmic-meta-api/apis/ai_meta.md +16 -3
  137. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/report-write-contracts.json +59 -26
  138. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/cli/rule-domain.json +1 -1
  139. package/skills/cosmic-build/skills/cosmic-meta-api/contracts/schema/report-write.schema.json +75 -18
  140. package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/scripts/pdm_auto.py +39 -0
  141. package/skills/cosmic-build/skills/cosmic-meta-api/modules/pdm/scripts/pdm_client.py +97 -10
  142. package/skills/cosmic-build/skills/cosmic-meta-api/modules/verify/SKILL.md +10 -12
  143. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_apps.py +3 -1
  144. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_formactions.py +38 -29
  145. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_listui.py +400 -233
  146. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_metaops.py +87 -45
  147. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_properties.py +42 -15
  148. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/cmd_rules.py +135 -5
  149. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/config.py +1 -1
  150. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/execution_errors.py +1 -1
  151. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/formatters.py +17 -11
  152. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/property_reroute.py +15 -5
  153. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/report_ops.py +1429 -238
  154. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/_core/validators.py +56 -28
  155. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/cosmic_api.py +380 -134
  156. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/field_decorator.py +1 -1
  157. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/meta_export.py +12 -11
  158. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/meta_verifier.py +42 -0
  159. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_add_field_placement_closure.py +8 -8
  160. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_build_configuration_readback.py +94 -0
  161. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_build_receipt_resume.py +47 -1
  162. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_metadata_unchanged_fail_closed.py +87 -0
  163. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_dym_evidence.py +23 -23
  164. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_entity_integrity.py +279 -4
  165. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_field_guard.py +1 -1
  166. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_plugin_contract.py +509 -32
  167. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_readback_derivation.py +178 -1
  168. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_recreate_plan.py +125 -10
  169. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_serve_contract.py +208 -0
  170. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_report_typed_filters.py +259 -50
  171. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_rule_inventory_perf.py +29 -0
  172. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_rule_write_closure.py +20 -0
  173. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_post_build_recovery.py +18 -0
  174. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_batch_verification_evidence.py +35 -0
  175. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_run_identity_guard.py +25 -0
  176. package/skills/cosmic-build/skills/cosmic-meta-api/scripts/test/test_time_range_rule.py +98 -0
  177. package/skills/cosmic-build/skills/cosmic-meta-knowledge/domain-model/report-model.md +20 -9
  178. package/skills/cosmic-build/skills/cosmic-meta-knowledge/generation/report-modeling-guide.md +55 -25
  179. package/skills/cosmic-build/skills/cosmic-meta-knowledge/property-guides/report-column-properties.md +15 -39
  180. package/skills/cosmic-build/skills/cosmic-meta-modeling/SKILL.md +19 -17
  181. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/SKILL.md +82 -38
  182. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/examples/golden-example-report-batch.md +64 -19
  183. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/examples/golden-example-report-plugin.md +32 -20
  184. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/examples/golden-example-report-tree.md +78 -31
  185. package/skills/cosmic-build/skills/cosmic-meta-modeling/modules/report/report-artifact-schema.json +2 -1
  186. package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-companion-fields.md +3 -0
  187. package/skills/cosmic-build/skills/cosmic-meta-modeling/references/authoring-list-configuration.md +2 -0
  188. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_contract.py +3 -1
  189. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/data_model_emit.py +27 -4
  190. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/report_validator.py +99 -44
  191. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/test_report_examples.py +31 -4
  192. package/skills/cosmic-build/skills/cosmic-meta-modeling/scripts/test_report_validator.py +129 -29
  193. package/skills/cosmic-build/skills/cosmic-meta-modifier/SKILL.md +6 -2
  194. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/operation/validation.md +2 -0
  195. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/property/SKILL.md +1 -1
  196. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/report-op/SKILL.md +104 -25
  197. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/rule/SKILL.md +9 -0
  198. package/skills/cosmic-build/skills/cosmic-meta-modifier/modules/verify/usage-guide.md +2 -2
  199. package/skills/cosmic-build/skills/cosmic-meta-modifier/references/list-filter-modification.md +39 -12
  200. package/skills/cosmic-build/skills/mcp-server/SKILL.md +39 -24
  201. package/skills/cosmic-build/skills/mcp-server/scripts/mcp_cli.py +20 -6
  202. package/skills/cosmic-dev-best-practices/SKILL.md +1 -1
  203. package/skills/cosmic-dev-best-practices/references/README.md +2 -2
  204. package/skills/cosmic-dev-best-practices/references/basedata-dev-convention.md +2 -2
  205. package/skills/cosmic-dev-best-practices/references/bill-dev-convention.md +4 -4
  206. package/skills/cosmic-dev-best-practices/references/design-document-convention.md +2 -2
  207. package/skills/cosmic-dev-best-practices/references/design-examples/basedata-design-example.md +4 -4
  208. package/skills/cosmic-dev-best-practices/references/design-examples/bill-design-example.md +13 -13
  209. package/skills/cosmic-dev-best-practices/references/elements/CustomerField.md +1 -1
  210. package/skills/cosmic-dev-best-practices/references/elements/README.md +1 -1
  211. package/skills/cosmic-dev-best-practices/references/elements/SupplierField.md +1 -1
  212. package/skills/cosmic-dev-best-practices/references/elements/common-field-property-conventions.md +109 -13
  213. package/skills/cosmic-dev-best-practices/references/layout-control-convention.md +1 -1
  214. package/skills/erp-analysis/references/delivery-contract.md +2 -1
  215. package/skills/erp-analysis/templates/AGENTS.template.md +3 -1
  216. package/skills/cosmic-build/assets/platform-report-filters/TypedReportFilterFields.java +0 -169
  217. package/skills/cosmic-build/assets/platform-report-filters/platform.patch +0 -98
  218. package/skills/cosmic-build/scripts/apply_report_filter_extension.py +0 -39
@@ -5,14 +5,14 @@ source_doc: "bos-runtime-plugin 报表示例"
5
5
  last_updated: "2026-04-03"
6
6
  status: "approved"
7
7
  scene_name: "报表数据查询插件"
8
- related_apis: ["AbstractReportListDataPlugin", "query", "getColumns", "ReportQueryParam", "DataSet", "ReportColumn", "Algo", "ORM", "QFilter", "BusinessDataServiceHelper"]
8
+ related_apis: ["AbstractReportListDataPlugin", "query", "getColumns", "ReportQueryParam", "DataSet", "ReportColumn", "Algo", "QueryServiceHelper.queryDataSet", "QFilter", "BusinessDataServiceHelper"]
9
9
  topic: "报表数据查询"
10
10
  ---
11
11
 
12
12
  # 场景:报表数据查询插件
13
13
 
14
14
  ## 适用情况
15
- 实现报表的数据查询逻辑,包括通过 ORM 查询数据库、通过 Algo 构建内存数据集、动态添加报表列等。适用于分组报表左右列表取数、树形报表明细取数、自定义数据源报表等场景。报表数据查询插件从 `AbstractReportListDataPlugin` 派生。
15
+ 实现报表的数据查询逻辑,包括通过 `QueryServiceHelper` 查询数据库、通过 Algo 构建内存数据集、动态添加报表列等。适用于分组报表左右列表取数、树形报表明细取数、自定义数据源报表等场景。报表数据查询插件从 `AbstractReportListDataPlugin` 派生。
16
16
 
17
17
  ## 事件/方法说明
18
18
 
@@ -21,7 +21,7 @@ topic: "报表数据查询"
21
21
  - `ReportColumn.setFieldKey(key)`:设置列标识,必须与 DataSet 中的字段名一致
22
22
  - `ReportColumn.setCaption(LocaleString)`:设置列标题
23
23
  - `ReportColumn.setFieldType(type)`:设置列类型(TYPE_TEXT、TYPE_BASEDATA 等)
24
- - `ORM.create().queryDataSet(...)`:通过 ORM 查询数据库返回 DataSet
24
+ - `QueryServiceHelper.queryDataSet(...)`:查询数据库并返回 DataSet;DCS 禁止 `kd.bos.orm.ORM`(`CVE-KD-2026-0508`)
25
25
  - `Algo.create(key).createDataSet(input)`:通过 Algo 构建内存 DataSet
26
26
  - `BusinessDataServiceHelper.loadSingleFromCache(...)`:从缓存加载基础资料
27
27
 
@@ -39,7 +39,7 @@ public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns)
39
39
  ## 代码示例
40
40
  `extracted` `needs-verification`
41
41
 
42
- 通过 ORM 查询数据库并动态添加列:
42
+ 通过查询服务读取数据并动态添加列:
43
43
 
44
44
  ```java
45
45
  package kd.bos.plugin.sample.report.bizcase;
@@ -51,24 +51,24 @@ import kd.bos.entity.report.AbstractReportColumn;
51
51
  import kd.bos.entity.report.AbstractReportListDataPlugin;
52
52
  import kd.bos.entity.report.ReportColumn;
53
53
  import kd.bos.entity.report.ReportQueryParam;
54
- import kd.bos.orm.ORM;
55
54
  import kd.bos.orm.query.QFilter;
55
+ import kd.bos.servicehelper.QueryServiceHelper;
56
56
 
57
57
  public class ReportListDataQuerySample extends AbstractReportListDataPlugin {
58
58
 
59
59
  @Override
60
60
  public DataSet query(ReportQueryParam queryParam, Object selectedObj) throws Throwable {
61
- ORM orm = ORM.create();
61
+ List<QFilter> filters = queryParam.getFilter().getHeadFilters();
62
62
  String selectedField = "number,name,parent as pid,isleaf,id as rowid";
63
- return orm.queryDataSet(getClass().getName(),
63
+ return QueryServiceHelper.queryDataSet(getClass().getName(),
64
64
  "kdtest_basedata_tree",
65
65
  selectedField,
66
- queryParam.getFilter().getHeadFilters().toArray(new QFilter[0]),
66
+ filters.toArray(new QFilter[filters.size()]),
67
67
  queryParam.getSortInfo());
68
68
  }
69
69
 
70
70
  @Override
71
- public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) {
71
+ public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {
72
72
  super.getColumns(columns);
73
73
  ReportColumn numberColumn = new ReportColumn();
74
74
  numberColumn.setCaption(new LocaleString("工号"));
@@ -122,7 +122,7 @@ public class ReportAlgoDataSample extends AbstractReportListDataPlugin {
122
122
  }
123
123
 
124
124
  @Override
125
- public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) {
125
+ public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {
126
126
  super.getColumns(columns);
127
127
  Set<String> keys = new HashSet<>(columns.size());
128
128
  for (AbstractReportColumn col : columns) {
@@ -201,7 +201,7 @@ public class ReportGroupRightDataSample extends AbstractReportListDataPlugin {
201
201
  }
202
202
 
203
203
  @Override
204
- public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) {
204
+ public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {
205
205
  super.getColumns(columns);
206
206
  ReportColumn col = new ReportColumn();
207
207
  col.setFieldKey("orgnumber");
@@ -220,4 +220,4 @@ public class ReportGroupRightDataSample extends AbstractReportListDataPlugin {
220
220
  - 动态生成的列不要设置 `dataIndex`,只需设置 `fieldKey` 并确保和 DataSet 中的字段名一致
221
221
  - 基础资料类型列需设置 `entityId`(引用实体标识)和 `displayProp`(显示属性)
222
222
  - 分组报表中,右侧列表的 `selectedObj` 参数为左侧选中行的数据对象
223
- - ORM 查询的 `selectFields` 支持 `as` 别名语法
223
+ - 查询的 `selectFields` 支持 `as` 别名语法
@@ -7,7 +7,7 @@ status: "approved"
7
7
  scene_name: "报表列合并"
8
8
  trigger_event: "setMergeColums"
9
9
  scene_keywords: ["setMergeColums", "ReportColumnMerge", "报表合并", "列合并", "packageData", "noMergeKey", "AbstractReportFormPlugin"]
10
- related_apis: ["AbstractReportFormPlugin.setMergeColums", "AbstractReportFormPlugin.packageData", "PackageDataEvent.getNoMergeKey"]
10
+ related_apis: ["AbstractReportFormPlugin.setMergeColums", "AbstractReportFormPlugin.packageData", "PackageDataEvent.getNoMergeKey", "ReportExportInitializeEvent.setMergeColumnRules"]
11
11
  ---
12
12
 
13
13
  # 场景:报表列合并
@@ -18,6 +18,7 @@ related_apis: ["AbstractReportFormPlugin.setMergeColums", "AbstractReportFormPlu
18
18
  ## 事件含义
19
19
  - `setMergeColums`:在报表渲染前触发,向 `columns` 列表中添加需要合并的字段标识
20
20
  - `packageData`:在数据打包时触发,可以通过 `getNoMergeKey()` 排除特定行的合并
21
+ - `exportInitialize`:导出开始时触发;`setMergeColumnRules(rules)` 设置导出文件如何合并单元格,这不由界面上的合并决定
21
22
 
22
23
  ## 涉及的核心对象(必读)
23
24
  | 对象 | 用途 | 文档路径 |
@@ -82,10 +83,14 @@ public class XxxMergeReportPlugin extends AbstractReportFormPlugin {
82
83
  @Override
83
84
  public void packageData(PackageDataEvent packageDataEvent) {
84
85
  super.packageData(packageDataEvent);
86
+ // source 是单元格所在的列;强转前先判断类型
87
+ if (!(packageDataEvent.getSource() instanceof ReportColumn)) {
88
+ return;
89
+ }
85
90
  ReportColumn column = (ReportColumn) packageDataEvent.getSource();
86
91
  // 当文本列的值为"小计"时,排除该行的合并
87
92
  if ("text_field".equals(column.getFieldKey())
88
- && "小计".equals(packageDataEvent.getFormatValue().toString())) {
93
+ && "小计".equals(String.valueOf(packageDataEvent.getFormatValue()))) {
89
94
  // 将当前列加入不合并列表,该行不参与合并
90
95
  packageDataEvent.getNoMergeKey().add(column.getFieldKey());
91
96
  }
@@ -103,9 +108,9 @@ import kd.bos.entity.report.FilterItemInfo;
103
108
  import kd.bos.entity.report.ReportColumn;
104
109
  import kd.bos.entity.report.ReportQueryParam;
105
110
  import kd.bos.metadata.entity.report.ReportColumnFactory;
106
- import kd.bos.orm.ORM;
107
111
  import kd.bos.orm.query.QCP;
108
112
  import kd.bos.orm.query.QFilter;
113
+ import kd.bos.servicehelper.QueryServiceHelper;
109
114
 
110
115
  import java.util.ArrayList;
111
116
  import java.util.List;
@@ -124,11 +129,10 @@ public class XxxReportQueryPlugin extends AbstractReportListDataPlugin {
124
129
  info.getValue()));
125
130
  }
126
131
  });
127
- ORM orm = ORM.create();
128
132
  String selectField = "text_field, integer_field, datetime_field";
129
- return orm.queryDataSet(getClass().getName(),
133
+ return QueryServiceHelper.queryDataSet(getClass().getName(),
130
134
  "target_entity", selectField,
131
- filters.toArray(new QFilter[0]), null);
135
+ filters.toArray(new QFilter[filters.size()]), null);
132
136
  }
133
137
 
134
138
  @Override
@@ -148,9 +152,43 @@ public class XxxReportQueryPlugin extends AbstractReportListDataPlugin {
148
152
  }
149
153
  ```
150
154
 
155
+ ### 示例4:导出文件合并单元格
156
+ ```java
157
+ import java.util.ArrayList;
158
+ import java.util.List;
159
+
160
+ import kd.bos.report.events.MergeColumnRule;
161
+ import kd.bos.report.events.ReportExportInitializeEvent;
162
+ import kd.bos.report.plugin.AbstractReportFormPlugin;
163
+
164
+ public class XxxExportMergeReportPlugin extends AbstractReportFormPlugin {
165
+
166
+ @Override
167
+ public void exportInitialize(ReportExportInitializeEvent event) {
168
+ super.exportInitialize(event);
169
+ List<MergeColumnRule> rules = new ArrayList<>(1);
170
+
171
+ // 分组字段:分组值相同的行构成一个合并区间
172
+ List<String> groupColumns = new ArrayList<>(2);
173
+ groupColumns.add("type");
174
+ groupColumns.add("amount");
175
+
176
+ // 合并字段:在每个区间内合并,不管它们自己相邻行的值是否相同
177
+ List<String> mergeColumns = new ArrayList<>(2);
178
+ mergeColumns.add("amount");
179
+ mergeColumns.add("currency");
180
+
181
+ rules.add(new MergeColumnRule(groupColumns, mergeColumns));
182
+ event.setMergeColumnRules(rules);
183
+ }
184
+ }
185
+ ```
186
+
151
187
  ## 注意事项
152
188
  - `setMergeColums` 中添加的字段标识必须与报表列定义中的 `fieldKey` 一致
153
189
  - 合并规则:相邻行中指定列的值完全相同时自动合并,值不同时断开
154
190
  - `packageData` 中通过 `getNoMergeKey().add()` 可以排除特定行的合并,适用于小计行、合计行等
155
191
  - 列合并仅影响显示效果,不影响数据查询和导出
192
+ - 导出文件改按 `exportInitialize` 的规则合并。一个合并字段只能属于一条规则。合并跟随分组字段:只要分组字段的值相同,合并字段就合并,不会比较合并字段自己相邻行的值——所以值也必须相同的合并字段要同时列入分组字段,就像示例4中的 `amount`
193
+ - 强转前用 `instanceof ReportColumn` 检查 `packageDataEvent.getSource()`,可能为 null 的值用 `String.valueOf(...)` 比较
156
194
  - 报表表单插件(`AbstractReportFormPlugin`)和报表数据查询插件(`AbstractReportListDataPlugin`)需要配合使用
@@ -0,0 +1,163 @@
1
+ ---
2
+ version: "1.0.0"
3
+ framework_version: "8.0.1"
4
+ source_doc: "标品报表案例 10"
5
+ last_updated: "2026-10-19"
6
+ status: "approved"
7
+ scene_name: "报表打印数据"
8
+ related_apis: ["AfterLoadDataEvent.getDataSource", "AfterLoadDataEvent.setDataRowSets", "CustomDataLoadEvent.getDataSource", "CustomDataLoadEvent.getCustomDataRows", "MainDataSource.getPageId", "CustomDataSource.getPageId", "CustomDataSource.getPkId", "CustomDataSource.getDsName", "CustomDataSource.getQueryField", "DataRowSet.put", "ReportView.getReportList", "ReportListModel.getRowData", "ReportListModel.getRowCount", "DynamicObject.getString", "DynamicObject.get"]
9
+ topic: "报表打印"
10
+ ---
11
+
12
+ # 场景:报表打印数据
13
+
14
+ ## 适用情况
15
+ 报表通过打印模板打印,但报表没有可供打印引擎加载的实体数据:它的行在报表页面的列表模型里。打印插件(`printplugin`,继承 `kd.bos.print.core.plugin.AbstractPrintPlugin`)从该模型取出行,交给模板的数据源——主数据源决定打印多少页,自定义数据源填充每一页。示例按物料分页打印:每页一个页头和该物料的行。
16
+
17
+ ## 事件/方法说明
18
+
19
+ - `afterLoadData(AfterLoadDataEvent)`:对主数据源(`getDataSource() instanceof MainDataSource`),`getPageId()` 是报表页面的标识;`setDataRowSets(rows)` 为每个打印页设置一行
20
+ - `loadCustomData(CustomDataLoadEvent)`:每个自定义数据源、每一页触发一次;`getDataSource()` 是 `CustomDataSource`,其 `getDsName()` 是它在模板中的名称,`getPkId()` 是该页所属主数据行的 `id`,`getPageId()` 是报表页面,`getQueryField()` 是模板使用的字段;把行加到 `getCustomDataRows()` 中
21
+ - `SessionManager.getCurrent().getView(pageId)`:报表页面的视图;`((ReportView) view).getReportList().getReportModel()` 是它的列表模型
22
+ - `ReportListModel.getRowCount()` / `getRowData(startIndex, length)`:报表的行,以列名为键的 `DynamicObject`
23
+ - `DataRowSet.put(fieldKey, new TextField(text))`:一个打印行,每个模板字段一个值
24
+
25
+ ## 方法签名
26
+ ```java
27
+ public class MyReportPrintPlugin extends AbstractPrintPlugin
28
+
29
+ @Override
30
+ public void afterLoadData(AfterLoadDataEvent evt)
31
+
32
+ @Override
33
+ public void loadCustomData(CustomDataLoadEvent evt)
34
+ ```
35
+
36
+ ## 代码示例
37
+ `extracted` `needs-verification`
38
+
39
+ 每个物料打印一页,页头和行都取自报表页面的模型:
40
+
41
+ ```java
42
+ package kd.bos.plugin.sample.report.print;
43
+
44
+ import java.util.ArrayList;
45
+ import java.util.HashMap;
46
+ import java.util.List;
47
+ import java.util.Map;
48
+ import java.util.Objects;
49
+
50
+ import kd.bos.cache.ThreadCache;
51
+ import kd.bos.dataentity.entity.DynamicObject;
52
+ import kd.bos.dataentity.entity.DynamicObjectCollection;
53
+ import kd.bos.mvc.SessionManager;
54
+ import kd.bos.mvc.report.ReportListModel;
55
+ import kd.bos.mvc.report.ReportView;
56
+ import kd.bos.print.core.data.DataRowSet;
57
+ import kd.bos.print.core.data.datasource.CustomDataSource;
58
+ import kd.bos.print.core.data.datasource.MainDataSource;
59
+ import kd.bos.print.core.data.datasource.PrtDataSource;
60
+ import kd.bos.print.core.data.field.TextField;
61
+ import kd.bos.print.core.plugin.AbstractPrintPlugin;
62
+ import kd.bos.print.core.plugin.event.AfterLoadDataEvent;
63
+ import kd.bos.print.core.plugin.event.CustomDataLoadEvent;
64
+
65
+ public class StockDetailReportPrintPlugin extends AbstractPrintPlugin {
66
+
67
+ // 页 id -> {首行, 行数},留给同一请求中的自定义数据源使用
68
+ private static final String PAGE_RANGES = "StockDetailReportPrintPlugin_pageRanges";
69
+ private static final String PAGE_HEAD = "printhead";
70
+ private static final String[] DETAIL_FIELDS = {"billno", "bizdate", "qty", "amount"};
71
+
72
+ @Override
73
+ public void afterLoadData(AfterLoadDataEvent evt) {
74
+ super.afterLoadData(evt);
75
+ PrtDataSource source = evt.getDataSource();
76
+ if (!(source instanceof MainDataSource)) {
77
+ return;
78
+ }
79
+ ReportListModel model = reportModel(((MainDataSource) source).getPageId());
80
+ if (model == null) {
81
+ return;
82
+ }
83
+ DynamicObjectCollection rows = model.getRowData(0, model.getRowCount());
84
+ Map<String, int[]> ranges = new HashMap<>(16);
85
+ List<DataRowSet> pages = new ArrayList<>(16);
86
+ int start = 0;
87
+ for (int i = 1; i <= rows.size(); i++) {
88
+ boolean pageEnds = i == rows.size()
89
+ || !Objects.equals(rows.get(i).getString("material"), rows.get(start).getString("material"));
90
+ if (pageEnds) {
91
+ // 主数据行的 "id" 会作为自定义数据源的 pkId 传回
92
+ String pageId = String.valueOf(start);
93
+ DataRowSet page = new DataRowSet();
94
+ page.put("id", new TextField(pageId));
95
+ pages.add(page);
96
+ ranges.put(pageId, new int[]{start, i - start});
97
+ start = i;
98
+ }
99
+ }
100
+ ThreadCache.put(PAGE_RANGES, ranges);
101
+ evt.setDataRowSets(pages);
102
+ }
103
+
104
+ @Override
105
+ public void loadCustomData(CustomDataLoadEvent evt) {
106
+ super.loadCustomData(evt);
107
+ CustomDataSource source = evt.getDataSource();
108
+ ReportListModel model = reportModel(source.getPageId());
109
+ Object ranges = ThreadCache.get(PAGE_RANGES);
110
+ if (model == null || !(ranges instanceof Map) || source.getPkId() == null) {
111
+ return;
112
+ }
113
+ int[] range = (int[]) ((Map<?, ?>) ranges).get(String.valueOf(source.getPkId()));
114
+ if (range == null) {
115
+ return;
116
+ }
117
+ // 起始行与行数
118
+ DynamicObjectCollection rows = model.getRowData(range[0], range[1]);
119
+ List<DataRowSet> printRows = evt.getCustomDataRows();
120
+ if (PAGE_HEAD.equals(source.getDsName())) {
121
+ DataRowSet head = new DataRowSet();
122
+ head.put("material", new TextField(rows.get(0).getString("material")));
123
+ printRows.add(head);
124
+ return;
125
+ }
126
+ // 明细行:只给模板要的字段
127
+ List<String> wanted = source.getQueryField();
128
+ int seq = 1;
129
+ for (DynamicObject row : rows) {
130
+ DataRowSet printRow = new DataRowSet();
131
+ printRow.put("seq", new TextField(String.valueOf(seq++)));
132
+ for (String field : DETAIL_FIELDS) {
133
+ if (wanted == null || wanted.contains(field)) {
134
+ Object value = row.get(field);
135
+ printRow.put(field, new TextField(value == null ? "" : String.valueOf(value)));
136
+ }
137
+ }
138
+ printRows.add(printRow);
139
+ }
140
+ }
141
+
142
+ // 报表没有实体行:打印它页面列表模型里的内容
143
+ private static ReportListModel reportModel(String pageId) {
144
+ Object view = SessionManager.getCurrent().getView(pageId);
145
+ if (!(view instanceof ReportView)) {
146
+ return null;
147
+ }
148
+ Object model = ((ReportView) view).getReportList().getReportModel();
149
+ return model instanceof ReportListModel ? (ReportListModel) model : null;
150
+ }
151
+ }
152
+ ```
153
+
154
+ ## 注意事项
155
+ - 打印插件是注册在打印模板上的 `printplugin` 类,不是报表插件;报表页面只负责发起打印。它的指南是 `print-plugin-guide.md`
156
+ - 主数据源决定打印多少页:每页一个 `DataRowSet`,它的 `id` 会以 `getPkId()` 传回给该页的每个自定义数据源。标品代码把 `id` 标注为页行必须携带的值
157
+ - `getRowData(startIndex, length)` 接收起始行和行数;页范围把两者都记下来
158
+ - `ThreadCache` 把页范围从主数据源带给同一个打印请求中的自定义数据源。它只在一个线程上有效:如果打印在另一个线程上加载数据,页范围就丢了——标品的兜底是由打印发起方直接把列表模型放进 `ThreadCache`
159
+ - 模板字段与插件字段按名称对应;`getQueryField()` 列出模板的字段,模板没有的字段就跳过。新增打印字段要同时改模板和插件
160
+ - 数字以文本打印:在 `new TextField(...)` 之前用用户的格式(`InteServiceHelper.getUserFormat(userId)`,再用 `FormatFactory.get(FormatTypes.Number)` 或 `FormatTypes.Currency`,配上行上的精度与货币符号)格式化;标品默认不打印零值
161
+ - 主数据源要读取模型的所有行来分页,所以超大报表要注意内存
162
+ - 旧版 API `kd.bos.entity.plugin.AbstractPrintServicePlugin.customPrintDataEntities` 在一个方法里用 `DynamicObject` 行完成同样的事;新开发使用 `AbstractPrintPlugin`(`kd.bos.print.core.*`)
163
+ - 8.0 SDK 同时声明了 `DataRowSet.put(String, Field)` 和 `DataRowSet.add(String, Field)`;8.0.1 参考记载的是 `put`,标品示例写的是 `add`。本页用有文档记载的 `put`
@@ -0,0 +1,188 @@
1
+ ---
2
+ version: "1.0.0"
3
+ framework_version: "8.0.1"
4
+ source_doc: "报表插件示例 示例2;标品报表案例 03"
5
+ last_updated: "2026-10-19"
6
+ status: "approved"
7
+ scene_name: "报表工具栏按钮与行数据"
8
+ related_apis: ["ReportList.getReportModel", "ReportList.getTotalRecords", "ReportList.setSelectedAll", "IReportListModel.getRowData", "ReportListModel.getRowData", "IPageCache.put", "IPageCache.get", "ListShowParameter.setBillFormId", "ListShowParameter.setListFilterParameter", "QFilter.of", "DynamicObject.getDynamicObject", "DynamicObject.getPkValue"]
9
+ topic: "报表表单插件"
10
+ ---
11
+
12
+ # 场景:报表工具栏按钮与行数据
13
+
14
+ ## 适用情况
15
+ 报表工具栏按钮作用于报表行:打开当前行背后的单据、处理所有选中行、由某一行生成单据。`reportform` 插件把按钮路由到 `itemClick`,找到行(`itemClick` 本身不带行),再从报表模型读出该行——每一行都以取数插件 DataSet 的列名为键。
16
+
17
+ ## 事件/方法说明
18
+
19
+ - `addItemClickListeners("toolbarap")`:把工具栏按钮路由到 `itemClick`;不注册,任何按钮都到不了插件。在 `registerListener` 中调用
20
+ - `itemClick(ItemClickEvent)`:`evt.getItemKey()` 是被点击的工具栏项标识
21
+ - `ReportList.addCellClickListener(CellClickListener)`:`cellClick(CellClickEvent)` 给出被点击的行,`e.getRow()`
22
+ - `getPageCache()`:页面级字符串缓存(`put(key, value)` / `get(key)`),把单元格点击时的行号带到按钮点击时
23
+ - `reportList.getReportModel().getRowData(rowIndex)`:以 `DynamicObject` 返回一行
24
+ - `ReportList.setSelectedAll(true)`:允许用户全选结果中的所有行;在 `beforeQuery` 中设置
25
+ - `IReportListModel.getRowData(startIndex, length, onlyWithSelectedRows)`:一段行,最后一个参数为 `true` 时只取选中行
26
+ - `ReportList.getTotalRecords()`:结果的总行数
27
+
28
+ ## 方法签名
29
+ ```java
30
+ @Override
31
+ public void registerListener(EventObject e)
32
+
33
+ @Override
34
+ public void itemClick(ItemClickEvent evt)
35
+
36
+ @Override
37
+ public void beforeQuery(ReportQueryParam queryParam)
38
+ ```
39
+
40
+ ## 代码示例
41
+ `extracted` `needs-verification`
42
+
43
+ 当前行:缓存被点击的行,再打开它背后的单据列表:
44
+
45
+ ```java
46
+ package kd.bos.plugin.sample.report.bizcase;
47
+
48
+ import java.util.Date;
49
+ import java.util.EventObject;
50
+
51
+ import kd.bos.dataentity.entity.DynamicObject;
52
+ import kd.bos.dataentity.resource.ResManager;
53
+ import kd.bos.entity.report.IReportListModel;
54
+ import kd.bos.form.IPageCache;
55
+ import kd.bos.form.ShowType;
56
+ import kd.bos.form.control.events.CellClickEvent;
57
+ import kd.bos.form.control.events.CellClickListener;
58
+ import kd.bos.form.control.events.ItemClickEvent;
59
+ import kd.bos.list.ListFilterParameter;
60
+ import kd.bos.list.ListShowParameter;
61
+ import kd.bos.orm.query.QFilter;
62
+ import kd.bos.report.ReportList;
63
+ import kd.bos.report.plugin.AbstractReportFormPlugin;
64
+
65
+ public class ToolbarReportFormPlugin extends AbstractReportFormPlugin {
66
+
67
+ private static final String TOOLBAR_KEY = "toolbarap";
68
+ private static final String REPORT_LIST_KEY = "reportlistap";
69
+ private static final String ROW_INDEX = "rowIndex";
70
+
71
+ @Override
72
+ public void registerListener(EventObject e) {
73
+ super.registerListener(e);
74
+ // 把工具栏按钮路由到 itemClick
75
+ this.addItemClickListeners(TOOLBAR_KEY);
76
+ // itemClick 不带当前行:记住用户最后点击的行
77
+ ReportList reportList = this.getControl(REPORT_LIST_KEY);
78
+ IPageCache pageCache = this.getPageCache();
79
+ reportList.addCellClickListener(new CellClickListener() {
80
+ @Override
81
+ public void cellClick(CellClickEvent event) {
82
+ pageCache.put(ROW_INDEX, String.valueOf(event.getRow()));
83
+ }
84
+
85
+ @Override
86
+ public void cellDoubleClick(CellClickEvent event) {
87
+ }
88
+ });
89
+ }
90
+
91
+ @Override
92
+ public void itemClick(ItemClickEvent evt) {
93
+ super.itemClick(evt);
94
+ if ("viewbillbtn".equals(evt.getItemKey())) {
95
+ showBillList();
96
+ }
97
+ }
98
+
99
+ private void showBillList() {
100
+ String rowIndex = this.getPageCache().get(ROW_INDEX);
101
+ if (rowIndex == null || rowIndex.isEmpty()) {
102
+ this.getView().showTipNotification(ResManager.loadKDString("请先选择一行数据。", "ToolbarReportFormPlugin_0", "xxx-report"));
103
+ return;
104
+ }
105
+ ReportList reportList = this.getControl(REPORT_LIST_KEY);
106
+ IReportListModel model = reportList.getReportModel();
107
+ // 行以取数插件 DataSet 的列名为键
108
+ DynamicObject row = model.getRowData(Integer.parseInt(rowIndex));
109
+ // 基础资料列取出来是 DynamicObject,主键用 getPkValue()
110
+ Object companyId = row.getDynamicObject("companycol").getPkValue();
111
+ Date startDate = row.getDate("startdatecol");
112
+ Date endDate = row.getDate("enddatecol");
113
+
114
+ ListShowParameter parameter = new ListShowParameter();
115
+ parameter.setFormId("bos_list");
116
+ parameter.setBillFormId(row.getString("billformidcol"));
117
+ parameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
118
+ ListFilterParameter listFilter = new ListFilterParameter();
119
+ listFilter.setFilter(QFilter.of("company = ? and bizdate >= ? and bizdate <= ?", companyId, startDate, endDate));
120
+ parameter.setListFilterParameter(listFilter);
121
+ this.getView().showForm(parameter);
122
+ }
123
+ }
124
+ ```
125
+
126
+ 所有选中行:查询前开启全选,点击时读出选中行:
127
+
128
+ ```java
129
+ package kd.bos.plugin.sample.report.bizcase;
130
+
131
+ import java.util.EventObject;
132
+
133
+ import kd.bos.dataentity.entity.DynamicObject;
134
+ import kd.bos.dataentity.entity.DynamicObjectCollection;
135
+ import kd.bos.dataentity.resource.ResManager;
136
+ import kd.bos.entity.report.IReportListModel;
137
+ import kd.bos.entity.report.ReportQueryParam;
138
+ import kd.bos.form.control.events.ItemClickEvent;
139
+ import kd.bos.report.ReportList;
140
+ import kd.bos.report.plugin.AbstractReportFormPlugin;
141
+
142
+ public class SelectAllReportFormPlugin extends AbstractReportFormPlugin {
143
+
144
+ @Override
145
+ public void registerListener(EventObject e) {
146
+ super.registerListener(e);
147
+ this.addItemClickListeners("toolbarap");
148
+ }
149
+
150
+ @Override
151
+ public void beforeQuery(ReportQueryParam queryParam) {
152
+ super.beforeQuery(queryParam);
153
+ ReportList reportList = this.getControl("reportlistap");
154
+ // 允许用户全选结果中的所有行
155
+ reportList.setSelectedAll(true);
156
+ }
157
+
158
+ @Override
159
+ public void itemClick(ItemClickEvent evt) {
160
+ super.itemClick(evt);
161
+ if (!"processbtn".equals(evt.getItemKey())) {
162
+ return;
163
+ }
164
+ ReportList reportList = this.getControl("reportlistap");
165
+ IReportListModel model = reportList.getReportModel();
166
+ // 起始行、行数、是否仅选中行
167
+ DynamicObjectCollection selected = model.getRowData(0, reportList.getTotalRecords(), true);
168
+ if (selected == null || selected.isEmpty()) {
169
+ this.getView().showTipNotification(ResManager.loadKDString("请选择要处理的行。", "SelectAllReportFormPlugin_0", "xxx-report"));
170
+ return;
171
+ }
172
+ for (DynamicObject row : selected) {
173
+ // ……按列名处理每一个选中行
174
+ }
175
+ }
176
+ }
177
+ ```
178
+
179
+ ## 注意事项
180
+ - 工具栏按钮是元数据:报表工具栏上的一个项,通常绑定 donothing 操作;它的标识就是 `evt.getItemKey()` 的返回值
181
+ - 用 `addItemClickListeners("toolbarap")` 在 `registerListener` 中注册工具栏监听;不注册,`itemClick` 永远不会触发。编译边界会拒绝类中缺少对应 `add*` 调用的 `itemClick`、`cellClick` 或 `hyperLinkClick` 覆写(`PLUGIN_SOURCE_LISTENER_UNREGISTERED`),也会拒绝在 `initialize` 中添加的监听(`PLUGIN_SOURCE_LIFECYCLE_MISUSE`)
182
+ - `itemClick` 不带当前行。把单元格点击的行号存进 `getPageCache()`——它只属于当前报表页面——并且像所有依赖行的按钮一样,没点行时给出提示
183
+ - 两个插件之间的契约是列名:`getRowData` 以取数插件 DataSet 的列名为每行的键,表单插件读取的列必须是已声明的报表列——不用于展示时设为隐藏——因为行数据按已声明的列打包
184
+ - 基础资料列返回 `DynamicObject`;主键用 `getPkValue()` 读取
185
+ - `getRowData(int, int, boolean)` 在 8.0 SDK 中是 `IReportListModel` 的 default 方法,所以直接在 `getReportModel()` 返回的模型上调用,无需强转。第二个参数是行数(8.0.1 参考中的 `length`):报表示例把它说成结束行,从第 0 行开始时两者相同——从其他行开始时传 `end - start`,标品打印插件就是这样做的
186
+ - `setSelectedAll(true)` 在查询前(`beforeQuery` 中)执行;开启后,报表示例用 `getRowData(0, reportList.getTotalRecords(), true)` 读出所有选中行
187
+ - 要把值传给另一个页面,用打开参数的自定义参数(`report-hyperlink-drill.md`),不要用页面缓存:页面缓存只属于当前页面
188
+ - 用户可见文本通过 `ResManager.loadKDString(文本, 资源标识, 模块)` 输出