dsh-crwu-workbench 0.0.10
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/CHANGELOG.md +1516 -0
- package/LICENSE +26 -0
- package/README.en.md +204 -0
- package/README.md +521 -0
- package/SECURITY.md +39 -0
- package/bin/darwin-arm64/crwu +0 -0
- package/bin/darwin-arm64/dws +0 -0
- package/bin/darwin-arm64/ossutil +0 -0
- package/bin/manifest.json +82 -0
- package/bin/win32-x64/crwu.exe +0 -0
- package/bin/win32-x64/dws.exe +4 -0
- package/bin/win32-x64/ossutil.exe +0 -0
- package/common/skills/.synced.json +8 -0
- package/common/skills/crwu-dws/SKILL.md +208 -0
- package/common/skills/crwu-dws/references/00-/347/233/256/345/275/225/345/277/253/347/205/247schema.md +113 -0
- package/common/skills/crwu-dws/references/01-/345/256/241/346/240/270/344/270/213/350/275/275/344/270/216manifest/350/247/204/350/214/203.md +115 -0
- package/common/skills/crwu-dws/references/02-/347/274/223/345/255/230/344/270/216/345/205/234/345/272/225/346/237/245/346/211/276/350/247/204/350/214/203.md +119 -0
- package/common/skills/crwu-dws/scripts/test_dws_source_contract.py +493 -0
- package/common/skills/crwu-h3yun-login/SKILL.md +130 -0
- package/common/skills/crwu-h3yun-query/SKILL.md +192 -0
- package/config/crwu-workbench.yml +26 -0
- package/cordis.patch.yml +46 -0
- package/lib/client.js +10346 -0
- package/lib/index.js +11584 -0
- package/package.json +119 -0
- package/scripts/prepare.mjs +59 -0
- package/skills/README.md +26 -0
- package/skills/crwu/crwu-audit/SKILL.md +152 -0
- package/skills/crwu/crwu-audit/references/00-input-and-route-profile.md +232 -0
- package/skills/crwu/crwu-audit/references/01-report-id-resolution.md +13 -0
- package/skills/crwu/crwu-audit/references/02-scope-classification.md +25 -0
- package/skills/crwu/crwu-audit/references/03-asset-classification.md +27 -0
- package/skills/crwu/crwu-audit/references/04-business-classification.md +63 -0
- package/skills/crwu/crwu-audit/references/05-method-classification.md +66 -0
- package/skills/crwu/crwu-audit/references/06-overlay-classification.md +42 -0
- package/skills/crwu/crwu-audit/references/07-skill-registry.md +57 -0
- package/skills/crwu/crwu-audit/references/08-union-dispatch-rules.md +142 -0
- package/skills/crwu/crwu-audit/references/09-review-risk-classification.md +85 -0
- package/skills/crwu/crwu-audit/references/10-capability-gap-proposal.md +68 -0
- package/skills/crwu/crwu-audit/references/11-html-delivery-spec.md +881 -0
- package/skills/crwu/crwu-audit/references/12-leaf-common-contract.md +202 -0
- package/skills/crwu/crwu-audit/references/13-dingtalk-result-publish.md +88 -0
- package/skills/crwu/crwu-audit/references/14-orchestration-workflow.md +52 -0
- package/skills/crwu/crwu-audit/references/99-maintenance.md +62 -0
- package/skills/crwu/crwu-audit/scripts/README.md +157 -0
- package/skills/crwu/crwu-audit/scripts/audit_delivery.py +2736 -0
- package/skills/crwu/crwu-audit/scripts/audit_result.schema.json +1659 -0
- package/skills/crwu/crwu-audit/scripts/examples/audit-result.sample.json +739 -0
- package/skills/crwu/crwu-audit/scripts/fetch_review_records.py +85 -0
- package/skills/crwu/crwu-audit/scripts/media_extract.py +513 -0
- package/skills/crwu/crwu-audit/scripts/prepare_materials.py +1252 -0
- package/skills/crwu/crwu-audit/scripts/test_audit_delivery.py +1678 -0
- package/skills/crwu/crwu-audit/scripts/test_audit_multiaxis_router.py +1339 -0
- package/skills/crwu/crwu-audit/scripts/test_fetch_review_records.py +77 -0
- package/skills/crwu/crwu-audit/scripts/test_media_extract.py +332 -0
- package/skills/crwu/crwu-audit/scripts/test_prepare_materials.py +1081 -0
- package/skills/crwu/crwu-audit/template/audit-report.html +435 -0
- package/skills/crwu/crwu-audit-asset-asset-group-goodwill/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/00-applicability.md +28 -0
- package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/01-kb-assembly.md +31 -0
- package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/02-review-focus.md +21 -0
- package/skills/crwu/crwu-audit-asset-asset-group-goodwill/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-debt/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-debt/references/00-applicability.md +40 -0
- package/skills/crwu/crwu-audit-asset-debt/references/01-kb-assembly.md +41 -0
- package/skills/crwu/crwu-audit-asset-debt/references/02-review-focus.md +54 -0
- package/skills/crwu/crwu-audit-asset-debt/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-enterprise-value/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-enterprise-value/references/00-applicability.md +31 -0
- package/skills/crwu/crwu-audit-asset-enterprise-value/references/01-kb-assembly.md +35 -0
- package/skills/crwu/crwu-audit-asset-enterprise-value/references/02-review-focus.md +33 -0
- package/skills/crwu/crwu-audit-asset-enterprise-value/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-equipment/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-equipment/references/00-applicability.md +40 -0
- package/skills/crwu/crwu-audit-asset-equipment/references/01-kb-assembly.md +39 -0
- package/skills/crwu/crwu-audit-asset-equipment/references/02-review-focus.md +52 -0
- package/skills/crwu/crwu-audit-asset-equipment/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-intangible/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-intangible/references/00-applicability.md +36 -0
- package/skills/crwu/crwu-audit-asset-intangible/references/01-kb-assembly.md +40 -0
- package/skills/crwu/crwu-audit-asset-intangible/references/02-review-focus.md +68 -0
- package/skills/crwu/crwu-audit-asset-intangible/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-inventory/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-inventory/references/00-applicability.md +28 -0
- package/skills/crwu/crwu-audit-asset-inventory/references/01-kb-assembly.md +31 -0
- package/skills/crwu/crwu-audit-asset-inventory/references/02-review-focus.md +21 -0
- package/skills/crwu/crwu-audit-asset-inventory/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-mining-right/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-mining-right/references/00-applicability.md +31 -0
- package/skills/crwu/crwu-audit-asset-mining-right/references/01-kb-assembly.md +35 -0
- package/skills/crwu/crwu-audit-asset-mining-right/references/02-review-focus.md +33 -0
- package/skills/crwu/crwu-audit-asset-mining-right/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-other/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-other/references/00-applicability.md +28 -0
- package/skills/crwu/crwu-audit-asset-other/references/01-kb-assembly.md +31 -0
- package/skills/crwu/crwu-audit-asset-other/references/02-review-focus.md +21 -0
- package/skills/crwu/crwu-audit-asset-other/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-portfolio/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-portfolio/references/00-applicability.md +28 -0
- package/skills/crwu/crwu-audit-asset-portfolio/references/01-kb-assembly.md +31 -0
- package/skills/crwu/crwu-audit-asset-portfolio/references/02-review-focus.md +21 -0
- package/skills/crwu/crwu-audit-asset-portfolio/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-realestate/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-realestate/references/00-applicability.md +43 -0
- package/skills/crwu/crwu-audit-asset-realestate/references/01-kb-assembly.md +75 -0
- package/skills/crwu/crwu-audit-asset-realestate/references/02-review-focus.md +93 -0
- package/skills/crwu/crwu-audit-asset-realestate/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-scrap-materials/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-scrap-materials/references/00-applicability.md +28 -0
- package/skills/crwu/crwu-audit-asset-scrap-materials/references/01-kb-assembly.md +31 -0
- package/skills/crwu/crwu-audit-asset-scrap-materials/references/02-review-focus.md +21 -0
- package/skills/crwu/crwu-audit-asset-scrap-materials/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-asset-transport-equipment/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-asset-transport-equipment/references/00-applicability.md +31 -0
- package/skills/crwu/crwu-audit-asset-transport-equipment/references/01-kb-assembly.md +35 -0
- package/skills/crwu/crwu-audit-asset-transport-equipment/references/02-review-focus.md +33 -0
- package/skills/crwu/crwu-audit-asset-transport-equipment/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-asset-operation/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-asset-operation/references/00-applicability.md +30 -0
- package/skills/crwu/crwu-audit-biz-asset-operation/references/01-kb-assembly.md +32 -0
- package/skills/crwu/crwu-audit-biz-asset-operation/references/02-review-focus.md +42 -0
- package/skills/crwu/crwu-audit-biz-asset-operation/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-consulting-review/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-consulting-review/references/00-applicability.md +30 -0
- package/skills/crwu/crwu-audit-biz-consulting-review/references/01-kb-assembly.md +32 -0
- package/skills/crwu/crwu-audit-biz-consulting-review/references/02-review-focus.md +40 -0
- package/skills/crwu/crwu-audit-biz-consulting-review/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-financial-reporting/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-financial-reporting/references/00-applicability.md +41 -0
- package/skills/crwu/crwu-audit-biz-financial-reporting/references/01-kb-assembly.md +40 -0
- package/skills/crwu/crwu-audit-biz-financial-reporting/references/02-review-focus.md +64 -0
- package/skills/crwu/crwu-audit-biz-financial-reporting/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-financing-debt/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-financing-debt/references/00-applicability.md +31 -0
- package/skills/crwu/crwu-audit-biz-financing-debt/references/01-kb-assembly.md +34 -0
- package/skills/crwu/crwu-audit-biz-financing-debt/references/02-review-focus.md +47 -0
- package/skills/crwu/crwu-audit-biz-financing-debt/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-investment-capital/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-investment-capital/references/00-applicability.md +31 -0
- package/skills/crwu/crwu-audit-biz-investment-capital/references/01-kb-assembly.md +34 -0
- package/skills/crwu/crwu-audit-biz-investment-capital/references/02-review-focus.md +47 -0
- package/skills/crwu/crwu-audit-biz-investment-capital/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/00-applicability.md +30 -0
- package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/01-kb-assembly.md +32 -0
- package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/02-review-focus.md +40 -0
- package/skills/crwu/crwu-audit-biz-judicial-liquidation-compensation/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-tax-history/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-tax-history/references/00-applicability.md +29 -0
- package/skills/crwu/crwu-audit-biz-tax-history/references/01-kb-assembly.md +30 -0
- package/skills/crwu/crwu-audit-biz-tax-history/references/02-review-focus.md +33 -0
- package/skills/crwu/crwu-audit-biz-tax-history/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-biz-transaction-disposal/SKILL.md +38 -0
- package/skills/crwu/crwu-audit-biz-transaction-disposal/references/00-applicability.md +31 -0
- package/skills/crwu/crwu-audit-biz-transaction-disposal/references/01-kb-assembly.md +34 -0
- package/skills/crwu/crwu-audit-biz-transaction-disposal/references/02-review-focus.md +47 -0
- package/skills/crwu/crwu-audit-biz-transaction-disposal/references/03-common-contract.md +202 -0
- package/skills/crwu/crwu-audit-datacheck/SKILL.md +59 -0
- package/skills/crwu/crwu-audit-datacheck/references/00-KB/350/243/205/351/205/215/350/241/250.md +25 -0
- package/skills/crwu/crwu-audit-datacheck/references/01-runtime-and-check-catalog.md +139 -0
- package/skills/crwu/crwu-audit-datacheck/scripts/recalc_check.py +521 -0
- package/skills/crwu/crwu-audit-datacheck/scripts/test_recalc_check.py +419 -0
- package/skills/crwu/crwu-audit-datacheck/scripts/test_skill_self_containment.py +44 -0
- package/skills/crwu/crwu-audit-external-data/SKILL.md +73 -0
- package/skills/crwu/crwu-audit-external-data/references/00-KB/350/243/205/351/205/215/350/241/250.md +38 -0
- package/skills/crwu/crwu-audit-external-data/references/01-connector-access.md +116 -0
- package/skills/crwu/crwu-audit-external-data/references/02-verification-workflow.md +78 -0
- package/skills/crwu/crwu-audit-external-data/scripts/connector_probe.py +374 -0
- package/skills/crwu/crwu-audit-external-data/scripts/test_connector_probe.py +264 -0
- package/skills/crwu/crwu-audit-output-filter/SKILL.md +34 -0
- package/skills/crwu/crwu-audit-output-filter/references/00-applicability.md +7 -0
- package/skills/crwu/crwu-audit-output-filter/references/01-kb-assembly.md +11 -0
- package/skills/crwu/crwu-audit-output-filter/references/02-review-focus.md +25 -0
- package/skills/crwu/crwu-audit-public-general-standards/SKILL.md +46 -0
- package/skills/crwu/crwu-audit-public-general-standards/references/00-applicability.md +41 -0
- package/skills/crwu/crwu-audit-public-general-standards/references/01-kb-assembly.md +66 -0
- package/skills/crwu/crwu-audit-public-general-standards/references/02-review-focus.md +111 -0
- package/skills/crwu/crwu-audit-public-general-standards/references/03-execution-contract.md +89 -0
- package/skills/crwu/crwu-dev-audit-optimize/SKILL.md +98 -0
- package/skills/crwu/crwu-dev-audit-optimize/references/00-/344/274/230/345/214/226/350/247/204/350/214/203/344/270/216/346/226/207/344/273/266/350/220/275/347/202/271.md +132 -0
- package/skills/crwu/crwu-dev-audit-optimize/references/01-/345/217/215/351/246/210/345/256/232/344/275/215/344/270/216/347/224/273/345/203/217/346/265/201/347/250/213.md +108 -0
- package/skills/crwu/crwu-dev-audit-optimize/references/02-/346/226/271/346/241/210/346/250/241/346/235/277/344/270/216/347/241/256/350/256/244/351/227/250/347/246/201.md +92 -0
- package/skills/crwu/crwu-dev-audit-optimize/references/03-AI/344/272/272/345/267/245/345/267/256/350/267/235/345/210/206/346/236/220/346/265/201/347/250/213.md +95 -0
- package/skills/crwu/crwu-dev-audit-optimize/scripts/examples/gap-analysis.sample.json +116 -0
- package/skills/crwu/crwu-dev-audit-optimize/scripts/gap_analysis.schema.json +33 -0
- package/skills/crwu/crwu-dev-audit-optimize/scripts/gap_analysis_delivery.py +475 -0
- package/skills/crwu/crwu-dev-audit-optimize/scripts/test_gap_analysis_delivery.py +855 -0
- package/skills/crwu/crwu-dev-audit-optimize/template/NOTICE.echarts.txt +7 -0
- package/skills/crwu/crwu-dev-audit-optimize/template/echarts.min.js +45 -0
- package/skills/crwu/crwu-dev-audit-optimize/template/gap-analysis-report.html +71 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/SKILL.md +74 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/00-responsibility-and-modes.md +62 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/01-kb-source-discovery.md +89 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/02-child-skill-contract.md +99 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/03-review-item-execution-contract.md +51 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/04-registry-and-mapping-update.md +73 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/05-validation-and-delivery.md +127 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/06-live-routing-reconciliation.md +136 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/references/07-kb-skill-map.md +411 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/README.md +200 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/check_audit_skill_mappings.py +2477 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/kb_tool.py +577 -0
- package/skills/crwu/crwu-dev-audit-skill-maintainer/scripts/test_audit_skill_maintainer.py +5097 -0
- package/skills/dws/LICENSE +178 -0
- package/skills/dws/NOTICE +17 -0
- package/skills/dws/dingtalk-aisearch/SKILL.md +83 -0
- package/skills/dws/dingtalk-aisearch/references/aisearch.md +249 -0
- package/skills/dws/dingtalk-aisearch/references/intent-guide.md +15 -0
- package/skills/dws/dingtalk-aisearch/references/lite-recipes.md +31 -0
- package/skills/dws/dingtalk-aitable/SKILL.md +139 -0
- package/skills/dws/dingtalk-aitable/references/06-data-analytics.md +11 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-advperm.md +251 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-attachment.md +49 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-best-practices.md +48 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-cell-value.md +346 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-dashboard-chart.md +46 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-data-analysis-sop.md +131 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-datasource.md +272 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-error-recovery.md +128 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-export-import.md +113 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-field-properties.md +238 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-field.md +186 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-filter-sort.md +135 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-form.md +130 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-formula-guide.md +224 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-primary-doc.md +58 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-create.md +52 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-delete.md +20 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-history.md +97 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-name-key.md +47 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-query.md +120 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-share.md +54 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-stats.md +59 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-update.md +66 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-record-upsert.md +89 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-view-config.md +140 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-view-extras.md +195 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-view-types.md +95 -0
- package/skills/dws/dingtalk-aitable/references/aitable/aitable-workflow.md +384 -0
- package/skills/dws/dingtalk-aitable/references/aitable-record-ops.md +80 -0
- package/skills/dws/dingtalk-aitable/references/aitable-section.md +30 -0
- package/skills/dws/dingtalk-aitable/references/aitable.md +59 -0
- package/skills/dws/dingtalk-aitable/references/field-rules.md +17 -0
- package/skills/dws/dingtalk-aitable/references/intent-guide.md +17 -0
- package/skills/dws/dingtalk-aitable/references/recipes/conventions.md +44 -0
- package/skills/dws/dingtalk-aitable/references/url-patterns.md +144 -0
- package/skills/dws/dingtalk-aitable/scripts/aitable_export_via_task.py +210 -0
- package/skills/dws/dingtalk-aitable/scripts/aitable_import_via_task.py +173 -0
- package/skills/dws/dingtalk-aitable/scripts/bulk_add_fields.py +273 -0
- package/skills/dws/dingtalk-aitable/scripts/import_records.py +333 -0
- package/skills/dws/dingtalk-aitable/scripts/upload_attachment.py +190 -0
- package/skills/dws/dingtalk-calendar/SKILL.md +137 -0
- package/skills/dws/dingtalk-calendar/references/03-meeting.md +56 -0
- package/skills/dws/dingtalk-calendar/references/calendar.md +760 -0
- package/skills/dws/dingtalk-calendar/references/intent-guide.md +9 -0
- package/skills/dws/dingtalk-calendar/references/lite-recipes.md +25 -0
- package/skills/dws/dingtalk-calendar/scripts/calendar_free_slot_finder.py +199 -0
- package/skills/dws/dingtalk-calendar/scripts/calendar_schedule_meeting.py +233 -0
- package/skills/dws/dingtalk-calendar/scripts/calendar_today_agenda.py +139 -0
- package/skills/dws/dingtalk-chat/SKILL.md +127 -0
- package/skills/dws/dingtalk-chat/references/01-messaging.md +103 -0
- package/skills/dws/dingtalk-chat/references/card/callback.md +10 -0
- package/skills/dws/dingtalk-chat/references/card/create.md +27 -0
- package/skills/dws/dingtalk-chat/references/card/schema.md +14 -0
- package/skills/dws/dingtalk-chat/references/card/update.md +13 -0
- package/skills/dws/dingtalk-chat/references/chat/chat-bot.md +187 -0
- package/skills/dws/dingtalk-chat/references/chat/chat-conversation.md +165 -0
- package/skills/dws/dingtalk-chat/references/chat/group-admin.md +144 -0
- package/skills/dws/dingtalk-chat/references/chat/group-discovery.md +121 -0
- package/skills/dws/dingtalk-chat/references/chat/message-actions.md +132 -0
- package/skills/dws/dingtalk-chat/references/chat/message-media.md +76 -0
- package/skills/dws/dingtalk-chat/references/chat/message-query.md +135 -0
- package/skills/dws/dingtalk-chat/references/chat/thread.md +46 -0
- package/skills/dws/dingtalk-chat/references/chat-emoji-list.md +216 -0
- package/skills/dws/dingtalk-chat/references/chat.md +140 -0
- package/skills/dws/dingtalk-chat/references/contracts.md +70 -0
- package/skills/dws/dingtalk-chat/references/intent-guide.md +56 -0
- package/skills/dws/dingtalk-contact/SKILL.md +122 -0
- package/skills/dws/dingtalk-contact/references/08-directory.md +51 -0
- package/skills/dws/dingtalk-contact/references/contact.md +595 -0
- package/skills/dws/dingtalk-contact/references/intent-guide.md +14 -0
- package/skills/dws/dingtalk-contact/references/lite-recipes.md +30 -0
- package/skills/dws/dingtalk-contact/references/recipes/conventions.md +44 -0
- package/skills/dws/dingtalk-contact/scripts/contact_dept_members.py +130 -0
- package/skills/dws/dingtalk-doc/SKILL.md +112 -0
- package/skills/dws/dingtalk-doc/references/04-document.md +57 -0
- package/skills/dws/dingtalk-doc/references/contracts.md +40 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-block.md +39 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-comment.md +29 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-create.md +54 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-export.md +30 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-import.md +28 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-info.md +12 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-media.md +46 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-read.md +56 -0
- package/skills/dws/dingtalk-doc/references/doc/doc-update.md +87 -0
- package/skills/dws/dingtalk-doc/references/doc/format/doc-jsonml-cookbook.md +469 -0
- package/skills/dws/dingtalk-doc/references/doc/format/doc-jsonml-schema.json +526 -0
- package/skills/dws/dingtalk-doc/references/doc/format/doc-jsonml-schema.md +711 -0
- package/skills/dws/dingtalk-doc/references/doc/style/doc-create-workflow.md +414 -0
- package/skills/dws/dingtalk-doc/references/doc/style/doc-style-guideline.md +404 -0
- package/skills/dws/dingtalk-doc/references/doc/style/doc-update-workflow.md +316 -0
- package/skills/dws/dingtalk-doc/references/doc.md +82 -0
- package/skills/dws/dingtalk-doc/references/intent-guide.md +20 -0
- package/skills/dws/dingtalk-drive/SKILL.md +128 -0
- package/skills/dws/dingtalk-drive/references/drive.md +126 -0
- package/skills/dws/dingtalk-drive/references/folder-sync.md +40 -0
- package/skills/dws/dingtalk-drive/references/intent-guide.md +22 -0
- package/skills/dws/dingtalk-drive/references/lite-recipes.md +39 -0
- package/skills/dws/dingtalk-event/SKILL.md +106 -0
- package/skills/dws/dingtalk-event/references/event-im-keys.md +54 -0
- package/skills/dws/dingtalk-event/references/event-im-lifecycle.md +35 -0
- package/skills/dws/dingtalk-event/references/event-im-operations.md +52 -0
- package/skills/dws/dingtalk-event/references/event-im-output.md +39 -0
- package/skills/dws/dingtalk-event/references/event-im.md +58 -0
- package/skills/dws/dingtalk-event/references/event-oa.md +155 -0
- package/skills/dws/dingtalk-event/references/event-todo.md +50 -0
- package/skills/dws/dingtalk-event/references/event-voip.md +69 -0
- package/skills/dws/dingtalk-mail/SKILL.md +113 -0
- package/skills/dws/dingtalk-mail/references/09-mail.md +45 -0
- package/skills/dws/dingtalk-mail/references/intent-guide.md +8 -0
- package/skills/dws/dingtalk-mail/references/lite-recipes.md +45 -0
- package/skills/dws/dingtalk-mail/references/mail.md +1889 -0
- package/skills/dws/dingtalk-mail/references/recipes/conventions.md +44 -0
- package/skills/dws/dingtalk-mail/scripts/mail_send_with_cc.py +122 -0
- package/skills/dws/dingtalk-mail/scripts/mail_unread_summary.py +114 -0
- package/skills/dws/dingtalk-minutes/SKILL.md +116 -0
- package/skills/dws/dingtalk-minutes/references/07-minutes.md +149 -0
- package/skills/dws/dingtalk-minutes/references/10-minutes-speaker-match.md +32 -0
- package/skills/dws/dingtalk-minutes/references/11-minutes-speaker-correct.md +40 -0
- package/skills/dws/dingtalk-minutes/references/intent-guide.md +79 -0
- package/skills/dws/dingtalk-minutes/references/lite-recipes.md +25 -0
- package/skills/dws/dingtalk-minutes/references/minutes.md +210 -0
- package/skills/dws/dingtalk-minutes/references/recipes/conventions.md +33 -0
- package/skills/dws/dingtalk-minutes/scripts/minutes_recent_summary.py +196 -0
- package/skills/dws/dingtalk-minutes/scripts/test_minutes_scripts.py +222 -0
- package/skills/dws/dingtalk-misc/SKILL.md +55 -0
- package/skills/dws/dingtalk-misc/references/05-reporting.md +29 -0
- package/skills/dws/dingtalk-misc/references/agoal.md +302 -0
- package/skills/dws/dingtalk-misc/references/attendance-intent-guide.md +7 -0
- package/skills/dws/dingtalk-misc/references/attendance-report.md +109 -0
- package/skills/dws/dingtalk-misc/references/attendance-schedule.md +115 -0
- package/skills/dws/dingtalk-misc/references/attendance-vacation.md +129 -0
- package/skills/dws/dingtalk-misc/references/attendance.md +149 -0
- package/skills/dws/dingtalk-misc/references/dev/app.md +42 -0
- package/skills/dws/dingtalk-misc/references/dev/connect.md +108 -0
- package/skills/dws/dingtalk-misc/references/dev/credentials.md +26 -0
- package/skills/dws/dingtalk-misc/references/dev/dev-index.md +13 -0
- package/skills/dws/dingtalk-misc/references/dev/event.md +47 -0
- package/skills/dws/dingtalk-misc/references/dev/mcp.md +106 -0
- package/skills/dws/dingtalk-misc/references/dev/member.md +19 -0
- package/skills/dws/dingtalk-misc/references/dev/permission.md +56 -0
- package/skills/dws/dingtalk-misc/references/dev/recipes.md +58 -0
- package/skills/dws/dingtalk-misc/references/dev/robot.md +74 -0
- package/skills/dws/dingtalk-misc/references/dev/security.md +21 -0
- package/skills/dws/dingtalk-misc/references/dev/version.md +99 -0
- package/skills/dws/dingtalk-misc/references/dev/webapp.md +22 -0
- package/skills/dws/dingtalk-misc/references/devapp.md +148 -0
- package/skills/dws/dingtalk-misc/references/devdoc-intent-guide.md +7 -0
- package/skills/dws/dingtalk-misc/references/devdoc.md +42 -0
- package/skills/dws/dingtalk-misc/references/ding.md +184 -0
- package/skills/dws/dingtalk-misc/references/hrbrain.md +67 -0
- package/skills/dws/dingtalk-misc/references/live.md +23 -0
- package/skills/dws/dingtalk-misc/references/markdown.md +167 -0
- package/skills/dws/dingtalk-misc/references/oa/oa-form-components.md +345 -0
- package/skills/dws/dingtalk-misc/references/oa/oa-process-nodes.md +374 -0
- package/skills/dws/dingtalk-misc/references/oa.md +1014 -0
- package/skills/dws/dingtalk-misc/references/openapi-explorer.md +47 -0
- package/skills/dws/dingtalk-misc/references/pat.md +52 -0
- package/skills/dws/dingtalk-misc/references/profile.md +41 -0
- package/skills/dws/dingtalk-misc/references/recruit.md +89 -0
- package/skills/dws/dingtalk-misc/references/report-conventions.md +44 -0
- package/skills/dws/dingtalk-misc/references/report-intent-guide.md +11 -0
- package/skills/dws/dingtalk-misc/references/report-lite-recipes.md +25 -0
- package/skills/dws/dingtalk-misc/references/report.md +109 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-batch-operations.md +104 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-chart.md +69 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-comment.md +166 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-conditional-format.md +59 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-dimension-operations.md +60 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-dropdown.md +103 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-export.md +135 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-filter-view.md +51 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-filter.md +181 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-formula.md +192 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-import.md +76 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-media-image.md +263 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-pivot-table.md +292 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-range-operations.md +161 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-read-data.md +60 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-revision-changeset.md +46 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-search-replace.md +120 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-style-format.md +71 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-version.md +84 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-workbook.md +59 -0
- package/skills/dws/dingtalk-misc/references/sheet/sheet-write-data.md +93 -0
- package/skills/dws/dingtalk-misc/references/sheet-conventions.md +44 -0
- package/skills/dws/dingtalk-misc/references/sheet-intent-guide.md +12 -0
- package/skills/dws/dingtalk-misc/references/sheet.md +166 -0
- package/skills/dws/dingtalk-misc/references/skill.md +98 -0
- package/skills/dws/dingtalk-misc/references/unsupported-scripts.md +49 -0
- package/skills/dws/dingtalk-misc/references/url-patterns.md +144 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/compose.md +200 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/01-overview.md +57 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/02-query.md +288 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/03-update.md +249 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/04-text-style.md +395 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/05-shape-frame-group-connector.md +186 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/06-vector-icon-path.md +313 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/07-examples-errors-write-support.md +270 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1/08-catalogs.md +61 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/open-nodes-v1.md +54 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/replace.md +41 -0
- package/skills/dws/dingtalk-misc/references/whiteboard/vector.md +51 -0
- package/skills/dws/dingtalk-misc/references/whiteboard.md +115 -0
- package/skills/dws/dingtalk-misc/scripts/aiapp_create_and_poll.py +138 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_my_record.py +91 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_report_checkin.py +440 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_report_common.py +1698 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_report_daily.py +558 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_report_detail.py +809 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_report_monthly.py +758 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_report_record.py +947 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_schedule_export.py +344 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_schedule_import.py +498 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_team_shift.py +89 -0
- package/skills/dws/dingtalk-misc/scripts/attendance_vacation_balance.py +617 -0
- package/skills/dws/dingtalk-misc/scripts/finance_daily_cashflow.py +70 -0
- package/skills/dws/dingtalk-misc/scripts/finance_expense_flow.py +138 -0
- package/skills/dws/dingtalk-misc/scripts/oa_batch_approve.py +158 -0
- package/skills/dws/dingtalk-misc/scripts/oa_pending_review.py +132 -0
- package/skills/dws/dingtalk-misc/scripts/report_received_today.py +315 -0
- package/skills/dws/dingtalk-misc/scripts/yida_custom_page_update.py +401 -0
- package/skills/dws/dingtalk-misc/scripts/yida_form_builder.py +526 -0
- package/skills/dws/dingtalk-misc/scripts/yida_form_fields.py +315 -0
- package/skills/dws/dingtalk-misc/scripts/yida_form_inspector.py +311 -0
- package/skills/dws/dingtalk-misc/scripts/yida_form_update.py +185 -0
- package/skills/dws/dingtalk-misc/scripts/yida_jsx_pipeline.py +1588 -0
- package/skills/dws/dingtalk-misc/scripts/yida_page_compiler.py +1441 -0
- package/skills/dws/dingtalk-misc/scripts/yida_page_generate.py +514 -0
- package/skills/dws/dingtalk-misc/scripts/yida_page_schema.py +519 -0
- package/skills/dws/dingtalk-misc/scripts/yida_page_self_check.py +398 -0
- package/skills/dws/dingtalk-misc/scripts/yida_process_flow.py +1478 -0
- package/skills/dws/dingtalk-misc/scripts/yida_process_update.py +589 -0
- package/skills/dws/dingtalk-misc/scripts/yida_report_builder.py +494 -0
- package/skills/dws/dingtalk-misc/scripts/yida_report_charts.py +1434 -0
- package/skills/dws/dingtalk-misc/scripts/yida_report_update.py +244 -0
- package/skills/dws/dingtalk-misc/scripts/yida_schema_common.py +340 -0
- package/skills/dws/dingtalk-shared/SKILL.md +83 -0
- package/skills/dws/dingtalk-shared/references/capability-limits.md +31 -0
- package/skills/dws/dingtalk-shared/references/channel-login.md +26 -0
- package/skills/dws/dingtalk-shared/references/confirmation.md +59 -0
- package/skills/dws/dingtalk-shared/references/error-codes.md +155 -0
- package/skills/dws/dingtalk-shared/references/global-reference.md +122 -0
- package/skills/dws/dingtalk-shared/references/intent-guide.md +537 -0
- package/skills/dws/dingtalk-shared/references/recipes/conventions.md +45 -0
- package/skills/dws/dingtalk-shared/references/recipes/lite-catalog.md +275 -0
- package/skills/dws/dingtalk-shared/references/recipes/meta.md +67 -0
- package/skills/dws/dingtalk-shared/references/routing.md +52 -0
- package/skills/dws/dingtalk-shared/references/runtime-contract.md +11 -0
- package/skills/dws/dingtalk-shared/references/schema-usage.md +88 -0
- package/skills/dws/dingtalk-shared/references/url-patterns.md +144 -0
- package/skills/dws/dingtalk-shared/references/workflow-routing.md +45 -0
- package/skills/dws/dingtalk-todo/SKILL.md +119 -0
- package/skills/dws/dingtalk-todo/references/02-task.md +70 -0
- package/skills/dws/dingtalk-todo/references/intent-guide.md +15 -0
- package/skills/dws/dingtalk-todo/references/lite-recipes.md +68 -0
- package/skills/dws/dingtalk-todo/references/recipes/conventions.md +44 -0
- package/skills/dws/dingtalk-todo/references/todo.md +517 -0
- package/skills/dws/dingtalk-todo/scripts/todo_batch_create.py +354 -0
- package/skills/dws/dingtalk-todo/scripts/todo_daily_summary.py +153 -0
- package/skills/dws/dingtalk-todo/scripts/todo_overdue_check.py +101 -0
- package/skills/dws/dingtalk-wiki/SKILL.md +117 -0
- package/skills/dws/dingtalk-wiki/references/intent-guide.md +14 -0
- package/skills/dws/dingtalk-wiki/references/lite-recipes.md +44 -0
- package/skills/dws/dingtalk-wiki/references/wiki-members.md +32 -0
- package/skills/dws/dingtalk-wiki/references/wiki-node-ops.md +46 -0
- package/skills/dws/dingtalk-wiki/references/wiki.md +65 -0
- package/skills/dws/provenance.json +27 -0
|
@@ -0,0 +1,1434 @@
|
|
|
1
|
+
"""
|
|
2
|
+
宜搭报表图表组件构造 — 按 chart.type 分发,产出 component dict + cube 查询模型。
|
|
3
|
+
|
|
4
|
+
支持 9 种图表: bar / line / pie / funnel / table / indicator / gauge / combo / pivot
|
|
5
|
+
|
|
6
|
+
dataSetModelMap 结构严格匹配宜搭报表引擎格式:
|
|
7
|
+
- 外层 key: chartData (bar/line/pie/funnel/gauge) / table / youshuData (indicator)
|
|
8
|
+
/ dataSetName (combo/pivot)
|
|
9
|
+
- 内层: dataViewQueryModel{cubeCode, fieldDefinitionList, fieldList, cubeTenantId}
|
|
10
|
+
+ 外层 fieldList (完整字段对象) + xField/yField 等角色字段
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import math
|
|
15
|
+
from typing import Any, Optional
|
|
16
|
+
|
|
17
|
+
from yida_schema_common import (
|
|
18
|
+
i18n,
|
|
19
|
+
next_node_id,
|
|
20
|
+
generate_field_id,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
# 图表类型 → componentName 映射
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
CHART_TYPE_MAP: dict[str, str] = {
|
|
28
|
+
"bar": "YoushuGroupedBarChart",
|
|
29
|
+
"line": "YoushuLineChart",
|
|
30
|
+
"pie": "YoushuPieChart",
|
|
31
|
+
"funnel": "YoushuFunnelChart",
|
|
32
|
+
"table": "YoushuTable",
|
|
33
|
+
"indicator": "YoushuSimpleIndicatorCard",
|
|
34
|
+
"gauge": "YoushuGauge",
|
|
35
|
+
"combo": "YoushuComboChart",
|
|
36
|
+
"pivot": "YoushuCrossPivotTable",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def _compute_dynamic_layout(chart_type: str, chart: dict[str, Any]) -> dict[str, Any]:
|
|
40
|
+
"""根据图表内容动态计算布局尺寸。"""
|
|
41
|
+
if chart_type == "table":
|
|
42
|
+
page_size = chart.get("pageSize", 20)
|
|
43
|
+
h = max(16, min(40, round(page_size * 0.9) + 6))
|
|
44
|
+
return {"w": 6, "h": h, "minH": h, "maxH": h, "resizeHandles": ["w", "e"]}
|
|
45
|
+
|
|
46
|
+
if chart_type == "indicator":
|
|
47
|
+
kpi_count = len(chart.get("kpi", []))
|
|
48
|
+
col = min(kpi_count, 4) or 1
|
|
49
|
+
rows = math.ceil(kpi_count / col)
|
|
50
|
+
h = max(11, 8 + rows * 5)
|
|
51
|
+
w = min(2 * min(kpi_count, 3), 6)
|
|
52
|
+
return {"w": w, "h": h, "minH": h, "maxH": h, "resizeHandles": ["w", "e"]}
|
|
53
|
+
|
|
54
|
+
if chart_type in ("bar", "line"):
|
|
55
|
+
y_raw = chart.get("yField", "")
|
|
56
|
+
y_count = len(y_raw) if isinstance(y_raw, list) else 1
|
|
57
|
+
h = 22 if y_count <= 3 else min(30, 22 + (y_count - 3) * 2)
|
|
58
|
+
return {"w": 3, "h": h}
|
|
59
|
+
|
|
60
|
+
if chart_type == "gauge":
|
|
61
|
+
return {"w": 2, "h": 18}
|
|
62
|
+
|
|
63
|
+
if chart_type == "combo":
|
|
64
|
+
return {"w": 6, "h": 22}
|
|
65
|
+
|
|
66
|
+
if chart_type == "pivot":
|
|
67
|
+
return {"w": 6, "h": 30}
|
|
68
|
+
|
|
69
|
+
return {"w": 3, "h": 22}
|
|
70
|
+
|
|
71
|
+
_VALUE_SUFFIX_PREFIXES = ("selectField_", "radioField_", "checkboxField_", "multiSelectField_", "employeeField_")
|
|
72
|
+
|
|
73
|
+
_CUBE_LABEL_SUFFIX: dict[str, str] = {
|
|
74
|
+
"selectField_": "_值",
|
|
75
|
+
"radioField_": "_值",
|
|
76
|
+
"checkboxField_": "_值",
|
|
77
|
+
"multiSelectField_": "_值",
|
|
78
|
+
"employeeField_": "_名称",
|
|
79
|
+
"departmentSelectField_": "_名称",
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
_DS_KEY_CHART = "chartData"
|
|
83
|
+
_DS_KEY_TABLE = "table"
|
|
84
|
+
_DS_KEY_INDICATOR = "youshuData"
|
|
85
|
+
_DS_KEY_DATASET = "dataSetName"
|
|
86
|
+
|
|
87
|
+
_TIME_GRAN_ID_SUFFIX: dict[str, str] = {
|
|
88
|
+
"YEAR": "1", "QUARTER": "2", "MONTH": "3",
|
|
89
|
+
"WEEK": "4", "DAY": "5", "HOUR": "6",
|
|
90
|
+
}
|
|
91
|
+
_TIME_GRAN_FORMAT: dict[str, str] = {
|
|
92
|
+
"YEAR": "yyyy", "QUARTER": "yyyy-Q", "MONTH": "yyyy-MM",
|
|
93
|
+
"WEEK": "yyyy-w", "DAY": "yyyy-MM-dd", "HOUR": "yyyy-MM-dd HH",
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_AGGREGATE_TYPES = frozenset({"COUNT", "SUM", "AVG", "MAX", "MIN", "COUNT_DISTINCT"})
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# ---------------------------------------------------------------------------
|
|
100
|
+
# 公共工具
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def normalize_cube_code(code: str) -> str:
|
|
105
|
+
"""FORM-E604838A-3121-43D1-... → FORM_E604838A312143D1..."""
|
|
106
|
+
if code.startswith(("FORM-", "FORM_")):
|
|
107
|
+
return "FORM_" + code[5:].replace("-", "")
|
|
108
|
+
return code.replace("-", "_")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
_STRIP_SUFFIXES = ("_id", "_date")
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def normalize_field_code(field_code: str) -> str:
|
|
115
|
+
fc = field_code
|
|
116
|
+
for sfx in _STRIP_SUFFIXES:
|
|
117
|
+
if fc.endswith(sfx):
|
|
118
|
+
fc = fc[:-len(sfx)]
|
|
119
|
+
break
|
|
120
|
+
if any(fc.startswith(p) for p in _VALUE_SUFFIX_PREFIXES):
|
|
121
|
+
if not fc.endswith("_value"):
|
|
122
|
+
return fc + "_value"
|
|
123
|
+
return fc
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _apply_cube_label_suffix(field_code: str, text: str) -> str:
|
|
127
|
+
"""fieldCode 带 _value 后缀时,同步给显示标签追加中文后缀。
|
|
128
|
+
|
|
129
|
+
cube 元数据中 selectField_xxx_value 显示名为 "原标签_值",
|
|
130
|
+
employeeField_xxx_value 显示名为 "原标签_名称"。
|
|
131
|
+
不追加会导致引擎报"找不到配置"。
|
|
132
|
+
"""
|
|
133
|
+
if not field_code.endswith("_value"):
|
|
134
|
+
return text
|
|
135
|
+
base = field_code[:-6]
|
|
136
|
+
for prefix, suffix in _CUBE_LABEL_SUFFIX.items():
|
|
137
|
+
if base.startswith(prefix):
|
|
138
|
+
if not text.endswith(suffix):
|
|
139
|
+
return text + suffix
|
|
140
|
+
return text
|
|
141
|
+
return text
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _derive_label(field_code: str) -> str:
|
|
145
|
+
"""从 fieldCode 推导可读标签:去前缀、去 _value 后缀。"""
|
|
146
|
+
fc = field_code
|
|
147
|
+
for p in _VALUE_SUFFIX_PREFIXES:
|
|
148
|
+
if fc.startswith(p):
|
|
149
|
+
fc = fc[len(p):]
|
|
150
|
+
break
|
|
151
|
+
else:
|
|
152
|
+
for prefix in ("textField_", "numberField_", "dateField_", "textareaField_",
|
|
153
|
+
"countrySelectField_", "addressField_", "attachmentField_",
|
|
154
|
+
"imageField_", "departmentSelectField_", "tableField_",
|
|
155
|
+
"associationFormField_", "serialNumberField_", "rateField_",
|
|
156
|
+
"cascadeDateField_"):
|
|
157
|
+
if fc.startswith(prefix):
|
|
158
|
+
fc = fc[len(prefix):]
|
|
159
|
+
break
|
|
160
|
+
if fc.endswith("_value"):
|
|
161
|
+
fc = fc[:-6]
|
|
162
|
+
return fc or field_code
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _infer_data_type(field_code: str) -> str:
|
|
166
|
+
if field_code.startswith("numberField_"):
|
|
167
|
+
return "NUMBER"
|
|
168
|
+
if field_code.startswith("dateField_"):
|
|
169
|
+
return "DATE"
|
|
170
|
+
if field_code.startswith(("employeeField_", "departmentSelectField_")):
|
|
171
|
+
return "STRING" if field_code.endswith("_value") else "ARRAY"
|
|
172
|
+
return "STRING"
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
_ARRAY_FIELD_PREFIXES = ("employeeField_", "departmentSelectField_")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _fix_array_field_for_aggregate(field_code: str, data_type: str, aggregate_type: str) -> tuple[str, str]:
|
|
179
|
+
"""数组字段做聚合时保留 _value 后缀(cube 元数据只认 _value),仅将 ARRAY 类型转为 STRING。"""
|
|
180
|
+
if aggregate_type == "NONE":
|
|
181
|
+
return field_code, data_type
|
|
182
|
+
if any(field_code.startswith(p) for p in _ARRAY_FIELD_PREFIXES):
|
|
183
|
+
import warnings
|
|
184
|
+
warnings.warn(
|
|
185
|
+
f"⚠ {field_code} 是数组字段,不能做聚合({aggregate_type})——"
|
|
186
|
+
f"cube SQL 会报 'aggregate cannot contain set-returning function'。"
|
|
187
|
+
f"请改用非数组字段(如 numberField / textField)做 {aggregate_type}。",
|
|
188
|
+
stacklevel=3,
|
|
189
|
+
)
|
|
190
|
+
if data_type == "ARRAY":
|
|
191
|
+
return field_code, "STRING"
|
|
192
|
+
return field_code, data_type
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _is_date_field(field_code: str) -> bool:
|
|
196
|
+
return field_code.startswith("dateField_")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _gen_alias() -> str:
|
|
200
|
+
return f"field_{next_node_id()}"
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# ---------------------------------------------------------------------------
|
|
204
|
+
# 字段解析:支持 string 或 rich field dict
|
|
205
|
+
# ---------------------------------------------------------------------------
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _resolve_field(raw: Any, cube_code: str) -> dict[str, Any]:
|
|
209
|
+
"""把 string 或 dict 输入统一解析为标准字段元数据。"""
|
|
210
|
+
if isinstance(raw, dict):
|
|
211
|
+
fc = normalize_field_code(raw.get("fieldCode", ""))
|
|
212
|
+
if not fc:
|
|
213
|
+
raise ValueError(
|
|
214
|
+
f"fieldCode 不能为空。请先通过 `dws yida form components` 获取源表字段定义,"
|
|
215
|
+
f"使用返回的 fieldCode 构造字段对象。收到: {raw!r}"
|
|
216
|
+
)
|
|
217
|
+
text = raw.get("text") or raw.get("label") or _derive_label(fc)
|
|
218
|
+
text = _apply_cube_label_suffix(fc, text)
|
|
219
|
+
return {
|
|
220
|
+
"fieldCode": fc,
|
|
221
|
+
"dataType": raw.get("dataType") or _infer_data_type(fc),
|
|
222
|
+
"text": text,
|
|
223
|
+
"id": raw.get("id") or fc,
|
|
224
|
+
"classifiedCode": raw.get("classifiedCode") or cube_code,
|
|
225
|
+
"timeGranularityType": raw.get("timeGranularityType"),
|
|
226
|
+
"timeFormat": raw.get("timeFormat"),
|
|
227
|
+
}
|
|
228
|
+
fc = normalize_field_code(str(raw))
|
|
229
|
+
if not fc:
|
|
230
|
+
raise ValueError(
|
|
231
|
+
"fieldCode 不能为空字符串。请先通过 `dws yida form components` 获取源表字段定义。"
|
|
232
|
+
)
|
|
233
|
+
text = _apply_cube_label_suffix(fc, _derive_label(fc))
|
|
234
|
+
return {
|
|
235
|
+
"fieldCode": fc,
|
|
236
|
+
"dataType": _infer_data_type(fc),
|
|
237
|
+
"text": text,
|
|
238
|
+
"id": fc,
|
|
239
|
+
"classifiedCode": cube_code,
|
|
240
|
+
"timeGranularityType": None,
|
|
241
|
+
"timeFormat": None,
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# ---------------------------------------------------------------------------
|
|
246
|
+
# 字段对象构造(匹配宜搭报表引擎格式)
|
|
247
|
+
# ---------------------------------------------------------------------------
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _build_query_field_def(
|
|
251
|
+
alias: str,
|
|
252
|
+
label: str,
|
|
253
|
+
cube_code: str,
|
|
254
|
+
field_code: str,
|
|
255
|
+
data_type: str,
|
|
256
|
+
aggregate_type: str = "NONE",
|
|
257
|
+
time_gran: Optional[str] = None,
|
|
258
|
+
classified_code: Optional[str] = None,
|
|
259
|
+
) -> dict[str, Any]:
|
|
260
|
+
"""dataViewQueryModel.fieldDefinitionList 中的单条定义。"""
|
|
261
|
+
return {
|
|
262
|
+
"classifiedCode": classified_code or cube_code,
|
|
263
|
+
"cubeCode": cube_code,
|
|
264
|
+
"fieldCode": field_code,
|
|
265
|
+
"dataType": data_type,
|
|
266
|
+
"isDim": False,
|
|
267
|
+
"aggregateType": aggregate_type,
|
|
268
|
+
"alias": alias,
|
|
269
|
+
"aliasName": {"type": "i18n", "zh_CN": label, "en_US": label},
|
|
270
|
+
"timeGranularityType": time_gran,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def _build_full_field(
|
|
275
|
+
alias: str,
|
|
276
|
+
label: str,
|
|
277
|
+
cube_code: str,
|
|
278
|
+
field_code: str,
|
|
279
|
+
data_type: str,
|
|
280
|
+
aggregate_type: str = "NONE",
|
|
281
|
+
time_gran: Optional[str] = None,
|
|
282
|
+
classified_code: Optional[str] = None,
|
|
283
|
+
field_id: Optional[str] = None,
|
|
284
|
+
time_format: Optional[str] = None,
|
|
285
|
+
) -> dict[str, Any]:
|
|
286
|
+
"""外层 fieldList / xField / yField 中的完整字段对象。"""
|
|
287
|
+
fid = field_id or field_code
|
|
288
|
+
effective_dt = "DOUBLE" if aggregate_type in _AGGREGATE_TYPES else data_type
|
|
289
|
+
result: dict[str, Any] = {
|
|
290
|
+
"title": i18n(label),
|
|
291
|
+
"classifiedCode": classified_code or cube_code,
|
|
292
|
+
"cubeCode": cube_code,
|
|
293
|
+
"fieldCode": field_code,
|
|
294
|
+
"isDimension": "false",
|
|
295
|
+
"dataType": effective_dt,
|
|
296
|
+
"format": {"type": "NONE"},
|
|
297
|
+
"link": [{"type": "NONE"}],
|
|
298
|
+
"drillList": [],
|
|
299
|
+
"aggregateType": aggregate_type,
|
|
300
|
+
"orderBy": {"type": "NONE", "reference": alias},
|
|
301
|
+
"fieldKey": alias,
|
|
302
|
+
"visible": True,
|
|
303
|
+
"beUsedTimes": 1,
|
|
304
|
+
"isVisible": "y",
|
|
305
|
+
"id": fid,
|
|
306
|
+
"text": label,
|
|
307
|
+
}
|
|
308
|
+
if aggregate_type in _AGGREGATE_TYPES:
|
|
309
|
+
result["measureType"] = "MEASURE_ATTRIBUTE"
|
|
310
|
+
if time_gran:
|
|
311
|
+
result["timeGranularityType"] = time_gran
|
|
312
|
+
suffix = _TIME_GRAN_ID_SUFFIX.get(time_gran, "")
|
|
313
|
+
if suffix:
|
|
314
|
+
result["id"] = field_code + suffix
|
|
315
|
+
fmt = time_format or _TIME_GRAN_FORMAT.get(time_gran)
|
|
316
|
+
if fmt:
|
|
317
|
+
result["timeFormat"] = fmt
|
|
318
|
+
return result
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def _wrap_dataset(
|
|
322
|
+
ds_key: str,
|
|
323
|
+
cube_code: str,
|
|
324
|
+
cube_tenant_id: str,
|
|
325
|
+
query_field_defs: list[dict[str, Any]],
|
|
326
|
+
aliases: list[str],
|
|
327
|
+
full_fields: list[dict[str, Any]],
|
|
328
|
+
extra: Optional[dict[str, Any]] = None,
|
|
329
|
+
extra_query: Optional[dict[str, Any]] = None,
|
|
330
|
+
) -> dict[str, Any]:
|
|
331
|
+
"""组装完整 dataSetModelMap(匹配宜搭报表引擎结构)。"""
|
|
332
|
+
query_model: dict[str, Any] = {
|
|
333
|
+
"cubeCode": cube_code,
|
|
334
|
+
"cubeTenantId": cube_tenant_id,
|
|
335
|
+
"fieldDefinitionList": query_field_defs,
|
|
336
|
+
"fieldList": aliases,
|
|
337
|
+
"filterList": [],
|
|
338
|
+
"orderByList": [],
|
|
339
|
+
}
|
|
340
|
+
if extra_query:
|
|
341
|
+
query_model.update(extra_query)
|
|
342
|
+
|
|
343
|
+
ds: dict[str, Any] = {
|
|
344
|
+
"cubeCodes": [cube_code],
|
|
345
|
+
"dataViewQueryModel": query_model,
|
|
346
|
+
"fieldList": full_fields,
|
|
347
|
+
"youshuDataType": "real",
|
|
348
|
+
"filterList": [],
|
|
349
|
+
"limit": "",
|
|
350
|
+
"mockData": [],
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if extra:
|
|
354
|
+
ds.update(extra)
|
|
355
|
+
return {ds_key: ds}
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
# ---------------------------------------------------------------------------
|
|
359
|
+
# 图表 settings 默认值
|
|
360
|
+
# ---------------------------------------------------------------------------
|
|
361
|
+
|
|
362
|
+
_AXIS_LABEL_STYLE = {
|
|
363
|
+
"labelType": "default",
|
|
364
|
+
"color": "rgba(23,26,29,0.4)",
|
|
365
|
+
"fontSize": 12,
|
|
366
|
+
"limitLengthType": "percent",
|
|
367
|
+
"percent": 30,
|
|
368
|
+
"value": 100,
|
|
369
|
+
"autoRotate": True,
|
|
370
|
+
"rotate": "0",
|
|
371
|
+
"autoHide": True,
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
_X_AXIS_DEFAULT = {
|
|
375
|
+
"showXAxis": True,
|
|
376
|
+
"showTitle": False,
|
|
377
|
+
"title": {"type": "i18n", "zh_CN": "", "en_US": ""},
|
|
378
|
+
"line": True,
|
|
379
|
+
"tickLine": True,
|
|
380
|
+
"grid": False,
|
|
381
|
+
"label": True,
|
|
382
|
+
"labelStyle": _AXIS_LABEL_STYLE,
|
|
383
|
+
"values": {"type": "i18n", "zh_CN": "", "en_US": ""},
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
_Y_AXIS_DEFAULT = {
|
|
387
|
+
"showYAxis": True,
|
|
388
|
+
"showTitle": False,
|
|
389
|
+
"title": {"type": "i18n", "zh_CN": "", "en_US": ""},
|
|
390
|
+
"line": False,
|
|
391
|
+
"tickLine": False,
|
|
392
|
+
"grid": True,
|
|
393
|
+
"label": True,
|
|
394
|
+
"labelStyle": _AXIS_LABEL_STYLE,
|
|
395
|
+
"min": None,
|
|
396
|
+
"max": None,
|
|
397
|
+
"tickCount": 5,
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
_CUSTOM_COLOR = "#5894FF,#394B76,#F7B900,#E55F24,#80D5F5,#9849B0,#3BC88A,#0E869D,#F4A49E,#80563C"
|
|
401
|
+
|
|
402
|
+
_LEGEND_DEFAULT = {"showLegend": True, "legendPosition": "top-left", "flipPage": True}
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def _get_chart_settings(chart_type: str, chart: dict[str, Any]) -> dict[str, Any]:
|
|
406
|
+
if chart_type == "bar":
|
|
407
|
+
return {
|
|
408
|
+
"container": {"height": 248},
|
|
409
|
+
"style": {
|
|
410
|
+
"mode": "group",
|
|
411
|
+
"linkGroup": False,
|
|
412
|
+
"transpose": False,
|
|
413
|
+
"barStyle": "ai",
|
|
414
|
+
"size": None,
|
|
415
|
+
"maxSize": None,
|
|
416
|
+
"minSize": None,
|
|
417
|
+
"barBackground": None,
|
|
418
|
+
"groupSpacing": 0,
|
|
419
|
+
"radiusLeftTop": 4,
|
|
420
|
+
"radiusRightTop": 4,
|
|
421
|
+
"radiusRightBottom": 0,
|
|
422
|
+
"radiusLeftBottom": 0,
|
|
423
|
+
"colorType": "CUSTOM_COLOR",
|
|
424
|
+
"chartColorsMode": "EHRColorsMode",
|
|
425
|
+
"customColor": _CUSTOM_COLOR,
|
|
426
|
+
},
|
|
427
|
+
"countLabel": {"showCountLabel": False, "fontSize": 12, "color": "#000"},
|
|
428
|
+
"axisType": "hz",
|
|
429
|
+
"xAxis": _X_AXIS_DEFAULT,
|
|
430
|
+
"yAxis": _Y_AXIS_DEFAULT,
|
|
431
|
+
"legend": _LEGEND_DEFAULT,
|
|
432
|
+
"label": {
|
|
433
|
+
"showLabel": True,
|
|
434
|
+
"labelShowStyle": "ai",
|
|
435
|
+
"fontSize": 12,
|
|
436
|
+
"autoColor": True,
|
|
437
|
+
"color": "#000",
|
|
438
|
+
"autoPosition": False,
|
|
439
|
+
"position": "middle",
|
|
440
|
+
"autoAdjust": True,
|
|
441
|
+
"autoHide": True,
|
|
442
|
+
},
|
|
443
|
+
"slider": {"showSlider": False},
|
|
444
|
+
"tooltip": {"showTooltip": True},
|
|
445
|
+
}
|
|
446
|
+
elif chart_type == "line":
|
|
447
|
+
return {
|
|
448
|
+
"container": {"height": 248},
|
|
449
|
+
"style": {
|
|
450
|
+
"mode": "none",
|
|
451
|
+
"lineStyle": "ai",
|
|
452
|
+
"lineSize": 2,
|
|
453
|
+
"smooth": False,
|
|
454
|
+
"showArea": False,
|
|
455
|
+
"areaOpacity": 0.25,
|
|
456
|
+
"showPoint": True,
|
|
457
|
+
"pointSize": 4,
|
|
458
|
+
"pointShape": "circle",
|
|
459
|
+
"showLine": True,
|
|
460
|
+
"lineWidth": 2,
|
|
461
|
+
"colorType": "CUSTOM_COLOR",
|
|
462
|
+
"chartColorsMode": "EHRColorsMode",
|
|
463
|
+
"customColor": _CUSTOM_COLOR,
|
|
464
|
+
},
|
|
465
|
+
"axisType": "hz",
|
|
466
|
+
"xAxis": _X_AXIS_DEFAULT,
|
|
467
|
+
"yAxis": _Y_AXIS_DEFAULT,
|
|
468
|
+
"legend": _LEGEND_DEFAULT,
|
|
469
|
+
"label": {"showLabel": True, "fontSize": 12, "color": "#000", "autoOverlap": True},
|
|
470
|
+
"slider": {"showSlider": False},
|
|
471
|
+
"tooltip": {"showTooltip": True},
|
|
472
|
+
}
|
|
473
|
+
elif chart_type == "pie":
|
|
474
|
+
return {
|
|
475
|
+
"container": {"height": 248},
|
|
476
|
+
"style": {
|
|
477
|
+
"radius": 75,
|
|
478
|
+
"isRing": False,
|
|
479
|
+
"innerRadius": 0,
|
|
480
|
+
"colorType": "CUSTOM_COLOR",
|
|
481
|
+
"chartColorsMode": "EHRColorsMode",
|
|
482
|
+
"customColor": _CUSTOM_COLOR,
|
|
483
|
+
},
|
|
484
|
+
"statistic": {"showStatistic": False},
|
|
485
|
+
"label": {
|
|
486
|
+
"showLabel": True,
|
|
487
|
+
"showLine": True,
|
|
488
|
+
"labelAlign": "outer",
|
|
489
|
+
"labelSize": 12,
|
|
490
|
+
"labelColor": "#404040",
|
|
491
|
+
"labelFormatType": "NAME_PERCENT",
|
|
492
|
+
},
|
|
493
|
+
"legend": {
|
|
494
|
+
"showLegend": True,
|
|
495
|
+
"legendPosition": "right",
|
|
496
|
+
"flipPage": True,
|
|
497
|
+
"type": "item",
|
|
498
|
+
"contentType": "NAME",
|
|
499
|
+
"cardWidth": None,
|
|
500
|
+
"ratio": 65,
|
|
501
|
+
"layout": "vertical",
|
|
502
|
+
"itemSpacing": 12,
|
|
503
|
+
},
|
|
504
|
+
"tooltip": {"showTooltip": True, "contentType": None},
|
|
505
|
+
"percentDigits": 2,
|
|
506
|
+
}
|
|
507
|
+
elif chart_type == "funnel":
|
|
508
|
+
return {
|
|
509
|
+
"container": {"height": 248},
|
|
510
|
+
"style": {
|
|
511
|
+
"colorType": "CUSTOM_COLOR",
|
|
512
|
+
"chartColorsMode": "EHRColorsMode",
|
|
513
|
+
"customColor": _CUSTOM_COLOR,
|
|
514
|
+
},
|
|
515
|
+
"legend": _LEGEND_DEFAULT,
|
|
516
|
+
"label": {"showLabel": True, "fontSize": 12, "color": "#000"},
|
|
517
|
+
"tooltip": {"showTooltip": True},
|
|
518
|
+
}
|
|
519
|
+
elif chart_type == "gauge":
|
|
520
|
+
return {
|
|
521
|
+
"container": {"height": 248},
|
|
522
|
+
"useSingleColor": False,
|
|
523
|
+
"singleColor": "#0089FF",
|
|
524
|
+
"color": [],
|
|
525
|
+
"tick": {"showTick": True, "min": None, "max": None, "tickInterval": None},
|
|
526
|
+
"assistValue": {"openAssistValue": True, "showCompare": False, "position": "bottom"},
|
|
527
|
+
"style": {"rounded": True, "pivot": True, "rangeSize": 16, "radius": 95, "innerRadius": 90},
|
|
528
|
+
}
|
|
529
|
+
elif chart_type == "combo":
|
|
530
|
+
return {
|
|
531
|
+
"container": {"height": 248},
|
|
532
|
+
"style": {
|
|
533
|
+
"sync": False,
|
|
534
|
+
"chartType": "bar-line",
|
|
535
|
+
"bar": {
|
|
536
|
+
"size": None, "maxSize": None, "minSize": None, "mode": "group",
|
|
537
|
+
"barBackground": None,
|
|
538
|
+
"radiusLeftTop": 4, "radiusRightTop": 4,
|
|
539
|
+
"radiusRightBottom": 0, "radiusLeftBottom": 0,
|
|
540
|
+
},
|
|
541
|
+
"line": {
|
|
542
|
+
"size": 2, "smooth": False,
|
|
543
|
+
"showPoint": True, "pointSize": 4, "pointShape": "circle",
|
|
544
|
+
},
|
|
545
|
+
"autoAdjust": True,
|
|
546
|
+
"colorType": "CUSTOM_COLOR",
|
|
547
|
+
"chartColorsMode": "EHRColorsMode",
|
|
548
|
+
"customColor": _CUSTOM_COLOR,
|
|
549
|
+
},
|
|
550
|
+
"xAxis": _X_AXIS_DEFAULT,
|
|
551
|
+
"leftYAxis": {
|
|
552
|
+
"showLeftYAxis": True, "showTitle": False,
|
|
553
|
+
"title": {"type": "i18n", "zh_CN": "", "en_US": ""},
|
|
554
|
+
"line": False, "tickLine": False, "grid": True, "label": True,
|
|
555
|
+
"labelStyle": _AXIS_LABEL_STYLE,
|
|
556
|
+
"min": None, "max": None, "tickCount": 5,
|
|
557
|
+
},
|
|
558
|
+
"rightYAxis": {
|
|
559
|
+
"showRightYAxis": True, "showTitle": False,
|
|
560
|
+
"title": {"type": "i18n", "zh_CN": "", "en_US": ""},
|
|
561
|
+
"line": False, "tickLine": False, "grid": False, "label": True,
|
|
562
|
+
"labelStyle": _AXIS_LABEL_STYLE,
|
|
563
|
+
"min": None, "max": None, "tickCount": 5,
|
|
564
|
+
},
|
|
565
|
+
"legend": _LEGEND_DEFAULT,
|
|
566
|
+
"leftLabel": {"showLabel": True, "fontSize": 12, "color": "#000"},
|
|
567
|
+
"rightLabel": {"showLabel": True, "fontSize": 12, "color": "#000"},
|
|
568
|
+
"slider": {"showSlider": False},
|
|
569
|
+
"tooltip": {"showTooltip": True},
|
|
570
|
+
}
|
|
571
|
+
elif chart_type == "table":
|
|
572
|
+
page_size = chart.get("pageSize", 20)
|
|
573
|
+
return {
|
|
574
|
+
"rglConfig": {"w": 6, "h": 21, "isHeightAuto": True},
|
|
575
|
+
"size": "medium",
|
|
576
|
+
"wordSize": "medium:14",
|
|
577
|
+
"theme": "split",
|
|
578
|
+
"mergeCell": False,
|
|
579
|
+
"fixedHeader": False,
|
|
580
|
+
"maxBodyHeight": "300",
|
|
581
|
+
"fixedColumnIndex": 1,
|
|
582
|
+
"isReverseTable": False,
|
|
583
|
+
"showReversedHeader": False,
|
|
584
|
+
"isUniqueRows": False,
|
|
585
|
+
"pagination": {
|
|
586
|
+
"isPagination": True,
|
|
587
|
+
"pageSize": page_size,
|
|
588
|
+
"pageShowCount": 5,
|
|
589
|
+
"showPageSelect": False,
|
|
590
|
+
"size": "small",
|
|
591
|
+
"type": "normal",
|
|
592
|
+
},
|
|
593
|
+
"isTree": False,
|
|
594
|
+
"idField": None,
|
|
595
|
+
"pidField": None,
|
|
596
|
+
"isLeaf": None,
|
|
597
|
+
"drilldownFilterList": None,
|
|
598
|
+
"defaultExpand": False,
|
|
599
|
+
"rankStyle": False,
|
|
600
|
+
"container": {"height": 472},
|
|
601
|
+
"titleTip": False,
|
|
602
|
+
"showCopyData": False,
|
|
603
|
+
"enableFieldSelect": False,
|
|
604
|
+
"defaultSelectedFields": "",
|
|
605
|
+
"hasFullscreen": False,
|
|
606
|
+
"copyAsImg": False,
|
|
607
|
+
"height": None,
|
|
608
|
+
"isHeightAuto": True,
|
|
609
|
+
}
|
|
610
|
+
elif chart_type == "indicator":
|
|
611
|
+
kpi_count = len(chart.get("kpi", []))
|
|
612
|
+
return {
|
|
613
|
+
"showSideStyle": "NONE",
|
|
614
|
+
"followTheme": False,
|
|
615
|
+
"themeType": "dark",
|
|
616
|
+
"showSideBorder": True,
|
|
617
|
+
"sideBarColor": "#0089FF",
|
|
618
|
+
"bgColorType": "single",
|
|
619
|
+
"singleBgColor": "#F1F2F3",
|
|
620
|
+
"colorType": "SCHEMA_COLOR",
|
|
621
|
+
"multipleBgColor": "defaultColorsMode",
|
|
622
|
+
"customColor": "#0089FF,#FF9200,#11AB4F,#FFD100,#7263EE,#67C5EB,#6B748C,#FF755A,#007E99,#FFA8A8",
|
|
623
|
+
"size": "normal",
|
|
624
|
+
"valueSize": "20px",
|
|
625
|
+
"titleMaxRow": 0,
|
|
626
|
+
"columnCount": min(kpi_count, 4) or 4,
|
|
627
|
+
"columnCountForH5": min(kpi_count, 2) or 2,
|
|
628
|
+
"popoverAlign": "b",
|
|
629
|
+
"container": {"height": 72},
|
|
630
|
+
"titleTip": False,
|
|
631
|
+
"enableFieldSelect": False,
|
|
632
|
+
"hasFullscreen": False,
|
|
633
|
+
"copyAsImg": False,
|
|
634
|
+
"height": None,
|
|
635
|
+
"isHeightAuto": True,
|
|
636
|
+
}
|
|
637
|
+
elif chart_type == "pivot":
|
|
638
|
+
return {
|
|
639
|
+
"rglConfig": {"w": 6, "h": 21, "isHeightAuto": True},
|
|
640
|
+
"maxBodyHeight": 500,
|
|
641
|
+
"size": "normal",
|
|
642
|
+
"rows": [],
|
|
643
|
+
"columns": [],
|
|
644
|
+
"measures": [],
|
|
645
|
+
"details": [],
|
|
646
|
+
"supportExport": False,
|
|
647
|
+
"exportType": "XJZ",
|
|
648
|
+
"dialogWidth": 850,
|
|
649
|
+
"dialogPageSize": 10,
|
|
650
|
+
"baseInfo": {
|
|
651
|
+
"isShowSetter": True, "isShowFilter": False, "isShowReload": False,
|
|
652
|
+
"isHideTitle": False, "isMeasureOrder": True, "isZebra": True,
|
|
653
|
+
"rowMaxSize": 3000, "columnsMaxSize": 500, "columnWidth": 100,
|
|
654
|
+
"dialogWidth": 850, "dialogPageSize": 10,
|
|
655
|
+
"detailExportData": {"supportExport": False, "exportType": "BROWSER"},
|
|
656
|
+
},
|
|
657
|
+
"mode": "summary",
|
|
658
|
+
"summaryInfo": {
|
|
659
|
+
"isRowTotal": True, "rowTotalWidth": 130, "rowTotalPosition": "end",
|
|
660
|
+
"isColumnTotal": True, "isSubTotal": False,
|
|
661
|
+
"rowMaxSize": 3000, "columnsMaxSize": 500,
|
|
662
|
+
},
|
|
663
|
+
"paginationInfo": {
|
|
664
|
+
"size": "small", "type": "normal", "pageShowCount": 5,
|
|
665
|
+
"pageSize": 10, "showPageSelect": False,
|
|
666
|
+
},
|
|
667
|
+
"container": {"height": 232},
|
|
668
|
+
"titleTip": False,
|
|
669
|
+
"hasFullscreen": False,
|
|
670
|
+
"copyAsImg": False,
|
|
671
|
+
"height": None,
|
|
672
|
+
"isHeightAuto": True,
|
|
673
|
+
}
|
|
674
|
+
return {}
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
# ---------------------------------------------------------------------------
|
|
678
|
+
# userConfig 构建(设计器数据配置面板)
|
|
679
|
+
# ---------------------------------------------------------------------------
|
|
680
|
+
|
|
681
|
+
def _setter(name: str, title: str, **extra_props: Any) -> dict[str, Any]:
|
|
682
|
+
item: dict[str, Any] = {"setterName": "ColumnFieldSetter", "name": name, "title": title}
|
|
683
|
+
if extra_props:
|
|
684
|
+
item["setterProps"] = extra_props
|
|
685
|
+
return item
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
def _build_user_config(chart_type: str) -> list[dict[str, Any]]:
|
|
689
|
+
if chart_type in ("bar", "line"):
|
|
690
|
+
return [{"name": _DS_KEY_CHART, "title": "配置数据", "items": [
|
|
691
|
+
_setter("xField", "横轴", single=True, showFormatTab=True, showFormulaEditor=True,
|
|
692
|
+
showFieldInfo=True, showAggregateTab=False, showDrillTab=True, showEditTab=True, showSortTab=True),
|
|
693
|
+
_setter("yField", "纵轴", showFormatTab=True, showFormulaEditor=True,
|
|
694
|
+
showFieldInfo=True, showEditTab=True, showSortTab=True, showDataLink=True),
|
|
695
|
+
_setter("groupField", "分组", single=True, showFormatTab=True, showEditTab=True),
|
|
696
|
+
_setter("annotationField", "参考线", showFormatTab=True, showEditTab=True),
|
|
697
|
+
]}]
|
|
698
|
+
if chart_type == "pie":
|
|
699
|
+
return [{"name": _DS_KEY_CHART, "title": "配置数据", "items": [
|
|
700
|
+
_setter("xField", "分类字段", single=True, showAggregateTab=False, showDrillTab=True, showColorTab=True),
|
|
701
|
+
_setter("yField", "数值字段", single=True, showDataLink=True),
|
|
702
|
+
_setter("ratio", "趋势值字段"),
|
|
703
|
+
_setter("totalValue", "总值字段"),
|
|
704
|
+
_setter("totalRatio", "总趋势值字段"),
|
|
705
|
+
]}]
|
|
706
|
+
if chart_type == "funnel":
|
|
707
|
+
return [{"name": _DS_KEY_CHART, "title": "配置数据", "items": [
|
|
708
|
+
_setter("xField", "横轴", single=True, showFormatTab=True, showAggregateTab=False,
|
|
709
|
+
showDrillTab=True, showEditTab=True, showSortTab=True),
|
|
710
|
+
_setter("yField", "纵轴", showFormatTab=True, showEditTab=True, showSortTab=True, showDataLink=True),
|
|
711
|
+
]}]
|
|
712
|
+
if chart_type == "combo":
|
|
713
|
+
return [{"name": _DS_KEY_DATASET, "title": "配置数据", "items": [
|
|
714
|
+
_setter("xField", "横轴", single=True),
|
|
715
|
+
_setter("leftYFields", "左纵轴", showDataLink=True),
|
|
716
|
+
_setter("rightYFields", "右纵轴", showDataLink=True),
|
|
717
|
+
_setter("annotationField", "参考线"),
|
|
718
|
+
]}]
|
|
719
|
+
if chart_type == "table":
|
|
720
|
+
return [{"name": _DS_KEY_TABLE, "title": "配置数据", "items": [
|
|
721
|
+
_setter("columnFields", "列", showFormulaEditor=True, showFieldInfo=True,
|
|
722
|
+
showDataLink=True, supportDynamicAlias=True, showBatchSet=True,
|
|
723
|
+
batchSetFields=["text", "title", "aggregateType", "format_type", "format_decimalDigit"]),
|
|
724
|
+
]}]
|
|
725
|
+
if chart_type == "indicator":
|
|
726
|
+
return [{"name": _DS_KEY_INDICATOR, "title": "指标数据", "items": [
|
|
727
|
+
_setter("kpi", "指标", single=False, showDataLink=True, supportDynamicAlias=True,
|
|
728
|
+
showBatchSet=True,
|
|
729
|
+
batchSetFields=["text", "title", "titleTip", "aggregateType",
|
|
730
|
+
"format_type", "format_decimalDigit", "unit"]),
|
|
731
|
+
_setter("helpKpi", "辅助指标", single=False, showDataLink=True),
|
|
732
|
+
]}]
|
|
733
|
+
if chart_type == "pivot":
|
|
734
|
+
return [{"name": _DS_KEY_DATASET, "title": "配置数据", "items": [
|
|
735
|
+
_setter("columnList", "列", showFormatTab=True, showEditTab=True),
|
|
736
|
+
]}]
|
|
737
|
+
if chart_type == "gauge":
|
|
738
|
+
return [{"name": _DS_KEY_CHART, "title": "配置数据", "items": [
|
|
739
|
+
_setter("valueField", "指标值", single=True),
|
|
740
|
+
_setter("assitValueField", "辅助值", single=True),
|
|
741
|
+
]}]
|
|
742
|
+
return []
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
# ---------------------------------------------------------------------------
|
|
746
|
+
# mockData 构建(设计器预览数据)
|
|
747
|
+
# ---------------------------------------------------------------------------
|
|
748
|
+
|
|
749
|
+
def _build_mock_data(chart_type: str) -> list[dict[str, Any]]:
|
|
750
|
+
if chart_type == "bar":
|
|
751
|
+
return [{"name": _DS_KEY_CHART, "data": {"data": [
|
|
752
|
+
{"month": "Jan.", "value": 18.9}, {"month": "Feb.", "value": 28.8},
|
|
753
|
+
{"month": "Mar.", "value": 39.3}, {"month": "Apr.", "value": 81.4},
|
|
754
|
+
{"month": "May", "value": 47},
|
|
755
|
+
], "meta": [
|
|
756
|
+
{"fieldKey": "xField", "dataType": "STRING", "title": "month"},
|
|
757
|
+
{"fieldKey": "yField", "dataType": "NUMBER", "title": "value"},
|
|
758
|
+
], "currentPage": 1, "totalCount": 5}}]
|
|
759
|
+
|
|
760
|
+
if chart_type == "line":
|
|
761
|
+
return [{"name": _DS_KEY_CHART, "data": {"data": [
|
|
762
|
+
{"xField": "2020", "yField": 3}, {"xField": "2021", "yField": 4},
|
|
763
|
+
{"xField": "2022", "yField": 3.5}, {"xField": "2023", "yField": 5},
|
|
764
|
+
{"xField": "2024", "yField": 4.9},
|
|
765
|
+
], "meta": [
|
|
766
|
+
{"fieldKey": "xField", "dataType": "STRING", "title": "xField"},
|
|
767
|
+
{"fieldKey": "yField", "dataType": "NUMBER", "title": "yField"},
|
|
768
|
+
], "currentPage": 1, "totalCount": 5}}]
|
|
769
|
+
|
|
770
|
+
if chart_type == "pie":
|
|
771
|
+
return [{"name": _DS_KEY_CHART, "data": {"data": [
|
|
772
|
+
{"xField": "分类A", "yField": 63, "ratio": 0.8, "totalValue": 202, "totalRatio": 0.32},
|
|
773
|
+
{"xField": "分类B", "yField": 72, "ratio": 0.5, "totalValue": 202, "totalRatio": 0.36},
|
|
774
|
+
{"xField": "分类C", "yField": 67, "ratio": 0.3, "totalValue": 202, "totalRatio": 0.33},
|
|
775
|
+
], "meta": [
|
|
776
|
+
{"fieldKey": "xField", "dataType": "STRING", "title": "xField"},
|
|
777
|
+
{"fieldKey": "yField", "dataType": "NUMBER", "title": "yField"},
|
|
778
|
+
{"fieldKey": "ratio", "dataType": "NUMBER", "title": "ratio"},
|
|
779
|
+
{"fieldKey": "totalValue", "dataType": "NUMBER", "title": "totalValue"},
|
|
780
|
+
{"fieldKey": "totalRatio", "dataType": "NUMBER", "title": "totalRatio"},
|
|
781
|
+
], "currentPage": 1, "totalCount": 3}}]
|
|
782
|
+
|
|
783
|
+
if chart_type == "funnel":
|
|
784
|
+
return [{"name": _DS_KEY_CHART, "data": {"data": [
|
|
785
|
+
{"xField": "展示", "yField": 100}, {"xField": "点击", "yField": 80},
|
|
786
|
+
{"xField": "访问", "yField": 60}, {"xField": "咨询", "yField": 40},
|
|
787
|
+
{"xField": "订单", "yField": 20},
|
|
788
|
+
], "meta": [
|
|
789
|
+
{"fieldKey": "xField", "dataType": "STRING", "title": "xField"},
|
|
790
|
+
{"fieldKey": "yField", "dataType": "NUMBER", "title": "yField"},
|
|
791
|
+
], "currentPage": 1, "totalCount": 5}}]
|
|
792
|
+
|
|
793
|
+
if chart_type == "gauge":
|
|
794
|
+
return [{"name": _DS_KEY_CHART, "data": {"data": [
|
|
795
|
+
{"value": 75, "assitValue": 100},
|
|
796
|
+
], "meta": [
|
|
797
|
+
{"fieldKey": "valueField", "dataType": "NUMBER", "title": "value"},
|
|
798
|
+
{"fieldKey": "assitValueField", "dataType": "NUMBER", "title": "assitValue"},
|
|
799
|
+
], "currentPage": 1, "totalCount": 1}}]
|
|
800
|
+
|
|
801
|
+
if chart_type == "combo":
|
|
802
|
+
return [{"name": _DS_KEY_DATASET, "data": {"data": [
|
|
803
|
+
{"xField": "Jan.", "leftY": 18.9, "rightY": 5},
|
|
804
|
+
{"xField": "Feb.", "leftY": 28.8, "rightY": 8},
|
|
805
|
+
{"xField": "Mar.", "leftY": 39.3, "rightY": 12},
|
|
806
|
+
{"xField": "Apr.", "leftY": 81.4, "rightY": 15},
|
|
807
|
+
{"xField": "May", "leftY": 47, "rightY": 10},
|
|
808
|
+
], "meta": [
|
|
809
|
+
{"fieldKey": "xField", "dataType": "STRING", "title": "xField"},
|
|
810
|
+
{"fieldKey": "leftYFields", "dataType": "NUMBER", "title": "leftY"},
|
|
811
|
+
{"fieldKey": "rightYFields", "dataType": "NUMBER", "title": "rightY"},
|
|
812
|
+
], "currentPage": 1, "totalCount": 5}}]
|
|
813
|
+
|
|
814
|
+
if chart_type == "table":
|
|
815
|
+
return [{"name": _DS_KEY_TABLE, "data": {"data": [
|
|
816
|
+
{"col1": "数据1", "col2": "数据2", "col3": 100},
|
|
817
|
+
{"col1": "数据4", "col2": "数据5", "col3": 200},
|
|
818
|
+
{"col1": "数据7", "col2": "数据8", "col3": 300},
|
|
819
|
+
], "meta": [
|
|
820
|
+
{"fieldKey": "columnFields", "dataType": "STRING", "title": "col1"},
|
|
821
|
+
{"fieldKey": "columnFields", "dataType": "STRING", "title": "col2"},
|
|
822
|
+
{"fieldKey": "columnFields", "dataType": "NUMBER", "title": "col3"},
|
|
823
|
+
], "currentPage": 1, "totalCount": 3}}]
|
|
824
|
+
|
|
825
|
+
if chart_type == "indicator":
|
|
826
|
+
return [{"name": _DS_KEY_INDICATOR, "data": {"data": [
|
|
827
|
+
{"kpi1": 23123, "kpi2": 7712},
|
|
828
|
+
], "meta": [
|
|
829
|
+
{"fieldKey": "kpi1", "dataType": "NUMBER", "title": "指标1", "category": "kpi"},
|
|
830
|
+
{"fieldKey": "kpi2", "dataType": "NUMBER", "title": "指标2", "category": "kpi"},
|
|
831
|
+
], "currentPage": 1, "totalCount": 1}}]
|
|
832
|
+
|
|
833
|
+
if chart_type == "pivot":
|
|
834
|
+
return [{"name": _DS_KEY_DATASET, "data": {"data": [
|
|
835
|
+
{"col1": 74, "col2": 9, "col3": 79},
|
|
836
|
+
{"col1": 85, "col2": 15, "col3": 62},
|
|
837
|
+
{"col1": 93, "col2": 28, "col3": 44},
|
|
838
|
+
], "meta": [
|
|
839
|
+
{"fieldKey": "columnList", "dataType": "NUMBER", "title": "col1"},
|
|
840
|
+
{"fieldKey": "columnList", "dataType": "NUMBER", "title": "col2"},
|
|
841
|
+
{"fieldKey": "columnList", "dataType": "NUMBER", "title": "col3"},
|
|
842
|
+
], "currentPage": 1, "totalCount": 3}}]
|
|
843
|
+
|
|
844
|
+
return []
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
# ---------------------------------------------------------------------------
|
|
848
|
+
# afterFetch / exportData / link 构建
|
|
849
|
+
# ---------------------------------------------------------------------------
|
|
850
|
+
|
|
851
|
+
_AFTER_FETCH = {
|
|
852
|
+
"type": "JSFunction",
|
|
853
|
+
"value": "function afterFetch(data, extraInfo) { return data; }",
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
_EXPORT_DATA = {
|
|
857
|
+
"supportExport": False,
|
|
858
|
+
"passType": "NO_PASS",
|
|
859
|
+
"exportType": "BROWSER",
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
_LINK = {
|
|
863
|
+
"hasLink": False,
|
|
864
|
+
"content": {"type": "i18n", "zh_CN": "更多", "en_US": "More"},
|
|
865
|
+
"onlyIcon": True,
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
# ---------------------------------------------------------------------------
|
|
870
|
+
# 顶层字段属性提取
|
|
871
|
+
# ---------------------------------------------------------------------------
|
|
872
|
+
|
|
873
|
+
def _extract_top_level_field_props(chart_type: str, ds_model_map: dict[str, Any]) -> dict[str, Any]:
|
|
874
|
+
"""从 dataSetModelMap 提取需要写入 props 顶层的字段属性。"""
|
|
875
|
+
result: dict[str, Any] = {}
|
|
876
|
+
if chart_type in ("bar", "line", "pie", "funnel"):
|
|
877
|
+
ds = ds_model_map.get(_DS_KEY_CHART, {})
|
|
878
|
+
result["xField"] = ds.get("xField", [])
|
|
879
|
+
result["yField"] = ds.get("yField", [])
|
|
880
|
+
if chart_type not in ("pie", "funnel"):
|
|
881
|
+
result["groupField"] = ds.get("groupField", [])
|
|
882
|
+
elif chart_type == "gauge":
|
|
883
|
+
ds = ds_model_map.get(_DS_KEY_CHART, {})
|
|
884
|
+
result["valueField"] = ds.get("valueField", [])
|
|
885
|
+
result["assitValueField"] = ds.get("assitValueField", [])
|
|
886
|
+
elif chart_type == "indicator":
|
|
887
|
+
ds = ds_model_map.get(_DS_KEY_INDICATOR, {})
|
|
888
|
+
result["kpiField"] = ds.get("kpi", [])
|
|
889
|
+
result["helpKpiField"] = ds.get("helpKpi", [])
|
|
890
|
+
elif chart_type == "table":
|
|
891
|
+
ds = ds_model_map.get(_DS_KEY_TABLE, {})
|
|
892
|
+
result["columnField"] = ds.get("columnFields", [])
|
|
893
|
+
elif chart_type == "combo":
|
|
894
|
+
ds = ds_model_map.get(_DS_KEY_DATASET, {})
|
|
895
|
+
result["xField"] = ds.get("xField", [])
|
|
896
|
+
result["leftYFields"] = ds.get("leftYFields", [])
|
|
897
|
+
result["rightYFields"] = ds.get("rightYFields", [])
|
|
898
|
+
elif chart_type == "pivot":
|
|
899
|
+
ds = ds_model_map.get(_DS_KEY_DATASET, {})
|
|
900
|
+
result["columnList"] = ds.get("columnList", [])
|
|
901
|
+
return result
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
# ---------------------------------------------------------------------------
|
|
905
|
+
# 主入口
|
|
906
|
+
# ---------------------------------------------------------------------------
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
def build_chart_component(
|
|
910
|
+
chart: dict[str, Any],
|
|
911
|
+
cube_tenant_id: str = "",
|
|
912
|
+
) -> tuple[dict[str, Any], str, dict[str, Any]]:
|
|
913
|
+
"""
|
|
914
|
+
构造图表组件。
|
|
915
|
+
|
|
916
|
+
Returns:
|
|
917
|
+
(component_node, fieldId, default_layout)
|
|
918
|
+
"""
|
|
919
|
+
chart_type = chart.get("type", "bar")
|
|
920
|
+
if chart_type not in CHART_TYPE_MAP:
|
|
921
|
+
raise ValueError(f"不支持的图表类型: {chart_type}(支持: {list(CHART_TYPE_MAP.keys())})")
|
|
922
|
+
|
|
923
|
+
component_name = CHART_TYPE_MAP[chart_type]
|
|
924
|
+
title = chart.get("title", "图表")
|
|
925
|
+
field_id = generate_field_id(component_name)
|
|
926
|
+
node_id = next_node_id()
|
|
927
|
+
|
|
928
|
+
cube_code = normalize_cube_code(chart.get("cubeCode", ""))
|
|
929
|
+
if not cube_code:
|
|
930
|
+
raise ValueError(f"图表 '{title}' 缺少 cubeCode")
|
|
931
|
+
|
|
932
|
+
data_set_model_map = _build_data_set_model_map(chart, cube_code, cube_tenant_id)
|
|
933
|
+
|
|
934
|
+
props: dict[str, Any] = {
|
|
935
|
+
"fieldId": field_id,
|
|
936
|
+
"cid": node_id,
|
|
937
|
+
"showComponentTitle": True,
|
|
938
|
+
"componentTitle": i18n(title),
|
|
939
|
+
"componentTitleTextAlign": "LEFT",
|
|
940
|
+
"titleTipContent": i18n(""),
|
|
941
|
+
"titleTipIconName": "help",
|
|
942
|
+
"headerSize": "medium",
|
|
943
|
+
"link": _LINK,
|
|
944
|
+
"exportData": _EXPORT_DATA,
|
|
945
|
+
"openRefresh": True,
|
|
946
|
+
"enabledCache": True,
|
|
947
|
+
"auth": [],
|
|
948
|
+
"afterFetch": _AFTER_FETCH,
|
|
949
|
+
"__style__": {},
|
|
950
|
+
"mockData": _build_mock_data(chart_type),
|
|
951
|
+
"dataSetModelMap": data_set_model_map,
|
|
952
|
+
"userConfig": _build_user_config(chart_type),
|
|
953
|
+
"settings": _get_chart_settings(chart_type, chart),
|
|
954
|
+
"titleTip": False,
|
|
955
|
+
"hasFullscreen": False,
|
|
956
|
+
"copyAsImg": False,
|
|
957
|
+
"height": None,
|
|
958
|
+
"isHeightAuto": True,
|
|
959
|
+
"datasetModel": {"filterList": []},
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
top_level = _extract_top_level_field_props(chart_type, data_set_model_map)
|
|
963
|
+
props.update(top_level)
|
|
964
|
+
|
|
965
|
+
if chart_type in ("table", "indicator"):
|
|
966
|
+
props["showFieldSelectIcon"] = True
|
|
967
|
+
|
|
968
|
+
if chart_type == "table":
|
|
969
|
+
props["pageSize"] = chart.get("pageSize", 20)
|
|
970
|
+
|
|
971
|
+
node: dict[str, Any] = {
|
|
972
|
+
"componentName": component_name,
|
|
973
|
+
"id": node_id,
|
|
974
|
+
"props": props,
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
computed = _compute_dynamic_layout(chart_type, chart)
|
|
978
|
+
layout: dict[str, Any] = {
|
|
979
|
+
"w": chart.get("w", computed["w"]),
|
|
980
|
+
"h": chart.get("h", computed["h"]),
|
|
981
|
+
}
|
|
982
|
+
for k in ("minH", "maxH", "resizeHandles"):
|
|
983
|
+
if k in computed:
|
|
984
|
+
layout[k] = computed[k]
|
|
985
|
+
|
|
986
|
+
return node, field_id, layout
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
# ---------------------------------------------------------------------------
|
|
990
|
+
# dataSetModelMap 构造
|
|
991
|
+
# ---------------------------------------------------------------------------
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
def _build_data_set_model_map(
|
|
995
|
+
chart: dict[str, Any],
|
|
996
|
+
cube_code: str,
|
|
997
|
+
cube_tenant_id: str,
|
|
998
|
+
) -> dict[str, Any]:
|
|
999
|
+
chart_type = chart.get("type", "bar")
|
|
1000
|
+
|
|
1001
|
+
if chart_type in ("bar", "line", "pie", "funnel"):
|
|
1002
|
+
return _build_xy_data_model(chart, cube_code, cube_tenant_id)
|
|
1003
|
+
elif chart_type == "table":
|
|
1004
|
+
return _build_table_data_model(chart, cube_code, cube_tenant_id)
|
|
1005
|
+
elif chart_type == "indicator":
|
|
1006
|
+
return _build_indicator_data_model(chart, cube_code, cube_tenant_id)
|
|
1007
|
+
elif chart_type == "gauge":
|
|
1008
|
+
return _build_gauge_data_model(chart, cube_code, cube_tenant_id)
|
|
1009
|
+
elif chart_type == "combo":
|
|
1010
|
+
return _build_combo_data_model(chart, cube_code, cube_tenant_id)
|
|
1011
|
+
elif chart_type == "pivot":
|
|
1012
|
+
return _build_pivot_data_model(chart, cube_code, cube_tenant_id)
|
|
1013
|
+
return {}
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
def _build_xy_data_model(
|
|
1017
|
+
chart: dict[str, Any],
|
|
1018
|
+
cube_code: str,
|
|
1019
|
+
cube_tenant_id: str,
|
|
1020
|
+
) -> dict[str, Any]:
|
|
1021
|
+
chart_type = chart.get("type", "bar")
|
|
1022
|
+
x_raw = chart.get("xField", "")
|
|
1023
|
+
x_resolved = _resolve_field(x_raw, cube_code)
|
|
1024
|
+
|
|
1025
|
+
y_raw = chart.get("yField", "")
|
|
1026
|
+
if isinstance(y_raw, (str, dict)):
|
|
1027
|
+
y_raw = [y_raw]
|
|
1028
|
+
y_resolved_list = [_resolve_field(f, cube_code) for f in y_raw]
|
|
1029
|
+
|
|
1030
|
+
agg_type = chart.get("aggregateType", "COUNT").upper()
|
|
1031
|
+
|
|
1032
|
+
x_label = _apply_cube_label_suffix(
|
|
1033
|
+
x_resolved["fieldCode"], chart.get("xLabel", "") or x_resolved["text"]
|
|
1034
|
+
)
|
|
1035
|
+
y_labels_raw = chart.get("yLabel", [])
|
|
1036
|
+
if isinstance(y_labels_raw, str):
|
|
1037
|
+
y_labels_raw = [y_labels_raw]
|
|
1038
|
+
|
|
1039
|
+
x_alias = _gen_alias()
|
|
1040
|
+
x_time_gran = x_resolved["timeGranularityType"] or (
|
|
1041
|
+
chart.get("timeGranularityType", "DAY") if _is_date_field(x_resolved["fieldCode"]) else None
|
|
1042
|
+
)
|
|
1043
|
+
|
|
1044
|
+
query_defs = [_build_query_field_def(
|
|
1045
|
+
x_alias, x_label, cube_code, x_resolved["fieldCode"], x_resolved["dataType"],
|
|
1046
|
+
"NONE", x_time_gran, classified_code=x_resolved["classifiedCode"],
|
|
1047
|
+
)]
|
|
1048
|
+
x_full = _build_full_field(
|
|
1049
|
+
x_alias, x_label, cube_code, x_resolved["fieldCode"], x_resolved["dataType"],
|
|
1050
|
+
"NONE", x_time_gran, classified_code=x_resolved["classifiedCode"],
|
|
1051
|
+
field_id=x_resolved["id"], time_format=x_resolved["timeFormat"],
|
|
1052
|
+
)
|
|
1053
|
+
all_full = [x_full]
|
|
1054
|
+
|
|
1055
|
+
y_aliases: list[str] = []
|
|
1056
|
+
y_fulls: list[dict[str, Any]] = []
|
|
1057
|
+
for i, yr in enumerate(y_resolved_list):
|
|
1058
|
+
y_label = _apply_cube_label_suffix(
|
|
1059
|
+
yr["fieldCode"], (y_labels_raw[i] if i < len(y_labels_raw) else "") or yr["text"]
|
|
1060
|
+
)
|
|
1061
|
+
y_alias = _gen_alias()
|
|
1062
|
+
y_aliases.append(y_alias)
|
|
1063
|
+
y_fc, y_dt = _fix_array_field_for_aggregate(yr["fieldCode"], yr["dataType"], agg_type)
|
|
1064
|
+
query_defs.append(_build_query_field_def(
|
|
1065
|
+
y_alias, y_label, cube_code, y_fc, y_dt,
|
|
1066
|
+
agg_type, classified_code=yr["classifiedCode"],
|
|
1067
|
+
))
|
|
1068
|
+
y_full = _build_full_field(
|
|
1069
|
+
y_alias, y_label, cube_code, y_fc, y_dt,
|
|
1070
|
+
agg_type, classified_code=yr["classifiedCode"], field_id=yr["id"],
|
|
1071
|
+
)
|
|
1072
|
+
y_fulls.append(y_full)
|
|
1073
|
+
all_full.append(y_full)
|
|
1074
|
+
|
|
1075
|
+
extra: dict[str, Any] = {"xField": [x_full], "yField": y_fulls}
|
|
1076
|
+
if chart_type == "pie":
|
|
1077
|
+
extra.update({"ratio": [], "totalValue": [], "totalRatio": [], "trailingIconField": []})
|
|
1078
|
+
elif chart_type != "funnel":
|
|
1079
|
+
extra.update({"groupField": [], "annotationField": []})
|
|
1080
|
+
|
|
1081
|
+
limit_val = chart.get("limit")
|
|
1082
|
+
if limit_val is not None:
|
|
1083
|
+
extra["limit"] = int(limit_val)
|
|
1084
|
+
|
|
1085
|
+
return _wrap_dataset(
|
|
1086
|
+
_DS_KEY_CHART, cube_code, cube_tenant_id,
|
|
1087
|
+
query_defs, [x_alias] + y_aliases, all_full,
|
|
1088
|
+
extra=extra,
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
def _build_table_data_model(
|
|
1093
|
+
chart: dict[str, Any],
|
|
1094
|
+
cube_code: str,
|
|
1095
|
+
cube_tenant_id: str,
|
|
1096
|
+
) -> dict[str, Any]:
|
|
1097
|
+
raw_columns = chart.get("columnFields", []) or chart.get("columns", []) or chart.get("fields", [])
|
|
1098
|
+
if not raw_columns:
|
|
1099
|
+
x_field = chart.get("xField", "")
|
|
1100
|
+
if x_field:
|
|
1101
|
+
raw_columns = [x_field]
|
|
1102
|
+
if not raw_columns:
|
|
1103
|
+
raise ValueError(
|
|
1104
|
+
"table 图表必须提供 columnFields(或 columns / fields / xField)。"
|
|
1105
|
+
"请先通过 `dws yida form components` 获取源表字段定义。"
|
|
1106
|
+
)
|
|
1107
|
+
|
|
1108
|
+
column_labels_raw = chart.get("columnLabels", [])
|
|
1109
|
+
resolved_columns = [_resolve_field(col, cube_code) for col in raw_columns]
|
|
1110
|
+
|
|
1111
|
+
query_defs: list[dict[str, Any]] = []
|
|
1112
|
+
aliases: list[str] = []
|
|
1113
|
+
full_fields: list[dict[str, Any]] = []
|
|
1114
|
+
|
|
1115
|
+
for i, rc in enumerate(resolved_columns):
|
|
1116
|
+
label = _apply_cube_label_suffix(
|
|
1117
|
+
rc["fieldCode"], (column_labels_raw[i] if i < len(column_labels_raw) else "") or rc["text"]
|
|
1118
|
+
)
|
|
1119
|
+
alias = _gen_alias()
|
|
1120
|
+
aliases.append(alias)
|
|
1121
|
+
time_gran = rc["timeGranularityType"] or (
|
|
1122
|
+
chart.get("timeGranularityType", "DAY") if _is_date_field(rc["fieldCode"]) else None
|
|
1123
|
+
)
|
|
1124
|
+
query_defs.append(_build_query_field_def(
|
|
1125
|
+
alias, label, cube_code, rc["fieldCode"], rc["dataType"],
|
|
1126
|
+
"NONE", time_gran, classified_code=rc["classifiedCode"],
|
|
1127
|
+
))
|
|
1128
|
+
full = _build_full_field(
|
|
1129
|
+
alias, label, cube_code, rc["fieldCode"], rc["dataType"],
|
|
1130
|
+
"NONE", time_gran, classified_code=rc["classifiedCode"],
|
|
1131
|
+
field_id=rc["id"], time_format=rc["timeFormat"],
|
|
1132
|
+
)
|
|
1133
|
+
full["sortable"] = False
|
|
1134
|
+
full["hidden"] = False
|
|
1135
|
+
full_fields.append(full)
|
|
1136
|
+
|
|
1137
|
+
column_fields: list[dict[str, Any]] = []
|
|
1138
|
+
for i, full in enumerate(full_fields):
|
|
1139
|
+
col: dict[str, Any] = {
|
|
1140
|
+
"aggregateType": full["aggregateType"],
|
|
1141
|
+
"beUsedTimes": 1,
|
|
1142
|
+
"classifiedCode": full["classifiedCode"],
|
|
1143
|
+
"cubeCode": full["cubeCode"],
|
|
1144
|
+
"dataType": full["dataType"],
|
|
1145
|
+
"fieldCode": full["fieldCode"],
|
|
1146
|
+
"fieldKey": full["fieldKey"],
|
|
1147
|
+
"id": full["id"],
|
|
1148
|
+
"text": full["text"],
|
|
1149
|
+
"title": full["title"],
|
|
1150
|
+
"visible": True,
|
|
1151
|
+
"width": 120,
|
|
1152
|
+
"align": "left",
|
|
1153
|
+
"fixed": "left" if i == 0 else None,
|
|
1154
|
+
"timeGranularityType": full.get("timeGranularityType"),
|
|
1155
|
+
"timeFormat": full.get("timeFormat"),
|
|
1156
|
+
"orderBy": full["orderBy"],
|
|
1157
|
+
}
|
|
1158
|
+
column_fields.append(col)
|
|
1159
|
+
|
|
1160
|
+
return _wrap_dataset(
|
|
1161
|
+
_DS_KEY_TABLE, cube_code, cube_tenant_id,
|
|
1162
|
+
query_defs, aliases, full_fields,
|
|
1163
|
+
extra={"columnFields": column_fields},
|
|
1164
|
+
)
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
def _build_indicator_data_model(
|
|
1168
|
+
chart: dict[str, Any],
|
|
1169
|
+
cube_code: str,
|
|
1170
|
+
cube_tenant_id: str,
|
|
1171
|
+
) -> dict[str, Any]:
|
|
1172
|
+
kpi_list = chart.get("kpi", []) or chart.get("kpiField", []) or chart.get("yField", []) or chart.get("fields", [])
|
|
1173
|
+
if not kpi_list:
|
|
1174
|
+
raise ValueError("indicator 图表必须提供 kpi(或 kpiField / yField / fields)数组")
|
|
1175
|
+
|
|
1176
|
+
query_defs: list[dict[str, Any]] = []
|
|
1177
|
+
aliases: list[str] = []
|
|
1178
|
+
full_fields: list[dict[str, Any]] = []
|
|
1179
|
+
|
|
1180
|
+
kpi_rich: list[dict[str, Any]] = []
|
|
1181
|
+
for kpi in kpi_list:
|
|
1182
|
+
if isinstance(kpi, str):
|
|
1183
|
+
kpi = {"fieldCode": kpi}
|
|
1184
|
+
fc = normalize_field_code(kpi.get("fieldCode", ""))
|
|
1185
|
+
agg = kpi.get("aggregateType", "COUNT").upper()
|
|
1186
|
+
dt = kpi.get("dataType") or _infer_data_type(fc)
|
|
1187
|
+
fc, dt = _fix_array_field_for_aggregate(fc, dt, agg)
|
|
1188
|
+
label = kpi.get("aliasName", "") or kpi.get("text", "") or kpi.get("label", "") or _derive_label(fc)
|
|
1189
|
+
label = _apply_cube_label_suffix(fc, label)
|
|
1190
|
+
field_id = kpi.get("id") or fc
|
|
1191
|
+
classified_code = kpi.get("classifiedCode") or cube_code
|
|
1192
|
+
alias = _gen_alias()
|
|
1193
|
+
aliases.append(alias)
|
|
1194
|
+
query_defs.append(_build_query_field_def(
|
|
1195
|
+
alias, label, cube_code, fc, dt, agg, classified_code=classified_code,
|
|
1196
|
+
))
|
|
1197
|
+
full = _build_full_field(
|
|
1198
|
+
alias, label, cube_code, fc, dt, agg,
|
|
1199
|
+
classified_code=classified_code, field_id=field_id,
|
|
1200
|
+
)
|
|
1201
|
+
full_fields.append(full)
|
|
1202
|
+
kpi_item: dict[str, Any] = {
|
|
1203
|
+
**full,
|
|
1204
|
+
"visible": True,
|
|
1205
|
+
"isVisible": "y",
|
|
1206
|
+
}
|
|
1207
|
+
kpi_rich.append(kpi_item)
|
|
1208
|
+
|
|
1209
|
+
help_kpi_list = chart.get("helpKpi", [])
|
|
1210
|
+
help_kpi_rich: list[dict[str, Any]] = []
|
|
1211
|
+
for hk in help_kpi_list:
|
|
1212
|
+
if isinstance(hk, str):
|
|
1213
|
+
hk = {"fieldCode": hk}
|
|
1214
|
+
fc = normalize_field_code(hk.get("fieldCode", ""))
|
|
1215
|
+
agg = hk.get("aggregateType", "COUNT").upper()
|
|
1216
|
+
dt = hk.get("dataType") or _infer_data_type(fc)
|
|
1217
|
+
fc, dt = _fix_array_field_for_aggregate(fc, dt, agg)
|
|
1218
|
+
label = hk.get("aliasName", "") or hk.get("text", "") or hk.get("label", "") or _derive_label(fc)
|
|
1219
|
+
label = _apply_cube_label_suffix(fc, label)
|
|
1220
|
+
field_id = hk.get("id") or fc
|
|
1221
|
+
classified_code = hk.get("classifiedCode") or cube_code
|
|
1222
|
+
alias = _gen_alias()
|
|
1223
|
+
aliases.append(alias)
|
|
1224
|
+
query_defs.append(_build_query_field_def(
|
|
1225
|
+
alias, label, cube_code, fc, dt, agg, classified_code=classified_code,
|
|
1226
|
+
))
|
|
1227
|
+
full = _build_full_field(
|
|
1228
|
+
alias, label, cube_code, fc, dt, agg,
|
|
1229
|
+
classified_code=classified_code, field_id=field_id,
|
|
1230
|
+
)
|
|
1231
|
+
full_fields.append(full)
|
|
1232
|
+
help_kpi_rich.append({**full, "visible": True, "isVisible": "y"})
|
|
1233
|
+
|
|
1234
|
+
return _wrap_dataset(
|
|
1235
|
+
_DS_KEY_INDICATOR, cube_code, cube_tenant_id,
|
|
1236
|
+
query_defs, aliases, full_fields,
|
|
1237
|
+
extra={"kpi": kpi_rich, "helpKpi": help_kpi_rich},
|
|
1238
|
+
)
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
def _build_gauge_data_model(
|
|
1242
|
+
chart: dict[str, Any],
|
|
1243
|
+
cube_code: str,
|
|
1244
|
+
cube_tenant_id: str,
|
|
1245
|
+
) -> dict[str, Any]:
|
|
1246
|
+
value_raw = chart.get("valueField") or chart.get("yField")
|
|
1247
|
+
if isinstance(value_raw, list):
|
|
1248
|
+
value_raw = value_raw[0] if value_raw else None
|
|
1249
|
+
if not value_raw:
|
|
1250
|
+
raise ValueError("gauge 图表必须提供 valueField(或 yField)")
|
|
1251
|
+
|
|
1252
|
+
value_resolved = _resolve_field(value_raw, cube_code)
|
|
1253
|
+
agg_type = chart.get("aggregateType", "AVG").upper()
|
|
1254
|
+
|
|
1255
|
+
v_alias = _gen_alias()
|
|
1256
|
+
v_label = _apply_cube_label_suffix(
|
|
1257
|
+
value_resolved["fieldCode"], chart.get("valueLabel", "") or value_resolved["text"]
|
|
1258
|
+
)
|
|
1259
|
+
v_fc, v_dt = _fix_array_field_for_aggregate(value_resolved["fieldCode"], value_resolved["dataType"], agg_type)
|
|
1260
|
+
|
|
1261
|
+
query_defs = [_build_query_field_def(
|
|
1262
|
+
v_alias, v_label, cube_code, v_fc, v_dt, agg_type,
|
|
1263
|
+
classified_code=value_resolved["classifiedCode"],
|
|
1264
|
+
)]
|
|
1265
|
+
v_full = _build_full_field(
|
|
1266
|
+
v_alias, v_label, cube_code, v_fc, v_dt, agg_type,
|
|
1267
|
+
classified_code=value_resolved["classifiedCode"], field_id=value_resolved["id"],
|
|
1268
|
+
)
|
|
1269
|
+
all_full = [v_full]
|
|
1270
|
+
aliases = [v_alias]
|
|
1271
|
+
|
|
1272
|
+
assit_fulls: list[dict[str, Any]] = []
|
|
1273
|
+
assit_raw = chart.get("assitValueField")
|
|
1274
|
+
if assit_raw:
|
|
1275
|
+
if isinstance(assit_raw, list):
|
|
1276
|
+
assit_raw = assit_raw[0] if assit_raw else None
|
|
1277
|
+
if assit_raw:
|
|
1278
|
+
assit_resolved = _resolve_field(assit_raw, cube_code)
|
|
1279
|
+
a_alias = _gen_alias()
|
|
1280
|
+
a_label = _apply_cube_label_suffix(
|
|
1281
|
+
assit_resolved["fieldCode"], chart.get("assitLabel", "") or assit_resolved["text"]
|
|
1282
|
+
)
|
|
1283
|
+
a_fc, a_dt = _fix_array_field_for_aggregate(
|
|
1284
|
+
assit_resolved["fieldCode"], assit_resolved["dataType"], agg_type
|
|
1285
|
+
)
|
|
1286
|
+
query_defs.append(_build_query_field_def(
|
|
1287
|
+
a_alias, a_label, cube_code, a_fc, a_dt, agg_type,
|
|
1288
|
+
classified_code=assit_resolved["classifiedCode"],
|
|
1289
|
+
))
|
|
1290
|
+
a_full = _build_full_field(
|
|
1291
|
+
a_alias, a_label, cube_code, a_fc, a_dt, agg_type,
|
|
1292
|
+
classified_code=assit_resolved["classifiedCode"], field_id=assit_resolved["id"],
|
|
1293
|
+
)
|
|
1294
|
+
all_full.append(a_full)
|
|
1295
|
+
aliases.append(a_alias)
|
|
1296
|
+
assit_fulls.append(a_full)
|
|
1297
|
+
|
|
1298
|
+
return _wrap_dataset(
|
|
1299
|
+
_DS_KEY_CHART, cube_code, cube_tenant_id,
|
|
1300
|
+
query_defs, aliases, all_full,
|
|
1301
|
+
extra={"valueField": [v_full], "assitValueField": assit_fulls},
|
|
1302
|
+
)
|
|
1303
|
+
|
|
1304
|
+
|
|
1305
|
+
def _build_combo_data_model(
|
|
1306
|
+
chart: dict[str, Any],
|
|
1307
|
+
cube_code: str,
|
|
1308
|
+
cube_tenant_id: str,
|
|
1309
|
+
) -> dict[str, Any]:
|
|
1310
|
+
x_raw = chart.get("xField", "")
|
|
1311
|
+
x_resolved = _resolve_field(x_raw, cube_code)
|
|
1312
|
+
|
|
1313
|
+
left_raw = chart.get("leftYFields", [])
|
|
1314
|
+
if isinstance(left_raw, (str, dict)):
|
|
1315
|
+
left_raw = [left_raw]
|
|
1316
|
+
right_raw = chart.get("rightYFields", [])
|
|
1317
|
+
if isinstance(right_raw, (str, dict)):
|
|
1318
|
+
right_raw = [right_raw]
|
|
1319
|
+
|
|
1320
|
+
if not left_raw and not right_raw:
|
|
1321
|
+
raise ValueError("combo 图表必须提供 leftYFields 或 rightYFields")
|
|
1322
|
+
|
|
1323
|
+
left_resolved = [_resolve_field(f, cube_code) for f in left_raw]
|
|
1324
|
+
right_resolved = [_resolve_field(f, cube_code) for f in right_raw]
|
|
1325
|
+
|
|
1326
|
+
left_agg = chart.get("leftAggregateType", "SUM").upper()
|
|
1327
|
+
right_agg = chart.get("rightAggregateType", "SUM").upper()
|
|
1328
|
+
|
|
1329
|
+
x_label = _apply_cube_label_suffix(
|
|
1330
|
+
x_resolved["fieldCode"], chart.get("xLabel", "") or x_resolved["text"]
|
|
1331
|
+
)
|
|
1332
|
+
x_alias = _gen_alias()
|
|
1333
|
+
x_time_gran = x_resolved["timeGranularityType"] or (
|
|
1334
|
+
chart.get("timeGranularityType", "DAY") if _is_date_field(x_resolved["fieldCode"]) else None
|
|
1335
|
+
)
|
|
1336
|
+
|
|
1337
|
+
query_defs = [_build_query_field_def(
|
|
1338
|
+
x_alias, x_label, cube_code, x_resolved["fieldCode"], x_resolved["dataType"],
|
|
1339
|
+
"NONE", x_time_gran, classified_code=x_resolved["classifiedCode"],
|
|
1340
|
+
)]
|
|
1341
|
+
x_full = _build_full_field(
|
|
1342
|
+
x_alias, x_label, cube_code, x_resolved["fieldCode"], x_resolved["dataType"],
|
|
1343
|
+
"NONE", x_time_gran, classified_code=x_resolved["classifiedCode"],
|
|
1344
|
+
field_id=x_resolved["id"], time_format=x_resolved["timeFormat"],
|
|
1345
|
+
)
|
|
1346
|
+
all_full = [x_full]
|
|
1347
|
+
all_aliases = [x_alias]
|
|
1348
|
+
|
|
1349
|
+
left_fulls: list[dict[str, Any]] = []
|
|
1350
|
+
for lr in left_resolved:
|
|
1351
|
+
alias = _gen_alias()
|
|
1352
|
+
all_aliases.append(alias)
|
|
1353
|
+
label = _apply_cube_label_suffix(lr["fieldCode"], lr["text"])
|
|
1354
|
+
fc, dt = _fix_array_field_for_aggregate(lr["fieldCode"], lr["dataType"], left_agg)
|
|
1355
|
+
query_defs.append(_build_query_field_def(
|
|
1356
|
+
alias, label, cube_code, fc, dt, left_agg, classified_code=lr["classifiedCode"],
|
|
1357
|
+
))
|
|
1358
|
+
full = _build_full_field(
|
|
1359
|
+
alias, label, cube_code, fc, dt, left_agg,
|
|
1360
|
+
classified_code=lr["classifiedCode"], field_id=lr["id"],
|
|
1361
|
+
)
|
|
1362
|
+
left_fulls.append(full)
|
|
1363
|
+
all_full.append(full)
|
|
1364
|
+
|
|
1365
|
+
right_fulls: list[dict[str, Any]] = []
|
|
1366
|
+
for rr in right_resolved:
|
|
1367
|
+
alias = _gen_alias()
|
|
1368
|
+
all_aliases.append(alias)
|
|
1369
|
+
label = _apply_cube_label_suffix(rr["fieldCode"], rr["text"])
|
|
1370
|
+
fc, dt = _fix_array_field_for_aggregate(rr["fieldCode"], rr["dataType"], right_agg)
|
|
1371
|
+
query_defs.append(_build_query_field_def(
|
|
1372
|
+
alias, label, cube_code, fc, dt, right_agg, classified_code=rr["classifiedCode"],
|
|
1373
|
+
))
|
|
1374
|
+
full = _build_full_field(
|
|
1375
|
+
alias, label, cube_code, fc, dt, right_agg,
|
|
1376
|
+
classified_code=rr["classifiedCode"], field_id=rr["id"],
|
|
1377
|
+
)
|
|
1378
|
+
right_fulls.append(full)
|
|
1379
|
+
all_full.append(full)
|
|
1380
|
+
|
|
1381
|
+
return _wrap_dataset(
|
|
1382
|
+
_DS_KEY_DATASET, cube_code, cube_tenant_id,
|
|
1383
|
+
query_defs, all_aliases, all_full,
|
|
1384
|
+
extra={
|
|
1385
|
+
"xField": [x_full],
|
|
1386
|
+
"leftYFields": left_fulls,
|
|
1387
|
+
"rightYFields": right_fulls,
|
|
1388
|
+
"annotationField": [],
|
|
1389
|
+
},
|
|
1390
|
+
)
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
def _build_pivot_data_model(
|
|
1394
|
+
chart: dict[str, Any],
|
|
1395
|
+
cube_code: str,
|
|
1396
|
+
cube_tenant_id: str,
|
|
1397
|
+
) -> dict[str, Any]:
|
|
1398
|
+
raw_columns = chart.get("columnList", []) or chart.get("columns", [])
|
|
1399
|
+
if not raw_columns:
|
|
1400
|
+
raise ValueError(
|
|
1401
|
+
"pivot 图表必须提供 columnList(或 columns)。"
|
|
1402
|
+
"请先通过 `dws yida form components` 获取源表字段定义。"
|
|
1403
|
+
)
|
|
1404
|
+
|
|
1405
|
+
resolved_columns = [_resolve_field(col, cube_code) for col in raw_columns]
|
|
1406
|
+
|
|
1407
|
+
query_defs: list[dict[str, Any]] = []
|
|
1408
|
+
aliases: list[str] = []
|
|
1409
|
+
full_fields: list[dict[str, Any]] = []
|
|
1410
|
+
|
|
1411
|
+
for rc in resolved_columns:
|
|
1412
|
+
label = _apply_cube_label_suffix(rc["fieldCode"], rc["text"])
|
|
1413
|
+
alias = _gen_alias()
|
|
1414
|
+
aliases.append(alias)
|
|
1415
|
+
time_gran = rc["timeGranularityType"] or (
|
|
1416
|
+
chart.get("timeGranularityType", "DAY") if _is_date_field(rc["fieldCode"]) else None
|
|
1417
|
+
)
|
|
1418
|
+
query_defs.append(_build_query_field_def(
|
|
1419
|
+
alias, label, cube_code, rc["fieldCode"], rc["dataType"],
|
|
1420
|
+
"NONE", time_gran, classified_code=rc["classifiedCode"],
|
|
1421
|
+
))
|
|
1422
|
+
full = _build_full_field(
|
|
1423
|
+
alias, label, cube_code, rc["fieldCode"], rc["dataType"],
|
|
1424
|
+
"NONE", time_gran, classified_code=rc["classifiedCode"],
|
|
1425
|
+
field_id=rc["id"], time_format=rc["timeFormat"],
|
|
1426
|
+
)
|
|
1427
|
+
full_fields.append(full)
|
|
1428
|
+
|
|
1429
|
+
return _wrap_dataset(
|
|
1430
|
+
_DS_KEY_DATASET, cube_code, cube_tenant_id,
|
|
1431
|
+
query_defs, aliases, full_fields,
|
|
1432
|
+
extra={"columnList": full_fields},
|
|
1433
|
+
extra_query={"filterMode": "PROFESSIONAL"},
|
|
1434
|
+
)
|