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,498 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
考勤排班导入脚本
|
|
4
|
+
|
|
5
|
+
[AI Agent 强制门禁] 本脚本执行前必须先阅读:
|
|
6
|
+
references/attendance-schedule.md
|
|
7
|
+
|
|
8
|
+
排班工作流、参数校验、班次校验、回显确认等约束全部在
|
|
9
|
+
attendance-schedule.md,禁止凭本脚本源码或 --help 自行组装命令。
|
|
10
|
+
|
|
11
|
+
职责:
|
|
12
|
+
1. 二次校验考勤组类型(必须为 TURN 排班制)
|
|
13
|
+
2. 二次校验班次 ID 在可用班次列表中
|
|
14
|
+
3. 回显排班内容表格,等待用户确认
|
|
15
|
+
4. 调用 dws attendance schedule import 执行排班
|
|
16
|
+
5. 输出执行结果摘要
|
|
17
|
+
|
|
18
|
+
用法:
|
|
19
|
+
python attendance_schedule_import.py \
|
|
20
|
+
--group-id 123456 \
|
|
21
|
+
--schedules '[{"userId":"u001","workDate":"2026-05-19","classId":789,"isRest":"N"}]' \
|
|
22
|
+
--confirm
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
import json
|
|
29
|
+
import sys
|
|
30
|
+
from datetime import datetime
|
|
31
|
+
from typing import Any
|
|
32
|
+
|
|
33
|
+
# 复用公共模块
|
|
34
|
+
from attendance_report_common import (
|
|
35
|
+
run_dws,
|
|
36
|
+
DwsCallError,
|
|
37
|
+
extract_records,
|
|
38
|
+
resolve_user_names,
|
|
39
|
+
log,
|
|
40
|
+
warn,
|
|
41
|
+
error,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
DATE_FMT = "%Y-%m-%d"
|
|
45
|
+
DATETIME_FMT = "%Y-%m-%d %H:%M:%S"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
49
|
+
# 考勤组校验
|
|
50
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
def _unwrap_group_vo(result: dict) -> dict:
|
|
53
|
+
"""从 group get 返回结构中提取 groupVO(type/name/classIds 等字段所在层)。
|
|
54
|
+
|
|
55
|
+
group get 返回结构:{groupVO: {type, name, classIds, ...}, ...}
|
|
56
|
+
filtered-get 返回结构可能直接是扁平的 {type, name, memberUsers, ...}
|
|
57
|
+
"""
|
|
58
|
+
if not isinstance(result, dict):
|
|
59
|
+
return result
|
|
60
|
+
group_vo = result.get("groupVO")
|
|
61
|
+
if isinstance(group_vo, dict) and group_vo.get("type"):
|
|
62
|
+
return group_vo
|
|
63
|
+
# 如果顶层已经有 type 字段,说明是扁平结构,直接返回
|
|
64
|
+
if result.get("type"):
|
|
65
|
+
return result
|
|
66
|
+
# 兜底:尝试从所有 dict 类型的值中找包含 type 字段的
|
|
67
|
+
for value in result.values():
|
|
68
|
+
if isinstance(value, dict) and value.get("type"):
|
|
69
|
+
return value
|
|
70
|
+
return result
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def validate_group_is_turn(group_id: int) -> dict:
|
|
74
|
+
"""校验考勤组存在且类型为 TURN(排班制),返回考勤组信息(groupVO 层级)。"""
|
|
75
|
+
log(f"🔍 校验考勤组 {group_id} ...")
|
|
76
|
+
|
|
77
|
+
# 优先用 group get 获取完整信息(含绑定班次列表)
|
|
78
|
+
try:
|
|
79
|
+
result = run_dws([
|
|
80
|
+
"attendance", "group", "get",
|
|
81
|
+
"--group-id", str(group_id),
|
|
82
|
+
])
|
|
83
|
+
except DwsCallError:
|
|
84
|
+
# 降级使用 filtered-get
|
|
85
|
+
try:
|
|
86
|
+
result = run_dws([
|
|
87
|
+
"attendance", "group", "filtered-get",
|
|
88
|
+
"--group-id", str(group_id),
|
|
89
|
+
])
|
|
90
|
+
except DwsCallError as exc:
|
|
91
|
+
error(f"查询考勤组失败: {exc}")
|
|
92
|
+
raise SystemExit(1) from exc
|
|
93
|
+
|
|
94
|
+
if not result or not isinstance(result, dict):
|
|
95
|
+
error(f"考勤组 {group_id} 不存在或返回数据异常")
|
|
96
|
+
raise SystemExit(1)
|
|
97
|
+
|
|
98
|
+
# 关键:从 groupVO 中提取 type/name 等字段
|
|
99
|
+
group_vo = _unwrap_group_vo(result)
|
|
100
|
+
group_type = group_vo.get("type", "")
|
|
101
|
+
group_name = group_vo.get("name", f"ID:{group_id}")
|
|
102
|
+
|
|
103
|
+
if not group_type:
|
|
104
|
+
# 调试输出,帮助排查结构
|
|
105
|
+
log(f"[debug] group get 返回顶层 keys: {list(result.keys())}")
|
|
106
|
+
error(f"未能从考勤组 {group_id} 返回数据中识别出类型字段")
|
|
107
|
+
raise SystemExit(1)
|
|
108
|
+
|
|
109
|
+
if group_type != "TURN":
|
|
110
|
+
type_label = {"FIXED": "固定班制", "NONE": "自由工时"}.get(group_type, group_type)
|
|
111
|
+
error(f"考勤组「{group_name}」类型为 {type_label},不是排班制(TURN),无法执行排班操作")
|
|
112
|
+
raise SystemExit(1)
|
|
113
|
+
|
|
114
|
+
log(f"✅ 考勤组「{group_name}」确认为排班制")
|
|
115
|
+
return group_vo
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
119
|
+
# 班次校验
|
|
120
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
def extract_group_bound_classes(group_info: dict) -> set[int]:
|
|
123
|
+
"""从考勤组详情中提取绑定的班次 ID 集合。
|
|
124
|
+
|
|
125
|
+
兼容多种字段结构:
|
|
126
|
+
- classIds: [int] — 班次 ID 数组
|
|
127
|
+
- classes / selectedClass: [dict] — 班次对象数组 (含 id/classId)
|
|
128
|
+
- shiftVOList: [dict] — 排班制特有,含 shiftSetting.shiftId
|
|
129
|
+
- classNameIdMap: {name: id} — 名称到 ID 映射
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
def _extract_from_obj(obj: dict) -> set[int]:
|
|
133
|
+
"""从单个 dict 层级中提取班次 ID。"""
|
|
134
|
+
ids: set[int] = set()
|
|
135
|
+
|
|
136
|
+
# 方式1: classIds / shiftIds 数组(最常见)
|
|
137
|
+
for key in ("classIds", "shiftIds", "classIdList"):
|
|
138
|
+
ids_list = obj.get(key)
|
|
139
|
+
if isinstance(ids_list, list):
|
|
140
|
+
for item in ids_list:
|
|
141
|
+
try:
|
|
142
|
+
ids.add(int(item))
|
|
143
|
+
except (ValueError, TypeError):
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
# 方式2: classes / selectedClass 对象数组
|
|
147
|
+
for key in ("classes", "selectedClass"):
|
|
148
|
+
classes = obj.get(key)
|
|
149
|
+
if isinstance(classes, list):
|
|
150
|
+
for item in classes:
|
|
151
|
+
if isinstance(item, dict):
|
|
152
|
+
class_id = item.get("id") or item.get("classId")
|
|
153
|
+
if class_id is not None:
|
|
154
|
+
ids.add(int(class_id))
|
|
155
|
+
elif isinstance(item, (int, str)):
|
|
156
|
+
try:
|
|
157
|
+
ids.add(int(item))
|
|
158
|
+
except (ValueError, TypeError):
|
|
159
|
+
pass
|
|
160
|
+
|
|
161
|
+
# 方式3: shiftVOList — 排班制考勤组特有字段
|
|
162
|
+
shift_vo_list = obj.get("shiftVOList")
|
|
163
|
+
if isinstance(shift_vo_list, list):
|
|
164
|
+
for shift_vo in shift_vo_list:
|
|
165
|
+
if not isinstance(shift_vo, dict):
|
|
166
|
+
continue
|
|
167
|
+
# shiftSetting.shiftId
|
|
168
|
+
shift_setting = shift_vo.get("shiftSetting")
|
|
169
|
+
if isinstance(shift_setting, dict):
|
|
170
|
+
shift_id = shift_setting.get("shiftId") or shift_setting.get("classId")
|
|
171
|
+
if shift_id is not None:
|
|
172
|
+
ids.add(int(shift_id))
|
|
173
|
+
# 直接在 shiftVO 层级的 id/shiftId/classId
|
|
174
|
+
for id_key in ("id", "shiftId", "classId"):
|
|
175
|
+
val = shift_vo.get(id_key)
|
|
176
|
+
if val is not None:
|
|
177
|
+
try:
|
|
178
|
+
ids.add(int(val))
|
|
179
|
+
except (ValueError, TypeError):
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
# 方式4: classNameIdMap {name: id}
|
|
183
|
+
class_map = obj.get("classNameIdMap")
|
|
184
|
+
if isinstance(class_map, dict):
|
|
185
|
+
for _, class_id in class_map.items():
|
|
186
|
+
try:
|
|
187
|
+
ids.add(int(class_id))
|
|
188
|
+
except (ValueError, TypeError):
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
return ids
|
|
192
|
+
|
|
193
|
+
# 优先从 groupVO 提取(group get 返回结构),兼容顶层扁平结构
|
|
194
|
+
bound_ids: set[int] = set()
|
|
195
|
+
|
|
196
|
+
group_vo = group_info.get("groupVO")
|
|
197
|
+
if isinstance(group_vo, dict):
|
|
198
|
+
bound_ids.update(_extract_from_obj(group_vo))
|
|
199
|
+
|
|
200
|
+
# 同时从顶层提取(兼容 filtered-get 或已解包的结构)
|
|
201
|
+
bound_ids.update(_extract_from_obj(group_info))
|
|
202
|
+
|
|
203
|
+
return bound_ids
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def fetch_all_classes() -> dict[int, str]:
|
|
207
|
+
"""获取全局所有班次,返回 {classId: className},用于 ID→名称映射。"""
|
|
208
|
+
log("🔍 获取班次名称映射 ...")
|
|
209
|
+
all_classes: dict[int, str] = {}
|
|
210
|
+
page_index = 1
|
|
211
|
+
page_size = 200
|
|
212
|
+
|
|
213
|
+
while True:
|
|
214
|
+
try:
|
|
215
|
+
result = run_dws([
|
|
216
|
+
"attendance", "class", "search",
|
|
217
|
+
"--page", str(page_index),
|
|
218
|
+
"--limit", str(page_size),
|
|
219
|
+
])
|
|
220
|
+
except DwsCallError as exc:
|
|
221
|
+
error(f"查询班次列表失败: {exc}")
|
|
222
|
+
raise SystemExit(1) from exc
|
|
223
|
+
|
|
224
|
+
records = extract_records(result) if result else []
|
|
225
|
+
if not records:
|
|
226
|
+
break
|
|
227
|
+
|
|
228
|
+
for record in records:
|
|
229
|
+
class_id = record.get("id") or record.get("classId")
|
|
230
|
+
class_name = record.get("name") or record.get("className") or str(class_id)
|
|
231
|
+
if class_id is not None:
|
|
232
|
+
all_classes[int(class_id)] = class_name
|
|
233
|
+
|
|
234
|
+
if len(records) < page_size:
|
|
235
|
+
break
|
|
236
|
+
page_index += 1
|
|
237
|
+
|
|
238
|
+
log(f"✅ 获取到 {len(all_classes)} 个班次名称")
|
|
239
|
+
return all_classes
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def validate_class_ids(
|
|
243
|
+
schedules: list[dict],
|
|
244
|
+
group_bound_class_ids: set[int],
|
|
245
|
+
all_classes: dict[int, str],
|
|
246
|
+
group_name: str,
|
|
247
|
+
) -> None:
|
|
248
|
+
"""校验排班记录中的 classId 都在该考勤组绑定的班次中。
|
|
249
|
+
|
|
250
|
+
如果考勤组未提取到绑定班次列表(可能是接口字段差异),
|
|
251
|
+
则降级为全局班次校验并输出警告。
|
|
252
|
+
"""
|
|
253
|
+
# 如果两个来源都无法获取到班次信息,跳过校验(排班导入接口本身有服务端校验)
|
|
254
|
+
no_bound = len(group_bound_class_ids) == 0
|
|
255
|
+
no_global = len(all_classes) == 0
|
|
256
|
+
|
|
257
|
+
if no_bound and no_global:
|
|
258
|
+
warn(f"无法获取考勤组绑定班次和全局班次列表,跳过班次校验(将依赖服务端校验)")
|
|
259
|
+
return
|
|
260
|
+
|
|
261
|
+
use_global_fallback = no_bound
|
|
262
|
+
if use_global_fallback:
|
|
263
|
+
warn(f"未能从考勤组「{group_name}」详情中提取绑定班次列表,降级为全局班次校验")
|
|
264
|
+
check_set = set(all_classes.keys())
|
|
265
|
+
else:
|
|
266
|
+
check_set = group_bound_class_ids
|
|
267
|
+
|
|
268
|
+
invalid_class_ids: set[int] = set()
|
|
269
|
+
|
|
270
|
+
for schedule in schedules:
|
|
271
|
+
is_rest = str(schedule.get("isRest", "N")).upper()
|
|
272
|
+
if is_rest == "Y":
|
|
273
|
+
continue
|
|
274
|
+
class_id = int(schedule.get("classId", 0))
|
|
275
|
+
if class_id != 0 and class_id not in check_set:
|
|
276
|
+
invalid_class_ids.add(class_id)
|
|
277
|
+
|
|
278
|
+
if invalid_class_ids:
|
|
279
|
+
invalid_names = [all_classes.get(cid, f"ID:{cid}") for cid in sorted(invalid_class_ids)]
|
|
280
|
+
if use_global_fallback:
|
|
281
|
+
error(f"以下班次不在可用班次列表中: {', '.join(invalid_names)}")
|
|
282
|
+
else:
|
|
283
|
+
error(f"以下班次不属于考勤组「{group_name}」: {', '.join(invalid_names)}")
|
|
284
|
+
log(f"「{group_name}」可用班次:")
|
|
285
|
+
available_ids = check_set if not use_global_fallback else set(all_classes.keys())
|
|
286
|
+
for cid in sorted(available_ids):
|
|
287
|
+
cname = all_classes.get(cid, f"ID:{cid}")
|
|
288
|
+
log(f" - {cname} (ID: {cid})")
|
|
289
|
+
raise SystemExit(1)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
293
|
+
# 日期格式标准化
|
|
294
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
295
|
+
|
|
296
|
+
def normalize_work_date(work_date: Any) -> str:
|
|
297
|
+
"""将 workDate 统一转换为 yyyy-MM-dd HH:mm:ss 格式。"""
|
|
298
|
+
if isinstance(work_date, (int, float)):
|
|
299
|
+
timestamp = work_date / 1000 if work_date > 1e12 else work_date
|
|
300
|
+
return datetime.fromtimestamp(timestamp).strftime(DATETIME_FMT)
|
|
301
|
+
|
|
302
|
+
date_str = str(work_date).strip()
|
|
303
|
+
|
|
304
|
+
for fmt in (DATETIME_FMT, DATE_FMT):
|
|
305
|
+
try:
|
|
306
|
+
parsed = datetime.strptime(date_str, fmt)
|
|
307
|
+
return parsed.strftime(DATETIME_FMT)
|
|
308
|
+
except ValueError:
|
|
309
|
+
continue
|
|
310
|
+
|
|
311
|
+
raise ValueError(f"无法解析日期格式: {work_date!r},请使用 YYYY-MM-DD 格式")
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
315
|
+
# 回显排班内容
|
|
316
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
def print_schedule_preview(
|
|
319
|
+
group_name: str,
|
|
320
|
+
group_id: int,
|
|
321
|
+
schedules: list[dict],
|
|
322
|
+
available_classes: dict[int, str],
|
|
323
|
+
user_names: dict[str, str],
|
|
324
|
+
) -> None:
|
|
325
|
+
"""向 stdout 打印排班预览表格供用户确认。"""
|
|
326
|
+
print("\n📋 排班确认")
|
|
327
|
+
print(f"\n考勤组: {group_name} (ID: {group_id})")
|
|
328
|
+
|
|
329
|
+
dates = sorted({s.get("workDate", "")[:10] for s in schedules})
|
|
330
|
+
if dates:
|
|
331
|
+
print(f"排班日期: {dates[0]} ~ {dates[-1]}")
|
|
332
|
+
|
|
333
|
+
print(f"\n{'员工姓名':<12} {'日期':<14} {'班次':<16} {'是否排休':<8}")
|
|
334
|
+
print("-" * 54)
|
|
335
|
+
|
|
336
|
+
for schedule in sorted(schedules, key=lambda s: (s.get("userId", ""), s.get("workDate", ""))):
|
|
337
|
+
user_id = schedule.get("userId", "")
|
|
338
|
+
user_name = user_names.get(user_id, user_id)
|
|
339
|
+
work_date = str(schedule.get("workDate", ""))[:10]
|
|
340
|
+
class_id = int(schedule.get("classId", 0))
|
|
341
|
+
is_rest = str(schedule.get("isRest", "N")).upper()
|
|
342
|
+
|
|
343
|
+
if is_rest == "Y":
|
|
344
|
+
class_display = "休息"
|
|
345
|
+
rest_display = "是"
|
|
346
|
+
else:
|
|
347
|
+
class_display = available_classes.get(class_id, f"未知班次(ID:{class_id})")
|
|
348
|
+
rest_display = "否"
|
|
349
|
+
|
|
350
|
+
print(f"{user_name:<12} {work_date:<14} {class_display:<16} {rest_display:<8}")
|
|
351
|
+
|
|
352
|
+
print(f"\n共 {len(schedules)} 条排班记录")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
356
|
+
# 执行排班
|
|
357
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
358
|
+
|
|
359
|
+
def execute_schedule_import(group_id: int, schedules: list[dict]) -> None:
|
|
360
|
+
"""调用 dws attendance schedule import 执行排班。"""
|
|
361
|
+
log(f"🚀 正在执行排班导入 ({len(schedules)} 条记录) ...")
|
|
362
|
+
|
|
363
|
+
schedules_json = json.dumps(schedules, ensure_ascii=False)
|
|
364
|
+
|
|
365
|
+
try:
|
|
366
|
+
result = run_dws([
|
|
367
|
+
"attendance", "schedule", "import",
|
|
368
|
+
"--groupId", str(group_id),
|
|
369
|
+
"--scheduleVOS", schedules_json,
|
|
370
|
+
"--yes",
|
|
371
|
+
])
|
|
372
|
+
except DwsCallError as exc:
|
|
373
|
+
error(f"排班导入失败: {exc}")
|
|
374
|
+
if exc.is_permission_error:
|
|
375
|
+
error("提示: 当前账号可能不是考勤管理员,请确认权限")
|
|
376
|
+
raise SystemExit(1) from exc
|
|
377
|
+
|
|
378
|
+
log("✅ 排班导入完成")
|
|
379
|
+
return result
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
383
|
+
# 主流程
|
|
384
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
385
|
+
|
|
386
|
+
def main() -> None:
|
|
387
|
+
parser = argparse.ArgumentParser(
|
|
388
|
+
description="考勤排班导入(含校验、回显、执行)",
|
|
389
|
+
epilog="执行前必须阅读 attendance-schedule.md",
|
|
390
|
+
)
|
|
391
|
+
parser.add_argument(
|
|
392
|
+
"--group-id", required=True, type=int,
|
|
393
|
+
help="考勤组 ID(必填,必须为排班制考勤组)",
|
|
394
|
+
)
|
|
395
|
+
parser.add_argument(
|
|
396
|
+
"--schedules", required=True,
|
|
397
|
+
help="排班记录 JSON 数组(必填),每条记录包含 userId/workDate/classId/isRest",
|
|
398
|
+
)
|
|
399
|
+
parser.add_argument(
|
|
400
|
+
"--confirm", action="store_true",
|
|
401
|
+
help="用户已确认排班内容(必填,表示用户已在 Agent 回显中确认)",
|
|
402
|
+
)
|
|
403
|
+
parser.add_argument(
|
|
404
|
+
"--dry-run", action="store_true",
|
|
405
|
+
help="仅校验和回显,不实际执行排班",
|
|
406
|
+
)
|
|
407
|
+
args = parser.parse_args()
|
|
408
|
+
|
|
409
|
+
# ── 解析排班记录 JSON ──
|
|
410
|
+
try:
|
|
411
|
+
schedules: list[dict] = json.loads(args.schedules)
|
|
412
|
+
except json.JSONDecodeError as exc:
|
|
413
|
+
error(f"--schedules JSON 格式错误: {exc}")
|
|
414
|
+
raise SystemExit(1) from exc
|
|
415
|
+
|
|
416
|
+
if not isinstance(schedules, list) or len(schedules) == 0:
|
|
417
|
+
error("--schedules 必须是非空 JSON 数组")
|
|
418
|
+
raise SystemExit(1)
|
|
419
|
+
|
|
420
|
+
# ── 校验必填字段 ──
|
|
421
|
+
required_fields = ("userId", "workDate", "classId", "isRest")
|
|
422
|
+
for idx, schedule in enumerate(schedules):
|
|
423
|
+
for field_name in required_fields:
|
|
424
|
+
if field_name not in schedule:
|
|
425
|
+
error(f"schedule[{idx}] 缺少必填字段: {field_name}")
|
|
426
|
+
raise SystemExit(1)
|
|
427
|
+
|
|
428
|
+
# ── 标准化日期格式 ──
|
|
429
|
+
for idx, schedule in enumerate(schedules):
|
|
430
|
+
try:
|
|
431
|
+
schedule["workDate"] = normalize_work_date(schedule["workDate"])
|
|
432
|
+
except ValueError as exc:
|
|
433
|
+
error(f"schedule[{idx}] 日期格式错误: {exc}")
|
|
434
|
+
raise SystemExit(1) from exc
|
|
435
|
+
|
|
436
|
+
# ── 阶段 1: 校验考勤组(必须为 TURN 排班制) ──
|
|
437
|
+
group_info = validate_group_is_turn(args.group_id)
|
|
438
|
+
group_name = group_info.get("name", f"ID:{args.group_id}")
|
|
439
|
+
|
|
440
|
+
# ── 阶段 2: 解析员工姓名 ──
|
|
441
|
+
user_ids = list({s["userId"] for s in schedules})
|
|
442
|
+
user_names = resolve_user_names(user_ids)
|
|
443
|
+
|
|
444
|
+
# ── 阶段 3: 校验班次(必须属于该考勤组) ──
|
|
445
|
+
group_bound_class_ids = extract_group_bound_classes(group_info)
|
|
446
|
+
all_classes = fetch_all_classes()
|
|
447
|
+
if group_bound_class_ids:
|
|
448
|
+
log(f"📋 考勤组「{group_name}」绑定了 {len(group_bound_class_ids)} 个班次:")
|
|
449
|
+
for cid in sorted(group_bound_class_ids):
|
|
450
|
+
cname = all_classes.get(cid, f"ID:{cid}")
|
|
451
|
+
log(f" - {cname} (ID: {cid})")
|
|
452
|
+
validate_class_ids(schedules, group_bound_class_ids, all_classes, group_name)
|
|
453
|
+
log("✅ 班次校验通过")
|
|
454
|
+
|
|
455
|
+
# ── 阶段 4: 回显排班内容 ──
|
|
456
|
+
print_schedule_preview(group_name, args.group_id, schedules, all_classes, user_names)
|
|
457
|
+
|
|
458
|
+
if args.dry_run:
|
|
459
|
+
print("\n[dry-run] 仅校验和回显,未实际执行排班")
|
|
460
|
+
return
|
|
461
|
+
|
|
462
|
+
if not args.confirm:
|
|
463
|
+
print("\n⚠️ 未传入 --confirm 参数,排班未执行")
|
|
464
|
+
print("请在 Agent 回显确认后,添加 --confirm 参数重新执行")
|
|
465
|
+
return
|
|
466
|
+
|
|
467
|
+
# ── 阶段 5: 执行排班 ──
|
|
468
|
+
execute_schedule_import(args.group_id, schedules)
|
|
469
|
+
|
|
470
|
+
# ── 阶段 6: 输出摘要 ──
|
|
471
|
+
print(f"\n✅ 排班导入成功!")
|
|
472
|
+
print(f" 考勤组: {group_name}")
|
|
473
|
+
print(f" 排班人数: {len(user_ids)}")
|
|
474
|
+
print(f" 排班记录: {len(schedules)} 条")
|
|
475
|
+
dates = sorted({s.get('workDate', '')[:10] for s in schedules})
|
|
476
|
+
if dates:
|
|
477
|
+
print(f" 日期范围: {dates[0]} ~ {dates[-1]}")
|
|
478
|
+
|
|
479
|
+
# 展示所有排班明细
|
|
480
|
+
print(f"\n{'员工姓名':<12} {'日期':<14} {'班次':<16} {'是否排休':<8}")
|
|
481
|
+
print("-" * 54)
|
|
482
|
+
for schedule in sorted(schedules, key=lambda s: (s.get("userId", ""), s.get("workDate", ""))):
|
|
483
|
+
uid = schedule.get("userId", "")
|
|
484
|
+
uname = user_names.get(uid, uid)
|
|
485
|
+
wdate = str(schedule.get("workDate", ""))[:10]
|
|
486
|
+
cid = int(schedule.get("classId", 0))
|
|
487
|
+
is_rest = str(schedule.get("isRest", "N")).upper()
|
|
488
|
+
if is_rest == "Y":
|
|
489
|
+
class_display = "休息"
|
|
490
|
+
rest_display = "是"
|
|
491
|
+
else:
|
|
492
|
+
class_display = all_classes.get(cid, f"未知班次(ID:{cid})")
|
|
493
|
+
rest_display = "否"
|
|
494
|
+
print(f"{uname:<12} {wdate:<14} {class_display:<16} {rest_display:<8}")
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
if __name__ == "__main__":
|
|
498
|
+
main()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
查询团队成员本周排班和出勤统计
|
|
4
|
+
|
|
5
|
+
用法:
|
|
6
|
+
python attendance_team_shift.py --users userId1,userId2,userId3
|
|
7
|
+
python attendance_team_shift.py --users userId1,userId2 \
|
|
8
|
+
--from 2026-03-10 --to 2026-03-14
|
|
9
|
+
python attendance_team_shift.py --users userId1 --dry-run
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
import json
|
|
14
|
+
import subprocess
|
|
15
|
+
import argparse
|
|
16
|
+
from datetime import datetime, timedelta
|
|
17
|
+
from typing import List, Any, Optional
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def run_dws(
|
|
21
|
+
args: List[str], dry_run: bool = False,
|
|
22
|
+
) -> Optional[Any]:
|
|
23
|
+
cmd = ['dws'] + args
|
|
24
|
+
if dry_run:
|
|
25
|
+
print(f"[dry-run] {' '.join(cmd)}")
|
|
26
|
+
return None
|
|
27
|
+
try:
|
|
28
|
+
result = subprocess.run(
|
|
29
|
+
cmd, capture_output=True, text=True, timeout=60
|
|
30
|
+
)
|
|
31
|
+
if result.returncode != 0:
|
|
32
|
+
print(f"错误:{result.stderr.strip()}", file=sys.stderr)
|
|
33
|
+
return None
|
|
34
|
+
return json.loads(result.stdout)
|
|
35
|
+
except (subprocess.TimeoutExpired, json.JSONDecodeError,
|
|
36
|
+
FileNotFoundError) as e:
|
|
37
|
+
print(f"错误:{e}", file=sys.stderr)
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_week_range():
|
|
42
|
+
today = datetime.now()
|
|
43
|
+
monday = today - timedelta(days=today.weekday())
|
|
44
|
+
friday = monday + timedelta(days=4)
|
|
45
|
+
return monday.strftime('%Y-%m-%d'), friday.strftime('%Y-%m-%d')
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def main():
|
|
49
|
+
parser = argparse.ArgumentParser(
|
|
50
|
+
description='查询团队成员排班和出勤统计'
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
'--users', required=True, help='用户 ID 列表,逗号分隔'
|
|
54
|
+
)
|
|
55
|
+
mon, fri = get_week_range()
|
|
56
|
+
parser.add_argument('--from', dest='from_date', default=mon)
|
|
57
|
+
parser.add_argument('--to', dest='to_date', default=fri)
|
|
58
|
+
parser.add_argument('--dry-run', action='store_true')
|
|
59
|
+
args = parser.parse_args()
|
|
60
|
+
|
|
61
|
+
user_count = len(args.users.split(','))
|
|
62
|
+
if user_count > 50:
|
|
63
|
+
print('错误:最多查询 50 人')
|
|
64
|
+
sys.exit(1)
|
|
65
|
+
|
|
66
|
+
print(f"📊 团队排班查询 ({args.from_date} ~ {args.to_date})")
|
|
67
|
+
print(f" 人数: {user_count}")
|
|
68
|
+
print('=' * 50)
|
|
69
|
+
|
|
70
|
+
print('\n🔍 查询排班信息...')
|
|
71
|
+
data = run_dws([
|
|
72
|
+
'attendance', 'shift', 'list',
|
|
73
|
+
'--users', args.users,
|
|
74
|
+
'--start', args.from_date,
|
|
75
|
+
'--end', args.to_date,
|
|
76
|
+
'--format', 'json',
|
|
77
|
+
], dry_run=args.dry_run)
|
|
78
|
+
|
|
79
|
+
if args.dry_run:
|
|
80
|
+
return
|
|
81
|
+
if not data:
|
|
82
|
+
print('未查到排班信息')
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
print(json.dumps(data, ensure_ascii=False, indent=2))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == '__main__':
|
|
89
|
+
main()
|